IDE: Add loading,saving macros

git-svn-id: trunk@37775 -
This commit is contained in:
martin 2012-06-25 01:08:39 +00:00
parent 0ac6e28810
commit 57a5800b00
4 changed files with 802 additions and 52 deletions

View File

@ -1,60 +1,130 @@
object MacroListView: TMacroListView
Left = 390
Height = 270
Height = 300
Top = 249
Width = 340
Caption = 'MacroListView'
ClientHeight = 270
ClientHeight = 300
ClientWidth = 340
Constraints.MinHeight = 270
Constraints.MinHeight = 300
Constraints.MinWidth = 300
OnActivate = FormActivate
OnDeactivate = FormActivate
LCLVersion = '1.1'
object Panel1: TPanel
AnchorSideRight.Control = pnlButtons
Left = 0
Height = 224
Top = 0
Left = 6
Height = 248
Top = 6
Width = 211
Align = alLeft
Anchors = [akTop, akLeft, akRight, akBottom]
BorderSpacing.Right = 12
BorderSpacing.Left = 6
BorderSpacing.Top = 6
BorderSpacing.Right = 6
BevelOuter = bvNone
ClientHeight = 224
ClientHeight = 248
ClientWidth = 211
TabOrder = 0
object lbRecordedView: TListView
Left = 0
Height = 202
Top = 22
Height = 199
Top = 24
Width = 211
Align = alClient
AutoWidthLastColumn = True
BorderSpacing.Top = 6
Columns = <
item
Width = 207
end>
PopupMenu = PopupMenu1
RowSelect = True
ShowColumnHeaders = False
TabOrder = 0
ViewStyle = vsReport
OnSelectItem = lbRecordedViewSelectItem
end
object lblRecordedTitle: TLabel
object ToolBar1: TToolBar
Left = 0
Height = 16
Height = 24
Top = 0
Width = 211
Align = alTop
Caption = 'lblRecordedTitle'
ParentColor = False
WordWrap = True
AutoSize = True
BorderSpacing.InnerBorder = 1
EdgeBorders = [ebLeft, ebTop, ebRight]
ParentShowHint = False
ShowCaptions = True
ShowHint = True
TabOrder = 1
object tbRecorded: TToolButton
Tag = 1
Left = 3
Top = 2
Caption = 'tbRecorded'
Down = True
Grouped = True
OnClick = tbRecordedClick
Style = tbsCheck
end
object tbProject: TToolButton
Tag = 1
Left = 72
Top = 2
Caption = 'tbProject'
Grouped = True
OnClick = tbProjectClick
Style = tbsCheck
end
object tbIDE: TToolButton
Tag = 1
Left = 128
Top = 2
Caption = 'tbIDE'
Grouped = True
OnClick = tbIDEClick
Style = tbsCheck
end
end
object ToolBar2: TToolBar
Left = 0
Height = 22
Top = 226
Width = 211
Align = alBottom
AutoSize = True
BorderSpacing.Top = 3
EdgeBorders = []
Flat = False
ShowCaptions = True
TabOrder = 2
object lbMoveTo: TLabel
Left = 1
Height = 22
Top = 0
Width = 55
Align = alLeft
Caption = 'lbMoveTo'
Layout = tlCenter
ParentColor = False
end
object tbMoveProject: TToolButton
Left = 56
Top = 0
Caption = 'tbMoveProject'
OnClick = tbMoveProjectClick
end
object tbMoveIDE: TToolButton
Left = 142
Top = 0
Caption = 'tbMoveIDE'
OnClick = tbMoveIDEClick
end
end
end
object ButtonPanel1: TButtonPanel
Left = 6
Height = 34
Top = 230
Top = 260
Width = 328
OKButton.Name = 'OKButton'
OKButton.DefaultCaption = True
@ -69,15 +139,15 @@ object MacroListView: TMacroListView
end
object pnlButtons: TPanel
Left = 223
Height = 224
Height = 254
Top = 0
Width = 117
Align = alRight
AutoSize = True
BevelOuter = bvNone
ClientHeight = 224
ClientHeight = 254
ClientWidth = 117
Constraints.MinHeight = 220
Constraints.MinHeight = 250
TabOrder = 2
object btnSelect: TButton
AnchorSideLeft.Control = pnlButtons
@ -127,7 +197,7 @@ object MacroListView: TMacroListView
AnchorSideBottom.Control = chkRepeat
Left = 6
Height = 25
Top = 85
Top = 115
Width = 105
Anchors = [akLeft, akRight, akBottom]
AutoSize = True
@ -147,7 +217,7 @@ object MacroListView: TMacroListView
AnchorSideBottom.Control = btnRecordStop
Left = 6
Height = 25
Top = 168
Top = 198
Width = 105
Anchors = [akLeft, akRight, akBottom]
AutoSize = True
@ -168,7 +238,7 @@ object MacroListView: TMacroListView
AnchorSideBottom.Side = asrBottom
Left = 6
Height = 25
Top = 199
Top = 229
Width = 105
Anchors = [akLeft, akRight, akBottom]
AutoSize = True
@ -187,7 +257,7 @@ object MacroListView: TMacroListView
AnchorSideBottom.Control = edRepeat
Left = 6
Height = 19
Top = 113
Top = 143
Width = 105
Anchors = [akLeft, akRight, akBottom]
BorderSpacing.Left = 6
@ -206,7 +276,7 @@ object MacroListView: TMacroListView
AnchorSideBottom.Control = btnRecord
Left = 6
Height = 23
Top = 135
Top = 165
Width = 105
Anchors = [akLeft, akRight, akBottom]
AutoSize = False
@ -219,5 +289,51 @@ object MacroListView: TMacroListView
TabOrder = 6
Value = 1
end
object btnDelete: TButton
AnchorSideLeft.Control = pnlButtons
AnchorSideTop.Control = btnRename
AnchorSideTop.Side = asrBottom
AnchorSideRight.Control = pnlButtons
AnchorSideRight.Side = asrBottom
AnchorSideBottom.Side = asrBottom
Left = 6
Height = 25
Top = 68
Width = 105
Anchors = [akTop, akLeft, akRight]
AutoSize = True
BorderSpacing.Left = 6
BorderSpacing.Top = 6
BorderSpacing.Right = 6
Caption = 'btnDelete'
OnClick = btnDeleteClick
TabOrder = 7
end
end
object PopupMenu1: TPopupMenu
left = 144
top = 72
object mnExport: TMenuItem
Caption = 'New Item1'
OnClick = mnExportClick
end
object mnImport: TMenuItem
Caption = 'New Item2'
OnClick = mnImportClick
end
end
object SaveDialog1: TSaveDialog
DefaultExt = '.xml'
Filter = 'xml|*.xml|*|*'
Options = [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist, ofNoReadOnlyReturn, ofEnableSizing, ofViewDetail]
left = 24
top = 56
end
object OpenDialog1: TOpenDialog
DefaultExt = '.xml'
Filter = 'xml|*.xml|*|*'
Options = [ofFileMustExist, ofEnableSizing, ofViewDetail]
left = 88
top = 64
end
end

