{ /*************************************************************************** codetoolsdefines.pas - Lazarus IDE unit ----------------------------------------- ***************************************************************************/ *************************************************************************** * * * This source is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This code is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * A copy of the GNU General Public License is available on the World * * Wide Web at . You can also * * obtain it by writing to the Free Software Foundation, * * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * *************************************************************************** Author: Mattias Gaertner Abstract: - TCodeToolsDefinesEditor is an editor for the CodeTools DefineTree used by the IDE. The DefineTree defines all values, that are not in the sources, but are provided by for example Makefiles, compiler command lines and compiler config files. There are three types of nodes: - auto generated: These are created by the IDE. - project specific: These nodes are saved in the project info file (.lpi) - the rest are global nodes, saved in the codetoolsoptions.xml file. } unit CodeToolsDefines; {$mode objfpc}{$H+} interface uses Classes, SysUtils, LCLLinux, Forms, Controls, Buttons, StdCtrls, ComCtrls, ExtCtrls, Menus, LResources, Graphics, Dialogs, ImgList, SynEdit, Laz_XMLCfg, DefineTemplates, CodeToolManager, CodeToolsOptions, CodeToolsDefPreview, TransferMacros, InputFileDialog, IDEOptionDefs; type TCodeToolsDefinesEditor = class(TForm) TheImageList: TImageList; MainMenu: TMainMenu; // exit menu ExitMenuItem: TMenuItem; SaveAndExitMenuItem: TMenuItem; DontSaveAndExitMenuItem: TMenuItem; // edit nodes EditMenuItem: TMenuItem; MoveNodeUpMenuItem: TMenuItem; MoveNodeDownMenuItem: TMenuItem; MoveNodeLvlUpMenuItem: TMenuItem; MoveNodeLvlDownMenuItem: TMenuItem; InsertBehindMenuItem: TMenuItem; InsertBehindDefineMenuItem: TMenuItem; InsertBehindDefineRecurseMenuItem: TMenuItem; InsertBehindUndefineMenuItem: TMenuItem; InsertBehindUndefineRecurseMenuItem: TMenuItem; InsertBehindUndefineAllMenuItem: TMenuItem; InsertBehindBlockMenuItem: TMenuItem; InsertBehindDirectoryMenuItem: TMenuItem; InsertBehindIfMenuItem: TMenuItem; InsertBehindIfDefMenuItem: TMenuItem; InsertBehindIfNotDefMenuItem: TMenuItem; InsertBehindElseIfMenuItem: TMenuItem; InsertBehindElseMenuItem: TMenuItem; InsertAsChildMenuItem: TMenuItem; InsertAsChildDefineMenuItem: TMenuItem; InsertAsChildDefineRecurseMenuItem: TMenuItem; InsertAsChildUndefineMenuItem: TMenuItem; InsertAsChildUndefineRecurseMenuItem: TMenuItem; InsertAsChildUndefineAllMenuItem: TMenuItem; InsertAsChildBlockMenuItem: TMenuItem; InsertAsChildDirectoryMenuItem: TMenuItem; InsertAsChildIfMenuItem: TMenuItem; InsertAsChildIfDefMenuItem: TMenuItem; InsertAsChildIfNotDefMenuItem: TMenuItem; InsertAsChildElseIfMenuItem: TMenuItem; InsertAsChildElseMenuItem: TMenuItem; DeleteNodeMenuItem: TMenuItem; ConvertActionMenuItem: TMenuItem; ConvertActionToDefineMenuItem: TMenuItem; ConvertActionToDefineRecurseMenuItem: TMenuItem; ConvertActionToUndefineMenuItem: TMenuItem; ConvertActionToUndefineRecurseMenuItem: TMenuItem; ConvertActionToUndefineAllMenuItem: TMenuItem; ConvertActionToBlockMenuItem: TMenuItem; ConvertActionToDirectoryMenuItem: TMenuItem; ConvertActionToIfMenuItem: TMenuItem; ConvertActionToIfDefMenuItem: TMenuItem; ConvertActionToIfNotDefMenuItem: TMenuItem; ConvertActionToElseIfMenuItem: TMenuItem; ConvertActionToElseMenuItem: TMenuItem; CopyToClipbrdMenuItem: TMenuItem; PasteFromClipbrdMenuItem: TMenuItem; // tools ToolsMenuItem: TMenuItem; OpenPreviewMenuItem: TMenuItem; ShowMacroListMenuItem: TMenuItem; // templates InsertTemplateMenuItem: TMenuItem; InsertFPCProjectDefinesTemplateMenuItem: TMenuItem; InsertFPCompilerDefinesTemplateMenuItem: TMenuItem; InsertFPCSourceDirTemplateMenuItem: TMenuItem; InsertLazarusSourceTemplateMenuItem: TMenuItem; InsertDelphi5CompilerDefinesTemplateMenuItem: TMenuItem; InsertDelphi5DirectoryTemplateMenuItem: TMenuItem; InsertDelphi5ProjectTemplateMenuItem: TMenuItem; InsertDelphi6CompilerDefinesTemplateMenuItem: TMenuItem; InsertDelphi6DirectoryTemplateMenuItem: TMenuItem; InsertDelphi6ProjectTemplateMenuItem: TMenuItem; // define tree DefineTreeView: TTreeView; // selected item SelectedItemGroupBox: TGroupBox; TypeLabel: TLabel; ProjectSpecificCheckBox: TCheckBox; NameLabel: TLabel; NameEdit: TEdit; DescriptionLabel: TLabel; DescriptionEdit: TEdit; VariableLabel: TLabel; VariableEdit: TEdit; ValueNoteBook: TNoteBook; ValueAsTextSynEdit: TSynEdit; ValueAsFilePathsSynEdit: TSynEdit; MoveFilePathUpBitBtn: TBitBtn; MoveFilePathDownBitBtn: TBitBtn; DeleteFilePathBitBtn: TBitBtn; InsertFilePathBitBtn: TBitBtn; // preview DefinePreview: TCodeToolsDefinesPreview; // misc procedure FormResize(Sender: TObject); procedure SelectedItemGroupBoxResize(Sender: TObject); procedure ValueNoteBookResize(Sender: TObject); procedure DefineTreeViewMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X,Y: integer); procedure ProjectSpecificCheckBoxClick(Sender: TObject); procedure RefreshPreview; // exit menu procedure SaveAndExitMenuItemClick(Sender: TObject); procedure DontSaveAndExitMenuItemClick(Sender: TObject); // value notebook procedure ValueNoteBookPageChanged(Sender: TObject); procedure MoveFilePathUpBitBtnClick(Sender: TObject); procedure MoveFilePathDownBitBtnClick(Sender: TObject); procedure DeleteFilePathBitBtnClick(Sender: TObject); procedure InsertFilePathBitBtnClick(Sender: TObject); // edit menu procedure InsertNodeMenuItemClick(Sender: TObject); procedure MoveNodeUpMenuItemClick(Sender: TObject); procedure MoveNodeDownMenuItemClick(Sender: TObject); procedure MoveNodeLvlUpMenuItemClick(Sender: TObject); procedure MoveNodeLvlDownMenuItemClick(Sender: TObject); procedure DeleteNodeMenuItemClick(Sender: TObject); procedure ConvertActionMenuItemClick(Sender: TObject); // tools menu procedure OpenPreviewMenuItemClick(Sender: TObject); // template menu procedure InsertFPCProjectDefinesTemplateMenuItemClick(Sender: TObject); procedure InsertFPCompilerDefinesTemplateMenuItemClick(Sender: TObject); procedure InsertFPCSourceDirDefinesTemplateMenuItemClick(Sender: TObject); procedure InsertLazarusSourceDefinesTemplateMenuItemClick(Sender: TObject); procedure InsertDelphiCompilerDefinesTemplateMenuItemClick(Sender: TObject); procedure InsertDelphiDirectoryTemplateMenuItemClick(Sender: TObject); procedure InsertDelphiProjectTemplateMenuItemClick(Sender: TObject); private FDefineTree: TDefineTree; FLastSelectedNode: TTreeNode; FBoss: TCodeToolManager; FTransferMacros: TTransferMacroList; procedure CreateComponents; function CreateSeperator : TMenuItem; procedure RebuildDefineTreeView; procedure AddDefineNodes(ANode: TDefineTemplate; AParent: TTreeNode; WithChilds,WithNextSiblings: boolean); procedure SetNodeImages(ANode: TTreeNode; WithSubNodes: boolean); procedure SetTransferMacros(const AValue: TTransferMacroList); procedure ValueAsPathToValueAsText; procedure SaveSelectedValues; procedure ShowSelectedValues; procedure SetTypeLabel; function ValueToFilePathText(const AValue: string): string; procedure InsertNewNode(Behind: boolean; Action: TDefineAction); procedure InsertTemplate(NewTemplate: TDefineTemplate); function FindUniqueName: string; function ConsistencyCheck: integer; procedure SetValuesEditable(AValue: boolean); public procedure Assign(ACodeToolBoss: TCodeToolManager; Options: TCodeToolsOptions); constructor Create(TheOwner: TComponent); override; destructor Destroy; override; property DefineTree: TDefineTree read FDefineTree; property Boss: TCodeToolManager read FBoss write FBoss; property Macros: TTransferMacroList read FTransferMacros write SetTransferMacros; end; function ShowCodeToolsDefinesEditor(ACodeToolBoss: TCodeToolManager; Options: TCodeToolsOptions; Macros: TTransferMacroList): TModalResult; function SaveGlobalCodeToolsDefines(ACodeToolBoss: TCodeToolManager; Options: TCodeToolsOptions): TModalResult; function SaveProjectSpecificCodeToolsDefines(ACodeToolBoss: TCodeToolManager; const ProjectInfoFile: string): TModalResult; function LoadCodeToolsDefines(ACodeToolBoss: TCodeToolManager; Options: TCodeToolsOptions; const ProjectInfoFile: string): TModalResult; implementation uses Math; type TWinControlClass = class of TWinControl; function SaveGlobalCodeToolsDefines(ACodeToolBoss: TCodeToolManager; Options: TCodeToolsOptions): TModalResult; var XMLConfig: TXMLConfig; begin Result:=mrCancel; try XMLConfig:=TXMLConfig.Create(Options.Filename); try ACodeToolBoss.DefineTree.SaveToXMLConfig(XMLConfig, 'CodeToolsGlobalDefines/',dtspGlobals); XMLConfig.Flush; finally XMLConfig.Free; end; Result:=mrOk; except on e: Exception do Result:=MessageDlg('Write error','Error while writing "' +Options.Filename+'"'#13+e.Message,mtError,[mbIgnore, mbAbort],0); end; end; function SaveProjectSpecificCodeToolsDefines(ACodeToolBoss: TCodeToolManager; const ProjectInfoFile: string): TModalResult; var XMLConfig: TXMLConfig; begin Result:=mrCancel; try XMLConfig:=TXMLConfig.Create(ProjectInfoFile); try ACodeToolBoss.DefineTree.SaveToXMLConfig(XMLConfig, 'ProjectSpecificCodeToolsDefines/',dtspProjectSpecific); XMLConfig.Flush; finally XMLConfig.Free; end; Result:=mrOk; except on e: Exception do Result:=MessageDlg('Write error','Error while writing "' +ProjectInfoFile+'"'#13+e.Message,mtError,[mbIgnore, mbAbort],0); end; end; function LoadCodeToolsDefines(ACodeToolBoss: TCodeToolManager; Options: TCodeToolsOptions; const ProjectInfoFile: string): TModalResult; // replaces globals and project defines if changed var NewDefineTree: TDefineTree; XMLConfig: TXMLConfig; begin Result:=mrCancel; NewDefineTree:=TDefineTree.Create; try // create a temporary copy of current defines NewDefineTree.Assign(ACodeToolBoss.DefineTree); // remove non auto generated = all globals and project specific defines NewDefineTree.RemoveNonAutoCreated; if (Options<>nil) and (Options.Filename<>'') then begin // load global defines try XMLConfig:=TXMLConfig.Create(Options.Filename); try NewDefineTree.LoadFromXMLConfig(XMLConfig, 'CodeToolsGlobalDefines/',dtlpGlobals,'Global'); finally XMLConfig.Free; end; Result:=mrOk; except on e: Exception do Result:=MessageDlg('Read error','Error reading "' +Options.Filename+'"'#13+e.Message,mtError,[mbIgnore, mbAbort],0); end; if Result<>mrOk then exit; end; if ProjectInfoFile<>'' then begin // load project specific defines try XMLConfig:=TXMLConfig.Create(ProjectInfoFile); try NewDefineTree.LoadFromXMLConfig(XMLConfig, 'ProjectSpecificCodeToolsDefines/',dtlpProjectSpecific, 'ProjectSpecific'); finally XMLConfig.Free; end; Result:=mrOk; except on e: Exception do Result:=MessageDlg('Read error','Error reading "' +ProjectInfoFile+'"'#13+e.Message,mtError,[mbIgnore, mbAbort],0); end; if Result<>mrOk then exit; end; // check if something changed (so the caches are only cleared if neccesary) if not NewDefineTree.IsEqual(ACodeToolBoss.DefineTree) then begin ACodeToolBoss.DefineTree.Assign(NewDefineTree); end; Result:=mrOk; finally NewDefineTree.Free; end; end; function ShowCodeToolsDefinesEditor(ACodeToolBoss: TCodeToolManager; Options: TCodeToolsOptions; Macros: TTransferMacroList): TModalResult; var CodeToolsDefinesEditor: TCodeToolsDefinesEditor; begin CodeToolsDefinesEditor:=TCodeToolsDefinesEditor.Create(Application); CodeToolsDefinesEditor.Assign(ACodeToolBoss,Options); CodeToolsDefinesEditor.Macros:=Macros; Result:=CodeToolsDefinesEditor.ShowModal; if Result=mrOk then begin if not CodeToolsDefinesEditor.DefineTree.IsEqual(ACodeToolBoss.DefineTree) then begin ACodeToolBoss.DefineTree.Assign(CodeToolsDefinesEditor.DefineTree); Result:=SaveGlobalCodeToolsDefines(ACodeToolBoss,Options); end; end; CodeToolsDefinesEditor.Free; end; { TCodeToolsDefinesEditor } procedure TCodeToolsDefinesEditor.SaveAndExitMenuItemClick(Sender: TObject); begin IDEDialogLayoutList.SaveLayout(Self); SaveSelectedValues; FLastSelectedNode:=nil; ModalResult:=mrOk; end; procedure TCodeToolsDefinesEditor.DontSaveAndExitMenuItemClick(Sender: TObject); begin IDEDialogLayoutList.SaveLayout(Self); ModalResult:=mrCancel; end; procedure TCodeToolsDefinesEditor.SelectedItemGroupBoxResize(Sender: TObject); var SelItemMaxX, SelItemMaxY: integer; begin SelItemMaxX:=SelectedItemGroupBox.ClientWidth; SelItemMaxY:=SelectedItemGroupBox.ClientHeight; with TypeLabel do begin Left:=5; Top:=3; Width:=SelItemMaxX-2*Left; end; with ProjectSpecificCheckBox do begin Left:=TypeLabel.Left; Top:=TypeLabel.Top+TypeLabel.Height+5; Width:=SelItemMaxX-2*Left; end; with NameLabel do begin Left:=ProjectSpecificCheckBox.Left; Top:=ProjectSpecificCheckBox.Top+ProjectSpecificCheckBox.Height+7; Width:=70; end; with NameEdit do begin Left:=NameLabel.Left+NameLabel.Width+5; Top:=NameLabel.Top; Width:=SelItemMaxX-Left-5; end; with DescriptionLabel do begin Left:=NameLabel.Left; Top:=NameLabel.Top+NameLabel.Height+7; Width:=70; end; with DescriptionEdit do begin Left:=DescriptionLabel.Left+DescriptionLabel.Width+5; Top:=DescriptionLabel.Top; Width:=SelItemMaxX-Left-5; end; with VariableLabel do begin Left:=DescriptionLabel.Left; Top:=DescriptionLabel.Top+DescriptionLabel.Height+7; Width:=70; end; with VariableEdit do begin Left:=VariableLabel.Left+VariableLabel.Width+5; Top:=VariableLabel.Top; Width:=SelItemMaxX-Left-5; end; with ValueNoteBook do begin Left:=0; Top:=VariableLabel.Top+VariableLabel.Height+8; Width:=SelItemMaxX; Height:=SelItemMaxY-Top; end; end; procedure TCodeToolsDefinesEditor.FormResize(Sender: TObject); var MaxX, MaxY, SelGrpBoxTop: integer; begin MaxX:=ClientWidth; MaxY:=ClientHeight; SelGrpBoxTop:=MaxY-310; // define tree --------------------------------------------------------------- with DefineTreeView do begin Left:=3; Top:=3; Width:=MaxX-2*Left; Height:=SelGrpBoxTop-2*Top; end; // selected item ------------------------------------------------------------- with SelectedItemGroupBox do begin Left:=DefineTreeView.Left; Top:=SelGrpBoxTop; Width:=MaxX-2*Left; Height:=MaxY-Top-Left; end; end; procedure TCodeToolsDefinesEditor.DefineTreeViewMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer); begin ShowSelectedValues; end; procedure TCodeToolsDefinesEditor.ValueNoteBookPageChanged(Sender: TObject); begin if ValueNoteBook.PageIndex=0 then ValueAsPathToValueAsText else ValueAsFilePathsSynEdit.Text:=ValueToFilePathText(ValueAsTextSynEdit.Text); end; procedure TCodeToolsDefinesEditor.MoveFilePathUpBitBtnClick(Sender: TObject); var y: integer; begin if ValueAsFilePathsSynEdit.ReadOnly then exit; y:=ValueAsFilePathsSynEdit.CaretY-1; if (y>0) and (y=0) and (y=0) and (y=0) and (ynil then SelTreeNode.MoveTo(SelTreeNode.GetNextSibling.GetNextSibling,naInsert) else SelTreeNode.MoveTo(SelTreeNode.GetNextSibling,naAdd); // move node down in DefineTree SelDefNode.Unbind; SelDefNode.InsertBehind(NextDefNode); SelTreeNode.MakeVisible; end; procedure TCodeToolsDefinesEditor.MoveNodeLvlUpMenuItemClick(Sender: TObject); var SelTreeNode: TTreeNode; SelDefNode, PrevDefNode: TDefineTemplate; begin SelTreeNode:=DefineTreeView.Selected; SaveSelectedValues; if (SelTreeNode=nil) or (SelTreeNode.Parent=nil) then exit; SelDefNode:=TDefineTemplate(SelTreeNode.Data); if SelDefNode.IsAutoGenerated then begin MessageDlg('Node is readonly','Auto generated nodes can not be edited.', mtInformation,[mbCancel],0); exit; end; // move node one lvl up in TreeView if SelTreeNode.Parent.GetNextSibling<>nil then SelTreeNode.MoveTo(SelTreeNode.Parent.GetNextSibling,naInsert) else SelTreeNode.MoveTo(SelTreeNode.Parent,naAdd); // move node one lvl up in DefineTree PrevDefNode:=SelDefNode.Parent; SelDefNode.Unbind; SelDefNode.InsertBehind(PrevDefNode); SetNodeImages(SelTreeNode,true); SelTreeNode.MakeVisible; end; procedure TCodeToolsDefinesEditor.MoveNodeLvlDownMenuItemClick(Sender: TObject); var SelTreeNode: TTreeNode; SelDefNode, PrevDefNode: TDefineTemplate; begin SelTreeNode:=DefineTreeView.Selected; SaveSelectedValues; if (SelTreeNode=nil) or (SelTreeNode.GetPrevSibling=nil) then exit; SelDefNode:=TDefineTemplate(SelTreeNode.Data); PrevDefNode:=SelDefNode.Prior; if (SelDefNode.IsAutoGenerated) or (PrevDefNode.IsAutoGenerated) then begin MessageDlg('Node is readonly','Auto generated nodes can not be edited.', mtInformation,[mbCancel],0); exit; end; if (not (PrevDefNode.Action in DefineActionBlocks)) then begin MessageDlg('Invalid previous node', 'Previous node can not contain child nodes.', mtInformation,[mbCancel],0); exit; end; // move node one lvl down in TreeView SelTreeNode.MoveTo(SelTreeNode.GetPrevSibling,naAddChild); // move node one lvl up in DefineTree SelDefNode.Unbind; PrevDefNode.AddChild(SelDefNode); SetNodeImages(SelTreeNode.Parent,true); SelTreeNode.MakeVisible; end; procedure TCodeToolsDefinesEditor.DeleteNodeMenuItemClick(Sender: TObject); var SelTreeNode: TTreeNode; SelDefNode: TDefineTemplate; begin SelTreeNode:=DefineTreeView.Selected; SaveSelectedValues; if (SelTreeNode=nil) then exit; SelDefNode:=TDefineTemplate(SelTreeNode.Data); if (SelDefNode.IsAutoGenerated) then begin MessageDlg('Node is readonly','Auto generated nodes can not be edited.', mtInformation,[mbCancel],0); exit; end; if FLastSelectedNode=SelTreeNode then FLastSelectedNode:=nil; // delete node in TreeView SelTreeNode.Free; // delete node in DefineTree SelDefNode.Unbind; SelDefNode.Free; end; procedure TCodeToolsDefinesEditor.ConvertActionMenuItemClick(Sender: TObject); var NewAction: TDefineAction; SelTreeNode: TTreeNode; SelDefNode: TDefineTemplate; begin SelTreeNode:=DefineTreeView.Selected; SaveSelectedValues; if SelTreeNode=nil then exit; SelDefNode:=TDefineTemplate(SelTreeNode.Data); if (SelDefNode.IsAutoGenerated) then begin MessageDlg('Node is readonly','Auto generated nodes can not be edited.', mtInformation,[mbCancel],0); exit; end; if Sender=ConvertActionToDefineMenuItem then NewAction:=da_Define else if Sender=ConvertActionToDefineRecurseMenuItem then NewAction:=da_DefineRecurse else if Sender=ConvertActionToUndefineMenuItem then NewAction:=da_Undefine else if Sender=ConvertActionToUndefineRecurseMenuItem then NewAction:=da_UndefineRecurse else if Sender=ConvertActionToUndefineAllMenuItem then NewAction:=da_UndefineAll else if Sender=ConvertActionToBlockMenuItem then NewAction:=da_Block else if Sender=ConvertActionToDirectoryMenuItem then NewAction:=da_Directory else if Sender=ConvertActionToIfMenuItem then NewAction:=da_If else if Sender=ConvertActionToIfDefMenuItem then NewAction:=da_IfDef else if Sender=ConvertActionToIfNotDefMenuItem then NewAction:=da_IfNDef else if Sender=ConvertActionToElseIfMenuItem then NewAction:=da_ElseIf else if Sender=ConvertActionToElseMenuItem then NewAction:=da_Else; SelDefNode.Action:=NewAction; SetNodeImages(SelTreeNode,false); SetTypeLabel; end; procedure TCodeToolsDefinesEditor.OpenPreviewMenuItemClick(Sender: TObject); begin if DefinePreview=nil then begin DefinePreview:=TCodeToolsDefinesPreview.Create(Self); DefinePreview.DefineTree:=DefineTree; DefinePreview.Show; end; RefreshPreview; BringWindowToTop(DefinePreview.Handle); end; procedure TCodeToolsDefinesEditor.InsertFPCProjectDefinesTemplateMenuItemClick( Sender: TObject); var InputFileDlg: TInputFileDialog; UnitSearchPath, UnitLinkList, DefaultFPCSrcDir, DefaultCompiler, CompilerPath, FPCSrcDIr: string; DirTemplate, FPCTemplate, FPCSrcTemplate: TDefineTemplate; begin InputFileDlg:=GetInputFileDialog; InputFileDlg.Macros:=Macros; with InputFileDlg do begin DefaultFPCSrcDir:='$(FPCSrcDir)'; DefaultCompiler:='$(CompPath)'; UnitSearchPath:=''; UnitLinkList:=''; BeginUpdate; Caption:='Create FPC Macros and paths for a fpc project directory'; FileCount:=3; FileTitles[0]:='Project directory'; FileDescs[0]:='The Free Pascal project directory.'; FileNames[0]:=''; FileFlags[0]:=[iftDirectory,iftNotEmpty,iftMustExist]; FileTitles[1]:='compiler path'; FileDescs[1]:='The path to the free pascal compiler for this project.'#13 +'Only required if you set the FPC CVS source below.'#13 +'Used to autocreate macros.'; FileNames[1]:=DefaultCompiler; FileFlags[1]:=[iftFilename]; FileTitles[2]:='FPC CVS source directory'; FileDescs[2]:='The Free Pascal CVS source directory.'#13 +'Not required. This will improve find declaration'#13 +'and debugging.'; FileNames[2]:=DefaultFPCSrcDir; FileFlags[2]:=[iftDirectory]; EndUpdate; if ShowModal=mrCancel then exit; // ask the compiler for Macros CompilerPath:=FileNames[1]; if Macros<>nil then Macros.SubstituteStr(CompilerPath); writeln(' CompilerPath="',CompilerPath,'"'); if (CompilerPath<>'') and (CompilerPath<>DefaultCompiler) then FPCTemplate:=Boss.DefinePool.CreateFPCTemplate(CompilerPath, UnitSearchPath) else FPCTemplate:=nil; // create path defines FPCSrcDir:=FileNames[2]; if Macros<>nil then Macros.SubstituteStr(FPCSrcDir); writeln(' FPCSrcDir="',FPCSrcDir,'"'); if (FPCSrcDir<>'') and (FPCSrcDir<>DefaultFPCSrcDir) and (UnitSearchPath<>'') then FPCSrcTemplate:=Boss.DefinePool.CreateFPCSrcTemplate(FPCSrcDir, UnitSearchPath, false, UnitLinkList) else FPCSrcTemplate:=nil; // create directory defines DirTemplate:=TDefineTemplate.Create('FPC Project ('+FileNames[0]+')', 'Free Pascal Project Directory','',FileNames[0],da_Directory); if (DefaultFPCSrcDir=Filenames[2]) and (DefaultCompiler=Filenames[1]) then begin // a normal fpc project -> nothing special needed FPCTemplate.Free; FPCSrcTemplate.Free; end else begin // a special fpc project -> create a world of its own DirTemplate.AddChild(TDefineTemplate.Create('Reset All', 'Reset all values','','',da_UndefineAll)); if FPCTemplate<>nil then DirTemplate.AddChild(FPCTemplate); if UnitLinkList<>'' then begin DirTemplate.AddChild(TDefineTemplate.Create('FPC Unit Links', 'Source filenames for standard FPC units', ExternalMacroStart+'UnitLinks',UnitLinkList,da_DefineRecurse)); end; FPCSrcTemplate.Free; end; InsertTemplate(DirTemplate); end; end; procedure TCodeToolsDefinesEditor.InsertFPCompilerDefinesTemplateMenuItemClick( Sender: TObject); var InputFileDlg: TInputFileDialog; s, CompilerPath, DefaultCompiler: string; FPCTemplate: TDefineTemplate; begin InputFileDlg:=GetInputFileDialog; InputFileDlg.Macros:=Macros; with InputFileDlg do begin DefaultCompiler:='$(CompPath)'; BeginUpdate; Caption:='Create Defines for Free Pascal Compiler'; FileCount:=1; FileTitles[0]:='compiler path'; FileDescs[0]:='The path to the free pascal compiler.'#13 +'For example "/usr/bin/ppc386 -n" or "/usr/local/bin/fpc @/etc/11fpc.cfg".'; FileNames[0]:=DefaultCompiler; FileFlags[0]:=[iftCmdLine,iftNotEmpty]; EndUpdate; if ShowModal=mrCancel then exit; CompilerPath:=FileNames[0]; if Macros<>nil then Macros.SubstituteStr(CompilerPath); writeln(' CompilerPath="',CompilerPath,'"'); FPCTemplate:=Boss.DefinePool.CreateFPCTemplate(CompilerPath,s); if FPCTemplate=nil then exit; FPCTemplate.Name:='Free Pascal Compiler ('+CompilerPath+')'; InsertTemplate(FPCTemplate); end; end; procedure TCodeToolsDefinesEditor.InsertFPCSourceDirDefinesTemplateMenuItemClick (Sender: TObject); var InputFileDlg: TInputFileDialog; UnitSearchPath, UnitLinks, DefaultCompiler, CompilerPath, FPCSrcDir: string; ResetAllTemplate, FPCSrcTemplate, FPCSrcDirTemplate, FPCTemplate: TDefineTemplate; begin InputFileDlg:=GetInputFileDialog; InputFileDlg.Macros:=Macros; with InputFileDlg do begin DefaultCompiler:='$(CompPath)'; UnitSearchPath:=''; BeginUpdate; Caption:='Create Defines for Free Pascal CVS Sources'; FileCount:=2; FileTitles[0]:='FPC CVS source directory'; FileDescs[0]:='The Free Pascal CVS source directory.'; FileNames[0]:='~/fpc_sources/1.1/fpc'; FileFlags[0]:=[iftDirectory,iftNotEmpty,iftMustExist]; FileTitles[1]:='compiler path'; FileDescs[1]:='The path to the free pascal compiler for this source.'#13 +'Used to autocreate macros.'; FileNames[1]:=DefaultCompiler; FileFlags[1]:=[iftFilename]; EndUpdate; if ShowModal=mrCancel then exit; // ask the compiler for Macros CompilerPath:=FileNames[1]; if Macros<>nil then Macros.SubstituteStr(CompilerPath); writeln(' CompilerPath="',CompilerPath,'"'); FPCTemplate:=Boss.DefinePool.CreateFPCTemplate(CompilerPath,UnitSearchPath); if FPCTemplate=nil then begin writeln('ERROR: unable to get FPC Compiler Macros from "',CompilerPath,'"'); exit; end; // create FPC CVS Source defines FPCSrcDir:=FileNames[0]; if Macros<>nil then Macros.SubstituteStr(FPCSrcDir); writeln(' FPCSrcDir="',FPCSrcDir,'"'); UnitSearchPath:=''; FPCSrcTemplate:=Boss.DefinePool.CreateFPCSrcTemplate(FPCSrcDir, UnitSearchPath, false, UnitLinks); if FPCSrcTemplate=nil then begin writeln('ERROR: unable to create FPC CVS Src defines for "',FPCSrcDir,'"'); FPCTemplate.Free; exit; end; // create directory defines FPCSrcDirTemplate:=FPCSrcTemplate.FirstChild.Next; FPCSrcDirTemplate.UnBind; FPCSrcTemplate.Free; FPCSrcDirTemplate.Name:='FPC CVS Sources ('+FileNames[0]+')'; ResetAllTemplate:=TDefineTemplate.Create('Reset All','Reset all values', '','',da_UndefineAll); ResetAllTemplate.InsertInFront(FPCSrcDirTemplate.FirstChild); FPCTemplate.InsertBehind(ResetAllTemplate); InsertTemplate(FPCSrcDirTemplate); end; end; procedure TCodeToolsDefinesEditor.InsertLazarusSourceDefinesTemplateMenuItemClick (Sender: TObject); var InputFileDlg: TInputFileDialog; LazTemplate: TDefineTemplate; begin InputFileDlg:=GetInputFileDialog; InputFileDlg.Macros:=Macros; with InputFileDlg do begin BeginUpdate; Caption:='Create Defines for Lazarus Directory'; FileCount:=1; FileTitles[0]:='Lazarus Directory'; FileDescs[0]:='The Lazarus main directory.'; FileNames[0]:=ExpandFilename(ExtractFilePath(ParamStr(0))); FileFlags[0]:=[iftDirectory,iftNotEmpty,iftMustExist]; EndUpdate; if ShowModal=mrCancel then exit; LazTemplate:=Boss.DefinePool.CreateLazarusSrcTemplate(FileNames[0], '$('+ExternalMacroStart+'LCLWidgetType)'); if LazTemplate=nil then exit; LazTemplate.Name:='Lazarus Directory ('+FileNames[0]+')'; InsertTemplate(LazTemplate); end; end; procedure TCodeToolsDefinesEditor.InsertDelphiCompilerDefinesTemplateMenuItemClick (Sender: TObject); var DelphiVersion: integer; begin if Sender=InsertDelphi6CompilerDefinesTemplateMenuItem then DelphiVersion:=6 else DelphiVersion:=5; InsertTemplate(Boss.DefinePool.CreateDelphiCompilerDefinesTemplate( DelphiVersion)); end; procedure TCodeToolsDefinesEditor.InsertDelphiDirectoryTemplateMenuItemClick( Sender: TObject); var InputFileDlg: TInputFileDialog; DirTemplate: TDefineTemplate; DelphiVersion: integer; DelphiName: string; begin if Sender=InsertDelphi6DirectoryTemplateMenuItem then DelphiVersion:=6 else DelphiVersion:=5; DelphiName:='Delphi'+IntToStr(DelphiVersion); InputFileDlg:=GetInputFileDialog; InputFileDlg.Macros:=Macros; with InputFileDlg do begin BeginUpdate; Caption:='Create Defines for '+DelphiName+' Directory'; FileCount:=1; FileTitles[0]:=DelphiName+' directory'; FileDescs[0]:='The '+DelphiName+' main directory,'#13 +'where Borland has installed all '+DelphiName+' sources.'#13 +'For example: C:/Programme/Borland/Delphi'+IntToStr(DelphiVersion); FileNames[0]:=SetDirSeparators( 'C:/Programme/Borland/Delphi'+IntToStr(DelphiVersion)); FileFlags[0]:=[iftDirectory,iftNotEmpty,iftMustExist]; EndUpdate; if ShowModal=mrCancel then exit; DirTemplate:=Boss.DefinePool.CreateDelphiDirectoryTemplate(FileNames[0], DelphiVersion); if DirTemplate=nil then exit; DirTemplate.Name:=DelphiName+' ('+FileNames[0]+')'; InsertTemplate(DirTemplate); end; end; procedure TCodeToolsDefinesEditor.InsertDelphiProjectTemplateMenuItemClick( Sender: TObject); var InputFileDlg: TInputFileDialog; ProjTemplate: TDefineTemplate; DelphiVersion: integer; DelphiName: string; begin if Sender=InsertDelphi6ProjectTemplateMenuItem then DelphiVersion:=6 else DelphiVersion:=5; DelphiName:='Delphi'+IntToStr(DelphiVersion); InputFileDlg:=GetInputFileDialog; InputFileDlg.Macros:=Macros; with InputFileDlg do begin BeginUpdate; Caption:='Create Defines for '+DelphiName+' Project'; FileCount:=2; FileTitles[0]:=DelphiName+' project directory'; FileDescs[0]:='The '+DelphiName+' project directory,'#13 +'which contains the .dpr, dpk file.'; FileNames[0]:=SetDirSeparators('C:/Programme/Borland/Delphi' +IntToStr(DelphiVersion)+'/YourProject'); FileFlags[0]:=[iftDirectory,iftNotEmpty,iftMustExist]; FileTitles[1]:=DelphiName+' directory'; FileDescs[1]:='The '+DelphiName+' main directory,'#13 +'where Borland has installed all '+DelphiName+' sources,'#13 +'which are used by this '+DelphiName+' project.'#13 +'For example: C:/Programme/Borland/Delphi'+IntToStr(DelphiVersion); FileNames[1]:=SetDirSeparators('C:/Programme/Borland/Delphi' +IntToStr(DelphiVersion)); FileFlags[1]:=[iftDirectory,iftNotEmpty,iftMustExist]; EndUpdate; if ShowModal=mrCancel then exit; ProjTemplate:=Boss.DefinePool.CreateDelphiProjectTemplate(FileNames[0], FileNames[1],DelphiVersion); if ProjTemplate=nil then exit; ProjTemplate.Name:=DelphiName+' Project ('+FileNames[0]+')'; InsertTemplate(ProjTemplate); end; end; procedure TCodeToolsDefinesEditor.ValueNoteBookResize(Sender: TObject); var ValNoteBookMaxX, ValNoteBookMaxY: integer; begin //ValNoteBookMaxX:=ValueNoteBook.ClientWidth-10;//ValueAsTextSynEdit.Parent.ClientWidth; //ValNoteBookMaxY:=ValueNoteBook.ClientHeight-30;//ValueAsTextSynEdit.Parent.ClientHeight; ValNoteBookMaxX:=ValueAsTextSynEdit.Parent.ClientWidth; ValNoteBookMaxY:=ValueAsTextSynEdit.Parent.ClientHeight; with ValueAsTextSynEdit do begin Left:=0; Top:=0; Width:=ValNoteBookMaxX; Height:=ValNoteBookMaxY; end; with ValueAsFilePathsSynEdit do begin Left:=0; Top:=0; Width:=ValNoteBookMaxX-80; Height:=ValNoteBookMaxY; end; with MoveFilePathUpBitBtn do begin Left:=ValNoteBookMaxX-75; Top:=1; Width:=ValNoteBookMaxX-Left-5; end; with MoveFilePathDownBitBtn do begin Left:=MoveFilePathUpBitBtn.Left; Top:=MoveFilePathUpBitBtn.Top+MoveFilePathUpBitBtn.Height+5; Width:=MoveFilePathUpBitBtn.Width; end; with DeleteFilePathBitBtn do begin Left:=MoveFilePathUpBitBtn.Left; Top:=MoveFilePathDownBitBtn.Top+MoveFilePathDownBitBtn.Height+5; Width:=MoveFilePathUpBitBtn.Width; end; with InsertFilePathBitBtn do begin Left:=MoveFilePathUpBitBtn.Left; Top:=DeleteFilePathBitBtn.Top+DeleteFilePathBitBtn.Height+5; Width:=MoveFilePathUpBitBtn.Width; end; end; procedure TCodeToolsDefinesEditor.ProjectSpecificCheckBoxClick(Sender: TObject); var SelTreeNode: TTreeNode; SelDefNode: TDefineTemplate; begin SelTreeNode:=DefineTreeView.Selected; if SelTreeNode=nil then exit; SelDefNode:=TDefineTemplate(SelTreeNode.Data); if ProjectSpecificCheckBox.Checked=(dtfProjectSpecific in SelDefNode.Flags) then exit; if SelDefNode.IsAutoGenerated then begin MessageDlg('Node is readonly','Auto generated nodes can not be edited.', mtInformation,[mbCancel],0); exit; end; if ProjectSpecificCheckBox.Checked then Include(SelDefNode.Flags,dtfProjectSpecific) else Exclude(SelDefNode.Flags,dtfProjectSpecific); SetNodeImages(SelTreeNode,true); SetTypeLabel; end; procedure TCodeToolsDefinesEditor.RefreshPreview; begin if DefinePreview=nil then exit; DefinePreview.ShowDefines; end; procedure TCodeToolsDefinesEditor.CreateComponents; procedure CreateWinControl(var AWinControl: TWinControl; AWinControlClass: TWinControlClass; const AName: string; AParent: TWinControl); begin AWinControl:=AWinControlClass.Create(Self); with AWinControl do begin Name:=AName; Parent:=AParent; Visible:=true; end; end; procedure AddMenuItem(var AMenuItem: TMenuItem; const AName, ACaption: string; AParent: TMenuItem); begin AMenuItem:=TMenuItem.Create(Self); AMenuItem.Name:=AName; AMenuItem.Caption:=ACaption; if AParent=nil then MainMenu.Items.Add(AMenuItem) else AParent.Add(AMenuItem); end; procedure AddResImg(const ResName: string); var Pixmap: TPixmap; begin Pixmap:=TPixmap.Create; Pixmap.TransparentColor:=clWhite; Pixmap.LoadFromLazarusResource(ResName); TheImageList.Add(Pixmap,nil) end; var i: integer; begin TheImageList:=TImageList.Create(Self); with TheImageList do begin Width:=22; Height:=22; Name:='TheImageList'; AddResImg('define_22x22'); AddResImg('definerecurse_22x22'); AddResImg('undefine_22x22'); AddResImg('undefinerecurse_22x22'); AddResImg('undefineall_22x22'); AddResImg('block_22x22'); AddResImg('directory_22x22'); AddResImg('if_22x22'); AddResImg('ifdef_22x22'); AddResImg('ifndef_22x22'); AddResImg('elseif_22x22'); AddResImg('else_22x22'); AddResImg('ctdefinestate_none_22x22'); AddResImg('ctdefinestate_auto_22x22'); AddResImg('ctdefinestate_projspec_22x22'); AddResImg('ctdefinestate_autoproj_22x22'); end; // Main Menu ----------------------------------------------------------------- MainMenu := TMainMenu.Create(Self); MainMenu.Name:='MainMenu'; Menu := MainMenu; // exit menu AddMenuItem(ExitMenuItem,'ExitMenuItem','Exit',nil); AddMenuItem(SaveAndExitMenuItem,'SaveAndExitMenuItem','Save and Exit', ExitMenuItem); SaveAndExitMenuItem.OnClick:=@SaveAndExitMenuItemClick; ExitMenuItem.Add(CreateSeperator); AddMenuItem(DontSaveAndExitMenuItem,'DontSaveAndExitMenuItem', 'Exit without Save',ExitMenuItem); DontSaveAndExitMenuItem.OnClick:=@DontSaveAndExitMenuItemClick; // edit nodes AddMenuItem(EditMenuItem,'EditMenuItem','Edit',nil); AddMenuItem(MoveNodeUpMenuItem,'MoveNodeUpMenuItem','Move node up', EditMenuItem); MoveNodeUpMenuItem.OnClick:=@MoveNodeUpMenuItemClick; AddMenuItem(MoveNodeDownMenuItem,'MoveNodeDownMenuItem','Move node down', EditMenuItem); MoveNodeDownMenuItem.OnClick:=@MoveNodeDownMenuItemClick; AddMenuItem(MoveNodeLvlUpMenuItem,'MoveNodeLvlUpMenuItem','Move node one level up', EditMenuItem); MoveNodeLvlUpMenuItem.OnClick:=@MoveNodeLvlUpMenuItemClick; AddMenuItem(MoveNodeLvlDownMenuItem,'MoveNodeLvlDownMenuItem','Move node one level down', EditMenuItem); MoveNodeLvlDownMenuItem.OnClick:=@MoveNodeLvlDownMenuItemClick; EditMenuItem.Add(CreateSeperator); AddMenuItem(InsertBehindMenuItem,'InsertBehindMenuItem','Insert node below', EditMenuItem); AddMenuItem(InsertAsChildMenuItem,'InsertAsChildMenuItem','Insert node as child', EditMenuItem); EditMenuItem.Add(CreateSeperator); AddMenuItem(DeleteNodeMenuItem,'DeleteNodeMenuItem','Delete node', EditMenuItem); DeleteNodeMenuItem.OnClick:=@DeleteNodeMenuItemClick; AddMenuItem(ConvertActionMenuItem,'ConvertActionMenuItem','Convert node', EditMenuItem); { EditMenuItem.Add(CreateSeperator); AddMenuItem(CopyToClipbrdMenuItem,'CopyToClipbrdMenuItem','Copy to clipboard', EditMenuItem); AddMenuItem(PasteFromClipbrdMenuItem,'PasteFromClipbrdMenuItem', 'Paste from clipboard',EditMenuItem);} // insert node behind submenu AddMenuItem(InsertBehindDefineMenuItem,'InsertBehindDefineMenuItem','Define', InsertBehindMenuItem); AddMenuItem(InsertBehindDefineRecurseMenuItem, 'InsertBehindDefineRecurseMenuItem','Define Recurse', InsertBehindMenuItem); AddMenuItem(InsertBehindUndefineMenuItem, 'InsertBehindUndefineMenuItem','Undefine', InsertBehindMenuItem); AddMenuItem(InsertBehindUndefineRecurseMenuItem, 'InsertBehindUndefineRecurseMenuItem','Undefine Recurse', InsertBehindMenuItem); AddMenuItem(InsertBehindUndefineAllMenuItem, 'InsertBehindUndefineAllMenuItem','Undefine All', InsertBehindMenuItem); InsertBehindMenuItem.Add(CreateSeperator); AddMenuItem(InsertBehindBlockMenuItem,'InsertBehindBlockMenuItem','Block', InsertBehindMenuItem); AddMenuItem(InsertBehindDirectoryMenuItem, 'InsertBehindDirectoryMenuItem','Directory', InsertBehindMenuItem); InsertBehindMenuItem.Add(CreateSeperator); AddMenuItem(InsertBehindIfMenuItem,'InsertBehindIfMenuItem','If', InsertBehindMenuItem); AddMenuItem(InsertBehindIfDefMenuItem,'InsertBehindIfDefMenuItem','IfDef', InsertBehindMenuItem); AddMenuItem(InsertBehindIfNotDefMenuItem,'InsertBehindIfNotDefMenuItem','IfNDef', InsertBehindMenuItem); AddMenuItem(InsertBehindElseIfMenuItem,'InsertBehindElseIfMenuItem','ElseIf', InsertBehindMenuItem); AddMenuItem(InsertBehindElseMenuItem,'InsertBehindElseMenuItem','Else', InsertBehindMenuItem); for i:=0 to InsertBehindMenuItem.Count-1 do if InsertBehindMenuItem[i].Caption<>'-' then InsertBehindMenuItem[i].OnClick:=@InsertNodeMenuItemClick; // insert node as child submenu AddMenuItem(InsertAsChildDefineMenuItem,'InsertAsChildDefineMenuItem','Define', InsertAsChildMenuItem); AddMenuItem(InsertAsChildDefineRecurseMenuItem, 'InsertAsChildDefineRecurseMenuItem','Define Recurse', InsertAsChildMenuItem); AddMenuItem(InsertAsChildUndefineMenuItem, 'InsertAsChildUndefineMenuItem','Undefine', InsertAsChildMenuItem); AddMenuItem(InsertAsChildUndefineRecurseMenuItem, 'InsertAsChildUndefineRecurseMenuItem','Undefine Recurse', InsertAsChildMenuItem); AddMenuItem(InsertAsChildUndefineAllMenuItem, 'InsertAsChildUndefineAllMenuItem','Undefine All', InsertAsChildMenuItem); InsertAsChildMenuItem.Add(CreateSeperator); AddMenuItem(InsertAsChildBlockMenuItem,'InsertAsChildBlockMenuItem','Block', InsertAsChildMenuItem); AddMenuItem(InsertAsChildDirectoryMenuItem, 'InsertAsChildDirectoryMenuItem','Directory', InsertAsChildMenuItem); InsertAsChildMenuItem.Add(CreateSeperator); AddMenuItem(InsertAsChildIfMenuItem,'InsertAsChildIfMenuItem','If', InsertAsChildMenuItem); AddMenuItem(InsertAsChildIfDefMenuItem,'InsertAsChildIfDefMenuItem','IfDef', InsertAsChildMenuItem); AddMenuItem(InsertAsChildIfNotDefMenuItem,'InsertAsChildIfNotDefMenuItem','IfNDef', InsertAsChildMenuItem); AddMenuItem(InsertAsChildElseIfMenuItem,'InsertAsChildElseIfMenuItem','ElseIf', InsertAsChildMenuItem); AddMenuItem(InsertAsChildElseMenuItem,'InsertAsChildElseMenuItem','Else', InsertAsChildMenuItem); for i:=0 to InsertAsChildMenuItem.Count-1 do if InsertAsChildMenuItem[i].Caption<>'-' then InsertAsChildMenuItem[i].OnClick:=@InsertNodeMenuItemClick; // convert node sub menu AddMenuItem(ConvertActionToDefineMenuItem,'ConvertActionToDefineMenuItem','Define', ConvertActionMenuItem); AddMenuItem(ConvertActionToDefineRecurseMenuItem, 'ConvertActionToDefineRecurseMenuItem','Define Recurse', ConvertActionMenuItem); AddMenuItem(ConvertActionToUndefineMenuItem, 'ConvertActionToUndefineMenuItem','Undefine', ConvertActionMenuItem); AddMenuItem(ConvertActionToUndefineRecurseMenuItem, 'ConvertActionToUndefineRecurseMenuItem','Undefine Recurse', ConvertActionMenuItem); AddMenuItem(ConvertActionToUndefineAllMenuItem, 'ConvertActionToUndefineAllMenuItem','Undefine All', ConvertActionMenuItem); ConvertActionMenuItem.Add(CreateSeperator); AddMenuItem(ConvertActionToBlockMenuItem,'ConvertActionToBlockMenuItem','Block', ConvertActionMenuItem); AddMenuItem(ConvertActionToDirectoryMenuItem, 'ConvertActionToDirectoryMenuItem','Directory', ConvertActionMenuItem); ConvertActionMenuItem.Add(CreateSeperator); AddMenuItem(ConvertActionToIfMenuItem,'ConvertActionToIfMenuItem','If', ConvertActionMenuItem); AddMenuItem(ConvertActionToIfDefMenuItem,'ConvertActionToIfDefMenuItem','IfDef', ConvertActionMenuItem); AddMenuItem(ConvertActionToIfNotDefMenuItem,'ConvertActionToIfNotDefMenuItem','IfNDef', ConvertActionMenuItem); AddMenuItem(ConvertActionToElseIfMenuItem,'ConvertActionToElseIfMenuItem','ElseIf', ConvertActionMenuItem); AddMenuItem(ConvertActionToElseMenuItem,'ConvertActionToElseMenuItem','Else', ConvertActionMenuItem); for i:=0 to ConvertActionMenuItem.Count-1 do if ConvertActionMenuItem[i].Caption<>'-' then ConvertActionMenuItem[i].OnClick:=@ConvertActionMenuItemClick; // tools {AddMenuItem(ToolsMenuItem,'ToolsMenuItem','Tools',nil); AddMenuItem(OpenPreviewMenuItem,'OpenPreviewMenuItem','Open Preview', ToolsMenuItem); OpenPreviewMenuItem.OnClick:=@OpenPreviewMenuItemClick; AddMenuItem(ShowMacroListMenuItem,'ShowMacroListMenuItem','Show Macros', ToolsMenuItem);} // templates AddMenuItem(InsertTemplateMenuItem,'InsertTemplateMenuItem', 'Insert Template',nil); AddMenuItem(InsertFPCProjectDefinesTemplateMenuItem, 'InsertFPCProjectDefinesTemplateMenuItem', 'Insert Free Pascal Project Template', InsertTemplateMenuItem); InsertFPCProjectDefinesTemplateMenuItem.OnClick:= @InsertFPCProjectDefinesTemplateMenuItemClick; AddMenuItem(InsertFPCompilerDefinesTemplateMenuItem, 'InsertFPCompilerDefinesTemplateMenuItem', 'Insert Free Pascal Compiler Template', InsertTemplateMenuItem); InsertFPCompilerDefinesTemplateMenuItem.OnClick:= @InsertFPCompilerDefinesTemplateMenuItemClick; AddMenuItem(InsertFPCSourceDirTemplateMenuItem, 'InsertFPCSourceDirTemplateMenuItem', 'Insert Free Pascal CVS Source Template', InsertTemplateMenuItem); InsertFPCSourceDirTemplateMenuItem.OnClick:= @InsertFPCSourceDirDefinesTemplateMenuItemClick; InsertTemplateMenuItem.Add(CreateSeperator); AddMenuItem(InsertLazarusSourceTemplateMenuItem, 'InsertLazarusSourceTemplateMenuItem', 'Insert Lazarus Directory Template', InsertTemplateMenuItem); InsertLazarusSourceTemplateMenuItem.OnClick:= @InsertLazarusSourceDefinesTemplateMenuItemClick; InsertTemplateMenuItem.Add(CreateSeperator); AddMenuItem(InsertDelphi5CompilerDefinesTemplateMenuItem, 'InsertDelphi5CompilerDefinesTemplateMenuItem', 'Insert Delphi 5 Compiler Template', InsertTemplateMenuItem); InsertDelphi5CompilerDefinesTemplateMenuItem.OnClick:= @InsertDelphiCompilerDefinesTemplateMenuItemClick; AddMenuItem(InsertDelphi5DirectoryTemplateMenuItem, 'InsertDelphi5DirectoryTemplateMenuItem', 'Insert Delphi 5 Directory Template', InsertTemplateMenuItem); InsertDelphi5DirectoryTemplateMenuItem.OnClick:= @InsertDelphiDirectoryTemplateMenuItemClick; AddMenuItem(InsertDelphi5ProjectTemplateMenuItem, 'InsertDelphi5ProjectTemplateMenuItem', 'Insert Delphi 5 Project Template', InsertTemplateMenuItem); InsertDelphi5ProjectTemplateMenuItem.OnClick:= @InsertDelphiProjectTemplateMenuItemClick; InsertTemplateMenuItem.Add(CreateSeperator); AddMenuItem(InsertDelphi6CompilerDefinesTemplateMenuItem, 'InsertDelphi6CompilerDefinesTemplateMenuItem', 'Insert Delphi 6 Compiler Template', InsertTemplateMenuItem); InsertDelphi6CompilerDefinesTemplateMenuItem.OnClick:= @InsertDelphiCompilerDefinesTemplateMenuItemClick; AddMenuItem(InsertDelphi6DirectoryTemplateMenuItem, 'InsertDelphi6DirectoryTemplateMenuItem', 'Insert Delphi 6 Directory Template', InsertTemplateMenuItem); InsertDelphi6DirectoryTemplateMenuItem.OnClick:= @InsertDelphiDirectoryTemplateMenuItemClick; AddMenuItem(InsertDelphi6ProjectTemplateMenuItem, 'InsertDelphi6ProjectTemplateMenuItem', 'Insert Delphi 6 Project Template', InsertTemplateMenuItem); InsertDelphi6ProjectTemplateMenuItem.OnClick:= @InsertDelphiProjectTemplateMenuItemClick; // define tree---------------------------------------------------------------- CreateWinControl(DefineTreeView,TTreeView,'DefineTreeView',Self); with DefineTreeView do begin DefaultItemHeight:=22; Images:=TheImageList; StateImages:=TheImageList; OnMouseUp:=@DefineTreeViewMouseUp; end; // selected item CreateWinControl(SelectedItemGroupBox,TGroupBox,'SelectedItemGroupBox',Self); SelectedItemGroupBox.Caption:='Selected Node:'; SelectedItemGroupBox.OnResize:=@SelectedItemGroupBoxResize; CreateWinControl(TypeLabel,TLabel,'TypeLabel',SelectedItemGroupBox); CreateWinControl(ProjectSpecificCheckBox,TCheckBox,'ProjectSpecificCheckBox', SelectedItemGroupBox); ProjectSpecificCheckBox.Caption:= 'Node and its children are only valid for this project'; ProjectSpecificCheckBox.OnClick:=@ProjectSpecificCheckBoxClick; CreateWinControl(NameLabel,TLabel,'NameLabel',SelectedItemGroupBox); NameLabel.Caption:='Name:'; CreateWinControl(NameEdit,TEdit,'NameEdit',SelectedItemGroupBox); CreateWinControl(DescriptionLabel,TLabel,'DescriptionLabel', SelectedItemGroupBox); DescriptionLabel.Caption:='Description:'; CreateWinControl(DescriptionEdit,TEdit,'DescriptionEdit', SelectedItemGroupBox); CreateWinControl(VariableLabel,TLabel,'VariableLabel',SelectedItemGroupBox); VariableLabel.Caption:='Variable:'; CreateWinControl(VariableEdit,TEdit,'VariableEdit',SelectedItemGroupBox); CreateWinControl(ValueNoteBook,TNoteBook,'ValueNoteBook', SelectedItemGroupBox); with ValueNoteBook do begin if PageCount>0 then Pages[0]:='Value as Text' else Pages.Add('Value as Text'); Pages.Add('Value as File Paths'); OnPageChanged:=@ValueNoteBookPageChanged; OnResize:=@ValueNoteBookResize; end; CreateWinControl(ValueAsTextSynEdit,TSynEdit,'ValueAsTextSynEdit', ValueNoteBook.Page[0]); ValueAsTextSynEdit.Options:=[eoBracketHighlight, eoHideRightMargin, eoDragDropEditing, eoHalfPageScroll, eoScrollByOneLess, eoScrollPastEol, eoSmartTabs, eoTabsToSpaces, eoTrimTrailingSpaces]; ValueAsTextSynEdit.Gutter.Visible:=false; ValueAsTextSynEdit.Align:=alClient; CreateWinControl(ValueAsFilePathsSynEdit,TSynEdit,'ValueAsFilePathsSynEdit', ValueNoteBook.Page[1]); ValueAsFilePathsSynEdit.Options:=[eoBracketHighlight, eoHideRightMargin, eoDragDropEditing, eoHalfPageScroll, eoScrollByOneLess, eoScrollPastEol, eoSmartTabs, eoTabsToSpaces, eoTrimTrailingSpaces]; ValueAsFilePathsSynEdit.Gutter.Visible:=false; CreateWinControl(MoveFilePathUpBitBtn,TBitBtn,'MoveFilePathUpBitBtn', ValueNoteBook.Page[1]); MoveFilePathUpBitBtn.Caption:='Up'; MoveFilePathUpBitBtn.OnClick:=@MoveFilePathUpBitBtnClick; CreateWinControl(MoveFilePathDownBitBtn,TBitBtn,'MoveFilePathDownBitBtn', ValueNoteBook.Page[1]); MoveFilePathDownBitBtn.Caption:='Down'; MoveFilePathDownBitBtn.OnClick:=@MoveFilePathDownBitBtnClick; CreateWinControl(DeleteFilePathBitBtn,TBitBtn,'DeleteFilePathBitBtn', ValueNoteBook.Page[1]); DeleteFilePathBitBtn.Caption:='Delete'; DeleteFilePathBitBtn.OnClick:=@DeleteFilePathBitBtnClick; CreateWinControl(InsertFilePathBitBtn,TBitBtn,'InsertFilePathBitBtn', ValueNoteBook.Page[1]); InsertFilePathBitBtn.Caption:='Insert'; InsertFilePathBitBtn.OnClick:=@InsertFilePathBitBtnClick; end; function TCodeToolsDefinesEditor.CreateSeperator : TMenuItem; begin Result := TMenuItem.Create(Self); Result.Caption := '-'; end; procedure TCodeToolsDefinesEditor.RebuildDefineTreeView; begin DefineTreeView.Items.BeginUpdate; DefineTreeView.Items.Clear; AddDefineNodes(FDefineTree.RootTemplate,nil,true,true); DefineTreeView.Items.EndUpdate; end; procedure TCodeToolsDefinesEditor.AddDefineNodes( ANode: TDefineTemplate; AParent: TTreeNode; WithChilds, WithNextSiblings: boolean); var NewTreeNode: TTreeNode; begin if ANode=nil then exit; //writeln(' AAA ',StringOfChar(' ',ANode.Level*2),' ',ANode.Name,' ',WithChilds,',',WithNextSiblings); DefineTreeView.Items.BeginUpdate; NewTreeNode:=DefineTreeView.Items.AddChildObject(AParent,ANode.Name,ANode); SetNodeImages(NewTreeNode,false); if WithChilds and (ANode.FirstChild<>nil) then begin AddDefineNodes(ANode.FirstChild,NewTreeNode,true,true); end; if WithNextSiblings and (ANode.Next<>nil) then begin AddDefineNodes(ANode.Next,AParent,WithChilds,true); end; DefineTreeView.Items.EndUpdate; end; procedure TCodeToolsDefinesEditor.SetNodeImages(ANode: TTreeNode; WithSubNodes: boolean); var ADefineTemplate: TDefineTemplate; begin ADefineTemplate:=TDefineTemplate(ANode.Data); case ADefineTemplate.Action of da_Define: ANode.ImageIndex:=0; da_DefineRecurse: ANode.ImageIndex:=1; da_Undefine: ANode.ImageIndex:=2; da_UndefineRecurse: ANode.ImageIndex:=3; da_UndefineAll: ANode.ImageIndex:=4; da_Block: ANode.ImageIndex:=5; da_Directory: ANode.ImageIndex:=6; da_If: ANode.ImageIndex:=7; da_IfDef: ANode.ImageIndex:=8; da_IfNDef: ANode.ImageIndex:=9; da_ElseIf: ANode.ImageIndex:=10; da_Else: ANode.ImageIndex:=11; else ANode.ImageIndex:=-1; end; ANode.SelectedIndex:=ANode.ImageIndex; if ADefineTemplate.IsAutoGenerated then begin if ADefineTemplate.IsProjectSpecific then ANode.StateIndex:=15 else ANode.StateIndex:=13; end else begin if ADefineTemplate.IsProjectSpecific then ANode.StateIndex:=14 else ANode.StateIndex:=12; end; if WithSubNodes then begin ANode:=ANode.GetFirstChild; while ANode<>nil do begin SetNodeImages(ANode,true); ANode:=ANode.GetNextSibling; end; end; end; procedure TCodeToolsDefinesEditor.SetTransferMacros( const AValue: TTransferMacroList); begin FTransferMacros:=AValue; end; procedure TCodeToolsDefinesEditor.ValueAsPathToValueAsText; var s: string; i, j, l: integer; begin s:=ValueAsFilePathsSynEdit.Text; l:=length(s); // replace line ends with semicolon i:=1; j:=1; while i<=l do begin if s[i] in [#10,#13] then begin inc(i); if (is[i]) then begin inc(i); end; s[j]:=';'; inc(j); end else begin s[j]:=s[i]; inc(i); inc(j); end; end; dec(j); while (j>=1) and (s[j]=';') do dec(j); SetLength(s,j); ValueAsTextSynEdit.Text:=s; end; procedure TCodeToolsDefinesEditor.SaveSelectedValues; var ATreeNode: TTreeNode; ADefNode: TDefineTemplate; s: string; l: integer; begin ATreeNode:=FLastSelectedNode; if (ATreeNode<>nil) then begin ADefNode:=TDefineTemplate(ATreeNode.Data); if (not ADefNode.IsAutoGenerated) then begin if ProjectSpecificCheckBox.Checked then Include(ADefNode.Flags,dtfProjectSpecific); ADefNode.Name:=NameEdit.Text; ATreeNode.Text:=ADefNode.Name; ADefNode.Variable:=VariableEdit.Text; ADefNode.Description:=DescriptionEdit.Text; if ValueNoteBook.PageIndex=1 then ValueAsPathToValueAsText; s:=ValueAsTextSynEdit.Text; l:=length(s); if (l>0) and (s[l] in [#13,#10]) then begin // remove line end at end of Text, that was added automatically dec(l); if (l>0) and (s[l] in [#13,#10]) and (s[l]<>s[l+1]) then dec(l); SetLength(s,l); end; ADefNode.Value:=s; end; FLastSelectedNode:=nil; end; end; procedure TCodeToolsDefinesEditor.ShowSelectedValues; var SelTreeNode: TTreeNode; SelDefNode: TDefineTemplate; begin SelTreeNode:=DefineTreeView.Selected; if SelTreeNode<>FLastSelectedNode then begin SaveSelectedValues; end; if SelTreeNode<>nil then begin SelDefNode:=TDefineTemplate(SelTreeNode.Data); SetValuesEditable(not SelDefNode.IsAutoGenerated); ProjectSpecificCheckBox.Checked:=dtfProjectSpecific in SelDefNode.Flags; NameEdit.Text:=SelDefNode.Name; DescriptionEdit.Text:=SelDefNode.Description; VariableEdit.Text:=SelDefNode.Variable; ValueAsTextSynEdit.Text:=SelDefNode.Value; ValueAsFilePathsSynEdit.Text:=ValueToFilePathText(SelDefNode.Value); if SelDefNode.IsAutoGenerated then begin ValueAsTextSynEdit.Options:=ValueAsTextSynEdit.Options+[eoNoCaret]; ValueAsTextSynEdit.ReadOnly:=true; end else begin ValueAsTextSynEdit.Options:=ValueAsTextSynEdit.Options-[eoNoCaret]; ValueAsTextSynEdit.ReadOnly:=false; end; ValueAsFilePathsSynEdit.Options:=ValueAsTextSynEdit.Options; ValueAsFilePathsSynEdit.ReadOnly:=ValueAsTextSynEdit.ReadOnly; end else begin SetValuesEditable(false); NameEdit.Text:=''; DescriptionEdit.Text:=''; VariableEdit.Text:=''; ValueAsTextSynEdit.Text:=''; ValueAsFilePathsSynEdit.Text:=''; end; SetTypeLabel; FLastSelectedNode:=SelTreeNode; end; procedure TCodeToolsDefinesEditor.SetTypeLabel; var SelTreeNode: TTreeNode; SelDefNode: TDefineTemplate; s: string; begin SelTreeNode:=DefineTreeView.Selected; if SelTreeNode<>nil then begin SelDefNode:=TDefineTemplate(SelTreeNode.Data); s:='Action: '+DefineActionNames[SelDefNode.Action]; if SelDefNode.IsAutoGenerated then s:=s+', auto generated'; if SelDefNode.IsProjectSpecific then s:=s+', project specific'; end else begin s:='none selected'; end; TypeLabel.Caption:=s; end; function TCodeToolsDefinesEditor.ValueToFilePathText(const AValue: string ): string; var i: integer; begin Result:=AValue; for i:=1 to length(Result) do if Result[i]=';' then Result[i]:=#13; end; procedure TCodeToolsDefinesEditor.InsertNewNode(Behind: boolean; Action: TDefineAction); var SelTreeNode, NodeInFront, ParentNode, NewTreeNode: TTreeNode; NewDefNode: TDefineTemplate; NewName, NewDescription, NewVariable, NewValue: string; begin SelTreeNode:=DefineTreeView.Selected; SaveSelectedValues; NodeInFront:=nil; ParentNode:=nil; if SelTreeNode<>nil then begin // there is an selected node if Behind then begin // insert behind selected node NodeInFront:=SelTreeNode; ParentNode:=NodeInFront.Parent; end else begin // insert as last child of selected node ParentNode:=SelTreeNode; NodeInFront:=ParentNode.GetFirstChild; if NodeInFront<>nil then begin while NodeInFront.GetNextSibling<>nil do NodeInFront:=NodeInFront.GetNextSibling; end; end; end else begin // no node selected, add as last root node NodeInFront:=DefineTreeView.Items.GetLastNode; end; if (ParentNode<>nil) and (TDefineTemplate(ParentNode.Data).IsAutoGenerated) then begin MessageDlg('Invalid parent','Auto created nodes can not be edited,'#13 +'nor can they have non auto created child nodes.',mtInformation,[mbCancel] ,0); exit; end; if (ParentNode<>nil) and (not (TDefineTemplate(ParentNode.Data).Action in DefineActionBlocks)) then begin MessageDlg('Invalid parent node', 'Parent node can not contain child nodes.', mtInformation,[mbCancel],0); exit; end; NewName:=FindUniqueName; NewDescription:=NewName; NewVariable:=''; NewValue:=''; NewDefNode:=TDefineTemplate.Create(NewName,NewDescription,NewVariable, NewValue,Action); // add node to treeview if (NodeInFront<>nil) then // insert in front NewTreeNode:=DefineTreeView.Items.InsertObjectBehind( NodeInFront,NewName,NewDefNode) else // add as last child NewTreeNode:=DefineTreeView.Items.AddChildObject(ParentNode,NewName, NewDefNode); // add node to define tree if NodeInFront<>nil then NewDefNode.InsertBehind(TDefineTemplate(NodeInFront.Data)) else if ParentNode<>nil then TDefineTemplate(ParentNode.Data).AddChild(NewDefNode) else FDefineTree.Add(NewDefNode); SetNodeImages(NewTreeNode,true); DefineTreeView.Selected:=NewTreeNode; ShowSelectedValues; end; procedure TCodeToolsDefinesEditor.InsertTemplate(NewTemplate: TDefineTemplate); procedure AddChilds(ATreeNode: TTreeNode); var ADefNode, ChildDefNode: TDefineTemplate; ChildTreeNode: TTreeNode; begin if ATreeNode=nil then exit; ADefNode:=TDefineTemplate(ATreeNode.Data); ChildDefNode:=ADefNode.FirstChild; while ChildDefNode<>nil do begin ChildTreeNode:=DefineTreeView.Items.AddChildObject(ATreeNode, ChildDefNode.Name,ChildDefNode); AddChilds(ChildTreeNode); ChildDefNode:=ChildDefNode.Next; end; end; var SelTreeNode, NewTreeNode: TTreeNode; SelDefNode: TDefineTemplate; begin SaveSelectedValues; if NewTemplate=nil then exit; NewTemplate.RemoveFlags([dtfAutoGenerated]); FLastSelectedNode:=nil; SelTreeNode:=DefineTreeView.Selected; if SelTreeNode<>nil then begin // insert behind selected node SelDefNode:=TDefineTemplate(SelTreeNode.Data); // insert in TreeView NewTreeNode:=DefineTreeView.Items.InsertObjectBehind(SelTreeNode, NewTemplate.Name,NewTemplate); // insert in DefineTree NewTemplate.InsertBehind(SelDefNode); end else begin // add as last root node // add in TreeView NewTreeNode:=DefineTreeView.Items.AddObject(nil,NewTemplate.Name,NewTemplate); // add in DefineTree DefineTree.Add(NewTemplate); end; // add childs to TreeView AddChilds(NewTreeNode); // show and select SetNodeImages(NewTreeNode,true); NewTreeNode.Selected:=true; ShowSelectedValues; end; function TCodeToolsDefinesEditor.FindUniqueName: string; var i: integer; begin i:=1; while (DefineTree.FindDefineTemplateByName('NewNode'+IntToStr(i),false)<>nil) do inc(i); Result:='NewNode'+IntToStr(i); end; function TCodeToolsDefinesEditor.ConsistencyCheck: integer; function CheckNode(ATreeNode: TTreeNode): integer; var ADefNode, DummyDefNode: TDefineTemplate; begin if ATreeNode=nil then exit; ADefNode:=TDefineTemplate(ATreeNode.Data); //writeln(' CheckNode "',ATreeNode.Text,'" "',ADefNode.Name,'"'); if ADefNode=nil then begin Result:=-1; exit; end; if (ATreeNode.GetPrevSibling<>nil) and (TDefineTemplate(ATreeNode.GetPrevSibling.Data)<>ADefNode.Prior) then begin Result:=-2; exit; end; if (ATreeNode.GetNextSibling<>nil) and (TDefineTemplate(ATreeNode.GetNextSibling.Data)<>ADefNode.Next) then begin write(' ERROR: ',ATreeNode.GetNextSibling.Text,' '); if ADefNode.Next<>nil then write('ADefNode.Next=',ADefNode.Next.Name,' ') else write('ADefNode.Next=nil '); DummyDefNode:=TDefineTemplate(ATreeNode.GetNextSibling.Data); if DummyDefNode<>nil then writeln('ATreeNode.GetNextSibling.Next=',DummyDefNode.Name) else writeln('ATreeNode.GetNextSibling.Next=nil'); {writeln('============================================='); DefineTreeView.WriteDebugReport('TV ',true); writeln('============================================='); DefineTree.WriteDebugReport; writeln('=============================================');} Result:=-3; exit; end; if (ATreeNode.GetFirstChild<>nil) and (TDefineTemplate(ATreeNode.GetFirstChild.Data)<>ADefNode.FirstChild) then begin Result:=-4; exit; end; Result:=CheckNode(ATreeNode.GetFirstChild); if Result<0 then exit; Result:=CheckNode(ATreeNode.GetNextSibling); if Result<0 then exit; end; begin Result:=DefineTreeView.ConsistencyCheck; if Result<0 then begin dec(Result,100000); exit; end; Result:=DefineTree.ConsistencyCheck; if Result<0 then begin dec(Result,200000); exit; end; Result:=CheckNode(DefineTreeView.Items.GetFirstNode); if Result<0 then begin dec(Result,300000); exit; end; Result:=0; end; procedure TCodeToolsDefinesEditor.SetValuesEditable(AValue: boolean); begin SelectedItemGroupBox.Enabled:=true; TypeLabel.Enabled:=true; ProjectSpecificCheckBox.Enabled:=AValue; NameLabel.Enabled:=AValue; NameEdit.Enabled:=AValue; DescriptionLabel.Enabled:=AValue; DescriptionEdit.Enabled:=AValue; VariableLabel.Enabled:=AValue; VariableEdit.Enabled:=AValue; ValueAsTextSynEdit.ReadOnly:=not AValue; ValueAsFilePathsSynEdit.ReadOnly:=not AValue; MoveFilePathUpBitBtn.Enabled:=AValue; MoveFilePathDownBitBtn.Enabled:=AValue; DeleteFilePathBitBtn.Enabled:=AValue; InsertFilePathBitBtn.Enabled:=AValue; end; procedure TCodeToolsDefinesEditor.Assign(ACodeToolBoss: TCodeToolManager; Options: TCodeToolsOptions); begin FLastSelectedNode:=nil; FBoss:=ACodeToolBoss; FDefineTree.Assign(ACodeToolBoss.DefineTree); RebuildDefineTreeView; ShowSelectedValues; end; constructor TCodeToolsDefinesEditor.Create(TheOwner: TComponent); begin inherited Create(TheOwner); Position:=poScreenCenter; IDEDialogLayoutList.ApplyLayout(Self,500, 460); if LazarusResources.Find(ClassName)=nil then begin Caption:='CodeTools Defines Editor'; OnResize:=@FormResize; CreateComponents; end; FDefineTree:=TDefineTree.Create; FormResize(Self); end; destructor TCodeToolsDefinesEditor.Destroy; begin FDefineTree.Free; inherited Destroy; end; //============================================================================== initialization {$I codetoolsdefines.lrs} end.