{ *************************************************************************** * * * 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 . You can also * * obtain it by writing to the Free Software Foundation, * * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * *************************************************************************** Abstract: The frame for 'IDE macro values' on the compiler options. Allows to add/delete/edit values for existing macros. It does not allow to define new IDE macros, only values. } unit IdeMacroValues; {$mode objfpc}{$H+} interface uses Math, Classes, SysUtils, LCLProc, Controls, FileUtil, Forms, Grids, Graphics, Menus, ComCtrls, Dialogs, AvgLvlTree, DefineTemplates, StdCtrls, GraphMath, ExtCtrls, Buttons, ProjectIntf, IDEImagesIntf, IDEOptionsIntf, CompOptsIntf, PackageDefs, compiler_inherited_options, TransferMacros, PathEditorDlg, Project, PackageSystem, LazarusIDEStrConsts, CompilerOptions, IDEProcs; type { TIdeMacroValuesFrame } TIdeMacroValuesFrame = class(TAbstractIDEOptionsEditor) IdeMacroValuesGroupBox: TGroupBox; IdeMacroValuesStringGrid: TStringGrid; MenuItem1: TMenuItem; procedure IdeMacroValuesStringGridEditingDone(Sender: TObject); procedure IdeMacroValuesStringGridSelectEditor(Sender: TObject; aCol, aRow: Integer; var Editor: TWinControl); procedure IdeMacroValuesStringGridSelection(Sender: TObject; aCol, aRow: Integer); private FLoadShowSessionFromProject: boolean; // FMacroValues: TProjectBuildMacros; FProject: TProject; FShowSession: boolean; FSwitchingMode: boolean; procedure UpdateMacrosControls; function GetAllIdeMacros: TStrings; procedure CleanMacrosGrid; procedure SaveMacros(UpdateControls: boolean); procedure UpdateInheritedOptions; procedure UpdateShowSession; procedure UpdateDialogCaption; function GetDialogCaption: string; public constructor Create(TheOwner: TComponent); override; destructor Destroy; override; function GetTitle: String; override; procedure Setup(ADialog: TAbstractOptionsEditorDialog); override; procedure ReadSettings(AOptions: TAbstractIDEOptions); override; procedure WriteSettings(AOptions: TAbstractIDEOptions); override; class function SupportedOptionsClass: TAbstractIDEOptionsClass; override; property AProject: TProject read FProject; // property MacroValues: TProjectBuildMacros read FMacroValues; property SwitchingMode: boolean read FSwitchingMode; // the active mode is currently switched property ShowSession: boolean read FShowSession write FShowSession; property LoadShowSessionFromProjects: boolean read FLoadShowSessionFromProject write FLoadShowSessionFromProject; end; implementation {$R *.lfm} { TIdeMacroValuesFrame } procedure TIdeMacroValuesFrame.IdeMacroValuesStringGridSelectEditor( Sender: TObject; aCol, aRow: Integer; var Editor: TWinControl); var PickList: TPickListCellEditor; sl: TStringList; Macros: TStrings; Grid: TStringGrid; MacroName: string; i: LongInt; Macro: TLazBuildMacro; begin // if MacroValues=nil then exit; Grid:=IdeMacroValuesStringGrid; if aCol=0 then begin // list all build MacroValues if not (Editor is TPickListCellEditor) then exit; PickList:=TPickListCellEditor(Editor); sl:=TStringList.Create; Macros:=nil; try if aRow=Grid.RowCount-1 then sl.Add('(none)') else sl.Add('(delete)'); Macros:=GetAllIdeMacros; sl.AddStrings(Macros); PickList.Items.Assign(sl); finally Macros.Free; sl.Free; end; end else if aCol=1 then begin // list all possible values of current macro if not (Editor is TPickListCellEditor) then exit; PickList:=TPickListCellEditor(Editor); MacroName:=Grid.Cells[0,aRow]; sl:=TStringList.Create; try Macros:=GetAllIdeMacros; i:=Macros.IndexOf(MacroName); if i>=0 then begin Macro:=TLazBuildMacro(Macros.Objects[i]); sl.AddStrings(Macro.Values); end else begin sl.Add(''); end; PickList.Items.Assign(sl); finally Macros.Free; sl.Free; end; end; end; procedure TIdeMacroValuesFrame.IdeMacroValuesStringGridEditingDone(Sender: TObject); begin SaveMacros(true); end; procedure TIdeMacroValuesFrame.IdeMacroValuesStringGridSelection( Sender: TObject; aCol, aRow: Integer); begin CleanMacrosGrid; end; procedure TIdeMacroValuesFrame.UpdateMacrosControls; var Grid: TStringGrid; i: Integer; begin Grid:=IdeMacroValuesStringGrid; Grid.RowCount:=Project1.MacroValues.Count+2; // + titles + add button for i:=0 to Project1.MacroValues.Count-1 do begin Grid.Cells[0,i+1]:=Project1.MacroValues.Names[i]; Grid.Cells[1,i+1]:=Project1.MacroValues.ValueFromIndex(i); end; i:=Project1.MacroValues.Count+1; Grid.Cells[0,i]:='(none)'; Grid.Cells[1,i]:=''; end; procedure TIdeMacroValuesFrame.UpdateDialogCaption; var Form: TCustomForm; begin Form:=GetParentForm(Self); if Form<>nil then Form.Caption:=GetDialogCaption; end; function TIdeMacroValuesFrame.GetDialogCaption: string; begin if AProject<>nil then begin Result := aProject.GetTitleOrName; Result:=Format(dlgProjectOptionsFor, [Result]); if AProject.BuildModes.Count>1 then Result:=Result+', '+copy(AProject.ActiveBuildMode.GetCaption,1,12); end else Result:='TIdeMacroValuesFrame.GetDialogCaption: no project'; end; function TIdeMacroValuesFrame.GetAllIdeMacros: TStrings; procedure Add(aBuildMacro: TLazBuildMacro); begin if GetAllIdeMacros.IndexOf(aBuildMacro.Identifier)>=0 then exit; GetAllIdeMacros.AddObject(aBuildMacro.Identifier,aBuildMacro); end; procedure Add(CompOpts: TLazCompilerOptions); var i: Integer; begin for i:=0 to CompOpts.BuildMacros.Count-1 do Add(CompOpts.BuildMacros[i]); end; var PkgList: TFPList; APackage: TLazPackage; i: Integer; begin Result:=TStringList.Create; if AProject=nil then exit; Add(AProject.CompilerOptions); PkgList:=nil; try PackageGraph.GetAllRequiredPackages(nil,AProject.FirstRequiredDependency,PkgList); if PkgList<>nil then begin for i:=0 to PkgList.Count-1 do begin if TObject(PkgList[i]) is TLazPackage then begin APackage:=TLazPackage(PkgList[i]); Add(APackage.CompilerOptions); end; end; end; finally PkgList.Free; end; TStringList(Result).Sort; end; procedure TIdeMacroValuesFrame.CleanMacrosGrid; var Grid: TStringGrid; aRow: Integer; MacroName: string; NeedNewRow: Boolean; begin Grid:=IdeMacroValuesStringGrid; // delete rows for aRow:=Grid.RowCount-2 downto 1 do begin if aRow=Grid.Row then continue; // row is selected MacroName:=Grid.Cells[0,aRow]; if (MacroName<>'') and IsValidIdent(MacroName) then continue; // valid macro name // delete row Grid.DeleteColRow(false,aRow); end; NeedNewRow:=Grid.RowCount<2; if (not NeedNewRow) then begin MacroName:=Grid.Cells[0,Grid.RowCount-1]; if (MacroName<>'') and IsValidIdent(MacroName) then NeedNewRow:=true; end; if NeedNewRow then begin Grid.RowCount:=Grid.RowCount+1; Grid.Cells[0,Grid.RowCount-1]:='(new)'; Grid.Cells[1,Grid.RowCount-1]:=''; end; end; procedure TIdeMacroValuesFrame.SaveMacros(UpdateControls: boolean); var Grid: TStringGrid; aRow: Integer; MacroName: string; Values: TStringList; Value: string; begin // if MacroValues=nil then exit; Grid:=IdeMacroValuesStringGrid; Values:=TStringList.Create; try for aRow:=1 to Grid.RowCount-1 do begin MacroName:=Grid.Cells[0,aRow]; if (MacroName='') or (not IsValidIdent(MacroName)) then continue; Value:=Grid.Cells[1,aRow]; Values.Values[MacroName]:=Value; end; if not Project1.MacroValues.Equals(Values) then begin // has changed Project1.MacroValues.Assign(Values); IncreaseBuildMacroChangeStamp; if UpdateControls then begin UpdateInheritedOptions; end; end; finally Values.Free; end; end; procedure TIdeMacroValuesFrame.UpdateInheritedOptions; var InhOptionCtrl: TCompilerInheritedOptionsFrame; begin InhOptionCtrl:=TCompilerInheritedOptionsFrame( FindOptionControl(TCompilerInheritedOptionsFrame)); if InhOptionCtrl=nil then exit; InhOptionCtrl.UpdateInheritedTree(AProject.CompilerOptions); end; procedure TIdeMacroValuesFrame.UpdateShowSession; begin if LoadShowSessionFromProjects then ShowSession:=(AProject<>nil) and (AProject.SessionStorage in [pssInProjectDir,pssInIDEConfig]); end; constructor TIdeMacroValuesFrame.Create(TheOwner: TComponent); begin inherited Create(TheOwner); FLoadShowSessionFromProject:=true; end; destructor TIdeMacroValuesFrame.Destroy; begin inherited Destroy; end; function TIdeMacroValuesFrame.GetTitle: String; begin Result := dlgIdeMacroValues; end; procedure TIdeMacroValuesFrame.Setup(ADialog: TAbstractOptionsEditorDialog); var Grid: TStringGrid; begin IdeMacroValuesGroupBox.Caption:=lisIDEMacroValuesForFPCMacrosUseCustomOptions; Grid:=IdeMacroValuesStringGrid; Grid.Columns.Add; Grid.Columns[0].Title.Caption:=lisMacroName; Grid.Columns[0].ButtonStyle:=cbsPickList; Grid.Columns.Add; Grid.Columns[1].Title.Caption:=lisMacroValue; Grid.Columns[1].ButtonStyle:=cbsPickList; end; procedure TIdeMacroValuesFrame.ReadSettings(AOptions: TAbstractIDEOptions); var PCOptions: TProjectCompilerOptions; begin if AOptions is TProjectCompilerOptions then begin PCOptions:=TProjectCompilerOptions(AOptions); FProject:=PCOptions.LazProject; Assert(FProject=Project1, 'TIdeMacroValuesFrame.ReadSettings: FProject<>Project1'); // FMacroValues:=FProject.ActiveBuildMode.MacroValues; // modes UpdateShowSession; // macros // MacroValues.Assign(FProject.MacroValues); UpdateMacrosControls; // options dialog UpdateDialogCaption; end; end; procedure TIdeMacroValuesFrame.WriteSettings(AOptions: TAbstractIDEOptions); begin if AOptions is TProjectCompilerOptions then SaveMacros(false); end; class function TIdeMacroValuesFrame.SupportedOptionsClass: TAbstractIDEOptionsClass; begin Result := TProjectCompilerOptions; end; initialization RegisterIDEOptionsEditor(GroupCompiler, TIdeMacroValuesFrame, CompilerOptionsMacroValues); end.