lazarus/packager/packageeditor.pas
2014-06-15 11:52:27 +00:00

3864 lines
131 KiB
ObjectPascal

{
***************************************************************************
* *
* 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 <http://www.gnu.org/copyleft/gpl.html>. 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+}
{$DEFINE VerbosePkgEditDrag}
interface
uses
// LCL FCL
Classes, SysUtils, Forms, Controls, StdCtrls, ComCtrls, Buttons, Graphics,
LCLType, LCLProc, Menus, Dialogs, FileUtil, LazFileCache,
contnrs,
// IDEIntf CodeTools
IDEImagesIntf, MenuIntf, ExtCtrls, LazIDEIntf, ProjectIntf, CodeToolsStructs,
CodeToolManager, CodeCache, CodeTree, FormEditingIntf, TreeFilterEdit,
PackageIntf, IDEDialogs, IDEHelpIntf, IDEOptionsIntf, IDEProcs,
LazarusIDEStrConsts, IDEDefs, CompilerOptions, ComponentReg, UnitResources,
SrcEditorIntf, IDEMsgIntf, IDEExternToolIntf, EnvironmentOpts, DialogProcs,
PackageDefs, AddToPackageDlg, PkgVirtualUnitEditor, MissingPkgFilesDlg,
PackageSystem, CleanPkgDeps;
const
PackageEditorMenuRootName = 'PackageEditor';
PackageEditorMenuFilesRootName = 'PackageEditorFiles';
PackageEditorWindowPrefix = 'PackageEditor_';
var
// single file
PkgEditMenuOpenFile: TIDEMenuCommand;
PkgEditMenuRemoveFile: TIDEMenuCommand;
PkgEditMenuReAddFile: TIDEMenuCommand;
PkgEditMenuEditVirtualUnit: TIDEMenuCommand;
PkgEditMenuSectionFileType: TIDEMenuSection;
// directories
PkgEditMenuExpandDirectory: TIDEMenuCommand;
PkgEditMenuCollapseDirectory: TIDEMenuCommand;
PkgEditMenuUseAllUnitsInDirectory: TIDEMenuCommand;
PkgEditMenuUseNoUnitsInDirectory: TIDEMenuCommand;
// dependencies
PkgEditMenuOpenPackage: TIDEMenuCommand;
PkgEditMenuRemoveDependency: TIDEMenuCommand;
PkgEditMenuReAddDependency: TIDEMenuCommand;
PkgEditMenuDependencyStoreFileNameAsDefault: TIDEMenuCommand;
PkgEditMenuDependencyStoreFileNameAsPreferred: TIDEMenuCommand;
PkgEditMenuDependencyClearStoredFileName: TIDEMenuCommand;
PkgEditMenuCleanDependencies: TIDEMenuCommand;
// multi files
PkgEditMenuSortFiles: TIDEMenuCommand;
PkgEditMenuFixFilesCase: TIDEMenuCommand;
PkgEditMenuShowMissingFiles: TIDEMenuCommand;
// package
PkgEditMenuSave: TIDEMenuCommand;
PkgEditMenuSaveAs: TIDEMenuCommand;
PkgEditMenuRevert: TIDEMenuCommand;
PkgEditMenuPublish: TIDEMenuCommand;
// compile
PkgEditMenuCompile: TIDEMenuCommand;
PkgEditMenuRecompileClean: TIDEMenuCommand;
PkgEditMenuRecompileAllRequired: TIDEMenuCommand;
PkgEditMenuCreateMakefile: TIDEMenuCommand;
PkgEditMenuCreateFpmakeFile: TIDEMenuCommand;
PkgEditMenuViewPackageSource: TIDEMenuCommand;
type
TOnCreatePkgMakefile =
function(Sender: TObject; APackage: TLazPackage): TModalResult of object;
TOnCreatePkgFpmakeFile =
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;
TOnViewPackageToDos =
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;
TPENodeType = (
penFile,
penDependency
);
{ TPENodeData }
TPENodeData = class(TTFENodeData)
public
Typ: TPENodeType;
Name: string; // file or package name
Removed: boolean;
Next: TPENodeData;
constructor Create(aTyp: TPENodeType; aName: string; aRemoved: boolean);
end;
TPEFlag = (
pefNeedUpdateTitle,
pefNeedUpdateButtons,
pefNeedUpdateFiles,
pefNeedUpdateRequiredPkgs,
pefNeedUpdateProperties,
pefNeedUpdateApplyDependencyButton,
pefNeedUpdateStatusBar
);
TPEFlags = set of TPEFlag;
{ TPackageEditorForm }
TPackageEditorForm = class(TBasePackageEditor)
MoveDownBtn: TSpeedButton;
MoveUpBtn: TSpeedButton;
DirectoryHierarchyButton: TSpeedButton;
OpenButton: TSpeedButton;
DisableI18NForLFMCheckBox: TCheckBox;
FilterEdit: TTreeFilterEdit;
FilterPanel: TPanel;
SortAlphabeticallyButton: TSpeedButton;
Splitter1: TSplitter;
// toolbar
ToolBar: TToolBar;
// toolbuttons
SaveBitBtn: TToolButton;
CompileBitBtn: TToolButton;
UseBitBtn: TToolButton;
AddBitBtn: TToolButton;
RemoveBitBtn: TToolButton;
OptionsBitBtn: TToolButton;
MoreBitBtn: TToolButton;
HelpBitBtn: TToolButton;
// items
ItemsTreeView: TTreeView;
// properties
PropsGroupBox: 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
UsePopupMenu: TPopupMenu;
ItemsPopupMenu: TPopupMenu;
MorePopupMenu: TPopupMenu;
procedure AddBitBtnClick(Sender: TObject);
procedure AddToProjectClick(Sender: TObject);
procedure AddToUsesPkgSectionCheckBoxChange(Sender: TObject);
procedure ApplyDependencyButtonClick(Sender: TObject);
procedure CallRegisterProcCheckBoxChange(Sender: TObject);
procedure ChangeFileTypeMenuItemClick(Sender: TObject);
procedure CleanDependenciesMenuItemClick(Sender: TObject);
procedure ClearDependencyFilenameMenuItemClick(Sender: TObject);
procedure CollapseDirectoryMenuItemClick(Sender: TObject);
procedure CompileAllCleanClick(Sender: TObject);
procedure CompileBitBtnClick(Sender: TObject);
procedure CompileCleanClick(Sender: TObject);
procedure CreateMakefileClick(Sender: TObject);
procedure CreateFpmakeFileClick(Sender: TObject);
procedure DirectoryHierarchyButtonClick(Sender: TObject);
procedure DisableI18NForLFMCheckBoxChange(Sender: TObject);
procedure EditVirtualUnitMenuItemClick(Sender: TObject);
procedure ExpandDirectoryMenuItemClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure ItemsPopupMenuPopup(Sender: TObject);
procedure ItemsTreeViewDragDrop(Sender, Source: TObject; X, Y: Integer);
procedure ItemsTreeViewDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure ItemsTreeViewKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure MorePopupMenuPopup(Sender: TObject);
procedure ItemsTreeViewDblClick(Sender: TObject);
procedure ItemsTreeViewSelectionChanged(Sender: TObject);
procedure FixFilesCaseMenuItemClick(Sender: TObject);
procedure HelpBitBtnClick(Sender: TObject);
procedure InstallClick(Sender: TObject);
procedure MaxVersionEditChange(Sender: TObject);
procedure MinVersionEditChange(Sender: TObject);
procedure MoveDownBtnClick(Sender: TObject);
procedure MoveUpBtnClick(Sender: TObject);
procedure OnIdle(Sender: TObject; var Done: Boolean);
procedure OpenFileMenuItemClick(Sender: TObject);
procedure OptionsBitBtnClick(Sender: TObject);
procedure PackageEditorFormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure PackageEditorFormCloseQuery(Sender: TObject; var CanClose: boolean);
procedure PublishClick(Sender: TObject);
procedure ReAddMenuItemClick(Sender: TObject);
procedure RegisteredListBoxDrawItem(Control: TWinControl; Index: Integer;
ARect: TRect; State: TOwnerDrawState);
procedure RemoveBitBtnClick(Sender: TObject);
procedure RevertClick(Sender: TObject);
procedure SaveAsClick(Sender: TObject);
procedure SaveBitBtnClick(Sender: TObject);
procedure SetDependencyDefaultFilenameMenuItemClick(Sender: TObject);
procedure SetDependencyPreferredFilenameMenuItemClick(Sender: TObject);
procedure ShowMissingFilesMenuItemClick(Sender: TObject);
procedure SortAlphabeticallyButtonClick(Sender: TObject);
procedure SortFilesMenuItemClick(Sender: TObject);
procedure UninstallClick(Sender: TObject);
procedure UseAllUnitsInDirectoryMenuItemClick(Sender: TObject);
procedure UseMaxVersionCheckBoxChange(Sender: TObject);
procedure UseMinVersionCheckBoxChange(Sender: TObject);
procedure UseNoUnitsInDirectoryMenuItemClick(Sender: TObject);
procedure UsePopupMenuPopup(Sender: TObject);
procedure ViewPkgSourceClick(Sender: TObject);
procedure ViewPkgTodosClick(Sender: TObject);
private
FIdleConnected: boolean;
FLazPackage: TLazPackage;
FNextSelectedPart: TPENodeData;// select this file/dependency on next update
FFilesNode: TTreeNode;
FRequiredPackagesNode: TTreeNode;
FRemovedFilesNode: TTreeNode;
FRemovedRequiredNode: TTreeNode;
FPlugins: TStringList; // ComponentClassName, Objects=TPkgComponent
FShowDirectoryHierarchy: boolean;
FSortAlphabetically: boolean;
FDirSummaryLabel: TLabel;
FSingleSelectedFile: TPkgFile;
FSingleSelectedDependency: TPkgDependency;
FFirstNodeData: array[TPENodeType] of TPENodeData;
fUpdateLock: integer;
procedure FreeNodeData(Typ: TPENodeType);
function CreateNodeData(Typ: TPENodeType; aName: string; aRemoved: boolean): TPENodeData;
procedure SetDependencyDefaultFilename(AsPreferred: boolean);
procedure SetIdleConnected(AValue: boolean);
procedure SetShowDirectoryHierarchy(const AValue: boolean);
procedure SetSortAlphabetically(const AValue: boolean);
procedure SetupComponents;
function OnTreeViewGetImageIndex(Str: String; Data: TObject; var AIsEnabled: Boolean): Integer;
procedure UpdatePending;
function CanUpdate(Flag: TPEFlag): boolean;
procedure UpdateTitle(Immediately: boolean = false);
procedure UpdateButtons(Immediately: boolean = false);
procedure UpdateFiles(Immediately: boolean = false);
procedure UpdateRequiredPkgs(Immediately: boolean = false);
procedure UpdatePEProperties(Immediately: boolean = false);
procedure UpdateApplyDependencyButton(Immediately: boolean = false);
procedure UpdateStatusBar(Immediately: boolean = false);
function GetNodeData(TVNode: TTreeNode): TPENodeData;
function GetNodeItem(NodeData: TPENodeData): TObject;
function GetNodeDataItem(TVNode: TTreeNode; out NodeData: TPENodeData;
out Item: TObject): boolean;
function IsDirectoryNode(Node: TTreeNode): boolean;
function GetNodeFilename(Node: TTreeNode): string;
procedure GetDirectorySummary(DirNode: TTreeNode;
out FileCount, HasRegisterProcCount, AddToUsesPkgSectionCount: integer);
procedure ExtendUnitIncPathForNewUnit(const AnUnitFilename,
AnIncludeFile: string; var IgnoreUnitPaths: TFilenameToStringTree);
procedure ExtendIncPathForNewIncludeFile(const AnIncludeFile: string;
var IgnoreIncPaths: TFilenameToStringTree);
function CanBeAddedToProject: boolean;
function CheckDrag(Sender, Source: TObject; X, Y: Integer;
out SrcPkgEdit: TPackageEditorForm;
out aFileCount, aDependencyCount, aDirectoryCount: integer;
out TargetTVNode: TTreeNode; out TargetTVType: TTreeViewInsertMarkType
): boolean;
function MoveFiles(SrcPkgEdit: TPackageEditorForm;
TargetDirectory: string): boolean;
function MoveFiles(SrcPkgEdit: TPackageEditorForm; PkgFiles: TFPList;
TargetDirectory: string): boolean;
protected
fFlags: TPEFlags;
fLastDlgPage: TAddToPkgType;
procedure SetLazPackage(const AValue: TLazPackage); override;
property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure DoCompile(CompileClean, CompileRequired: boolean);
procedure DoFixFilesCase;
procedure DoShowMissingFiles;
procedure DoMoveCurrentFile(Offset: integer);
procedure DoMoveDependency(Offset: integer);
procedure DoPublishProject;
procedure DoEditVirtualUnit;
procedure DoExpandDirectory;
procedure DoCollapseDirectory;
procedure DoUseUnitsInDirectory(Use: boolean);
procedure DoRevert;
procedure DoSave(SaveAs: boolean);
procedure DoSortFiles;
function DoOpenPkgFile(PkgFile: TPkgFile): TModalResult;
procedure UpdateAll(Immediately: boolean); override;
function ShowAddDialog(var DlgPage: TAddToPkgType): TModalResult;
procedure BeginUdate;
procedure EndUpdate;
public
property LazPackage: TLazPackage read FLazPackage write SetLazPackage;
property SortAlphabetically: boolean read FSortAlphabetically write SetSortAlphabetically;
property ShowDirectoryHierarchy: boolean read FShowDirectoryHierarchy write SetShowDirectoryHierarchy;
end;
{ TPackageEditors }
TPackageEditors = class
private
FItems: TFPList; // list of TPackageEditorForm
FOnAddToProject: TOnAddPkgToProject;
FOnAfterWritePackage: TIDEOptionsWriteEvent;
FOnBeforeReadPackage: TNotifyEvent;
FOnCompilePackage: TOnCompilePackage;
FOnCreateNewFile: TOnCreateNewPkgFile;
FOnCreateMakefile: TOnCreatePkgMakefile;
FOnCreateFpmakeFile: TOnCreatePkgFpmakeFile;
FOnDeleteAmbiguousFiles: TOnDeleteAmbiguousFiles;
FOnFreeEditor: TOnFreePkgEditor;
FOnGetIDEFileInfo: TGetIDEFileStateEvent;
FOnGetUnitRegisterInfo: TOnGetUnitRegisterInfo;
FOnInstallPackage: TOnInstallPackage;
FOnOpenFile: TOnOpenFile;
FOnOpenPackage: TOnOpenPackage;
FOnOpenPkgFile: TOnOpenPkgFile;
FOnPublishPackage: TOnPublishPackage;
FOnRevertPackage: TOnRevertPackage;
FOnSavePackage: TOnSavePackage;
FOnUninstallPackage: TOnUninstallPackage;
FOnViewPackageSource: TOnViewPackageSource;
FOnViewPackageToDos: TOnViewPackageToDos;
function GetEditors(Index: integer): TPackageEditorForm;
public
constructor Create;
destructor Destroy; override;
function Count: integer;
procedure Clear;
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(Immediately: boolean);
function ShouldNotBeInstalled(APackage: TLazPackage): boolean;// possible, but probably a bad idea
function InstallPackage(APackage: TLazPackage): TModalResult;
function UninstallPackage(APackage: TLazPackage): TModalResult;
function ViewPkgSource(APackage: TLazPackage): TModalResult;
function ViewPkgToDos(APackage: TLazPackage): TModalResult;
function DeleteAmbiguousFiles(APackage: TLazPackage;
const Filename: string): TModalResult;
function AddToProject(APackage: TLazPackage;
OnlyTestIfPossible: boolean): TModalResult;
function CreateMakefile(APackage: TLazPackage): TModalResult;
function CreateFpmakeFile(APackage: TLazPackage): TModalResult;
public
property Editors[Index: integer]: TPackageEditorForm read GetEditors;
property OnAddToProject: TOnAddPkgToProject read FOnAddToProject
write FOnAddToProject;
property OnAfterWritePackage: TIDEOptionsWriteEvent read FOnAfterWritePackage
write FOnAfterWritePackage;
property OnBeforeReadPackage: TNotifyEvent read FOnBeforeReadPackage
write FOnBeforeReadPackage;
property OnCompilePackage: TOnCompilePackage read FOnCompilePackage
write FOnCompilePackage;
property OnCreateMakeFile: TOnCreatePkgMakefile read FOnCreateMakefile
write FOnCreateMakefile;
property OnCreateFpmakeFile: TOnCreatePkgFpmakeFile read FOnCreateFpmakeFile
write FOnCreateFpmakeFile;
property OnCreateNewFile: TOnCreateNewPkgFile read FOnCreateNewFile
write FOnCreateNewFile;
property OnDeleteAmbiguousFiles: TOnDeleteAmbiguousFiles
read FOnDeleteAmbiguousFiles write FOnDeleteAmbiguousFiles;
property OnFreeEditor: TOnFreePkgEditor read FOnFreeEditor
write FOnFreeEditor;
property OnGetIDEFileInfo: TGetIDEFileStateEvent read FOnGetIDEFileInfo
write FOnGetIDEFileInfo;
property OnGetUnitRegisterInfo: TOnGetUnitRegisterInfo
read FOnGetUnitRegisterInfo write FOnGetUnitRegisterInfo;
property OnInstallPackage: TOnInstallPackage read FOnInstallPackage
write FOnInstallPackage;
property OnOpenFile: TOnOpenFile read FOnOpenFile write FOnOpenFile;
property OnOpenPackage: TOnOpenPackage read FOnOpenPackage
write FOnOpenPackage;
property OnOpenPkgFile: TOnOpenPkgFile read FOnOpenPkgFile
write FOnOpenPkgFile;
property OnPublishPackage: TOnPublishPackage read FOnPublishPackage
write FOnPublishPackage;
property OnRevertPackage: TOnRevertPackage read FOnRevertPackage
write FOnRevertPackage;
property OnSavePackage: TOnSavePackage read FOnSavePackage
write FOnSavePackage;
property OnUninstallPackage: TOnUninstallPackage read FOnUninstallPackage
write FOnUninstallPackage;
property OnViewPackageSource: TOnViewPackageSource read FOnViewPackageSource
write FOnViewPackageSource;
property OnViewPackageToDos: TOnViewPackageToDos read FOnViewPackageToDos
write FOnViewPackageToDos;
end;
var
PackageEditors: TPackageEditors;
procedure RegisterStandardPackageEditorMenuItems;
implementation
{$R *.lfm}
var
ImageIndexFiles: integer;
ImageIndexRemovedFiles: integer;
ImageIndexRequired: integer;
ImageIndexRemovedRequired: integer;
ImageIndexUnit: integer;
ImageIndexRegisterUnit: integer;
ImageIndexLFM: integer;
ImageIndexLRS: integer;
ImageIndexInclude: integer;
ImageIndexIssues: integer;
ImageIndexText: integer;
ImageIndexBinary: integer;
ImageIndexConflict: integer;
ImageIndexDirectory: integer;
procedure RegisterStandardPackageEditorMenuItems;
var
AParent: TIDEMenuSection;
begin
PackageEditorMenuRoot :=RegisterIDEMenuRoot(PackageEditorMenuRootName);
PackageEditorMenuFilesRoot:=RegisterIDEMenuRoot(PackageEditorMenuFilesRootName);
// register the section for operations on single files
PkgEditMenuSectionFile:=RegisterIDEMenuSection(PackageEditorMenuFilesRoot,'File');
AParent:=PkgEditMenuSectionFile;
PkgEditMenuOpenFile:=RegisterIDEMenuCommand(AParent,'Open File',lisOpenFile);
PkgEditMenuRemoveFile:=RegisterIDEMenuCommand(AParent,'Remove File',lisPckEditRemoveFile);
PkgEditMenuReAddFile:=RegisterIDEMenuCommand(AParent,'ReAdd File',lisPckEditReAddFile);
PkgEditMenuEditVirtualUnit:=RegisterIDEMenuCommand(AParent,'Edit Virtual File',lisPEEditVirtualUnit);
PkgEditMenuSectionFileType:=RegisterIDESubMenu(AParent,'File Type',lisAF2PFileType);
// register the section for operations on directories
PkgEditMenuSectionDirectory:=RegisterIDEMenuSection(PackageEditorMenuFilesRoot,'Directory');
AParent:=PkgEditMenuSectionDirectory;
PkgEditMenuExpandDirectory:=RegisterIDEMenuCommand(AParent,'Expand directory',lisPEExpandDirectory);
PkgEditMenuCollapseDirectory:=RegisterIDEMenuCommand(AParent, 'Collapse directory', lisPECollapseDirectory);
PkgEditMenuUseAllUnitsInDirectory:=RegisterIDEMenuCommand(AParent, 'Use all units in directory', lisPEUseAllUnitsInDirectory);
PkgEditMenuUseNoUnitsInDirectory:=RegisterIDEMenuCommand(AParent, 'Use no units in directory', lisPEUseNoUnitsInDirectory);
// register the section for operations on dependencies
PkgEditMenuSectionDependency:=RegisterIDEMenuSection(PackageEditorMenuFilesRoot,'Dependency');
AParent:=PkgEditMenuSectionDependency;
PkgEditMenuOpenPackage:=RegisterIDEMenuCommand(AParent,'Open Package',lisMenuOpenPackage);
PkgEditMenuRemoveDependency:=RegisterIDEMenuCommand(AParent,'Remove Dependency',lisPckEditRemoveDependency);
PkgEditMenuReAddDependency:=RegisterIDEMenuCommand(AParent,'ReAdd Dependency',lisPckEditReAddDependency);
PkgEditMenuDependencyStoreFileNameAsDefault:=RegisterIDEMenuCommand(AParent,'Dependency Store Filename As Default',lisPckEditStoreFileNameAsDefaultForThisDependency);
PkgEditMenuDependencyStoreFileNameAsPreferred:=RegisterIDEMenuCommand(AParent,'Dependency Store Filename As Preferred',lisPckEditStoreFileNameAsPreferredForThisDependency);
PkgEditMenuDependencyClearStoredFileName:=RegisterIDEMenuCommand(AParent,'Dependency Clear Stored Filename',lisPckEditClearDefaultPreferredFilenameOfDependency);
PkgEditMenuCleanDependencies:=RegisterIDEMenuCommand(AParent, 'Clean up dependencies', lisPckEditCleanUpDependencies);
// register the section for operations on all files
PkgEditMenuSectionFiles:=RegisterIDEMenuSection(PackageEditorMenuRoot,'Files');
AParent:=PkgEditMenuSectionFiles;
PkgEditMenuSortFiles:=RegisterIDEMenuCommand(AParent,'Sort Files Permanently',lisPESortFiles);
PkgEditMenuFixFilesCase:=RegisterIDEMenuCommand(AParent,'Fix Files Case',lisPEFixFilesCase);
PkgEditMenuShowMissingFiles:=RegisterIDEMenuCommand(AParent, 'Show Missing Files', lisPEShowMissingFiles);
// register the section for using the package
PkgEditMenuSectionUse:=RegisterIDEMenuSection(PackageEditorMenuRoot,'Use');
// register the section for saving the package
PkgEditMenuSectionSave:=RegisterIDEMenuSection(PackageEditorMenuRoot,'Save');
AParent:=PkgEditMenuSectionSave;
PkgEditMenuSave:=RegisterIDEMenuCommand(AParent, 'Save', lisPckEditSavePackage);
PkgEditMenuSaveAs:=RegisterIDEMenuCommand(AParent, 'Save As', lisPESavePackageAs);
PkgEditMenuRevert:=RegisterIDEMenuCommand(AParent, 'Revert', lisPERevertPackage);
PkgEditMenuPublish:=RegisterIDEMenuCommand(AParent,'Publish',lisPkgEditPublishPackage);
// register the section for compiling the package
PkgEditMenuSectionCompile:=RegisterIDEMenuSection(PackageEditorMenuRoot,'Compile');
AParent:=PkgEditMenuSectionCompile;
PkgEditMenuCompile:=RegisterIDEMenuCommand(AParent,'Compile',lisCompile);
PkgEditMenuRecompileClean:=RegisterIDEMenuCommand(AParent,'Recompile Clean',lisPckEditRecompileClean);
PkgEditMenuRecompileAllRequired:=RegisterIDEMenuCommand(AParent,'Recompile All Required',lisPckEditRecompileAllRequired);
PkgEditMenuCreateFpmakeFile:=RegisterIDEMenuCommand(AParent,'Create fpmake.pp',lisPckEditCreateFpmakeFile);
PkgEditMenuCreateMakefile:=RegisterIDEMenuCommand(AParent,'Create Makefile',lisPckEditCreateMakefile);
// register the section for adding to or removing from package
PkgEditMenuSectionAddRemove:=RegisterIDEMenuSection(PackageEditorMenuRoot,'AddRemove');
// register the section for other things
PkgEditMenuSectionMisc:=RegisterIDEMenuSection(PackageEditorMenuRoot,'Misc');
AParent:=PkgEditMenuSectionMisc;
PkgEditMenuViewPackageSource:=RegisterIDEMenuCommand(AParent,'View Package Source',lisPckEditViewPackageSource);
end;
{ TPENodeData }
constructor TPENodeData.Create(aTyp: TPENodeType; aName: string;
aRemoved: boolean);
begin
Typ:=aTyp;
Name:=aName;;
Removed:=aRemoved;
end;
{ TPackageEditorForm }
procedure TPackageEditorForm.PublishClick(Sender: TObject);
begin
DoPublishProject;
end;
procedure TPackageEditorForm.ReAddMenuItemClick(Sender: TObject);
var
PkgFile: TPkgFile;
AFilename: String;
Dependency: TPkgDependency;
i: Integer;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
begin
BeginUdate;
try
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
if not NodeData.Removed then continue;
if Item is TPkgFile then begin
// re-add file
PkgFile:=TPkgFile(Item);
AFilename:=PkgFile.GetFullFilename;
if PkgFile.FileType in PkgFileRealUnitTypes 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);
UpdateFiles;
end else if Item is TPkgDependency then begin
Dependency:=TPkgDependency(Item);
// re-add dependency
if CheckAddingDependency(LazPackage,Dependency,false,true)<>mrOk then exit;
LazPackage.RemoveRemovedDependency(Dependency);
PackageGraph.AddDependencyToPackage(LazPackage,Dependency);
UpdateRequiredPkgs;
end;
end;
finally
EndUpdate;
end;
end;
procedure TPackageEditorForm.ItemsPopupMenuPopup(Sender: TObject);
procedure SetItem(Item: TIDEMenuCommand; AnOnClick: TNotifyEvent;
aShow: boolean = true; AEnable: boolean = true);
begin
//debugln(['SetItem ',Item.Caption,' Visible=',aShow,' Enable=',AEnable]);
Item.OnClick:=AnOnClick;
Item.Visible:=aShow;
Item.Enabled:=AEnable;
end;
procedure AddFileTypeMenuItem;
var
CurPFT: TPkgFileType;
VirtualFileExists: Boolean;
NewMenuItem: TIDEMenuCommand;
begin
PkgEditMenuSectionFileType.Clear;
if FSingleSelectedFile=nil then exit;
VirtualFileExists:=(FSingleSelectedFile.FileType=pftVirtualUnit)
and FileExistsCached(FSingleSelectedFile.GetFullFilename);
for CurPFT:=Low(TPkgFileType) to High(TPkgFileType) do begin
NewMenuItem:=RegisterIDEMenuCommand(PkgEditMenuSectionFileType,
'SetFileType'+IntToStr(ord(CurPFT)),
GetPkgFileTypeLocalizedName(CurPFT),
@ChangeFileTypeMenuItemClick);
if CurPFT=FSingleSelectedFile.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(FSingleSelectedFile.Filename) then
// a pascal file can be changed into anything
NewMenuItem.Enabled:=true
else
// default is to not allow
NewMenuItem.Enabled:=false;
end;
end;
var
i: Integer;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
SingleSelectedRemoved: Boolean;
SelDepCount: Integer;
SelFileCount: Integer;
SelDirCount: Integer;
SelRemovedFileCount: Integer;
Writable: Boolean;
CurDependency: TPkgDependency;
CurFile: TPkgFile;
begin
//debugln(['TPackageEditorForm.FilesPopupMenuPopup START ',ItemsPopupMenu.Items.Count]);
PackageEditorMenuFilesRoot.MenuItem:=ItemsPopupMenu.Items;
//debugln(['TPackageEditorForm.FilesPopupMenuPopup START after connect ',ItemsPopupMenu.Items.Count]);
PackageEditorMenuRoot.BeginUpdate;
try
SelFileCount:=0;
SelDepCount:=0;
SelDirCount:=0;
SelRemovedFileCount:=0;
SingleSelectedRemoved:=false;
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if GetNodeDataItem(TVNode,NodeData,Item) then begin
if Item is TPkgFile then begin
CurFile:=TPkgFile(Item);
inc(SelFileCount);
FSingleSelectedFile:=CurFile;
SingleSelectedRemoved:=NodeData.Removed;
if NodeData.Removed then
inc(SelRemovedFileCount);
end else if Item is TPkgDependency then begin
CurDependency:=TPkgDependency(Item);
inc(SelDepCount);
FSingleSelectedDependency:=CurDependency;
SingleSelectedRemoved:=NodeData.Removed;
end;
end else if IsDirectoryNode(TVNode) or (TVNode=FFilesNode) then begin
inc(SelDirCount);
end;
end;
if (SelFileCount+SelDepCount+SelDirCount>1) then begin
// it is a multi selection
FSingleSelectedFile:=nil;
FSingleSelectedDependency:=nil;
end;
Writable:=(not LazPackage.ReadOnly);
PkgEditMenuSectionFileType.Clear;
// items for single files, under section PkgEditMenuSectionFile
PkgEditMenuSectionFile.Visible:=SelFileCount>0;
if PkgEditMenuSectionFile.Visible then begin
SetItem(PkgEditMenuOpenFile,@OpenFileMenuItemClick);
SetItem(PkgEditMenuReAddFile,@ReAddMenuItemClick,SingleSelectedRemoved);
SetItem(PkgEditMenuRemoveFile,@RemoveBitBtnClick,SelRemovedFileCount>0,RemoveBitBtn.Enabled);
AddFileTypeMenuItem;
SetItem(PkgEditMenuEditVirtualUnit,@EditVirtualUnitMenuItemClick,
(FSingleSelectedFile<>nil) and (FSingleSelectedFile.FileType=pftVirtualUnit)
and not SingleSelectedRemoved,Writable);
end;
// items for directories, under section PkgEditMenuSectionDirectory
PkgEditMenuSectionDirectory.Visible:=(SelDirCount>0) and ShowDirectoryHierarchy;
if PkgEditMenuSectionDirectory.Visible then begin
SetItem(PkgEditMenuExpandDirectory,@ExpandDirectoryMenuItemClick);
SetItem(PkgEditMenuCollapseDirectory,@CollapseDirectoryMenuItemClick);
SetItem(PkgEditMenuUseAllUnitsInDirectory,@UseAllUnitsInDirectoryMenuItemClick);
SetItem(PkgEditMenuUseNoUnitsInDirectory,@UseNoUnitsInDirectoryMenuItemClick);
end;
// items for dependencies, under section PkgEditMenuSectionDependency
PkgEditMenuSectionDependency.Visible:=(SelDepCount>0)
or (ItemsTreeView.Selected=FRequiredPackagesNode);
SetItem(PkgEditMenuOpenPackage,@OpenFileMenuItemClick,
(FSingleSelectedDependency<>nil) and (FSingleSelectedDependency.RequiredPackage<>nil));
SetItem(PkgEditMenuRemoveDependency,@RemoveBitBtnClick,
(FSingleSelectedDependency<>nil) and (not SingleSelectedRemoved),
Writable);
SetItem(PkgEditMenuReAddDependency,@ReAddMenuItemClick,
(FSingleSelectedDependency<>nil) and SingleSelectedRemoved,
Writable);
SetItem(PkgEditMenuDependencyStoreFileNameAsDefault,
@SetDependencyDefaultFilenameMenuItemClick,
(FSingleSelectedDependency<>nil) and (not SingleSelectedRemoved),
Writable and (FSingleSelectedDependency<>nil)
and (FSingleSelectedDependency.RequiredPackage<>nil));
SetItem(PkgEditMenuDependencyStoreFileNameAsPreferred,
@SetDependencyPreferredFilenameMenuItemClick,
(FSingleSelectedDependency<>nil) and (not SingleSelectedRemoved),
Writable and (FSingleSelectedDependency<>nil)
and (FSingleSelectedDependency.RequiredPackage<>nil));
SetItem(PkgEditMenuDependencyClearStoredFileName,
@ClearDependencyFilenameMenuItemClick,
(FSingleSelectedDependency<>nil) and (not SingleSelectedRemoved),
Writable and (FSingleSelectedDependency<>nil)
and (FSingleSelectedDependency.RequiredPackage<>nil));
SetItem(PkgEditMenuCleanDependencies,
@CleanDependenciesMenuItemClick,LazPackage.FirstRequiredDependency<>nil,
Writable);
finally
PackageEditorMenuRoot.EndUpdate;
end;
//debugln(['TPackageEditorForm.FilesPopupMenuPopup END ',ItemsPopupMenu.Items.Count]); PackageEditorMenuRoot.WriteDebugReport(' ',true);
end;
procedure TPackageEditorForm.ItemsTreeViewDragDrop(Sender, Source: TObject; X,
Y: Integer);
var
SrcPkgEdit: TPackageEditorForm;
FileCount: integer;
DepCount: integer;
DirCount: integer;
TargetTVNode: TTreeNode;
TargetTVType: TTreeViewInsertMarkType;
NodeData: TPENodeData;
Item: TObject;
PkgFile: TPkgFile;
Directory: String;
begin
if not CheckDrag(Sender, Source, X, Y, SrcPkgEdit, FileCount,
DepCount, DirCount, TargetTVNode, TargetTVType)
then begin
ItemsTreeView.SetInsertMark(nil,tvimNone);
ShowMessage('drop failed, dragover was wrong');
exit;
end;
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.ItemsTreeViewDragDrop START']);
{$ENDIF}
if GetNodeDataItem(TargetTVNode,NodeData,Item) then begin
if Item is TPkgFile then begin
PkgFile:=TPkgFile(Item);
if FileCount=0 then exit;
// drag files
Directory:=ExtractFilePath(PkgFile.GetFullFilename);
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.ItemsTreeViewDragDrop drag files to directory of ',PkgFile.Filename]);
{$ENDIF}
MoveFiles(SrcPkgEdit,Directory);
end else if Item is TPkgDependency then begin
if DepCount=0 then exit;
// ToDo: drag dependencies
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.ItemsTreeViewDragDrop: drag dependencies']);
{$ENDIF}
ShowMessage('Not implemented yet: drag dependencies');
end;
end else if IsDirectoryNode(TargetTVNode) or (TargetTVNode=FFilesNode) then begin
Directory:=GetNodeFilename(TargetTVNode);
if FileCount>0 then begin
// drag files
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.ItemsTreeViewDragDrop drag files to ',LazPackage.Directory]);
{$ENDIF}
MoveFiles(SrcPkgEdit,Directory);
end else if DirCount>0 then begin
// drag directory
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.ItemsTreeViewDragDrop: drag directory']);
{$ENDIF}
ShowMessage('Not implemented yet: drag directory');
end else begin
ShowMessage('I cannot drag that to a directory');
end;
end else if TargetTVNode=FRequiredPackagesNode then begin
if DepCount=0 then exit;
// ToDo: drag dependencies
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.ItemsTreeViewDragDrop: drag dependencies']);
{$ENDIF}
ShowMessage('Not implemented yet: drag dependencies');
end;
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.ItemsTreeViewDragDrop END']);
{$ENDIF}
end;
procedure TPackageEditorForm.ItemsTreeViewDragOver(Sender, Source: TObject; X,
Y: Integer; State: TDragState; var Accept: Boolean);
var
SrcPkgEdit: TPackageEditorForm;
FileCount: Integer;
DepCount: Integer;
DirCount: Integer;
TargetTVNode: TTreeNode;
TargetTVType: TTreeViewInsertMarkType;
begin
//debugln(['TPackageEditorForm.ItemsTreeViewDragOver ',DbgSName(Source),' State=',ord(State),' FromSelf=',Source=ItemsTreeView]);
if not CheckDrag(Sender, Source, X, Y, SrcPkgEdit, FileCount,
DepCount, DirCount, TargetTVNode, TargetTVType)
then begin
ItemsTreeView.SetInsertMark(nil,tvimNone);
Accept:=false;
exit;
end;
if State=dsDragLeave then
ItemsTreeView.SetInsertMark(nil,tvimNone)
else
ItemsTreeView.SetInsertMark(TargetTVNode,TargetTVType);
Accept:=true;
end;
procedure TPackageEditorForm.MorePopupMenuPopup(Sender: TObject);
var
Writable: Boolean;
procedure SetItem(Item: TIDEMenuCommand; AnOnClick: TNotifyEvent;
aShow: boolean = true; AEnable: boolean = true);
begin
//debugln(['SetItem ',Item.Caption,' Visible=',aShow,' Enable=',AEnable]);
Item.OnClick:=AnOnClick;
Item.Visible:=aShow;
Item.Enabled:=AEnable;
end;
begin
PackageEditorMenuRoot.MenuItem:=MorePopupMenu.Items;
PackageEditorMenuRoot.BeginUpdate;
try
Writable:=(not LazPackage.ReadOnly);
PkgEditMenuSectionFileType.Clear;
// under section PkgEditMenuSectionFiles
SetItem(PkgEditMenuSortFiles,@SortFilesMenuItemClick,(LazPackage.FileCount>1),Writable);
SetItem(PkgEditMenuFixFilesCase,@FixFilesCaseMenuItemClick,(LazPackage.FileCount>0),Writable);
SetItem(PkgEditMenuShowMissingFiles,@ShowMissingFilesMenuItemClick,(LazPackage.FileCount>0),Writable);
// under section PkgEditMenuSectionSave
SetItem(PkgEditMenuSave,@SaveBitBtnClick,true,SaveBitBtn.Enabled);
SetItem(PkgEditMenuSaveAs,@SaveAsClick,true,true);
SetItem(PkgEditMenuRevert,@RevertClick,true,
(not LazPackage.IsVirtual) and FileExistsUTF8(LazPackage.Filename));
SetItem(PkgEditMenuPublish,@PublishClick,true,
(not LazPackage.Missing) and LazPackage.HasDirectory);
// under section PkgEditMenuSectionCompile
SetItem(PkgEditMenuCompile,@CompileBitBtnClick,true,CompileBitBtn.Enabled);
SetItem(PkgEditMenuRecompileClean,@CompileCleanClick,true,CompileBitBtn.Enabled);
SetItem(PkgEditMenuRecompileAllRequired,@CompileAllCleanClick,true,CompileBitBtn.Enabled);
SetItem(PkgEditMenuCreateFpmakeFile,@CreateFpmakeFileClick,true,CompileBitBtn.Enabled);
SetItem(PkgEditMenuCreateMakefile,@CreateMakefileClick,true,CompileBitBtn.Enabled);
// under section PkgEditMenuSectionMisc
SetItem(PkgEditMenuViewPackageSource,@ViewPkgSourceClick);
finally
PackageEditorMenuRoot.EndUpdate;
end;
end;
procedure TPackageEditorForm.SortAlphabeticallyButtonClick(Sender: TObject);
begin
SortAlphabetically:=SortAlphabeticallyButton.Down;
end;
procedure TPackageEditorForm.UsePopupMenuPopup(Sender: TObject);
var
ItemCnt: Integer;
function AddPopupMenuItem(const ACaption: string; AnEvent: TNotifyEvent;
EnabledFlag: boolean): TMenuItem;
begin
if UsePopupMenu.Items.Count<=ItemCnt then begin
Result:=TMenuItem.Create(Self);
UsePopupMenu.Items.Add(Result);
end else begin
Result:=UsePopupMenu.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;
begin
ItemCnt:=0;
AddPopupMenuItem(lisPckEditAddToProject, @AddToProjectClick,
CanBeAddedToProject);
AddPopupMenuItem(lisPckEditInstall, @InstallClick,(not LazPackage.Missing)
and (LazPackage.PackageType in [lptDesignTime,lptRunAndDesignTime]));
AddPopupMenuItem(lisPckEditUninstall, @UninstallClick,
(LazPackage.Installed<>pitNope) or (LazPackage.AutoInstall<>pitNope));
// remove unneeded menu items
while UsePopupMenu.Items.Count>ItemCnt do
UsePopupMenu.Items.Delete(UsePopupMenu.Items.Count-1);
end;
procedure TPackageEditorForm.ItemsTreeViewDblClick(Sender: TObject);
begin
OpenFileMenuItemClick(Self);
end;
procedure TPackageEditorForm.ItemsTreeViewKeyDown(Sender: TObject;
var Key: Word; Shift: TShiftState);
var
Handled: Boolean;
begin
Handled := True;
if (ssCtrl in Shift) then
begin
if Key = VK_UP then
MoveUpBtnClick(Nil)
else if Key = VK_DOWN then
MoveDownBtnClick(Nil)
else
Handled := False;
end
else if Key = VK_RETURN then
OpenFileMenuItemClick(Nil)
else if Key = VK_DELETE then
RemoveBitBtnClick(Nil)
else if Key = VK_INSERT then
AddBitBtnClick(Nil)
else
Handled := False;
if Handled then
Key := VK_UNKNOWN;
end;
procedure TPackageEditorForm.ItemsTreeViewSelectionChanged(Sender: TObject);
begin
if fUpdateLock>0 then exit;
UpdatePEProperties;
UpdateButtons;
end;
procedure TPackageEditorForm.HelpBitBtnClick(Sender: TObject);
begin
LazarusHelp.ShowHelpForIDEControl(Self);
end;
procedure TPackageEditorForm.InstallClick(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.SetDependencyDefaultFilenameMenuItemClick(Sender: TObject);
begin
SetDependencyDefaultFilename(false);
end;
procedure TPackageEditorForm.SetDependencyPreferredFilenameMenuItemClick(Sender: TObject);
begin
SetDependencyDefaultFilename(true);
end;
procedure TPackageEditorForm.ClearDependencyFilenameMenuItemClick(Sender: TObject);
begin
if LazPackage=nil then exit;
if FSingleSelectedDependency=nil then exit;
if LazPackage.ReadOnly then exit;
if FSingleSelectedDependency.RequiredPackage=nil then exit;
if FSingleSelectedDependency.DefaultFilename='' then exit;
FSingleSelectedDependency.DefaultFilename:='';
FSingleSelectedDependency.PreferDefaultFilename:=false;
LazPackage.Modified:=true;
UpdateRequiredPkgs;
UpdateButtons;
end;
procedure TPackageEditorForm.CollapseDirectoryMenuItemClick(Sender: TObject);
begin
DoCollapseDirectory;
end;
procedure TPackageEditorForm.MoveUpBtnClick(Sender: TObject);
begin
if SortAlphabetically then exit;
if Assigned(FSingleSelectedFile) then
DoMoveCurrentFile(-1)
else if Assigned(FSingleSelectedDependency) then
DoMoveDependency(-1)
end;
procedure TPackageEditorForm.OnIdle(Sender: TObject; var Done: Boolean);
begin
if fUpdateLock>0 then exit;
IdleConnected:=false;
UpdatePending;
end;
procedure TPackageEditorForm.MoveDownBtnClick(Sender: TObject);
begin
if SortAlphabetically then exit;
if Assigned(FSingleSelectedFile) then
DoMoveCurrentFile(1)
else if Assigned(FSingleSelectedDependency) then
DoMoveDependency(1)
end;
procedure TPackageEditorForm.OpenFileMenuItemClick(Sender: TObject);
var
CurFile: TPkgFile;
CurDependency: TPkgDependency;
i: Integer;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
begin
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if GetNodeDataItem(TVNode,NodeData,Item) then begin
if Item is TPkgFile then begin
CurFile:=TPkgFile(Item);
if DoOpenPkgFile(CurFile)<>mrOk then exit;
end else if Item is TPkgDependency then begin
CurDependency:=TPkgDependency(Item);
if PackageEditors.OpenDependency(Self,CurDependency)<>mrOk then exit;
end;
end;
end;
end;
procedure TPackageEditorForm.OptionsBitBtnClick(Sender: TObject);
const
Settings: array[Boolean] of TIDEOptionsEditorSettings = (
[],
[ioesReadOnly]
);
begin
Package1 := LazPackage;
Package1.OnBeforeRead:=PackageEditors.OnBeforeReadPackage;
Package1.OnAfterWrite:=PackageEditors.OnAfterWritePackage;
LazarusIDE.DoOpenIDEOptions(nil,
Format(lisPckEditCompilerOptionsForPackage, [LazPackage.IDAsString]),
[TLazPackage, TPkgCompilerOptions], Settings[LazPackage.ReadOnly]);
UpdateButtons;
UpdateTitle;
UpdateStatusBar;
end;
procedure TPackageEditorForm.PackageEditorFormClose(Sender: TObject;
var CloseAction: TCloseAction);
begin
//debugln(['TPackageEditorForm.PackageEditorFormClose ',Caption]);
if LazPackage=nil then exit;
end;
procedure TPackageEditorForm.PackageEditorFormCloseQuery(Sender: TObject;
var CanClose: boolean);
var
MsgResult: Integer;
begin
//debugln(['TPackageEditorForm.PackageEditorFormCloseQuery ',Caption]);
if (LazPackage<>nil) and (not (lpfDestroying in LazPackage.Flags))
and (not LazPackage.ReadOnly) and LazPackage.Modified then begin
MsgResult:=MessageDlg(lisPkgMangSavePackage,
Format(lisPckEditPackageHasChangedSavePackage, [LazPackage.IDAsString, LineEnding]),
mtConfirmation,[mbYes,mbNo,mbAbort],0);
case MsgResult of
mrYes:
MsgResult:=PackageEditors.SavePackage(LazPackage,false);
mrNo:
LazPackage.UserIgnoreChangeStamp:=LazPackage.ChangeStamp;
end;
if MsgResult=mrAbort then CanClose:=false;
LazPackage.Modified:=false; // clear modified flag, so that it will be closed
end;
//debugln(['TPackageEditorForm.PackageEditorFormCloseQuery CanClose=',CanClose,' ',Caption]);
if CanClose then
Application.ReleaseComponent(Self);
end;
procedure TPackageEditorForm.RegisteredListBoxDrawItem(Control: TWinControl;
Index: Integer; ARect: TRect; State: TOwnerDrawState);
var
CurComponent: TPkgComponent;
CurStr: string;
CurObject: TObject;
TxtH: Integer;
CurIcon: TCustomBitmap;
IconWidth: Integer;
IconHeight: Integer;
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);
FillRect(ARect);
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;
CurFile: TPkgFile;
CurDependency: TPkgDependency;
s: String;
mt: TMsgDlgType;
i: Integer;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
MainUnitSelected: Boolean;
FileWarning: String;
FileCount: Integer;
PkgCount: Integer;
PkgWarning: String;
begin
BeginUdate;
try
ANode:=ItemsTreeView.Selected;
if (ANode=nil) or LazPackage.ReadOnly then begin
UpdateButtons;
exit;
end;
// check selection
MainUnitSelected:=false;
FileWarning:='';
FileCount:=0;
PkgCount:=0;
PkgWarning:='';
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
if NodeData.Removed then continue;
if Item is TPkgFile then begin
CurFile:=TPkgFile(Item);
inc(FileCount);
if CurFile.FileType=pftMainUnit then
MainUnitSelected:=true;
if FileWarning='' then
FileWarning:=Format(lisPckEditRemoveFileFromPackage,
[CurFile.Filename, LineEnding, LazPackage.IDAsString]);
end else if Item is TPkgDependency then begin
CurDependency:=TPkgDependency(Item);
inc(PkgCount);
if PkgWarning='' then
PkgWarning:=Format(lisPckEditRemoveDependencyFromPackage,
[CurDependency.AsString, LineEnding, LazPackage.IDAsString]);
end;
end;
if (FileCount=0) and (PkgCount=0) then begin
UpdateButtons;
exit;
end;
// confirm deletion
if FileCount>0 then begin
s:='';
mt:=mtConfirmation;
if FileCount=1 then
s:=FileWarning
else
s:=Format(lisRemoveFilesFromPackage, [IntToStr(FileCount), LazPackage.
Name]);
if MainUnitSelected then begin
s+=Format(lisWarningThisIsTheMainUnitTheNewMainUnitWillBePas,
[LineEnding+LineEnding, lowercase(LazPackage.Name)]);
mt:=mtWarning;
end;
if IDEMessageDialog(lisPckEditRemoveFile2,s,mt,[mbYes,mbNo])<>mrYes then
exit;
end;
if PkgCount>0 then begin
s:='';
mt:=mtConfirmation;
if PkgCount=1 then
s:=PkgWarning
else
s:=Format(lisRemoveDependenciesFromPackage, [IntToStr(PkgCount),
LazPackage.Name]);
if IDEMessageDialog(lisPckEditRemoveDependencyFromPackage,s,mt,[mbYes,mbNo])<>mrYes then
exit;
end;
// remove
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
if NodeData.Removed then continue;
if Item is TPkgFile then begin
CurFile:=TPkgFile(Item);
LazPackage.RemoveFile(CurFile);
UpdateFiles;
end else if Item is TPkgDependency then begin
CurDependency:=TPkgDependency(Item);
PackageGraph.RemoveDependencyFromPackage(LazPackage,CurDependency,true);
UpdateRequiredPkgs;
end;
end;
finally
EndUpdate;
end;
end;
procedure TPackageEditorForm.EditVirtualUnitMenuItemClick(Sender: TObject);
begin
DoEditVirtualUnit;
end;
procedure TPackageEditorForm.ExpandDirectoryMenuItemClick(Sender: TObject);
begin
DoExpandDirectory;
end;
procedure TPackageEditorForm.FormCreate(Sender: TObject);
begin
FPlugins:=TStringList.Create;
SetupComponents;
SortAlphabetically := EnvironmentOptions.PackageEditorSortAlphabetically;
ShowDirectoryHierarchy := EnvironmentOptions.PackageEditorShowDirHierarchy;
end;
procedure TPackageEditorForm.FormDestroy(Sender: TObject);
var
nt: TPENodeType;
begin
IdleConnected:=true;
FreeAndNil(FNextSelectedPart);
EnvironmentOptions.PackageEditorSortAlphabetically := SortAlphabetically;
EnvironmentOptions.PackageEditorShowDirHierarchy := ShowDirectoryHierarchy;
FilterEdit.ForceFilter('');
for nt:=Low(TPENodeType) to High(TPENodeType) do
FreeNodeData(nt);
if PackageEditorMenuRoot.MenuItem=ItemsPopupMenu.Items then
PackageEditorMenuRoot.MenuItem:=nil;
PackageEditors.DoFreeEditor(LazPackage);
FLazPackage:=nil;
FreeAndNil(FPlugins);
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.ShowMissingFilesMenuItemClick(Sender: TObject);
begin
DoShowMissingFiles;
end;
procedure TPackageEditorForm.UninstallClick(Sender: TObject);
begin
PackageEditors.UninstallPackage(LazPackage);
end;
procedure TPackageEditorForm.UseAllUnitsInDirectoryMenuItemClick(Sender: TObject);
begin
DoUseUnitsInDirectory(true);
end;
procedure TPackageEditorForm.ViewPkgSourceClick(Sender: TObject);
begin
PackageEditors.ViewPkgSource(LazPackage);
end;
procedure TPackageEditorForm.ViewPkgTodosClick(Sender: TObject);
begin
PackageEditors.ViewPkgToDos(LazPackage);
end;
procedure TPackageEditorForm.FreeNodeData(Typ: TPENodeType);
var
NodeData: TPENodeData;
n: TPENodeData;
begin
NodeData:=FFirstNodeData[Typ];
while NodeData<>nil do begin
n:=NodeData;
NodeData:=NodeData.Next;
if Assigned(n.Branch) Then
n.Branch.FreeNodeData(n.Node);
n.Free;
end;
FFirstNodeData[Typ]:=nil;
end;
function TPackageEditorForm.CreateNodeData(Typ: TPENodeType; aName: string;
aRemoved: boolean): TPENodeData;
begin
Result:=TPENodeData.Create(Typ,aName,aRemoved);
Result.Next:=FFirstNodeData[Typ];
FFirstNodeData[Typ]:=Result;
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.UseNoUnitsInDirectoryMenuItemClick(Sender: TObject);
begin
DoUseUnitsInDirectory(false);
end;
procedure TPackageEditorForm.AddBitBtnClick(Sender: TObject);
begin
if LazPackage=nil then exit;
BeginUdate;
try
ShowAddDialog(fLastDlgPage);
finally
EndUpdate;
end;
end;
procedure TPackageEditorForm.AddToUsesPkgSectionCheckBoxChange(Sender: TObject);
var
CurFile: TPkgFile;
i: Integer;
OtherFile: TPkgFile;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
j: Integer;
begin
if LazPackage=nil then exit;
BeginUdate;
try
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
if Item is TPkgFile then begin
CurFile:=TPkgFile(Item);
if not (CurFile.FileType in PkgFileUnitTypes) then continue;
if CurFile.AddToUsesPkgSection=AddToUsesPkgSectionCheckBox.Checked then
continue;
// change flag
CurFile.AddToUsesPkgSection:=AddToUsesPkgSectionCheckBox.Checked;
if (not NodeData.Removed) and CurFile.AddToUsesPkgSection then begin
// mark all other units with the same name as unused
for j:=0 to LazPackage.FileCount-1 do begin
OtherFile:=LazPackage.Files[j];
if (OtherFile<>CurFile)
and (SysUtils.CompareText(OtherFile.Unit_Name,CurFile.Unit_Name)=0) then
OtherFile.AddToUsesPkgSection:=false;
end;
end;
LazPackage.Modified:=true;
UpdateFiles;
end;
end;
finally
EndUpdate;
end;
end;
procedure TPackageEditorForm.AddToProjectClick(Sender: TObject);
begin
if LazPackage=nil then exit;
PackageEditors.AddToProject(LazPackage,false);
end;
procedure TPackageEditorForm.ApplyDependencyButtonClick(Sender: TObject);
var
NewDependency: TPkgDependency;
begin
if LazPackage=nil then exit;
if FSingleSelectedDependency=nil then exit;
if LazPackage.FindDependencyByName(FSingleSelectedDependency.PackageName
)<>FSingleSelectedDependency then exit;
NewDependency:=TPkgDependency.Create;
try
NewDependency.Assign(FSingleSelectedDependency);
// 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, LineEnding]),
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, LineEnding]),
mtError,[mbCancel],0);
exit;
end;
end else begin
NewDependency.Flags:=NewDependency.Flags-[pdfMaxVersion];
end;
PackageGraph.ChangeDependency(FSingleSelectedDependency,NewDependency);
finally
NewDependency.Free;
end;
end;
procedure TPackageEditorForm.CallRegisterProcCheckBoxChange(Sender: TObject);
var
CurFile: TPkgFile;
i: Integer;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
begin
if LazPackage=nil then exit;
BeginUdate;
try
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
if not (Item is TPkgFile) then continue;
CurFile:=TPkgFile(Item);
if not (CurFile.FileType in PkgFileUnitTypes) then continue;
if CurFile.HasRegisterProc=CallRegisterProcCheckBox.Checked then exit;
CurFile.HasRegisterProc:=CallRegisterProcCheckBox.Checked;
if not NodeData.Removed then
LazPackage.Modified:=true;
UpdateFiles;
end;
finally
EndUpdate;
end;
end;
procedure TPackageEditorForm.ChangeFileTypeMenuItemClick(Sender: TObject);
var
CurPFT: TPkgFileType;
CurFile: TPkgFile;
CurItem: TIDEMenuCommand;
i: Integer;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
begin
if LazPackage=nil then exit;
CurItem:=TIDEMenuCommand(Sender);
for CurPFT:=Low(TPkgFileType) to High(TPkgFileType) do begin
if CurItem.Caption=GetPkgFileTypeLocalizedName(CurPFT) then begin
BeginUdate;
try
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
if not (Item is TPkgFile) then continue;
CurFile:=TPkgFile(Item);
if CurFile.FileType=CurPFT then continue;
if (not FilenameIsPascalUnit(CurFile.Filename))
and (CurPFT in PkgFileUnitTypes) then
continue;
CurFile.FileType:=CurPFT;
if not NodeData.Removed then
LazPackage.Modified:=true;
UpdateFiles;
end;
finally
EndUpdate;
end;
exit;
end;
end;
end;
procedure TPackageEditorForm.CleanDependenciesMenuItemClick(Sender: TObject);
var
ListOfNodeInfos: TObjectList;
i: Integer;
Info: TCPDNodeInfo;
Dependency: TPkgDependency;
begin
if LazPackage=nil then exit;
BeginUdate;
ListOfNodeInfos:=nil;
try
if ShowCleanPkgDepDlg(LazPackage,ListOfNodeInfos)<>mrOk then exit;
for i:=0 to ListOfNodeInfos.Count-1 do begin
Info:=TCPDNodeInfo(ListOfNodeInfos[i]);
Dependency:=LazPackage.FindDependencyByName(Info.Dependency);
if Dependency<>nil then
PackageGraph.RemoveDependencyFromPackage(LazPackage,Dependency,true);
end;
finally
ListOfNodeInfos.Free;
EndUpdate;
end;
end;
procedure TPackageEditorForm.CompileAllCleanClick(Sender: TObject);
begin
if LazPackage=nil then exit;
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.CreateMakefileClick(Sender: TObject);
begin
PackageEditors.CreateMakefile(LazPackage);
end;
procedure TPackageEditorForm.CreateFpmakeFileClick(Sender: TObject);
begin
debugln(['TPackageEditorForm.CreateFpmakeFileClick AAA1']);
PackageEditors.CreateFpmakeFile(LazPackage);
end;
procedure TPackageEditorForm.DirectoryHierarchyButtonClick(Sender: TObject);
begin
ShowDirectoryHierarchy:=DirectoryHierarchyButton.Down;
end;
procedure TPackageEditorForm.DisableI18NForLFMCheckBoxChange(Sender: TObject);
var
CurFile: TPkgFile;
i: Integer;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
begin
if LazPackage=nil then exit;
BeginUdate;
try
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
if not (Item is TPkgFile) then continue;
CurFile:=TPkgFile(Item);
if not (CurFile.FileType in PkgFileUnitTypes) then continue;
if CurFile.DisableI18NForLFM=DisableI18NForLFMCheckBox.Checked then
continue;
CurFile.DisableI18NForLFM:=DisableI18NForLFMCheckBox.Checked;
if not NodeData.Removed then
LazPackage.Modified:=true;
UpdateFiles;
end;
finally
EndUpdate;
end;
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 begin
Name:=Name+'___off___';
exit;
end;
Name:=PackageEditorWindowPrefix+LazPackage.Name;
FLazPackage.Editor:=Self;
// update components
UpdateAll(true);
end;
procedure TPackageEditorForm.SetupComponents;
function CreateToolButton(AName, ACaption, AHint, AImageName: String; AOnClick: TNotifyEvent): TToolButton;
begin
Result := TToolButton.Create(Self);
Result.Name := AName;
Result.Caption := ACaption;
Result.Hint := AHint;
if AImageName <> '' then
Result.ImageIndex := IDEImages.LoadImage(16, AImageName);
Result.ShowHint := True;
Result.OnClick := AOnClick;
Result.AutoSize := True;
Result.Parent := ToolBar;
end;
function CreateDivider: TToolButton;
begin
Result := TToolButton.Create(Self);
Result.Style := tbsDivider;
Result.AutoSize := True;
Result.Parent := ToolBar;
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');
ImageIndexIssues := IDEImages.LoadImage(16, 'pkg_issues');
ImageIndexText := IDEImages.LoadImage(16, 'pkg_text');
ImageIndexBinary := IDEImages.LoadImage(16, 'pkg_binary');
ImageIndexConflict := IDEImages.LoadImage(16, 'pkg_conflict');
ImageIndexDirectory := IDEImages.LoadImage(16, 'pkg_files');
ItemsTreeView.Images := IDEImages.Images_16;
ToolBar.Images := IDEImages.Images_16;
FilterEdit.OnGetImageIndex:=@OnTreeViewGetImageIndex;
SaveBitBtn := CreateToolButton('SaveBitBtn', lisMenuSave, lisPckEditSavePackage, 'laz_save', @SaveBitBtnClick);
CompileBitBtn := CreateToolButton('CompileBitBtn', lisCompile, lisPckEditCompilePackage, 'pkg_compile', @CompileBitBtnClick);
UseBitBtn := CreateToolButton('UseBitBtn', lisPckEditInstall, lisPckEditInstallPackageInTheIDE, 'pkg_install', nil);
CreateDivider;
AddBitBtn := CreateToolButton('AddBitBtn', lisAdd, lisPckEditAddAnItem, 'laz_add', @AddBitBtnClick);
RemoveBitBtn := CreateToolButton('RemoveBitBtn', lisRemove, lisPckEditRemoveSelectedItem, 'laz_delete', @RemoveBitBtnClick);
CreateDivider;
OptionsBitBtn := CreateToolButton('OptionsBitBtn', dlgFROpts, lisPckEditEditGeneralOptions, 'pkg_properties', @OptionsBitBtnClick);
HelpBitBtn := CreateToolButton('HelpBitBtn', GetButtonCaption(idButtonHelp), lisPkgEdThereAreMoreFunctionsInThePopupmenu, 'menu_help', @HelpBitBtnClick);
MoreBitBtn := CreateToolButton('MoreBitBtn', lisMoreSub, lisPkgEdThereAreMoreFunctionsInThePopupmenu, '', nil);
MoreBitBtn.DropdownMenu := MorePopupMenu;
// Buttons on FilterPanel
OpenButton.LoadGlyphFromResourceName(HInstance, 'laz_open');
OpenButton.Hint:=lisOpenFile2;
SortAlphabeticallyButton.Hint:=lisPESortFilesAlphabetically;
SortAlphabeticallyButton.LoadGlyphFromResourceName(HInstance, 'pkg_sortalphabetically');
DirectoryHierarchyButton.Hint:=lisPEShowDirectoryHierarchy;
DirectoryHierarchyButton.LoadGlyphFromResourceName(HInstance, 'pkg_hierarchical');
// Up / Down buttons
MoveUpBtn.LoadGlyphFromResourceName(HInstance, 'arrow_up');
MoveDownBtn.LoadGlyphFromResourceName(HInstance, 'arrow_down');
MoveUpBtn.Hint:=lisMoveSelectedUp;
MoveDownBtn.Hint:=lisMoveSelectedDown;
ItemsTreeView.BeginUpdate;
FFilesNode:=ItemsTreeView.Items.Add(nil, dlgEnvFiles);
FFilesNode.ImageIndex:=ImageIndexFiles;
FFilesNode.SelectedIndex:=FFilesNode.ImageIndex;
FRequiredPackagesNode:=ItemsTreeView.Items.Add(nil, lisPckEditRequiredPackages);
FRequiredPackagesNode.ImageIndex:=ImageIndexRequired;
FRequiredPackagesNode.SelectedIndex:=FRequiredPackagesNode.ImageIndex;
ItemsTreeView.EndUpdate;
PropsGroupBox.Caption:=lisPckEditFileProperties;
CallRegisterProcCheckBox.Caption:=lisPckEditRegisterUnit;
CallRegisterProcCheckBox.Hint:=Format(lisPckEditCallRegisterProcedureOfSelectedUnit, ['"', '"']);
AddToUsesPkgSectionCheckBox.Caption:=lisPkgMangUseUnit;
AddToUsesPkgSectionCheckBox.Hint:=lisPkgMangAddUnitToUsesClauseOfPackageDisableThisOnlyForUnit;
DisableI18NForLFMCheckBox.Caption:=lisPckDisableI18NOfLfm;
DisableI18NForLFMCheckBox.Hint:=lisPckWhenTheFormIsSavedTheIDECanStoreAllTTranslateString;
UseMinVersionCheckBox.Caption:=lisPckEditMinimumVersion;
UseMaxVersionCheckBox.Caption:=lisPckEditMaximumVersion;
ApplyDependencyButton.Caption:=lisPckEditApplyChanges;
RegisteredPluginsGroupBox.Caption:=lisPckEditRegisteredPlugins;
RegisteredListBox.ItemHeight:=ComponentPaletteImageHeight;
FDirSummaryLabel:=TLabel.Create(Self);
with FDirSummaryLabel do
begin
Name:='DirSummaryLabel';
Parent:=PropsGroupBox;
end;
end;
procedure TPackageEditorForm.SetDependencyDefaultFilename(AsPreferred: boolean);
var
NewFilename: String;
begin
if LazPackage=nil then exit;
if FSingleSelectedDependency=nil then exit;
if LazPackage.FindDependencyByName(FSingleSelectedDependency.PackageName
)<>FSingleSelectedDependency then exit;
if LazPackage.ReadOnly then exit;
if FSingleSelectedDependency.RequiredPackage=nil then exit;
NewFilename:=FSingleSelectedDependency.RequiredPackage.Filename;
if (NewFilename=FSingleSelectedDependency.DefaultFilename)
and (FSingleSelectedDependency.PreferDefaultFilename=AsPreferred) then
exit;
BeginUdate;
try
FSingleSelectedDependency.DefaultFilename:=NewFilename;
FSingleSelectedDependency.PreferDefaultFilename:=AsPreferred;
LazPackage.Modified:=true;
UpdateRequiredPkgs;
UpdateButtons;
finally
EndUpdate;
end;
end;
procedure TPackageEditorForm.SetIdleConnected(AValue: boolean);
begin
if csDestroying in ComponentState then
AValue:=false;
if FIdleConnected=AValue then Exit;
FIdleConnected:=AValue;
if IdleConnected then
Application.AddOnIdleHandler(@OnIdle)
else
Application.RemoveOnIdleHandler(@OnIdle);
end;
procedure TPackageEditorForm.SetShowDirectoryHierarchy(const AValue: boolean);
begin
//debugln(['TPackageEditorForm.SetShowDirectoryHierachy Old=',FShowDirectoryHierarchy,' New=',AValue]);
if FShowDirectoryHierarchy=AValue then exit;
FShowDirectoryHierarchy:=AValue;
DirectoryHierarchyButton.Down:=FShowDirectoryHierarchy;
FilterEdit.ShowDirHierarchy:=FShowDirectoryHierarchy;
FilterEdit.InvalidateFilter;
end;
procedure TPackageEditorForm.SetSortAlphabetically(const AValue: boolean);
begin
if FSortAlphabetically=AValue then exit;
FSortAlphabetically:=AValue;
SortAlphabeticallyButton.Down:=FSortAlphabetically;
FilterEdit.SortData:=FSortAlphabetically;
FilterEdit.InvalidateFilter;
end;
procedure TPackageEditorForm.UpdateAll(Immediately: boolean);
begin
if csDestroying in ComponentState then exit;
if LazPackage=nil then exit;
Name:=PackageEditorWindowPrefix+LazPackage.Name;
fFlags:=fFlags+[
pefNeedUpdateTitle,
pefNeedUpdateButtons,
pefNeedUpdateFiles,
pefNeedUpdateRequiredPkgs,
pefNeedUpdateProperties,
pefNeedUpdateApplyDependencyButton,
pefNeedUpdateStatusBar];
UpdatePending;
end;
function TPackageEditorForm.ShowAddDialog(var DlgPage: TAddToPkgType): TModalResult;
var
IgnoreUnitPaths, IgnoreIncPaths: TFilenameToStringTree;
function PkgDependsOn(PkgName: string): boolean;
begin
if PkgName='' then exit(false);
Result:=PackageGraph.FindDependencyRecursively(LazPackage.FirstRequiredDependency,PkgName)<>nil;
end;
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 FileExistsUTF8(NewLFMFilename)
and (LazPackage.FindPkgFile(NewLFMFilename,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 FileExistsUTF8(NewLRSFilename)
and (LazPackage.FindPkgFile(NewLRSFilename,true,false)=nil) then
LazPackage.AddFile(NewLRSFilename,'',pftLRS,[],cpNormal)
else
NewLRSFilename:='';
end;
ExtendUnitIncPathForNewUnit(AddParams.UnitFilename,NewLRSFilename,
IgnoreUnitPaths);
// add unit file
with AddParams do
LazPackage.AddFile(UnitFilename,Unit_Name,FileType,PkgFileFlags,cpNormal);
FreeAndNil(FNextSelectedPart);
FNextSelectedPart:=TPENodeData.Create(penFile,AddParams.UnitFilename,false);
PackageEditors.DeleteAmbiguousFiles(LazPackage,AddParams.UnitFilename);
UpdateFiles;
end;
procedure AddVirtualUnit(AddParams: TAddToPkgResult);
begin
with AddParams do
LazPackage.AddFile(UnitFilename,Unit_Name,FileType,PkgFileFlags,cpNormal);
FreeAndNil(FNextSelectedPart);
FNextSelectedPart:=TPENodeData.Create(penFile,AddParams.UnitFilename,false);
PackageEditors.DeleteAmbiguousFiles(LazPackage,AddParams.UnitFilename);
UpdateFiles;
end;
procedure AddNewComponent(AddParams: TAddToPkgResult);
begin
ExtendUnitIncPathForNewUnit(AddParams.UnitFilename,'',IgnoreUnitPaths);
// add file
with AddParams do
LazPackage.AddFile(UnitFilename,Unit_Name,FileType,PkgFileFlags,cpNormal);
FreeAndNil(FNextSelectedPart);
FNextSelectedPart:=TPENodeData.Create(penFile,AddParams.UnitFilename,false);
// add dependency
if (AddParams.Dependency<>nil)
and (not PkgDependsOn(AddParams.Dependency.PackageName)) then
PackageGraph.AddDependencyToPackage(LazPackage,AddParams.Dependency);
if (AddParams.IconFile<>'')
and (not PkgDependsOn('LCL')) then
PackageGraph.AddDependencyToPackage(LazPackage,PackageGraph.LCLPackage);
PackageEditors.DeleteAmbiguousFiles(LazPackage,AddParams.UnitFilename);
// open file in editor
PackageEditors.CreateNewFile(Self,AddParams);
UpdateFiles;
end;
procedure AddRequiredPkg(AddParams: TAddToPkgResult);
begin
// add dependency
PackageGraph.AddDependencyToPackage(LazPackage,AddParams.Dependency);
FreeAndNil(FNextSelectedPart);
FNextSelectedPart:=TPENodeData.Create(penDependency,
AddParams.Dependency.PackageName,false);
UpdateRequiredPkgs;
end;
procedure AddFile(AddParams: TAddToPkgResult);
begin
// add file
with AddParams do begin
if (CompareFileExt(UnitFilename,'.inc',false)=0)
or (CompareFileExt(UnitFilename,'.lrs',false)=0) then
ExtendIncPathForNewIncludeFile(UnitFilename,IgnoreIncPaths);
LazPackage.AddFile(UnitFilename,Unit_Name,FileType,PkgFileFlags,cpNormal);
end;
FreeAndNil(FNextSelectedPart);
FNextSelectedPart:=TPENodeData.Create(penFile,AddParams.UnitFilename,false);
UpdateFiles;
end;
procedure AddNewFile(AddParams: TAddToPkgResult);
var
NewFilename: String;
DummyResult: TModalResult;
NewFileType: TPkgFileType;
NewPkgFileFlags: TPkgFileFlags;
Desc: TProjectFileDescriptor;
NewUnitName: String;
HasRegisterProc: Boolean;
begin
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);
FreeAndNil(FNextSelectedPart);
FNextSelectedPart:=TPENodeData.Create(penFile,NewFilename,false);
UpdateFiles;
end;
end;
end;
var
AddParams: TAddToPkgResult;
OldParams: TAddToPkgResult;
begin
if LazPackage.ReadOnly then begin
UpdateButtons;
exit(mrCancel);
end;
Result:=ShowAddToPackageDlg(LazPackage,AddParams,PackageEditors.OnGetIDEFileInfo,
PackageEditors.OnGetUnitRegisterInfo,DlgPage);
fLastDlgPage:=DlgPage;
if Result<>mrOk then exit;
PackageGraph.BeginUpdate(false);
IgnoreUnitPaths:=nil;
IgnoreIncPaths:=nil;
try
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;
finally
IgnoreUnitPaths.Free;
IgnoreIncPaths.Free;
PackageGraph.EndUpdate;
end;
end;
procedure TPackageEditorForm.BeginUdate;
begin
inc(fUpdateLock);
end;
procedure TPackageEditorForm.EndUpdate;
begin
if fUpdateLock=0 then
RaiseException('');
dec(fUpdateLock);
UpdatePending;
end;
procedure TPackageEditorForm.UpdateTitle(Immediately: boolean);
var
NewCaption: String;
begin
if not CanUpdate(pefNeedUpdateTitle) then exit;
NewCaption:=Format(lisPckEditPackage, [FLazPackage.Name]);
if LazPackage.Modified then
NewCaption:=NewCaption+'*';
Caption:=NewCaption;
end;
procedure TPackageEditorForm.UpdateButtons(Immediately: boolean);
var
i: Integer;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
Writable: Boolean;
ActiveFileCnt: Integer;
ActiveDepCount: Integer;
FileCount: Integer;
DepCount: Integer;
begin
if not CanUpdate(pefNeedUpdateButtons) then exit;
FileCount:=0;
DepCount:=0;
ActiveFileCnt:=0;
ActiveDepCount:=0;
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
if Item is TPkgFile then begin
inc(FileCount);
if not NodeData.Removed then
inc(ActiveFileCnt);
end else if Item is TPkgDependency then begin
inc(DepCount);
if not NodeData.Removed then
inc(ActiveDepCount);
end;
end;
Writable:=not LazPackage.ReadOnly;
SaveBitBtn.Enabled:=Writable and (LazPackage.IsVirtual or LazPackage.Modified);
CompileBitBtn.Enabled:=(not LazPackage.IsVirtual) and LazPackage.CompilerOptions.HasCommands;
AddBitBtn.Enabled:=Writable;
RemoveBitBtn.Enabled:=Writable and (ActiveFileCnt+ActiveDepCount>0);
OpenButton.Enabled:=(FileCount+DepCount>0);
UseBitBtn.Caption:=lisUseSub;
UseBitBtn.Hint:=lisClickToSeeThePossibleUses;
UseBitBtn.OnClick:=nil;
UseBitBtn.DropdownMenu:=UsePopupMenu;
OptionsBitBtn.Enabled:=true;
end;
function TPackageEditorForm.OnTreeViewGetImageIndex(Str: String; Data: TObject;
var AIsEnabled: Boolean): Integer;
var
PkgFile: TPkgFile;
Item: TObject;
PkgDependency: TPkgDependency;
NodeData: TPENodeData;
begin
Result:=-1;
if not (Data is TPENodeData) then exit;
NodeData:=TPENodeData(Data);
Item:=GetNodeItem(NodeData);
if Item=nil then exit;
if Item is TPkgFile then begin
PkgFile:=TPkgFile(Item);
case PkgFile.FileType of
pftUnit,pftVirtualUnit,pftMainUnit:
if PkgFile.HasRegisterProc then
Result:=ImageIndexRegisterUnit
else
Result:=ImageIndexUnit;
pftLFM: Result:=ImageIndexLFM;
pftLRS: Result:=ImageIndexLRS;
pftInclude: Result:=ImageIndexInclude;
pftIssues: Result:=ImageIndexIssues;
pftText: Result:=ImageIndexText;
pftBinary: Result:=ImageIndexBinary;
else
Result:=-1;
end;
end
else if Item is TPkgDependency then begin
PkgDependency:=TPkgDependency(Item);
if PkgDependency.Removed then
Result:=ImageIndexRemovedRequired
else if PkgDependency.LoadPackageResult=lprSuccess then
Result:=ImageIndexRequired
else
Result:=ImageIndexConflict;
end;
end;
procedure TPackageEditorForm.UpdatePending;
begin
if pefNeedUpdateTitle in fFlags then
UpdateTitle(true);
if pefNeedUpdateButtons in fFlags then
UpdateButtons(true);
if pefNeedUpdateFiles in fFlags then
UpdateFiles(true);
if pefNeedUpdateRequiredPkgs in fFlags then
UpdateRequiredPkgs(true);
if pefNeedUpdateProperties in fFlags then
UpdatePEProperties(true);
if pefNeedUpdateApplyDependencyButton in fFlags then
UpdateApplyDependencyButton(true);
if pefNeedUpdateStatusBar in fFlags then
UpdateStatusBar(true);
end;
function TPackageEditorForm.CanUpdate(Flag: TPEFlag): boolean;
begin
Result:=false;
if csDestroying in ComponentState then exit;
if LazPackage=nil then exit;
if fUpdateLock>0 then begin
Include(fFlags,Flag);
IdleConnected:=true;
Result:=false;
end else begin
Exclude(fFlags,Flag);
Result:=true;
end;
end;
procedure TPackageEditorForm.UpdateFiles(Immediately: boolean);
var
i: Integer;
CurFile: TPkgFile;
FilesBranch, RemovedBranch: TTreeFilterBranch;
Filename: String;
NodeData: TPENodeData;
OldFilter : String;
begin
if not CanUpdate(pefNeedUpdateFiles) then exit;
OldFilter := FilterEdit.ForceFilter('');
// files belonging to package
FilesBranch:=FilterEdit.GetBranch(FFilesNode);
FreeNodeData(penFile);
FilesBranch.Clear;
FilterEdit.SelectedPart:=nil;
FilterEdit.ShowDirHierarchy:=ShowDirectoryHierarchy;
FilterEdit.SortData:=SortAlphabetically;
FilterEdit.ImageIndexDirectory:=ImageIndexDirectory;
// collect and sort files
for i:=0 to LazPackage.FileCount-1 do begin
CurFile:=LazPackage.Files[i];
NodeData:=CreateNodeData(penFile,CurFile.Filename,false);
Filename:=CurFile.GetShortFilename(true);
if Filename='' then continue;
if (FNextSelectedPart<>nil) and (FNextSelectedPart.Typ=penFile)
and (FNextSelectedPart.Name=NodeData.Name)
then
FilterEdit.SelectedPart:=NodeData;
FilesBranch.AddNodeData(Filename, NodeData, CurFile.Filename);
end;
if (FNextSelectedPart<>nil) and (FNextSelectedPart.Typ=penFile) then
FreeAndNil(FNextSelectedPart);
// removed files
if LazPackage.RemovedFilesCount>0 then begin
// Create root node for removed dependencies if not done yet.
if FRemovedFilesNode=nil then begin
FRemovedFilesNode:=ItemsTreeView.Items.Add(FRequiredPackagesNode,
lisPckEditRemovedFiles);
FRemovedFilesNode.ImageIndex:=ImageIndexRemovedFiles;
FRemovedFilesNode.SelectedIndex:=FRemovedFilesNode.ImageIndex;
end;
RemovedBranch:=FilterEdit.GetBranch(FRemovedFilesNode);
RemovedBranch.Clear;
for i:=0 to LazPackage.RemovedFilesCount-1 do begin
CurFile:=LazPackage.RemovedFiles[i];
NodeData:=CreateNodeData(penFile,CurFile.Filename,true);
RemovedBranch.AddNodeData(CurFile.GetShortFilename(true), NodeData);
end;
end else begin
// No more removed files left -> delete the root node
if FRemovedFilesNode<>nil then begin
FilterEdit.DeleteBranch(FRemovedFilesNode);
FreeAndNil(FRemovedFilesNode);
end;
end;
FilterEdit.Filter := OldFilter; // This triggers ApplyFilter
FilterEdit.InvalidateFilter;
UpdatePEProperties(true);
end;
procedure TPackageEditorForm.UpdateRequiredPkgs(Immediately: boolean);
var
CurDependency: TPkgDependency;
RequiredBranch, RemovedBranch: TTreeFilterBranch;
CurNodeText, aFilename, OldFilter: String;
NodeData: TPENodeData;
begin
if not CanUpdate(pefNeedUpdateRequiredPkgs) then exit;
OldFilter := FilterEdit.ForceFilter('');
// required packages
RequiredBranch:=FilterEdit.GetBranch(FRequiredPackagesNode);
FreeNodeData(penDependency);
RequiredBranch.Clear;
CurDependency:=LazPackage.FirstRequiredDependency;
FilterEdit.SelectedPart:=nil;
while CurDependency<>nil do begin
CurNodeText:=CurDependency.AsString;
if CurDependency.DefaultFilename<>'' then begin
aFilename:=CurDependency.MakeFilenameRelativeToOwner(CurDependency.DefaultFilename);
if CurDependency.PreferDefaultFilename then
CurNodeText:=CurNodeText+' in '+aFilename // like the 'in' keyword in uses section
else
CurNodeText:=Format(lisPckEditDefault, [CurNodeText, aFilename]);
end;
NodeData:=CreateNodeData(penDependency,CurDependency.PackageName,false);
if (FNextSelectedPart<>nil) and (FNextSelectedPart.Typ=penDependency)
and (FNextSelectedPart.Name=NodeData.Name)
then
FilterEdit.SelectedPart:=NodeData;
RequiredBranch.AddNodeData(CurNodeText, NodeData);
CurDependency:=CurDependency.NextRequiresDependency;
end;
if (FNextSelectedPart<>nil) and (FNextSelectedPart.Typ=penDependency) then
FreeAndNil(FNextSelectedPart);
// removed required packages
CurDependency:=LazPackage.FirstRemovedDependency;
if CurDependency<>nil then begin
if FRemovedRequiredNode=nil then begin
FRemovedRequiredNode:=ItemsTreeView.Items.Add(nil,lisPckEditRemovedRequiredPackages);
FRemovedRequiredNode.ImageIndex:=ImageIndexRemovedRequired;
FRemovedRequiredNode.SelectedIndex:=FRemovedRequiredNode.ImageIndex;
end;
RemovedBranch:=FilterEdit.GetBranch(FRemovedRequiredNode);
RemovedBranch.Clear;
while CurDependency<>nil do begin
NodeData:=CreateNodeData(penDependency,CurDependency.PackageName,true);
RemovedBranch.AddNodeData(CurDependency.AsString, NodeData);
CurDependency:=CurDependency.NextRequiresDependency;
end;
end else begin
if FRemovedRequiredNode<>nil then begin
FilterEdit.DeleteBranch(FRemovedRequiredNode);
FreeAndNil(FRemovedRequiredNode);
end;
end;
FNextSelectedPart:=nil;
FilterEdit.Filter := OldFilter; // This triggers ApplyFilter
FilterEdit.InvalidateFilter;
UpdatePEProperties(true);
end;
procedure TPackageEditorForm.UpdatePEProperties(Immediately: boolean);
type
TMultiBool = (mubNone, mubAllTrue, mubAllFalse, mubMixed);
procedure MergeMultiBool(var b: TMultiBool; NewValue: boolean);
begin
case b of
mubNone: if NewValue then b:=mubAllTrue else b:=mubAllFalse;
mubAllTrue: if not NewValue then b:=mubMixed;
mubAllFalse: if NewValue then b:=mubMixed;
mubMixed: ;
end;
end;
procedure SetCheckBox(Box: TCheckBox; aVisible: boolean; State: TMultiBool);
begin
Box.Visible:=aVisible;
case State of
mubAllTrue:
begin
Box.State:=cbChecked;
Box.AllowGrayed:=false;
end;
mubAllFalse:
begin
Box.State:=cbUnchecked;
Box.AllowGrayed:=false;
end;
mubMixed:
begin
Box.AllowGrayed:=true;
Box.State:=cbGrayed;
end;
end;
end;
var
CurFile: TPkgFile;
CurDependency: TPkgDependency;
CurComponent: TPkgComponent;
CurLine, CurFilename: string;
i, j: Integer;
NodeData: TPENodeData;
Item: TObject;
SelFileCount: Integer;
SelDepCount: Integer;
SelHasRegisterProc: TMultiBool;
SelAddToUsesPkgSection: TMultiBool;
SelDisableI18NForLFM: TMultiBool;
SelUnitCount: Integer;
SelDirCount: Integer;
SelHasLFMCount: Integer;
OnlyFilesSelected: Boolean;
OnlyFilesWithUnitsSelected: Boolean;
aVisible: Boolean;
TVNode: TTreeNode;
SingleSelectedDirectory: TTreeNode;
SingleSelectedRemoved: Boolean;
SingleSelected: TTreeNode;
FileCount: integer;
HasRegisterProcCount: integer;
AddToUsesPkgSectionCount: integer;
begin
if not CanUpdate(pefNeedUpdateProperties) then exit;
FPlugins.Clear;
// check selection
FSingleSelectedDependency:=nil;
FSingleSelectedFile:=nil;
SingleSelectedDirectory:=nil;
SingleSelectedRemoved:=false;
SingleSelected:=nil;
SelFileCount:=0;
SelDepCount:=0;
SelHasRegisterProc:=mubNone;
SelAddToUsesPkgSection:=mubNone;
SelDisableI18NForLFM:=mubNone;
SelUnitCount:=0;
SelHasLFMCount:=0;
SelDirCount:=0;
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if GetNodeDataItem(TVNode,NodeData,Item) then begin
if Item is TPkgFile then begin
CurFile:=TPkgFile(Item);
inc(SelFileCount);
FSingleSelectedFile:=CurFile;
SingleSelected:=TVNode;
SingleSelectedRemoved:=NodeData.Removed;
MergeMultiBool(SelHasRegisterProc,CurFile.HasRegisterProc);
if CurFile.FileType in PkgFileUnitTypes then begin
inc(SelUnitCount);
MergeMultiBool(SelAddToUsesPkgSection,CurFile.AddToUsesPkgSection);
if (CurFile.FileType in PkgFileRealUnitTypes) then
begin
CurFilename:=CurFile.GetFullFilename;
if FilenameIsAbsolute(CurFilename)
and FileExistsCached(ChangeFileExt(CurFilename,'.lfm'))
then begin
inc(SelHasLFMCount);
MergeMultiBool(SelDisableI18NForLFM,CurFile.DisableI18NForLFM);
end;
end;
// fetch all registered plugins
for j:=0 to CurFile.ComponentCount-1 do begin
CurComponent:=CurFile.Components[j];
CurLine:=CurComponent.ComponentClass.ClassName;
FPlugins.AddObject(CurLine,CurComponent);
end;
end;
end else if Item is TPkgDependency then begin
inc(SelDepCount);
CurDependency:=TPkgDependency(Item);
FSingleSelectedDependency:=CurDependency;
SingleSelected:=TVNode;
SingleSelectedRemoved:=NodeData.Removed;
end;
end else if IsDirectoryNode(TVNode) or (TVNode=FFilesNode) then begin
inc(SelDirCount);
SingleSelectedDirectory:=TVNode;
SingleSelected:=TVNode;
end;
end;
if (SelFileCount+SelDepCount+SelDirCount>1) then begin
// it is a multi selection
FSingleSelectedFile:=nil;
FSingleSelectedDependency:=nil;
SingleSelectedDirectory:=nil;
SingleSelected:=nil;
end;
OnlyFilesSelected:=(SelFileCount>0) and (SelDepCount=0) and (SelDirCount=0);
OnlyFilesWithUnitsSelected:=OnlyFilesSelected and (SelUnitCount>0);
//debugln(['TPackageEditorForm.UpdatePEProperties SelFileCount=',SelFileCount,' SelDepCount=',SelDepCount,' SelDirCount=',SelDirCount,' SelUnitCount=',SelUnitCount]);
//debugln(['TPackageEditorForm.UpdatePEProperties FSingleSelectedFile=',FSingleSelectedFile<>nil,' FSingleSelectedDependency=',FSingleSelectedDependency<>nil,' SingleSelectedDirectory=',SingleSelectedDirectory<>nil]);
DisableAlign;
try
// move up/down (only single selection)
aVisible:=(not (SortAlphabetically or SingleSelectedRemoved))
and ((FSingleSelectedFile<>nil) or (FSingleSelectedDependency<>nil));
MoveUpBtn.Enabled :=aVisible and Assigned(SingleSelected.GetPrevVisibleSibling);
MoveDownBtn.Enabled:=aVisible and Assigned(SingleSelected.GetNextVisibleSibling);
// Min/Max version of dependency (only single selection)
aVisible:=FSingleSelectedDependency<>nil;
UseMinVersionCheckBox.Visible:=aVisible;
MinVersionEdit.Visible:=aVisible;
UseMaxVersionCheckBox.Visible:=aVisible;
MaxVersionEdit.Visible:=aVisible;
ApplyDependencyButton.Visible:=aVisible;
// 'RegisterProc' of files (supports multi selection)
SetCheckBox(CallRegisterProcCheckBox,OnlyFilesWithUnitsSelected,
SelHasRegisterProc);
CallRegisterProcCheckBox.Enabled:=(not LazPackage.ReadOnly);
// 'Add to uses' of files (supports multi selection)
SetCheckBox(AddToUsesPkgSectionCheckBox,OnlyFilesWithUnitsSelected,
SelAddToUsesPkgSection);
AddToUsesPkgSectionCheckBox.Enabled:=(not LazPackage.ReadOnly);
// disable i18n for lfm (supports multi selection)
SetCheckBox(DisableI18NForLFMCheckBox,
OnlyFilesWithUnitsSelected and (SelHasLFMCount>0) and LazPackage.EnableI18N
and LazPackage.EnableI18NForLFM,
SelDisableI18NForLFM);
DisableI18NForLFMCheckBox.Enabled:=(not LazPackage.ReadOnly);
// registered plugins (supports multi selection)
RegisteredPluginsGroupBox.Visible:=OnlyFilesWithUnitsSelected;
RegisteredPluginsGroupBox.Enabled:=(not LazPackage.ReadOnly);
if not RegisteredPluginsGroupBox.Visible then
FPlugins.Clear;
RegisteredListBox.Items.Assign(FPlugins);
// directory summary (only single selection)
FDirSummaryLabel.Visible:=(SelFileCount=0) and (SelDepCount=0) and (SelDirCount=1);
if SelFileCount>0 then begin
PropsGroupBox.Enabled:=true;
PropsGroupBox.Caption:=lisPckEditFileProperties;
end
else if FSingleSelectedDependency<>nil then begin
PropsGroupBox.Enabled:=not SingleSelectedRemoved;
PropsGroupBox.Caption:=lisPckEditDependencyProperties;
UseMinVersionCheckBox.Checked:=pdfMinVersion in FSingleSelectedDependency.Flags;
MinVersionEdit.Text:=FSingleSelectedDependency.MinVersion.AsString;
MinVersionEdit.Enabled:=pdfMinVersion in FSingleSelectedDependency.Flags;
UseMaxVersionCheckBox.Checked:=pdfMaxVersion in FSingleSelectedDependency.Flags;
MaxVersionEdit.Text:=FSingleSelectedDependency.MaxVersion.AsString;
MaxVersionEdit.Enabled:=pdfMaxVersion in FSingleSelectedDependency.Flags;
UpdateApplyDependencyButton;
end
else if SingleSelectedDirectory<>nil then begin
PropsGroupBox.Enabled:=true;
GetDirectorySummary(SingleSelectedDirectory,
FileCount,HasRegisterProcCount,AddToUsesPkgSectionCount);
FDirSummaryLabel.Caption:=Format(
lisFilesHasRegisterProcedureInPackageUsesSection, [IntToStr(FileCount),
IntToStr(HasRegisterProcCount), IntToStr(AddToUsesPkgSectionCount)]);
end
else begin
PropsGroupBox.Enabled:=false;
end;
finally
EnableAlign;
end;
end;
procedure TPackageEditorForm.UpdateApplyDependencyButton(Immediately: boolean);
var
DependencyChanged: Boolean;
AVersion: TPkgVersion;
i: Integer;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
begin
if not CanUpdate(pefNeedUpdateApplyDependencyButton) then exit;
FSingleSelectedDependency:=nil;
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
TVNode:=ItemsTreeView.Selections[i];
if not GetNodeDataItem(TVNode,NodeData,Item) then continue;
if Item is TPkgFile then begin
FSingleSelectedDependency:=nil;
break;
end else if Item is TPkgDependency then begin
if FSingleSelectedDependency<>nil then begin
FSingleSelectedDependency:=nil;
break;
end;
FSingleSelectedDependency:=TPkgDependency(Item);
end;
end;
DependencyChanged:=false;
if (FSingleSelectedDependency<>nil) then begin
// check min version
if UseMinVersionCheckBox.Checked<>(pdfMinVersion in FSingleSelectedDependency.Flags) then
DependencyChanged:=true;
if UseMinVersionCheckBox.Checked then begin
AVersion:=TPkgVersion.Create;
if AVersion.ReadString(MinVersionEdit.Text)
and (AVersion.Compare(FSingleSelectedDependency.MinVersion)<>0) then
DependencyChanged:=true;
AVersion.Free;
end;
// check max version
if UseMaxVersionCheckBox.Checked<>(pdfMaxVersion in FSingleSelectedDependency.Flags) then
DependencyChanged:=true;
if UseMaxVersionCheckBox.Checked then begin
AVersion:=TPkgVersion.Create;
if AVersion.ReadString(MaxVersionEdit.Text)
and (AVersion.Compare(FSingleSelectedDependency.MaxVersion)<>0) then
DependencyChanged:=true;
AVersion.Free;
end;
end;
ApplyDependencyButton.Enabled:=DependencyChanged;
end;
procedure TPackageEditorForm.UpdateStatusBar(Immediately: boolean);
var
StatusText: String;
begin
if not CanUpdate(pefNeedUpdateStatusBar) 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.GetNodeData(TVNode: TTreeNode): TPENodeData;
var
o: TObject;
begin
Result:=nil;
if (TVNode=nil) then exit;
o:=TObject(TVNode.Data);
if o is TFileNameItem then
o:=TObject(TFileNameItem(o).Data);
if o is TPENodeData then
Result:=TPENodeData(o);
end;
function TPackageEditorForm.GetNodeItem(NodeData: TPENodeData): TObject;
begin
Result:=nil;
if (LazPackage=nil) or (NodeData=nil) then exit;
case NodeData.Typ of
penFile:
if NodeData.Removed then
Result:=LazPackage.FindRemovedPkgFile(NodeData.Name)
else
Result:=LazPackage.FindPkgFile(NodeData.Name,true,true);
penDependency:
if NodeData.Removed then
Result:=LazPackage.FindRemovedDependencyByName(NodeData.Name)
else
Result:=LazPackage.FindDependencyByName(NodeData.Name);
end;
end;
function TPackageEditorForm.GetNodeDataItem(TVNode: TTreeNode; out
NodeData: TPENodeData; out Item: TObject): boolean;
begin
Result:=false;
Item:=nil;
NodeData:=GetNodeData(TVNode);
Item:=GetNodeItem(NodeData);
Result:=Item<>nil;
end;
function TPackageEditorForm.IsDirectoryNode(Node: TTreeNode): boolean;
begin
Result:=(Node<>nil) and (Node.Data=nil) and Node.HasAsParent(FFilesNode);
end;
function TPackageEditorForm.GetNodeFilename(Node: TTreeNode): string;
var
Item: TFileNameItem;
begin
Result:='';
if Node=nil then exit;
if Node=FFilesNode then
exit(LazPackage.DirectoryExpanded);
Item:=TFileNameItem(Node.Data);
if not (Item is TFileNameItem) then exit;
Result:=Item.Filename;
end;
procedure TPackageEditorForm.GetDirectorySummary(DirNode: TTreeNode; out
FileCount, HasRegisterProcCount, AddToUsesPkgSectionCount: integer);
procedure Traverse(Node: TTreeNode);
var
CurFile: TPkgFile;
NodeData: TPENodeData;
begin
NodeData:=GetNodeData(Node);
if NodeData<>nil then begin
if NodeData.Typ=penFile then begin
CurFile:=LazPackage.FindPkgFile(NodeData.Name,true,true);
if CurFile<>nil then begin
inc(FileCount);
if CurFile.HasRegisterProc then inc(HasRegisterProcCount);
if CurFile.AddToUsesPkgSection then inc(AddToUsesPkgSectionCount);
end;
end;
end;
Node:=Node.GetFirstChild;
while Node<>nil do begin
Traverse(Node);
Node:=Node.GetNextSibling;
end;
end;
begin
FileCount:=0;
HasRegisterProcCount:=0;
AddToUsesPkgSectionCount:=0;
Traverse(DirNode);
end;
procedure TPackageEditorForm.ExtendUnitIncPathForNewUnit(const AnUnitFilename,
AnIncludeFile: string;
var IgnoreUnitPaths: TFilenameToStringTree);
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,true);
if ShortDirectory='' then exit;
LazPackage.LongenFilename(NewDirectory);
NewDirectory:=ChompPathDelim(NewDirectory);
UnitPath:=LazPackage.GetUnitPath(false);
UnitPathPos:=SearchDirectoryInSearchPath(UnitPath,NewDirectory,1);
IncPathPos:=1;
if AnIncludeFile<>'' then begin
NewIncDirectory:=ChompPathDelim(ExtractFilePath(AnIncludeFile));
ShortIncDirectory:=NewIncDirectory;
LazPackage.ShortenFilename(ShortIncDirectory,false);
if ShortIncDirectory<>'' then begin
LazPackage.LongenFilename(NewIncDirectory);
NewIncDirectory:=ChompPathDelim(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 (IgnoreUnitPaths<>nil) and (IgnoreUnitPaths.Contains(ShortDirectory))
then exit;
if MessageDlg(lisPkgEditNewUnitNotInUnitpath,
Format(lisPkgEditTheFileIsCurrentlyNotInTheUnitpathOfThePackage,
[AnUnitFilename, LineEnding, LineEnding, LineEnding, ShortDirectory]),
mtConfirmation,[mbYes,mbNo],0)<>mrYes
then begin
if IgnoreUnitPaths=nil then
IgnoreUnitPaths:=TFilenameToStringTree.Create(false);
IgnoreUnitPaths.Add(ShortDirectory,'');
exit;
end;
// 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;
procedure TPackageEditorForm.ExtendIncPathForNewIncludeFile(
const AnIncludeFile: string; var IgnoreIncPaths: TFilenameToStringTree);
var
NewDirectory: String;
ShortDirectory: String;
IncPath: String;
IncPathPos: LongInt;
begin
if LazPackage=nil then exit;
// check if directory is already in the unit path of the package
NewDirectory:=ExtractFilePath(AnIncludeFile);
ShortDirectory:=NewDirectory;
LazPackage.ShortenFilename(ShortDirectory,false);
if ShortDirectory='' then exit;
LazPackage.LongenFilename(NewDirectory);
NewDirectory:=ChompPathDelim(NewDirectory);
IncPath:=LazPackage.GetIncludePath(false);
IncPathPos:=SearchDirectoryInSearchPath(IncPath,NewDirectory,1);
if IncPathPos>0 then exit;
// ask user to add the unit path
if (IgnoreIncPaths<>nil) and (IgnoreIncPaths.Contains(ShortDirectory))
then exit;
if MessageDlg(lisPENewFileNotInIncludePath,
Format(lisPETheFileIsCurrentlyNotInTheIncludePathOfThePackageA,
[AnIncludeFile, LineEnding, ShortDirectory]),
mtConfirmation,[mbYes,mbNo],0)<>mrYes
then begin
if IgnoreIncPaths=nil then
IgnoreIncPaths:=TFilenameToStringTree.Create(false);
IgnoreIncPaths.Add(ShortDirectory,'');
exit;
end;
// add path
with LazPackage.CompilerOptions do
IncludePath:=MergeSearchPaths(IncludePath,ShortDirectory);
end;
function TPackageEditorForm.CanBeAddedToProject: boolean;
begin
if LazPackage=nil then exit(false);
Result:=PackageEditors.AddToProject(LazPackage,true)=mrOk;
end;
function TPackageEditorForm.CheckDrag(Sender, Source: TObject; X, Y: Integer;
out SrcPkgEdit: TPackageEditorForm; out aFileCount, aDependencyCount,
aDirectoryCount: integer; out TargetTVNode: TTreeNode; out
TargetTVType: TTreeViewInsertMarkType): boolean;
var
SrcTV: TTreeView;
aParent: TWinControl;
i: Integer;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
Directory: String;
begin
Result:=false;
SrcPkgEdit:=nil;
aFileCount:=0;
aDependencyCount:=0;
aDirectoryCount:=0;
TargetTVNode:=nil;
TargetTVType:=tvimNone;
if LazPackage.ReadOnly then exit;
if Source=ItemsTreeView then begin
// move items within the package
SrcPkgEdit:=Self;
end else if (Source is TTreeView) then begin
SrcTV:=TTreeView(Source);
if SrcTV.Name<>ItemsTreeView.Name then exit;
aParent:=SrcTV;
repeat
if aParent=nil then exit;
aParent:=aParent.Parent;
until aParent is TPackageEditorForm;
// move items to another package
SrcPkgEdit:=TPackageEditorForm(aParent);
//debugln(['TPackageEditorForm.ItemsTreeViewDragOver from another package editor: ',SrcPkgEdit.LazPackage.Name]);
end else
exit;
if SrcPkgEdit.LazPackage.ReadOnly then exit;
if (SrcPkgEdit<>Self) and (SrcPkgEdit.LazPackage.IsVirtual or LazPackage.IsVirtual)
then
exit; // no move between virtual packages
// check items
aFileCount:=0;
aDependencyCount:=0;
aDirectoryCount:=0;
for i:=0 to SrcPkgEdit.ItemsTreeView.SelectionCount-1 do begin
TVNode:=SrcPkgEdit.ItemsTreeView.Selections[i];
if SrcPkgEdit.GetNodeDataItem(TVNode,NodeData,Item) then begin
if NodeData.Removed then exit; // removed things cannot be moved
if Item is TPkgFile then begin
inc(aFileCount);
end else if Item is TPkgDependency then begin
inc(aDependencyCount);
end;
end else if SrcPkgEdit.IsDirectoryNode(TVNode) then begin
inc(aDirectoryCount);
end;
end;
if aFileCount+aDependencyCount+aDirectoryCount=0 then begin
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.CheckDrag failed: nothing useful dragged']);
{$ENDIF}
exit;
end;
if aDirectoryCount>1 then begin
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.CheckDrag failed: more than one directory']);
{$ENDIF}
exit; // only one directory per move
end;
if Abs(aFileCount)+Abs(aDependencyCount)+Abs(aDirectoryCount)>1 then begin
// more than one type, but only one type can be dragged
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.CheckDrag failed: more than one type']);
{$ENDIF}
exit;
end;
ItemsTreeView.GetInsertMarkAt(X,Y,TargetTVNode,TargetTVType);
if TargetTVNode=nil then begin
if aDependencyCount>0 then begin
TargetTVNode:=FRequiredPackagesNode;
end else begin
TargetTVNode:=FFilesNode;
end;
TargetTVType:=tvimAsFirstChild;
end;
if GetNodeDataItem(TargetTVNode,NodeData,Item) then begin
if TargetTVType in [tvimNone,tvimAsFirstChild] then
TargetTVType:=tvimAsNextSibling;
if Item is TPkgFile then begin
if aFileCount=0 then exit;
// drag files
{$IFNDEF EnablePkgEditDnd}
debugln(['TPackageEditorForm.CheckDrag todo: drag files']);
exit;
{$ENDIF}
end else if Item is TPkgDependency then begin
if aDependencyCount=0 then exit;
// ToDo: drag dependencies
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.CheckDrag todo: drag dependencies']);
{$ENDIF}
end;
end else if IsDirectoryNode(TargetTVNode) or (TargetTVNode=FFilesNode) then begin
Directory:=GetNodeFilename(TargetTVNode);
if not FilenameIsAbsolute(Directory) then begin
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.CheckDrag: invalid target directory ',Directory]);
{$ENDIF}
exit;
end;
if TargetTVNode=FFilesNode then
TargetTVType:=tvimAsFirstChild;
if aFileCount>0 then begin
// drag files
{$IFNDEF EnablePkgEditDnd}
debugln(['TPackageEditorForm.CheckDrag todo: drag files']);
exit;
{$ENDIF}
end else if aDirectoryCount>0 then begin
// ToDo: drag directory
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.CheckDrag todo: drag directory']);
{$ENDIF}
exit;
end else begin
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.CheckDrag failed: expected files or directory']);
{$ENDIF}
exit;
end;
end else if TargetTVNode=FRequiredPackagesNode then begin
if aDependencyCount=0 then exit;
// ToDo: drag dependencies
TargetTVType:=tvimAsFirstChild;
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.CheckDrag todo: drag dependencies']);
{$ENDIF}
exit;
end else begin
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.CheckDrag failed: invalid target node: ',TargetTVNode.Text]);
{$ENDIF}
exit;
end;
if (SrcPkgEdit=Self) and (TargetTVNode.Selected or TargetTVNode.MultiSelected)
then begin
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.CheckDrag failed: target is selected']);
{$ENDIF}
exit;
end;
Result:=true;
end;
function TPackageEditorForm.MoveFiles(SrcPkgEdit: TPackageEditorForm;
TargetDirectory: string): boolean;
var
Files: TFPList; // list of TPkgFile
i: Integer;
TVNode: TTreeNode;
NodeData: TPENodeData;
Item: TObject;
begin
Result:=false;
if not FilenameIsAbsolute(TargetDirectory) then exit;
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.MoveFiles Self=',LazPackage.Filename,' Src=',SrcPkgEdit.LazPackage.Filename,' Dir="',TargetDirectory,'"']);
{$ENDIF}
Files:=TFPList.Create;
try
for i:=0 to SrcPkgEdit.ItemsTreeView.SelectionCount-1 do begin
TVNode:=SrcPkgEdit.ItemsTreeView.Selections[i];
if not GetNodeDataItem(TVNode, NodeData, Item) then continue;
if NodeData.Removed then continue;
if not (Item is TPkgFile) then continue;
Files.Add(Item);
end;
if Files.Count=0 then exit(true);
Result:=MoveFiles(SrcPkgEdit,Files,TargetDirectory);
finally
Files.Free;
end;
end;
function TPackageEditorForm.MoveFiles(SrcPkgEdit: TPackageEditorForm;
PkgFiles: TFPList; TargetDirectory: string): boolean;
var
SrcPackage: TLazPackage;
AllChangedFilenames: TFilenameToStringTree;
NewFileToOldPkgFile: TFilenameToPointerTree;
ChangedFilenames: TFilenameToStringTree; // old to new file name
UnitFilenameToResFileList: TFilenameToPointerTree; // filename to TStringList
TargetPkgList: TFPList;
SrcPkgList: TFPList;
procedure DeleteNonExistingPkgFiles;
var
i: Integer;
PkgFile: TPkgFile;
aFilename: String;
begin
// ignore non existing files
for i:=PkgFiles.Count-1 downto 0 do begin
PkgFile:=TPkgFile(PkgFiles[i]);
aFilename:=PkgFile.GetFullFilename;
if not FileExistsCached(aFilename) then begin
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.MoveFiles WARNING: file not found: ',aFilename]);
{$ENDIF}
PkgFiles.Delete(i);
end;
end;
end;
procedure AddResFile(ResFiles: TStringList; ResFile: string);
var
NewResFile: String;
begin
if not FilenameIsAbsolute(ResFile) then exit;
if AllChangedFilenames.Contains(ResFile) then exit;
if IndexInRecentList(ResFiles,rltFile,ResFile)>=0 then exit;
if not FileExistsCached(ResFile) then exit;
ResFiles.Add(ResFile);
NewResFile:=TargetDirectory+ExtractFilename(ResFile);
AllChangedFilenames[ResFile]:=NewResFile;
end;
function CollectFiles(out MoveFileCount: integer): boolean;
var
i: Integer;
PkgFile: TPkgFile;
OldFilename: String;
NewFilename: String;
ResFileList: TStringList;
UnitResArr: TUnitResourcefileFormatArr;
j: Integer;
aFilename: String;
S2PItem: PStringToPointerTreeItem;
begin
Result:=false;
MoveFileCount:=0;
for i:=0 to PkgFiles.Count-1 do begin
PkgFile:=TPkgFile(PkgFiles[i]);
OldFilename:=PkgFile.GetFullFilename;
NewFilename:=TargetDirectory+ExtractFilename(OldFilename);
// check if two copied/moved files will get the same new file name
if NewFileToOldPkgFile.Contains(NewFilename) then begin
IDEMessageDialog('Conflict detected',
'Two moved files will have the same file name:'#13
+PkgFile.Filename+#13
+TPkgFile(NewFileToOldPkgFile[NewFilename]).Filename+#13
+'in package '+LazPackage.Name,mtError,[mbCancel]);
exit;
end;
NewFileToOldPkgFile[NewFilename]:=PkgFile;
if CompareFilenames(NewFilename,OldFilename)<>0 then begin
// file be copied/moved to another directory
inc(MoveFileCount);
ChangedFilenames[OldFilename]:=NewFilename;
AllChangedFilenames[OldFilename]:=NewFilename;
// check resource file
if PkgFile.FileType=pftUnit then begin
ResFileList:=TStringList.Create;
UnitFilenameToResFileList[OldFilename]:=ResFileList;
AddResFile(ResFileList,ChangeFileExt(OldFilename,'.lfm'));
AddResFile(ResFileList,ChangeFileExt(OldFilename,'.dfm'));
AddResFile(ResFileList,ChangeFileExt(OldFilename,'.lrs'));
UnitResArr:=GetUnitResourcefileFormats;
for j:=0 to length(UnitResArr)-1 do begin
aFilename:=UnitResArr[j].GetUnitResourceFilename(OldFilename,true);
AddResFile(ResFileList,aFilename);
end;
end;
end;
end;
// remove res files, that are in PkgFiles
for S2PItem in UnitFilenameToResFileList do begin
OldFilename:=S2PItem^.Name;
ResFileList:=TStringList(S2PItem^.Value);
for i:=ResFileList.Count-1 downto 0 do begin
if ChangedFilenames.Contains(ResFileList[i]) then
ResFileList.Delete(i);
end;
end;
Result:=true;
end;
function CheckNewFilesDoNotExist: boolean;
var
S2SItem: PStringToStringTreeItem;
OldFilename: String;
NewFilename: String;
ConflictFile: TPkgFile;
CurName: String;
ShortFilename: String;
r: TModalResult;
i: Integer;
WarnUnitClash: Boolean;
WarnNameClash: Boolean;
begin
Result:=false;
WarnUnitClash:=true;
WarnNameClash:=true;
for S2SItem in AllChangedFilenames do begin
OldFilename:=S2SItem^.Name;
NewFilename:=S2SItem^.Value;
if CompareFilenames(OldFilename,NewFilename)=0 then continue;
// check file does not exist
if FileExistsCached(NewFilename) then begin
IDEMessageDialog('Conflict detected',
'There is already a file'#13
+NewFilename+#13
+'in package '+LazPackage.Name,mtError,[mbCancel]);
exit;
end;
if (LazPackage<>SrcPackage) then begin
// warn duplicate names
if FilenameIsPascalUnit(NewFilename) then begin
// warn duplicate unit name
CurName:=ExtractFileNameOnly(NewFilename);
ConflictFile:=LazPackage.FindUnit(CurName,true);
if (ConflictFile<>nil) and WarnUnitClash then begin
ShortFilename:=NewFilename;
LazPackage.ShortenFilename(ShortFilename,true);
r:=IDEMessageDialog('Duplicate Unit',
'There is already a unit "'+CurName+'" in package '+LazPackage.Name+#13
+'Old: '+ConflictFile.GetShortFilename(true)+#13
+'New: '+ShortFilename+#13
+'You have to make sure that the unit search path of the package contains only one of them.'#13
+#13
+'Continue?'
,mtWarning,[mbYes,mbYesToAll,mbCancel]);
case r of
mrYes: ;
mrYesToAll: WarnUnitClash:=false;
else exit;
end;
end;
end else begin
// warn duplicate file
for i:=0 to LazPackage.FileCount-1 do begin
if not WarnNameClash then continue;
ConflictFile:=LazPackage.Files[i];
CurName:=ExtractFilename(NewFilename);
if UTF8CompareText(CurName,ExtractFileName(ConflictFile.Filename))<>0
then
continue;
ShortFilename:=NewFilename;
LazPackage.ShortenFilename(ShortFilename,true);
r:=IDEMessageDialog('Duplicate File Name',
'There is already a file "'+CurName+'" in package '+LazPackage.Name+#13
+'Old: '+ConflictFile.GetShortFilename(true)+#13
+'New: '+ShortFilename+#13
+#13
+'Continue?'
,mtWarning,[mbYes,mbYesToAll,mbCancel]);
case r of
mrYes: ;
mrYesToAll: WarnNameClash:=false;
else exit;
end;
end;
end;
end;
end;
Result:=true;
end;
function CloseSrcEditors: boolean;
var
i: Integer;
SrcEdit: TSourceEditorInterface;
begin
for i:=SourceEditorManagerIntf.SourceEditorCount-1 downto 0 do begin
if i>=SourceEditorManagerIntf.SourceEditorCount then continue;
SrcEdit:=SourceEditorManagerIntf.SourceEditors[i];
if not AllChangedFilenames.Contains(SrcEdit.FileName) then continue;
if LazarusIDE.DoCloseEditorFile(SrcEdit,
[cfSaveFirst,cfCloseDependencies])<>mrOk
then begin
{$IFDEF VerbosePkgEditDrag}
debugln(['CloseSrcEditors failed']);
{$ENDIF}
exit(false);
end;
end;
Result:=true;
end;
function CheckUsesSection(Tool: TCodeTool; UsesNode: TCodeTreeNode): boolean;
var
AnUnitName, AnUnitInFilename: string;
NewCode: TCodeBuffer;
UnitFilename: string;
Node: TCodeTreeNode;
ErrorPos: Integer;
NewCompiledUnitname: String;
CompiledFilename: String;
CodePos: TCodeXYPosition;
Msg: String;
PkgName: String;
begin
if UsesNode=nil then exit(true);
// check that all used units are available in the target package
Node:=UsesNode.FirstChild;
while Node<>nil do begin
// read unit name
AnUnitInFilename:='';
AnUnitName:=Tool.ExtractUsedUnitName(Node,@AnUnitInFilename);
ErrorPos:=Node.StartPos;
Node:=Node.NextBrother;
if AnUnitName='' then continue;
// find unit file
NewCode:=Tool.FindUnitSource(AnUnitName,AnUnitInFilename,false,Node.StartPos);
if (NewCode=nil) then begin
// no source found
// => search for ppu
NewCompiledUnitname:=AnUnitName+'.ppu';
CompiledFilename:=Tool.DirectoryCache.FindCompiledUnitInCompletePath(
NewCompiledUnitname,false);
if CompiledFilename='' then begin
// unit not found
// (that is ok, e.g. if the unit is used on another platform)
// => only warn
Msg:='unit '+AnUnitName+' not found';
if not Tool.CleanPosToCaret(ErrorPos,CodePos) then continue;
{$IFNDEF EnableOldExtTools}
IDEMessagesWindow.AddCustomMessage(mluWarning,Msg,
CodePos.Code.Filename,CodePos.Y,CodePos.X,'Move Files');
{$ELSE}
IDEMessagesWindow.AddMsg('Warning: '+Msg,'',-1);
{$ENDIF}
continue;
end;
UnitFilename:=CompiledFilename;
end else begin
// unit found
UnitFilename:=NewCode.Filename;
if AllChangedFilenames.Contains(UnitFilename) then begin
// this unit will be moved too => ok
continue;
end;
end;
// UnitFilename is now either a .pas/pp/p or .ppu file
// ToDo: find package
PkgName:='';
if not Tool.CleanPosToCaret(ErrorPos,CodePos) then continue;
Msg:='unit '+AnUnitName+' requires package '+PkgName;
{$IFNDEF EnableOldExtTools}
IDEMessagesWindow.AddCustomMessage(mluWarning,Msg,
CodePos.Code.Filename,CodePos.Y,CodePos.X,'Move Files');
{$ELSE}
IDEMessagesWindow.AddMsg('Warning: '+Msg,'',-1);
{$ENDIF}
end;
end;
function CheckUsesSections: boolean;
// check that all used units are available in the target package
var
i: Integer;
PkgFile: TPkgFile;
OldFilename: String;
Code: TCodeBuffer;
Tool: TCodeTool;
begin
if LazPackage=SrcPackage then
exit(true);
// moving files to another package
if PackageGraph.FindDependencyRecursively(
LazPackage.FirstRequiredDependency,SrcPackage)<>nil
then begin
// units are moved to higher level package
// => no check needed
exit(true);
end;
// check that all used units are available in the target package
Result:=true;
for i:=0 to PkgFiles.Count-1 do begin
PkgFile:=TPkgFile(PkgFiles[i]);
if PkgFile.FileType<>pftUnit then continue;
OldFilename:=PkgFile.GetFullFilename;
if LoadCodeBuffer(Code,OldFilename,[lbfUpdateFromDisk,lbfCheckIfText],false)<>mrOk
then exit;
CodeToolBoss.Explore(Code,Tool,false);
if not CheckUsesSection(Tool,Tool.FindMainUsesSection) then
Result:=false;
if not CheckUsesSection(Tool,Tool.FindImplementationUsesSection) then
Result:=false;
end;
if not Result then begin
if IDEMessageDialog('Warning',
'Moving these units will break their uses sections. See Messages window for details.',
mtWarning,[mbIgnore,mbCancel])<>mrIgnore
then
exit;
Result:=true;
end;
end;
var
MoveFileCount: Integer;
MsgResult: TModalResult;
DeleteOld: Boolean;
begin
Result:=false;
DeleteNonExistingPkgFiles;
if PkgFiles.Count=0 then exit;
if not FilenameIsAbsolute(TargetDirectory) then exit;
TargetDirectory:=AppendPathDelim(TargetDirectory);
{$IFDEF VerbosePkgEditDrag}
debugln(['TPackageEditorForm.MoveFiles Self=',LazPackage.Filename,' Src=',SrcPkgEdit.LazPackage.Filename,' Dir="',TargetDirectory,'" FileCount=',PkgFiles.Count]);
{$ENDIF}
SrcPackage:=SrcPkgEdit.LazPackage;
// check TargetDirectory
if CheckDirectoryIsWritable(TargetDirectory)<>mrOk then exit;
IDEMessagesWindow.Clear;
NewFileToOldPkgFile:=TFilenameToPointerTree.Create(false);
ChangedFilenames:=TFilenameToStringTree.Create(false);
AllChangedFilenames:=TFilenameToStringTree.Create(false);
UnitFilenameToResFileList:=TFilenameToPointerTree.Create(false);
UnitFilenameToResFileList.FreeValues:=true;
TargetPkgList:=nil;
SrcPkgList:=nil;
try
// collect all affected files including resource files
if not CollectFiles(MoveFileCount) then exit;
// check if new position is free
if not CheckNewFilesDoNotExist then exit;
if (MoveFileCount=0) and (LazPackage=SrcPackage) then begin
// no move, only change order in package
// ToDo: check this case in ItemsTreeViewDragDrop
IDEMessageDialog('Not implemented yet',
'Changing order via drag and drop is not yet implemented.',
mtInformation,[mbOk]);
exit;
end;
// ask for confirmation
if PkgFiles.Count=MoveFileCount then begin
MsgResult:=IDEQuestionDialog('Move or Copy files?',
'Move or copy '+IntToStr(MoveFileCount)+' file(s) from package '+SrcPackage.Name+' to the directory'#13
+TargetDirectory+#13
+'of package '+LazPackage.Name+'.',
mtConfirmation,[100,'Move',101,'Copy',mrCancel]);
case MsgResult of
100: DeleteOld:=true;
101: DeleteOld:=false;
else exit;
end;
end else begin
if IDEMessageDialog('Move files?',
'Move '+IntToStr(MoveFileCount)+' file(s) from package '+SrcPackage.Name+' to the directory'#13
+TargetDirectory+#13
+'of package '+LazPackage.Name+'.',
mtConfirmation,[mbOk,mbCancel])<>mrOK
then exit;
DeleteOld:=true;
end;
// fetch used packages
PackageGraph.GetAllRequiredPackages(LazPackage,nil,TargetPkgList);
PackageGraph.GetAllRequiredPackages(SrcPackage,nil,SrcPkgList);
// check uses sections
if not CheckUsesSections then exit;
if DeleteOld then begin
// close files and res files in source editor
if not CloseSrcEditors then exit;
end;
if (SrcPackage<>LazPackage) then begin
// files will be moved to another directory
// => clear output directory of SrcPackage
if PackageGraph.PreparePackageOutputDirectory(SrcPackage,true)<>mrOk then
exit;
end;
ShowMessage('Moving files is not yet implemented');
exit;
// move/copy file and res files, Note: some files are res files
// move/copy TPkgFile, make uses-unit unique
// extend unit/include path of LazPackage
// clean up unit/inlude path of SrcPkg
Result:=true;
finally
TargetPkgList.Free;
SrcPkgList.Free;
UnitFilenameToResFileList.Free;
AllChangedFilenames.Free;
ChangedFilenames.Free;
NewFileToOldPkgFile.Free;
end;
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(true);
end;
procedure TPackageEditorForm.DoPublishProject;
begin
PackageEditors.PublishPackage(LazPackage);
end;
procedure TPackageEditorForm.DoEditVirtualUnit;
begin
if LazPackage=nil then exit;
if (FSingleSelectedFile=nil)
or (FSingleSelectedFile.FileType<>pftVirtualUnit)
or (LazPackage.IndexOfPkgFile(FSingleSelectedFile)<0)
then exit;
if ShowEditVirtualPackageDialog(FSingleSelectedFile)=mrOk then
UpdateFiles;
end;
procedure TPackageEditorForm.DoExpandDirectory;
var
CurNode: TTreeNode;
begin
if not ShowDirectoryHierarchy then exit;
CurNode:=ItemsTreeView.Selected;
if not (IsDirectoryNode(CurNode) or (CurNode=FFilesNode)) then exit;
ItemsTreeView.BeginUpdate;
CurNode.Expand(true);
ItemsTreeView.EndUpdate;
end;
procedure TPackageEditorForm.DoCollapseDirectory;
var
CurNode: TTreeNode;
Node: TTreeNode;
begin
if not ShowDirectoryHierarchy then exit;
CurNode:=ItemsTreeView.Selected;
if not (IsDirectoryNode(CurNode) or (CurNode=FFilesNode)) then exit;
ItemsTreeView.BeginUpdate;
Node:=CurNode.GetFirstChild;
while Node<>nil do
begin
Node.Collapse(true);
Node:=Node.GetNextSibling;
end;
ItemsTreeView.EndUpdate;
end;
procedure TPackageEditorForm.DoUseUnitsInDirectory(Use: boolean);
procedure Traverse(Node: TTreeNode);
var
PkgFile: TPkgFile;
NodeData: TPENodeData;
begin
NodeData:=GetNodeData(Node);
if (NodeData<>nil) and (NodeData.Typ=penFile) then
begin
PkgFile:=LazPackage.FindPkgFile(NodeData.Name,true,true);
if (PkgFile<>nil) and (PkgFile.FileType in [pftUnit,pftVirtualUnit]) then
begin
if PkgFile.AddToUsesPkgSection<>Use then
begin
PkgFile.AddToUsesPkgSection:=Use;
LazPackage.Modified:=true;
end;
end;
end;
Node:=Node.GetFirstChild;
while Node<>nil do
begin
Traverse(Node);
Node:=Node.GetNextSibling;
end;
end;
var
CurNode: TTreeNode;
begin
if not ShowDirectoryHierarchy then exit;
CurNode:=ItemsTreeView.Selected;
if not (IsDirectoryNode(CurNode) or (CurNode=FFilesNode)) then exit;
Traverse(CurNode);
UpdatePEProperties;
end;
procedure TPackageEditorForm.DoMoveCurrentFile(Offset: integer);
var
OldIndex, NewIndex: Integer;
FilesBranch: TTreeFilterBranch;
begin
if (LazPackage=nil) or (FSingleSelectedFile=nil) then exit;
OldIndex:=LazPackage.IndexOfPkgFile(FSingleSelectedFile);
if OldIndex<0 then exit;
NewIndex:=OldIndex+Offset;
if (NewIndex<0) or (NewIndex>=LazPackage.FileCount) then exit;
FilesBranch:=FilterEdit.GetExistingBranch(FFilesNode);
LazPackage.MoveFile(OldIndex,NewIndex);
FilesBranch.MoveFile(OldIndex,NewIndex);
UpdatePEProperties;
UpdateStatusBar;
FilterEdit.InvalidateFilter;
end;
procedure TPackageEditorForm.DoMoveDependency(Offset: integer);
var
OldSelection: TStringList;
begin
ItemsTreeView.BeginUpdate;
OldSelection:=ItemsTreeView.StoreCurrentSelection;
if Offset<0 then
PackageGraph.MoveRequiredDependencyUp(FSingleSelectedDependency)
else
PackageGraph.MoveRequiredDependencyDown(FSingleSelectedDependency);
ItemsTreeView.ApplyStoredSelection(OldSelection);
ItemsTreeView.EndUpdate;
end;
procedure TPackageEditorForm.DoSortFiles;
var
TreeSelection: TStringList;
begin
TreeSelection:=ItemsTreeView.StoreCurrentSelection;
LazPackage.SortFiles;
UpdateFiles;
ItemsTreeView.ApplyStoredSelection(TreeSelection);
end;
function TPackageEditorForm.DoOpenPkgFile(PkgFile: TPkgFile): TModalResult;
begin
Result:=PackageEditors.OpenPkgFile(Self,PkgFile);
end;
procedure TPackageEditorForm.DoFixFilesCase;
begin
if LazPackage.FixFilesCaseSensitivity then
LazPackage.Modified:=true;
UpdateFiles;
UpdateButtons;
end;
procedure TPackageEditorForm.DoShowMissingFiles;
begin
ShowMissingPkgFilesDialog(LazPackage);
UpdateFiles;
end;
constructor TPackageEditorForm.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
end;
destructor TPackageEditorForm.Destroy;
begin
inherited Destroy;
end;
{ TPackageEditors }
function TPackageEditors.GetEditors(Index: integer): TPackageEditorForm;
begin
Result:=TPackageEditorForm(FItems[Index]);
end;
constructor TPackageEditors.Create;
begin
FItems:=TFPList.Create;
end;
destructor TPackageEditors.Destroy;
begin
Clear;
FreeAndNil(FItems);
inherited Destroy;
end;
function TPackageEditors.Count: integer;
begin
Result:=FItems.Count;
end;
procedure TPackageEditors.Clear;
begin
FItems.Clear;
end;
procedure TPackageEditors.Remove(Editor: TPackageEditorForm);
begin
if FItems<>nil then
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(LazarusIDE.OwningComponent);
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,false)=lprSuccess then
begin
APackage:=Dependency.RequiredPackage;
if Assigned(OnOpenPackage) then Result:=OnOpenPackage(Sender,APackage);
end;
end;
procedure TPackageEditors.DoFreeEditor(Pkg: TLazPackage);
begin
if FItems<>nil then
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(Immediately: boolean);
var
i: Integer;
begin
for i:=0 to Count-1 do
Editors[i].UpdateAll(Immediately);
end;
function TPackageEditors.ShouldNotBeInstalled(APackage: TLazPackage): boolean;
begin
Result:=APackage.Missing
or ((APackage.FindUnitWithRegister=nil) and (APackage.Provides.Count=0));
end;
function TPackageEditors.InstallPackage(APackage: TLazPackage): TModalResult;
begin
if ShouldNotBeInstalled(APackage) then begin
if IDEQuestionDialog(lisNotAnInstallPackage,
Format(lisThePackageDoesNotHaveAnyRegisterProcedureWhichTypi,
[APackage.Name, LineEnding, LineEnding]),
mtWarning,
[mrIgnore, lisInstallItILikeTheFat, mrCancel, lisCancel], '')<>mrIgnore
then exit(mrCancel);
end;
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.ViewPkgSource(APackage: TLazPackage): TModalResult;
begin
if Assigned(OnViewPackageSource) then
Result:=OnViewPackageSource(Self,APackage)
else
Result:=mrCancel;
end;
function TPackageEditors.ViewPkgToDos(APackage: TLazPackage): TModalResult;
begin
if Assigned(OnViewPackageToDos) then
Result:=OnViewPackageToDos(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.CreateFpmakeFile(APackage: TLazPackage): TModalResult;
begin
if Assigned(OnCreateFpmakefile) then
Result:=OnCreateFpmakefile(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;
initialization
PackageEditors:=nil;
end.