IDE, IDEIntf: Ability to register custom option editors for files in packages

git-svn-id: trunk@59911 -
This commit is contained in:
joost 2018-12-26 22:46:24 +00:00
parent 9d545d09b1
commit 344263decc
6 changed files with 259 additions and 40 deletions

View File

@ -238,6 +238,8 @@ const
GroupPkgCompiler = 200200;
GroupPackageFile = 200300;
var
HasGUI: boolean = true; // lazbuild sets this to false

View File

@ -412,6 +412,17 @@ type
property Package: TIDEPackage read GetPackage;
end;
{ TAbstractPackageFileIDEOptions }
TAbstractPackageFileIDEOptions = class(TAbstractIDEOptions)
protected
function GetPackageFile: TLazPackageFile; virtual; abstract;
function GetPackage: TIDEPackage; virtual; abstract;
public
property PackageFile: TLazPackageFile read GetPackageFile;
property Package: TIDEPackage read GetPackage;
end;
var
PackageDescriptors: TPackageDescriptors; // will be set by the IDE

View File

@ -4773,6 +4773,7 @@ resourcestring
+'%sThis means it will be installed in the IDE.'
+'%sInstallation packages must be designtime Packages.';
lisPckOptsPackageOptions = 'Package Options';
lisPckOptsPackageFileOptions = 'Additional Package File Options';
// package explorer (package graph)
lisMenuPackageGraph = 'Package Graph';

View File

@ -788,7 +788,23 @@ type
procedure UpdateAll(Immediately: boolean = false); virtual; abstract;
property LazPackage: TLazPackage read GetLazPackage write SetLazPackage;
end;
{ TPackageFileIDEOptions }
TPackageFileIDEOptions = class(TAbstractPackageFileIDEOptions)
private
FPackageFile: TLazPackageFile;
FLazPackage: TLazPackage;
protected
function GetPackageFile: TLazPackageFile; override;
function GetPackage: TLazPackage; override;
public
constructor Create(APackage: TLazPackage; APackageFile: TLazPackageFile);
class function GetInstance: TAbstractIDEOptions; override;
class function GetGroupCaption: string; override;
end;
const
LazPkgXMLFileVersion = 4;
@ -1401,6 +1417,35 @@ begin
Result:=nil;
end;
{ TPackageFileIDEOptions }
function TPackageFileIDEOptions.GetPackageFile: TLazPackageFile;
begin
Result := FPackageFile;
end;
constructor TPackageFileIDEOptions.Create(APackage: TLazPackage; APackageFile: TLazPackageFile);
begin
inherited Create;
FLazPackage := APackage;
FPackageFile := APackageFile;
end;
class function TPackageFileIDEOptions.GetGroupCaption: string;
begin
Result := lisPckOptsPackageFileOptions;
end;
class function TPackageFileIDEOptions.GetInstance: TAbstractIDEOptions;
begin
Result := Nil;
end;
function TPackageFileIDEOptions.GetPackage: TLazPackage;
begin
Result := FLazPackage;
end;
{ TPkgFile }
procedure TPkgFile.SetFilename(const AValue: string);
@ -4679,6 +4724,7 @@ end;
initialization
RegisterIDEOptionsGroup(GroupPackage, TPackageIDEOptions);
RegisterIDEOptionsGroup(GroupPkgCompiler, TPkgCompilerOptions);
RegisterIDEOptionsGroup(GroupPackageFile, TPackageFileIDEOptions);
PackageDependencies:=TAVLTree.Create(@ComparePkgDependencyNames);
finalization

View File

