cmdlinecfg:

* minimized TCmdLineLayoutInfo class public section;
* updated the TCmdLineScrollBoxControl loader to use %%other switch; using hash list to check of used/unused controls;
* updated readme.txt description for UI layout controls;
* updated IDE package to make the dialog look close to the existing compiler options;
* updated testguibuild to be able to load a certain section only;
* added smaller sample files for testguibuild, modified conf.coptui to have %%other switch, where all "non-default" compiler options would go;

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@2806 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
skalogryz
2013-10-12 17:15:48 +00:00
parent c63c5bb6b7
commit 33dadcd154
15 changed files with 474 additions and 148 deletions

View File

@ -3,8 +3,7 @@ unit cmdlinecfgui;
interface
uses
Classes, SysUtils,
cmdlinecfg;
Classes, SysUtils, contnrs, cmdlinecfg;
type
{ TCmdLineLayoutInfo }
@ -15,6 +14,7 @@ type
{ TLayoutSection }
TLayoutElementType = (letSwitch, letSection);
TLayoutElementTypes = set of TLayoutElementType;
TLayoutSection = class(TObject)
//level : integer; // number of "dots" in the name
@ -27,22 +27,17 @@ type
Elements : array of TLayoutSection;
ElemCount : integer;
function AddElement(const AName: string; AElementType: TLayoutElementType): TLayoutSection;
constructor Create(const AName: string = ''; AElementType: TLayoutElementType = letSection);
destructor Destroy; override;
property Name: string read fName;
property ElementType: TLayoutElementType read fElementType;
end;
TCmdLineLayoutInfo = class(TObject)
private
fSections: TStringList;
fValidOrder: Boolean;
function DoGetSection(const SectName: String; Forced: Boolean = true): TLayoutSection;
public
RootElement : TLayoutSection;
constructor Create;
destructor Destroy; override;
function AddSection(const Section: string): TLayoutSection;
function GetSection(const Section: string): TLayoutSection;
//function GetSwitches(const Section: string; Dst: TStrings): Boolean;
end;
{ TCmdLineUIControl }
@ -53,14 +48,94 @@ type
protected
procedure ValueChanged; virtual;
public
procedure Init(cfg: TCmdLineCfg; layout: TCmdLineLayoutInfo); virtual; abstract;
procedure Init(cfg: TCmdLineCfg; layout: TCmdLineLayoutInfo; const ASection : string = ''); virtual; abstract;
procedure SetValues(list: TList {of TCmdLineOptionValue}); virtual; abstract;
procedure Serialize(list: TList {of TCmdLineOptionValue}); virtual; abstract;
property OnValueChanged: TNotifyEvent read FValueChanged write fValueChanged;
end;
function LayoutFindElement(aparent: TLayoutSection; const Name: string; LookFor: TLayoutElementTypes = [letSection] ): TLayoutSection;
procedure LayoutEnumElement(aparent: TLayoutSection; list: TList; LookFor: TLayoutElementTypes = [letSection] );
procedure LayoutGetUnused(cmd: TCmdLineCfg; layout: TLayoutSection; list: TList);
implementation
procedure LayoutGetSwitches(root: TLayoutSection; hash: TFPHashObjectList);
var
sct : TList;
i : Integer;
j : Integer;
el : TLayoutSection;
sel : TLayoutSection;
begin
sct:=TList.Create;
try
sct.Add(root);
j:=0;
while j<sct.Count do begin
el:=TLayoutSection(sct[j]);
for i:=0 to el.ElemCount-1 do begin
sel:=el.Elements[i];
if sel.ElementType = letSection then
sct.Add(sel)
else begin
hash.Add(sel.Name, sel);
end;
end;
inc(j);
end;
finally
sct.Free;
end;
end;
procedure LayoutEnumElement(aparent: TLayoutSection; list: TList;
LookFor: TLayoutElementTypes);
var
i : integer;
begin
if not Assigned(list) or not Assigned(aparent) or (LookFor = []) then Exit;
for i:=0 to aparent.ElemCount-1 do begin
if aparent.Elements[i].ElementType in LookFor then
list.Add(aparent.Elements[i]);
end;
end;
procedure LayoutGetUnused(cmd: TCmdLineCfg; layout: TLayoutSection; list: TList);
var
i : Integer;
hash : TFPHashObjectList;
opt : TCmdLineCfgOption;
begin
if not Assigned(cmd) or not Assigned(layout) or not Assigned(list) then Exit;
hash := TFPHashObjectList.Create(false);
try
LayoutGetSwitches(layout, hash);
for i:=0 to cmd.Options.Count-1 do begin
opt:=TCmdLineCfgOption(cmd.Options[i]);
if not Assigned(hash.Find(opt.Name)) then begin
list.Add(opt);
end;
end;
finally
hash.Free;
end;
end;
function LayoutFindElement(aparent: TLayoutSection; const Name: string; LookFor: TLayoutElementTypes = [letSection]): TLayoutSection;
var
i : integer;
nm : string;
begin
Result:=nil;
if not Assigned(aparent) or (LookFor = []) then Exit;
nm:=AnsiLowerCase(Name);
for i:=0 to aparent.ElemCount-1 do
if (aparent.Elements[i].fElementType in LookFor) and (AnsiLowerCase(aparent.Elements[i].Name)=nm) then
Result:=aparent.Elements[i];
end;
{ TLayoutSection }
function TLayoutSection.AddElement(const AName: string; AElementType: TLayoutElementType): TLayoutSection;
@ -69,14 +144,20 @@ begin
if ElemCount=0 then SetLength(Elements, 2)
else SetLength(Elements, ElemCount*2);
end;
Result:=TLayoutSection.Create;
Result.fName:=AName;
Result.fElementType:=AElementType;
Result:=TLayoutSection.Create(AName, AElementType);
Result.Display:=Aname;
Elements[ElemCount]:=Result;
inc(ElemCount);
end;
constructor TLayoutSection.Create(const AName: string;
AElementType: TLayoutElementType);
begin
inherited Create;
fName:=AName;
fElementType:=AElementType;
end;
destructor TLayoutSection.Destroy;
var
i : integer;
@ -86,7 +167,7 @@ begin
end;
{ TCmdLineLayoutInfo }
{
function TCmdLineLayoutInfo.DoGetSection(const SectName: String; Forced: Boolean): TLayoutSection;
var
i : integer;
@ -101,18 +182,17 @@ begin
end else
Result:=TLayoutSection(fSections.Objects[i]);
end;
}
constructor TCmdLineLayoutInfo.Create;
begin
fSections:=TStringList.Create;
fSections.OwnsObjects:=true;
AddSection('');
RootElement:=TLayoutSection.Create;
RootElement.fName:='';
RootElement.fElementType:=letSection;
end;
destructor TCmdLineLayoutInfo.Destroy;
begin
fSections.Clear; // need to call clear explicitly, since FREE doesn't free objects (even if owned)
fSections.Free;
RootElement.Free;
inherited Destroy;
end;
@ -121,7 +201,7 @@ end;
begin
GetSection(Section).fswitches.Add(SwitchOrName);
end;}
{
function TCmdLineLayoutInfo.AddSection(const Section: string): TLayoutSection;
begin
Result:=DoGetSection(Section, true);
@ -131,7 +211,7 @@ function TCmdLineLayoutInfo.GetSection(const Section: string): TLayoutSection;
begin
Result:=DoGetSection(Section, false);
end;
}
{function TCmdLineLayoutInfo.GetSections(Dst: TStrings): Boolean;
var
i : Integer;

View File

@ -45,7 +45,7 @@ begin
st:=TSectionIterator.Create;
try
st.lt:=lt;
st.sc:=lt.GetSection('');
st.sc:=lt.RootElement;
core.Iterate( st.Iterate, st)
finally
st.Free;

View File

@ -28,13 +28,15 @@ type
TCmdLineScrollBoxControl = class(TCmdLineUIControl)
private
fScrollBox : TScrollBox;
fCfg : TCmdLineCfg;
fControls : TList;
fOptToCtrl : TFPHashObjectList;
fParent : TWinControl;
fOtherMet : Boolean;
protected
flayout: TCmdLineLayoutInfo;
fusedoptlist: TStringList;
fusedoptlist: TFPHashObjectList;
procedure OnChange(Sender: TObject);
procedure OnCndChange(Sender: TObject);
procedure RevaluateConditions;
@ -45,21 +47,13 @@ type
public
constructor Create(AParent: TWinControl);
destructor Destroy; override;
procedure Init(cfg: TCmdLineCfg; layout: TCmdLineLayoutInfo); override;
procedure Init(cfg: TCmdLineCfg; layout: TCmdLineLayoutInfo; const ASection: string = ''); override;
procedure SetValues(list: TList {of TCmdLineOptionValue}); override;
procedure Serialize(list: TList {of TCmdLineOptionValue}); override;
end;
procedure ReleaseScrollBox(box: TCmdLineScrollBoxControl);
implementation
procedure ReleaseScrollBox(box: TCmdLineScrollBoxControl);
begin
if not Assigned(box) then Exit;
box.fScrollBox.Free;
end;
{ TControlInfo }
constructor TControlInfo.Create(aopt: TCmdLineCfgOption; actrl: TControl);
@ -215,6 +209,7 @@ var
k : Integer;
box : TGroupBox;
by : integer;
opt : TCmdLineCfgOption;
begin
if not Assigned(sct) then begin
Result:=VOffset;
@ -247,10 +242,15 @@ begin
end else
y:=AllocForSection(AParent, y, ls );
end else begin
k:=fusedoptlist.IndexOf(ls.Name);
if (k>=0) then begin
l.Add( fusedoptlist.Objects[k] );
fusedoptlist.Delete(k);
if (AnsiLowerCase(ls.Name)='%%other') and not fOtherMet then begin
LayoutGetUnused( fCfg, flayout.RootElement, l );
fOtherMet := true;
end else begin
k := fusedoptlist.FindIndexOf(ls.Name);
if k>=0 then begin
l.Add( fusedoptlist.Items[k] );
fusedoptlist.Delete(k);
end;
end;
end;
end;
@ -275,10 +275,7 @@ end;
constructor TCmdLineScrollBoxControl.Create(AParent: TWinControl);
begin
inherited Create;
fScrollBox := TScrollBox.Create(AParent);
fScrollBox.Align:=alClient;
fScrollBox.Parent:=AParent;
fScrollBox.VertScrollBar.Tracking:=true;
fParent:=AParent;
fControls:=TList.Create;
fOptToCtrl:=TFPHashObjectList.Create(true);
end;
@ -291,7 +288,7 @@ begin
inherited Destroy;
end;
procedure TCmdLineScrollBoxControl.Init(cfg: TCmdLineCfg; layout: TCmdLineLayoutInfo);
procedure TCmdLineScrollBoxControl.Init(cfg: TCmdLineCfg; layout: TCmdLineLayoutInfo; const ASection: string = '');
var
i : Integer;
opt : TCmdLineCfgOption;
@ -299,6 +296,8 @@ var
l : TList;
nm : string;
y : Integer;
sct : TLayoutSection;
sctnm : string;
begin
if not Assigned(cfg) then Exit;
fCfg:=cfg;
@ -306,26 +305,31 @@ begin
list.CaseSensitive:=true; // must be case sensitive
l:=TList.Create;
fOptToCtrl.Clear;
fusedoptlist:=list;
fusedoptlist:=TFPHashObjectList.Create(false);
flayout:=layout;
try
y:=24;
y:=0;
for i:=0 to cfg.Options.Count-1 do begin
opt:=TCmdLineCfgOption(cfg.Options[i]);
nm:=opt.Name;
if nm='' then nm:=opt.Key;
list.AddObject(nm, cfg.Options[i]);
fusedoptlist.Add(nm, cfg.Options[i]);
end;
if Assigned(layout) then y:=AllocForSection(fScrollBox, y, layout.GetSection(''));
if Assigned(layout) then begin
y:=AllocHeaderLabel(fScrollBox, y, 'Other');
if not Assigned(layout) then begin
for i:=0 to list.Count-1 do l.Add(list.Objects[i]);
AllocControls(fParent, y, l);
end else begin
fOtherMet:=false;
sctnm:=ASection;
sct:=layout.RootElement;
if ASection<>'' then sct:=LayoutFindElement(sct, sctnm);
if Assigned(sct) then
y:=AllocForSection(fParent, y, sct, sctnm<>'');
end;
l.Clear;
for i:=0 to list.Count-1 do
l.Add(list.Objects[i]);
AllocControls(fScrollBox, y, l);
finally
fusedoptlist.Free;
fusedoptlist:=nil;
flayout:=nil;
l.Free;
@ -340,6 +344,7 @@ var
i : Integer;
mlt : TFPHashList;
isPath : Boolean;
ci : TControlInfo;
const
Delims : array [Boolean] of string = (' ', ';');
begin
@ -350,7 +355,9 @@ begin
for i:=0 to list.Count-1 do begin
vl:=TCmdLineOptionValue(list[i]);
if not Assigned(vl.Option) then Continue;
ctrl:=TControlInfo(fOptToCtrl.Find(vl.Option.Name)).ctrl;
ci:=TControlInfo(fOptToCtrl.Find(vl.Option.Name));
if not Assigned(ci) then Continue;
ctrl:=ci.ctrl;
if not Assigned(ctrl) then Continue;
if ctrl is TComboBox then SetValueComboBox(vl.Option, vl.Value, TComboBoX(ctrl))
else if ctrl is TCheckBox then SetValueCheckBox(vl.Option, vl.Value, TCheckBox(ctrl))

View File

@ -17,7 +17,7 @@
<CompilerPath Value="$(CompPath)"/>
</Other>
</CompilerOptions>
<Files Count="13">
<Files Count="12">
<Item1>
<Filename Value="optviewform.pas"/>
<UnitName Value="optviewform"/>
@ -27,50 +27,46 @@
<UnitName Value="cmdlinelclctrlsbox"/>
</Item2>
<Item3>
<Filename Value="..\cmdlinelclpropgrid.pas"/>
<UnitName Value="cmdlinelclpropgrid"/>
</Item3>
<Item4>
<Filename Value="..\cmdlinelclutils.pas"/>
<UnitName Value="cmdlinelclutils"/>
</Item4>
<Item5>
</Item3>
<Item4>
<Filename Value="..\cmdlinecfg.pas"/>
<UnitName Value="cmdlinecfg"/>
</Item5>
<Item6>
</Item4>
<Item5>
<Filename Value="..\cmdlinecfgjson.pas"/>
<UnitName Value="cmdlinecfgjson"/>
</Item6>
<Item7>
</Item5>
<Item6>
<Filename Value="..\cmdlinecfgparser.pas"/>
<UnitName Value="cmdlinecfgparser"/>
</Item7>
<Item8>
</Item6>
<Item7>
<Filename Value="..\cmdlinecfgui.pas"/>
<UnitName Value="cmdlinecfgui"/>
</Item8>
<Item9>
</Item7>
<Item8>
<Filename Value="..\cmdlinecfguijson.pas"/>
<UnitName Value="cmdlinecfguijson"/>
</Item9>
<Item10>
</Item8>
<Item9>
<Filename Value="..\cmdlinecfgutils.pas"/>
<UnitName Value="cmdlinecfgutils"/>
</Item10>
<Item11>
</Item9>
<Item10>
<Filename Value="..\cmdlinefpccond.pas"/>
<UnitName Value="cmdlinefpccond"/>
</Item11>
<Item12>
</Item10>
<Item11>
<Filename Value="cfgcompoptreg.pas"/>
<HasRegisterProc Value="True"/>
<UnitName Value="cfgcompoptreg"/>
</Item12>
<Item13>
</Item11>
<Item12>
<Filename Value="optviewform.lfm"/>
<Type Value="LFM"/>
</Item13>
</Item12>
</Files>
<Type Value="DesignTime"/>
<RequiredPkgs Count="3">

View File

@ -7,10 +7,9 @@ unit cfgcompopt;
interface
uses
optviewform, cmdlinelclctrlsbox, cmdlinelclpropgrid, cmdlinelclutils,
cmdlinecfg, cmdlinecfgjson, cmdlinecfgparser, cmdlinecfgui,
cmdlinecfguijson, cmdlinecfgutils, cmdlinefpccond, cfgcompoptreg,
LazarusPackageIntf;
optviewform, cmdlinelclctrlsbox, cmdlinelclutils, cmdlinecfg,
cmdlinecfgjson, cmdlinecfgparser, cmdlinecfgui, cmdlinecfguijson,
cmdlinecfgutils, cmdlinefpccond, cfgcompoptreg, LazarusPackageIntf;
implementation

View File

@ -1,46 +1,73 @@
object OptView: TOptView
Left = 359
Left = 571
Height = 240
Top = 214
Top = 171
Width = 320
Caption = 'OptView'
ClientHeight = 240
ClientWidth = 320
OnDestroy = FormDestroy
OnShow = FormShow
LCLVersion = '1.1'
LCLVersion = '1.3'
object Panel1: TPanel
Left = 0
Height = 190
Height = 200
Top = 0
Width = 320
Align = alClient
Caption = 'Panel1'
ClientHeight = 200
ClientWidth = 320
TabOrder = 0
object ListBox1: TListBox
Left = 1
Height = 198
Top = 1
Width = 130
Align = alLeft
ItemHeight = 0
OnClick = ListBox1Click
OnSelectionChange = ListBox1SelectionChange
TabOrder = 0
end
object Splitter1: TSplitter
Left = 131
Height = 198
Top = 1
Width = 5
end
object Panel3: TPanel
Left = 136
Height = 198
Top = 1
Width = 183
Align = alClient
BevelOuter = bvNone
TabOrder = 2
end
end
object Panel2: TPanel
Left = 0
Height = 50
Top = 190
Height = 40
Top = 200
Width = 320
Align = alBottom
Caption = 'Panel2'
ClientHeight = 50
ClientHeight = 40
ClientWidth = 320
TabOrder = 1
OnResize = Panel2Resize
object btnOk: TButton
Left = 33
Left = 72
Height = 25
Top = 15
Top = 8
Width = 75
Caption = 'Ok'
ModalResult = 1
TabOrder = 0
end
object btnCancel: TButton
Left = 115
Left = 152
Height = 25
Top = 15
Top = 8
Width = 75
Caption = 'Cancel'
ModalResult = 2

View File

@ -7,26 +7,40 @@ interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
LCLIntf,
StdCtrls, LazIDEIntf, IDEOptionsIntf, ProjectIntf, CompOptsIntf, cmdlinecfg,
cmdlinecfgjson, cmdlinecfgui, cmdlinecfguijson, cmdlinelclctrlsbox, cmdlinelazcompopt;
StdCtrls, LazIDEIntf, IDEOptionsIntf, ProjectIntf, CompOptsIntf, cmdlinecfg
//, cmdlinecfgjson
, cmdlinecfgui
//, cmdlinecfguijson
, cmdlinelclctrlsbox, cmdlinelazcompopt;
type
TOptionsBox = record
box : TScrollBox;
cmd : TCmdLineScrollBoxControl;
end;
{ TOptView }
TOptView = class(TForm)
btnOk: TButton;
btnCancel: TButton;
ListBox1: TListBox;
Panel1: TPanel;
Panel2: TPanel;
Panel3: TPanel;
Splitter1: TSplitter;
procedure FormDestroy(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
procedure ListBox1SelectionChange(Sender: TObject; User: boolean);
procedure Panel2Resize(Sender: TObject);
private
{ private declarations }
cmd : TCmdLineScrollBoxControl;
sections : array of TOptionsBox;
cfg : TCmdLineCfg;
layout : TCmdLineLayoutInfo;
procedure InitOpts(acfg: TCmdLineCfg; alayout: TCmdLineLayoutInfo);
procedure ClearSections(clearboxes: Boolean = true);
public
{ public declarations }
function ShowForOpts(opt: TLazCompilerOptions): Integer;
@ -46,20 +60,19 @@ implementation
function ReviewOpts(acfg: TCmdLineCfg; alayout: TCmdLineLayoutInfo; opt: TLazCompilerOptions = nil): Integer;
begin
if not Assigned(OptView) then OptView:=TOptView.Create(Application);
OptView.Caption:='Review Compiler Options';
if (OptView.cfg<>acfg) or (OptView.layout<>alayout) then
OptView.InitOpts(acfg, alayout);
if not Assigned(opt) and Assigned(LazarusIDE.ActiveProject) then
opt:=LazarusIDE.ActiveProject.LazCompilerOptions;
if Assigned(OptView.cmd) and Assigned(opt) then
Result:=OptView.ShowForOpts(opt)
else
Result:=mrCancel;
if Assigned(opt) then Result:=OptView.ShowForOpts(opt)
else Result:=mrCancel;
end;
procedure TOptView.FormDestroy(Sender: TObject);
begin
cmd.Free;
ClearSections(false);
end;
procedure TOptView.FormShow(Sender: TObject);
@ -67,14 +80,74 @@ begin
end;
procedure TOptView.InitOpts(acfg: TCmdLineCfg; alayout: TCmdLineLayoutInfo);
procedure TOptView.ListBox1Click(Sender: TObject);
begin
ReleaseScrollBox(cmd);
cmd.Free;
end;
procedure TOptView.ListBox1SelectionChange(Sender: TObject; User: boolean);
var
i : Integer;
idx: integer;
begin
idx:=ListBox1.ItemIndex;
if (idx>=0) and (idx<length(sections)) then begin
sections[idx].box.BringToFront;
sections[idx].box.Show;
for i:=0 to length(sections)-1 do
if i<>idx then sections[i].box.Hide;
end;
end;
procedure TOptView.Panel2Resize(Sender: TObject);
var
w: integer;
begin
w:=Self.Width div 2;
btnOk.Left:=w - btnOk.Width - 2;
btnCancel.Left:=w+2;
end;
procedure TOptView.InitOpts(acfg: TCmdLineCfg; alayout: TCmdLineLayoutInfo);
var
lt : TList;
i : Integer;
ls : TLayoutSection;
begin
ClearSections;
cfg:=acfg;
layout:=alayout;
cmd:=TCmdLineScrollBoxControl.Create(Panel1);
cmd.Init(cfg, layout);
//cmd:=
lt:=TList.Create;
try
LayoutEnumElement( layout.RootElement, lt);
SetLength(sections, lt.Count);
for i:=0 to lt.Count-1 do begin
ls:=TLayoutSection(lt[i]);
ListBox1.AddItem( ls.Display, ls);
sections[i].box:=TScrollBox.Create(Panel3);
sections[i].box.Visible:=false;
sections[i].box.Parent:=Panel3;
sections[i].box.Align:=alClient;
sections[i].cmd:=TCmdLineScrollBoxControl.Create(sections[i].box);
sections[i].cmd.Init(cfg, layout, ls.Name);
end;
finally
lt.Free;
end;
end;
procedure TOptView.ClearSections(clearboxes: Boolean);
var
i : integer;
begin
for i:=0 to length(sections)-1 do begin
sections[i].cmd.Free;
if clearboxes then sections[i].box.Free;
end;
SetLength(sections,0);
end;
function TOptView.ShowForOpts(opt: TLazCompilerOptions): Integer;
@ -85,13 +158,14 @@ begin
list := TList.Create;
try
LazCompOptToVals(opt, cfg, list);
cmd.SetValues(list);
for i:=0 to length(sections)-1 do sections[i].cmd.SetValues(list);
for i:=0 to list.Count-1 do TObject(list[i]).Free;
Result:=ShowModal;
if Result=mrOK then begin
list.Clear;
cmd.Serialize(list);
for i:=0 to length(sections)-1 do
sections[i].cmd.Serialize(list);
ValsToLazCompOpt(list, opt);
for i:=0 to list.Count-1 do TObject(list[i]).Free;
end;

View File

@ -1,5 +1,32 @@
Command Line Configuration
== Source files ==
cmdlinecfg.pas - the core unit defining the primary class for configuration
cmdlinecfgutils.pas - utility functions
cmdlinecfgparser.pas - the unit for parsing input strings into command lines
and mapping them to classes of cmdlinecfg.
cmdlinecfgjson.pas - the json format reader of command-line configurations
=== User Interface ===
cmdlinecfgui.pas - core unit for UI controller of command-line options
cmdlinecfguijson.pas - json read of UI controller info.
cmdlinelclctrlsbox.pas - LCL-based consols list UI controller
cmdlinelclpropgrid.pas - LCL-based propery grid UI controller
cmdlinelclutils.pas - the function contains a number of utility functions
for allocating LCL controls based on the information about command-line option
=== Lazarus specific ===
cmdlinelazcompopt.pas - Lazarus IDE specific file, that converts a set of cmdlinecfg classes
to Lazarus project
=== Condition checks ===
cmdlinefpccond.pas - the utility function for verification of FPC specific conditions (cpu/os)
(doesn't depend on cmdlinecfg.pas)
see "FPC Condition" below
== JSON Storage ==
@ -80,6 +107,8 @@ Example of JSON Storage:
]
}
== FPC Condition ==
Free Pascal Compiler condition define for what target (CPU, CPU-OS) the option or value of an option
@ -98,4 +127,56 @@ If an option is available for multple platforms, each condition has to be comma
i386,x86_64,arm-linux
== UI controller ==
UI controller is an abstraction layer, that does the representation of the command-line utils to an user.
The core class is:
TCmdLineUIControl
method
procedure Init(cfg: TCmdLineCfg; layout: TCmdLineLayoutInfo; ASection: string);
- method accepts the description of the command-line options
and optional layout information;
method must initialize (create) all necessary UI controls;
the place to initialize controls must be defined in the method constructor
* if layout information is passed, the controller should use it to represent the user interface
* if Asection is not an empty string and layout is passed, controller should
initialize controls for this section only.
Futher operations for "SetValue" and "Serialize" should be limited
to the command-line options, contained in the layout of the passed section.
if layout information is not passed, section should be ignored
* Since it's possible that a new command-line option is introduced
prior to update of the user interface information,
a layout information can specify switch "%%other" (name is case-insesitive)
where all switches should go, that don't have a specific location within the layout information.
if "%%other" switch is not introduced by the layout, these command-line options that are not part of the layout
must not be shown.
if multiple "%%other" switches are declared, the first met should be used
procedure SetValues(list: TList);
- method should initialized UI controls to the values passed in the list
the list will contain objects TCmdLineOptionValue class.
the methods must not retain or free any of the objects
procedure Serialize(list: TList);
- method should gather the values from the user interface
method should not check the existense of TCmdLineOptionValue in the passed list
instead it must only ADD serialized TCmdLineOptionValue values
events
OnValueChanged: TNotifyEvent - the event should be triggered every time a value is changed by a user;
the even must not be triggered during handling of SetValues method
The supplemental classes:
TCmdLineLayoutInfo - the class contains a description of how to represent command-line utils.
any implementation of TCmdLineUIControl must be able to work without
any TCmdLineLayoutInfo provided.
TLayoutSection - the description of a certain section of "command-line configurations".
typically command-line options are grouped into sections
=== GUI Hints ===
hideempty - if the there're no command-line options to be displayed, the section should be hidden

View File

@ -44,4 +44,7 @@
"display": "Verbosity",
"switches": ["-ve","-vw", "-vn","-vh","-vi","-vp","-vc","-vx","-v0","-vd","-vu","-vt","-vl","-vb","-va","-l","-Se"]
}
,"other": {
"display": "Other", "switches": ["%%other"]
}
}

