IDE: add Intf to inject pages into the initial setup dialog.

This commit is contained in:
Martin 2024-08-05 16:32:48 +02:00
parent 6e4a0dd2ae
commit c9afc8aa72
4 changed files with 375 additions and 38 deletions

View File

@ -7,10 +7,10 @@ object InitialSetupDialog: TInitialSetupDialog
Caption = 'InitialSetupDialog'
ClientHeight = 450
ClientWidth = 620
Position = poScreenCenter
LCLVersion = '3.99.0.0'
OnCreate = FormCreate
OnDestroy = FormDestroy
Position = poScreenCenter
LCLVersion = '2.3.0.0'
object PropertiesTreeView: TTreeView
AnchorSideLeft.Control = Owner
AnchorSideTop.Control = WelcomePaintBox
@ -32,8 +32,8 @@ object InitialSetupDialog: TInitialSetupDialog
ShowLines = False
ShowRoot = False
TabOrder = 0
OnSelectionChanged = PropertiesTreeViewSelectionChanged
Options = [tvoAutoItemHeight, tvoHideSelection, tvoKeepCollapsedNodes, tvoReadOnly, tvoToolTips, tvoThemedDraw]
OnSelectionChanged = PropertiesTreeViewSelectionChanged
end
object Splitter1: TSplitter
AnchorSideTop.Control = PropertiesTreeView
@ -68,9 +68,9 @@ object InitialSetupDialog: TInitialSetupDialog
AutoSize = True
Caption = 'StartIDEBitBtn'
Constraints.MinWidth = 100
OnClick = StartIDEBitBtnClick
ParentFont = False
TabOrder = 0
OnClick = StartIDEBitBtnClick
end
end
object PropertiesPageControl: TPageControl
@ -88,11 +88,11 @@ object InitialSetupDialog: TInitialSetupDialog
ActivePage = DebuggerTabSheet
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Right = 6
Options = [nboHidePageListPopup]
ParentFont = False
TabIndex = 4
TabOrder = 3
OnChange = PropertiesPageControlChange
Options = [nboHidePageListPopup]
object LazarusTabSheet: TTabSheet
Caption = 'LazarusTabSheet'
ChildSizing.LeftRightSpacing = 6
@ -125,10 +125,10 @@ object InitialSetupDialog: TInitialSetupDialog
Width = 424
Anchors = [akTop, akLeft, akRight]
ItemHeight = 15
OnChange = LazDirComboBoxChange
ParentFont = False
TabOrder = 0
Text = 'LazDirComboBox'
OnChange = LazDirComboBoxChange
end
object LazDirMemo: TMemo
AnchorSideTop.Control = LazDirBrowseButton
@ -161,9 +161,9 @@ object InitialSetupDialog: TInitialSetupDialog
Width = 132
AutoSize = True
Caption = 'LazDirBrowseButton'
OnClick = LazDirBrowseButtonClick
ParentFont = False
TabOrder = 2
OnClick = LazDirBrowseButtonClick
end
end
object CompilerTabSheet: TTabSheet
@ -198,10 +198,10 @@ object InitialSetupDialog: TInitialSetupDialog
Width = 424
Anchors = [akTop, akLeft, akRight]
ItemHeight = 15
OnChange = CompilerComboBoxChange
ParentFont = False
TabOrder = 0
Text = 'CompilerComboBox'
OnChange = CompilerComboBoxChange
end
object CompilerBrowseButton: TButton
AnchorSideLeft.Control = CompilerTabSheet
@ -213,9 +213,9 @@ object InitialSetupDialog: TInitialSetupDialog
Width = 149
AutoSize = True
Caption = 'CompilerBrowseButton'
OnClick = CompilerBrowseButtonClick
ParentFont = False
TabOrder = 1
OnClick = CompilerBrowseButtonClick
end
object CompilerMemo: TMemo
AnchorSideLeft.Control = CompilerTabSheet
@ -268,10 +268,10 @@ object InitialSetupDialog: TInitialSetupDialog
Width = 424
Align = alTop
ItemHeight = 15
OnChange = FPCSrcDirComboBoxChange
ParentFont = False
TabOrder = 0
Text = 'FPCSrcDirComboBox'
OnChange = FPCSrcDirComboBoxChange
end
object FPCSrcDirBrowseButton: TButton
AnchorSideLeft.Control = FPCSourcesTabSheet
@ -283,9 +283,9 @@ object InitialSetupDialog: TInitialSetupDialog
Width = 152
AutoSize = True
Caption = 'FPCSrcDirBrowseButton'
OnClick = FPCSrcDirBrowseButtonClick
ParentFont = False
TabOrder = 1
OnClick = FPCSrcDirBrowseButtonClick
end
object FPCSrcDirMemo: TMemo
AnchorSideTop.Control = FPCSrcDirBrowseButton
@ -346,9 +346,9 @@ object InitialSetupDialog: TInitialSetupDialog
Top = 56
Width = 78
Caption = 'Stop'
OnClick = StopScanButtonClick
ParentFont = False
TabOrder = 4
OnClick = StopScanButtonClick
end
end
object MakeExeTabSheet: TTabSheet
@ -364,10 +364,10 @@ object InitialSetupDialog: TInitialSetupDialog
Align = alTop
BorderSpacing.Around = 6
ItemHeight = 15
OnChange = MakeExeComboBoxChange
ParentFont = False
TabOrder = 0
Text = 'MakeExeComboBox'
OnChange = MakeExeComboBoxChange
end
object MakeExeLabel: TLabel
Left = 6
@ -392,9 +392,9 @@ object InitialSetupDialog: TInitialSetupDialog
AutoSize = True
BorderSpacing.Around = 6
Caption = 'MakeExeBrowseButton'
OnClick = MakeExeBrowseButtonClick
ParentFont = False
TabOrder = 1
OnClick = MakeExeBrowseButtonClick
end
object MakeExeMemo: TMemo
AnchorSideTop.Control = MakeExeBrowseButton
@ -434,10 +434,10 @@ object InitialSetupDialog: TInitialSetupDialog
Align = alTop
BorderSpacing.Around = 6
ItemHeight = 15
OnChange = FppkgComboBoxChange
ParentFont = False
TabOrder = 0
Text = 'FppkgComboBox'
OnChange = FppkgComboBoxChange
end
object FppkgLabel: TLabel
Left = 6
@ -462,9 +462,9 @@ object InitialSetupDialog: TInitialSetupDialog
AutoSize = True
BorderSpacing.Around = 6
Caption = 'FppkgBrowseButton'
OnClick = FppkgBrowseButtonClick
ParentFont = False
TabOrder = 1
OnClick = FppkgBrowseButtonClick
end
object FppkgMemo: TMemo
AnchorSideTop.Control = FppkgWriteConfigButton
@ -499,9 +499,9 @@ object InitialSetupDialog: TInitialSetupDialog
BorderSpacing.Around = 6
Caption = 'FppkgWriteConfigButton'
Enabled = False
OnClick = FppkgWriteConfigButtonClick
ParentFont = False
TabOrder = 3
OnClick = FppkgWriteConfigButtonClick
end
end
end