View File

@ -5,13 +5,73 @@ unit EditorMacroListViewer;
interface
uses
Classes, SysUtils, FileUtil, SynMacroRecorder, SynEdit, Forms, Controls, Graphics, Dialogs,
StdCtrls, ButtonPanel, ComCtrls, ExtCtrls, Spin, MainBar, IDEWindowIntf, IDEImagesIntf,
LazarusIDEStrConsts, SrcEditorIntf;
Classes, SysUtils, FileUtil, Laz2_XMLCfg, SynMacroRecorder, SynEdit, SynEditKeyCmds,
FileProcs, Forms, Controls, Graphics, Dialogs, StdCtrls, ButtonPanel, ComCtrls, ExtCtrls,
Spin, Menus, MainBar, IDEWindowIntf, IDEImagesIntf, LazarusIDEStrConsts, ProjectDefs,
LazConf, Project, SrcEditorIntf;
type
TEditorMacro = TSynMacroRecorder;
{ TEditorMacro }
TEditorMacro = class(TSynMacroRecorder)
private
FHasError: Boolean;
FFailedText: String;
public
constructor Create(aOwner: TComponent); override;
function GetAsText: String;
procedure SetFromText(const AText: String);
procedure WriteToXmlConf(AConf: TXMLConfig; const APath: String);
procedure ReadFromXmlConf(AConf: TXMLConfig; const APath: String);
property HasError: Boolean read FHasError;
end;
{ TSynMacroEventWriter }
{ TIdeMacroEventWriter }
TIdeMacroEventWriter = class(TSynMacroEventWriter)
private
FText: String;
FCmdName, FParams: String;
FUseLineFeed: Boolean;
public
constructor Create;
procedure BeginEvent;
procedure FinishEvent;
procedure WriteEventCommand(const ACmd: TSynEditorCommand); override;
procedure WriteEventParam(const AParam: string); override;
procedure WriteEventParam(const AParam: integer); override;
property Text: String read FText;
property UseLineFeed: Boolean read FUseLineFeed write FUseLineFeed;
end;
{ TIdeMacroEventReader }
TIdeMacroEventReader = class(TSynMacroEventReader)
private
FEventName: String;
FHasError: Boolean;
FText: String;
FEventCommand: TSynEditorCommand;
FParams: Array of record
ParamType: TSynEventParamType;
Text : String;
Num: Integer;
end;
protected
function GetParamAsInt(Index: Integer): Integer; override;
function GetParamAsString(Index: Integer): String; override;
function GetParamType(Index: Integer): TSynEventParamType; override;
public
constructor Create(const Atext: String);
function EventCommand: TSynEditorCommand; override;
function ParamCount: Integer; override;
function ParseNextEvent: Boolean;
property EventName: String read FEventName;
property HasError: Boolean read FHasError;
end;
{ TEditorMacroList }
@ -24,6 +84,8 @@ type
public
constructor Create;
destructor Destroy; override;
procedure WriteToXmlConf(AConf: TXMLConfig; const APath: String);
procedure ReadFromXmlConf(AConf: TXMLConfig; const APath: String);
procedure ClearAndFreeMacros;
function Count: Integer;
function IndexOf(AMacro: TEditorMacro): Integer;
@ -40,26 +102,49 @@ type
btnPlay: TButton;
btnRecord: TButton;
btnRecordStop: TButton;
btnDelete: TButton;
btnSelect: TButton;
btnRename: TButton;
ButtonPanel1: TButtonPanel;
chkRepeat: TCheckBox;
lblRecordedTitle: TLabel;
lbMoveTo: TLabel;
lbRecordedView: TListView;
mnExport: TMenuItem;
mnImport: TMenuItem;
OpenDialog1: TOpenDialog;
Panel1: TPanel;
pnlButtons: TPanel;
PopupMenu1: TPopupMenu;
RenameButton: TPanelBitBtn;
edRepeat: TSpinEdit;
SaveDialog1: TSaveDialog;
ToolBar1: TToolBar;
tbRecorded: TToolButton;
tbProject: TToolButton;
tbIDE: TToolButton;
ToolBar2: TToolBar;
tbMoveProject: TToolButton;
tbMoveIDE: TToolButton;
procedure btnDeleteClick(Sender: TObject);
procedure btnPlayClick(Sender: TObject);
procedure btnRecordClick(Sender: TObject);
procedure btnRecordStopClick(Sender: TObject);
procedure btnRenameClick(Sender: TObject);
procedure btnSelectClick(Sender: TObject);
procedure FormActivate(Sender: TObject);
procedure lbRecordedViewSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
procedure mnExportClick(Sender: TObject);
procedure mnImportClick(Sender: TObject);
procedure tbIDEClick(Sender: TObject);
procedure tbMoveIDEClick(Sender: TObject);
procedure tbMoveProjectClick(Sender: TObject);
procedure tbProjectClick(Sender: TObject);
procedure tbRecordedClick(Sender: TObject);
private
FImageRec: Integer;
FImagePlay: Integer;
FImageSel: Integer;
FImageErr: Integer;
FIsPlaying: Boolean;
procedure DoOnMacroListChange(Sender: TObject);
procedure UpdateDisplay;
@ -73,6 +158,11 @@ type
procedure ShowMacroListViewer;
procedure DoEditorMacroStateChanged;
procedure LoadProjectSpecificInfo(XMLConfig: TXMLConfig; Merge: boolean);
procedure SaveProjectSpecificInfo(XMLConfig: TXMLConfig; Flags: TProjectWriteFlags);
procedure LoadGlobalInfo;
procedure SaveGlobalInfo;
var
EditorMacroRecorder: TEditorMacro = nil; // set by SourceEditor
@ -80,10 +170,13 @@ implementation
var
MacroListView: TMacroListView = nil;
EditorMacroList: TEditorMacroList = nil;
CurrentEditorMacroList: TEditorMacroList = nil;
EditorMacroListRec, EditorMacroListProj, EditorMacroListGlob: TEditorMacroList;
CurrentRecordingMacro: TEditorMacro = nil; // Points to a Macro in the list (copy)
CurrentActiveMacro: TEditorMacro = nil; // Points to a Macro in the list (copy)
MacroRecCounter: Integer = 1;
const
GlobalConfFileName = 'EditorMacros.xml';
procedure ShowMacroListViewer;
begin
@ -101,7 +194,7 @@ begin
then begin
// finished recarding
if EditorMacroRecorder.IsEmpty then begin
EditorMacroList.Remove(CurrentRecordingMacro);
EditorMacroListRec.Remove(CurrentRecordingMacro);
FreeAndNil(CurrentRecordingMacro);
end else begin
CurrentRecordingMacro.AssignEventsFrom(EditorMacroRecorder);
@ -112,23 +205,371 @@ begin
if (EditorMacroRecorder.State = msRecording) and (CurrentRecordingMacro = nil) then begin
CurrentRecordingMacro := TEditorMacro.Create(nil);
CurrentRecordingMacro.MacroName := Format(lisNewMacroName, [EditorMacroList.Count+1]);
EditorMacroList.Add(CurrentRecordingMacro);
CurrentRecordingMacro.MacroName := Format(lisNewMacroName, [MacroRecCounter]);
inc(MacroRecCounter);
EditorMacroListRec.Add(CurrentRecordingMacro);
end;
if MacroListView <> nil then
MacroListView.DoEditorMacroStateChanged;
end;
procedure LoadProjectSpecificInfo(XMLConfig: TXMLConfig; Merge: boolean);
begin
EditorMacroListProj.ReadFromXmlConf(XMLConfig, '');
end;
procedure SaveProjectSpecificInfo(XMLConfig: TXMLConfig; Flags: TProjectWriteFlags);
begin
if not (pwfSkipSeparateSessionInfo in Flags) then
begin
EditorMacroListProj.WriteToXmlConf(XMLConfig, '');
end;
end;
procedure LoadGlobalInfo;
var
Filename: String;
XMLConfig: TXMLConfig;
begin
Filename := TrimFilename(AppendPathDelim(GetPrimaryConfigPath)+GlobalConfFileName);
XMLConfig := TXMLConfig.Create(Filename);
EditorMacroListGlob.ReadFromXmlConf(XMLConfig, '');
XMLConfig.Free;
end;
procedure SaveGlobalInfo;
var
Filename: String;
XMLConfig: TXMLConfig;
begin
Filename := TrimFilename(AppendPathDelim(GetPrimaryConfigPath)+GlobalConfFileName);
XMLConfig := TXMLConfig.CreateClean(Filename);
EditorMacroListGlob.WriteToXmlConf(XMLConfig, '');
XMLConfig.Free;
end;
{ TEditorMacro }
constructor TEditorMacro.Create(aOwner: TComponent);
begin
inherited Create(aOwner);
FHasError := False;
end;
function TEditorMacro.GetAsText: String;
var
i : integer;
W: TIdeMacroEventWriter;
begin
if FHasError then begin
Result := FFailedText;
exit;
end;
W := TIdeMacroEventWriter.Create;
try
if Assigned(fEvents) then
begin
for i := 0 to fEvents.Count -1 do
begin
W.BeginEvent;
Events[i].SaveToWriter(W);
W.FinishEvent;
end;
end;
Result := w.Text;
finally
W.Free;
end;
end;
procedure TEditorMacro.SetFromText(const AText: String);
var
iEvent: TSynMacroEvent;
R: TIdeMacroEventReader;
begin
Stop;
Clear;
fEvents := TList.Create;
R := TIdeMacroEventReader.Create(AText);
try
while R.ParseNextEvent do begin
iEvent := CreateMacroEvent(R.EventCommand);
iEvent.LoadFromReader(R);
fEvents.Add(iEvent);
end;
if R.HasError then begin
FHasError := True;
FFailedText := AText;
end;
finally
R.Free;
end;
end;
procedure TEditorMacro.WriteToXmlConf(AConf: TXMLConfig; const APath: String);
begin
AConf.SetValue(APath + 'Name', MacroName);
AConf.SetValue(APath + 'Code/Value', GetAsText);
end;
procedure TEditorMacro.ReadFromXmlConf(AConf: TXMLConfig; const APath: String);
var
s: String;
begin
s := AConf.GetValue(APath + 'Name', '');
if s <> '' then MacroName := s;
s := AConf.GetValue(APath + 'Code/Value', '');
SetFromText(s);
if (not FHasError) and (EventCount = 0) then begin
FHasError := True;
FFailedText := s;
end;
end;
{ TIdeMacroEventReader }
function TIdeMacroEventReader.GetParamAsInt(Index: Integer): Integer;
begin
if (Index < 0) or (Index >= Length(FParams)) or (ParamType[Index] <> ptInteger)
then begin
FHasError := True;
exit; // TODO error
end;
Result := FParams[Index].Num;
end;
function TIdeMacroEventReader.GetParamAsString(Index: Integer): String;
begin
if (Index < 0) or (Index >= Length(FParams)) or (ParamType[Index] <> ptString)
then begin
FHasError := True;
exit; // TODO error
end;
Result := FParams[Index].Text;
end;
function TIdeMacroEventReader.GetParamType(Index: Integer): TSynEventParamType;
begin
if (Index < 0) or (Index >= Length(FParams)) then begin
FHasError := True;
exit; // TODO error
end;
Result := FParams[Index].ParamType;
end;
constructor TIdeMacroEventReader.Create(const Atext: String);
begin
FText := Atext;
FHasError := False;
end;
function TIdeMacroEventReader.EventCommand: TSynEditorCommand;
begin
Result := FEventCommand;
end;
function TIdeMacroEventReader.ParamCount: Integer;
begin
Result := Length(FParams);
end;
function TIdeMacroEventReader.ParseNextEvent: Boolean;
procedure SkipNum(var i: integer);
begin
while (i <= Length(FText)) and (FText[i] in ['0'..'9']) do inc (i);
end;
procedure SkipSpace(var i: integer);
begin
while (i <= Length(FText)) and (FText[i] in [' '..#9, #13, #10]) do inc (i);
end;
var
c,i,j,k: Integer;
s: String;
begin
FEventName := '';
FText := Trim(FText);
Result := (FText <> '') and (not FHasError);
if not Result then exit;
Result := False;
FHasError := True; // Assume the worst
i := 1;
while (i <= Length(FText)) and (FText[i] in ['a'..'z','A'..'Z','0'..'9','_']) do inc (i);
if i = 1 then exit; // Todo error
s := Copy(FText, 1, i-1);
if not IdentToEditorCommand(s, j) then exit; // Todo error
FEventCommand := j;
FEventName := s;
while (i <= Length(FText)) and (FText[i] in [' ', #9]) do inc (i);
if (i > Length(FText)) then exit; // Todo error
SetLength(FParams, 0);
c := 0;
if (FText[i] = '(') then begin
inc(i);
repeat
SkipSpace(i);
if (i > Length(FText)) then exit; // Todo error
if FText[i] in ['0'..'9'] then begin
// Parse number
j := i;
SkipNum(i);
SetLength(FParams, c + 1);
FParams[c].ParamType := ptInteger;
FParams[c].Num := StrToInt(copy(FText, i, j-i));
inc(c);
end
else
if FText[i] in ['#', ''''] then begin
// Parse string
s := '';
repeat
case FText[i] of
'#': begin
j := i;
SkipNum(i);
k := StrToInt(copy(FText, i, j-i));
if k > 255 then exit; // TODO error, todo utf8
s := s + chr(k);
end;
'''': begin
inc(i);
repeat
case FText[i] of
'''': begin
if (i+1 <= Length(FText)) and (FText[i+1] = '''') then begin
s := s + '''';
inc(i,2);
end
else begin
inc(i);
break;
end;
end;
else begin
s := s + FText[i];
inc(i);
end;
end;
until i > Length(FText);
end;
else
break;
end;
until i > Length(FText);
SetLength(FParams, c + 1);
FParams[c].ParamType := ptString;
FParams[c].Text := s;
inc(c);
end
else
exit; // Todo error
SkipSpace(i);
if (i >= Length(FText)) then exit; // Todo error
if FText[i] = ')' then break;
if not(FText[i] = ',') then exit; // Todo error
inc(i);
until i > Length(FText);
inc(i);
end;
if (i > Length(FText)) then exit; // Todo error
if (FText[i] = ';') then begin
Delete(FText, 1, i);
Result := True;
FHasError := False;
exit;
end;
end;
{ TSynMacroEventWriter }
constructor TIdeMacroEventWriter.Create;
begin
FUseLineFeed := False;
end;
procedure TIdeMacroEventWriter.BeginEvent;
begin
FCmdName := '';
FParams := '';
end;
procedure TIdeMacroEventWriter.FinishEvent;
begin
FText := FText + FCmdName;
if FParams <> '' then
FText := FText + '(' + FParams + ')';
FText := FText + ';';
if FUseLineFeed then
FText := FText + LineEnding;
end;
procedure TIdeMacroEventWriter.WriteEventCommand(const ACmd: TSynEditorCommand);
begin
EditorCommandToIdent(ACmd, FCmdName);
end;
procedure TIdeMacroEventWriter.WriteEventParam(const AParam: string);
var
s: String;
i: Integer;
InQuotes: Boolean;
begin
if FParams <> '' then
FParams := FParams + ', ';
s := '';
InQuotes := False;
for i := 1 to length(AParam) do
case AParam[i] of
#0..#31: begin
if InQuotes then s := s + '''';
InQuotes := False;
s := s + '#' + IntToStr(ord(AParam[i]));
end;
'''': begin
if not InQuotes then s := s + '''';
InQuotes := True;
s := s + '''''';
end;
else begin
if not InQuotes then s := s + '''';
InQuotes := True;
s := s + AParam[i];
end;
end;
if InQuotes then s := s + '''';
FParams := FParams + s;
end;
procedure TIdeMacroEventWriter.WriteEventParam(const AParam: integer);
begin
if FParams <> '' then
FParams := FParams + ', ';
FParams := FParams + IntToStr(AParam);
end;
{ TMacroListView }
procedure TMacroListView.btnRenameClick(Sender: TObject);
var
s: String;
M: TSynMacroRecorder;
M: TEditorMacro;
begin
if lbRecordedView.ItemIndex < 0 then exit;
M := EditorMacroList.Macros[lbRecordedView.ItemIndex];
M := CurrentEditorMacroList.Macros[lbRecordedView.ItemIndex];
s := M.MacroName;
if InputQuery('New Macroname', Format('Enter new mawe for Macro "%s"', [m.MacroName]), s)
then begin
@ -151,7 +592,7 @@ begin
Application.ProcessMessages;
try
EditorMacroRecorder.AssignEventsFrom(EditorMacroList.Macros[lbRecordedView.ItemIndex]);
EditorMacroRecorder.AssignEventsFrom(CurrentEditorMacroList.Macros[lbRecordedView.ItemIndex]);
while i > 0 do begin
EditorMacroRecorder.PlaybackMacro(TCustomSynEdit(SourceEditorManagerIntf.ActiveEditor.EditorControl));
Application.ProcessMessages;
@ -166,6 +607,20 @@ begin
end;
procedure TMacroListView.btnDeleteClick(Sender: TObject);
begin
if lbRecordedView.ItemIndex < 0 then exit;
if MessageDlg(lisDeleteSelectedMacro, mtConfirmation, [mbYes, mbNo], 0) = mrYes
then begin
if CurrentActiveMacro = CurrentEditorMacroList.Macros[lbRecordedView.ItemIndex] then begin
CurrentActiveMacro := nil;
EditorMacroRecorder.Clear;
end;
CurrentEditorMacroList.Delete(lbRecordedView.ItemIndex);
UpdateDisplay;
end;
end;
procedure TMacroListView.btnRecordClick(Sender: TObject);
begin
if EditorMacroRecorder.State = msStopped then begin
@ -192,36 +647,126 @@ procedure TMacroListView.btnSelectClick(Sender: TObject);
begin
if EditorMacroRecorder.State <> msStopped then exit;
if lbRecordedView.ItemIndex >= 0 then
CurrentActiveMacro := EditorMacroList.Macros[lbRecordedView.ItemIndex]
CurrentActiveMacro := CurrentEditorMacroList.Macros[lbRecordedView.ItemIndex]
else
CurrentActiveMacro := nil;
EditorMacroRecorder.AssignEventsFrom(CurrentActiveMacro);
UpdateDisplay;
end;
procedure TMacroListView.FormActivate(Sender: TObject);
begin
lbRecordedView.HideSelection := Active;
end;
procedure TMacroListView.lbRecordedViewSelectItem(Sender: TObject; Item: TListItem;
Selected: Boolean);
begin
UpdateButtons;
end;
procedure TMacroListView.mnExportClick(Sender: TObject);
var
Conf: TXMLConfig;
begin
if lbRecordedView.ItemIndex < 0 then exit;
if SaveDialog1.Execute then begin
Conf := TXMLConfig.Create(SaveDialog1.FileName);
try
Conf.Clear;
Conf.SetValue('EditorMacros/Count', 1);
CurrentEditorMacroList.Macros[lbRecordedView.ItemIndex].WriteToXmlConf(Conf, 'EditorMacros/Macro1/');
finally
Conf.Free;
end;
end;
end;
procedure TMacroListView.mnImportClick(Sender: TObject);
var
Conf: TXMLConfig;
NewMacro: TEditorMacro;
begin
if OpenDialog1.Execute then begin
Conf := TXMLConfig.Create(OpenDialog1.FileName);
try
NewMacro := TEditorMacro.Create(nil);
NewMacro.ReadFromXmlConf(Conf, 'EditorMacros/Macro1/');
if NewMacro.EventCount > 0 then
CurrentEditorMacroList.Add(NewMacro)
else
NewMacro.Free;
finally
Conf.Free;
end;
end;
end;
procedure TMacroListView.tbIDEClick(Sender: TObject);
begin
CurrentEditorMacroList := EditorMacroListGlob;
UpdateDisplay;
end;
procedure TMacroListView.tbMoveIDEClick(Sender: TObject);
var
i: Integer;
begin
if (lbRecordedView.ItemIndex < 0) or (CurrentEditorMacroList = EditorMacroListGlob) then exit;
i := lbRecordedView.ItemIndex;
EditorMacroListGlob.Add(CurrentEditorMacroList.Macros[i]);
CurrentEditorMacroList.Delete(i);
UpdateDisplay;
end;
procedure TMacroListView.tbMoveProjectClick(Sender: TObject);
var
i: Integer;
begin
if (lbRecordedView.ItemIndex < 0) or (CurrentEditorMacroList = EditorMacroListProj) then exit;
i := lbRecordedView.ItemIndex;
EditorMacroListProj.Add(CurrentEditorMacroList.Macros[i]);
CurrentEditorMacroList.Delete(i);
UpdateDisplay;
end;
procedure TMacroListView.tbProjectClick(Sender: TObject);
begin
CurrentEditorMacroList := EditorMacroListProj;
UpdateDisplay;
end;
procedure TMacroListView.tbRecordedClick(Sender: TObject);
begin
CurrentEditorMacroList := EditorMacroListRec;
UpdateDisplay;
end;
procedure TMacroListView.DoOnMacroListChange(Sender: TObject);
begin
UpdateDisplay;
if Sender = EditorMacroListProj then
Project1.SessionModified := True;
end;
procedure TMacroListView.UpdateDisplay;
var
NewItem: TListItem;
i, idx: Integer;
M: TSynMacroRecorder;
M: TEditorMacro;
begin
idx := lbRecordedView.ItemIndex;
lbRecordedView.Items.Clear;
for i := 0 to EditorMacroList.Count - 1 do begin
M := EditorMacroList.Macros[i];
for i := 0 to CurrentEditorMacroList.Count - 1 do begin
M := CurrentEditorMacroList.Macros[i];
NewItem := lbRecordedView.Items.Add;
NewItem.Caption := M.MacroName;
if M.HasError then
NewItem.ImageIndex := FImageErr
else
if (m = CurrentRecordingMacro) then
NewItem.ImageIndex := FImageRec
else
@ -243,12 +788,21 @@ end;
procedure TMacroListView.UpdateButtons;
var
IsStopped: Boolean;
IsSel, IsErr, IsStopped: Boolean;
M: TEditorMacro;
begin
IsSel := (lbRecordedView.ItemIndex >= 0);
IsStopped := (EditorMacroRecorder.State = msStopped);
btnSelect.Enabled := IsStopped and (lbRecordedView.ItemIndex >= 0) and (not FIsPlaying);
btnRename.Enabled := IsStopped and (lbRecordedView.ItemIndex >= 0) and (not FIsPlaying);
btnPlay.Enabled := IsStopped and (lbRecordedView.ItemIndex >= 0) and (not FIsPlaying);
if IsSel then
M := CurrentEditorMacroList.Macros[lbRecordedView.ItemIndex];
IsErr := IsSel and M.HasError;
btnSelect.Enabled := IsStopped and IsSel and (not FIsPlaying) and (not IsErr);
btnRename.Enabled := IsStopped and IsSel and (not FIsPlaying) and (not IsErr);
btnDelete.Enabled := IsStopped and IsSel and (not FIsPlaying);
btnPlay.Enabled := IsStopped and IsSel and (not FIsPlaying) and (not IsErr);
chkRepeat.Enabled := IsStopped and (not FIsPlaying);
edRepeat.Enabled := IsStopped and (not FIsPlaying);
@ -261,6 +815,14 @@ begin
btnRecord.Caption := lisContinue
else
btnRecord.Caption := lisRecord;
mnImport.Enabled := IsStopped and (not FIsPlaying);
mnExport.Enabled := IsStopped and IsSel and (not FIsPlaying);
tbMoveProject.Visible := CurrentEditorMacroList <> EditorMacroListProj;
tbMoveProject.Enabled := IsStopped and IsSel and (not FIsPlaying);
tbMoveIDE.Visible := CurrentEditorMacroList <> EditorMacroListGlob;
tbMoveIDE.Enabled := IsStopped and IsSel and (not FIsPlaying);
end;
procedure TMacroListView.DoEditorMacroStateChanged;
@ -272,18 +834,38 @@ constructor TMacroListView.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
Caption := lisEditorMacros;
EditorMacroList.OnChange := @DoOnMacroListChange;
lblRecordedTitle.Caption := lisRecordedMacros;
EditorMacroListRec.OnChange := @DoOnMacroListChange;
EditorMacroListProj.OnChange := @DoOnMacroListChange;
EditorMacroListGlob.OnChange := @DoOnMacroListChange;
tbRecorded.Caption := lisRecordedMacros;
tbProject.Caption := lisProjectMacro;
tbIDE.Caption := lisIDE;
tbRecorded.Hint := lisNewRecordedMacrosNotToBeSaved;
tbProject.Hint := lisSavedWithProjectSession;
tbIDE.Hint := lisSavedWithIDESettings;
tbMoveProject.Caption := lisProjectMacro;
tbMoveIDE.Caption := lisIDE;
lbMoveTo.Caption := lisMoveTo;
btnSelect.Caption := lisMenuSelect;
btnRename.Caption := lisRename2;
btnDelete.Caption := lisDelete;
btnPlay.Caption := lisPlay;
chkRepeat.Caption := lisRepeat;
btnRecord.Caption := lisRecord;
btnRecordStop.Caption := lisStop;
SaveDialog1.Title := lisSaveMacroAs;
OpenDialog1.Title := lisLoadMacroFrom;
mnImport.Caption := lisImport;
mnExport.Caption := lisExport;
lbRecordedView.SmallImages := IDEImages.Images_16;
FImageRec := IDEImages.LoadImage(16, 'Record'); // red dot
FImagePlay := IDEImages.LoadImage(16, 'menu_run'); // green triangle
FImageSel := IDEImages.LoadImage(16, 'arrow_right');
FImageErr := IDEImages.LoadImage(16, 'state_error');
FIsPlaying := False;
UpdateButtons;
@ -309,11 +891,38 @@ end;
destructor TEditorMacroList.Destroy;
begin
FOnChange := nil;
ClearAndFreeMacros;
FreeAndNil(FList);
inherited Destroy;
end;
procedure TEditorMacroList.WriteToXmlConf(AConf: TXMLConfig; const APath: String);
var
i: Integer;
begin
AConf.SetValue(APath + 'EditorMacros/Count', Count);
for i := 0 to Count - 1 do
Macros[i].WriteToXmlConf(AConf, 'EditorMacros/Macro'+IntToStr(i+1)+'/');
end;
procedure TEditorMacroList.ReadFromXmlConf(AConf: TXMLConfig; const APath: String);
var
c, i: Integer;
NewMacro: TEditorMacro;
begin
ClearAndFreeMacros;
c := AConf.GetValue(APath + 'EditorMacros/Count', 0);
for i := 0 to c -1 do begin
NewMacro := TEditorMacro.Create(nil);
try
NewMacro.ReadFromXmlConf(AConf, 'EditorMacros/Macro'+IntToStr(i+1)+'/');
finally
Add(NewMacro)
end;
end;
end;
procedure TEditorMacroList.ClearAndFreeMacros;
var
i: Integer;
@ -355,10 +964,16 @@ end;
{$R *.lfm}
initialization
EditorMacroList := TEditorMacroList.Create;
EditorMacroListRec := TEditorMacroList.Create;
EditorMacroListProj := TEditorMacroList.Create;
EditorMacroListGlob := TEditorMacroList.Create;
CurrentEditorMacroList := EditorMacroListRec;
finalization
FreeAndNil(EditorMacroList);
CurrentEditorMacroList := nil;
FreeAndNil(EditorMacroListRec);
FreeAndNil(EditorMacroListProj);
FreeAndNil(EditorMacroListGlob);
end.

View File

@ -5531,13 +5531,22 @@ resourcestring
lisWhatNeedsBuilding = 'What needs building';
lisTarget = 'Target:';
lisDirectives = 'Directives';
lisRecordedMacros = 'Recorded Macros';
lisRecordedMacros = 'Recorded';
lisRename2 = 'Rename ...';
lisNewMacroName = 'Macro %d';
lisEditorMacros = 'Editor macros';
lisPlay = 'Play';
lisRecord = 'Record';
lisRepeat = 'Repeat';
lisDeleteSelectedMacro = 'Delete selected macro?';
lisSaveMacroAs = 'Save macro as';
lisLoadMacroFrom = 'Load macro from';
lisImport = 'Import ...';
lisProjectMacro = 'Project';
lisNewRecordedMacrosNotToBeSaved = 'New recorded macros. Not to be saved';
lisSavedWithProjectSession = 'Saved with project session';
lisSavedWithIDESettings = 'Saved with IDE settings';
lisMoveTo = 'Move to: ';
implementation

View File

@ -1333,6 +1333,7 @@ begin
Application.ShowButtonGlyphs := ShowButtonGlyphs;
Application.ShowMenuGlyphs := ShowMenuGlyphs;
end;
EditorMacroListViewer.LoadGlobalInfo;
OldVer:=EnvironmentOptions.OldLazarusVersion;
NowVer:=GetLazarusVersionString;
@ -5323,6 +5324,7 @@ begin
fNeedSaveEnvironment:=false;
SaveDesktopSettings(EnvironmentOptions);
EnvironmentOptions.Save(false);
EditorMacroListViewer.SaveGlobalInfo;
//debugln('TMainIDE.SaveEnvironment A ',dbgsName(ObjectInspector1.Favourites));
if (ObjectInspector1<>nil) and (ObjectInspector1.Favourites<>nil) then
SaveOIFavouriteProperties(ObjectInspector1.Favourites);
@ -8321,6 +8323,10 @@ procedure TMainIDE.OnLoadProjectInfoFromXMLConfig(TheProject: TProject;
begin
if TheProject=Project1 then
DebugBoss.LoadProjectSpecificInfo(XMLConfig,Merge);
if (TheProject=Project1)
then
EditorMacroListViewer.LoadProjectSpecificInfo(XMLConfig, Merge);
end;
procedure TMainIDE.OnSaveProjectInfoToXMLConfig(TheProject: TProject;
@ -8329,6 +8335,10 @@ begin
if (TheProject=Project1) and (not (pwfSkipDebuggerSettings in WriteFlags))
then
DebugBoss.SaveProjectSpecificInfo(XMLConfig,WriteFlags);
if (TheProject=Project1)
then
EditorMacroListViewer.SaveProjectSpecificInfo(XMLConfig, WriteFlags);
end;
procedure TMainIDE.OnProjectGetTestDirectory(TheProject: TProject;