View File

@ -1,19 +1,19 @@
object Form1: TForm1
Left = 411
Height = 319
Height = 339
Top = 197
Width = 425
Width = 441
Caption = 'Form1'
ClientHeight = 319
ClientWidth = 425
ClientHeight = 339
ClientWidth = 441
OnCreate = FormCreate
OnDestroy = FormDestroy
LCLVersion = '1.1'
LCLVersion = '1.3'
object Memo1: TMemo
Left = 0
Height = 90
Top = 179
Width = 425
Top = 199
Width = 441
Align = alBottom
Lines.Strings = (
'Memo1'
@ -24,36 +24,20 @@ object Form1: TForm1
Cursor = crVSplit
Left = 0
Height = 5
Top = 174
Width = 425
Top = 194
Width = 441
Align = alBottom
ResizeAnchor = akBottom
end
object Label1: TLabel
Left = 47
Height = 13
Top = 44
Width = 31
Caption = 'Label1'
ParentColor = False
end
object Edit1: TEdit
Left = 105
Height = 21
Top = 46
Width = 191
TabOrder = 2
Text = 'Edit1'
end
object Panel1: TPanel
Left = 0
Height = 50
Top = 269
Width = 425
Top = 289
Width = 441
Align = alBottom
ClientHeight = 50
ClientWidth = 425
TabOrder = 3
ClientWidth = 441
TabOrder = 2
object toOpt: TButton
Left = 8
Height = 25
@ -64,4 +48,15 @@ object Form1: TForm1
TabOrder = 0
end
end
object ScrollBox1: TScrollBox
Left = 0
Height = 196
Top = 0
Width = 440
HorzScrollBar.Page = 436
VertScrollBar.Page = 192
VertScrollBar.Tracking = True
Anchors = [akTop, akLeft, akRight, akBottom]
TabOrder = 3
end
end

View File

@ -5,8 +5,8 @@ unit mainform;
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ValEdit,
StdCtrls, ExtCtrls
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs
,StdCtrls, ExtCtrls
,cmdlinecfg , cmdlinelclctrlsbox, cmdlinecfgjson //, patheditor
,cmdlinecfgui, cmdlinecfguijson
,cmdlinecfgparser;
@ -16,9 +16,8 @@ type
{ TForm1 }
TForm1 = class(TForm)
ScrollBox1: TScrollBox;
toOpt: TButton;
Edit1: TEdit;
Label1: TLabel;
Memo1: TMemo;
Panel1: TPanel;
Splitter1: TSplitter;
@ -30,6 +29,7 @@ type
ctrl : TCmdLineScrollBoxControl;
cfg : TCmdLineCfg;
lt : TCmdLineLayoutInfo;
sct : string; // desired section
public
{ public declarations }
procedure OnValueChanged(Sender: TObject);
@ -47,17 +47,36 @@ implementation
procedure TForm1.FormCreate(Sender: TObject);
begin
{cmdlinelclutils.ADirsDialogs:=DummyEditPaths;
cmdlinelclutils.AFilesDialogs:=DummyEditPaths;}
cmdlinelclutils.AFilesDialogs:=DummyEditPaths;
}
ctrl:=TCmdLineScrollBoxControl.Create(Self);
{fScrollBox := TScrollBox.Create(AParent);
fScrollBox.Align:=alClient;
fScrollBox.Parent:=AParent;
fScrollBox.VertScrollBar.Tracking:=true;}
Memo1.Clear;
if ParamCount=0 then begin
Memo1.Lines.Add('Please pass the following information through the command-line: ');
Memo1.Lines.Add(' 1. json file for command-lines');
Memo1.Lines.Add(' (optional) 2. layout information json file ');
Memo1.Lines.Add(' (optional) 3. name of the section that you would need to render');
end;
ctrl:=TCmdLineScrollBoxControl.Create(ScrollBox1);
if ParamCount>0 then begin
cfg:=TCmdLineCfg.Create;
CmdLineCfgJSONReadFile(ParamStr(1), cfg);
if ParamCOunt>1 then begin
lt:=TCmdLineLayoutInfo.Create;
CmdLineUIJSONReadFile(PAramStr(2), lt);
CmdLineUIJSONReadFile(ParamStr(2), lt);
end;
ctrl.Init(cfg, lt);
if ParamCount>2 then
sct:=ParamStr(3);
Self.Caption:=Paramstr(1);
if sct<>'' then Self.Caption:=Self.Caption+'.'+sct;
ctrl.Init(cfg, lt, sct);
ctrl.OnValueChanged:=OnValueChanged;
end;
end;