View File

@ -41,7 +41,7 @@ interface
uses
// RTL + FCL
Classes, SysUtils, pkgglobals, fpmkunit,
Classes, SysUtils, fgl, pkgglobals, fpmkunit,
// LCL
Forms, Controls, Buttons, Dialogs, Graphics, ComCtrls, ExtCtrls, StdCtrls,
// CodeTools
@ -53,16 +53,26 @@ uses
// DebuggerIntf
DbgIntfDebuggerBase,
// LazDebuggerGdbmi
GDBMIDebugger,
GDBMIDebugger, DividerBevel,
// IdeConfig
LazConf, EnvironmentOpts, TransferMacros, IDEProcs,
// IDE
LazarusIDEStrConsts, IDETranslations, BaseBuildManager, InitialSetupProc,
GenerateFppkgConfigurationDlg, InitialSetupDlgDebuggerFrame, IdeDebuggerOpts;
GenerateFppkgConfigurationDlg, LazarusPackageIntf, InitialSetupDlgDebuggerFrame, IdeDebuggerOpts;
type
TInitialSetupDialog = class;
TSetupFrameInfo = record
Node: TTreeNode;
Page: TTabSheet;
State: TInitSetupDlgFrameState;
Action: TInitSetupDlgFrameAction;
Group: String;
end;
TSetupDlgFrameMap = specialize TFPGMap<Pointer{ISetupDlgFrame}, TSetupFrameInfo>;
TGroupMap = specialize TFPGMap<string, TSetupFrameInfo>;
{ TSearchFpcSourceThread }
TSearchFpcSourceThread = class(TThread)
@ -88,7 +98,7 @@ type
{ TInitialSetupDialog }
TInitialSetupDialog = class(TForm)
TInitialSetupDialog = class(TForm, ISetupDlgProvider)
BtnPanel: TPanel;
CompilerBrowseButton: TButton;
CompilerComboBox: TComboBox;
@ -149,6 +159,8 @@ type
procedure FppkgWriteConfigButtonClick(Sender: TObject);
private
FInitDebuggerFrame: TInitDebuggerFrame;
FSetupDlgFrameMap: TSetupDlgFrameMap;
FSetupDlgGroupMap: TGroupMap;
FFlags: TSDFlags;
FLastParsedLazDir: string;
fLastParsedCompiler: string;
@ -156,16 +168,21 @@ type
fLastParsedMakeExe: string;
fLastParsedFppkgConfigFile: string;
FIdleConnected: boolean;
ImgIDFatal: LongInt;
ImgIDError: LongInt;
ImgIDWarning: LongInt;
ImgIDNote: LongInt;
ImgIDHint: LongInt;
ImgIDInfo: LongInt;
FHeadGraphic: TPortableNetworkGraphic;
FSelectingPage: boolean;
FCandidates: array[TSDFilenameType] of TSDFileInfoList; // list of TSDFileInfo
fSearchFpcSourceThread: TSearchFpcSourceThread;
procedure DoDbgFrameStateChanged(AState: TSDFilenameQuality);
procedure FrameStateChanged(AnSender: ISetupDlgFrame; AState: TInitSetupDlgFrameState; AnAction: TInitSetupDlgFrameAction);
procedure SetGroupCaption(AGroupId, AName: String);
procedure UpdateCaptions;
procedure SelectPage(const NodeText: string);
procedure SelectPage(const ATreeNode: TTreeNode; AnUserSelect: Boolean = False);
function SelectDirectory(aTitle: string): string;
function SelectDirectory(aTitle: string; aPathFileName: string;
aEnvOptParseType: TEnvOptParseType): string; overload;
@ -200,6 +217,7 @@ type
TVNodeDebugger: TTreeNode;
TVNodeFppkg: TTreeNode;
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure Init; //Check for config errors, find and show alternatives
property IdleConnected: boolean read FIdleConnected write SetIdleConnected;
end;
@ -243,6 +261,15 @@ end;
{ TSearchFpcSourceThread }
function DoCompFrameList(const Item1, Item2: ISetupDlgFrame): Integer;
begin
Result := Item1.SortOrder - Item2.SortOrder;
if Result = 0 then begin
if Item1.UniqueId < Item2.UniqueId then Result := -1;
if Item1.UniqueId > Item2.UniqueId then Result := 1;
end;
end;
constructor TSearchFpcSourceThread.Create(aSetupDialog: TInitialSetupDialog);
begin
inherited Create(True);
@ -397,6 +424,17 @@ end;
{ TInitialSetupDialog }
procedure TInitialSetupDialog.FormCreate(Sender: TObject);
var
FrameList: TSetupDlgFrameList;
i, GrpIdx: Integer;
NewNode: TTreeNode;
NewTab: TTabSheet;
ScrollBox: TScrollBox;
NewParent: TWinControl;
CurFrame: ISetupDlgFrame;
Info, GrpInfo: TSetupFrameInfo;
Grp: String;
NewDiv: TDividerBevel;
begin
LazarusTabSheet.Caption:='Lazarus';
CompilerTabSheet.Caption:=lisCompiler;
@ -413,15 +451,114 @@ begin
TVNodeFPCSources:=PropertiesTreeView.Items.Add(nil,FPCSourcesTabSheet.Caption);
TVNodeMakeExe:=PropertiesTreeView.Items.Add(nil,MakeExeTabSheet.Caption);
TVNodeDebugger:=PropertiesTreeView.Items.Add(nil,DebuggerTabSheet.Caption);
LazarusTabSheet.Tag := PtrUInt(Pointer(TVNodeLazarus));
CompilerTabSheet.Tag := PtrUInt(Pointer(TVNodeCompiler));
FPCSourcesTabSheet.Tag := PtrUInt(Pointer(TVNodeFPCSources));
MakeExeTabSheet.Tag := PtrUInt(Pointer(TVNodeMakeExe));
DebuggerTabSheet.Tag := PtrUInt(Pointer(TVNodeDebugger));
FppkgTabSheet.TabVisible := EnvironmentOptions.FppkgCheck;
if FppkgTabSheet.TabVisible then
if FppkgTabSheet.TabVisible then begin
TVNodeFppkg:=PropertiesTreeView.Items.Add(nil,FppkgTabSheet.Caption);
ImgIDError := Imagelist1.AddResourceName(HInstance, 'state_error');
FppkgTabSheet.Tag := PtrUInt(Pointer(TVNodeFppkg));
end;
ImgIDFatal := Imagelist1.AddResourceName(HInstance, 'state_fatal');
ImgIDError := Imagelist1.AddResourceName(HInstance, 'state_error');
ImgIDWarning := Imagelist1.AddResourceName(HInstance, 'state_warning');
ImgIDHint := Imagelist1.AddResourceName(HInstance, 'state_hint');
ImgIDNote := Imagelist1.AddResourceName(HInstance, 'state_note');
ImgIDHint := Imagelist1.AddResourceName(HInstance, 'state_hint');
ImgIDInfo := Imagelist1.AddResourceName(HInstance, 'state_information');
IDEImages.AssignImage(StopScanButton, 'menu_stop');
FrameList := SetupDlgFrameList;
FrameList.Sort(@DoCompFrameList);
DisableAutoSizing;
try
for i := 0 to FrameList.Count - 1 do begin
CurFrame := FrameList[i];
Grp := CurFrame.GroupId;
GrpIdx := -1;
NewNode := nil;
if Grp <> '' then begin
GrpIdx := FSetupDlgGroupMap.IndexOf(Grp);
if GrpIdx >= 0 then begin
GrpInfo := FSetupDlgGroupMap.Data[GrpIdx];
NewNode := GrpInfo.Node;
NewTab := GrpInfo.Page;
ScrollBox := NewTab.Controls[0] as TScrollBox;
end;
end;
if NewNode = nil then begin
NewNode := PropertiesTreeView.Items.Add(nil, CurFrame.Caption);
NewTab := PropertiesPageControl.AddTabSheet;
NewTab.Caption := CurFrame.Caption;
NewTab.Tag := PtrUInt(NewNode);
ScrollBox := TScrollBox.Create(Self);
ScrollBox.Parent := NewTab;
ScrollBox.Align := alClient;
ScrollBox.HorzScrollBar.Visible := False;
NewParent := ScrollBox;
if (GrpIdx < 0) and (Grp <> '') then begin
GrpInfo.Node := NewNode;
GrpInfo.Page := NewTab;
GrpInfo.State := issOk;
GrpInfo.Action := isaReady;
GrpIdx := FSetupDlgGroupMap.Add(Grp, GrpInfo);
end;
end;
if GrpIdx >= 0 then begin
NewDiv := TDividerBevel.Create(Self);
NewDiv.Parent := ScrollBox;
if ScrollBox.ControlCount > 1 then begin
NewDiv.AnchorSide[akTop].Side := asrBottom;
NewDiv.AnchorSide[akTop].Control := ScrollBox.Controls[ScrollBox.ControlCount - 2];
end
else begin
NewDiv.AnchorSide[akTop].Side := asrTop;
NewDiv.AnchorSide[akTop].Control := ScrollBox;
end;
NewDiv.AnchorSide[akLeft].Side := asrTop;
NewDiv.AnchorSide[akLeft].Control := ScrollBox;
NewDiv.AnchorSide[akRight].Side := asrBottom;
NewDiv.AnchorSide[akRight].Control := ScrollBox;
NewDiv.Anchors := [akTop, akLeft, akRight];
NewDiv.Caption := CurFrame.Caption;
NewParent := TPanel.Create(Self);
TPanel(NewParent).Parent := ScrollBox;
TPanel(NewParent).AnchorSide[akTop].Side := asrBottom;
TPanel(NewParent).AnchorSide[akTop].Control := NewDiv;
TPanel(NewParent).AnchorSide[akLeft].Side := asrTop;
TPanel(NewParent).AnchorSide[akLeft].Control := ScrollBox;
TPanel(NewParent).AnchorSide[akRight].Side := asrBottom;
TPanel(NewParent).AnchorSide[akRight].Control := ScrollBox;
TPanel(NewParent).Anchors := [akTop, akLeft, akRight];
TPanel(NewParent).AutoSize := True;
TPanel(NewParent).BevelInner := bvNone;
TPanel(NewParent).BevelOuter := bvNone;
end;
Info.Node := NewNode;
Info.Page := NewTab;
Info.State := issOk;
Info.Action := isaReady;
Info.Group := Grp;
FSetupDlgFrameMap.Add(Pointer(CurFrame), Info);
CurFrame.AddToDialog(Self, NewParent, Self);
end;
finally
EnableAutoSizing;
end;
UpdateCaptions;
Application.AddOnActivateHandler(@OnAppActivate);
@ -573,22 +710,22 @@ end;
procedure TInitialSetupDialog.PropertiesPageControlChange(Sender: TObject);
var
s: String;
i: Integer;
t: PtrInt;
begin
if PropertiesPageControl.ActivePage=nil then exit;
s:=PropertiesPageControl.ActivePage.Caption;
t:=PropertiesPageControl.ActivePage.tag;
for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do
if PropertiesTreeView.Items.TopLvlItems[i].Text=s then
PropertiesTreeView.Selected:=PropertiesTreeView.Items.TopLvlItems[i];
if PtrUInt(PropertiesTreeView.Items.TopLvlItems[i])=t then
SelectPage(PropertiesTreeView.Items.TopLvlItems[i], True);
end;
procedure TInitialSetupDialog.PropertiesTreeViewSelectionChanged(Sender: TObject);
begin
if PropertiesTreeView.Selected=nil then
SelectPage(TVNodeLazarus.Text)
SelectPage(TVNodeLazarus)
else
SelectPage(PropertiesTreeView.Selected.Text);
SelectPage(PropertiesTreeView.Selected, True);
end;
procedure TInitialSetupDialog.StartIDEBitBtnClick(Sender: TObject);
@ -596,6 +733,7 @@ var
Node: TTreeNode;
s: String;
MsgResult: TModalResult;
i: Integer;
begin
Node:=FirstErrorNode;
s:='';
@ -628,6 +766,8 @@ begin
if s<>'' then
EnvironmentOptions.MakeFilename:=s;
FInitDebuggerFrame.ApplySelection;
for i := 0 to SetupDlgFrameList.Count - 1 do
SetupDlgFrameList[i].ApplySelection;
ModalResult:=mrOk;
end;
@ -650,7 +790,11 @@ begin
end;
procedure TInitialSetupDialog.OnIdle(Sender: TObject; var Done: Boolean);
var
f: Boolean;
i: Integer;
begin
f := FFlags <> [];
if sdfCompilerFilenameNeedsUpdate in FFlags then begin
UpdateCompilerFilenameCandidates;
UpdateCompilerNote;
@ -670,6 +814,11 @@ begin
UpdateFppkgNote;
end else
IdleConnected:=false;
if f then begin
for i := 0 to SetupDlgFrameList.Count - 1 do
SetupDlgFrameList[i].UpdateState;
end;
end;
procedure TInitialSetupDialog.UpdateCaptions;
@ -727,22 +876,88 @@ begin
TVNodeDebugger.SelectedIndex:=ImageIndex;
end;
procedure TInitialSetupDialog.SelectPage(const NodeText: string);
procedure TInitialSetupDialog.FrameStateChanged(AnSender: ISetupDlgFrame;
AState: TInitSetupDlgFrameState; AnAction: TInitSetupDlgFrameAction);
var
ImageIndex, i, j: Integer;
nd: TTreeNode;
info, info2: TSetupFrameInfo;
begin
i := FSetupDlgFrameMap.IndexOf(Pointer(AnSender));
if i < 0 then exit;
info := FSetupDlgFrameMap.Data[i];
nd := info.Node;
info.State := AState;
info.Action := AnAction;
FSetupDlgFrameMap.Data[i] := info;
if info.Group <> '' then begin
for j := 0 to FSetupDlgFrameMap.Count - 1 do begin
info2 := FSetupDlgFrameMap.Data[j];
if (info2.Group = info.Group) then begin
if (info2.State > AState) then AState := info2.State;
end;
end;
end;
ImageIndex := -1;
case AState of
issOk: ImageIndex := -1;
issInfo: ImageIndex := ImgIDInfo;
issHint: ImageIndex := ImgIDHint;
issNote: ImageIndex := ImgIDNote;
issWarning: ImageIndex := ImgIDWarning;
issError: ImageIndex := ImgIDError;
issFatal: ImageIndex := ImgIDFatal;
end;
nd.ImageIndex:=ImageIndex;
nd.SelectedIndex:=ImageIndex;
end;
procedure TInitialSetupDialog.SetGroupCaption(AGroupId, AName: String);
var
GrpIdx: Integer;
GrpInfo: TSetupFrameInfo;
begin
GrpIdx := FSetupDlgGroupMap.IndexOf(AGroupId);
if GrpIdx >= 0 then begin
GrpInfo := FSetupDlgGroupMap.Data[GrpIdx];
GrpInfo.Page.Caption := AName;
GrpInfo.Node.Text := AName;
end;
end;
procedure TInitialSetupDialog.SelectPage(const ATreeNode: TTreeNode; AnUserSelect: Boolean);
var
i: Integer;
Node: TTreeNode;
info: TSetupFrameInfo;
begin
if FSelectingPage then exit;
FSelectingPage:=true;
try
for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do begin
Node:=PropertiesTreeView.Items.TopLvlItems[i];
if Node.Text=NodeText then begin
if Node=ATreeNode then begin
PropertiesTreeView.Selected:=Node;
break;
end;
end;
for i:=0 to PropertiesPageControl.PageCount-1 do begin
if PropertiesPageControl.Pages[i].Tag=PtrUInt(ATreeNode) then begin
PropertiesPageControl.ActivePageIndex:=i;
break;
end;
end;
for i := 0 to FSetupDlgFrameMap.Count - 1 do begin
info := FSetupDlgFrameMap.Data[i];
if info.Node = ATreeNode then
ISetupDlgFrame(FSetupDlgFrameMap.Keys[i]).PageSelected(AnUserSelect);
end;
finally
FSelectingPage:=false;
end;
@ -1049,6 +1264,11 @@ function TInitialSetupDialog.FirstErrorNode: TTreeNode;
var
i: Integer;
begin
for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do
begin
Result:=PropertiesTreeView.Items.TopLvlItems[i];
if Result.ImageIndex=ImgIDFatal then exit;
end;
for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do
begin
Result:=PropertiesTreeView.Items.TopLvlItems[i];
@ -1067,6 +1287,24 @@ begin
if Result.ImageIndex=ImgIDWarning then
exit;
end;
for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do
begin
Result:=PropertiesTreeView.Items.TopLvlItems[i];
if Result.ImageIndex=ImgIDNote then
exit;
end;
for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do
begin
Result:=PropertiesTreeView.Items.TopLvlItems[i];
if Result.ImageIndex=ImgIDHint then
exit;
end;
for i:=0 to PropertiesTreeView.Items.TopLvlCount-1 do
begin
Result:=PropertiesTreeView.Items.TopLvlItems[i];
if Result.ImageIndex=ImgIDInfo then
exit;
end;
Result:=nil;
end;
@ -1131,6 +1369,8 @@ end;
constructor TInitialSetupDialog.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
FSetupDlgFrameMap := TSetupDlgFrameMap.Create;
FSetupDlgGroupMap := TGroupMap.Create;
FInitDebuggerFrame := TInitDebuggerFrame.Create(Self);
FInitDebuggerFrame.Parent := DebuggerTabSheet;
@ -1139,6 +1379,18 @@ begin
FInitDebuggerFrame.Init;
end;
destructor TInitialSetupDialog.Destroy;
var
i: Integer;
begin
for i := 0 to SetupDlgFrameList.Count - 1 do
SetupDlgFrameList[i].Done;
inherited Destroy;
FSetupDlgFrameMap.Free;
FSetupDlgGroupMap.Free;
end;
procedure TInitialSetupDialog.Init;
var
Node: TTreeNode;
@ -1148,6 +1400,7 @@ var
SecondaryFilename: String;
PrimaryEnvs: TStringList;
SecondaryEnvs: TStringList;
i: Integer;
begin
IsFirstStart:=not FileExistsCached(EnvironmentOptions.Filename);
if not IsFirstStart then begin
@ -1235,7 +1488,7 @@ begin
{$IFNDEF LCLCarbon}
// carbon interface does not support Synchronize outside Application.Run
StartFPCSrcThread;
SelectPage(TVNodeFPCSources.Text);
SelectPage(TVNodeFPCSources);
{$ENDIF}
end;
end;
@ -1276,11 +1529,16 @@ begin
UpdateFppkgNote;
end;
for i := 0 to SetupDlgFrameList.Count - 1 do
SetupDlgFrameList[i].Init;
for i := 0 to SetupDlgFrameList.Count - 1 do
SetupDlgFrameList[i].UpdateState;
// select first error
Node:=FirstErrorNode;
if Node=nil then
Node:=TVNodeLazarus;
PropertiesTreeView.Selected:=Node;
SelectPage(Node);
end;
procedure TInitialSetupDialog.UpdateFppkgNote;

