lazarus/ide/allcompileroptions.pas
2013-07-27 17:26:49 +00:00

338 lines
11 KiB
ObjectPascal

unit AllCompilerOptions;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
contnrs, Buttons, ButtonPanel, EditBtn,
FileProcs, EnvironmentOpts, Compiler, LazarusIDEStrConsts;
type
{ TfrmAllCompilerOptions }
TfrmAllCompilerOptions = class(TForm)
btnResetOptionsFilter: TSpeedButton;
ButtonPanel1: TButtonPanel;
cbShowModified: TCheckBox;
cbUseComments: TCheckBox;
edOptionsFilter: TEdit;
sbAllOptions: TScrollBox;
procedure btnResetOptionsFilterClick(Sender: TObject);
procedure cbShowModifiedClick(Sender: TObject);
procedure edOptionsFilterChange(Sender: TObject);
procedure FormShow(Sender: TObject);
private
FCustomOptions: TStrings;
FIdleConnected: Boolean;
FOptionsReader: TCompilerOptReader;
FGeneratedControls: TComponentList;
FEffectiveFilter: string;
FEffectiveShowModified: Boolean;
FInitialRender: Boolean;
procedure SetIdleConnected(AValue: Boolean);
procedure OnIdle(Sender: TObject; var Done: Boolean);
procedure CheckBoxClick(Sender: TObject);
procedure EditChange(Sender: TObject);
procedure ComboChange(Sender: TObject);
procedure RenderAndFilterOptions;
private
property IdleConnected: Boolean read FIdleConnected write SetIdleConnected;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
function ToCustomOptions(aStrings: TStrings): TModalResult;
public
property CustomOptions: TStrings read FCustomOptions write FCustomOptions;
property OptionsReader: TCompilerOptReader read FOptionsReader;
end;
var
frmAllCompilerOptions: TfrmAllCompilerOptions;
implementation
{$R *.lfm}
{ TfrmAllCompilerOptions }
constructor TfrmAllCompilerOptions.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
FOptionsReader := TCompilerOptReader.Create;
FGeneratedControls := TComponentList.Create;
end;
destructor TfrmAllCompilerOptions.Destroy;
begin
FGeneratedControls.Clear;
FreeAndNil(FGeneratedControls);
FreeAndNil(FOptionsReader);
inherited Destroy;
end;
function TfrmAllCompilerOptions.ToCustomOptions(aStrings: TStrings): TModalResult;
begin
Result := OptionsReader.ToCustomOptions(aStrings, cbUseComments.Checked);
end;
procedure TfrmAllCompilerOptions.FormShow(Sender: TObject);
begin
Caption:=lisAllOptions;
edOptionsFilter.Enabled := False; // Until the options are read.
edOptionsFilter.Hint := 'Filter the available options list';
btnResetOptionsFilter.LoadGlyphFromLazarusResource(ResBtnListFilter);
btnResetOptionsFilter.Enabled := False;
btnResetOptionsFilter.Hint := 'Clear the filter for options';
FEffectiveFilter:=#1; // Set an impossible value first, makes sure options are filtered.
FInitialRender := True;
IdleConnected := True;
end;
procedure TfrmAllCompilerOptions.edOptionsFilterChange(Sender: TObject);
begin
btnResetOptionsFilter.Enabled := edOptionsFilter.Text<>'';
// Filter the list of options in OnIdle handler
IdleConnected := True;
end;
procedure TfrmAllCompilerOptions.btnResetOptionsFilterClick(Sender: TObject);
begin
edOptionsFilter.Text := '';
btnResetOptionsFilter.Enabled := False;
end;
procedure TfrmAllCompilerOptions.cbShowModifiedClick(Sender: TObject);
begin
IdleConnected := True;
end;
procedure TfrmAllCompilerOptions.SetIdleConnected(AValue: Boolean);
begin
if FIdleConnected = AValue then exit;
FIdleConnected := AValue;
if FIdleConnected then
Application.AddOnIdleHandler(@OnIdle)
else
Application.RemoveOnIdleHandler(@OnIdle);
end;
procedure TfrmAllCompilerOptions.OnIdle(Sender: TObject; var Done: Boolean);
begin
IdleConnected := False;
Screen.Cursor := crHourGlass;
try
edOptionsFilter.Enabled := False;
with FOptionsReader do
if RootOptGroup.CompilerOpts.Count = 0 then
begin
CompilerExecutable := EnvironmentOptions.CompilerFilename;
if ReadAndParseOptions <> mrOK then
ShowMessage(ErrorMsg);
FromCustomOptions(FCustomOptions);
end;
RenderAndFilterOptions;
edOptionsFilter.Enabled := True;
finally
Screen.Cursor := crDefault;
end;
end;
procedure TfrmAllCompilerOptions.CheckBoxClick(Sender: TObject);
var
cb: TCheckBox;
Opt: TCompilerOpt;
begin
cb := Sender as TCheckBox;
Opt := FOptionsReader.FindOptionById(cb.Tag);
if Assigned(Opt) then
begin
if cb.Checked then
Opt.Value := 'True'
else
Opt.Value := '';
end;
end;
procedure TfrmAllCompilerOptions.EditChange(Sender: TObject);
var
ed: TEdit;
Opt: TCompilerOpt;
begin
ed := Sender as TEdit;
Opt := FOptionsReader.FindOptionById(ed.Tag);
if Assigned(Opt) then
Opt.Value := ed.Text;
end;
procedure TfrmAllCompilerOptions.ComboChange(Sender: TObject);
var
cb: TComboBox;
Opt: TCompilerOpt;
begin
cb := Sender as TComboBox;
Opt := FOptionsReader.FindOptionById(cb.Tag);
if Assigned(Opt) then
Opt.Value := cb.Text;
end;
procedure TfrmAllCompilerOptions.RenderAndFilterOptions;
const
LeftEdit = 120;
LeftDescrEdit = 230;
LeftDescrBoolean = 150;
var
Opt: TCompilerOpt;
yLoc: Integer;
Container: TCustomControl;
function MakeOptionCntrl(aCntrlClass: TControlClass; aCaption: string;
aTopOffs: integer=0): TControl;
begin
Result := aCntrlClass.Create(Nil);
Result.Parent := Container;
Result.Top := yLoc+aTopOffs;
Result.Left := Opt.Indentation*4;
Result.Caption := aCaption;
Result.Tag := Opt.Id;
FGeneratedControls.Add(Result);
end;
function MakeEditCntrl(aLbl: TControl; aCntrlClass: TControlClass): TControl;
// TEdit or TComboBox
begin
Result := aCntrlClass.Create(Nil);
Result.Parent := Container;
Result.AnchorSide[akTop].Control := aLbl;
Result.AnchorSide[akTop].Side := asrCenter;
Result.Left := LeftEdit; // Now use Left instead of anchors
Result.Anchors := [akLeft,akTop];
Result.Tag := Opt.Id;
FGeneratedControls.Add(Result);
end;
procedure MakeDescrLabel(aCntrl: TControl; aLeft: integer);
// Description label after CheckBox / Edit control
var
Lbl: TControl;
begin
Lbl := TLabel.Create(Nil);
Lbl.Parent := Container;
Lbl.Caption := Opt.Description;
Lbl.AnchorSide[akTop].Control := aCntrl;
Lbl.AnchorSide[akTop].Side := asrCenter;
Lbl.Left := aLeft; // Now use Left instead of anchors
Lbl.Anchors := [akLeft,akTop];
FGeneratedControls.Add(Lbl);
end;
procedure AddChoices(aComboBox: TComboBox; aCategory: string);
// Add selection choices to ComboBox from data originating from "fpc -i".
var
i: Integer;
begin
with FOptionsReader.SupportedCategories do
if Find(aCategory, i) then
aComboBox.Items.Assign(Objects[i] as TStrings)
else
raise Exception.CreateFmt('AddChoices: Selection list for "%s" is not found.',
[aCategory]);
end;
procedure RenderOneLevel(aParentGroup: TCompilerOptGroup);
var
Cntrl, Lbl: TControl;
cb: TComboBox;
i, NewLeft: Integer;
begin
for i := 0 to aParentGroup.CompilerOpts.Count-1 do begin
Opt := TCompilerOpt(aParentGroup.CompilerOpts[i]);
if Opt.Ignored or not Opt.Visible then Continue; // Maybe filtered out
case Opt.EditKind of
oeGroup, oeSet: begin // Label for group or set
Cntrl := MakeOptionCntrl(TLabel, Opt.Option+Opt.Suffix+#9#9+Opt.Description);
end;
oeBoolean: begin // CheckBox
Cntrl := MakeOptionCntrl(TCheckBox, Opt.Option);
Assert((Opt.Value='') or (Opt.Value='True'), 'Wrong value in Boolean option '+Opt.Option);
TCheckBox(Cntrl).Checked := Opt.Value<>'';
if Length(Opt.Option) > 10 then
NewLeft := LeftDescrBoolean + (Length(Opt.Option)-10)*8
else
NewLeft := LeftDescrBoolean;
Cntrl.OnClick := @CheckBoxClick;
MakeDescrLabel(Cntrl, NewLeft);
end;
oeSetElem: begin // Sub-item for set, CheckBox
Cntrl := MakeOptionCntrl(TCheckBox, Opt.Option+Opt.Description);
Assert((Opt.Value='') or (Opt.Value='True'), 'Wrong value in Boolean option '+Opt.Option);
TCheckBox(Cntrl).Checked := Opt.Value<>'';
Cntrl.OnClick := @CheckBoxClick;
end;
oeNumber, oeText, oeSetNumber: begin // Edit
Lbl := MakeOptionCntrl(TLabel, Opt.Option+Opt.Suffix, 3);
Cntrl := MakeEditCntrl(Lbl, TEdit);
TEdit(Cntrl).Text := Opt.Value;
TEdit(Cntrl).OnChange := @EditChange;
MakeDescrLabel(Cntrl, LeftDescrEdit);
end;
oeList: begin // ComboBox
Lbl := MakeOptionCntrl(TLabel, Opt.Option+Opt.Suffix, 3);
Cntrl := MakeEditCntrl(Lbl, TComboBox);
cb := TComboBox(Cntrl);
cb.Style := csDropDownList;
// ToDo: Move this logic to parser data so values can be validated better.
case Opt.Option of
'-Ca': AddChoices(cb, 'ABI targets:');
'-Cf': AddChoices(cb, 'FPU instruction sets:');
'-Cp': AddChoices(cb, 'CPU instruction sets:');
'-Oo[NO]': AddChoices(cb, 'Optimizations:');
'-Op': AddChoices(cb, 'CPU instruction sets:');
'-OW': AddChoices(cb, 'Whole Program Optimizations:');
'-Ow': AddChoices(cb, 'Whole Program Optimizations:');
else
raise Exception.Create('AddChoices: Unknown option ' + Opt.Option);
end;
cb.Text := Opt.Value;
cb.OnChange := @ComboChange;
MakeDescrLabel(Cntrl, LeftDescrEdit);
end
else
raise Exception.Create('TCompilerOptsRenderer.Render: Unknown EditKind.');
end;
Inc(yLoc, Cntrl.Height+2);
if Opt is TCompilerOptGroup then
RenderOneLevel(TCompilerOptGroup(Opt)); // Show other levels recursively
end;
end;
begin
if (FEffectiveFilter = edOptionsFilter.Text)
and (FEffectiveShowModified = cbShowModified.Checked) then Exit;
Container := sbAllOptions;
Container.DisableAutoSizing;
try
// First filter and set Visible flag.
FOptionsReader.FilterOptions(edOptionsFilter.Text, cbShowModified.Checked);
// Then create and place new controls in GUI
FGeneratedControls.Clear;
yLoc := 0;
RenderOneLevel(FOptionsReader.RootOptGroup);
FEffectiveFilter := edOptionsFilter.Text;
FEffectiveShowModified := cbShowModified.Checked;
{$IFDEF AllOptsFocusFilter}
if not FInitialRender then
FocusControl(edOptionsFilter);
{$ENDIF}
FInitialRender := False;
finally
Container.EnableAutoSizing;
Container.Invalidate;
end;
end;
end.