View File

@ -0,0 +1,21 @@
{
"executable":"sample",
"version":"1.0",
"testkey":"-iV",
"testValue":"1.0",
"options": [
{"key":"-a", "display":"This is option A" }
,{"key":"-b", "display":"This option controls B"}
,{"key":"-c", "display":"C is controlled by this checkbox" }
,{ "key":"-d%value%", "display":"This is drop down values - one of many"
,"options": [
{"value": "1", "display":"One"}
,{"value": "2", "display":"Two"}
,{"value": "3", "display":"Three"}
,{"value": "4", "display":"Four"}
,{"value": "5", "display":"Five"}
]
}
,{"key":"-z", "display":"Z is the last control not in sample.ui" }
]
}

View File

@ -0,0 +1,10 @@
{
"primary": {
"display": "Primary Part",
"switches": ["-a","-d"]
}
,"secondary": {
"display": "Secondary Part",
"switches": ["-b","-c"]
}
}

View File

@ -0,0 +1,15 @@
{
"primary": {
"display": "Primary Part",
"switches": ["-a","-d"]
}
,"secondary": {
"display": "Secondary Part",
"switches": ["-b","-c"]
}
,"other": {
"display": "Other",
"hint": "hideempty",
"switches": ["%%other"]
}
}

View File

@ -9,7 +9,6 @@
<Title Value="project1"/>
<ResourceType Value="res"/>
<UseXPManifest Value="True"/>
<Icon Value="0"/>
</General>
<i18n>
<EnableI18N LFM="False"/>