mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-06 03:58:01 +02:00
3893 lines
131 KiB
ObjectPascal
3893 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1335, USA. *
|
|
* *
|
|
***************************************************************************
|
|
|
|
Author: Mattias Gaertner
|
|
|
|
Abstract:
|
|
TPackageEditorForm is the form of a package editor.
|
|
}
|
|
unit PackageEditor;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
{off $DEFINE VerbosePkgEditDrag}
|
|
|
|
interface
|
|
|
|
uses
|
|
// RTL, FCL
|
|
Classes, SysUtils, Contnrs,
|
|
// LCL
|
|
Forms, Controls, StdCtrls, ComCtrls, Buttons, Graphics, Menus, Dialogs,
|
|
ExtCtrls, ImgList, LCLType, LCLIntf,
|
|
// LazControls
|
|
TreeFilterEdit,
|
|
// Codetools
|
|
CodeToolManager, CodeCache, DirectoryCacher, FileProcs,
|
|
// LazUtils
|
|
FileUtil, LazFileUtils, LazFileCache, AvgLvlTree, LazLoggerBase, LazTracer,
|
|
// BuildIntf
|
|
ProjectIntf, PackageDependencyIntf, PackageIntf, PackageLinkIntf,
|
|
IDEOptionsIntf, NewItemIntf, ComponentReg,
|
|
// IDEIntf
|
|
IDEImagesIntf, MenuIntf, LazIDEIntf, FormEditingIntf, IDEHelpIntf, InputHistory,
|
|
IdeIntfStrConsts, IDEWindowIntf, IDEDialogs, IDEOptEditorIntf, SrcEditorIntf,
|
|
// IdeConfig
|
|
EnvironmentOpts, SearchPathProcs, ParsedCompilerOpts, CompilerOptions,
|
|
// IDE
|
|
MainBase, DialogProcs, LazarusIDEStrConsts, IDEDefs,
|
|
PackageSystem, PackageDefs, AddToPackageDlg, AddPkgDependencyDlg, ComponentPalette,
|
|
AddFPMakeDependencyDlg, ProjPackChecks, PkgVirtualUnitEditor, CleanPkgDeps,
|
|
MissingPkgFilesDlg, ProjPackFilePropGui, ProjPackEditing, BasePkgManager;
|
|
|
|
const
|
|
PackageEditorMenuRootName = 'PackageEditor';
|
|
PackageEditorMenuFilesRootName = 'PackageEditorFiles';
|
|
PackageEditorWindowPrefix = 'PackageEditor_';
|
|
var
|
|
// General actions for the Files and Required packages root nodes.
|
|
// Duplicates actions found under the "Add" button.
|
|
PkgEditMenuAddDiskFile: TIDEMenuCommand;
|
|
PkgEditMenuAddNewDiskFiles: TIDEMenuCommand;
|
|
PkgEditMenuAddNewFile: TIDEMenuCommand;
|
|
PkgEditMenuAddNewComp: TIDEMenuCommand;
|
|
PkgEditMenuAddNewReqr: TIDEMenuCommand;
|
|
PkgEditMenuAddNewFPMakeReqr: TIDEMenuCommand;
|
|
|
|
// selected files
|
|
PkgEditMenuOpenFile: TIDEMenuCommand;
|
|
PkgEditMenuRemoveFile: TIDEMenuCommand;
|
|
PkgEditMenuReAddFile: TIDEMenuCommand;
|
|
PkgEditMenuCopyMoveToDirectory: TIDEMenuCommand;
|
|
PkgEditMenuEditVirtualUnit: TIDEMenuCommand;
|
|
PkgEditMenuSectionFileType: TIDEMenuSection;
|
|
|
|
// directories
|
|
PkgEditMenuExpandDirectory: TIDEMenuCommand;
|
|
PkgEditMenuCollapseDirectory: TIDEMenuCommand;
|
|
PkgEditMenuUseAllUnitsInDirectory: TIDEMenuCommand;
|
|
PkgEditMenuUseNoUnitsInDirectory: TIDEMenuCommand;
|
|
PkgEditMenuOpenFolder: TIDEMenuCommand;
|
|
|
|
// dependencies
|
|
PkgEditMenuRemoveDependency: TIDEMenuCommand;
|
|
PkgEditMenuReAddDependency: TIDEMenuCommand;
|
|
PkgEditMenuDepStoreFileNameDefault: TIDEMenuCommand;
|
|
PkgEditMenuDepStoreFileNamePreferred: TIDEMenuCommand;
|
|
PkgEditMenuDepClearStoredFileName: TIDEMenuCommand;
|
|
PkgEditMenuCleanDependencies: TIDEMenuCommand;
|
|
|
|
// all files
|
|
PkgEditMenuFindInFiles: TIDEMenuCommand;
|
|
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
|
|
TOnPkgEvent = function(Sender: TObject; APackage: TLazPackage): TModalResult of object;
|
|
TOnAddPkgToProject =
|
|
function(Sender: TObject; APackage: TLazPackage;
|
|
OnlyTestIfPossible: boolean): TModalResult of object;
|
|
TOnCompilePackage =
|
|
function(Sender: TObject; APackage: TLazPackage;
|
|
CompileClean, CompileRequired: boolean): 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;
|
|
TOnOpenFile =
|
|
function(Sender: TObject; const Filename: string): TModalResult of object;
|
|
TOnOpenPkgFile =
|
|
function(Sender: TObject; PkgFile: TPkgFile): TModalResult of object;
|
|
TOnSavePackage =
|
|
function(Sender: TObject; APackage: TLazPackage;
|
|
SaveAs: boolean): TModalResult of object;
|
|
|
|
TIDEPackageOptsDlgAction = (
|
|
iodaRead,
|
|
iodaWrite,
|
|
iodaRestore
|
|
);
|
|
|
|
{ TPETVSelectedView }
|
|
|
|
TPETVSelectedView = record
|
|
NeedEndUpdate: boolean;
|
|
OldScrollLeft: integer;
|
|
OldScrollTop: integer;
|
|
OldNodePath: string;
|
|
|
|
RestoreFilter: boolean;
|
|
OldFilter: string;
|
|
end;
|
|
|
|
{ TPackageEditorForm }
|
|
|
|
TPackageEditorForm = class(TBasePackageEditor,IFilesEditorInterface)
|
|
MenuItem1: TMenuItem;
|
|
mnuAddNewDiskFiles: TMenuItem;
|
|
mnuAddFPMakeReq: TMenuItem;
|
|
mnuAddDiskFile: TMenuItem;
|
|
mnuAddNewFile: TMenuItem;
|
|
mnuAddNewComp: TMenuItem;
|
|
mnuAddNewReqr: TMenuItem;
|
|
MoveDownBtn: TSpeedButton;
|
|
MoveUpBtn: TSpeedButton;
|
|
DirectoryHierarchyButton: TSpeedButton;
|
|
OpenButton: TSpeedButton;
|
|
FilterEdit: TTreeFilterEdit;
|
|
FilterPanel: TPanel;
|
|
AddPopupMenu: TPopupMenu;
|
|
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;
|
|
PropsPageControl: TPageControl;
|
|
CommonOptionsTabSheet: TTabSheet;
|
|
// statusbar
|
|
StatusBar: TStatusBar;
|
|
// hidden components
|
|
UsePopupMenu: TPopupMenu;
|
|
ItemsPopupMenu: TPopupMenu;
|
|
MorePopupMenu: TPopupMenu;
|
|
procedure AddToProjectClick(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 CopyMoveToDirMenuItemClick(Sender: TObject);
|
|
procedure CreateMakefileClick(Sender: TObject);
|
|
procedure CreateFpmakeFileClick(Sender: TObject);
|
|
procedure DirectoryHierarchyButtonClick(Sender: TObject);
|
|
procedure EditVirtualUnitMenuItemClick(Sender: TObject);
|
|
procedure ExpandDirectoryMenuItemClick(Sender: TObject);
|
|
procedure FilterEditAfterFilter(Sender: TObject);
|
|
procedure FilterEditKeyDown(Sender: TObject; var Key: Word; {%H-}Shift: TShiftState);
|
|
procedure FindInFilesMenuItemClick(Sender: TObject);
|
|
procedure FormCreate(Sender: TObject);
|
|
procedure FormDestroy(Sender: TObject);
|
|
procedure FormDropFiles(Sender: TObject; const FileNames: array of String);
|
|
procedure FormResize(Sender: TObject);
|
|
procedure ItemsPopupMenuPopup(Sender: TObject);
|
|
procedure ItemsTreeViewAdvancedCustomDrawItem(Sender: TCustomTreeView;
|
|
Node: TTreeNode; {%H-}State: TCustomDrawState; Stage: TCustomDrawStage;
|
|
var {%H-}PaintImages, {%H-}DefaultDraw: Boolean);
|
|
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 mnuAddDiskFileClick(Sender: TObject);
|
|
procedure mnuAddFPMakeReqClick(Sender: TObject);
|
|
procedure mnuAddNewDiskFilesClick(Sender: TObject);
|
|
procedure mnuAddNewCompClick(Sender: TObject);
|
|
procedure mnuAddNewReqrClick(Sender: TObject);
|
|
procedure mnuAddNewFileClick(Sender: TObject);
|
|
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 MoveDownBtnClick(Sender: TObject);
|
|
procedure MoveUpBtnClick(Sender: TObject);
|
|
procedure OnIdle(Sender: TObject; var {%H-}Done: Boolean);
|
|
procedure OpenButtonClick(Sender: TObject);
|
|
procedure OpenFolderMenuItemClick(Sender: TObject);
|
|
procedure OptionsBitBtnClick(Sender: TObject);
|
|
procedure PackageEditorFormClose(Sender: TObject; var {%H-}CloseAction: TCloseAction);
|
|
procedure PackageEditorFormCloseQuery(Sender: TObject; var CanClose: boolean);
|
|
procedure PublishClick(Sender: TObject);
|
|
procedure ReAddMenuItemClick(Sender: TObject);
|
|
procedure RemoveBitBtnClick(Sender: TObject);
|
|
procedure RevertClick(Sender: TObject);
|
|
procedure SaveAsClick(Sender: TObject);
|
|
procedure SaveBitBtnClick(Sender: TObject);
|
|
procedure SetDepDefaultFilenameMenuItemClick(Sender: TObject);
|
|
procedure SetDepPreferredFilenameMenuItemClick(Sender: TObject);
|
|
procedure ShowMissingFilesMenuItemClick(Sender: TObject);
|
|
procedure SortAlphabeticallyButtonClick(Sender: TObject);
|
|
procedure SortFilesMenuItemClick(Sender: TObject);
|
|
procedure UninstallClick(Sender: TObject);
|
|
procedure UseAllUnitsInDirectoryMenuItemClick(Sender: TObject);
|
|
procedure UseNoUnitsInDirectoryMenuItemClick(Sender: TObject);
|
|
procedure UsePopupMenuPopup(Sender: TObject);
|
|
procedure ViewPkgSourceClick(Sender: TObject);
|
|
procedure ViewPkgTodosClick(Sender: TObject);
|
|
private
|
|
FIdleConnected: boolean;
|
|
FCompiling: boolean;
|
|
FCompileDesignTimePkg: 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
|
|
FPropGui: TProjPackFilePropGui;
|
|
FShowDirectoryHierarchy: boolean;
|
|
FSortAlphabetically: boolean;
|
|
FDirSummaryLabel: TLabel;
|
|
FOptionsShownOfFile: TPkgFile;
|
|
fUpdateLock: integer;
|
|
fForcedFlags: TPEFlags;
|
|
procedure DoAddNewFile(NewItem: TNewIDEItemTemplate);
|
|
function CreateToolButton(AName, ACaption, AHint, AImageName: String;
|
|
AOnClick: TNotifyEvent): TToolButton;
|
|
function CreateDivider: TToolButton;
|
|
procedure SetDependencyDefaultFilename(AsPreferred: boolean);
|
|
procedure SetIdleConnected(AValue: boolean);
|
|
procedure SetShowDirectoryHierarchy(const AValue: boolean);
|
|
procedure SetSortAlphabetically(const AValue: boolean);
|
|
procedure SetupComponents;
|
|
procedure CreatePackageFileEditors;
|
|
function TreeViewGetImageIndex({%H-}Str: String; Data: TObject; var {%H-}AIsEnabled: Boolean): Integer;
|
|
procedure StoreItemsTVSelectedNode(out OldView: TPETVSelectedView; StoreFilter: boolean);
|
|
procedure RestoreItemsTVSelectedNode(const OldView: TPETVSelectedView);
|
|
function CanUpdate(Flag: TPEFlag; Immediately: boolean): boolean;
|
|
procedure UpdatePending;
|
|
procedure UpdateTitle(Immediately: boolean = false);
|
|
procedure UpdateFiles(Immediately: boolean = false);
|
|
procedure UpdateRemovedFiles(Immediately: boolean = false);
|
|
procedure UpdateRequiredPackages(Immediately: boolean = false);
|
|
procedure UpdatePEProperties(Immediately: boolean = false);
|
|
procedure UpdateButtons(Immediately: boolean = false);
|
|
procedure UpdateStatusBar(Immediately: boolean = false);
|
|
function GetDependencyToUpdate(Immediately: boolean): TPkgDependencyID;
|
|
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;
|
|
procedure PackageListAvailable(Sender: TObject);
|
|
function PassesFilter(rec: PIDEOptionsGroupRec): Boolean;
|
|
procedure TraverseSettings(AOptions: TAbstractPackageFileIDEOptions; anAction: TIDEPackageOptsDlgAction);
|
|
procedure FileOptionsToGui;
|
|
procedure GuiToFileOptions(Restore: boolean);
|
|
procedure FileOptionsChange(Sender: TObject);
|
|
procedure CallRegisterProcCheckBoxChange(Sender: TObject);
|
|
procedure AddToUsesPkgSectionCheckBoxChange(Sender: TObject);
|
|
procedure ApplyDependencyButtonClick(Sender: TObject);
|
|
procedure RegisteredListBoxDrawItem({%H-}Control: TWinControl; Index: Integer;
|
|
ARect: TRect; {%H-}State: TOwnerDrawState);
|
|
procedure DisableI18NForLFMCheckBoxChange(Sender: TObject);
|
|
procedure SelectFileNode(const AFileName: string);
|
|
procedure AddUserFiles(Filenames: TStrings);
|
|
protected
|
|
fFlags: TPEFlags;
|
|
procedure SetLazPackage(const AValue: TLazPackage); override;
|
|
property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
|
|
public
|
|
constructor Create(TheOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
function CanCloseEditor: TModalResult; override;
|
|
procedure DoCompile(CompileClean, CompileRequired, WarnIDEPkg: boolean);
|
|
procedure DoFindInFiles;
|
|
procedure DoFixFilesCase;
|
|
procedure DoShowMissingFiles;
|
|
procedure DoMoveCurrentFile(Offset: integer);
|
|
procedure DoMoveDependency(Offset: integer);
|
|
procedure DoPublishPackage;
|
|
procedure DoEditVirtualUnit;
|
|
procedure DoExpandCollapseDirectory(ExpandIt: Boolean);
|
|
procedure DoUseUnitsInDirectory(Use: boolean);
|
|
procedure DoRevert;
|
|
procedure DoSave(SaveAs: boolean);
|
|
procedure DoSortFiles;
|
|
function ShowNewCompDialog: TModalResult;
|
|
function ShowAddDepDialog: TModalResult;
|
|
function ShowAddFPMakeDepDialog: TModalResult;
|
|
function PkgNameToFormName(const PkgName: string): string;
|
|
function GetSingleSelectedDependency: TPkgDependency;
|
|
function GetSingleSelectedFile: TPkgFile;
|
|
public
|
|
// IFilesEditorInterface
|
|
function FilesEditTreeView: TTreeView;
|
|
function FilesEditForm: TCustomForm;
|
|
function FilesOwner: TObject; // = Lazpackage
|
|
function FilesOwnerName: string;
|
|
function TVNodeFiles: TTreeNode;
|
|
function TVNodeRequiredPackages: TTreeNode;
|
|
function FilesBaseDirectory: string;
|
|
function FilesOwnerReadOnly: boolean;
|
|
function FirstRequiredDependency: TPkgDependency;
|
|
function ExtendUnitSearchPath(NewUnitPaths: string): boolean;
|
|
function ExtendIncSearchPath(NewIncPaths: string): boolean;
|
|
function GetNodeItem(NodeData: TPENodeData): TObject;
|
|
function GetNodeDataItem(TVNode: TTreeNode; out NodeData: TPENodeData;
|
|
out Item: TObject): boolean;
|
|
function GetNodeFilename(Node: TTreeNode): string;
|
|
function IsDirectoryNode(Node: TTreeNode): boolean;
|
|
procedure BeginUpdate;
|
|
procedure EndUpdate;
|
|
procedure UpdateAll(Immediately: boolean = false); override;
|
|
public
|
|
property LazPackage: TLazPackage read FLazPackage write SetLazPackage;
|
|
property SortAlphabetically: boolean read FSortAlphabetically write SetSortAlphabetically;
|
|
property ShowDirectoryHierarchy: boolean read FShowDirectoryHierarchy write SetShowDirectoryHierarchy;
|
|
property FilesNode: TTreeNode read FFilesNode;
|
|
property RequiredPackagesNode: TTreeNode read FRequiredPackagesNode;
|
|
end;
|
|
|
|
|
|
{ TPackageEditors }
|
|
|
|
TPackageEditors = class
|
|
private
|
|
FItems: TFPList; // list of TPackageEditorForm
|
|
FOnAddToProject: TOnAddPkgToProject;
|
|
FOnAfterWritePackage: TIDEOptionsWriteEvent;
|
|
FOnBeforeReadPackage: TNotifyEvent;
|
|
FOnCompilePackage: TOnCompilePackage;
|
|
FOnCopyMoveFiles: TNotifyEvent;
|
|
FOnCreateNewFile: TOnCreateNewPkgFile;
|
|
FOnCreateMakefile: TOnPkgEvent;
|
|
FOnCreateFpmakeFile: TOnPkgEvent;
|
|
FOnDeleteAmbiguousFiles: TOnDeleteAmbiguousFiles;
|
|
FOnDragDropTreeView: TDragDropEvent;
|
|
FOnDragOverTreeView: TOnDragOverTreeView;
|
|
FOnShowFindInFiles: TOnPkgEvent;
|
|
FOnFreeEditor: TOnFreePkgEditor;
|
|
FOnGetIDEFileInfo: TGetIDEFileStateEvent;
|
|
FOnInstallPackage: TOnPkgEvent;
|
|
FOnOpenFile: TOnOpenFile;
|
|
FOnOpenPackage: TOnPkgEvent;
|
|
FOnOpenPkgFile: TOnOpenPkgFile;
|
|
FOnPublishPackage: TOnPkgEvent;
|
|
FOnRevertPackage: TOnPkgEvent;
|
|
FOnSavePackage: TOnSavePackage;
|
|
FOnUninstallPackage: TOnPkgEvent;
|
|
FOnViewPackageSource: TOnPkgEvent;
|
|
FOnViewPackageToDos: TOnPkgEvent;
|
|
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 IndexOfPackage(const PkgName: string): integer;
|
|
function FindEditor(Pkg: TLazPackage): TPackageEditorForm; overload;
|
|
function FindEditor(const PkgName: string): TPackageEditorForm; overload;
|
|
function CreateEditor(Pkg: TLazPackage; DoDisableAutoSizing: boolean): TPackageEditorForm;
|
|
function OpenEditor(Pkg: TLazPackage; BringToFront: boolean): 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 FindInFiles(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;
|
|
function TreeViewToPkgEditor(TV: TTreeView): TPackageEditorForm;
|
|
procedure ActiveEditorChanged(Sender: TObject);
|
|
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 OnCopyMoveFiles: TNotifyEvent read FOnCopyMoveFiles
|
|
write FOnCopyMoveFiles;
|
|
property OnCreateFpmakeFile: TOnPkgEvent read FOnCreateFpmakeFile
|
|
write FOnCreateFpmakeFile;
|
|
property OnCreateMakeFile: TOnPkgEvent read FOnCreateMakefile
|
|
write FOnCreateMakefile;
|
|
property OnCreateNewFile: TOnCreateNewPkgFile read FOnCreateNewFile
|
|
write FOnCreateNewFile;
|
|
property OnDeleteAmbiguousFiles: TOnDeleteAmbiguousFiles
|
|
read FOnDeleteAmbiguousFiles write FOnDeleteAmbiguousFiles;
|
|
property OnDragDropTreeView: TDragDropEvent read FOnDragDropTreeView
|
|
write FOnDragDropTreeView;
|
|
property OnDragOverTreeView: TOnDragOverTreeView read FOnDragOverTreeView
|
|
write FOnDragOverTreeView;
|
|
property OnShowFindInFiles: TOnPkgEvent read FOnShowFindInFiles write FOnShowFindInFiles;
|
|
property OnFreeEditor: TOnFreePkgEditor read FOnFreeEditor
|
|
write FOnFreeEditor;
|
|
property OnGetIDEFileInfo: TGetIDEFileStateEvent read FOnGetIDEFileInfo
|
|
write FOnGetIDEFileInfo;
|
|
property OnInstallPackage: TOnPkgEvent read FOnInstallPackage
|
|
write FOnInstallPackage;
|
|
property OnOpenFile: TOnOpenFile read FOnOpenFile write FOnOpenFile;
|
|
property OnOpenPackage: TOnPkgEvent read FOnOpenPackage
|
|
write FOnOpenPackage;
|
|
property OnOpenPkgFile: TOnOpenPkgFile read FOnOpenPkgFile
|
|
write FOnOpenPkgFile;
|
|
property OnPublishPackage: TOnPkgEvent read FOnPublishPackage
|
|
write FOnPublishPackage;
|
|
property OnRevertPackage: TOnPkgEvent read FOnRevertPackage
|
|
write FOnRevertPackage;
|
|
property OnSavePackage: TOnSavePackage read FOnSavePackage
|
|
write FOnSavePackage;
|
|
property OnUninstallPackage: TOnPkgEvent read FOnUninstallPackage
|
|
write FOnUninstallPackage;
|
|
property OnViewPackageSource: TOnPkgEvent read FOnViewPackageSource
|
|
write FOnViewPackageSource;
|
|
property OnViewPackageToDos: TOnPkgEvent read FOnViewPackageToDos
|
|
write FOnViewPackageToDos;
|
|
end;
|
|
|
|
var
|
|
PackageEditors: TPackageEditors;
|
|
|
|
procedure RegisterStandardPackageEditorMenuItems;
|
|
|
|
implementation
|
|
|
|
uses
|
|
NewDialog;
|
|
|
|
{$R *.lfm}
|
|
|
|
var
|
|
ImageIndexFiles: integer;
|
|
ImageIndexRemovedFiles: integer;
|
|
ImageIndexUnit: integer;
|
|
ImageIndexRegisterUnit: integer;
|
|
ImageIndexLFM: integer;
|
|
ImageIndexLRS: integer;
|
|
ImageIndexInclude: integer;
|
|
ImageIndexIssues: integer;
|
|
ImageIndexText: integer;
|
|
ImageIndexBinary: integer;
|
|
ImageIndexDirectory: integer;
|
|
|
|
procedure RegisterStandardPackageEditorMenuItems;
|
|
var
|
|
AParent: TIDEMenuSection;
|
|
begin
|
|
PackageEditorMenuRoot :=RegisterIDEMenuRoot(PackageEditorMenuRootName);
|
|
PackageEditorMenuFilesRoot:=RegisterIDEMenuRoot(PackageEditorMenuFilesRootName);
|
|
|
|
// register the section for operations on selected files
|
|
PkgEditMenuSectionFile:=RegisterIDEMenuSection(PackageEditorMenuFilesRoot,'File');
|
|
AParent:=PkgEditMenuSectionFile;
|
|
PkgEditMenuAddDiskFile:=RegisterIDEMenuCommand(AParent,'Add disk file',lisPckEditAddFilesFromFileSystem);
|
|
PkgEditMenuAddNewDiskFiles:=RegisterIDEMenuCommand(AParent,'Add new disk files',lisAddNewFilesFromFileSystem);
|
|
PkgEditMenuAddNewFile:=RegisterIDEMenuCommand(AParent,'New file',lisA2PNewFile);
|
|
PkgEditMenuAddNewComp:=RegisterIDEMenuCommand(AParent,'New component',lisMenuNewComponent);
|
|
PkgEditMenuAddNewReqr:=RegisterIDEMenuCommand(AParent,'New requirement',lisProjAddNewRequirement);
|
|
PkgEditMenuAddNewFPMakeReqr:=RegisterIDEMenuCommand(AParent,'New FPMake requirement',lisProjAddNewFPMakeRequirement);
|
|
//
|
|
PkgEditMenuOpenFile:=RegisterIDEMenuCommand(AParent,'Open File',lisOpen);
|
|
PkgEditMenuRemoveFile:=RegisterIDEMenuCommand(AParent,'Remove File',lisPckEditRemoveFile);
|
|
PkgEditMenuReAddFile:=RegisterIDEMenuCommand(AParent,'ReAdd File',lisPckEditReAddFile);
|
|
PkgEditMenuCopyMoveToDirectory:=RegisterIDEMenuCommand(AParent, 'Copy/Move File to Directory', lisCopyMoveFileToDirectory);
|
|
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);
|
|
PkgEditMenuOpenFolder:=RegisterIDEMenuCommand(AParent, 'Open folder', lisMenuOpenFolder);
|
|
|
|
// register the section for operations on dependencies
|
|
PkgEditMenuSectionDependency:=RegisterIDEMenuSection(PackageEditorMenuFilesRoot,'Dependency');
|
|
AParent:=PkgEditMenuSectionDependency;
|
|
PkgEditMenuRemoveDependency:=RegisterIDEMenuCommand(AParent,'Remove Dependency',lisPckEditRemoveDependency);
|
|
PkgEditMenuReAddDependency:=RegisterIDEMenuCommand(AParent,'ReAdd Dependency',lisPckEditReAddDependency);
|
|
PkgEditMenuDepStoreFileNameDefault:=RegisterIDEMenuCommand(AParent,'Dependency Store Filename As Default',lisPckEditStoreFileNameAsDefaultForThisDependency);
|
|
PkgEditMenuDepStoreFileNamePreferred:=RegisterIDEMenuCommand(AParent,'Dependency Store Filename As Preferred',lisPckEditStoreFileNameAsPreferredForThisDependency);
|
|
PkgEditMenuDepClearStoredFileName:=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;
|
|
PkgEditMenuFindInFiles:=RegisterIDEMenuCommand(AParent,'Find in files',srkmecFindInFiles + ' ...');
|
|
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;
|
|
|
|
{ TPackageEditorForm }
|
|
|
|
procedure TPackageEditorForm.PublishClick(Sender: TObject);
|
|
begin
|
|
DoPublishPackage;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.ReAddMenuItemClick(Sender: TObject);
|
|
var
|
|
PkgFile: TPkgFile;
|
|
AFilename: String;
|
|
Dependency: TPkgDependency;
|
|
i: Integer;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
YesToAll: TYesToAllList;
|
|
r: TModalResult;
|
|
begin
|
|
BeginUpdate;
|
|
YesToAll:=TYesToAllList.Create;
|
|
try
|
|
for i:=ItemsTreeView.SelectionCount-1 downto 0 do
|
|
begin
|
|
if not GetNodeDataItem(ItemsTreeView.Selections[i],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;
|
|
r:=TPkgFileCheck.ReAddingFile(LazPackage, PkgFile.FileType, AFilename,
|
|
PackageEditors.OnGetIDEFileInfo,YesToAll);
|
|
if r=mrIgnore then continue;
|
|
if r<>mrOk then exit;
|
|
//PkgFile.Filename:=AFilename;
|
|
Assert(PkgFile.Filename=AFilename, 'TPackageEditorForm.ReAddMenuItemClick: Unexpected Filename.');
|
|
LazPackage.UnremovePkgFile(PkgFile);
|
|
end
|
|
else if Item is TPkgDependency then begin
|
|
Dependency:=TPkgDependency(Item);
|
|
// Re-add dependency
|
|
fForcedFlags:=[pefNeedUpdateRemovedFiles,pefNeedUpdateRequiredPkgs];
|
|
r:=TPkgFileCheck.AddingDependency(LazPackage,Dependency,true);
|
|
if r=mrIgnore then continue;
|
|
if r<>mrOk then exit;
|
|
LazPackage.RemoveRemovedDependency(Dependency);
|
|
PackageGraph.AddDependencyToPackage(LazPackage,Dependency);
|
|
end;
|
|
end;
|
|
LazPackage.Modified:=True;
|
|
finally
|
|
YesToAll.Free;
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
type
|
|
PackageSelType = (pstFile, pstDir, pstDep, pstFPMake, pstFilesNode,
|
|
pstReqPackNode, pstRemFile, pstRemDep);
|
|
PackageSelTypes = set of PackageSelType;
|
|
|
|
procedure TPackageEditorForm.ItemsPopupMenuPopup(Sender: TObject);
|
|
var
|
|
UserSelection: PackageSelTypes;
|
|
SingleSelectedFile: TPkgFile;
|
|
SingleSelectedDep: TPkgDependency;
|
|
|
|
procedure CollectSelected;
|
|
var
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
CurDependency: TPkgDependency;
|
|
CurFile: TPkgFile;
|
|
i: Integer;
|
|
begin
|
|
UserSelection := [];
|
|
SingleSelectedFile := Nil;
|
|
SingleSelectedDep := Nil;
|
|
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 ItemsTreeView.SelectionCount=1 then
|
|
SingleSelectedFile := CurFile;
|
|
if NodeData.Removed then
|
|
Include(UserSelection, pstRemFile)
|
|
else
|
|
Include(UserSelection, pstFile);
|
|
end else if Item is TPkgDependency then begin
|
|
CurDependency := TPkgDependency(Item);
|
|
if (ItemsTreeView.SelectionCount=1) {and Assigned(CurDependency.RequiredPackage)} then
|
|
SingleSelectedDep:=CurDependency;
|
|
if CurDependency.DependencyType=pdtFPMake then
|
|
Include(UserSelection, pstFPMake);
|
|
if NodeData.Removed then
|
|
Include(UserSelection, pstRemDep)
|
|
else
|
|
Include(UserSelection, pstDep);
|
|
end;
|
|
end
|
|
else if IsDirectoryNode(TVNode) then
|
|
Include(UserSelection, pstDir)
|
|
else if TVNode=FFilesNode then
|
|
Include(UserSelection, pstFilesNode)
|
|
else if TVNode=FRequiredPackagesNode then
|
|
Include(UserSelection, pstReqPackNode);
|
|
end;
|
|
end;
|
|
|
|
procedure SetItem(Item: TIDEMenuCommand; AnOnClick: TNotifyEvent;
|
|
aShow: boolean = true; AEnable: boolean = true);
|
|
begin
|
|
Item.OnClick:=AnOnClick;
|
|
Item.Visible:=aShow;
|
|
Item.Enabled:=AEnable;
|
|
end;
|
|
|
|
procedure AddFileTypeMenuItem;
|
|
var
|
|
CurPFT: TPkgFileType;
|
|
VirtualFileExists: Boolean;
|
|
NewMenuItem: TIDEMenuCommand;
|
|
begin
|
|
PkgEditMenuSectionFileType.Visible:=Assigned(SingleSelectedFile);
|
|
if not PkgEditMenuSectionFileType.Visible then Exit;
|
|
PkgEditMenuSectionFileType.Clear;
|
|
VirtualFileExists:=(SingleSelectedFile.FileType=pftVirtualUnit)
|
|
and FileExistsCached(SingleSelectedFile.GetFullFilename);
|
|
for CurPFT:=Low(TPkgFileType) to High(TPkgFileType) do begin
|
|
NewMenuItem:=RegisterIDEMenuCommand(PkgEditMenuSectionFileType,
|
|
'SetFileType'+IntToStr(ord(CurPFT)),
|
|
GetPkgFileTypeLocalizedName(CurPFT),
|
|
@ChangeFileTypeMenuItemClick);
|
|
if CurPFT=SingleSelectedFile.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 FilenameHasPascalExt(SingleSelectedFile.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
|
|
OpenItemEnable, Writable: Boolean;
|
|
OpenItemCapt: String;
|
|
begin
|
|
//debugln(['TPackageEditorForm.FilesPopupMenuPopup START ',ItemsPopupMenu.Items.Count]);
|
|
PackageEditorMenuFilesRoot.MenuItem:=ItemsPopupMenu.Items;
|
|
//debugln(['TPackageEditorForm.FilesPopupMenuPopup START after connect ',ItemsPopupMenu.Items.Count]);
|
|
//PackageEditorMenuRoot.BeginUpdate;
|
|
try
|
|
CollectSelected;
|
|
OpenItemCapt := lisOpen; // May be changed later.
|
|
OpenItemEnable := True;
|
|
Writable := not LazPackage.ReadOnly;
|
|
|
|
// items for Files node and for selected files, under section PkgEditMenuSectionFile
|
|
PkgEditMenuSectionFile.Visible := not (pstDir in UserSelection);
|
|
if PkgEditMenuSectionFile.Visible then
|
|
begin
|
|
// Files root node
|
|
SetItem(PkgEditMenuAddDiskFile, @mnuAddDiskFileClick, UserSelection=[pstFilesNode],
|
|
Writable);
|
|
SetItem(PkgEditMenuAddNewDiskFiles, @mnuAddNewDiskFilesClick, UserSelection=[pstFilesNode],
|
|
Writable);
|
|
SetItem(PkgEditMenuAddNewFile, @mnuAddNewFileClick, UserSelection=[pstFilesNode],
|
|
Writable);
|
|
SetItem(PkgEditMenuAddNewComp, @mnuAddNewCompClick, UserSelection=[pstFilesNode],
|
|
Writable);
|
|
// Required packages root node
|
|
SetItem(PkgEditMenuAddNewReqr, @mnuAddNewReqrClick, UserSelection=[pstReqPackNode],
|
|
Writable);
|
|
SetItem(PkgEditMenuAddNewFPMakeReqr, @mnuAddFPMakeReqClick, UserSelection=[pstReqPackNode],
|
|
Writable);
|
|
// selected files
|
|
SetItem(PkgEditMenuOpenFile, @OpenButtonClick,
|
|
UserSelection*[pstFilesNode,pstReqPackNode,pstFPMake]=[]);
|
|
SetItem(PkgEditMenuRemoveFile, @RemoveBitBtnClick,
|
|
UserSelection=[pstFile], RemoveBitBtn.Enabled);
|
|
SetItem(PkgEditMenuReAddFile, @ReAddMenuItemClick,
|
|
UserSelection=[pstRemFile]);
|
|
SetItem(PkgEditMenuCopyMoveToDirectory, @CopyMoveToDirMenuItemClick,
|
|
(UserSelection=[pstFile]) and LazPackage.HasDirectory);
|
|
AddFileTypeMenuItem;
|
|
SetItem(PkgEditMenuEditVirtualUnit, @EditVirtualUnitMenuItemClick,
|
|
Assigned(SingleSelectedFile) and (SingleSelectedFile.FileType=pftVirtualUnit),
|
|
Writable);
|
|
end;
|
|
|
|
// items for directories, under section PkgEditMenuSectionDirectory
|
|
PkgEditMenuSectionDirectory.Visible := UserSelection<=[pstDir,pstFilesNode];
|
|
if PkgEditMenuSectionDirectory.Visible then
|
|
begin
|
|
SetItem(PkgEditMenuExpandDirectory, @ExpandDirectoryMenuItemClick);
|
|
SetItem(PkgEditMenuCollapseDirectory, @CollapseDirectoryMenuItemClick);
|
|
SetItem(PkgEditMenuUseAllUnitsInDirectory, @UseAllUnitsInDirectoryMenuItemClick);
|
|
SetItem(PkgEditMenuUseNoUnitsInDirectory, @UseNoUnitsInDirectoryMenuItemClick);
|
|
SetItem(PkgEditMenuOpenFolder, @OpenFolderMenuItemClick);
|
|
end;
|
|
|
|
// items for dependencies, under section PkgEditMenuSectionDependency
|
|
PkgEditMenuSectionDependency.Visible := (UserSelection*[pstDep,pstRemDep] <> [])
|
|
or (ItemsTreeView.Selected=FRequiredPackagesNode);
|
|
if PkgEditMenuSectionDependency.Visible then
|
|
begin
|
|
if Assigned(SingleSelectedDep) then
|
|
case SingleSelectedDep.LoadPackageResult of
|
|
lprAvailableOnline:
|
|
OpenItemCapt := lisPckEditInstall;
|
|
lprNotFound:
|
|
if Assigned(OPMInterface) and not OPMInterface.IsPackageListLoaded then
|
|
OpenItemCapt := lisPckEditCheckAvailabilityOnline
|
|
else begin
|
|
//OpenItemCapt := lisUENotFound;
|
|
OpenItemEnable := False;
|
|
end;
|
|
end;
|
|
SetItem(PkgEditMenuRemoveDependency, @RemoveBitBtnClick,
|
|
pstdep in UserSelection, Writable);
|
|
SetItem(PkgEditMenuReAddDependency,@ReAddMenuItemClick,
|
|
pstRemDep in UserSelection, Writable);
|
|
SetItem(PkgEditMenuDepStoreFileNameDefault, @SetDepDefaultFilenameMenuItemClick,
|
|
Assigned(SingleSelectedDep), Writable);
|
|
SetItem(PkgEditMenuDepStoreFileNamePreferred, @SetDepPreferredFilenameMenuItemClick,
|
|
Assigned(SingleSelectedDep), Writable);
|
|
SetItem(PkgEditMenuDepClearStoredFileName, @ClearDependencyFilenameMenuItemClick,
|
|
Assigned(SingleSelectedDep), Writable);
|
|
SetItem(PkgEditMenuCleanDependencies, @CleanDependenciesMenuItemClick,
|
|
Assigned(LazPackage.FirstRequiredDependency), Writable);
|
|
end;
|
|
if PkgEditMenuOpenFile.MenuItem<>nil then
|
|
begin
|
|
PkgEditMenuOpenFile.MenuItem.Caption := OpenItemCapt;
|
|
PkgEditMenuOpenFile.MenuItem.Enabled := OpenItemEnable;
|
|
end;
|
|
finally
|
|
//PackageEditorMenuRoot.EndUpdate;
|
|
SingleSelectedFile := Nil;
|
|
SingleSelectedDep := Nil;
|
|
end;
|
|
//debugln(['TPackageEditorForm.FilesPopupMenuPopup END ',ItemsPopupMenu.Items.Count]); PackageEditorMenuRoot.WriteDebugReport(' ',true);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.ItemsTreeViewAdvancedCustomDrawItem(
|
|
Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState;
|
|
Stage: TCustomDrawStage; var PaintImages, DefaultDraw: Boolean);
|
|
var
|
|
NodeData: TPENodeData;
|
|
r: TRect;
|
|
y: Integer;
|
|
begin
|
|
if Stage=cdPostPaint then begin
|
|
NodeData:=GetNodeData(Node);
|
|
if (NodeData<>nil) then begin
|
|
if (NodeData.Typ=penFile) and (not NodeData.Removed)
|
|
and (NodeData.FileType<>pftVirtualUnit) and FilenameIsAbsolute(NodeData.Name)
|
|
and (not FileExistsCached(NodeData.Name))
|
|
then begin
|
|
r:=Node.DisplayRect(true);
|
|
ItemsTreeView.Canvas.Pen.Color:=clRed;
|
|
y:=(r.Top+r.Bottom) div 2;
|
|
ItemsTreeView.Canvas.Line(r.Left,y,r.Right,y);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.ItemsTreeViewDragDrop(Sender, Source: TObject; X, Y: Integer);
|
|
begin
|
|
PackageEditors.OnDragDropTreeView(Sender, Source, X, Y);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.ItemsTreeViewDragOver(Sender, Source: TObject; X, Y: Integer;
|
|
State: TDragState; var Accept: Boolean);
|
|
var
|
|
TargetTVNode: TTreeNode;
|
|
TargetTVType: TTreeViewInsertMarkType;
|
|
begin
|
|
//debugln(['TPackageEditorForm.ItemsTreeViewDragOver ',DbgSName(Source),' State=',ord(State),' FromSelf=',Source=ItemsTreeView]);
|
|
Accept:=PackageEditors.OnDragOverTreeView(Sender,Source,X,Y,TargetTVNode,TargetTVType);
|
|
if Accept and (State<>dsDragLeave) then
|
|
ItemsTreeView.SetInsertMark(TargetTVNode,TargetTVType)
|
|
else
|
|
ItemsTreeView.SetInsertMark(nil,tvimNone);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.MorePopupMenuPopup(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;
|
|
|
|
var
|
|
Writable, CanPublish: Boolean;
|
|
pcos: TParsedCompilerOptString;
|
|
CurrentPath: String;
|
|
begin
|
|
PackageEditorMenuRoot.MenuItem:=MorePopupMenu.Items;
|
|
//PackageEditorMenuRoot.BeginUpdate;
|
|
try
|
|
Writable:=(not LazPackage.ReadOnly);
|
|
|
|
// under section PkgEditMenuSectionFiles
|
|
SetItem(PkgEditMenuFindInFiles,@FindInFilesMenuItemClick);
|
|
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));
|
|
CanPublish:=(not LazPackage.Missing) and LazPackage.HasDirectory;
|
|
for pcos in [pcosUnitPath,pcosIncludePath] do
|
|
begin
|
|
CurrentPath:=LazPackage.CompilerOptions.ParsedOpts.GetParsedValue(pcos);
|
|
CurrentPath:=CreateRelativeSearchPath(CurrentPath,LazPackage.DirectoryExpanded);
|
|
//debugln(['TPackageEditorForm.MorePopupMenuPopup Unit=',CurrentPath]);
|
|
if Pos('..',CurrentPath)>0 then
|
|
CanPublish:=false;
|
|
end;
|
|
SetItem(PkgEditMenuPublish,@PublishClick,true,CanPublish);
|
|
|
|
// 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
|
|
OpenButtonClick(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
|
|
OpenButtonClick(Nil)
|
|
else if Key = VK_DELETE then
|
|
RemoveBitBtnClick(Nil)
|
|
else if Key = VK_INSERT then
|
|
mnuAddDiskFileClick(Nil)
|
|
else
|
|
Handled := False;
|
|
|
|
if Handled then
|
|
Key := VK_UNKNOWN;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.mnuAddFPMakeReqClick(Sender: TObject);
|
|
begin
|
|
ShowAddFPMakeDepDialog
|
|
end;
|
|
|
|
procedure TPackageEditorForm.mnuAddNewDiskFilesClick(Sender: TObject);
|
|
|
|
function IsNewFile(const aFilename, aValue: string): boolean;
|
|
var
|
|
Ext: String;
|
|
IDEFileFlags: TIDEFileStateFlags;
|
|
begin
|
|
Result:=false;
|
|
if CompareFilenames(ExtractFilename(aFilename),'fpmake.pp')=0 then exit;
|
|
if CompareFilenames(aFilename,LazPackage.GetSrcFilename)=0 then exit;
|
|
|
|
if not FilenameIsPascalUnit(aFilename) then
|
|
begin
|
|
if aValue='Include' then
|
|
begin
|
|
Ext:=ExtractFileExt(aFilename);
|
|
if IsPascalIncExt(PChar(Ext))=pietNone then exit;
|
|
end else
|
|
exit;
|
|
end;
|
|
if LazPackage.FindPkgFile(aFilename,true,true)<>nil then
|
|
exit; // already in package
|
|
if PackageGraph.FindFileInAllPackages(aFilename,true,false)<>nil then
|
|
exit; // already in a package
|
|
PackageEditors.OnGetIDEFileInfo(Self,aFilename,[ifsPartOfProject],IDEFileFlags);
|
|
if ifsPartOfProject in IDEFileFlags then
|
|
exit;
|
|
|
|
Result:=true;
|
|
end;
|
|
|
|
var
|
|
Files: TFilenameToStringTree;
|
|
aFilename, NewUnitName, Msg: String;
|
|
Item: PStringToStringItem;
|
|
Code: TCodeBuffer;
|
|
NewFileType: TPkgFileType;
|
|
NewFlags: TPkgFileFlags;
|
|
begin
|
|
if LazPackage.IsVirtual then exit;
|
|
if TPkgFileCheck.ReadOnlyOk(LazPackage)<>mrOK then exit;
|
|
|
|
Files:=TFilenameToStringTree.Create(true);
|
|
try
|
|
// collect all units from unit and include paths
|
|
CollectFilesInSearchPath(LazPackage.GetUnitPath(false),Files,'Unit');
|
|
CollectFilesInSearchPath(LazPackage.GetIncludePath(false),Files,'Include');
|
|
|
|
// collect new files
|
|
Msg:='';
|
|
for Item in Files do
|
|
begin
|
|
aFilename:=Item^.Name;
|
|
if IsNewFile(aFilename,Item^.Value) then
|
|
Msg+=LineEnding+CreateRelativePath(aFilename,LazPackage.Directory,true,false)
|
|
else
|
|
Item^.Value:='';
|
|
end;
|
|
|
|
if Msg='' then
|
|
begin
|
|
IDEMessageDialog(lisNoNewFileFound,
|
|
lisAllPasPpPIncInUnitIncludePathAreAlreadyInAProjectP, mtInformation, [
|
|
mbOk]
|
|
);
|
|
exit;
|
|
end;
|
|
|
|
// ask user
|
|
Msg:=lisAddTheFollowingFiles+Msg;
|
|
if IDEMessageDialog(lisAddNewDiskFiles, Msg, mtConfirmation, [mbOk, mbCancel
|
|
])<>mrOk then
|
|
exit;
|
|
|
|
// add files
|
|
for Item in Files do begin
|
|
if Item^.Value='' then continue;
|
|
aFilename:=Item^.Name;
|
|
NewFlags:=[];
|
|
Code:=CodeToolBoss.LoadFile(aFilename,true,false);
|
|
NewUnitName:='';
|
|
if FilenameIsPascalUnit(aFilename) then
|
|
NewUnitName:=CodeToolBoss.GetSourceName(Code,false);
|
|
if NewUnitName<>'' then
|
|
NewFileType:=pftUnit
|
|
else
|
|
NewFileType:=pftInclude;
|
|
if CodeToolBoss.HasInterfaceRegisterProc(Code) then
|
|
Include(NewFlags,pffHasRegisterProc);
|
|
LazPackage.AddFile(aFilename,NewUnitName,NewFileType,NewFlags,cpNormal);
|
|
end;
|
|
|
|
finally
|
|
Files.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.mnuAddNewCompClick(Sender: TObject);
|
|
begin
|
|
ShowNewCompDialog;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.mnuAddNewReqrClick(Sender: TObject);
|
|
begin
|
|
ShowAddDepDialog;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.mnuAddNewFileClick(Sender: TObject);
|
|
var
|
|
NewItem: TNewIDEItemTemplate;
|
|
begin
|
|
// Reuse the "New..." dialog for "Add new file".
|
|
if ShowNewIDEItemDialog(NewItem, true)=mrOk then
|
|
DoAddNewFile(NewItem);
|
|
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.SetDepDefaultFilenameMenuItemClick(Sender: TObject);
|
|
begin
|
|
SetDependencyDefaultFilename(false);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.SetDepPreferredFilenameMenuItemClick(Sender: TObject);
|
|
begin
|
|
SetDependencyDefaultFilename(true);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.ClearDependencyFilenameMenuItemClick(Sender: TObject);
|
|
var
|
|
CurDependency: TPkgDependency;
|
|
begin
|
|
CurDependency:=GetSingleSelectedDependency;
|
|
if CurDependency=nil then exit;
|
|
if (LazPackage=nil) or LazPackage.ReadOnly then exit;
|
|
if CurDependency.DefaultFilename='' then exit;
|
|
CurDependency.DefaultFilename:='';
|
|
CurDependency.PreferDefaultFilename:=false;
|
|
LazPackage.Modified:=true;
|
|
UpdateRequiredPackages;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.CollapseDirectoryMenuItemClick(Sender: TObject);
|
|
begin
|
|
DoExpandCollapseDirectory(False);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.MoveUpBtnClick(Sender: TObject);
|
|
begin
|
|
if SortAlphabetically then exit;
|
|
if Assigned(GetSingleSelectedFile) then
|
|
DoMoveCurrentFile(-1)
|
|
else if Assigned(GetSingleSelectedDependency) then
|
|
DoMoveDependency(-1);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.MoveDownBtnClick(Sender: TObject);
|
|
begin
|
|
if SortAlphabetically then exit;
|
|
if Assigned(GetSingleSelectedFile) then
|
|
DoMoveCurrentFile(1)
|
|
else if Assigned(GetSingleSelectedDependency) then
|
|
DoMoveDependency(1)
|
|
end;
|
|
|
|
procedure TPackageEditorForm.OnIdle(Sender: TObject; var Done: Boolean);
|
|
begin
|
|
if fUpdateLock>0 then exit;
|
|
IdleConnected:=false;
|
|
UpdatePending;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.OpenButtonClick(Sender: TObject);
|
|
var
|
|
i: Integer;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
begin
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do
|
|
begin
|
|
if GetNodeDataItem(ItemsTreeView.Selections[i],NodeData,Item) then
|
|
begin
|
|
if Item is TPkgFile then
|
|
begin
|
|
if PackageEditors.OpenPkgFile(Self,TPkgFile(Item))<>mrOk then
|
|
Exit;
|
|
end
|
|
else if Item is TPkgDependency then
|
|
if not OpmAddOrOpenDependency(TPkgDependency(Item)) then
|
|
Exit;
|
|
end;
|
|
end;
|
|
OpmInstallPendingDependencies;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.OptionsBitBtnClick(Sender: TObject);
|
|
const
|
|
Settings: array[Boolean] of TIDEOptionsEditorSettings = (
|
|
[],
|
|
[ioesReadOnly]
|
|
);
|
|
begin
|
|
Package1 := LazPackage;
|
|
Package1.IDEOptions.OnBeforeRead:=PackageEditors.OnBeforeReadPackage;
|
|
Package1.IDEOptions.OnAfterWrite:=PackageEditors.OnAfterWritePackage;
|
|
LazarusIDE.DoOpenIDEOptions(nil,
|
|
Format(lisPckEditOptionsForPackage, [LazPackage.IDAsString]),
|
|
[TPackageIDEOptions, TPkgCompilerOptions], Settings[LazPackage.ReadOnly]);
|
|
UpdateTitle;
|
|
UpdateButtons;
|
|
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);
|
|
begin
|
|
CanClose:=CanCloseEditor=mrOK;
|
|
if CanClose then
|
|
Application.ReleaseComponent(Self);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.RegisteredListBoxDrawItem(Control: TWinControl;
|
|
Index: Integer; ARect: TRect; State: TOwnerDrawState);
|
|
var
|
|
CurComponent: TPaletteComponent;
|
|
CurStr: string;
|
|
CurObject: TObject;
|
|
TxtH: Integer;
|
|
IconWidth: Integer;
|
|
IconHeight: Integer;
|
|
IL: TCustomImageList;
|
|
II: TImageIndex;
|
|
Res: TScaledImageListResolution;
|
|
l25PPIScaled: 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 TPaletteComponent then begin
|
|
// draw registered component
|
|
CurComponent:=TPaletteComponent(CurObject);
|
|
with FPropGui.RegisteredListBox do begin
|
|
if Assigned(CurComponent.RealPage) then
|
|
CurStr:=Format(lisPckEditPage,[CurComponent.ComponentClass.ClassName,
|
|
CurComponent.RealPage.PageName])
|
|
else
|
|
CurStr:=CurComponent.ComponentClass.ClassName;
|
|
TxtH:=Canvas.TextHeight(CurStr);
|
|
Canvas.FillRect(ARect);
|
|
IL:=CurComponent.Images;
|
|
II:=CurComponent.ImageIndex;
|
|
l25PPIScaled:=ARect.Bottom - ARect.Top;
|
|
//DebugLn('TPackageEditorForm.RegisteredListBoxDrawItem ',DbgSName(CurIcon),' ',CurComponent.ComponentClass.ClassName);
|
|
if (IL<>nil) and (II>=0) then begin
|
|
Res := IL.ResolutionForControl[0, Self];
|
|
IconWidth:=Res.Width;
|
|
IconHeight:=Res.Height;
|
|
Res.Draw(Canvas,
|
|
ARect.Left+(l25PPIScaled-IconWidth) div 2,
|
|
ARect.Top+(ARect.Bottom-ARect.Top-IconHeight) div 2, II);
|
|
end;
|
|
Canvas.TextOut(ARect.Left+l25PPIScaled,
|
|
ARect.Top+(ARect.Bottom-ARect.Top-TxtH) div 2, CurStr);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.RemoveBitBtnClick(Sender: TObject);
|
|
var
|
|
MainUnitSelected: Boolean;
|
|
FileWarning, PkgWarning: String;
|
|
FileCount, PkgCount: Integer;
|
|
|
|
procedure CheckFileSelection(CurFile: TPkgFile);
|
|
begin
|
|
inc(FileCount);
|
|
if CurFile.FileType=pftMainUnit then
|
|
MainUnitSelected:=true;
|
|
if FileWarning='' then
|
|
FileWarning:=Format(lisPckEditRemoveFileFromPackage,
|
|
[CurFile.Filename, LineEnding, LazPackage.IDAsString]);
|
|
end;
|
|
|
|
procedure CheckPkgSelection(CurDependency: TPkgDependency);
|
|
begin
|
|
inc(PkgCount);
|
|
if PkgWarning='' then
|
|
PkgWarning:=Format(lisPckEditRemoveDependencyFromPackage,
|
|
[CurDependency.AsString, LineEnding, LazPackage.IDAsString]);
|
|
end;
|
|
|
|
function ConfirmFileDeletion: TModalResult;
|
|
var
|
|
mt: TMsgDlgType;
|
|
s: String;
|
|
begin
|
|
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;
|
|
Result:=IDEMessageDialog(lisPckEditRemoveFile2, s, mt, [mbYes,mbNo]);
|
|
end;
|
|
|
|
function ConfirmPkgDeletion: TModalResult;
|
|
var
|
|
mt: TMsgDlgType;
|
|
s: String;
|
|
begin
|
|
mt:=mtConfirmation;
|
|
if PkgCount=1 then
|
|
s:=PkgWarning
|
|
else
|
|
s:=Format(lisRemoveDependenciesFromPackage, [IntToStr(PkgCount), LazPackage.Name]);
|
|
Result:=IDEMessageDialog(lisRemove2, s, mt, [mbYes, mbNo]);
|
|
end;
|
|
|
|
var
|
|
ANode: TTreeNode;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
FilesBranch: TTreeFilterBranch;
|
|
i: Integer;
|
|
begin
|
|
BeginUpdate;
|
|
try
|
|
ANode:=ItemsTreeView.Selected;
|
|
if (ANode=nil) or LazPackage.ReadOnly then begin
|
|
UpdateButtons;
|
|
exit;
|
|
end;
|
|
|
|
MainUnitSelected:=false;
|
|
FileCount:=0;
|
|
FileWarning:='';
|
|
PkgCount:=0;
|
|
PkgWarning:='';
|
|
|
|
// check selection
|
|
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
|
|
CheckFileSelection(TPkgFile(Item))
|
|
else if Item is TPkgDependency then
|
|
CheckPkgSelection(TPkgDependency(Item));
|
|
end;
|
|
if (FileCount=0) and (PkgCount=0) then begin
|
|
UpdateButtons;
|
|
exit;
|
|
end;
|
|
|
|
// confirm deletion
|
|
if FileCount>0 then begin
|
|
if ConfirmFileDeletion<>mrYes then Exit;
|
|
FilesBranch:=FilterEdit.GetExistingBranch(FFilesNode);
|
|
end;
|
|
if (PkgCount>0) and (ConfirmPkgDeletion<>mrYes) then Exit;
|
|
|
|
// remove
|
|
for i:=ItemsTreeView.SelectionCount-1 downto 0 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
|
|
FilesBranch.DeleteData(TVNode);
|
|
LazPackage.RemoveFileSilently(TPkgFile(Item));
|
|
end
|
|
else if Item is TPkgDependency then
|
|
LazPackage.RemoveRequiredDepSilently(TPkgDependency(Item));
|
|
end;
|
|
if FileCount>0 then // Force update for removed files only.
|
|
fForcedFlags:=fForcedFlags+[pefNeedUpdateRemovedFiles];
|
|
if PkgCount>0 then
|
|
fForcedFlags:=fForcedFlags+[pefNeedUpdateRemovedFiles,pefNeedUpdateRequiredPkgs];
|
|
LazPackage.Modified:=True;
|
|
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.EditVirtualUnitMenuItemClick(Sender: TObject);
|
|
begin
|
|
DoEditVirtualUnit;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.ExpandDirectoryMenuItemClick(Sender: TObject);
|
|
begin
|
|
DoExpandCollapseDirectory(True);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.FilterEditKeyDown(Sender: TObject; var Key: Word;
|
|
Shift: TShiftState);
|
|
begin
|
|
if Key = VK_RETURN then
|
|
begin
|
|
OpenButtonClick(Nil);
|
|
Key := VK_UNKNOWN;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.FindInFilesMenuItemClick(Sender: TObject);
|
|
begin
|
|
DoFindInFiles;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.FormCreate(Sender: TObject);
|
|
begin
|
|
FPlugins:=TStringList.Create;
|
|
FPropGui:=TProjPackFilePropGui.Create(CommonOptionsTabSheet, True);
|
|
SetupComponents;
|
|
SortAlphabetically := EnvironmentOptions.PackageEditorSortAlphabetically;
|
|
ShowDirectoryHierarchy := EnvironmentOptions.PackageEditorShowDirHierarchy;
|
|
if OPMInterface <> nil then
|
|
OPMInterface.AddPackageListNotification(@PackageListAvailable);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.FormDestroy(Sender: TObject);
|
|
begin
|
|
if OPMInterface <> nil then
|
|
OPMInterface.RemovePackageListNotification(@PackageListAvailable);
|
|
IdleConnected:=false;
|
|
FreeAndNil(FNextSelectedPart);
|
|
EnvironmentOptions.PackageEditorSortAlphabetically := SortAlphabetically;
|
|
EnvironmentOptions.PackageEditorShowDirHierarchy := ShowDirectoryHierarchy;
|
|
FilterEdit.ForceFilter('');
|
|
if PackageEditorMenuRoot.MenuItem=ItemsPopupMenu.Items then
|
|
PackageEditorMenuRoot.MenuItem:=nil;
|
|
FreeAndNil(FPropGui);
|
|
PackageEditors.DoFreeEditor(LazPackage);
|
|
FLazPackage:=nil;
|
|
FreeAndNil(FPlugins);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.FormDropFiles(Sender: TObject;
|
|
const FileNames: array of String);
|
|
var
|
|
Files: TStringList;
|
|
begin
|
|
{$IFDEF VerbosePkgEditDrag}
|
|
debugln(['TPackageEditorForm.FormDropFiles ',length(FileNames)]);
|
|
{$ENDIF}
|
|
if length(FileNames)=0 then exit;
|
|
|
|
//debugln(['TPackageEditorForm.FormDropFiles ']);
|
|
// the Drop event comes before the Application activate event or not at all
|
|
// => invalidate file state
|
|
InvalidateFileStateCache;
|
|
|
|
Files:=TStringList.Create;
|
|
try
|
|
Files.AddStrings(FileNames);
|
|
AddUserFiles(Files);
|
|
finally
|
|
Files.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.FormResize(Sender: TObject);
|
|
begin
|
|
PropsGroupBox.Constraints.MaxHeight := self.Height - ToolBar.Height - FilterPanel.Height
|
|
- StatusBar.Height - 20;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.RevertClick(Sender: TObject);
|
|
begin
|
|
DoRevert;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.SaveBitBtnClick(Sender: TObject);
|
|
begin
|
|
DoSave(false);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.SelectFileNode(const AFileName: string);
|
|
function _FindInChildren(_Parent: TTreeNode): TTreeNode;
|
|
var
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
PFile: TPkgFile;
|
|
begin
|
|
Result := nil;
|
|
|
|
TVNode:=_Parent.GetFirstChild;
|
|
while Assigned(TVNode) do
|
|
begin
|
|
if GetNodeDataItem(TVNode,NodeData,Item) and (Item is TPkgFile) then
|
|
begin
|
|
PFile := TPkgFile(Item);
|
|
if SameFileName(PFile.GetFullFilename, AFileName) then
|
|
Exit(TVNode);
|
|
end;
|
|
if TVNode.HasChildren then
|
|
begin
|
|
Result := _FindInChildren(TVNode);
|
|
if Assigned(Result) then
|
|
Exit;
|
|
end;
|
|
TVNode := TVNode.GetNextSibling;
|
|
end;
|
|
end;
|
|
var
|
|
FileNode: TTreeNode;
|
|
begin
|
|
if not Assigned(FFilesNode) then
|
|
Exit;
|
|
FileNode := _FindInChildren(FFilesNode);
|
|
if Assigned(FileNode) then
|
|
begin
|
|
ItemsTreeView.BeginUpdate;
|
|
try
|
|
ItemsTreeView.ClearSelection;
|
|
ItemsTreeView.Selected := FileNode;
|
|
finally
|
|
ItemsTreeView.EndUpdate;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.AddUserFiles(Filenames: TStrings);
|
|
var
|
|
YesToAll: TYesToAllList;
|
|
NewUnitPaths, NewIncPaths, NewFilename: String;
|
|
r: TModalResult;
|
|
i, j: Integer;
|
|
begin
|
|
if Filenames.Count=0 then exit;
|
|
YesToAll:=TYesToAllList.Create;
|
|
BeginUpdate;
|
|
try
|
|
NewUnitPaths:='';
|
|
NewIncPaths:='';
|
|
for i:=0 to Filenames.Count-1 do
|
|
begin
|
|
NewFilename:=ExpandFileNameUTF8(Filenames[i]);
|
|
j:=i-1;
|
|
while (j>=0) and (CompareFilenames(NewFilename,Filenames[j])<>0) do
|
|
dec(j);
|
|
if j>=0 then begin
|
|
debugln(['Warning: (lazarus) TPackageEditorForm.AddUserFiles ignoring duplicate "',NewFilename,'"']);
|
|
continue;
|
|
end;
|
|
r:=TPkgFileCheck.AddingFile(LazPackage, NewFilename,
|
|
PackageEditors.OnGetIDEFileInfo,YesToAll);
|
|
if r=mrOK then
|
|
LazPackage.AddFileByName(NewFilename, NewUnitPaths, NewIncPaths)
|
|
else if r=mrAbort then
|
|
break;
|
|
end;
|
|
// extend unit and include search path
|
|
if not LazPackage.ExtendUnitSearchPath(NewUnitPaths) then exit;
|
|
if not LazPackage.ExtendIncSearchPath(NewIncPaths) then exit;
|
|
finally
|
|
YesToAll.Free;
|
|
EndUpdate;
|
|
end;
|
|
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.ViewPkgSourceClick(Sender: TObject);
|
|
begin
|
|
PackageEditors.ViewPkgSource(LazPackage);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.ViewPkgTodosClick(Sender: TObject);
|
|
begin
|
|
PackageEditors.ViewPkgToDos(LazPackage);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.UseAllUnitsInDirectoryMenuItemClick(Sender: TObject);
|
|
begin
|
|
DoUseUnitsInDirectory(true);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.UseNoUnitsInDirectoryMenuItemClick(Sender: TObject);
|
|
begin
|
|
DoUseUnitsInDirectory(false);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.OpenFolderMenuItemClick(Sender: TObject);
|
|
begin
|
|
OpenDocument(LazPackage.Directory);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.mnuAddDiskFileClick(Sender: TObject);
|
|
var
|
|
OpenDialog: TOpenDialog;
|
|
i: Integer;
|
|
begin
|
|
// is readonly
|
|
if TPkgFileCheck.ReadOnlyOk(LazPackage)<>mrOK then exit;
|
|
OpenDialog:=TOpenDialog.Create(nil);
|
|
try
|
|
InputHistories.ApplyFileDialogSettings(OpenDialog);
|
|
OpenDialog.InitialDir:=LazPackage.GetFileDialogInitialDir(OpenDialog.InitialDir);
|
|
OpenDialog.Title:=lisOpenFile;
|
|
OpenDialog.Options:=OpenDialog.Options
|
|
+[ofFileMustExist,ofPathMustExist,ofAllowMultiSelect];
|
|
OpenDialog.Filter:=
|
|
dlgFilterAll+' ('+GetAllFilesMask+')|'+GetAllFilesMask
|
|
+'|'+dlgFilterLazarusUnit+' (*.pas;*.pp)|*.pas;*.pp'
|
|
+'|'+dlgFilterLazarusProject+' (*.lpi)|*.lpi'
|
|
+'|'+dlgFilterLazarusForm+' (*.lfm;*.dfm;*.fmx)|*.lfm;*.dfm;*.fmx'
|
|
+'|'+dlgFilterLazarusPackage+' (*.lpk)|*.lpk'
|
|
+'|'+dlgFilterLazarusProjectSource+' (*.lpr)|*.lpr';
|
|
if OpenDialog.Execute then
|
|
begin
|
|
InputHistories.StoreFileDialogSettings(OpenDialog);
|
|
AddUserFiles(OpenDialog.Files);
|
|
end;
|
|
finally
|
|
OpenDialog.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.AddToUsesPkgSectionCheckBoxChange(Sender: TObject);
|
|
var
|
|
CurFile: TPkgFile;
|
|
OtherFile: TPkgFile;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
i, j: Integer;
|
|
begin
|
|
if LazPackage=nil then exit;
|
|
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.AddToUsesPkgSection=FPropGui.AddToUsesPkgSectionCheckBox.Checked then continue;
|
|
// change flag
|
|
CurFile.AddToUsesPkgSection:=FPropGui.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 (CompareText(OtherFile.Unit_Name,CurFile.Unit_Name)=0) then
|
|
OtherFile.AddToUsesPkgSection:=false;
|
|
end;
|
|
end;
|
|
LazPackage.Modified:=True;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.AddToProjectClick(Sender: TObject);
|
|
begin
|
|
if LazPackage=nil then exit;
|
|
PackageEditors.AddToProject(LazPackage,false);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.ApplyDependencyButtonClick(Sender: TObject);
|
|
var
|
|
CurDependency: TPkgDependency;
|
|
begin
|
|
CurDependency:=GetSingleSelectedDependency;
|
|
if (LazPackage=nil) or (CurDependency=nil)
|
|
or not FPropGui.CheckApplyDependency(CurDependency) then exit;
|
|
LazPackage.Modified:=True;
|
|
PkgBoss.ApplyDependency(CurDependency);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.CallRegisterProcCheckBoxChange(Sender: TObject);
|
|
var
|
|
CurFile: TPkgFile;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
i: Integer;
|
|
begin
|
|
if LazPackage=nil then exit;
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) or not (Item is TPkgFile) then
|
|
continue;
|
|
CurFile:=TPkgFile(Item);
|
|
if not (CurFile.FileType in PkgFileUnitTypes)
|
|
or CurFile.HasRegisterProc=FPropGui.CallRegisterProcCheckBox.Checked then
|
|
continue;
|
|
CurFile.HasRegisterProc:=FPropGui.CallRegisterProcCheckBox.Checked;
|
|
if not NodeData.Removed then
|
|
LazPackage.Modified:=True;
|
|
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
|
|
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 FilenameHasPascalExt(CurFile.Filename))
|
|
and (CurPFT in PkgFileUnitTypes) then
|
|
continue;
|
|
CurFile.FileType:=CurPFT;
|
|
if not NodeData.Removed then
|
|
LazPackage.Modified:=True;
|
|
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;
|
|
BeginUpdate;
|
|
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 begin
|
|
fForcedFlags:=[pefNeedUpdateRemovedFiles,pefNeedUpdateRequiredPkgs];
|
|
PackageGraph.RemoveDependencyFromPackage(LazPackage,Dependency,true);
|
|
end;
|
|
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,true);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.CompileCleanClick(Sender: TObject);
|
|
begin
|
|
DoCompile(true,false,true);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.CopyMoveToDirMenuItemClick(Sender: TObject);
|
|
begin
|
|
PackageEditors.OnCopyMoveFiles(Self);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.CompileBitBtnClick(Sender: TObject);
|
|
begin
|
|
DoCompile(false,false,true);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.CreateMakefileClick(Sender: TObject);
|
|
begin
|
|
PackageEditors.CreateMakefile(LazPackage);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.CreateFpmakeFileClick(Sender: TObject);
|
|
begin
|
|
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;
|
|
BeginUpdate;
|
|
try
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do begin
|
|
TVNode:=ItemsTreeView.Selections[i];
|
|
if not GetNodeDataItem(TVNode,NodeData,Item) or not (Item is TPkgFile) then
|
|
continue;
|
|
CurFile:=TPkgFile(Item);
|
|
if not (CurFile.FileType in PkgFileUnitTypes)
|
|
or CurFile.DisableI18NForLFM=FPropGui.DisableI18NForLFMCheckBox.Checked then
|
|
continue;
|
|
CurFile.DisableI18NForLFM:=FPropGui.DisableI18NForLFMCheckBox.Checked;
|
|
if not NodeData.Removed then
|
|
LazPackage.Modified:=true;
|
|
end;
|
|
finally
|
|
EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.SetLazPackage(const AValue: TLazPackage);
|
|
begin
|
|
//force editor name change when package name changed!
|
|
if (FLazPackage=Nil)
|
|
and ( (AValue=Nil) or (Name=PkgNameToFormName(AValue.Name)) )
|
|
then
|
|
exit;
|
|
if FLazPackage<>nil then
|
|
begin
|
|
FLazPackage.Editor:=nil;
|
|
if EnvironmentOptions.LastOpenPackages.Remove(FLazPackage.Filename) then
|
|
MainIDE.SaveEnvironment;
|
|
end;
|
|
FLazPackage:=AValue;
|
|
if FLazPackage=nil then begin
|
|
Name:=Name+'___off___';
|
|
exit;
|
|
end;
|
|
EnvironmentOptions.LastOpenPackages.Add(FLazPackage.Filename);
|
|
MainIDE.SaveEnvironment;
|
|
FLazPackage.Editor:=Self;
|
|
// set Name and update components.
|
|
UpdateAll(true);
|
|
end;
|
|
|
|
function TPackageEditorForm.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(AImageName);
|
|
Result.ShowHint := True;
|
|
Result.OnClick := AOnClick;
|
|
Result.AutoSize := True;
|
|
Result.Parent := ToolBar;
|
|
end;
|
|
|
|
function TPackageEditorForm.CreateDivider: TToolButton;
|
|
begin
|
|
Result := TToolButton.Create(Self);
|
|
Result.Style := tbsDivider;
|
|
Result.AutoSize := True;
|
|
Result.Parent := ToolBar;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.SetupComponents;
|
|
begin
|
|
ImageIndexFiles := IDEImages.LoadImage('pkg_files');
|
|
ImageIndexRemovedFiles := IDEImages.LoadImage('pkg_removedfiles');
|
|
ImageIndexUnit := IDEImages.LoadImage('pkg_unit');
|
|
ImageIndexRegisterUnit := IDEImages.LoadImage('pkg_registerunit');
|
|
ImageIndexLFM := IDEImages.LoadImage('pkg_lfm');
|
|
ImageIndexLRS := IDEImages.LoadImage('pkg_lrs');
|
|
ImageIndexInclude := IDEImages.LoadImage('pkg_include');
|
|
ImageIndexIssues := IDEImages.LoadImage('pkg_issues');
|
|
ImageIndexText := IDEImages.LoadImage('pkg_text');
|
|
ImageIndexBinary := IDEImages.LoadImage('pkg_binary');
|
|
ImageIndexDirectory := IDEImages.LoadImage('pkg_files');
|
|
|
|
ItemsTreeView.Images := IDEImages.Images_16;
|
|
ToolBar.Images := IDEImages.Images_16;
|
|
FilterEdit.OnGetImageIndex:=@TreeViewGetImageIndex;
|
|
|
|
SaveBitBtn := CreateToolButton('SaveBitBtn', lisMenuSave, lisPckEditSavePackage, 'laz_save', @SaveBitBtnClick);
|
|
CompileBitBtn := CreateToolButton('CompileBitBtn', lisCompile, lisPckEditCompilePackage, 'pkg_compile', @CompileBitBtnClick);
|
|
UseBitBtn := CreateToolButton('UseBitBtn', lisUse, lisClickToSeeTheChoices, 'pkg_install', nil);
|
|
UseBitBtn.Style:=tbsButtonDrop;
|
|
CreateDivider;
|
|
AddBitBtn := CreateToolButton('AddBitBtn', lisAdd, lisClickToSeeTheChoices, 'laz_add', nil);
|
|
AddBitBtn.Style:=tbsButtonDrop;
|
|
RemoveBitBtn := CreateToolButton('RemoveBitBtn', lisRemove, lisPckEditRemoveSelectedItem, 'laz_delete', @RemoveBitBtnClick);
|
|
CreateDivider;
|
|
OptionsBitBtn := CreateToolButton('OptionsBitBtn', lisOptions, lisPckEditEditGeneralOptions, 'pkg_properties', @OptionsBitBtnClick);
|
|
HelpBitBtn := CreateToolButton('HelpBitBtn', GetButtonCaption(idButtonHelp), lisMenuOnlineHelp, 'btn_help', @HelpBitBtnClick);
|
|
MoreBitBtn := CreateToolButton('MoreBitBtn', lisMoreSub, lisPkgEdMoreFunctionsForThePackage, '', nil);
|
|
MoreBitBtn.Style:=tbsButtonDrop;
|
|
|
|
UseBitBtn.DropdownMenu := UsePopupMenu;
|
|
AddBitBtn.DropdownMenu := AddPopupMenu;
|
|
MoreBitBtn.DropdownMenu := MorePopupMenu;
|
|
|
|
mnuAddDiskFile.Caption := lisPckEditAddFilesFromFileSystem;
|
|
mnuAddNewDiskFiles.Caption := lisAddNewFilesFromFileSystem;
|
|
mnuAddNewFile.Caption := lisA2PNewFile;
|
|
mnuAddNewComp.Caption := lisMenuNewComponent;
|
|
mnuAddNewReqr.Caption := lisProjAddNewRequirement;
|
|
mnuAddFPMakeReq.Caption := lisProjAddNewFPMakeRequirement;
|
|
|
|
// Buttons on FilterPanel
|
|
IDEImages.AssignImage(OpenButton, 'laz_open');
|
|
OpenButton.Hint:=lisOpenFile2;
|
|
SortAlphabeticallyButton.Hint:=lisPESortFilesAlphabetically;
|
|
IDEImages.AssignImage(SortAlphabeticallyButton, 'pkg_sortalphabetically');
|
|
DirectoryHierarchyButton.Hint:=lisPEShowDirectoryHierarchy;
|
|
IDEImages.AssignImage(DirectoryHierarchyButton, 'pkg_hierarchical');
|
|
|
|
// Up / Down buttons
|
|
IDEImages.AssignImage(MoveUpBtn, 'arrow_up');
|
|
IDEImages.AssignImage(MoveDownBtn, 'arrow_down');
|
|
MoveUpBtn.Hint:=lisMoveSelectedUp;
|
|
MoveDownBtn.Hint:=lisMoveSelectedDown;
|
|
|
|
// file properties
|
|
FPropGui.AddToUsesPkgSectionCheckBox.OnChange := @AddToUsesPkgSectionCheckBoxChange;
|
|
FPropGui.CallRegisterProcCheckBox.OnChange := @CallRegisterProcCheckBoxChange;
|
|
FPropGui.RegisteredListBox.OnDrawItem := @RegisteredListBoxDrawItem;
|
|
FPropGui.DisableI18NForLFMCheckBox.OnChange := @DisableI18NForLFMCheckBoxChange;
|
|
// dependency properties
|
|
FPropGui.OnGetPkgDep := @GetDependencyToUpdate;
|
|
FPropGui.ApplyDependencyButton.OnClick := @ApplyDependencyButtonClick;
|
|
|
|
ItemsTreeView.BeginUpdate;
|
|
FFilesNode:=ItemsTreeView.Items.Add(nil, dlgEnvFiles);
|
|
FFilesNode.ImageIndex:=ImageIndexFiles;
|
|
FFilesNode.SelectedIndex:=FFilesNode.ImageIndex;
|
|
FRequiredPackagesNode:=ItemsTreeView.Items.Add(nil, lisPckEditRequiredPackages);
|
|
FRequiredPackagesNode.ImageIndex:=FPropGui.ImageIndexRequired;
|
|
FRequiredPackagesNode.SelectedIndex:=FRequiredPackagesNode.ImageIndex;
|
|
ItemsTreeView.EndUpdate;
|
|
|
|
PropsGroupBox.Caption:=lisPckEditFileProperties;
|
|
CommonOptionsTabSheet.Caption:=lisPckEditCommonOptions;
|
|
|
|
FDirSummaryLabel:=TLabel.Create(Self);
|
|
FDirSummaryLabel.Name:='DirSummaryLabel';
|
|
FDirSummaryLabel.Parent:=CommonOptionsTabSheet;
|
|
CreatePackageFileEditors;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.SetDependencyDefaultFilename(AsPreferred: boolean);
|
|
var
|
|
NewFilename: String;
|
|
CurDependency: TPkgDependency;
|
|
begin
|
|
if LazPackage=nil then exit;
|
|
CurDependency:=GetSingleSelectedDependency;
|
|
if CurDependency=nil then begin
|
|
debugln(['Info: [TPackageEditorForm.SetDependencyDefaultFilename] CurDependency=nil']);
|
|
exit;
|
|
end;
|
|
if LazPackage.ReadOnly then begin
|
|
debugln(['Info: [TPackageEditorForm.SetDependencyDefaultFilename] ReadOnly']);
|
|
exit;
|
|
end;
|
|
if CurDependency.RequiredPackage=nil then begin
|
|
debugln(['Info: [TPackageEditorForm.SetDependencyDefaultFilename] RequiredPackage=nil']);
|
|
exit;
|
|
end;
|
|
NewFilename:=CurDependency.RequiredPackage.Filename;
|
|
if (NewFilename=CurDependency.DefaultFilename)
|
|
and (CurDependency.PreferDefaultFilename=AsPreferred) then begin
|
|
debugln(['Info: [TPackageEditorForm.SetDependencyDefaultFilename] PreferDefaultFilename=AsPreferred']);
|
|
exit;
|
|
end;
|
|
BeginUpdate;
|
|
try
|
|
CurDependency.DefaultFilename:=NewFilename;
|
|
CurDependency.PreferDefaultFilename:=AsPreferred;
|
|
LazPackage.Modified:=true;
|
|
UpdateRequiredPackages;
|
|
debugln(['Info: TPackageEditorForm.SetDependencyDefaultFilename ',CurDependency.PackageName,' DefaultFilename:=',NewFilename,' AsPreferred=',AsPreferred]);
|
|
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;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.SetSortAlphabetically(const AValue: boolean);
|
|
begin
|
|
if FSortAlphabetically=AValue then exit;
|
|
FSortAlphabetically:=AValue;
|
|
SortAlphabeticallyButton.Down:=FSortAlphabetically;
|
|
FilterEdit.SortData:=FSortAlphabetically;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.UpdateAll(Immediately: boolean);
|
|
begin
|
|
if csDestroying in ComponentState then exit;
|
|
if LazPackage=nil then exit;
|
|
Name:=PkgNameToFormName(LazPackage.Name);
|
|
if fForcedFlags<>[] then
|
|
fFlags:=fFlags+fForcedFlags // Flags forcing a partial update
|
|
else
|
|
fFlags:=fFlags+[ // Otherwise all flags.
|
|
pefNeedUpdateTitle,
|
|
pefNeedUpdateFiles,
|
|
pefNeedUpdateRemovedFiles,
|
|
pefNeedUpdateRequiredPkgs,
|
|
pefNeedUpdateProperties,
|
|
pefNeedUpdateButtons,
|
|
pefNeedUpdateApplyDependencyButton,
|
|
pefNeedUpdateStatusBar];
|
|
if Immediately then
|
|
UpdatePending
|
|
else
|
|
IdleConnected:=true;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoAddNewFile(NewItem: TNewIDEItemTemplate);
|
|
var
|
|
NewFilename, NewUnitName: String;
|
|
NewFileType: TPkgFileType;
|
|
NewFlags: TPkgFileFlags;
|
|
Desc: TProjectFileDescriptor;
|
|
CodeBuffer: TCodeBuffer;
|
|
begin
|
|
if not (NewItem is TNewItemProjectFile) then exit;
|
|
// create new file
|
|
Desc:=TNewItemProjectFile(NewItem).Descriptor;
|
|
NewFilename:='';
|
|
if LazarusIDE.DoNewFile(Desc,NewFilename,'',
|
|
[nfOpenInEditor,nfCreateDefaultSrc,nfIsNotPartOfProject],LazPackage)<>mrOk
|
|
then exit;
|
|
// success -> now add it to package
|
|
NewUnitName:='';
|
|
NewFileType:=FileNameToPkgFileType(NewFilename);
|
|
NewFlags:=[];
|
|
if (NewFileType in PkgFileUnitTypes) then begin
|
|
Include(NewFlags,pffAddToPkgUsesSection);
|
|
CodeBuffer:=CodeToolBoss.LoadFile(NewFilename,true,false);
|
|
if CodeBuffer<>nil then begin
|
|
NewUnitName:=CodeToolBoss.GetSourceName(CodeBuffer,false);
|
|
if CodeToolBoss.HasInterfaceRegisterProc(CodeBuffer) then
|
|
Include(NewFlags,pffHasRegisterProc);
|
|
end
|
|
else
|
|
NewUnitName:=ExtractFilenameOnly(NewFilename);
|
|
end;
|
|
DebugLn(['TPackageEditorForm.DoAddNewFile: NewUnitName=', NewUnitName,
|
|
', NewFilename=', NewFilename]);
|
|
LazPackage.AddFile(NewFilename,NewUnitName,NewFileType,NewFlags,cpNormal);
|
|
FreeAndNil(FNextSelectedPart);
|
|
FNextSelectedPart:=TPENodeData.Create(penFile,NewFilename,false);
|
|
end;
|
|
|
|
function TPackageEditorForm.ShowNewCompDialog: TModalResult;
|
|
var
|
|
IgnoreUnitPaths: TFilenameToStringTree;
|
|
|
|
function PkgDependsOn(PkgName: string): boolean;
|
|
begin
|
|
if PkgName='' then exit(false);
|
|
Result:=PackageGraph.FindDependencyRecursively(LazPackage.FirstRequiredDependency,PkgName)<>nil;
|
|
end;
|
|
|
|
procedure AddNewComponent(AddParams: TAddToPkgResult);
|
|
begin
|
|
ExtendUnitIncPathForNewUnit(AddParams.UnitFilename, '', IgnoreUnitPaths);
|
|
// add file
|
|
with AddParams do
|
|
begin
|
|
Assert(FilenameIsAbsolute(UnitFilename), 'AddNewComponent: Filename is relative.');
|
|
// This file can also replace an existing file.
|
|
if LazPackage.FindPkgFile(UnitFilename,true,false)=nil then
|
|
LazPackage.AddFile(UnitFilename, Unit_Name, FileType, PkgFileFlags, cpNormal)
|
|
else
|
|
LazPackage.Modified:=True;
|
|
FreeAndNil(FNextSelectedPart);
|
|
FNextSelectedPart:=TPENodeData.Create(penFile, UnitFilename, false);
|
|
PackageEditors.DeleteAmbiguousFiles(LazPackage, UnitFilename);
|
|
end;
|
|
// open file in editor
|
|
PackageEditors.CreateNewFile(Self,AddParams);
|
|
end;
|
|
|
|
var
|
|
AddParams, OldParams: TAddToPkgResult;
|
|
begin
|
|
if LazPackage.ReadOnly then begin
|
|
UpdateButtons;
|
|
exit(mrCancel);
|
|
end;
|
|
|
|
Result:=ShowAddToPackageDlg(LazPackage, AddParams);
|
|
if Result<>mrOk then exit;
|
|
|
|
PackageGraph.BeginUpdate(false);
|
|
IgnoreUnitPaths:=nil;
|
|
try
|
|
while AddParams<>nil do begin
|
|
AddNewComponent(AddParams);
|
|
OldParams:=AddParams;
|
|
AddParams:=AddParams.Next;
|
|
OldParams.Next:=nil;
|
|
OldParams.Free;
|
|
end;
|
|
AddParams.Free;
|
|
Assert(LazPackage.Modified, 'TPackageEditorForm.ShowAddDialog: LazPackage.Modified = False');
|
|
finally
|
|
IgnoreUnitPaths.Free;
|
|
PackageGraph.EndUpdate;
|
|
end;
|
|
end;
|
|
|
|
function TPackageEditorForm.ShowAddDepDialog: TModalResult;
|
|
var
|
|
Deps: TPkgDependencyList;
|
|
i: Integer;
|
|
begin
|
|
if LazPackage.ReadOnly then begin
|
|
UpdateButtons;
|
|
exit(mrCancel);
|
|
end;
|
|
Result:=ShowAddPkgDependencyDlg(LazPackage, Deps);
|
|
try
|
|
if (Result<>mrOk) or (Deps.Count=0) then exit;
|
|
PackageGraph.BeginUpdate(false);
|
|
try
|
|
// add all dependencies
|
|
fForcedFlags := [pefNeedUpdateRequiredPkgs];
|
|
FreeAndNil(FNextSelectedPart);
|
|
for i := 0 to Deps.Count-1 do
|
|
PackageGraph.AddDependencyToPackage(LazPackage, Deps[i]);
|
|
FNextSelectedPart := TPENodeData.Create(penDependency,
|
|
Deps[Deps.Count-1].PackageName, false);
|
|
Assert(LazPackage.Modified, 'TPackageEditorForm.ShowAddDepDialog: LazPackage.Modified = False');
|
|
finally
|
|
PackageGraph.EndUpdate;
|
|
end;
|
|
finally
|
|
Deps.Free;
|
|
end;
|
|
end;
|
|
|
|
function TPackageEditorForm.ShowAddFPMakeDepDialog: TModalResult;
|
|
var
|
|
Deps: TPkgDependencyList;
|
|
i: Integer;
|
|
begin
|
|
if LazPackage.ReadOnly then begin
|
|
UpdateButtons;
|
|
exit(mrCancel);
|
|
end;
|
|
Result:=ShowAddFPMakeDependencyDlg(LazPackage, Deps);
|
|
try
|
|
if (Result<>mrOk) or (Deps.Count=0) then exit;
|
|
PackageGraph.BeginUpdate(false);
|
|
try
|
|
// add all dependencies
|
|
fForcedFlags := [pefNeedUpdateRequiredPkgs];
|
|
FreeAndNil(FNextSelectedPart);
|
|
for i := 0 to Deps.Count-1 do
|
|
PackageGraph.AddDependencyToPackage(LazPackage, Deps[i]);
|
|
FNextSelectedPart := TPENodeData.Create(penDependency,
|
|
Deps[Deps.Count-1].PackageName, false);
|
|
Assert(LazPackage.Modified, 'TPackageEditorForm.ShowAddFPMakeDepDialog: LazPackage.Modified = False');
|
|
finally
|
|
PackageGraph.EndUpdate;
|
|
end;
|
|
finally
|
|
Deps.Free;
|
|
end;
|
|
end;
|
|
|
|
function TPackageEditorForm.PkgNameToFormName(const PkgName: string): string;
|
|
begin
|
|
Result:=PackageEditorWindowPrefix+StringReplace(PkgName,'.','_',[rfReplaceAll]);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.BeginUpdate;
|
|
begin
|
|
inc(fUpdateLock);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.EndUpdate;
|
|
begin
|
|
if fUpdateLock=0 then
|
|
RaiseGDBException('');
|
|
dec(fUpdateLock);
|
|
if fUpdateLock=0 then
|
|
IdleConnected:=true;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.UpdateTitle(Immediately: boolean);
|
|
var
|
|
NewCaption: String;
|
|
s: string;
|
|
begin
|
|
if not CanUpdate(pefNeedUpdateTitle,Immediately) then exit;
|
|
s:=FLazPackage.Name+' V'+FLazPackage.Version.AsString;
|
|
NewCaption:=Format(lisPckEditPackage, [s]);
|
|
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,Immediately) 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);
|
|
end;
|
|
|
|
function TPackageEditorForm.TreeViewGetImageIndex(Str: String; Data: TObject;
|
|
var AIsEnabled: Boolean): Integer;
|
|
var
|
|
PkgFile: TPkgFile;
|
|
Item: TObject;
|
|
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{%H-};
|
|
end;
|
|
end
|
|
else if Item is TPkgDependency then
|
|
Result:=FPropGui.GetDependencyImageIndex(TPkgDependency(Item));
|
|
end;
|
|
|
|
procedure TPackageEditorForm.UpdatePending;
|
|
var
|
|
OldView: TPETVSelectedView;
|
|
begin
|
|
StoreItemsTVSelectedNode(OldView,false);
|
|
try
|
|
if pefNeedUpdateTitle in fFlags then
|
|
UpdateTitle(true);
|
|
if pefNeedUpdateFiles in fFlags then
|
|
UpdateFiles(true);
|
|
if pefNeedUpdateRemovedFiles in fFlags then
|
|
UpdateRemovedFiles(true);
|
|
if pefNeedUpdateRequiredPkgs in fFlags then
|
|
UpdateRequiredPackages(true);
|
|
if pefNeedUpdateProperties in fFlags then
|
|
UpdatePEProperties(true);
|
|
if pefNeedUpdateButtons in fFlags then
|
|
UpdateButtons(true);
|
|
//if pefNeedUpdateApplyDependencyButton in fFlags then
|
|
// FPropGui.UpdateApplyDependencyButton(true);
|
|
if pefNeedUpdateStatusBar in fFlags then
|
|
UpdateStatusBar(true);
|
|
with FPropGui.CallRegisterProcCheckBox do // adjust top of groupbox now.
|
|
FPropGui.RegisteredPluginsGroupBox.Top := ScaleDesignToForm(Height);
|
|
IdleConnected:=false;
|
|
finally
|
|
RestoreItemsTVSelectedNode(OldView);
|
|
fForcedFlags:=[];
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.StoreItemsTVSelectedNode(out
|
|
OldView: TPETVSelectedView; StoreFilter: boolean);
|
|
var
|
|
SelNode: TTreeNode;
|
|
begin
|
|
if ItemsTreeView.Items.IsUpdating then
|
|
begin
|
|
OldView:=Default(TPETVSelectedView);
|
|
end else begin
|
|
ItemsTreeView.BeginUpdate;
|
|
OldView.NeedEndUpdate:=true;
|
|
OldView.OldScrollLeft:=ItemsTreeView.ScrolledLeft;
|
|
OldView.OldScrollTop:=ItemsTreeView.ScrolledTop;
|
|
OldView.OldNodePath:='';
|
|
SelNode:=ItemsTreeView.Selected;
|
|
if SelNode<>nil then
|
|
OldView.OldNodePath:=SelNode.GetTextPath;
|
|
end;
|
|
|
|
if StoreFilter and not OldView.RestoreFilter then
|
|
begin
|
|
OldView.RestoreFilter:=true;
|
|
OldView.OldFilter:=FilterEdit.ForceFilter('');
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.RestoreItemsTVSelectedNode(
|
|
const OldView: TPETVSelectedView);
|
|
var
|
|
SelNode: TTreeNode;
|
|
begin
|
|
if not OldView.NeedEndUpdate then exit;
|
|
|
|
// restore selected node and scroll position
|
|
try
|
|
if OldView.RestoreFilter then
|
|
begin
|
|
FilterEdit.Filter:=OldView.OldFilter;
|
|
FilterEdit.InvalidateFilter; // Needed when OldFilter = ''
|
|
end;
|
|
|
|
SelNode:=ItemsTreeView.Selected;
|
|
if (SelNode=nil) and (OldView.OldNodePath<>'') then
|
|
ItemsTreeView.Selected:=ItemsTreeView.Items.FindNodeWithTextPath(OldView.OldNodePath);
|
|
ItemsTreeView.ScrolledLeft:=OldView.OldScrollLeft;
|
|
ItemsTreeView.ScrolledTop:=OldView.OldScrollTop;
|
|
finally
|
|
ItemsTreeView.EndUpdate;
|
|
end;
|
|
|
|
if OldView.RestoreFilter then
|
|
begin
|
|
UpdatePEProperties;
|
|
UpdateButtons;
|
|
end;
|
|
end;
|
|
|
|
function TPackageEditorForm.CanUpdate(Flag: TPEFlag; Immediately: boolean): boolean;
|
|
begin
|
|
Result:=false;
|
|
if csDestroying in ComponentState then exit;
|
|
if LazPackage=nil then exit;
|
|
if (fUpdateLock>0) and not Immediately then begin
|
|
Include(fFlags,Flag);
|
|
IdleConnected:=true;
|
|
end else begin
|
|
Exclude(fFlags,Flag);
|
|
Result:=true;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.UpdateFiles(Immediately: boolean);
|
|
var
|
|
i: Integer;
|
|
CurFile: TPkgFile;
|
|
FilesBranch: TTreeFilterBranch;
|
|
Filename: String;
|
|
NodeData: TPENodeData;
|
|
OldView: TPETVSelectedView;
|
|
begin
|
|
if not CanUpdate(pefNeedUpdateFiles,Immediately) then exit;
|
|
|
|
StoreItemsTVSelectedNode(OldView,true);
|
|
try
|
|
// files belonging to package
|
|
FilesBranch:=FilterEdit.GetCleanBranch(FFilesNode);
|
|
FPropGui.FreeNodeData(penFile);
|
|
FilesBranch.ClearNodeData;
|
|
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:=FPropGui.CreateNodeData(penFile,CurFile.Filename,false);
|
|
NodeData.FileType:=CurFile.FileType;
|
|
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);
|
|
finally
|
|
RestoreItemsTVSelectedNode(OldView);
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.UpdateRemovedFiles(Immediately: boolean = false);
|
|
var
|
|
i: Integer;
|
|
CurFile: TPkgFile;
|
|
RemovedBranch: TTreeFilterBranch;
|
|
NodeData: TPENodeData;
|
|
OldView: TPETVSelectedView;
|
|
begin
|
|
if not CanUpdate(pefNeedUpdateRemovedFiles,Immediately) then exit;
|
|
|
|
StoreItemsTVSelectedNode(OldView,true);
|
|
try
|
|
if LazPackage.RemovedFilesCount>0 then begin
|
|
// Create root node for removed files 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.GetCleanBranch(FRemovedFilesNode);
|
|
RemovedBranch.ClearNodeData;
|
|
for i:=0 to LazPackage.RemovedFilesCount-1 do begin
|
|
CurFile:=LazPackage.RemovedFiles[i];
|
|
NodeData:=FPropGui.CreateNodeData(penFile,CurFile.Filename,true);
|
|
RemovedBranch.AddNodeData(CurFile.GetShortFilename(true), NodeData);
|
|
end;
|
|
RemovedBranch.InvalidateBranch;
|
|
end
|
|
else begin
|
|
// No more removed files left -> delete the root node
|
|
if FRemovedFilesNode<>nil then begin
|
|
FilterEdit.DeleteBranch(FRemovedFilesNode);
|
|
FilterEdit.InvalidateFilter;
|
|
FreeAndNil(FRemovedFilesNode);
|
|
end;
|
|
end;
|
|
finally
|
|
RestoreItemsTVSelectedNode(OldView);
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.UpdateRequiredPackages(Immediately: boolean);
|
|
var
|
|
Dependency: TPkgDependency;
|
|
RequiredBranch, RemovedBranch: TTreeFilterBranch;
|
|
NodeData: TPENodeData;
|
|
OldView: TPETVSelectedView;
|
|
begin
|
|
if not CanUpdate(pefNeedUpdateRequiredPkgs,Immediately) then exit;
|
|
|
|
StoreItemsTVSelectedNode(OldView,true);
|
|
try
|
|
// required packages
|
|
RequiredBranch:=FilterEdit.GetCleanBranch(FRequiredPackagesNode);
|
|
RequiredBranch.ClearNodeData;
|
|
FPropGui.FreeNodeData(penDependency);
|
|
Dependency:=LazPackage.FirstRequiredDependency;
|
|
FilterEdit.SelectedPart:=nil;
|
|
while Dependency<>nil do begin
|
|
NodeData:=FPropGui.CreateNodeData(penDependency,Dependency.PackageName,false);
|
|
if (FNextSelectedPart<>nil) and (FNextSelectedPart.Typ=penDependency)
|
|
and (FNextSelectedPart.Name=NodeData.Name)
|
|
then
|
|
FilterEdit.SelectedPart:=NodeData;
|
|
RequiredBranch.AddNodeData(Dependency.AsString(False,True)+OPNote(Dependency), NodeData);
|
|
Dependency:=Dependency.NextRequiresDependency;
|
|
end;
|
|
if (FNextSelectedPart<>nil) and (FNextSelectedPart.Typ=penDependency) then
|
|
FreeAndNil(FNextSelectedPart);
|
|
RequiredBranch.InvalidateBranch;
|
|
|
|
// removed required packages
|
|
Dependency:=LazPackage.FirstRemovedDependency;
|
|
if Dependency<>nil then begin
|
|
if FRemovedRequiredNode=nil then begin
|
|
FRemovedRequiredNode:=ItemsTreeView.Items.Add(nil,lisPckEditRemovedRequiredPackages);
|
|
FRemovedRequiredNode.ImageIndex:=FPropGui.ImageIndexRemovedRequired;
|
|
FRemovedRequiredNode.SelectedIndex:=FRemovedRequiredNode.ImageIndex;
|
|
end;
|
|
RemovedBranch:=FilterEdit.GetCleanBranch(FRemovedRequiredNode);
|
|
RemovedBranch.ClearNodeData;
|
|
while Dependency<>nil do begin
|
|
NodeData:=FPropGui.CreateNodeData(penDependency,Dependency.PackageName,true);
|
|
RemovedBranch.AddNodeData(Dependency.AsString(False,True)+OPNote(Dependency), NodeData);
|
|
Dependency:=Dependency.NextRequiresDependency;
|
|
end;
|
|
RemovedBranch.InvalidateBranch;
|
|
end else begin
|
|
if FRemovedRequiredNode<>nil then begin
|
|
FilterEdit.DeleteBranch(FRemovedRequiredNode);
|
|
FreeAndNil(FRemovedRequiredNode);
|
|
end;
|
|
end;
|
|
FNextSelectedPart:=nil;
|
|
|
|
finally
|
|
RestoreItemsTVSelectedNode(OldView);
|
|
end;
|
|
end;
|
|
|
|
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 TPackageEditorForm.UpdatePEProperties(Immediately: boolean);
|
|
var
|
|
CurFile, SingleSelectedFile: TPkgFile;
|
|
CurDependency, SingleSelectedDep: TPkgDependency;
|
|
CurComponent: TPkgComponent;
|
|
CurLine, CurFilename: string;
|
|
TVNode, SingleSelectedDirectory, SingleSelectedNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
i, j: Integer;
|
|
SelFileCount, SelDepCount, SelUnitCount, SelDirCount, SelHasLFMCount: Integer;
|
|
FileCount, HasRegisterProcCount, AddToUsesPkgSectionCount: integer;
|
|
SelHasRegisterProc, SelAddToUsesPkgSection, SelDisableI18NForLFM: TMultiBool;
|
|
aVisible, OnlyFilesWithUnitsSelected, SingleSelectedRemoved: Boolean;
|
|
begin
|
|
if not CanUpdate(pefNeedUpdateProperties,Immediately) then exit;
|
|
GuiToFileOptions(False);
|
|
FPlugins.Clear;
|
|
|
|
// check selection
|
|
SingleSelectedNode:=nil;
|
|
SingleSelectedDep:=nil;
|
|
SingleSelectedFile:=nil;
|
|
SingleSelectedDirectory:=nil;
|
|
SingleSelectedRemoved:=false;
|
|
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);
|
|
SingleSelectedFile:=CurFile;
|
|
SingleSelectedNode:=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);
|
|
SingleSelectedDep:=CurDependency;
|
|
SingleSelectedNode:=TVNode;
|
|
SingleSelectedRemoved:=NodeData.Removed;
|
|
end;
|
|
end else if IsDirectoryNode(TVNode) or (TVNode=FFilesNode) then begin
|
|
inc(SelDirCount);
|
|
SingleSelectedDirectory:=TVNode;
|
|
SingleSelectedNode:=TVNode;
|
|
end //else if TVNode=FRequiredPackagesNode then
|
|
// DebugLn('UpdatePEProperties: Required packages selected');
|
|
end;
|
|
|
|
if (SelFileCount+SelDepCount+SelDirCount>1) then begin
|
|
// it is a multi selection
|
|
SingleSelectedFile:=nil;
|
|
SingleSelectedDep:=nil;
|
|
SingleSelectedDirectory:=nil;
|
|
SingleSelectedNode:=nil;
|
|
end;
|
|
|
|
//debugln(['TPackageEditorForm.UpdatePEProperties SelFileCount=',SelFileCount,' SelDepCount=',SelDepCount,' SelDirCount=',SelDirCount,' SelUnitCount=',SelUnitCount]);
|
|
//debugln(['TPackageEditorForm.UpdatePEProperties FSingleSelectedFile=',SingleSelectedFile<>nil,' FSingleSelectedDependency=',SingleSelectedDep<>nil,' SingleSelectedDirectory=',SingleSelectedDirectory<>nil]);
|
|
|
|
OnlyFilesWithUnitsSelected:=
|
|
(SelFileCount>0) and (SelDepCount=0) and (SelDirCount=0) and (SelUnitCount>0);
|
|
FPropGui.ControlVisible := OnlyFilesWithUnitsSelected;
|
|
FPropGui.ControlEnabled := not LazPackage.ReadOnly;
|
|
DisableAlign;
|
|
try
|
|
FPropGui.SetAddToUsesCB(SelAddToUsesPkgSection); // 'Add to uses' of files
|
|
FPropGui.SetCallRegisterProcCB(SelHasRegisterProc); // 'RegisterProc' of files
|
|
FPropGui.SetRegisteredPluginsGB(FPlugins); // registered plugins
|
|
|
|
// Min/Max version of dependency (only single selection)
|
|
FPropGui.ControlVisible := SingleSelectedDep<>nil;
|
|
FPropGui.SetMinMaxVisibility;
|
|
|
|
// disable i18n for lfm
|
|
FPropGui.ControlVisible := OnlyFilesWithUnitsSelected and (SelHasLFMCount>0)
|
|
and LazPackage.EnableI18N and LazPackage.EnableI18NForLFM;
|
|
FPropGui.SetDisableI18NCB(SelDisableI18NForLFM);
|
|
|
|
// move up/down (only single selection)
|
|
aVisible := (FilterEdit.Filter='')
|
|
and (not (SortAlphabetically or ShowDirectoryHierarchy or SingleSelectedRemoved))
|
|
and ((SingleSelectedFile<>nil) or (SingleSelectedDep<>nil));
|
|
MoveUpBtn.Enabled :=aVisible and Assigned(SingleSelectedNode.GetPrevVisibleSibling);
|
|
MoveDownBtn.Enabled:=aVisible and Assigned(SingleSelectedNode.GetNextVisibleSibling);
|
|
|
|
// 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 SingleSelectedDep<>nil then begin
|
|
PropsGroupBox.Enabled:=not SingleSelectedRemoved;
|
|
PropsGroupBox.Caption:=lisPckEditDependencyProperties;
|
|
FPropGui.SetMinMaxValues(SingleSelectedDep);
|
|
FPropGui.UpdateApplyDependencyButton;
|
|
end
|
|
else if SingleSelectedDirectory<>nil then begin
|
|
PropsGroupBox.Enabled:=true;
|
|
PropsGroupBox.Caption:=lisPckEditFileProperties;
|
|
GetDirectorySummary(SingleSelectedDirectory,
|
|
FileCount,HasRegisterProcCount,AddToUsesPkgSectionCount);
|
|
FDirSummaryLabel.Caption:=Format(
|
|
lisFilesHasRegisterProcedureInPackageUsesSection, [IntToStr(FileCount),
|
|
IntToStr(HasRegisterProcCount), IntToStr(AddToUsesPkgSectionCount)]);
|
|
end
|
|
else begin
|
|
PropsGroupBox.Enabled:=false;
|
|
PropsGroupBox.Caption:=lisPckEditDependencyProperties;
|
|
end;
|
|
|
|
if SingleSelectedFile<>nil then begin
|
|
for i := 2 to PropsPageControl.PageCount -1 do
|
|
PropsPageControl.pages[i].Visible := True;
|
|
FileOptionsToGui;
|
|
PropsPageControl.ShowTabs := PropsPageControl.PageCount > 1;
|
|
end else begin
|
|
for i := 2 to PropsPageControl.PageCount -1 do
|
|
PropsPageControl.pages[i].Visible := False;
|
|
PropsPageControl.ShowTabs := False;
|
|
end;
|
|
finally
|
|
EnableAlign;
|
|
end;
|
|
end;
|
|
|
|
function TPackageEditorForm.GetSingleSelectedDependency: TPkgDependency;
|
|
var
|
|
i: Integer;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
begin
|
|
Result:=nil;
|
|
for i:=0 to ItemsTreeView.SelectionCount-1 do
|
|
begin
|
|
if not GetNodeDataItem(ItemsTreeView.Selections[i],NodeData,Item) then continue;
|
|
if Item is TPkgDependency then
|
|
begin
|
|
if Result<>nil then
|
|
Exit(nil); // not single selected
|
|
Result:=TPkgDependency(Item);
|
|
end
|
|
else
|
|
Exit(nil);
|
|
end;
|
|
end;
|
|
|
|
function TPackageEditorForm.GetSingleSelectedFile: TPkgFile;
|
|
var
|
|
i: Integer;
|
|
TVNode: TTreeNode;
|
|
NodeData: TPENodeData;
|
|
Item: TObject;
|
|
begin
|
|
Result:=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
|
|
if Result<>nil then begin
|
|
// not single selected
|
|
Result:=nil;
|
|
break;
|
|
end;
|
|
Result:=TPkgFile(Item);
|
|
break;
|
|
end else if Item is TPkgDependency then begin
|
|
Result:=nil;
|
|
break;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TPackageEditorForm.GetDependencyToUpdate(Immediately: boolean): TPkgDependencyID;
|
|
begin
|
|
if CanUpdate(pefNeedUpdateApplyDependencyButton,Immediately) then
|
|
Result:=GetSingleSelectedDependency
|
|
else
|
|
Result:=nil;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.UpdateStatusBar(Immediately: boolean);
|
|
var
|
|
StatusText: String;
|
|
begin
|
|
if not CanUpdate(pefNeedUpdateStatusBar,Immediately) 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.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(FilesBaseDirectory);
|
|
Item:=TFileNameItem(Node.Data);
|
|
if (Item is TFileNameItem) then begin
|
|
Result:=Item.Filename;
|
|
end else if Node.HasAsParent(FFilesNode) then begin
|
|
// directory node
|
|
Result:=Node.Text;
|
|
end else
|
|
exit;
|
|
if not FilenameIsAbsolute(Result) then
|
|
Result:=AppendPathDelim(FilesBaseDirectory)+Result;
|
|
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;
|
|
ShortIncDirectory:='';
|
|
LazPackage.LongenFilename(NewDirectory);
|
|
NewDirectory:=ChompPathDelim(NewDirectory);
|
|
|
|
UnitPath:=LazPackage.GetUnitPath(false);
|
|
UnitPathPos:=SearchDirectoryInMaskedSearchPath(UnitPath,NewDirectory);
|
|
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:=SearchDirectoryInMaskedSearchPath(IncPath,NewIncDirectory);
|
|
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
|
|
LazPackage.CompilerOptions.MergeToUnitPaths(ShortDirectory);
|
|
end;
|
|
if IncPathPos<1 then
|
|
// the unit is in unitpath, but the include file not in the incpath
|
|
// -> auto extend the include path
|
|
LazPackage.CompilerOptions.MergeToIncludePaths(ShortIncDirectory);
|
|
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:=SearchDirectoryInMaskedSearchPath(IncPath,NewDirectory);
|
|
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
|
|
LazPackage.CompilerOptions.MergeToIncludePaths(ShortDirectory);
|
|
end;
|
|
|
|
function TPackageEditorForm.ExtendUnitSearchPath(NewUnitPaths: string): boolean;
|
|
begin
|
|
Result:=LazPackage.ExtendUnitSearchPath(NewUnitPaths);
|
|
end;
|
|
|
|
function TPackageEditorForm.ExtendIncSearchPath(NewIncPaths: string): boolean;
|
|
begin
|
|
Result:=LazPackage.ExtendIncSearchPath(NewIncPaths);
|
|
end;
|
|
|
|
function TPackageEditorForm.FilesEditTreeView: TTreeView;
|
|
begin
|
|
Result:=ItemsTreeView;
|
|
end;
|
|
|
|
function TPackageEditorForm.FilesEditForm: TCustomForm;
|
|
begin
|
|
Result:=Self;
|
|
end;
|
|
|
|
function TPackageEditorForm.FilesOwner: TObject;
|
|
begin
|
|
Result:=LazPackage;
|
|
end;
|
|
|
|
function TPackageEditorForm.FilesOwnerName: string;
|
|
begin
|
|
Result:=Format(lisPackage2, [LazPackage.Name]);
|
|
end;
|
|
|
|
function TPackageEditorForm.TVNodeFiles: TTreeNode;
|
|
begin
|
|
Result:=FFilesNode;
|
|
end;
|
|
|
|
function TPackageEditorForm.TVNodeRequiredPackages: TTreeNode;
|
|
begin
|
|
Result:=FRequiredPackagesNode;
|
|
end;
|
|
|
|
function TPackageEditorForm.FilesBaseDirectory: string;
|
|
begin
|
|
Result:=LazPackage.DirectoryExpanded;
|
|
end;
|
|
|
|
function TPackageEditorForm.FilesOwnerReadOnly: boolean;
|
|
begin
|
|
Result:=LazPackage.ReadOnly;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.FilterEditAfterFilter(Sender: TObject);
|
|
var
|
|
LPackage: TIDEPackage;
|
|
begin
|
|
if Assigned(SourceEditorManagerIntf) and Assigned(PackageEditingInterface) and Assigned(SourceEditorManagerIntf.ActiveEditor) then
|
|
begin
|
|
PackageEditingInterface.GetPackageOfSourceEditor(LPackage, SourceEditorManagerIntf.ActiveEditor);
|
|
if (LPackage is TLazPackage) and (TLazPackage(LPackage).Editor = Self) then
|
|
SelectFileNode(SourceEditorManagerIntf.ActiveEditor.FileName);
|
|
end;
|
|
end;
|
|
|
|
function TPackageEditorForm.FirstRequiredDependency: TPkgDependency;
|
|
begin
|
|
Result:=LazPackage.FirstRequiredDependency;
|
|
end;
|
|
|
|
function TPackageEditorForm.CanBeAddedToProject: boolean;
|
|
begin
|
|
if LazPackage=nil then exit(false);
|
|
Result:=PackageEditors.AddToProject(LazPackage,true)=mrOk;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.PackageListAvailable(Sender: TObject);
|
|
begin
|
|
//DebugLn(['TPackageEditorForm.PackageListAvailable: ', LazPackage.Name]);
|
|
UpdateRequiredPackages;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoSave(SaveAs: boolean);
|
|
begin
|
|
GuiToFileOptions(False);
|
|
PackageEditors.SavePackage(LazPackage,SaveAs);
|
|
UpdateTitle;
|
|
UpdateButtons;
|
|
UpdateStatusBar;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoCompile(CompileClean, CompileRequired,
|
|
WarnIDEPkg: boolean);
|
|
var
|
|
MsgResult: Integer;
|
|
begin
|
|
if WarnIDEPkg and not FCompileDesignTimePkg
|
|
and (LazPackage.PackageType=lptDesignTime) then
|
|
begin
|
|
MsgResult:=IDEQuestionDialog(dlgMsgWinColorUrgentWarning,
|
|
Format(lisPackageIsDesigntimeOnlySoItShouldOnlyBeCompiledInt, [
|
|
LazPackage.Name, #13]),
|
|
mtWarning, [mrYes, lisCompileWithProjectSettings,
|
|
mrYesToAll, lisCompileAndDoNotAskAgain, mrCancel]);
|
|
case MsgResult of
|
|
mrYes: ;
|
|
mrYesToAll:
|
|
FCompileDesignTimePkg:=true; // store setting only while running the IDE
|
|
// when IDE restarts, ask again
|
|
else exit;
|
|
end;
|
|
end;
|
|
CompileBitBtn.Enabled:=False;
|
|
FCompiling:=True;
|
|
PackageEditors.CompilePackage(LazPackage,CompileClean,CompileRequired);
|
|
FCompiling:=False;
|
|
UpdateTitle;
|
|
UpdateButtons;
|
|
UpdateStatusBar;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoFindInFiles;
|
|
begin
|
|
PackageEditors.FindInFiles(LazPackage);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoRevert;
|
|
begin
|
|
if MessageDlg(lisPkgEditRevertPackage,
|
|
Format(lisPkgEditDoYouReallyWantToForgetAllChangesToPackageAnd, [LazPackage.IDAsString]),
|
|
mtConfirmation,[mbYes,mbNo],0)<>mrYes
|
|
then exit;
|
|
PackageEditors.RevertPackage(LazPackage);
|
|
UpdateAll(false);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoPublishPackage;
|
|
begin
|
|
PackageEditors.PublishPackage(LazPackage);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoEditVirtualUnit;
|
|
var
|
|
PkgFile: TPkgFile;
|
|
begin
|
|
if LazPackage=nil then exit;
|
|
PkgFile:=GetSingleSelectedFile;
|
|
if (PkgFile=nil)
|
|
or (PkgFile.FileType<>pftVirtualUnit)
|
|
or (LazPackage.IndexOfPkgFile(PkgFile)<0)
|
|
then exit;
|
|
if ShowEditVirtualPackageDialog(PkgFile)=mrOk then
|
|
UpdateFiles;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoExpandCollapseDirectory(ExpandIt: Boolean);
|
|
var
|
|
CurNode: TTreeNode;
|
|
begin
|
|
CurNode:=ItemsTreeView.Selected;
|
|
if not (IsDirectoryNode(CurNode) or (CurNode=FFilesNode)) then exit;
|
|
ItemsTreeView.BeginUpdate;
|
|
if ExpandIt then
|
|
CurNode.Expand(true)
|
|
else
|
|
CurNode.Collapse(true);
|
|
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;
|
|
PkgFile: TPkgFile;
|
|
begin
|
|
PkgFile:=GetSingleSelectedFile;
|
|
if (LazPackage=nil) or (PkgFile=nil) then exit;
|
|
OldIndex:=LazPackage.IndexOfPkgFile(PkgFile);
|
|
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.Move(OldIndex,NewIndex);
|
|
UpdatePEProperties;
|
|
UpdateStatusBar;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoMoveDependency(Offset: integer);
|
|
var
|
|
OldIndex, NewIndex: Integer;
|
|
RequiredBranch: TTreeFilterBranch;
|
|
Moved: Boolean;
|
|
Dependency: TPkgDependency;
|
|
begin
|
|
Dependency:=GetSingleSelectedDependency;
|
|
if (LazPackage=nil) or (Dependency=nil) then exit;
|
|
if Offset<0 then
|
|
Moved := LazPackage.MoveRequiredDependencyUp(Dependency)
|
|
else
|
|
Moved := LazPackage.MoveRequiredDependencyDown(Dependency);
|
|
if not Moved then exit;
|
|
RequiredBranch:=FilterEdit.GetExistingBranch(FRequiredPackagesNode);
|
|
OldIndex:=RequiredBranch.Items.IndexOf(Dependency.AsString(False,True)+OPNote(Dependency));
|
|
NewIndex:=OldIndex+Offset;
|
|
RequiredBranch.Move(OldIndex,NewIndex);
|
|
LazPackage.Modified:=true;
|
|
UpdatePEProperties;
|
|
UpdateStatusBar;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoSortFiles;
|
|
var
|
|
TreeSelection: TStringList;
|
|
begin
|
|
TreeSelection:=ItemsTreeView.StoreCurrentSelection;
|
|
LazPackage.SortFiles;
|
|
ItemsTreeView.ApplyStoredSelection(TreeSelection);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoFixFilesCase;
|
|
begin
|
|
LazPackage.FixFilesCaseSensitivity;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.DoShowMissingFiles;
|
|
begin
|
|
ShowMissingPkgFilesDialog(LazPackage);
|
|
end;
|
|
|
|
constructor TPackageEditorForm.Create(TheOwner: TComponent);
|
|
begin
|
|
inherited Create(TheOwner);
|
|
end;
|
|
|
|
destructor TPackageEditorForm.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TPackageEditorForm.CanCloseEditor: TModalResult;
|
|
var
|
|
MsgResult: Integer;
|
|
begin
|
|
Result:=mrOK;
|
|
//debugln(['TPackageEditorForm.CanCloseEditor ',Caption]);
|
|
if (LazPackage<>nil) and (not (lpfDestroying in LazPackage.Flags)) then
|
|
begin
|
|
if LazPackage.ReadOnly then
|
|
LazPackage.Modified:=false // clear modified flag, so that it will be closed
|
|
else if 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
|
|
Result:=mrAbort
|
|
else
|
|
LazPackage.Modified:=false; // clear modified flag, so that it will be closed
|
|
end;
|
|
if not MainIDE.IDEIsClosing then
|
|
begin
|
|
if FCompiling then begin
|
|
DebugLn(['TPackageEditorForm.CanCloseEditor: ', Caption, ' compiling, do not close.']);
|
|
Result:=mrCancel;
|
|
end;
|
|
if Result=mrOK then
|
|
begin
|
|
EnvironmentOptions.LastOpenPackages.Remove(LazPackage.Filename);
|
|
MainIDE.SaveEnvironment;
|
|
end;
|
|
end;
|
|
end;
|
|
//debugln(['TPackageEditorForm.CanCloseEditor Result=',dbgs(Result),' ',Caption]);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.TraverseSettings(AOptions: TAbstractPackageFileIDEOptions;
|
|
anAction: TIDEPackageOptsDlgAction);
|
|
|
|
procedure Traverse(Control: TWinControl);
|
|
var
|
|
i: Integer;
|
|
begin
|
|
if Control <> nil then
|
|
begin
|
|
if Control is TAbstractIDEOptionsEditor then
|
|
with TAbstractIDEOptionsEditor(Control) do
|
|
case anAction of
|
|
iodaRead: ReadSettings(AOptions);
|
|
iodaWrite: WriteSettings(AOptions);
|
|
iodaRestore: RestoreSettings(AOptions);
|
|
end;
|
|
for i := 0 to Control.ControlCount -1 do
|
|
if Control.Controls[i] is TWinControl then
|
|
Traverse(TWinControl(Control.Controls[i]));
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
Traverse(PropsPageControl);
|
|
end;
|
|
|
|
procedure TPackageEditorForm.CreatePackageFileEditors;
|
|
var
|
|
Instance: TAbstractIDEOptionsEditor;
|
|
i, j: integer;
|
|
Rec: PIDEOptionsGroupRec;
|
|
AGroupCaption: string;
|
|
ACaption: string;
|
|
ItemTabSheet: TTabSheet;
|
|
begin
|
|
IDEEditorGroups.Resort;
|
|
for i := 0 to IDEEditorGroups.Count - 1 do
|
|
begin
|
|
Rec := IDEEditorGroups[i];
|
|
//DebugLn(['TPackageEditorForm.CreatePackageFileEditors ',Rec^.GroupClass.ClassName]);
|
|
if PassesFilter(Rec) then
|
|
begin
|
|
if Rec^.GroupClass<>nil then
|
|
AGroupCaption := Rec^.GroupClass.GetGroupCaption
|
|
else
|
|
AGroupCaption := '';
|
|
for j := 0 to Rec^.Items.Count - 1 do
|
|
begin
|
|
ItemTabSheet := PropsPageControl.AddTabSheet;
|
|
ItemTabSheet.Align := alClient;
|
|
Instance := Rec^.Items[j]^.EditorClass.Create(Self);
|
|
// Instance.OnLoadIDEOptions := @LoadIDEOptions;
|
|
// Instance.OnSaveIDEOptions := @SaveIDEOptions;
|
|
// In principle the parameter should be a TAbstractOptionsEditorDialog,
|
|
// but in this case this is not available, so pass nil.
|
|
// Better would be to change the structure of the classes to avoid this
|
|
// problem.
|
|
Instance.Setup(Nil);
|
|
Instance.OnChange := @FileOptionsChange;
|
|
Instance.Tag := Rec^.Items[j]^.Index;
|
|
Instance.Parent := ItemTabSheet;
|
|
Instance.Rec := Rec^.Items[j];
|
|
ACaption := Instance.GetTitle;
|
|
if AGroupCaption <> ACaption then
|
|
ACaption := AGroupCaption + ' - ' + ACaption;
|
|
ItemTabSheet.Caption := ACaption;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.FileOptionsToGui;
|
|
type
|
|
TStage = (sBefore, sRead, sAfter);
|
|
var
|
|
i: integer;
|
|
Rec: PIDEOptionsGroupRec;
|
|
InstCls: TAbstractPackageFileIDEOptionsClass;
|
|
Instance: TAbstractPackageFileIDEOptions;
|
|
InstanceList: TFPList;
|
|
stag: TStage;
|
|
PkgFile: TPkgFile;
|
|
begin
|
|
PkgFile:=GetSingleSelectedFile;
|
|
if not Assigned(PkgFile) then exit;
|
|
FOptionsShownOfFile := PkgFile;
|
|
for stag:=low(TStage) to High(TStage) do
|
|
begin
|
|
InstanceList:=TFPList.Create;
|
|
for i := 0 to IDEEditorGroups.Count - 1 do
|
|
begin
|
|
Rec := IDEEditorGroups[i];
|
|
if not PassesFilter(Rec) then
|
|
Continue;
|
|
InstCls := TAbstractPackageFileIDEOptionsClass(Rec^.GroupClass);
|
|
Instance := TAbstractPackageFileIDEOptions(InstCls.GetInstance(LazPackage, FOptionsShownOfFile));
|
|
if (InstanceList.IndexOf(Instance)<0) and Assigned(Instance) then
|
|
begin
|
|
InstanceList.Add(Instance);
|
|
case stag of
|
|
sBefore:
|
|
Instance.DoBeforeRead;
|
|
sRead:
|
|
TraverseSettings(Instance,iodaRead);
|
|
sAfter:
|
|
Instance.DoAfterRead;
|
|
end;
|
|
end;
|
|
end;
|
|
if stag=sRead then
|
|
TraverseSettings(nil,iodaRead); // load settings that does not belong to any group
|
|
InstanceList.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.GuiToFileOptions(Restore: boolean);
|
|
type
|
|
TStage = (sBefore, sWrite, sAfter);
|
|
var
|
|
i: integer;
|
|
Rec: PIDEOptionsGroupRec;
|
|
InstCls: TAbstractPackageFileIDEOptionsClass;
|
|
Instance: TAbstractPackageFileIDEOptions;
|
|
stag: TStage;
|
|
begin
|
|
if Assigned(FOptionsShownOfFile) then
|
|
begin
|
|
for stag:=low(TStage) to High(TStage) do
|
|
begin
|
|
for i := 0 to IDEEditorGroups.Count - 1 do
|
|
begin
|
|
Rec := IDEEditorGroups[i];
|
|
if not PassesFilter(Rec) then
|
|
Continue;
|
|
InstCls := TAbstractPackageFileIDEOptionsClass(Rec^.GroupClass);
|
|
Instance := TAbstractPackageFileIDEOptions(InstCls.GetInstance(LazPackage, FOptionsShownOfFile));
|
|
if Assigned(Instance) then
|
|
begin
|
|
case stag of
|
|
sBefore:
|
|
Instance.DoBeforeWrite(Restore);
|
|
sWrite:
|
|
if Restore then
|
|
TraverseSettings(Instance,iodaRestore)
|
|
else
|
|
TraverseSettings(Instance,iodaWrite);
|
|
sAfter:
|
|
Instance.DoAfterWrite(Restore);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
// save settings that do not belong to any group
|
|
if stag=sWrite then
|
|
if Restore then
|
|
TraverseSettings(nil,iodaRestore)
|
|
else
|
|
TraverseSettings(nil,iodaWrite);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TPackageEditorForm.FileOptionsChange(Sender: TObject);
|
|
begin
|
|
LazPackage.Modified := True;
|
|
end;
|
|
|
|
function TPackageEditorForm.PassesFilter(rec: PIDEOptionsGroupRec): Boolean;
|
|
begin
|
|
Result := (Rec^.GroupClass.InheritsFrom(TAbstractPackageFileIDEOptions)) and (Rec^.Items <> nil);
|
|
end;
|
|
|
|
{ TPackageEditors }
|
|
|
|
function TPackageEditors.GetEditors(Index: integer): TPackageEditorForm;
|
|
begin
|
|
Result:=TPackageEditorForm(FItems[Index]);
|
|
end;
|
|
|
|
function TPackageEditors.IndexOfPackage(const PkgName: string): integer;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 0 to Count-1 do
|
|
if Assigned(Editors[I].LazPackage) and
|
|
SameText(ExtractFileNameOnly(Editors[I].LazPackage.Filename), PkgName)
|
|
then
|
|
Exit(I);
|
|
|
|
Result := -1;
|
|
end;
|
|
|
|
constructor TPackageEditors.Create;
|
|
begin
|
|
FItems:=TFPList.Create;
|
|
end;
|
|
|
|
procedure TPackageEditors.ActiveEditorChanged(Sender: TObject);
|
|
var
|
|
LPackage: TIDEPackage;
|
|
LForm: TPackageEditorForm;
|
|
begin
|
|
if Assigned(SourceEditorManagerIntf.ActiveEditor) then
|
|
begin
|
|
PackageEditingInterface.GetPackageOfSourceEditor(LPackage, SourceEditorManagerIntf.ActiveEditor);
|
|
if (LPackage is TLazPackage) and (TLazPackage(LPackage).Editor is TPackageEditorForm) then
|
|
begin
|
|
LForm := TPackageEditorForm(TLazPackage(LPackage).Editor);
|
|
LForm.SelectFileNode(SourceEditorManagerIntf.ActiveEditor.FileName);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
destructor TPackageEditors.Destroy;
|
|
begin
|
|
if SourceEditorManagerIntf <> nil then
|
|
SourceEditorManagerIntf.UnRegisterChangeEvent(semEditorActivate,@ActiveEditorChanged);
|
|
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.CreateEditor(Pkg: TLazPackage;
|
|
DoDisableAutoSizing: boolean): TPackageEditorForm;
|
|
begin
|
|
Result:=FindEditor(Pkg);
|
|
if Result<>nil then begin
|
|
if DoDisableAutoSizing then
|
|
Result.DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster Delayed'){$ENDIF};
|
|
end else begin
|
|
Result:=TPackageEditorForm(TPackageEditorForm.NewInstance);
|
|
{$IFDEF DebugDisableAutoSizing}
|
|
if DoDisableAutoSizing then
|
|
Result.DisableAutoSizing('TAnchorDockMaster Delayed')
|
|
else
|
|
Result.DisableAutoSizing('TPackageEditors.OpenEditor');
|
|
{$ELSE}
|
|
Result.DisableAutoSizing;
|
|
{$ENDIF}
|
|
Result.Create(LazarusIDE.OwningComponent);
|
|
Result.LazPackage:=Pkg;
|
|
FItems.Add(Result);
|
|
if not DoDisableAutoSizing then
|
|
Result.EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TPackageEditors.OpenEditor'){$ENDIF};
|
|
end;
|
|
end;
|
|
|
|
function TPackageEditors.OpenEditor(Pkg: TLazPackage; BringToFront: boolean
|
|
): TPackageEditorForm;
|
|
begin
|
|
Result:=CreateEditor(Pkg,true);
|
|
try
|
|
IDEWindowCreators.ShowForm(Result, BringToFront);
|
|
finally
|
|
Result.EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TAnchorDockMaster Delayed'){$ENDIF};
|
|
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
|
|
if Dependency.DependencyType=pdtLazarus then
|
|
begin
|
|
APackage:=Dependency.RequiredPackage;
|
|
if Assigned(OnOpenPackage) then
|
|
Result:=OnOpenPackage(Sender,APackage);
|
|
end
|
|
else
|
|
ShowMessage('It is not possible to open FPMake packages.');
|
|
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.FindEditor(const PkgName: string): TPackageEditorForm;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
i:=IndexOfPackage(PkgName);
|
|
if i>=0 then
|
|
Result:=Editors[i]
|
|
else
|
|
Result:=nil;
|
|
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;
|
|
var
|
|
Dep: TPkgDependency;
|
|
CurPkg: TLazPackage;
|
|
begin
|
|
if APackage.Missing then
|
|
exit(true)
|
|
else if (APackage.FindUnitWithRegister<>nil) or (APackage.Provides.Count>0) then
|
|
exit(false);
|
|
Dep:=APackage.FirstRequiredDependency;
|
|
while Dep<>nil do begin
|
|
CurPkg:=Dep.RequiredPackage;
|
|
if (CurPkg<>nil) then begin
|
|
if (CurPkg.FindUnitWithRegister<>nil) or (CurPkg.Provides.Count>0) then
|
|
exit(false);
|
|
end;
|
|
Dep:=Dep.NextRequiresDependency;
|
|
end;
|
|
Result:=true;
|
|
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.FindInFiles(APackage: TLazPackage): TModalResult;
|
|
begin
|
|
if Assigned(OnShowFindInFiles) then
|
|
Result:=OnShowFindInFiles(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.TreeViewToPkgEditor(TV: TTreeView): TPackageEditorForm;
|
|
var
|
|
aParent: TWinControl;
|
|
begin
|
|
Result:=nil;
|
|
if TV.Name<>'ItemsTreeView' then exit;
|
|
aParent:=TV;
|
|
repeat
|
|
if aParent=nil then exit;
|
|
aParent:=aParent.Parent;
|
|
until aParent is TPackageEditorForm;
|
|
Result:=TPackageEditorForm(aParent);
|
|
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;
|
|
IDEWindowsGlobalOptions.Add(PackageEditorWindowPrefix, False);
|
|
|
|
end.
|
|
|