View File

@ -108,7 +108,7 @@ uses
DbgIntfDebuggerBase, DbgIntfProcess, LazDebuggerIntf, LazDebuggerIntfBaseTypes,
idedebuggerpackage, FpDebugValueConvertors, IdeDebuggerBackendValueConv, IdeDebuggerBase,
// packager
PackageSystem, PkgManager, BasePkgManager, LPKCache,
PackageSystem, PkgManager, BasePkgManager, LPKCache, LazarusPackageIntf,
// source editing
SourceEditor, CodeToolsOptions, IDEOptionDefs,
CodeToolsDefines, DiffDialog, UnitInfoDlg, EditorOptions,
@ -1436,6 +1436,7 @@ var
Note: string;
ConfigFile: string;
SkipAllTests: Boolean;
i: Integer;
begin
{$IFDEF DebugSearchFPCSrcThread}
ShowSetupDialog:=true;
@ -1520,6 +1521,11 @@ begin
ShowSetupDialog:=true;
end;
for i := 0 to SetupDlgFrameList.Count - 1 do begin
if ShowSetupDialog then break;
ShowSetupDialog := SetupDlgFrameList[i].RequireSetup;
end;
// show setup dialog
if ShowSetupDialog then begin
OldLazDir:=EnvironmentOptions.LazarusDirectory;