@ -15,7 +15,7 @@ object PackageEditorForm: TPackageEditorForm
OnCreate = FormCreate
OnDestroy = FormDestroy
OnDropFiles = FormDropFiles
LCLVersion = '1.9.0.0'
LCLVersion = '2.1.0.0'
object ToolBar: TToolBar
Left = 0
Height = 48
@ -30,7 +30,7 @@ object PackageEditorForm: TPackageEditorForm
object PropsGroupBox: TGroupBox
Left = 0
Height = 118
Top = 316
Top = 218
Width = 464
Align = alBottom
Caption = 'PropsGroupBox'
@ -39,9 +39,9 @@ object PackageEditorForm: TPackageEditorForm
TabOrder = 3
object CallRegisterProcCheckBox: TCheckBox
Left = 0
Height = 21
Height = 23
Top = 0
Width = 187
Width = 202
Caption = 'CallRegisterProcCheckBox'
OnChange = CallRegisterProcCheckBoxChange
ParentShowHint = False
@ -51,10 +51,10 @@ object PackageEditorForm: TPackageEditorForm
object AddToUsesPkgSectionCheckBox: TCheckBox
AnchorSideLeft.Control = CallRegisterProcCheckBox
AnchorSideLeft.Side = asrBottom
Left = 197
Height = 21
Left = 212
Height = 23
Top = 0
Width = 222
Width = 239
BorderSpacing.Left = 10
Caption = 'AddToUsesPkgSectionCheckBox'
OnChange = AddToUsesPkgSectionCheckBoxChange
@ -67,9 +67,9 @@ object PackageEditorForm: TPackageEditorForm
AnchorSideTop.Control = MinVersionEdit
AnchorSideTop.Side = asrCenter
Left = 0
Height = 21
Top = 2
Width = 179
Height = 23
Top = 7
Width = 191
Caption = 'UseMinVersionCheckBox'
OnChange = UseMinVersionCheckBoxChange
TabOrder = 2
@ -78,8 +78,8 @@ object PackageEditorForm: TPackageEditorForm
AnchorSideLeft.Control = UseMinVersionCheckBox
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = PropsGroupBox
Left = 189
Height = 25
Left = 201
Height = 36
Top = 0
Width = 100
BorderSpacing.Left = 10
@ -92,9 +92,9 @@ object PackageEditorForm: TPackageEditorForm
AnchorSideTop.Control = MaxVersionEdit
AnchorSideTop.Side = asrCenter
Left = 0
Height = 21
Top = 29
Width = 183
Height = 23
Top = 45
Width = 194
Caption = 'UseMaxVersionCheckBox'
OnChange = UseMaxVersionCheckBoxChange
TabOrder = 4
@ -104,9 +104,9 @@ object PackageEditorForm: TPackageEditorForm
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = MinVersionEdit
AnchorSideTop.Side = asrBottom
Left = 193
Height = 25
Top = 27
Left = 204
Height = 36
Top = 38
Width = 100
BorderSpacing.Left = 10
BorderSpacing.Top = 2
@ -119,9 +119,9 @@ object PackageEditorForm: TPackageEditorForm
AnchorSideTop.Control = MaxVersionEdit
AnchorSideTop.Side = asrBottom
Left = 0
Height = 25
Top = 58
Width = 163
Height = 35
Top = 80
Width = 178
AutoSize = True
BorderSpacing.Top = 6
Caption = 'ApplyDependencyButton'
@ -129,8 +129,6 @@ object PackageEditorForm: TPackageEditorForm
TabOrder = 6
end
object RegisteredPluginsGroupBox: TGroupBox
AnchorSideTop.Control = CallRegisterProcCheckBox
AnchorSideTop.Side = asrBottom
Left = 0
Height = 71
Top = 27
@ -160,10 +158,10 @@ object PackageEditorForm: TPackageEditorForm
AnchorSideLeft.Control = AddToUsesPkgSectionCheckBox
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = AddToUsesPkgSectionCheckBox
Left = 425
Height = 21
Left = 457
Height = 23
Top = 0
Width = 209
Width = 225
BorderSpacing.Left = 6
Caption = 'DisableI18NForLFMCheckBox'
OnChange = DisableI18NForLFMCheckBoxChange
@ -183,7 +181,7 @@ object PackageEditorForm: TPackageEditorForm
Cursor = crVSplit
Left = 0
Height = 5
Top = 311
Top = 213
Width = 464
Align = alBottom
ResizeAnchor = akBottom
@ -246,8 +244,8 @@ object PackageEditorForm: TPackageEditorForm
AnchorSideTop.Side = asrCenter
AnchorSideRight.Side = asrBottom
Left = 163
Height = 25
Top = 2
Height = 36
Top = -4
Width = 300
ButtonWidth = 23
Anchors = [akTop, akLeft, akRight]
@ -315,7 +313,7 @@ object PackageEditorForm: TPackageEditorForm
end
object ItemsTreeView: TTreeView
Left = 0
Height = 234
Height = 136
Top = 77
Width = 464
Align = alClient
@ -334,24 +332,33 @@ object PackageEditorForm: TPackageEditorForm
OnSelectionChanged = ItemsTreeViewSelectionChanged
Options = [tvoAllowMultiselect, tvoAutoItemHeight, tvoHideSelection, tvoKeepCollapsedNodes, tvoReadOnly, tvoRightClickSelect, tvoShowButtons, tvoShowLines, tvoShowRoot, tvoToolTips, tvoThemedDraw]
end
object EditorsGroupsPanel: TPanel
Left = 0
Height = 98
Top = 336
Width = 464
Align = alBottom
BevelOuter = bvNone
TabOrder = 6
end
object ItemsPopupMenu: TPopupMenu
OnPopup = ItemsPopupMenuPopup
left = 180
top = 10
Left = 180
Top = 10
end
object UsePopupMenu: TPopupMenu
OnPopup = UsePopupMenuPopup
left = 70
top = 10
Left = 70
Top = 10
end
object MorePopupMenu: TPopupMenu
OnPopup = MorePopupMenuPopup
left = 300
top = 10
Left = 300
Top = 10
end
object AddPopupMenu: TPopupMenu
left = 120
top = 10
Left = 120
Top = 10
object mnuAddDiskFile: TMenuItem
Caption = 'Add file...'
Default = True

