{ $Id$ } { /*************************************************************************** packageeditor.pas ----------------- ***************************************************************************/ *************************************************************************** * * * 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: TPackageEditorForm is the form of a package editor. } unit PackageEditor; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Controls, StdCtrls, ComCtrls, Buttons, LResources, Graphics, LCLType, LCLProc, Menus, Dialogs, FileUtil, HelpIntfs, AVL_Tree, Laz_XMLCfg, LazIDEIntf, ProjectIntf, FormEditingIntf, IDEProcs, LazConf, LazarusIDEStrConsts, IDEOptionDefs, IDEDefs, IDEContextHelpEdit, CompilerOptions, CompilerOptionsDlg, ComponentReg, PackageDefs, PkgOptionsDlg, AddToPackageDlg, PkgVirtualUnitEditor, PackageSystem; type TOnCreatePkgMakefile = function(Sender: TObject; APackage: TLazPackage): TModalResult of object; TOnOpenFile = function(Sender: TObject; const Filename: string): TModalResult of object; TOnOpenPkgFile = function(Sender: TObject; PkgFile: TPkgFile): TModalResult of object; TOnOpenPackage = function(Sender: TObject; APackage: TLazPackage): TModalResult of object; TOnSavePackage = function(Sender: TObject; APackage: TLazPackage; SaveAs: boolean): TModalResult of object; TOnRevertPackage = function(Sender: TObject; APackage: TLazPackage): TModalResult of object; TOnPublishPackage = function(Sender: TObject; APackage: TLazPackage): TModalResult of object; TOnCompilePackage = function(Sender: TObject; APackage: TLazPackage; CompileClean, CompileRequired: boolean): TModalResult of object; TOnAddPkgToProject = function(Sender: TObject; APackage: TLazPackage; OnlyTestIfPossible: boolean): TModalResult of object; TOnInstallPackage = function(Sender: TObject; APackage: TLazPackage): TModalResult of object; TOnUninstallPackage = function(Sender: TObject; APackage: TLazPackage): TModalResult of object; TOnViewPackageSource = function(Sender: TObject; APackage: TLazPackage): TModalResult of object; TOnCreateNewPkgFile = function(Sender: TObject; Params: TAddToPkgResult): TModalResult of object; TOnDeleteAmbiguousFiles = function(Sender: TObject; APackage: TLazPackage; const Filename: string): TModalResult of object; TOnFreePkgEditor = procedure(APackage: TLazPackage) of object; { TPackageEditorLayout } TPackageEditorLayout = class public Filename: string; Rectangle: TRect; constructor Create; destructor Destroy; override; procedure LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string); procedure SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string); end; { TPackageEditorForm } TPackageEditorForm = class(TBasePackageEditor) // buttons SaveBitBtn: TBitBtn; CompileBitBtn: TBitBtn; AddBitBtn: TBitBtn; RemoveBitBtn: TBitBtn; InstallBitBtn: TBitBtn; OptionsBitBtn: TBitBtn; CompilerOptionsBitBtn: TBitBtn; MoreBitBtn: TBitBtn; HelpBitBtn: TBitBtn; // items FilesTreeView: TTreeView; // properties FilePropsGroupBox: TGroupBox; // file properties CallRegisterProcCheckBox: TCheckBox; AddToUsesPkgSectionCheckBox: TCheckBox; RegisteredPluginsGroupBox: TGroupBox; RegisteredListBox: TListBox; // dependency properties UseMinVersionCheckBox: TCheckBox; MinVersionEdit: TEdit; UseMaxVersionCheckBox: TCheckBox; MaxVersionEdit: TEdit; ApplyDependencyButton: TButton; // statusbar StatusBar: TStatusBar; // hidden components FilesPopupMenu: TPopupMenu; procedure AddBitBtnClick(Sender: TObject); procedure AddToUsesPkgSectionCheckBoxChange(Sender: TObject); procedure AddToProjectClick(Sender: TObject); procedure ApplyDependencyButtonClick(Sender: TObject); procedure CallRegisterProcCheckBoxChange(Sender: TObject); procedure ChangeFileTypeMenuItemClick(Sender: TObject); procedure CompileAllCleanClick(Sender: TObject); procedure CompileBitBtnClick(Sender: TObject); procedure CompileCleanClick(Sender: TObject); procedure CompilerOptionsBitBtnClick(Sender: TObject); procedure CreateMakefileClick(Sender: TObject); procedure FilePropsGroupBoxResize(Sender: TObject); procedure FilesPopupMenuPopup(Sender: TObject); procedure FilesTreeViewDblClick(Sender: TObject); procedure FilesTreeViewSelectionChanged(Sender: TObject); procedure FixFilesCaseMenuItemClick(Sender: TObject); procedure HelpBitBtnClick(Sender: TObject); procedure InstallBitBtnClick(Sender: TObject); procedure MaxVersionEditChange(Sender: TObject); procedure MinVersionEditChange(Sender: TObject); procedure MoreBitBtnClick(Sender: TObject); procedure MoveDependencyDownClick(Sender: TObject); procedure MoveDependencyUpClick(Sender: TObject); procedure MoveFileDownMenuItemClick(Sender: TObject); procedure MoveFileUpMenuItemClick(Sender: TObject); procedure SetDependencyFilenameMenuItemClick(Sender: TObject); procedure ClearDependencyFilenameMenuItemClick(Sender: TObject); procedure OpenFileMenuItemClick(Sender: TObject); procedure OptionsBitBtnClick(Sender: TObject); procedure PackageEditorFormClose(Sender: TObject; var CloseAction: TCloseAction); procedure PackageEditorFormCloseQuery(Sender: TObject; var CanClose: boolean); procedure PackageEditorFormResize(Sender: TObject); procedure PublishClick(Sender: TObject); procedure ReAddMenuItemClick(Sender: TObject); procedure RegisteredListBoxDrawItem(Control: TWinControl; Index: Integer; ARect: TRect; State: TOwnerDrawState); procedure RemoveBitBtnClick(Sender: TObject); procedure EditVirtualUnitMenuItemClick(Sender: TObject); procedure RevertClick(Sender: TObject); procedure SaveAsClick(Sender: TObject); procedure SaveBitBtnClick(Sender: TObject); procedure SortFilesMenuItemClick(Sender: TObject); procedure UninstallClick(Sender: TObject); procedure UseMaxVersionCheckBoxChange(Sender: TObject); procedure UseMinVersionCheckBoxChange(Sender: TObject); procedure ViewPkgSourceClick(Sender: TObject); private FLazPackage: TLazPackage; FilesNode: TTreeNode; RequiredPackagesNode: TTreeNode; RemovedFilesNode: TTreeNode; RemovedRequiredNode: TTreeNode; FPlugins: TStringList; procedure SetLazPackage(const AValue: TLazPackage); override; procedure SetupComponents; procedure UpdateAll; override; procedure UpdateTitle; procedure UpdateButtons; procedure UpdateFiles; procedure UpdateRequiredPkgs; procedure UpdateSelectedFile; procedure UpdateApplyDependencyButton; procedure UpdateStatusBar; function GetCurrentDependency(var Removed: boolean): TPkgDependency; function GetCurrentFile(var Removed: boolean): TPkgFile; function StoreCurrentTreeSelection: TStringList; procedure ApplyTreeSelection(ASelection: TStringList; FreeList: boolean); procedure ExtendUnitIncPathForNewUnit(const AnUnitFilename, AnIncludeFile: string); function CanBeAddedToProject: boolean; public constructor Create(TheOwner: TComponent); override; destructor Destroy; override; procedure DoCompile(CompileClean, CompileRequired: boolean); procedure DoFixFilesCase; procedure DoMoveCurrentFile(Offset: integer); procedure DoPublishProject; procedure DoEditVirtualUnit; procedure DoRevert; procedure DoSave(SaveAs: boolean); procedure DoSortFiles; procedure DoOpenPkgFile(PkgFile: TPkgFile); public property LazPackage: TLazPackage read FLazPackage write SetLazPackage; end; { TPackageEditors } TPackageEditors = class private FItems: TList; // list of TPackageEditorForm fLayouts: TAVLTree;// tree of TPackageEditorLayout sorted for filename FOnAddToProject: TOnAddPkgToProject; FOnCompilePackage: TOnCompilePackage; FOnCreateNewFile: TOnCreateNewPkgFile; FOnCreatePkgMakefile: TOnCreatePkgMakefile; FOnDeleteAmbiguousFiles: TOnDeleteAmbiguousFiles; FOnFreeEditor: TOnFreePkgEditor; FOnGetIDEFileInfo: TGetIDEFileStateEvent; FOnGetUnitRegisterInfo: TOnGetUnitRegisterInfo; FOnImExportCompilerOptions: TNotifyEvent; FOnInstallPackage: TOnInstallPackage; FOnOpenFile: TOnOpenFile; FOnOpenPackage: TOnOpenPackage; FOnOpenPkgFile: TOnOpenPkgFile; FOnPublishPackage: TOnPublishPackage; FOnRevertPackage: TOnRevertPackage; FOnSavePackage: TOnSavePackage; FOnUninstallPackage: TOnUninstallPackage; FOnViewPackageSource: TOnViewPackageSource; function GetEditors(Index: integer): TPackageEditorForm; procedure ApplyLayout(AnEditor: TPackageEditorForm); procedure SaveLayout(AnEditor: TPackageEditorForm); procedure LoadLayouts; function GetLayoutConfigFilename: string; public constructor Create; destructor Destroy; override; function Count: integer; procedure Clear; procedure SaveLayouts; procedure Remove(Editor: TPackageEditorForm); function IndexOfPackage(Pkg: TLazPackage): integer; function FindEditor(Pkg: TLazPackage): TPackageEditorForm; function OpenEditor(Pkg: TLazPackage): TPackageEditorForm; function OpenFile(Sender: TObject; const Filename: string): TModalResult; function OpenPkgFile(Sender: TObject; PkgFile: TPkgFile): TModalResult; function OpenDependency(Sender: TObject; Dependency: TPkgDependency): TModalResult; procedure DoFreeEditor(Pkg: TLazPackage); function CreateNewFile(Sender: TObject; Params: TAddToPkgResult): TModalResult; function SavePackage(APackage: TLazPackage; SaveAs: boolean): TModalResult; function RevertPackage(APackage: TLazPackage): TModalResult; function PublishPackage(APackage: TLazPackage): TModalResult; function CompilePackage(APackage: TLazPackage; CompileClean,CompileRequired: boolean): TModalResult; procedure UpdateAllEditors; function InstallPackage(APackage: TLazPackage): TModalResult; function UninstallPackage(APackage: TLazPackage): TModalResult; function ViewPkgSourcePackage(APackage: TLazPackage): TModalResult; function DeleteAmbiguousFiles(APackage: TLazPackage; const Filename: string): TModalResult; function AddToProject(APackage: TLazPackage; OnlyTestIfPossible: boolean): TModalResult; function CreateMakefile(APackage: TLazPackage): TModalResult; public property Editors[Index: integer]: TPackageEditorForm read GetEditors; property OnCreateNewFile: TOnCreateNewPkgFile read FOnCreateNewFile write FOnCreateNewFile; property OnOpenFile: TOnOpenFile read FOnOpenFile write FOnOpenFile; property OnOpenPkgFile: TOnOpenPkgFile read FOnOpenPkgFile write FOnOpenPkgFile; property OnOpenPackage: TOnOpenPackage read FOnOpenPackage write FOnOpenPackage; property OnGetIDEFileInfo: TGetIDEFileStateEvent read FOnGetIDEFileInfo write FOnGetIDEFileInfo; property OnGetUnitRegisterInfo: TOnGetUnitRegisterInfo read FOnGetUnitRegisterInfo write FOnGetUnitRegisterInfo; property OnFreeEditor: TOnFreePkgEditor read FOnFreeEditor write FOnFreeEditor; property OnSavePackage: TOnSavePackage read FOnSavePackage write FOnSavePackage; property OnRevertPackage: TOnRevertPackage read FOnRevertPackage write FOnRevertPackage; property OnPublishPackage: TOnPublishPackage read FOnPublishPackage write FOnPublishPackage; property OnCompilePackage: TOnCompilePackage read FOnCompilePackage write FOnCompilePackage; property OnInstallPackage: TOnInstallPackage read FOnInstallPackage write FOnInstallPackage; property OnUninstallPackage: TOnUninstallPackage read FOnUninstallPackage write FOnUninstallPackage; property OnViewPackageSource: TOnViewPackageSource read FOnViewPackageSource write FOnViewPackageSource; property OnDeleteAmbiguousFiles: TOnDeleteAmbiguousFiles read FOnDeleteAmbiguousFiles write FOnDeleteAmbiguousFiles; property OnImExportCompilerOptions: TNotifyEvent read FOnImExportCompilerOptions write FOnImExportCompilerOptions; property OnAddToProject: TOnAddPkgToProject read FOnAddToProject write FOnAddToProject; property OnCreateMakefile: TOnCreatePkgMakefile read FOnCreatePkgMakefile write FOnCreatePkgMakefile; end; var PackageEditors: TPackageEditors; implementation uses Math, IDEImagesIntf; var ImageIndexFiles: integer; ImageIndexRemovedFiles: integer; ImageIndexRequired: integer; ImageIndexRemovedRequired: integer; ImageIndexUnit: integer; ImageIndexRegisterUnit: integer; ImageIndexLFM: integer; ImageIndexLRS: integer; ImageIndexInclude: integer; ImageIndexText: integer; ImageIndexBinary: integer; ImageIndexConflict: integer; function CompareLayouts(Data1, Data2: Pointer): integer; var Layout1: TPackageEditorLayout; Layout2: TPackageEditorLayout; begin Layout1:=TPackageEditorLayout(Data1); Layout2:=TPackageEditorLayout(Data2); Result:=CompareFilenames(Layout1.Filename,Layout2.Filename); end; function CompareFilenameWithLayout(Key, Data: Pointer): integer; var Filename: String; Layout: TPackageEditorLayout; begin Filename:=String(Key); Layout:=TPackageEditorLayout(Data); Result:=CompareFilenames(Filename,Layout.Filename); end; { TPackageEditorForm } procedure TPackageEditorForm.PackageEditorFormResize(Sender: TObject); var x: Integer; y: Integer; w: Integer; h: Integer; y1: Integer; y2: Integer; begin x:=0; y:=0; w:=ClientWidth div 5; h:=SaveBitBtn.Height; y1:=y; y2:=y1+h; // first column of buttons SaveBitBtn.SetBounds(x,y1,w,h); CompileBitBtn.SetBounds(x,y2,w,h); inc(x,w); // second column of buttons AddBitBtn.SetBounds(x,y1,w,h); RemoveBitBtn.SetBounds(x,y2,w,h); inc(x,w); // third and forth column of buttons OptionsBitBtn.SetBounds(x,y1,w,h); CompilerOptionsBitBtn.SetBounds(x,y2,2*w,h); inc(x,w); InstallBitBtn.SetBounds(x,y1,w,h); inc(x,w); // fifth column of buttons HelpBitBtn.SetBounds(x,y1,ClientWidth-x,h); MoreBitBtn.SetBounds(x,y2,ClientWidth-x,h); FilePropsGroupBox.Height:=120; end; procedure TPackageEditorForm.PublishClick(Sender: TObject); begin DoPublishProject; end; procedure TPackageEditorForm.ReAddMenuItemClick(Sender: TObject); var PkgFile: TPkgFile; AFilename: String; Dependency: TPkgDependency; Removed: boolean; begin PkgFile:=GetCurrentFile(Removed); if (PkgFile<>nil) then begin if Removed then begin // re-add file AFilename:=PkgFile.Filename; if PkgFile.FileType=pftUnit then begin if not CheckAddingUnitFilename(LazPackage,d2ptUnit, PackageEditors.OnGetIDEFileInfo,AFilename) then exit; end else if PkgFile.FileType=pftVirtualUnit then begin if not CheckAddingUnitFilename(LazPackage,d2ptVirtualUnit, PackageEditors.OnGetIDEFileInfo,AFilename) then exit; end else begin if not CheckAddingUnitFilename(LazPackage,d2ptFile, PackageEditors.OnGetIDEFileInfo,AFilename) then exit; end; PkgFile.Filename:=AFilename; LazPackage.UnremovePkgFile(PkgFile); UpdateAll; end; end else begin Dependency:=GetCurrentDependency(Removed); if (Dependency<>nil) and (Removed) then begin // re-add dependency if not CheckAddingDependency(LazPackage,Dependency) then exit; LazPackage.RemoveRemovedDependency(Dependency); PackageGraph.AddDependencyToPackage(LazPackage,Dependency); end; end; end; procedure TPackageEditorForm.FilesPopupMenuPopup(Sender: TObject); var ItemCnt: Integer; CurDependency: TPkgDependency; Removed: boolean; CurFile: TPkgFile; Writable: Boolean; FileIndex: Integer; function AddPopupMenuItem(const ACaption: string; AnEvent: TNotifyEvent; EnabledFlag: boolean): TMenuItem; begin if FilesPopupMenu.Items.Count<=ItemCnt then begin Result:=TMenuItem.Create(Self); FilesPopupMenu.Items.Add(Result); end else begin Result:=FilesPopupMenu.Items[ItemCnt]; while Result.Count>0 do Result.Delete(Result.Count-1); end; Result.Caption:=ACaption; Result.OnClick:=AnEvent; Result.Enabled:=EnabledFlag; inc(ItemCnt); end; procedure AddFileTypeMenuItem; var FileTypeMenuItem: TMenuItem; CurPFT: TPkgFileType; NewMenuItem: TMenuItem; VirtualFileExists: Boolean; begin FileTypeMenuItem:=AddPopupMenuItem(lisAF2PFileType, nil, true); VirtualFileExists:=(CurFile.FileType=pftVirtualUnit) and FileExists(CurFile.Filename); for CurPFT:=Low(TPkgFileType) to High(TPkgFileType) do begin NewMenuItem:=TMenuItem.Create(Self); NewMenuItem.Caption:=GetPkgFileTypeLocalizedName(CurPFT); NewMenuItem.OnClick:=@ChangeFileTypeMenuItemClick; if CurPFT=CurFile.FileType then begin // menuitem to keep the current type NewMenuItem.Enabled:=true; NewMenuItem.Checked:=true; end else if VirtualFileExists then // a virtual unit that exists can be changed into anything NewMenuItem.Enabled:=true else if (not (CurPFT in PkgFileUnitTypes)) then // all other files can be changed into all non unit types NewMenuItem.Enabled:=true else if FilenameIsPascalUnit(CurFile.Filename) then // a pascal file can be changed into anything NewMenuItem.Enabled:=true else // default is to not allow NewMenuItem.Enabled:=false; FileTypeMenuItem.Add(NewMenuItem); end; end; begin ItemCnt:=0; CurDependency:=GetCurrentDependency(Removed); Writable:=(not LazPackage.ReadOnly); if CurDependency=nil then CurFile:=GetCurrentFile(Removed) else CurFile:=nil; if CurFile<>nil then begin FileIndex:=LazPackage.IndexOfPkgFile(CurFile); if not Removed then begin AddPopupMenuItem(lisOpenFile, @OpenFileMenuItemClick, true); AddPopupMenuItem(lisPckEditRemoveFile, @RemoveBitBtnClick, RemoveBitBtn.Enabled); AddPopupMenuItem('Move file up', @MoveFileUpMenuItemClick, (FileIndex>0) and Writable); AddPopupMenuItem('Move file down', @MoveFileDownMenuItemClick, (FileIndex1 then begin AddPopupMenuItem('Sort files', @SortFilesMenuItemClick, Writable); AddPopupMenuItem('Fix Files Case', @FixFilesCaseMenuItemClick, Writable); end; if CurDependency<>nil then begin if (not Removed) then begin AddPopupMenuItem(lisMenuOpenPackage, @OpenFileMenuItemClick, true); AddPopupMenuItem(lisPckEditRemoveDependency, @RemoveBitBtnClick, RemoveBitBtn.Enabled); AddPopupMenuItem(lisPckEditMoveDependencyUp, @MoveDependencyUpClick, (CurDependency.PrevRequiresDependency<>nil) and Writable); AddPopupMenuItem(lisPckEditMoveDependencyDown, @MoveDependencyDownClick, (CurDependency.NextRequiresDependency<>nil) and Writable); AddPopupMenuItem(lisPckEditSetDependencyDefaultFilename, @SetDependencyFilenameMenuItemClick, Writable and (CurDependency.RequiredPackage<>nil)); AddPopupMenuItem(lisPckEditClearDependencyDefaultFilename, @ClearDependencyFilenameMenuItemClick, Writable and (CurDependency.DefaultFilename<>'')); end else begin AddPopupMenuItem(lisMenuOpenPackage, @OpenFileMenuItemClick, true); AddPopupMenuItem(lisPckEditReAddDependency, @ReAddMenuItemClick, AddBitBtn.Enabled); end; end; if ItemCnt>0 then AddPopupMenuItem('-',nil,true); AddPopupMenuItem(lisPckEditAddToProject, @AddToProjectClick, CanBeAddedToProject); AddPopupMenuItem(lisPckEditInstall, @InstallBitBtnClick, InstallBitBtn.Enabled ); AddPopupMenuItem(lisPckEditUninstall, @UninstallClick, (LazPackage.Installed<>pitNope) or (LazPackage.AutoInstall<>pitNope)); AddPopupMenuItem('-',nil,true); AddPopupMenuItem(lisMenuSave, @SaveBitBtnClick, SaveBitBtn.Enabled); AddPopupMenuItem(lisMenuSaveAs, @SaveAsClick, not LazPackage.AutoCreated); AddPopupMenuItem(lisMenuRevert, @RevertClick, (not LazPackage.AutoCreated) and FileExists(LazPackage.Filename)); AddPopupMenuItem(lisPkgEditPublishPackage, @PublishClick, (not LazPackage.AutoCreated) and (LazPackage.HasDirectory)); AddPopupMenuItem('-',nil,true); AddPopupMenuItem(lisPckEditCompile, @CompileBitBtnClick, CompileBitBtn.Enabled ); AddPopupMenuItem(lisPckEditRecompileClean, @CompileCleanClick, CompileBitBtn.Enabled); AddPopupMenuItem(lisPckEditRecompileAllRequired, @CompileAllCleanClick, CompileBitBtn.Enabled); AddPopupMenuItem(lisPckEditCreateMakefile, @CreateMakefileClick, CompileBitBtn.Enabled); AddPopupMenuItem('-',nil,true); AddPopupMenuItem(lisCodeTemplAdd, @AddBitBtnClick, AddBitBtn.Enabled); AddPopupMenuItem(lisExtToolRemove, @RemoveBitBtnClick, RemoveBitBtn.Enabled); AddPopupMenuItem('-',nil,true); AddPopupMenuItem(lisPckEditGeneralOptions, @OptionsBitBtnClick, OptionsBitBtn.Enabled); AddPopupMenuItem(dlgCompilerOptions, @CompilerOptionsBitBtnClick, CompilerOptionsBitBtn.Enabled); AddPopupMenuItem(lisPckEditViewPackgeSource, @ViewPkgSourceClick,true); // remove unneeded menu items while FilesPopupMenu.Items.Count>ItemCnt do FilesPopupMenu.Items.Delete(FilesPopupMenu.Items.Count-1); end; procedure TPackageEditorForm.FilesTreeViewDblClick(Sender: TObject); begin OpenFileMenuItemClick(Self); end; procedure TPackageEditorForm.FilesTreeViewSelectionChanged(Sender: TObject); begin UpdateSelectedFile; UpdateButtons; end; procedure TPackageEditorForm.HelpBitBtnClick(Sender: TObject); begin ShowContextHelpForIDE(HelpBitBtn); end; procedure TPackageEditorForm.InstallBitBtnClick(Sender: TObject); begin PackageEditors.InstallPackage(LazPackage); end; procedure TPackageEditorForm.MaxVersionEditChange(Sender: TObject); begin UpdateApplyDependencyButton; end; procedure TPackageEditorForm.MinVersionEditChange(Sender: TObject); begin UpdateApplyDependencyButton; end; procedure TPackageEditorForm.MoreBitBtnClick(Sender: TObject); var p: TPoint; begin p:=MoreBitBtn.ClientToScreen(Point(0,MoreBitBtn.Height)); FilesPopupMenu.Popup(p.x,p.y); end; procedure TPackageEditorForm.MoveDependencyUpClick(Sender: TObject); var CurDependency: TPkgDependency; Removed: boolean; OldSelection: TStringList; begin CurDependency:=GetCurrentDependency(Removed); if (CurDependency=nil) or Removed then exit; FilesTreeView.BeginUpdate; OldSelection:=StoreCurrentTreeSelection; PackageGraph.MoveRequiredDependencyUp(CurDependency); ApplyTreeSelection(OldSelection,true); FilesTreeView.EndUpdate; end; procedure TPackageEditorForm.MoveDependencyDownClick(Sender: TObject); var CurDependency: TPkgDependency; Removed: boolean; OldSelection: TStringList; begin CurDependency:=GetCurrentDependency(Removed); if (CurDependency=nil) or Removed then exit; FilesTreeView.BeginUpdate; OldSelection:=StoreCurrentTreeSelection; PackageGraph.MoveRequiredDependencyDown(CurDependency); ApplyTreeSelection(OldSelection,true); FilesTreeView.EndUpdate; end; procedure TPackageEditorForm.MoveFileUpMenuItemClick(Sender: TObject); begin DoMoveCurrentFile(-1); end; procedure TPackageEditorForm.SetDependencyFilenameMenuItemClick(Sender: TObject ); var Removed: boolean; CurDependency: TPkgDependency; NewFilename: String; begin CurDependency:=GetCurrentDependency(Removed); if (CurDependency=nil) or Removed then exit; if LazPackage.ReadOnly then exit; if CurDependency.RequiredPackage=nil then exit; NewFilename:=CurDependency.RequiredPackage.Filename; if NewFilename=CurDependency.DefaultFilename then exit; CurDependency.DefaultFilename:=NewFilename; LazPackage.Modified:=true; UpdateRequiredPkgs; UpdateButtons; end; procedure TPackageEditorForm.ClearDependencyFilenameMenuItemClick( Sender: TObject); var Removed: boolean; CurDependency: TPkgDependency; begin CurDependency:=GetCurrentDependency(Removed); if (CurDependency=nil) or Removed then exit; if LazPackage.ReadOnly then exit; if CurDependency.RequiredPackage=nil then exit; if CurDependency.DefaultFilename='' then exit; CurDependency.DefaultFilename:=''; LazPackage.Modified:=true; UpdateRequiredPkgs; UpdateButtons; end; procedure TPackageEditorForm.MoveFileDownMenuItemClick(Sender: TObject); begin DoMoveCurrentFile(1); end; procedure TPackageEditorForm.OpenFileMenuItemClick(Sender: TObject); var CurNode: TTreeNode; NodeIndex: Integer; CurFile: TPkgFile; CurDependency: TPkgDependency; begin CurNode:=FilesTreeView.Selected; if CurNode=nil then exit; NodeIndex:=CurNode.Index; if CurNode.Parent<>nil then begin if CurNode.Parent=FilesNode then begin CurFile:=LazPackage.Files[NodeIndex]; DoOpenPkgFile(CurFile); end else if CurNode.Parent=RequiredPackagesNode then begin CurDependency:=LazPackage.RequiredDepByIndex(NodeIndex); PackageEditors.OpenDependency(Self,CurDependency); end else if CurNode.Parent=RemovedFilesNode then begin CurFile:=LazPackage.RemovedFiles[NodeIndex]; DoOpenPkgFile(CurFile); end else if CurNode.Parent=RemovedRequiredNode then begin CurDependency:=LazPackage.RemovedDepByIndex(NodeIndex); PackageEditors.OpenDependency(Self,CurDependency); end; end; end; procedure TPackageEditorForm.OptionsBitBtnClick(Sender: TObject); begin ShowPackageOptionsDlg(LazPackage); UpdateButtons; UpdateTitle; UpdateStatusBar; end; procedure TPackageEditorForm.PackageEditorFormClose(Sender: TObject; var CloseAction: TCloseAction); begin if LazPackage=nil then exit; PackageEditors.SaveLayout(Self); end; procedure TPackageEditorForm.PackageEditorFormCloseQuery(Sender: TObject; var CanClose: boolean); var MsgResult: Integer; begin if (LazPackage=nil) or (lpfDestroying in LazPackage.Flags) or (LazPackage.ReadOnly) or (not LazPackage.Modified) then exit; MsgResult:=MessageDlg(lisPckEditSaveChanges, Format(lisPckEditPackageHasChangedSavePackage, ['"', LazPackage.IDAsString, '"', #13]), mtConfirmation,[mbYes,mbNo,mbAbort],0); if MsgResult=mrYes then begin MsgResult:=PackageEditors.SavePackage(LazPackage,false); end; if MsgResult=mrAbort then CanClose:=false; end; procedure TPackageEditorForm.RegisteredListBoxDrawItem(Control: TWinControl; Index: Integer; ARect: TRect; State: TOwnerDrawState); var CurComponent: TPkgComponent; CurStr: string; CurObject: TObject; TxtH: Integer; CurIcon: TBitmap; IconWidth: Integer; IconHeight: Integer; CurRect: TRect; begin //DebugLn('TPackageEditorForm.RegisteredListBoxDrawItem START'); if LazPackage=nil then exit; if (Index<0) or (Index>=FPlugins.Count) then exit; CurObject:=FPlugins.Objects[Index]; if CurObject is TPkgComponent then begin // draw registered component CurComponent:=TPkgComponent(CurObject); with RegisteredListBox.Canvas do begin CurStr:=Format(lisPckEditPage, [CurComponent.ComponentClass.ClassName, CurComponent.Page.PageName]); TxtH:=TextHeight(CurStr); CurRect:=ARect; inc(CurRect.Left,25); FillRect(CurRect); Brush.Color:=clLtGray; CurRect:=ARect; CurRect.Right:=ARect.Left+25; FillRect(CurRect); CurIcon:=CurComponent.Icon; //DebugLn('TPackageEditorForm.RegisteredListBoxDrawItem ',DbgSName(CurIcon),' ',CurComponent.ComponentClass.ClassName); if CurIcon<>nil then begin IconWidth:=CurIcon.Width; IconHeight:=CurIcon.Height; Draw(ARect.Left+(25-IconWidth) div 2, ARect.Top+(ARect.Bottom-ARect.Top-IconHeight) div 2, CurIcon); end; TextOut(ARect.Left+25, ARect.Top+(ARect.Bottom-ARect.Top-TxtH) div 2, CurStr); end; end; end; procedure TPackageEditorForm.RemoveBitBtnClick(Sender: TObject); var ANode: TTreeNode; NodeIndex: Integer; CurFile: TPkgFile; CurDependency: TPkgDependency; begin ANode:=FilesTreeView.Selected; if (ANode=nil) or LazPackage.ReadOnly then begin UpdateButtons; exit; end; NodeIndex:=ANode.Index; if ANode.Parent=FilesNode then begin // get current package file CurFile:=LazPackage.Files[NodeIndex]; if CurFile<>nil then begin // confirm deletion if MessageDlg(lisPckEditRemoveFile2, Format(lisPckEditRemoveFileFromPackage, ['"', CurFile.Filename, '"', #13, '"', LazPackage.IDAsString, '"']), mtConfirmation,[mbYes,mbNo],0)=mrNo then exit; LazPackage.RemoveFile(CurFile); end; UpdateAll; end else if ANode.Parent=RequiredPackagesNode then begin // get current dependency CurDependency:=LazPackage.RequiredDepByIndex(NodeIndex); if CurDependency<>nil then begin // confirm deletion if MessageDlg(lisPckEditRemoveDependency2, Format(lisPckEditRemoveDependencyFromPackage, ['"', CurDependency.AsString, '"', #13, '"', LazPackage.IDAsString, '"']), mtConfirmation,[mbYes,mbNo],0)=mrNo then exit; PackageGraph.RemoveDependencyFromPackage(LazPackage,CurDependency,true); end; end; end; procedure TPackageEditorForm.EditVirtualUnitMenuItemClick(Sender: TObject); begin DoEditVirtualUnit; end; procedure TPackageEditorForm.RevertClick(Sender: TObject); begin DoRevert; end; procedure TPackageEditorForm.SaveBitBtnClick(Sender: TObject); begin DoSave(false); end; procedure TPackageEditorForm.SaveAsClick(Sender: TObject); begin DoSave(true); end; procedure TPackageEditorForm.SortFilesMenuItemClick(Sender: TObject); begin DoSortFiles; end; procedure TPackageEditorForm.FixFilesCaseMenuItemClick(Sender: TObject); begin DoFixFilesCase; end; procedure TPackageEditorForm.UninstallClick(Sender: TObject); begin PackageEditors.UninstallPackage(LazPackage); end; procedure TPackageEditorForm.ViewPkgSourceClick(Sender: TObject); begin PackageEditors.ViewPkgSourcePackage(LazPackage); end; procedure TPackageEditorForm.UseMaxVersionCheckBoxChange(Sender: TObject); begin MaxVersionEdit.Enabled:=UseMaxVersionCheckBox.Checked; UpdateApplyDependencyButton; end; procedure TPackageEditorForm.UseMinVersionCheckBoxChange(Sender: TObject); begin MinVersionEdit.Enabled:=UseMinVersionCheckBox.Checked; UpdateApplyDependencyButton; end; procedure TPackageEditorForm.FilePropsGroupBoxResize(Sender: TObject); var y: Integer; x: Integer; w: Integer; begin // components for files w:=(ClientWidth-15) div 2; with CallRegisterProcCheckBox do SetBounds(3,0,w,Height); x:=3+w+9; with AddToUsesPkgSectionCheckBox do SetBounds(x,0,w,Height); y:=CallRegisterProcCheckBox.Top+CallRegisterProcCheckBox.Height+3; with RegisteredPluginsGroupBox do SetBounds(0,y,Parent.ClientWidth,Parent.ClientHeight-y); // components for dependencies x:=5; y:=3; with UseMinVersionCheckBox do SetBounds(x,y,150,MinVersionEdit.Height); inc(x,UseMinVersionCheckBox.Width+5); with MinVersionEdit do SetBounds(x,y,120,Height); x:=5; inc(y,MinVersionEdit.Height+5); with UseMaxVersionCheckBox do SetBounds(x,y,UseMinVersionCheckBox.Width,MaxVersionEdit.Height); inc(x,UseMaxVersionCheckBox.Width+5); with MaxVersionEdit do SetBounds(x,y,MinVersionEdit.Width,Height); inc(y,MaxVersionEdit.Height+10); x:=5; with ApplyDependencyButton do SetBounds(x,y,150,Height); end; procedure TPackageEditorForm.AddBitBtnClick(Sender: TObject); procedure AddUnit(AddParams: TAddToPkgResult); var NewLFMFilename: String; NewLRSFilename: String; begin NewLFMFilename:=''; NewLRSFilename:=''; // add lfm file if AddParams.AutoAddLFMFile then begin NewLFMFilename:=ChangeFileExt(AddParams.UnitFilename,'.lfm'); if FileExists(NewLFMFilename) and (LazPackage.FindPkgFile(NewLFMFilename,false,true,false)=nil) then LazPackage.AddFile(NewLFMFilename,'',pftLFM,[],cpNormal) else NewLFMFilename:=''; end; // add lrs file if AddParams.AutoAddLRSFile then begin NewLRSFilename:=ChangeFileExt(AddParams.UnitFilename,'.lrs'); if FileExists(NewLRSFilename) and (LazPackage.FindPkgFile(NewLRSFilename,false,true,false)=nil) then LazPackage.AddFile(NewLRSFilename,'',pftLRS,[],cpNormal) else NewLRSFilename:=''; end; ExtendUnitIncPathForNewUnit(AddParams.UnitFilename,NewLRSFilename); // add unit file with AddParams do LazPackage.AddFile(UnitFilename,UnitName,FileType,PkgFileFlags,cpNormal); PackageEditors.DeleteAmbiguousFiles(LazPackage,AddParams.UnitFilename); UpdateAll; end; procedure AddVirtualUnit(AddParams: TAddToPkgResult); begin with AddParams do LazPackage.AddFile(UnitFilename,UnitName,FileType,PkgFileFlags,cpNormal); PackageEditors.DeleteAmbiguousFiles(LazPackage,AddParams.UnitFilename); UpdateAll; end; procedure AddNewComponent(AddParams: TAddToPkgResult); begin ExtendUnitIncPathForNewUnit(AddParams.UnitFilename,''); // add file with AddParams do LazPackage.AddFile(UnitFilename,UnitName,FileType,PkgFileFlags,cpNormal); // add dependency if AddParams.Dependency<>nil then begin PackageGraph.AddDependencyToPackage(LazPackage,AddParams.Dependency); end; // open file in editor PackageEditors.CreateNewFile(Self,AddParams); UpdateAll; end; procedure AddRequiredPkg(AddParams: TAddToPkgResult); begin // add dependency PackageGraph.AddDependencyToPackage(LazPackage,AddParams.Dependency); end; procedure AddFile(AddParams: TAddToPkgResult); begin // add file with AddParams do LazPackage.AddFile(UnitFilename,UnitName,FileType,PkgFileFlags,cpNormal); UpdateAll; end; procedure AddNewFile(AddParams: TAddToPkgResult); var NewFilename: String; DummyResult: TModalResult; NewFileType: TPkgFileType; NewPkgFileFlags: TPkgFileFlags; Desc: TProjectFileDescriptor; NewUnitName: String; HasRegisterProc: Boolean; begin // create new file if AddParams.NewItem is TNewItemProjectFile then begin // create new file Desc:=TNewItemProjectFile(AddParams.NewItem).Descriptor; NewFilename:=''; DummyResult:=LazarusIDE.DoNewFile(Desc,NewFilename,'', [nfOpenInEditor,nfCreateDefaultSrc,nfIsNotPartOfProject],LazPackage); if DummyResult=mrOk then begin // success // -> now add it to package NewUnitName:=''; NewFileType:=FileNameToPkgFileType(NewFilename); NewPkgFileFlags:=[]; if (NewFileType in PkgFileUnitTypes) then begin Include(NewPkgFileFlags,pffAddToPkgUsesSection); NewUnitName:=ExtractFilenameOnly(NewFilename); if Assigned(PackageEditors.OnGetUnitRegisterInfo) then begin HasRegisterProc:=false; PackageEditors.OnGetUnitRegisterInfo(Self,NewFilename, NewUnitName,HasRegisterProc); if HasRegisterProc then Include(NewPkgFileFlags,pffHasRegisterProc); end; end; LazPackage.AddFile(NewFilename,NewUnitName,NewFileType,NewPkgFileFlags, cpNormal); UpdateAll; end; end; end; var AddParams: TAddToPkgResult; OldParams: TAddToPkgResult; begin if LazPackage.ReadOnly then begin UpdateButtons; exit; end; if ShowAddToPackageDlg(LazPackage,AddParams,PackageEditors.OnGetIDEFileInfo, PackageEditors.OnGetUnitRegisterInfo) <>mrOk then exit; PackageGraph.BeginUpdate(false); while AddParams<>nil do begin case AddParams.AddType of d2ptUnit: AddUnit(AddParams); d2ptVirtualUnit: AddVirtualUnit(AddParams); d2ptNewComponent: AddNewComponent(AddParams); d2ptRequiredPkg: AddRequiredPkg(AddParams); d2ptFile: AddFile(AddParams); d2ptNewFile: AddNewFile(AddParams); end; OldParams:=AddParams; AddParams:=AddParams.Next; OldParams.Next:=nil; OldParams.Free; end; AddParams.Free; LazPackage.Modified:=true; PackageGraph.EndUpdate; end; procedure TPackageEditorForm.AddToUsesPkgSectionCheckBoxChange(Sender: TObject); var CurFile: TPkgFile; Removed: boolean; begin if LazPackage=nil then exit; CurFile:=GetCurrentFile(Removed); if (CurFile=nil) then exit; if CurFile.AddToUsesPkgSection=AddToUsesPkgSectionCheckBox.Checked then exit; CurFile.AddToUsesPkgSection:=AddToUsesPkgSectionCheckBox.Checked; LazPackage.Modified:=not Removed; UpdateAll; end; procedure TPackageEditorForm.AddToProjectClick(Sender: TObject); begin if LazPackage=nil then exit; PackageEditors.AddToProject(LazPackage,false); end; procedure TPackageEditorForm.ApplyDependencyButtonClick(Sender: TObject); var CurDependency: TPkgDependency; Removed: boolean; NewDependency: TPkgDependency; begin CurDependency:=GetCurrentDependency(Removed); if (CurDependency=nil) or Removed then exit; NewDependency:=TPkgDependency.Create; try NewDependency.Assign(CurDependency); // read minimum version if UseMinVersionCheckBox.Checked then begin NewDependency.Flags:=NewDependency.Flags+[pdfMinVersion]; if not NewDependency.MinVersion.ReadString(MinVersionEdit.Text) then begin MessageDlg(lisPckEditInvalidMinimumVersion, Format(lisPckEditTheMinimumVersionIsNotAValidPackageVersion, ['"', MinVersionEdit.Text, '"', #13]), mtError,[mbCancel],0); exit; end; end else begin NewDependency.Flags:=NewDependency.Flags-[pdfMinVersion]; end; // read maximum version if UseMaxVersionCheckBox.Checked then begin NewDependency.Flags:=NewDependency.Flags+[pdfMaxVersion]; if not NewDependency.MaxVersion.ReadString(MaxVersionEdit.Text) then begin MessageDlg(lisPckEditInvalidMaximumVersion, Format(lisPckEditTheMaximumVersionIsNotAValidPackageVersion, ['"', MaxVersionEdit.Text, '"', #13]), mtError,[mbCancel],0); exit; end; end else begin NewDependency.Flags:=NewDependency.Flags-[pdfMaxVersion]; end; PackageGraph.ChangeDependency(CurDependency,NewDependency); finally NewDependency.Free; end; end; procedure TPackageEditorForm.CallRegisterProcCheckBoxChange(Sender: TObject); var CurFile: TPkgFile; Removed: boolean; begin if LazPackage=nil then exit; CurFile:=GetCurrentFile(Removed); if (CurFile=nil) then exit; if CurFile.HasRegisterProc=CallRegisterProcCheckBox.Checked then exit; CurFile.HasRegisterProc:=CallRegisterProcCheckBox.Checked; LazPackage.Modified:=not Removed; UpdateAll; end; procedure TPackageEditorForm.ChangeFileTypeMenuItemClick(Sender: TObject); var i: Integer; CurItem: TMenuItem; CurPFT: TPkgFileType; Removed: boolean; CurFile: TPkgFile; begin CurItem:=TMenuItem(Sender); i:=CurItem.Parent.IndexOf(CurItem); if i<0 then exit; CurFile:=GetCurrentFile(Removed); if CurFile=nil then exit; for CurPFT:=Low(TPkgFileType) to High(TPkgFileType) do begin if CurItem.Caption=GetPkgFileTypeLocalizedName(CurPFT) then begin if (not FilenameIsPascalUnit(CurFile.Filename)) and (CurPFT in [pftUnit,pftVirtualUnit]) then exit; if CurFile.FileType<>CurPFT then begin CurFile.FileType:=CurPFT; LazPackage.Modified:=true; UpdateAll; end; exit; end; end; end; procedure TPackageEditorForm.CompileAllCleanClick(Sender: TObject); begin if MessageDlg(lisPckEditCompileEverything, lisPckEditReCompileThisAndAllRequiredPackages, mtConfirmation,[mbYes,mbNo],0)<>mrYes then exit; DoCompile(true,true); end; procedure TPackageEditorForm.CompileCleanClick(Sender: TObject); begin DoCompile(true,false); end; procedure TPackageEditorForm.CompileBitBtnClick(Sender: TObject); begin DoCompile(false,false); end; procedure TPackageEditorForm.CompilerOptionsBitBtnClick(Sender: TObject); var CompilerOptsDlg: TfrmCompilerOptions; begin CompilerOptsDlg:=TfrmCompilerOptions.Create(Self); CompilerOptsDlg.CompilerOpts:=LazPackage.CompilerOptions; CompilerOptsDlg.OnImExportCompilerOptions:= PackageEditors.OnImExportCompilerOptions; with CompilerOptsDlg do begin GetCompilerOptions; Caption:=Format(lisPckEditCompilerOptionsForPackage,[LazPackage.IDAsString]); ReadOnly:=LazPackage.ReadOnly; if ShowModal=mrOk then LazPackage.DefineTemplates.AllChanged; Free; end; UpdateTitle; UpdateButtons; UpdateStatusBar; end; procedure TPackageEditorForm.CreateMakefileClick(Sender: TObject); begin PackageEditors.CreateMakefile(LazPackage); end; procedure TPackageEditorForm.SetLazPackage(const AValue: TLazPackage); begin if FLazPackage=AValue then exit; if FLazPackage<>nil then FLazPackage.Editor:=nil; FLazPackage:=AValue; if FLazPackage=nil then exit; FLazPackage.Editor:=Self; PackageEditors.ApplyLayout(Self); // update components UpdateAll; // show files FilesNode.Expanded:=true; end; procedure TPackageEditorForm.SetupComponents; procedure LoadBitBtnGlyph(ABitBtn: TBitBtn; const ResName: string); begin ABitBtn.Glyph.LoadFromLazarusResource(ResName); end; begin ImageIndexFiles := IDEImages.LoadImage(16, 'pkg_files'); ImageIndexRemovedFiles := IDEImages.LoadImage(16, 'pkg_removedfiles'); ImageIndexRequired := IDEImages.LoadImage(16, 'pkg_required'); ImageIndexRemovedRequired := IDEImages.LoadImage(16, 'pkg_removedrequired'); ImageIndexUnit := IDEImages.LoadImage(16, 'pkg_unit'); ImageIndexRegisterUnit := IDEImages.LoadImage(16, 'pkg_registerunit'); ImageIndexLFM := IDEImages.LoadImage(16, 'pkg_lfm'); ImageIndexLRS := IDEImages.LoadImage(16, 'pkg_lrs'); ImageIndexInclude := IDEImages.LoadImage(16, 'pkg_include'); ImageIndexText := IDEImages.LoadImage(16, 'pkg_text'); ImageIndexBinary := IDEImages.LoadImage(16, 'pkg_binary'); ImageIndexConflict := IDEImages.LoadImage(16, 'pkg_conflict'); SaveBitBtn:=TBitBtn.Create(Self); with SaveBitBtn do begin Name:='SaveBitBtn'; Parent:=Self; Caption:=lisMenuSave; OnClick:=@SaveBitBtnClick; Hint:=lisPckEditSavePackage; ShowHint:=true; end; CompileBitBtn:=TBitBtn.Create(Self); with CompileBitBtn do begin Name:='CompileBitBtn'; Parent:=Self; Caption:=lisPckEditCompile; OnClick:=@CompileBitBtnClick; Hint:=lisPckEditCompilePackage; ShowHint:=true; end; AddBitBtn:=TBitBtn.Create(Self); with AddBitBtn do begin Name:='AddBitBtn'; Parent:=Self; Caption:=lisCodeTemplAdd; OnClick:=@AddBitBtnClick; Hint:=lisPckEditAddAnItem; ShowHint:=true; end; RemoveBitBtn:=TBitBtn.Create(Self); with RemoveBitBtn do begin Name:='RemoveBitBtn'; Parent:=Self; Caption:=lisExtToolRemove; OnClick:=@RemoveBitBtnClick; Hint:=lisPckEditRemoveSelectedItem; ShowHint:=true; end; InstallBitBtn:=TBitBtn.Create(Self); with InstallBitBtn do begin Name:='InstallBitBtn'; Parent:=Self; Caption:=lisPckEditInstall; OnClick:=@InstallBitBtnClick; Hint:=lisPckEditInstallPackageInTheIDE; ShowHint:=true; end; OptionsBitBtn:=TBitBtn.Create(Self); with OptionsBitBtn do begin Name:='OptionsBitBtn'; Parent:=Self; Caption:=dlgFROpts; OnClick:=@OptionsBitBtnClick; Hint:=lisPckEditEditGeneralOptions; ShowHint:=true; end; CompilerOptionsBitBtn:=TBitBtn.Create(Self); with CompilerOptionsBitBtn do begin Name:='CompilerOptionsBitBtn'; Parent:=Self; Caption:=lisPckEditCompOpts; OnClick:=@CompilerOptionsBitBtnClick; Hint:=lisPckEditEditOptionsToCompilePackage; ShowHint:=true; end; HelpBitBtn:=TBitBtn.Create(Self); with HelpBitBtn do begin Name:='HelpBitBtn'; Parent:=Self; Caption:=lisPckEditHelp; OnClick:=@HelpBitBtnClick; Hint:=lisPkgEdThereAreMoreFunctionsInThePopupmenu; ShowHint:=true; end; MoreBitBtn:=TBitBtn.Create(Self); with MoreBitBtn do begin Name:='MoreBitBtn'; Parent:=Self; Caption:=lisPckEditMore; Enabled:=true; OnClick:=@MoreBitBtnClick; Hint:=lisPkgEdThereAreMoreFunctionsInThePopupmenu; ShowHint:=true; end; FilesPopupMenu:=TPopupMenu.Create(Self); with FilesPopupMenu do begin Name:='FilesPopupMenu'; OnPopup:=@FilesPopupMenuPopup; end; FilesTreeView:=TTreeView.Create(Self); with FilesTreeView do begin Name:='FilesTreeView'; Parent:=Self; BeginUpdate; Images := IDEImages.Images_16; FilesNode:=Items.Add(nil, dlgEnvFiles); FilesNode.ImageIndex:=ImageIndexFiles; FilesNode.SelectedIndex:=FilesNode.ImageIndex; RequiredPackagesNode:=Items.Add(nil, lisPckEditRequiredPackages); RequiredPackagesNode.ImageIndex:=ImageIndexRequired; RequiredPackagesNode.SelectedIndex:=RequiredPackagesNode.ImageIndex; EndUpdate; PopupMenu:=FilesPopupMenu; OnSelectionChanged:=@FilesTreeViewSelectionChanged; Options:=Options+[tvoRightClickSelect]; OnDblClick:=@FilesTreeViewDblClick; Anchors:=[akLeft,akRight,akTop,akBottom]; end; FilePropsGroupBox:=TGroupBox.Create(Self); with FilePropsGroupBox do begin Name:='FilePropsGroupBox'; Parent:=Self; Caption:=lisPckEditFileProperties; OnResize:=@FilePropsGroupBoxResize; Anchors:=[akLeft,akRight,akBottom]; end; CallRegisterProcCheckBox:=TCheckBox.Create(Self); with CallRegisterProcCheckBox do begin Name:='CallRegisterProcCheckBox'; Parent:=FilePropsGroupBox; Caption:=lisPckEditRegisterUnit; UseOnChange:=true; OnChange:=@CallRegisterProcCheckBoxChange; Hint:=Format(lisPckEditCallRegisterProcedureOfSelectedUnit, ['"', '"']); ShowHint:=true; end; AddToUsesPkgSectionCheckBox:=TCheckBox.Create(Self); with AddToUsesPkgSectionCheckBox do begin Name:='AddToUsesPkgSectionCheckBox'; Caption:=lisPkgMangUseUnit; UseOnChange:=true; OnChange:=@AddToUsesPkgSectionCheckBoxChange; Hint:=lisPkgMangAddUnitToUsesClauseOfPackageDisableThisOnlyForUnit; ShowHint:=true; Parent:=FilePropsGroupBox; end; RegisteredPluginsGroupBox:=TGroupBox.Create(Self); with RegisteredPluginsGroupBox do begin Name:='RegisteredPluginsGroupBox'; Caption:=lisPckEditRegisteredPlugins; Parent:=FilePropsGroupBox; end; RegisteredListBox:=TListBox.Create(Self); with RegisteredListBox do begin Name:='RegisteredListBox'; Align:=alClient; ItemHeight:=ComponentPaletteImageHeight; OnDrawItem:=@RegisteredListBoxDrawItem; Style:= lbOwnerDrawFixed; Parent:=RegisteredPluginsGroupBox; //DebugLn('TPackageEditorForm.SetupComponents AAAAAAAAAA'); end; UseMinVersionCheckBox:=TCheckBox.Create(Self); with UseMinVersionCheckBox do begin Name:='UseMinVersionCheckBox'; Caption:=lisPckEditMinimumVersion; UseOnChange:=true; OnChange:=@UseMinVersionCheckBoxChange; Parent:=FilePropsGroupBox; end; MinVersionEdit:=TEdit.Create(Self); with MinVersionEdit do begin Name:='MinVersionEdit'; Text:=''; OnChange:=@MinVersionEditChange; Parent:=FilePropsGroupBox; end; UseMaxVersionCheckBox:=TCheckBox.Create(Self); with UseMaxVersionCheckBox do begin Name:='UseMaxVersionCheckBox'; Caption:=lisPckEditMaximumVersion; UseOnChange:=true; OnChange:=@UseMaxVersionCheckBoxChange; Parent:=FilePropsGroupBox; end; MaxVersionEdit:=TEdit.Create(Self); with MaxVersionEdit do begin Name:='MaxVersionEdit'; Parent:=FilePropsGroupBox; Text:=''; OnChange:=@MaxVersionEditChange; end; ApplyDependencyButton:=TButton.Create(Self); with ApplyDependencyButton do begin Name:='ApplyDependencyButton'; Parent:=FilePropsGroupBox; Caption:=lisPckEditApplyChanges; OnClick:=@ApplyDependencyButtonClick; end; StatusBar:=TStatusBar.Create(Self); with StatusBar do begin Name:='StatusBar'; Parent:=Self; Align:=alBottom; end; FilePropsGroupBox.AnchorParallel(akLeft,0,Self); FilePropsGroupBox.AnchorParallel(akRight,0,Self); FilePropsGroupBox.AnchorToNeighbour(akBottom,0,StatusBar); FilePropsGroupBox.Height:=120; FilesTreeView.AnchorToNeighbour(akTop,0,CompileBitBtn); FilesTreeView.AnchorParallel(akLeft,0,Self); FilesTreeView.AnchorParallel(akRight,0,Self); FilesTreeView.AnchorToNeighbour(akBottom,0,FilePropsGroupBox); end; procedure TPackageEditorForm.UpdateAll; begin if LazPackage=nil then exit; FilesTreeView.BeginUpdate; UpdateTitle; UpdateButtons; UpdateFiles; UpdateRequiredPkgs; UpdateSelectedFile; UpdateStatusBar; FilesTreeView.EndUpdate; end; procedure TPackageEditorForm.UpdateTitle; var NewCaption: String; begin if LazPackage=nil then exit; NewCaption:=Format(lisPckEditPackage, [FLazPackage.Name]); if LazPackage.Modified then NewCaption:=NewCaption+'*'; Caption:=NewCaption; end; procedure TPackageEditorForm.UpdateButtons; begin if LazPackage=nil then exit; SaveBitBtn.Enabled:=(not LazPackage.ReadOnly) and (LazPackage.IsVirtual or LazPackage.Modified); CompileBitBtn.Enabled:=(not LazPackage.IsVirtual); AddBitBtn.Enabled:=not LazPackage.ReadOnly; RemoveBitBtn.Enabled:=(not LazPackage.ReadOnly) and (FilesTreeView.Selected<>nil) and ((FilesTreeView.Selected.Parent=FilesNode) or (FilesTreeView.Selected.Parent=RequiredPackagesNode)); InstallBitBtn.Enabled:=(not LazPackage.AutoCreated); OptionsBitBtn.Enabled:=true; CompilerOptionsBitBtn.Enabled:=true; end; procedure TPackageEditorForm.UpdateFiles; procedure SetImageIndex(ANode: TTreeNode; PkgFile: TPkgFile); begin case PkgFile.FileType of pftUnit,pftVirtualUnit: if PkgFile.HasRegisterProc then ANode.ImageIndex:=ImageIndexRegisterUnit else ANode.ImageIndex:=ImageIndexUnit; pftLFM: ANode.ImageIndex:=ImageIndexLFM; pftLRS: ANode.ImageIndex:=ImageIndexLRS; pftInclude: ANode.ImageIndex:=ImageIndexInclude; pftText: ANode.ImageIndex:=ImageIndexText; pftBinary: ANode.ImageIndex:=ImageIndexBinary; else ANode.ImageIndex:=-1; end; ANode.SelectedIndex:=ANode.ImageIndex; end; var Cnt: Integer; i: Integer; CurFile: TPkgFile; CurNode: TTreeNode; NextNode: TTreeNode; begin if LazPackage=nil then exit; FilesTreeView.BeginUpdate; // files CurNode:=FilesNode.GetFirstChild; Cnt:=LazPackage.FileCount; for i:=0 to Cnt-1 do begin if CurNode=nil then CurNode:=FilesTreeView.Items.AddChild(FilesNode,''); CurFile:=LazPackage.Files[i]; CurNode.Text:=CurFile.GetShortFilename(true); SetImageIndex(CurNode,CurFile); CurNode:=CurNode.GetNextSibling; end; while CurNode<>nil do begin NextNode:=CurNode.GetNextSibling; CurNode.Free; CurNode:=NextNode; end; FilesNode.Expanded:=true; // removed files if LazPackage.RemovedFilesCount>0 then begin if RemovedFilesNode=nil then begin RemovedFilesNode:= FilesTreeView.Items.Add(RequiredPackagesNode, lisPckEditRemovedFilesTheseEntriesAreNotSavedToTheLpkFile); RemovedFilesNode.ImageIndex:=ImageIndexRemovedFiles; RemovedFilesNode.SelectedIndex:=RemovedFilesNode.ImageIndex; end; CurNode:=RemovedFilesNode.GetFirstChild; Cnt:=LazPackage.RemovedFilesCount; for i:=0 to Cnt-1 do begin if CurNode=nil then CurNode:=FilesTreeView.Items.AddChild(RemovedFilesNode,''); CurFile:=LazPackage.RemovedFiles[i]; CurNode.Text:=CurFile.GetShortFilename(true); SetImageIndex(CurNode,CurFile); CurNode:=CurNode.GetNextSibling; end; while CurNode<>nil do begin NextNode:=CurNode.GetNextSibling; CurNode.Free; CurNode:=NextNode; end; RemovedFilesNode.Expanded:=true; end else begin FreeAndNil(RemovedFilesNode); end; FilesTreeView.EndUpdate; end; procedure TPackageEditorForm.UpdateRequiredPkgs; var CurNode: TTreeNode; CurDependency: TPkgDependency; NextNode: TTreeNode; CurNodeText: String; begin if LazPackage=nil then exit; FilesTreeView.BeginUpdate; // required packages CurNode:=RequiredPackagesNode.GetFirstChild; CurDependency:=LazPackage.FirstRequiredDependency; while CurDependency<>nil do begin if CurNode=nil then CurNode:=FilesTreeView.Items.AddChild(RequiredPackagesNode,''); CurNodeText:=CurDependency.AsString; if CurDependency.DefaultFilename<>'' then CurNodeText:=CurNodeText+' in ' +CurDependency.MakeFilenameRelativeToOwner( CurDependency.DefaultFilename); CurNode.Text:=CurNodeText; if CurDependency.LoadPackageResult=lprSuccess then CurNode.ImageIndex:=ImageIndexRequired else CurNode.ImageIndex:=ImageIndexConflict; CurNode.SelectedIndex:=CurNode.ImageIndex; CurNode:=CurNode.GetNextSibling; CurDependency:=CurDependency.NextRequiresDependency; end; while CurNode<>nil do begin NextNode:=CurNode.GetNextSibling; CurNode.Free; CurNode:=NextNode; end; RequiredPackagesNode.Expanded:=true; // removed required packages CurDependency:=LazPackage.FirstRemovedDependency; if CurDependency<>nil then begin if RemovedRequiredNode=nil then begin RemovedRequiredNode:= FilesTreeView.Items.Add(nil, lisPckEditRemovedRequiredPackagesTheseEntriesAreNotSaved); RemovedRequiredNode.ImageIndex:=ImageIndexRemovedRequired; RemovedRequiredNode.SelectedIndex:=RemovedRequiredNode.ImageIndex; end; CurNode:=RemovedRequiredNode.GetFirstChild; while CurDependency<>nil do begin if CurNode=nil then CurNode:=FilesTreeView.Items.AddChild(RemovedRequiredNode,''); CurNode.Text:=CurDependency.AsString; CurNode.ImageIndex:=RemovedRequiredNode.ImageIndex; CurNode.SelectedIndex:=CurNode.ImageIndex; CurNode:=CurNode.GetNextSibling; CurDependency:=CurDependency.NextRequiresDependency; end; while CurNode<>nil do begin NextNode:=CurNode.GetNextSibling; CurNode.Free; CurNode:=NextNode; end; RemovedRequiredNode.Expanded:=true; end else begin FreeAndNil(RemovedRequiredNode); end; FilesTreeView.EndUpdate; end; procedure TPackageEditorForm.UpdateSelectedFile; var CurFile: TPkgFile; i: Integer; CurComponent: TPkgComponent; CurLine: string; CurListIndex: Integer; RegCompCnt: Integer; Dependency: TPkgDependency; Removed: boolean; begin if LazPackage=nil then exit; FPlugins.Clear; Dependency:=nil; CurFile:=GetCurrentFile(Removed); if CurFile=nil then Dependency:=GetCurrentDependency(Removed); // make components visible UseMinVersionCheckBox.Visible:=Dependency<>nil; MinVersionEdit.Visible:=Dependency<>nil; UseMaxVersionCheckBox.Visible:=Dependency<>nil; MaxVersionEdit.Visible:=Dependency<>nil; ApplyDependencyButton.Visible:=Dependency<>nil; CallRegisterProcCheckBox.Visible:=CurFile<>nil; AddToUsesPkgSectionCheckBox.Visible:=CurFile<>nil; RegisteredPluginsGroupBox.Visible:=CurFile<>nil; if CurFile<>nil then begin FilePropsGroupBox.Enabled:=true; FilePropsGroupBox.Caption:=lisPckEditFileProperties; // set Register Unit checkbox CallRegisterProcCheckBox.Enabled:=(not LazPackage.ReadOnly) and (CurFile.FileType in [pftUnit,pftVirtualUnit]); CallRegisterProcCheckBox.Checked:=pffHasRegisterProc in CurFile.Flags; AddToUsesPkgSectionCheckBox.Checked:=pffAddToPkgUsesSection in CurFile.Flags; AddToUsesPkgSectionCheckBox.Enabled:=(not LazPackage.ReadOnly) and (CurFile.FileType in PkgFileUnitTypes); // fetch all registered plugins CurListIndex:=0; RegCompCnt:=CurFile.ComponentCount; for i:=0 to RegCompCnt-1 do begin CurComponent:=CurFile.Components[i]; CurLine:=CurComponent.ComponentClass.ClassName; FPlugins.AddObject(CurLine,CurComponent); inc(CurListIndex); end; // put them in the RegisteredListBox RegisteredListBox.Items.Assign(FPlugins); end else if Dependency<>nil then begin FilePropsGroupBox.Enabled:=not Removed; FilePropsGroupBox.Caption:=lisPckEditDependencyProperties; UseMinVersionCheckBox.Checked:=pdfMinVersion in Dependency.Flags; MinVersionEdit.Text:=Dependency.MinVersion.AsString; MinVersionEdit.Enabled:=pdfMinVersion in Dependency.Flags; UseMaxVersionCheckBox.Checked:=pdfMaxVersion in Dependency.Flags; MaxVersionEdit.Text:=Dependency.MaxVersion.AsString; MaxVersionEdit.Enabled:=pdfMaxVersion in Dependency.Flags; UpdateApplyDependencyButton; end else begin FilePropsGroupBox.Enabled:=false; end; end; procedure TPackageEditorForm.UpdateApplyDependencyButton; var DepencyChanged: Boolean; CurDependency: TPkgDependency; AVersion: TPkgVersion; Removed: boolean; begin if LazPackage=nil then exit; DepencyChanged:=false; CurDependency:=GetCurrentDependency(Removed); if (CurDependency<>nil) then begin // check min version if UseMinVersionCheckBox.Checked <>(pdfMinVersion in CurDependency.Flags) then begin DepencyChanged:=true; end; if UseMinVersionCheckBox.Checked then begin AVersion:=TPkgVersion.Create; if AVersion.ReadString(MinVersionEdit.Text) and (AVersion.Compare(CurDependency.MinVersion)<>0) then begin DepencyChanged:=true; end; AVersion.Free; end; // check max version if UseMaxVersionCheckBox.Checked <>(pdfMaxVersion in CurDependency.Flags) then begin DepencyChanged:=true; end; if UseMaxVersionCheckBox.Checked then begin AVersion:=TPkgVersion.Create; if AVersion.ReadString(MaxVersionEdit.Text) and (AVersion.Compare(CurDependency.MaxVersion)<>0) then begin DepencyChanged:=true; end; AVersion.Free; end; end; ApplyDependencyButton.Enabled:=DepencyChanged; end; procedure TPackageEditorForm.UpdateStatusBar; var StatusText: String; begin if LazPackage=nil then exit; if LazPackage.IsVirtual and (not LazPackage.ReadOnly) then begin StatusText:=Format(lisPckEditpackageNotSaved, [LazPackage.Name]); end else begin StatusText:=LazPackage.Filename; end; if LazPackage.ReadOnly then StatusText:=Format(lisPckEditReadOnly, [StatusText]); if LazPackage.Modified then StatusText:=Format(lisPckEditModified, [StatusText]); StatusBar.SimpleText:=StatusText; end; function TPackageEditorForm.GetCurrentDependency(var Removed: boolean ): TPkgDependency; var CurNode: TTreeNode; NodeIndex: Integer; begin Result:=nil; CurNode:=FilesTreeView.Selected; if (CurNode<>nil) and (CurNode.Parent<>nil) then begin NodeIndex:=CurNode.Index; if CurNode.Parent=RequiredPackagesNode then begin Result:=LazPackage.RequiredDepByIndex(NodeIndex); Removed:=false; end else if CurNode.Parent=RemovedRequiredNode then begin Result:=LazPackage.RemovedDepByIndex(NodeIndex); Removed:=true; end; end; end; function TPackageEditorForm.GetCurrentFile(var Removed: boolean): TPkgFile; var CurNode: TTreeNode; NodeIndex: Integer; begin Result:=nil; CurNode:=FilesTreeView.Selected; if (CurNode<>nil) and (CurNode.Parent<>nil) then begin NodeIndex:=CurNode.Index; if CurNode.Parent=FilesNode then begin Result:=LazPackage.Files[NodeIndex]; Removed:=false; end else if CurNode.Parent=RemovedFilesNode then begin Result:=LazPackage.RemovedFiles[NodeIndex]; Removed:=true; end; end; end; function TPackageEditorForm.StoreCurrentTreeSelection: TStringList; var ANode: TTreeNode; begin Result:=TStringList.Create; ANode:=FilesTreeView.Selected; while ANode<>nil do begin Result.Insert(0,ANode.Text); ANode:=ANode.Parent; end; end; procedure TPackageEditorForm.ApplyTreeSelection(ASelection: TStringList; FreeList: boolean); var ANode: TTreeNode; CurText: string; begin ANode:=nil; while ASelection.Count>0 do begin CurText:=ASelection[0]; if ANode=nil then ANode:=FilesTreeView.Items.GetFirstNode else ANode:=ANode.GetFirstChild; while ANode.Text<>CurText do ANode:=ANode.GetNextSibling; if ANode=nil then break; ASelection.Delete(0); end; if ANode<>nil then FilesTreeView.Selected:=ANode; if FreeList then ASelection.Free; end; procedure TPackageEditorForm.ExtendUnitIncPathForNewUnit(const AnUnitFilename, AnIncludeFile: string); var NewDirectory: String; UnitPath: String; ShortDirectory: String; NewIncDirectory: String; ShortIncDirectory: String; IncPath: String; UnitPathPos: Integer; IncPathPos: Integer; begin if LazPackage=nil then exit; // check if directory is already in the unit path of the package NewDirectory:=ExtractFilePath(AnUnitFilename); ShortDirectory:=NewDirectory; LazPackage.ShortenFilename(ShortDirectory,false); if ShortDirectory='' then exit; LazPackage.LongenFilename(NewDirectory); UnitPath:=LazPackage.GetUnitPath(false); UnitPathPos:=SearchDirectoryInSearchPath(UnitPath,NewDirectory,1); IncPathPos:=1; if AnIncludeFile<>'' then begin NewIncDirectory:=ExtractFilePath(AnIncludeFile); ShortIncDirectory:=NewIncDirectory; LazPackage.ShortenFilename(ShortIncDirectory,false); if ShortIncDirectory<>'' then begin LazPackage.LongenFilename(NewIncDirectory); IncPath:=LazPackage.GetIncludePath(false); IncPathPos:=SearchDirectoryInSearchPath(IncPath,NewIncDirectory,1); end; end; if UnitPathPos<1 then begin // ask user to add the unit path if MessageDlg(lisPkgEditNewUnitNotInUnitpath, Format(lisPkgEditTheFileIsCurrentlyNotInTheUnitpathOfThePackage, ['"', AnUnitFilename, '"', #13, #13, #13, '"', ShortDirectory, '"']), mtConfirmation,[mbYes,mbNo],0)<>mrYes then exit; // add path with LazPackage.CompilerOptions do OtherUnitFiles:=MergeSearchPaths(OtherUnitFiles,ShortDirectory); end; if IncPathPos<1 then begin // the unit is in unitpath, but the include file not in the incpath // -> auto extend the include path with LazPackage.CompilerOptions do IncludePath:=MergeSearchPaths(IncludePath,ShortIncDirectory); end; end; function TPackageEditorForm.CanBeAddedToProject: boolean; begin if LazPackage=nil then exit; Result:=PackageEditors.AddToProject(LazPackage,true)=mrOk; end; procedure TPackageEditorForm.DoSave(SaveAs: boolean); begin PackageEditors.SavePackage(LazPackage,SaveAs); UpdateButtons; UpdateTitle; UpdateStatusBar; end; procedure TPackageEditorForm.DoCompile(CompileClean, CompileRequired: boolean); begin PackageEditors.CompilePackage(LazPackage,CompileClean,CompileRequired); UpdateButtons; UpdateTitle; UpdateStatusBar; end; procedure TPackageEditorForm.DoRevert; begin if MessageDlg(lisPkgEditRevertPackage, Format(lisPkgEditDoYouReallyWantToForgetAllChangesToPackageAnd, [ LazPackage.IDAsString]), mtConfirmation,[mbYes,mbNo],0)<>mrYes then exit; PackageEditors.RevertPackage(LazPackage); UpdateAll; end; procedure TPackageEditorForm.DoPublishProject; begin PackageEditors.PublishPackage(LazPackage); UpdateAll; end; procedure TPackageEditorForm.DoEditVirtualUnit; var Removed: boolean; CurFile: TPkgFile; begin CurFile:=GetCurrentFile(Removed); if (CurFile=nil) or Removed then exit; if ShowEditVirtualPackageDialog(CurFile)=mrOk then UpdateAll; end; procedure TPackageEditorForm.DoMoveCurrentFile(Offset: integer); var Removed: boolean; CurFile: TPkgFile; OldIndex: Integer; NewIndex: Integer; TreeSelection: TStringList; begin CurFile:=GetCurrentFile(Removed); if (CurFile=nil) or Removed then exit; OldIndex:=LazPackage.IndexOfPkgFile(CurFile); NewIndex:=OldIndex+Offset; if (NewIndex<0) or (NewIndex>=LazPackage.FileCount) then exit; TreeSelection:=StoreCurrentTreeSelection; LazPackage.MoveFile(OldIndex,NewIndex); UpdateFiles; ApplyTreeSelection(TreeSelection,true); UpdateButtons; UpdateStatusBar; end; procedure TPackageEditorForm.DoSortFiles; var TreeSelection: TStringList; begin TreeSelection:=StoreCurrentTreeSelection; LazPackage.SortFiles; UpdateAll; ApplyTreeSelection(TreeSelection,true); end; procedure TPackageEditorForm.DoOpenPkgFile(PkgFile: TPkgFile); begin PackageEditors.OpenPkgFile(Self,PkgFile); end; procedure TPackageEditorForm.DoFixFilesCase; begin if LazPackage.FixFilesCaseSensitivity then LazPackage.Modified:=true; UpdateFiles; UpdateButtons; end; constructor TPackageEditorForm.Create(TheOwner: TComponent); begin inherited Create(TheOwner); FPlugins:=TStringList.Create; SetupComponents; OnResize:=@PackageEditorFormResize; OnCloseQuery:=@PackageEditorFormCloseQuery; OnClose:=@PackageEditorFormClose; end; destructor TPackageEditorForm.Destroy; begin PackageEditors.DoFreeEditor(LazPackage); FreeAndNil(FPlugins); inherited Destroy; end; { TPackageEditors } function TPackageEditors.GetEditors(Index: integer): TPackageEditorForm; begin Result:=TPackageEditorForm(FItems[Index]); end; procedure TPackageEditors.ApplyLayout(AnEditor: TPackageEditorForm); var PkgFilename: String; ANode: TAVLTreeNode; ARect: TRect; begin if fLayouts=nil then LoadLayouts; PkgFilename:=AnEditor.LazPackage.Filename; ANode:=fLayouts.FindKey(Pointer(PkgFilename),@CompareFilenameWithLayout); // find a nice position for the editor if ANode<>nil then ARect:=TPackageEditorLayout(ANode.Data).Rectangle else ARect:=Rect(0,0,0,0); if (ARect.BottomScreen.Height) or (ARect.Right>Screen.Width) then ARect:=CreateNiceWindowPosition(500,400); AnEditor.SetBounds(ARect.Left,ARect.Top, ARect.Right-ARect.Left,ARect.Bottom-ARect.Top); end; procedure TPackageEditors.SaveLayout(AnEditor: TPackageEditorForm); var PkgFilename: String; ANode: TAVLTreeNode; CurLayout: TPackageEditorLayout; begin if fLayouts=nil then exit; PkgFilename:=AnEditor.LazPackage.Filename; ANode:=fLayouts.FindKey(Pointer(PkgFilename),@CompareFilenameWithLayout); if ANode<>nil then begin CurLayout:=TPackageEditorLayout(ANode.Data); fLayouts.Remove(CurLayout); end else begin CurLayout:=TPackageEditorLayout.Create; end; CurLayout.Filename:=PkgFilename; with AnEditor do CurLayout.Rectangle:=Bounds(Left,Top,Width,Height); fLayouts.Add(CurLayout); end; procedure TPackageEditors.LoadLayouts; var Filename: String; Path: String; XMLConfig: TXMLConfig; LayoutCount: Integer; NewLayout: TPackageEditorLayout; i: Integer; begin if fLayouts=nil then fLayouts:=TAVLTree.Create(@CompareLayouts); fLayouts.FreeAndClear; Filename:=GetLayoutConfigFilename; if not FileExists(Filename) then exit; try XMLConfig:=TXMLConfig.Create(Filename); except DebugLn('ERROR: unable to open package editor layouts "',Filename,'"'); exit; end; try try Path:='PackageEditorLayouts/'; LayoutCount:=XMLConfig.GetValue(Path+'Count/Value',0); for i:=1 to LayoutCount do begin NewLayout:=TPackageEditorLayout.Create; NewLayout.LoadFromXMLConfig(XMLConfig,Path+'Layout'+IntToStr(i)); if (NewLayout.Filename='') or (fLayouts.Find(NewLayout)<>nil) then NewLayout.Free else fLayouts.Add(NewLayout); end; finally XMLConfig.Free; end; except on E: Exception do begin DebugLn('ERROR: unable read miscellaneous options from "',Filename,'": ',E.Message); end; end; end; function TPackageEditors.GetLayoutConfigFilename: string; begin Result:=SetDirSeparators(GetPrimaryConfigPath+'/packageeditorlayouts.xml'); end; constructor TPackageEditors.Create; begin FItems:=TList.Create; end; destructor TPackageEditors.Destroy; begin Clear; FItems.Free; if fLayouts<>nil then begin fLayouts.FreeAndClear; fLayouts.Free; end; inherited Destroy; end; function TPackageEditors.Count: integer; begin Result:=FItems.Count; end; procedure TPackageEditors.Clear; begin FItems.Clear; end; procedure TPackageEditors.SaveLayouts; var Filename: String; XMLConfig: TXMLConfig; Path: String; LayoutCount: Integer; ANode: TAVLTreeNode; CurLayout: TPackageEditorLayout; begin if fLayouts=nil then exit; Filename:=GetLayoutConfigFilename; try XMLConfig:=TXMLConfig.CreateClean(Filename); except on E: Exception do begin DebugLn('ERROR: unable to open miscellaneous options "',Filename,'": ',E.Message); exit; end; end; try try Path:='PackageEditorLayouts/'; LayoutCount:=0; ANode:=fLayouts.FindLowest; while ANode<>nil do begin inc(LayoutCount); CurLayout:=TPackageEditorLayout(ANode.Data); CurLayout.SaveToXMLConfig(XMLConfig,Path+'Layout'+IntToStr(LayoutCount)); ANode:=fLayouts.FindSuccessor(ANode); end; XMLConfig.SetDeleteValue(Path+'Count/Value',LayoutCount,0); InvalidateFileStateCache; XMLConfig.Flush; finally XMLConfig.Free; end; except DebugLn('ERROR: unable read miscellaneous options from "',Filename,'"'); end; end; procedure TPackageEditors.Remove(Editor: TPackageEditorForm); begin FItems.Remove(Editor); end; function TPackageEditors.IndexOfPackage(Pkg: TLazPackage): integer; begin Result:=Count-1; while (Result>=0) and (Editors[Result].LazPackage<>Pkg) do dec(Result); end; function TPackageEditors.FindEditor(Pkg: TLazPackage): TPackageEditorForm; var i: Integer; begin i:=IndexOfPackage(Pkg); if i>=0 then Result:=Editors[i] else Result:=nil; end; function TPackageEditors.OpenEditor(Pkg: TLazPackage): TPackageEditorForm; begin Result:=FindEditor(Pkg); if Result=nil then begin Result:=TPackageEditorForm.Create(Application); Result.LazPackage:=Pkg; FItems.Add(Result); end; end; function TPackageEditors.OpenFile(Sender: TObject; const Filename: string ): TModalResult; begin if Assigned(OnOpenFile) then Result:=OnOpenFile(Sender,Filename) else Result:=mrCancel; end; function TPackageEditors.OpenPkgFile(Sender: TObject; PkgFile: TPkgFile ): TModalResult; begin if Assigned(OnOpenPkgFile) then Result:=OnOpenPkgFile(Sender,PkgFile) else Result:=mrCancel; end; function TPackageEditors.OpenDependency(Sender: TObject; Dependency: TPkgDependency): TModalResult; var APackage: TLazPackage; begin Result:=mrCancel; if PackageGraph.OpenDependency(Dependency)=lprSuccess then begin APackage:=Dependency.RequiredPackage; if Assigned(OnOpenPackage) then Result:=OnOpenPackage(Sender,APackage); end; end; procedure TPackageEditors.DoFreeEditor(Pkg: TLazPackage); begin FItems.Remove(Pkg.Editor); if Assigned(OnFreeEditor) then OnFreeEditor(Pkg); end; function TPackageEditors.CreateNewFile(Sender: TObject; Params: TAddToPkgResult): TModalResult; begin Result:=mrCancel; if Assigned(OnCreateNewFile) then Result:=OnCreateNewFile(Sender,Params) else Result:=mrCancel; end; function TPackageEditors.SavePackage(APackage: TLazPackage; SaveAs: boolean): TModalResult; begin if Assigned(OnSavePackage) then Result:=OnSavePackage(Self,APackage,SaveAs) else Result:=mrCancel; end; function TPackageEditors.CompilePackage(APackage: TLazPackage; CompileClean, CompileRequired: boolean): TModalResult; begin if Assigned(OnCompilePackage) then Result:=OnCompilePackage(Self,APackage,CompileClean,CompileRequired) else Result:=mrCancel; end; procedure TPackageEditors.UpdateAllEditors; var i: Integer; begin for i:=0 to Count-1 do Editors[i].UpdateAll; end; function TPackageEditors.InstallPackage(APackage: TLazPackage): TModalResult; begin if Assigned(OnInstallPackage) then Result:=OnInstallPackage(Self,APackage) else Result:=mrCancel; end; function TPackageEditors.UninstallPackage(APackage: TLazPackage): TModalResult; begin if Assigned(OnUninstallPackage) then Result:=OnUninstallPackage(Self,APackage) else Result:=mrCancel; end; function TPackageEditors.ViewPkgSourcePackage(APackage: TLazPackage ): TModalResult; begin if Assigned(OnViewPackageSource) then Result:=OnViewPackageSource(Self,APackage) else Result:=mrCancel; end; function TPackageEditors.DeleteAmbiguousFiles(APackage: TLazPackage; const Filename: string): TModalResult; begin if Assigned(OnDeleteAmbiguousFiles) then Result:=OnDeleteAmbiguousFiles(Self,APackage,Filename) else Result:=mrOk; end; function TPackageEditors.AddToProject(APackage: TLazPackage; OnlyTestIfPossible: boolean): TModalResult; begin if Assigned(OnAddToProject) then Result:=OnAddToProject(Self,APackage,OnlyTestIfPossible) else Result:=mrCancel; end; function TPackageEditors.CreateMakefile(APackage: TLazPackage): TModalResult; begin if Assigned(OnCreateMakefile) then Result:=OnCreateMakefile(Self,APackage) else Result:=mrCancel; end; function TPackageEditors.RevertPackage(APackage: TLazPackage): TModalResult; begin if Assigned(OnRevertPackage) then Result:=OnRevertPackage(Self,APackage) else Result:=mrCancel; end; function TPackageEditors.PublishPackage(APackage: TLazPackage): TModalResult; begin if Assigned(OnPublishPackage) then Result:=OnPublishPackage(Self,APackage) else Result:=mrCancel; end; { TPackageEditorLayout } constructor TPackageEditorLayout.Create; begin end; destructor TPackageEditorLayout.Destroy; begin inherited Destroy; end; procedure TPackageEditorLayout.LoadFromXMLConfig(XMLConfig: TXMLConfig; const Path: string); begin Filename:=XMLConfig.GetValue(Path+'Filename/Value',''); LoadRect(XMLConfig,Path+'Rect/',Rectangle); end; procedure TPackageEditorLayout.SaveToXMLConfig(XMLConfig: TXMLConfig; const Path: string); begin XMLConfig.SetDeleteValue(Path+'Filename/Value',Filename,''); SaveRect(XMLConfig,Path+'Rect/',Rectangle); end; initialization PackageEditors:=nil; end.