View File

@ -20,6 +20,7 @@
unit LazarusPackageIntf;
{$mode objfpc}{$H+}
{$Interfaces CORBA}
interface
@ -27,7 +28,7 @@ uses
{$IFDEF FPC_DOTTEDUNITS}
System.Classes;
{$ELSE}
Classes;
Classes, SysUtils, fgl;
{$ENDIF}
type
@ -43,17 +44,81 @@ type
end;
PRegisteredPackage = ^TRegisteredPackage;
(* ISetupDlgFrame - Used in initial setup dlg
Registration must be done from an initialization section.
The dialog is shown before the "Register" procedures of package are called
*)
ISetupDlgFrame = interface;
// Ordered by severity
TInitSetupDlgFrameState = ( // icon to show in SetupDlg
issOk, issInfo, issHint, issNote, issWarning, issError, issFatal
);
TInitSetupDlgFrameAction = ( // actions needed
isaReady,
isaRestartNeeded
//isaRebuildNeeded
);
ISetupDlgProvider = interface ['{DF17C90A-FED6-4D04-8BFA-B8C2DE84876F}']
procedure FrameStateChanged(AnSender: ISetupDlgFrame; AState: TInitSetupDlgFrameState; AnAction: TInitSetupDlgFrameAction);
procedure SetGroupCaption(AGroupId, AName: String);
end;
ISetupDlgFrame = interface ['{2516A45E-32D5-4826-AA7E-45163437E7E9}']
(* RequireSetup: The package wants the initial setup dialog shown, it requires user feedback *)
function RequireSetup: boolean;
(* AddToDialog: Package should perform all necessary GUI setup
During creation, he package will receive 3 calls in the following order:
- AddToDialog: To setup GUI
- Init: To do any required work, except GUI
- UpdateState: To indicate its initial state. It may also Update it's own GUI
*)
procedure AddToDialog(AnOwner, AParent: TComponent; // AParent: TWinControl that will hold the frame
ADialog: ISetupDlgProvider
);
(* Init: Any heavy initialization work. No GUI work. (This might be run in a thread) *)
procedure Init; // Called once
(* Done: Teardown, Owner/Parent get freed. THe frame will be freed if it is owned. *)
procedure Done; // Called once // Owner/Parent get freed
function Caption: String;
function SortOrder: Integer; // 3rd Party start at 1000 upwards
function UniqueId: String;
function GroupId: String;
(* PageSelected: Either the user selected the page, or it was show automatically *)
procedure PageSelected(AnUserActivated: Boolean);
(* UpdateState: The Package should call all methods on ISetupDlgProvider needed to indicate its state.
It must do so before it returns.
Any state (if more states are added in future) that is not indicated shall be assumed default or undefined.
States must be indicated, even if they have not changed since the last time.
*)
procedure UpdateState;
(* ApplySelection: Called before the IDE is started *)
procedure ApplySelection;
function Internal: TObject; // for usage by the package
end;
TSetupDlgFrameList = specialize TFPGList<ISetupDlgFrame>;
var
RegisteredPackages: TFPList; // list of PRegisteredPackage
RegisterUnitProc: TRegisterUnitProc;
TheSetupDlgFrameList: TSetupDlgFrameList;
procedure RegisterUnit(const TheUnitName: string; RegisterProc: TRegisterProc);
procedure RegisterPackage(const ThePackageName: string;
RegisterProc: TRegisterProc);
procedure ClearRegisteredPackages;
function SetupDlgFrameList: TSetupDlgFrameList;
implementation
operator < (a,b: ISetupDlgFrame): boolean;
begin
end;
procedure RegisterUnit(const TheUnitName: string; RegisterProc: TRegisterProc);
begin
RegisterUnitProc(TheUnitName,RegisterProc);
@ -86,6 +151,13 @@ begin
end;
end;
function SetupDlgFrameList: TSetupDlgFrameList;
begin
if TheSetupDlgFrameList = nil then
TheSetupDlgFrameList := TSetupDlgFrameList.Create;
Result := TheSetupDlgFrameList;
end;
procedure InternalInit;
begin
RegisterUnitProc:=nil;
@ -102,6 +174,7 @@ initialization
finalization
InternalFinal;
FreeAndNil(TheSetupDlgFrameList);
end.