View File

@ -43,7 +43,7 @@ uses
// IDEIntf
IDEImagesIntf, MenuIntf, LazIDEIntf, ProjectIntf,
FormEditingIntf, PackageDependencyIntf, PackageIntf, IDEHelpIntf, IDEOptionsIntf,
NewItemIntf, IDEWindowIntf, IDEDialogs, ComponentReg,
NewItemIntf, IDEWindowIntf, IDEDialogs, ComponentReg, IDEOptEditorIntf,
// IDE
MainBase, IDEProcs, LazarusIDEStrConsts, IDEDefs, CompilerOptions,
EnvironmentOpts, DialogProcs, InputHistory, PackageDefs, AddToPackageDlg,
@ -182,6 +182,12 @@ type
);
TPEFlags = set of TPEFlag;
TIDEPackageOptsDlgAction = (
iodaRead,
iodaWrite,
iodaRestore
);
{ TPackageEditorForm }
TPackageEditorForm = class(TBasePackageEditor,IFilesEditorInterface)
@ -233,6 +239,7 @@ type
UsePopupMenu: TPopupMenu;
ItemsPopupMenu: TPopupMenu;
MorePopupMenu: TPopupMenu;
EditorsGroupsPanel: TPanel;
procedure AddToProjectClick(Sender: TObject);
procedure AddToUsesPkgSectionCheckBoxChange(Sender: TObject);
procedure ApplyDependencyButtonClick(Sender: TObject);
@ -320,6 +327,8 @@ type
FSingleSelectedNode: TTreeNode;
FSingleSelectedFile: TPkgFile;
FSingleSelectedDep: TPkgDependency;
FHasEditorsGroups: Boolean;
FOptionsShownOfFile: TPkgFile;
FFirstNodeData: array[TPENodeType] of TPENodeData;
fUpdateLock: integer;
fForcedFlags: TPEFlags;
@ -332,6 +341,7 @@ type
procedure SetShowDirectoryHierarchy(const AValue: boolean);
procedure SetSortAlphabetically(const AValue: boolean);
procedure SetupComponents;
procedure CreatePackageFileEditors;
function OnTreeViewGetImageIndex({%H-}Str: String; Data: TObject; var {%H-}AIsEnabled: Boolean): Integer;
procedure UpdateNodeImage(TVNode: TTreeNode);
procedure UpdateNodeImage(TVNode: TTreeNode; NodeData: TPENodeData; Item: TObject);
@ -352,6 +362,10 @@ type
procedure ExtendIncPathForNewIncludeFile(const AnIncludeFile: string;
var IgnoreIncPaths: TFilenameToStringTree);
function CanBeAddedToProject: boolean;
procedure TraverseSettings(AOptions: TPackageFileIDEOptions; anAction: TIDEPackageOptsDlgAction);
procedure FileOptionsToGui;
procedure GuiToFileOptions;
procedure FileOptionsChange(Sender: TObject);
protected
fFlags: TPEFlags;
procedure SetLazPackage(const AValue: TLazPackage); override;
@ -2007,6 +2021,8 @@ begin
Name:='DirSummaryLabel';
Parent:=PropsGroupBox;
end;
CreatePackageFileEditors;
end;
procedure TPackageEditorForm.SetDependencyDefaultFilename(AsPreferred: boolean);
@ -2644,6 +2660,8 @@ var
begin
if not CanUpdate(pefNeedUpdateProperties,Immediately) then exit;
GuiToFileOptions;
FPlugins.Clear;
// check selection
@ -2784,6 +2802,13 @@ begin
else begin
PropsGroupBox.Enabled:=false;
end;
if FSingleSelectedFile<>nil then begin
EditorsGroupsPanel.Visible := FHasEditorsGroups;
FileOptionsToGui;
end else begin
EditorsGroupsPanel.Visible := False;
end;
finally
EnableAlign;
end;
@ -3122,6 +3147,7 @@ end;
procedure TPackageEditorForm.DoSave(SaveAs: boolean);
begin
GuiToFileOptions;
PackageEditors.SavePackage(LazPackage,SaveAs);
UpdateTitle;
UpdateButtons;
@ -3296,6 +3322,132 @@ begin
inherited Destroy;
end;
procedure TPackageEditorForm.TraverseSettings(AOptions: TPackageFileIDEOptions; anAction: TIDEPackageOptsDlgAction);
procedure Traverse(Control: TWinControl);
var
i: Integer;
begin
if Control <> nil then
begin
if Control is TAbstractIDEOptionsEditor then
with TAbstractIDEOptionsEditor(Control) do
begin
case anAction of
iodaRead: ReadSettings(AOptions);
iodaWrite: WriteSettings(AOptions);
iodaRestore: RestoreSettings(AOptions);
end;
end;
for i := 0 to Control.ControlCount -1 do
if Control.Controls[i] is TWinControl then
begin
Traverse(TWinControl(Control.Controls[i]));
end;
end;
end;
begin
Traverse(EditorsGroupsPanel);
end;
procedure TPackageEditorForm.CreatePackageFileEditors;
var
Instance: TAbstractIDEOptionsEditor;
i, j: integer;
Rec: PIDEOptionsGroupRec;
ACaption: string;
ItemTabSheet: TTabSheet;
GroupPageControl: TPageControl;
GroupGroupBox: TGroupBox;
begin
FHasEditorsGroups := False;
IDEEditorGroups.Resort;
for i := 0 to IDEEditorGroups.Count - 1 do
begin
Rec := IDEEditorGroups[i];
DebugLn(['TPackageEditorForm.CreatePackageFileEditors ',Rec^.GroupClass.ClassName]);
if (Rec^.GroupClass.InheritsFrom(TAbstractPackageFileIDEOptions)) and (Rec^.Items <> nil) then
begin
if Rec^.GroupClass<>nil then
ACaption := Rec^.GroupClass.GetGroupCaption
else
ACaption := format('Group<%d>',[i]);
GroupGroupBox := TGroupBox.Create(Self);
GroupGroupBox.Caption := ACaption;
GroupGroupBox.Align := alClient;
GroupGroupBox.Parent := EditorsGroupsPanel;
GroupPageControl := TPageControl.Create(Self);
GroupPageControl.Parent := GroupGroupBox;
GroupPageControl.Align := alClient;
FHasEditorsGroups := True;
for j := 0 to Rec^.Items.Count - 1 do
begin
ItemTabSheet := GroupPageControl.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];
ItemTabSheet.Caption := Instance.GetTitle;
end;
end;
end;
EditorsGroupsPanel.Visible := FHasEditorsGroups;
end;
procedure TPackageEditorForm.FileOptionsToGui;
var
PackageOptions: TPackageFileIDEOptions;
begin
if Assigned(FSingleSelectedFile) then
begin
FOptionsShownOfFile := FSingleSelectedFile;
PackageOptions := TPackageFileIDEOptions.Create(LazPackage, FOptionsShownOfFile);
try
PackageOptions.DoBeforeRead;
TraverseSettings(PackageOptions, iodaRead);
PackageOptions.DoAfterRead;
finally;
PackageOptions.Free;
end;
end;
end;
procedure TPackageEditorForm.GuiToFileOptions;
var
PackageOptions: TPackageFileIDEOptions;
begin
if Assigned(FOptionsShownOfFile) then
begin
PackageOptions := TPackageFileIDEOptions.Create(LazPackage, FOptionsShownOfFile);
try
PackageOptions.DoBeforeWrite(False);
TraverseSettings(PackageOptions, iodaWrite);
PackageOptions.DoAfterWrite(False);
finally;
PackageOptions.Free;
end;
end;
end;
procedure TPackageEditorForm.FileOptionsChange(Sender: TObject);
begin
LazPackage.Modified := True;
end;
{ TPackageEditors }
function TPackageEditors.GetEditors(Index: integer): TPackageEditorForm;