mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-03 00:38:15 +02:00
IDE/SynEdit: Added basic macro recorder
git-svn-id: trunk@35456 -
This commit is contained in:
parent
8fd52f78f1
commit
6c2f247b5d
@ -282,7 +282,7 @@ const
|
||||
// If ask by SynEdit they add an offset
|
||||
|
||||
// Return the next offset
|
||||
function AllocatePluginKeyRange(Count: Integer): integer;
|
||||
function AllocatePluginKeyRange(Count: Integer; OffsetOnly: Boolean = False): integer;
|
||||
|
||||
type
|
||||
ESynKeyError = class(Exception);
|
||||
@ -693,12 +693,14 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
function AllocatePluginKeyRange(Count: Integer): integer;
|
||||
function AllocatePluginKeyRange(Count: Integer; OffsetOnly: Boolean): integer;
|
||||
const
|
||||
CurOffset : integer = 0;
|
||||
begin
|
||||
Result := CurOffset;
|
||||
inc(CurOffset, Count);
|
||||
if not OffsetOnly then
|
||||
inc(Result, ecPluginFirst);
|
||||
end;
|
||||
|
||||
function EditorCommandToDescrString(Cmd: TSynEditorCommand): string;
|
||||
|
@ -297,7 +297,7 @@ const
|
||||
// If ask by SynEdit they add an offset
|
||||
|
||||
// Return the next offset
|
||||
function AllocatePluginMouseRange(Count: Integer): integer;
|
||||
function AllocatePluginMouseRange(Count: Integer; OffsetOnly: Boolean = False): integer;
|
||||
|
||||
function MouseCommandName(emc: TSynEditorMouseCommand): String;
|
||||
function MouseCommandConfigName(emc: TSynEditorMouseCommand): String;
|
||||
@ -348,12 +348,14 @@ const
|
||||
|
||||
);
|
||||
|
||||
function AllocatePluginMouseRange(Count: Integer): integer;
|
||||
function AllocatePluginMouseRange(Count: Integer; OffsetOnly: Boolean = False): integer;
|
||||
const
|
||||
CurOffset : integer = 0;
|
||||
begin
|
||||
Result := CurOffset;
|
||||
inc(CurOffset, Count);
|
||||
if not OffsetOnly then
|
||||
inc(Result, emcPluginFirst);
|
||||
end;
|
||||
|
||||
function MouseCommandName(emc: TSynEditorMouseCommand): String;
|
||||
|
@ -41,26 +41,8 @@ unit SynEditPlugins;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes,
|
||||
{$IFDEF SYN_CLX}
|
||||
Qt,
|
||||
Types,
|
||||
QMenus,
|
||||
{$ELSE}
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
{$IFDEF USE_UTF8BIDI_LCL}
|
||||
utf8bidi,
|
||||
{$ENDIF}
|
||||
LCLIntf,
|
||||
{$ELSE}
|
||||
Windows,
|
||||
{$ENDIF}
|
||||
Menus,
|
||||
{$ENDIF}
|
||||
SynEdit,
|
||||
SynEditKeyCmds,
|
||||
Controls,
|
||||
LCLType;
|
||||
Classes, Menus, LCLType, SysUtils,
|
||||
SynEdit, SynEditKeyCmds, SynEditTypes, SynEditStrConst;
|
||||
|
||||
type
|
||||
|
||||
@ -76,10 +58,10 @@ type
|
||||
procedure SetEditor(const AValue: TCustomSynEdit); override;
|
||||
procedure DoEditorDestroyed(const AValue: TCustomSynEdit); override;
|
||||
function IndexOfEditor(const AValue: TCustomSynEdit): integer;
|
||||
function AddEditor(AValue: TCustomSynEdit): integer;
|
||||
function RemoveEditor(AValue: TCustomSynEdit): integer;
|
||||
public
|
||||
destructor Destroy; override;
|
||||
function AddEditor(AValue: TCustomSynEdit): integer;
|
||||
function RemoveEditor(AValue: TCustomSynEdit): integer;
|
||||
property Editors[aIndex: integer]: TCustomSynEdit read GetEditors;
|
||||
property EditorCount: integer read GetEditorCount;
|
||||
end;
|
||||
@ -89,7 +71,7 @@ type
|
||||
TAbstractSynHookerPlugin = class(TAbstractSynPlugin)
|
||||
protected
|
||||
procedure HookEditor(aEditor: TCustomSynEdit; aCommandID: TSynEditorCommand;
|
||||
aOldShortCut, aNewShortCut: TShortCut);
|
||||
aOldShortCut, aNewShortCut: TShortCut; AFlags: THookedCommandFlags = [hcfPreExec, hcfPostExec]);
|
||||
procedure UnHookEditor(aEditor: TCustomSynEdit;
|
||||
aCommandID: TSynEditorCommand; aShortCut: TShortCut);
|
||||
procedure OnCommand(Sender: TObject; AfterProcessing: boolean;
|
||||
@ -151,27 +133,14 @@ type
|
||||
property CurrentString: String read fCurrentString write SetCurrentString;
|
||||
end deprecated;
|
||||
|
||||
function NewPluginCommand: TSynEditorCommand; deprecated;
|
||||
function NewPluginCommand: TSynEditorCommand; deprecated; // Use AllocatePluginKeyRange
|
||||
procedure ReleasePluginCommand(aCmd: TSynEditorCommand); deprecated;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
SynEditTypes,
|
||||
SysUtils,
|
||||
{$IFDEF SYN_CLX}
|
||||
QForms,
|
||||
{$ELSE}
|
||||
Forms,
|
||||
{$ENDIF}
|
||||
{$IFNDEF SYN_LAZARUS}
|
||||
SynEditMiscProcs,
|
||||
{$ENDIF}
|
||||
SynEditStrConst;
|
||||
|
||||
function NewPluginCommand: TSynEditorCommand;
|
||||
begin
|
||||
Result := ecPluginFirst + AllocatePluginKeyRange(1);
|
||||
Result := AllocatePluginKeyRange(1);
|
||||
end;
|
||||
|
||||
procedure ReleasePluginCommand(aCmd: TSynEditorCommand);
|
||||
@ -286,7 +255,8 @@ end;
|
||||
{ TAbstractSynHookerPlugin }
|
||||
|
||||
procedure TAbstractSynHookerPlugin.HookEditor(aEditor: TCustomSynEdit;
|
||||
aCommandID: TSynEditorCommand; aOldShortCut, aNewShortCut: TShortCut);
|
||||
aCommandID: TSynEditorCommand; aOldShortCut, aNewShortCut: TShortCut;
|
||||
AFlags: THookedCommandFlags = [hcfPreExec, hcfPostExec]);
|
||||
var
|
||||
iIndex: integer;
|
||||
iKeystroke: TSynEditKeyStroke;
|
||||
@ -323,7 +293,9 @@ begin
|
||||
raise;
|
||||
end;
|
||||
iKeystroke.Command := aCommandID;
|
||||
aEditor.RegisterCommandHandler( {$IFDEF FPC}@{$ENDIF}OnCommand, Self );
|
||||
|
||||
if AFlags <> [] then
|
||||
aEditor.RegisterCommandHandler( {$IFDEF FPC}@{$ENDIF}OnCommand, Self, AFlags);
|
||||
end;
|
||||
|
||||
procedure TAbstractSynHookerPlugin.UnHookEditor(aEditor: TCustomSynEdit;
|
||||
@ -366,7 +338,7 @@ constructor TAbstractSynSingleHookPlugin.Create(aOwner: TComponent);
|
||||
begin
|
||||
inherited;
|
||||
// TODO: subclasses should implement per class, not per instance
|
||||
fCommandID := ecPluginFirst + AllocatePluginKeyRange(1);
|
||||
fCommandID := AllocatePluginKeyRange(1);
|
||||
fShortCut := DefaultShortCut;
|
||||
end;
|
||||
|
||||
|
@ -41,37 +41,10 @@ unit SynMacroRecorder;
|
||||
interface
|
||||
|
||||
uses
|
||||
Classes,
|
||||
SynEdit,
|
||||
SynEditKeyCmds, //js 06-04-2002 got consts out here and qconsts in
|
||||
{$IFDEF SYN_CLX}
|
||||
QConsts,
|
||||
QStdCtrls,
|
||||
QControls,
|
||||
Qt,
|
||||
Types,
|
||||
QGraphics,
|
||||
QMenus,
|
||||
{$ELSE}
|
||||
Controls,
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
{$IFDEF USE_UTF8BIDI_LCL}
|
||||
utf8bidi,
|
||||
{$ENDIF}
|
||||
FileUtil, Types, LCLIntf, LCLType,
|
||||
{$ELSE}
|
||||
Windows, Messages,
|
||||
{$ENDIF}
|
||||
Graphics,
|
||||
Menus,
|
||||
{$ENDIF}
|
||||
SynEditPlugins;
|
||||
Classes, SysUtils, FileUtil, Types, LCLType, Menus,
|
||||
SynEdit, SynEditKeyCmds, SynEditPlugins;
|
||||
|
||||
{$IFDEF SYN_COMPILER_3_UP}
|
||||
resourcestring
|
||||
{$ELSE}
|
||||
const
|
||||
{$ENDIF}
|
||||
sCannotRecord = 'Cannot record macro when recording';
|
||||
sCannotPlay = 'Cannot playback macro when recording';
|
||||
sCannotPause = 'Can only pause when recording';
|
||||
@ -89,7 +62,7 @@ type
|
||||
public
|
||||
constructor Create; {$IFNDEF FPC}virtual;{$ENDIF}
|
||||
procedure Initialize(aCmd: TSynEditorCommand;
|
||||
{$IFDEF SYN_LAZARUS}const aChar: TUTF8Char{$ELSE}aChar: Char{$ENDIF};
|
||||
const aChar: TUTF8Char;
|
||||
aData: Pointer); virtual; abstract;
|
||||
{ the CommandID must not be read inside LoadFromStream/SaveToStream. It's read by the
|
||||
MacroRecorder component to decide which MacroEvent class to instanciate }
|
||||
@ -107,7 +80,7 @@ type
|
||||
procedure InitEventParameters(aStr : string); override;
|
||||
public
|
||||
procedure Initialize(aCmd: TSynEditorCommand;
|
||||
{$IFDEF SYN_LAZARUS}const aChar: TUTF8Char{$ELSE}aChar: Char{$ENDIF};
|
||||
const aChar: TUTF8Char;
|
||||
aData: Pointer); override;
|
||||
procedure LoadFromStream(aStream: TStream); override;
|
||||
procedure SaveToStream(aStream: TStream); override;
|
||||
@ -118,22 +91,18 @@ type
|
||||
|
||||
TSynCharEvent = class(TSynMacroEvent)
|
||||
protected
|
||||
fKey: {$IFDEF SYN_LAZARUS}TUTF8Char{$ELSE}Char{$ENDIF};
|
||||
fKey: TUTF8Char;
|
||||
function GetAsString : string; override;
|
||||
procedure InitEventParameters(aStr : string); override;
|
||||
public
|
||||
procedure Initialize(aCmd: TSynEditorCommand;
|
||||
{$IFDEF SYN_LAZARUS}const aChar: TUTF8Char{$ELSE}aChar: Char{$ENDIF};
|
||||
const aChar: TUTF8Char;
|
||||
aData: Pointer); override;
|
||||
procedure LoadFromStream(aStream: TStream); override;
|
||||
procedure SaveToStream(aStream: TStream); override;
|
||||
procedure Playback(aEditor: TCustomSynEdit); override;
|
||||
public
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
property Key: TUTF8Char read fKey write fKey;
|
||||
{$ELSE}
|
||||
property Key: Char read fKey write fKey;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
TSynStringEvent = class(TSynMacroEvent)
|
||||
@ -143,7 +112,7 @@ type
|
||||
procedure InitEventParameters(aStr : string); override;
|
||||
public
|
||||
procedure Initialize(aCmd: TSynEditorCommand;
|
||||
{$IFDEF SYN_LAZARUS}const aChar: TUTF8Char{$ELSE}aChar: Char{$ENDIF};
|
||||
const aChar: TUTF8Char;
|
||||
aData: Pointer); override;
|
||||
procedure LoadFromStream(aStream: TStream); override;
|
||||
procedure SaveToStream(aStream: TStream); override;
|
||||
@ -159,7 +128,7 @@ type
|
||||
procedure InitEventParameters(aStr : string); override;
|
||||
public
|
||||
procedure Initialize(aCmd: TSynEditorCommand;
|
||||
{$IFDEF SYN_LAZARUS}const aChar: TUTF8Char{$ELSE}aChar: Char{$ENDIF};
|
||||
const aChar: TUTF8Char;
|
||||
aData: Pointer); override;
|
||||
procedure LoadFromStream(aStream: TStream); override;
|
||||
procedure SaveToStream(aStream: TStream); override;
|
||||
@ -173,7 +142,7 @@ type
|
||||
fData: Pointer;
|
||||
public
|
||||
procedure Initialize(aCmd: TSynEditorCommand;
|
||||
{$IFDEF SYN_LAZARUS}const aChar: TUTF8Char{$ELSE}aChar: Char{$ENDIF};
|
||||
const aChar: TUTF8Char;
|
||||
aData: Pointer); override;
|
||||
procedure LoadFromStream(aStream: TStream); override;
|
||||
procedure SaveToStream(aStream: TStream); override;
|
||||
@ -195,21 +164,26 @@ type
|
||||
|
||||
TCustomSynMacroRecorder = class(TAbstractSynHookerPlugin)
|
||||
private
|
||||
fCommandIDs: array [TSynMacroCommand] of TSynEditorCommand;
|
||||
fCommandIDUserSet: array [TSynMacroCommand] of Boolean;
|
||||
fShortCuts: array [TSynMacroCommand] of TShortCut;
|
||||
fOnStateChange: TNotifyEvent;
|
||||
fOnUserCommand: TSynUserCommandEvent;
|
||||
fMacroName: string;
|
||||
fSaveMarkerPos: boolean;
|
||||
FStartPlayBack: boolean;
|
||||
function GetCommandIDs(Index: integer): TSynEditorCommand;
|
||||
function GetEvent(aIndex: integer): TSynMacroEvent;
|
||||
function GetEventCount: integer;
|
||||
function GetAsString: string;
|
||||
procedure SetAsString(const Value: string);
|
||||
procedure SetCommandIDs(AIndex: Integer; AValue: TSynEditorCommand);
|
||||
procedure HookEditorCmd(ACmd: TSynMacroCommand; AnOldShortCut: TShortCut = 0);
|
||||
procedure UnHookEditorCmd(ACmd: TSynMacroCommand);
|
||||
protected
|
||||
fCurrentEditor: TCustomSynEdit;
|
||||
fState: TSynMacroState;
|
||||
fEvents: TList;
|
||||
fCommandIDs: array [TSynMacroCommand] of TSynEditorCommand;
|
||||
procedure SetShortCut(const Index: Integer; const Value: TShortCut);
|
||||
function GetIsEmpty: boolean;
|
||||
procedure StateChanged;
|
||||
@ -217,12 +191,24 @@ type
|
||||
procedure DoRemoveEditor(aEditor: TCustomSynEdit); override;
|
||||
procedure OnCommand(Sender: TObject; AfterProcessing: boolean;
|
||||
var Handled: boolean; var Command: TSynEditorCommand;
|
||||
var aChar: {$IFDEF SYN_LAZARUS}TUTF8Char{$ELSE}Char{$ENDIF};
|
||||
var aChar: TUTF8Char;
|
||||
Data: pointer; HandlerData: pointer); override;
|
||||
// hcfInit for recording, so we get the unmodified command
|
||||
procedure OnPreCommand(Sender: TObject; AfterProcessing: boolean;
|
||||
var Handled: boolean; var Command: TSynEditorCommand;
|
||||
var aChar: TUTF8Char;
|
||||
Data: pointer; HandlerData: pointer);
|
||||
// hcfFinish for playback, so there are no locks.
|
||||
// Locks interfere with selection (locked caret, no callback to selection)
|
||||
// and undo, does not work insid an UndoBlock
|
||||
procedure OnFinishCommand(Sender: TObject; AfterProcessing: boolean;
|
||||
var Handled: boolean; var Command: TSynEditorCommand;
|
||||
var aChar: TUTF8Char;
|
||||
Data: pointer; HandlerData: pointer);
|
||||
function CreateMacroEvent(aCmd: TSynEditorCommand): TSynMacroEvent;
|
||||
protected
|
||||
property RecordCommandID: TSynEditorCommand index ord(mcRecord) read GetCommandIDs;
|
||||
property PlaybackCommandID: TSynEditorCommand index ord(mcPlayback) read GetCommandIDs;
|
||||
property RecordCommandID: TSynEditorCommand index ord(mcRecord) read GetCommandIDs write SetCommandIDs;
|
||||
property PlaybackCommandID: TSynEditorCommand index ord(mcPlayback) read GetCommandIDs write SetCommandIDs;
|
||||
function GetShortCuts(Cmd: integer): TShortCut;
|
||||
public
|
||||
constructor Create(aOwner: TComponent); override;
|
||||
@ -249,6 +235,7 @@ type
|
||||
procedure SaveToFile(aFilename : string);
|
||||
property EventCount: integer read GetEventCount;
|
||||
property Events[aIndex: integer]: TSynMacroEvent read GetEvent;
|
||||
property CurrentEditor: TCustomSynEdit read fCurrentEditor; // while recording
|
||||
property RecordShortCut: TShortCut index Ord(mcRecord)
|
||||
read GetShortCuts write SetShortCut;
|
||||
property PlaybackShortCut: TShortCut index Ord(mcPlayback)
|
||||
@ -263,6 +250,9 @@ type
|
||||
end;
|
||||
|
||||
TSynMacroRecorder = class(TCustomSynMacroRecorder)
|
||||
public
|
||||
property RecordCommandID;
|
||||
property PlaybackCommandID;
|
||||
published
|
||||
property SaveMarkerPos;
|
||||
property RecordShortCut;
|
||||
@ -274,25 +264,9 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
{$IFNDEF SYN_LAZARUS}
|
||||
SynEditMiscProcs,
|
||||
SynEditTypes,
|
||||
{$ENDIF}
|
||||
{$IFDEF SYN_CLX}
|
||||
QForms,
|
||||
{$ELSE}
|
||||
Forms,
|
||||
{$IFDEF SYN_COMPILER_6_UP}
|
||||
RTLConsts,
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
SysUtils;
|
||||
|
||||
{ TSynDataEvent }
|
||||
|
||||
procedure TSynDataEvent.Initialize(aCmd: TSynEditorCommand;
|
||||
{$IFDEF SYN_LAZARUS}const aChar: TUTF8Char{$ELSE}aChar: Char{$ENDIF};
|
||||
procedure TSynDataEvent.Initialize(aCmd: TSynEditorCommand; const aChar: TUTF8Char;
|
||||
aData: Pointer);
|
||||
begin
|
||||
fCommand := aCmd;
|
||||
@ -350,15 +324,10 @@ constructor TCustomSynMacroRecorder.Create(aOwner: TComponent);
|
||||
begin
|
||||
inherited;
|
||||
fMacroName := 'unnamed';
|
||||
fCommandIDs[mcRecord] := NewPluginCommand;
|
||||
fCommandIDs[mcPlayback] := NewPluginCommand;
|
||||
{$IFDEF SYN_CLX} //js 06-04-2002 not only for linux, should also use qmenus when in clx for windows
|
||||
fShortCuts[mcRecord] := QMenus.ShortCut( Ord('R'), [ssCtrl, ssShift] );
|
||||
fShortCuts[mcPlayback] := QMenus.ShortCut( Ord('P'), [ssCtrl, ssShift] );
|
||||
{$ELSE}
|
||||
fCommandIDs[mcRecord] := ecNone;
|
||||
fCommandIDs[mcPlayback] := ecNone;
|
||||
fShortCuts[mcRecord] := Menus.ShortCut( Ord('R'), [ssCtrl, ssShift] );
|
||||
fShortCuts[mcPlayback] := Menus.ShortCut( Ord('P'), [ssCtrl, ssShift] );
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
function TCustomSynMacroRecorder.CreateMacroEvent(aCmd: TSynEditorCommand): TSynMacroEvent;
|
||||
@ -409,21 +378,33 @@ end;
|
||||
destructor TCustomSynMacroRecorder.Destroy;
|
||||
begin
|
||||
Clear;
|
||||
SetCommandIDs(ord(mcRecord), ecNone);
|
||||
SetCommandIDs(ord(mcPlayback), ecNone);
|
||||
inherited;
|
||||
ReleasePluginCommand( PlaybackCommandID );
|
||||
ReleasePluginCommand( RecordCommandID );
|
||||
end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.DoAddEditor(aEditor: TCustomSynEdit);
|
||||
begin
|
||||
HookEditor( aEditor, RecordCommandID, 0, RecordShortCut );
|
||||
HookEditor( aEditor, PlaybackCommandID, 0, PlaybackShortCut );
|
||||
if (RecordCommandID <> ecNone) and (RecordShortCut <> 0) then
|
||||
HookEditor( aEditor, RecordCommandID, 0, RecordShortCut, []);
|
||||
if (PlaybackCommandID <> ecNone) and (PlaybackShortCut <> 0) then
|
||||
HookEditor( aEditor, PlaybackCommandID, 0, PlaybackShortCut, []);
|
||||
|
||||
aEditor.RegisterCommandHandler( {$IFDEF FPC}@{$ENDIF}OnCommand, Self, [hcfPreExec]);
|
||||
aEditor.RegisterCommandHandler( {$IFDEF FPC}@{$ENDIF}OnPreCommand, Self, [hcfInit]);
|
||||
aEditor.RegisterCommandHandler( {$IFDEF FPC}@{$ENDIF}OnFinishCommand, Self, [hcfFinish]);
|
||||
end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.DoRemoveEditor(aEditor: TCustomSynEdit);
|
||||
begin
|
||||
UnHookEditor( aEditor, RecordCommandID, RecordShortCut );
|
||||
UnHookEditor( aEditor, PlaybackCommandID, PlaybackShortCut );
|
||||
if RecordCommandID <> ecNone then
|
||||
UnHookEditor( aEditor, RecordCommandID, RecordShortCut );
|
||||
if PlaybackCommandID <> ecNone then
|
||||
UnHookEditor( aEditor, PlaybackCommandID, PlaybackShortCut );
|
||||
|
||||
aEditor.UnregisterCommandHandler( {$IFDEF FPC}@{$ENDIF}OnCommand);
|
||||
aEditor.UnregisterCommandHandler( {$IFDEF FPC}@{$ENDIF}OnPreCommand);
|
||||
aEditor.UnregisterCommandHandler( {$IFDEF FPC}@{$ENDIF}OnFinishCommand);
|
||||
end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.Error(const aMsg: String);
|
||||
@ -440,6 +421,11 @@ function TCustomSynMacroRecorder.GetCommandIDs(Index: integer
|
||||
): TSynEditorCommand;
|
||||
begin
|
||||
Result:=fCommandIDs[TSynMacroCommand(Index)];
|
||||
if Result = ecNone then begin
|
||||
Result := AllocatePluginKeyRange(1);
|
||||
fCommandIDs[TSynMacroCommand(Index)] := Result;
|
||||
fCommandIDUserSet[TSynMacroCommand(Index)] := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TCustomSynMacroRecorder.GetEventCount: integer;
|
||||
@ -508,65 +494,76 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.OnCommand(Sender: TObject;
|
||||
AfterProcessing: boolean; var Handled: boolean;
|
||||
var Command: TSynEditorCommand;
|
||||
var aChar: {$IFDEF SYN_LAZARUS}TUTF8Char{$ELSE}Char{$ENDIF}; Data,
|
||||
procedure TCustomSynMacroRecorder.OnCommand(Sender: TObject; AfterProcessing: boolean;
|
||||
var Handled: boolean; var Command: TSynEditorCommand; var aChar: TUTF8Char; Data: pointer;
|
||||
HandlerData: pointer);
|
||||
begin
|
||||
FStartPlayBack := False;
|
||||
case State of
|
||||
msStopped:
|
||||
if Command = RecordCommandID then
|
||||
begin
|
||||
RecordMacro( TCustomSynEdit( Sender ) );
|
||||
Handled := True;
|
||||
end
|
||||
else if Command = PlaybackCommandID then
|
||||
begin
|
||||
FStartPlayBack := True;
|
||||
Handled := True;
|
||||
end;
|
||||
msPlaying:
|
||||
;
|
||||
msPaused:
|
||||
if Command = PlaybackCommandID then
|
||||
begin
|
||||
Resume;
|
||||
Handled := True;
|
||||
end;
|
||||
msRecording:
|
||||
if Command = PlaybackCommandID then
|
||||
begin
|
||||
Pause;
|
||||
Handled := True;
|
||||
end
|
||||
else if Command = RecordCommandID then
|
||||
begin
|
||||
Stop;
|
||||
Handled := True;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.OnPreCommand(Sender: TObject; AfterProcessing: boolean;
|
||||
var Handled: boolean; var Command: TSynEditorCommand; var aChar: TUTF8Char; Data: pointer;
|
||||
HandlerData: pointer);
|
||||
var
|
||||
iEvent: TSynMacroEvent;
|
||||
begin
|
||||
if AfterProcessing then
|
||||
if (Command = PlaybackCommandID) or (Command = RecordCommandID) then
|
||||
exit;
|
||||
|
||||
if (Sender = fCurrentEditor) and (State = msRecording) and (Command <> ecNone) then
|
||||
begin
|
||||
if (Sender = fCurrentEditor) and (State = msRecording) and (Command <> ecNone) then
|
||||
iEvent := CreateMacroEvent( Command );
|
||||
iEvent.Initialize( Command, aChar, Data );
|
||||
fEvents.Add( iEvent );
|
||||
if SaveMarkerPos and (Command >= ecSetMarker0) and
|
||||
(Command <= ecSetMarker9) and (Data = nil) then
|
||||
begin
|
||||
iEvent := CreateMacroEvent( Command );
|
||||
iEvent.Initialize( Command, aChar, Data );
|
||||
fEvents.Add( iEvent );
|
||||
if SaveMarkerPos and (Command >= ecSetMarker0) and
|
||||
(Command <= ecSetMarker9) and (Data = nil) then
|
||||
begin
|
||||
TSynPositionEvent(iEvent).Position := fCurrentEditor.CaretXY;
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
{not AfterProcessing}
|
||||
case State of
|
||||
msStopped:
|
||||
if Command = RecordCommandID then
|
||||
begin
|
||||
RecordMacro( TCustomSynEdit( Sender ) );
|
||||
Handled := True;
|
||||
end
|
||||
else if Command = PlaybackCommandID then
|
||||
begin
|
||||
PlaybackMacro( TCustomSynEdit( Sender ) );
|
||||
Handled := True;
|
||||
end;
|
||||
msPlaying:
|
||||
;
|
||||
msPaused:
|
||||
if Command = PlaybackCommandID then
|
||||
begin
|
||||
Resume;
|
||||
Handled := True;
|
||||
end;
|
||||
msRecording:
|
||||
if Command = PlaybackCommandID then
|
||||
begin
|
||||
Pause;
|
||||
Handled := True;
|
||||
end
|
||||
else if Command = RecordCommandID then
|
||||
begin
|
||||
Stop;
|
||||
Handled := True;
|
||||
end;
|
||||
TSynPositionEvent(iEvent).Position := fCurrentEditor.CaretXY;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.OnFinishCommand(Sender: TObject; AfterProcessing: boolean;
|
||||
var Handled: boolean; var Command: TSynEditorCommand; var aChar: TUTF8Char; Data: pointer;
|
||||
HandlerData: pointer);
|
||||
begin
|
||||
if not FStartPlayBack then exit;
|
||||
FStartPlayBack := False;
|
||||
PlaybackMacro( TCustomSynEdit( Sender ) );
|
||||
end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.Pause;
|
||||
begin
|
||||
if State <> msRecording then
|
||||
@ -624,23 +621,13 @@ end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.SetShortCut(const Index: Integer;
|
||||
const Value: TShortCut);
|
||||
var
|
||||
cEditor: integer;
|
||||
begin
|
||||
if fShortCuts[TSynMacroCommand(Index)] <> Value then
|
||||
begin
|
||||
if Assigned(fEditors) then
|
||||
if Value <> 0 then
|
||||
begin
|
||||
for cEditor := 0 to fEditors.Count -1 do
|
||||
HookEditor( Editors[cEditor], fCommandIDs[TSynMacroCommand(Index)],
|
||||
fShortCuts[TSynMacroCommand(Index)], Value );
|
||||
end else
|
||||
begin
|
||||
for cEditor := 0 to fEditors.Count -1 do
|
||||
UnHookEditor( Editors[cEditor], fCommandIDs[TSynMacroCommand(Index)],
|
||||
fShortCuts[TSynMacroCommand(Index)] );
|
||||
end;
|
||||
if Value <> 0 then
|
||||
HookEditorCmd(TSynMacroCommand(Index), fShortCuts[TSynMacroCommand(Index)])
|
||||
else
|
||||
UnHookEditorCmd(TSynMacroCommand(Index));
|
||||
fShortCuts[TSynMacroCommand(Index)] := Value;
|
||||
end;
|
||||
end;
|
||||
@ -717,6 +704,58 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.SetCommandIDs(AIndex: Integer; AValue: TSynEditorCommand);
|
||||
begin
|
||||
if (fCommandIDs[TSynMacroCommand(AIndex)] = AValue) and
|
||||
(fCommandIDUserSet[TSynMacroCommand(AIndex)] or (AValue = ecNone))
|
||||
then
|
||||
exit;
|
||||
|
||||
UnHookEditorCmd(TSynMacroCommand(AIndex));
|
||||
|
||||
//if (fCommandIDs[TSynMacroCommand(Index)] <> ecNone) and
|
||||
// (not fCommandIDUserSet[TSynMacroCommand(Index)])
|
||||
//then
|
||||
// ReleasePluginCommand(fCommandIDs[TSynMacroCommand(Index)]);
|
||||
|
||||
fCommandIDs[TSynMacroCommand(AIndex)] := AValue;
|
||||
fCommandIDUserSet[TSynMacroCommand(AIndex)] := AValue <> ecNone;
|
||||
|
||||
HookEditorCmd(TSynMacroCommand(AIndex));
|
||||
end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.HookEditorCmd(ACmd: TSynMacroCommand;
|
||||
AnOldShortCut: TShortCut);
|
||||
var
|
||||
cEditor: Integer;
|
||||
c: TSynEditorCommand;
|
||||
begin
|
||||
c := GetCommandIDs(ord(ACmd));
|
||||
if (not Assigned(fEditors)) or (c = ecNone) then
|
||||
exit;
|
||||
|
||||
if fShortCuts[ACmd] = 0 then begin
|
||||
UnHookEditorCmd(ACmd);
|
||||
exit;
|
||||
end;
|
||||
|
||||
for cEditor := 0 to fEditors.Count -1 do
|
||||
HookEditor(Editors[cEditor], c, AnOldShortCut, fShortCuts[ACmd], []);
|
||||
end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.UnHookEditorCmd(ACmd: TSynMacroCommand);
|
||||
var
|
||||
c: TSynEditorCommand;
|
||||
cEditor: Integer;
|
||||
begin
|
||||
c := GetCommandIDs(ord(ACmd));
|
||||
if (not Assigned(fEditors)) or (c = ecNone) then
|
||||
exit;
|
||||
|
||||
for cEditor := 0 to fEditors.Count -1 do
|
||||
UnHookEditor(Editors[cEditor], c, fShortCuts[ACmd]);
|
||||
end;
|
||||
|
||||
procedure TCustomSynMacroRecorder.LoadFromFile(aFilename: string);
|
||||
var
|
||||
F : TFileStream;
|
||||
@ -758,8 +797,7 @@ begin
|
||||
RepeatCount := Byte(StrToIntDef(Trim(aStr), 1));
|
||||
end;
|
||||
|
||||
procedure TSynBasicEvent.Initialize(aCmd: TSynEditorCommand;
|
||||
{$IFDEF SYN_LAZARUS}const aChar: TUTF8Char{$ELSE}aChar: Char{$ENDIF};
|
||||
procedure TSynBasicEvent.Initialize(aCmd: TSynEditorCommand; const aChar: TUTF8Char;
|
||||
aData: Pointer);
|
||||
begin
|
||||
Command := aCmd;
|
||||
@ -811,8 +849,7 @@ begin
|
||||
RepeatCount := Byte(StrToIntDef(Trim(aStr), 1));
|
||||
end;
|
||||
|
||||
procedure TSynCharEvent.Initialize(aCmd: TSynEditorCommand;
|
||||
{$IFDEF SYN_LAZARUS}const aChar: TUTF8Char{$ELSE}aChar: Char{$ENDIF};
|
||||
procedure TSynCharEvent.Initialize(aCmd: TSynEditorCommand; const aChar: TUTF8Char;
|
||||
aData: Pointer);
|
||||
begin
|
||||
Key := aChar;
|
||||
@ -881,8 +918,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynPositionEvent.Initialize(aCmd: TSynEditorCommand;
|
||||
{$IFDEF SYN_LAZARUS}const aChar: TUTF8Char{$ELSE}aChar: Char{$ENDIF};
|
||||
procedure TSynPositionEvent.Initialize(aCmd: TSynEditorCommand; const aChar: TUTF8Char;
|
||||
aData: Pointer);
|
||||
begin
|
||||
inherited;
|
||||
@ -953,8 +989,7 @@ begin
|
||||
RepeatCount := Byte(StrToIntDef(Trim(aStr), 1));
|
||||
end;
|
||||
|
||||
procedure TSynStringEvent.Initialize(aCmd: TSynEditorCommand;
|
||||
{$IFDEF SYN_LAZARUS}const aChar: TUTF8Char{$ELSE}aChar: Char{$ENDIF};
|
||||
procedure TSynStringEvent.Initialize(aCmd: TSynEditorCommand; const aChar: TUTF8Char;
|
||||
aData: Pointer);
|
||||
begin
|
||||
Value := String(aData);
|
||||
@ -968,13 +1003,7 @@ begin
|
||||
aStream.Read(l, SizeOf(l));
|
||||
GetMem(Buff, l);
|
||||
try
|
||||
{$IFDEF FPC}
|
||||
FillChar(Buff^,l,0);
|
||||
{$ELSE}
|
||||
{$IFNDEF SYN_CLX} //js 07-04-2002 changed from IFDEF WINDOWS
|
||||
FillMemory(Buff, l, 0);
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
aStream.Read(Buff^, l);
|
||||
fString := Buff;
|
||||
finally
|
||||
@ -1009,13 +1038,7 @@ begin
|
||||
aStream.Write(l, sizeof(l));
|
||||
GetMem(Buff, l);
|
||||
try
|
||||
{$IFDEF FPC}
|
||||
FillChar(Buff^,l,0);
|
||||
{$ELSE}
|
||||
{$IFNDEF SYN_CLX} //js 07-04-2002 changed from IFDEF WINDOWS
|
||||
FillMemory(Buff, l, 0);
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
StrPCopy(Buff, Value);
|
||||
aStream.Write(Buff^, l);
|
||||
finally
|
||||
|
@ -1564,8 +1564,8 @@ end;
|
||||
|
||||
|
||||
initialization
|
||||
MouseOffset := AllocatePluginMouseRange(emcSynPSyncroEdCount);
|
||||
KeyOffset := AllocatePluginKeyRange(ecSynPSyncroEdCount);
|
||||
MouseOffset := AllocatePluginMouseRange(emcSynPSyncroEdCount, True);
|
||||
KeyOffset := AllocatePluginKeyRange(ecSynPSyncroEdCount, True);
|
||||
|
||||
RegisterKeyCmdIdentProcs({$IFDEF FPC}@{$ENDIF}IdentToSyncroCommand,
|
||||
{$IFDEF FPC}@{$ENDIF}SyncroCommandToIdent);
|
||||
|
@ -478,7 +478,7 @@ begin
|
||||
end;
|
||||
|
||||
initialization
|
||||
KeyOffset := AllocatePluginKeyRange(ecSynPTmplEdCount + 1);
|
||||
KeyOffset := AllocatePluginKeyRange(ecSynPTmplEdCount + 1, True);
|
||||
|
||||
end.
|
||||
|
||||
|
@ -639,6 +639,10 @@ begin
|
||||
ecDesignerForwardOne : Result:= lisDsgOrderForwardOne;
|
||||
ecDesignerBackOne : Result:= lisDsgOrderBackOne;
|
||||
|
||||
// macro
|
||||
ecSynMacroRecord : Result:= srkmecSynMacroRecord;
|
||||
ecSynMacroPlay : Result:= srkmecSynMacroPlay;
|
||||
|
||||
// Edit template
|
||||
ecIdePTmplEdNextCell: Result := srkmecSynPTmplEdNextCell;
|
||||
ecIdePTmplEdNextCellSel: Result := srkmecSynPTmplEdNextCellSel;
|
||||
@ -1215,6 +1219,10 @@ begin
|
||||
ecDesignerForwardOne: SetSingle(VK_PRIOR,[ssCtrl]);
|
||||
ecDesignerBackOne: SetSingle(VK_NEXT,[ssCtrl]);
|
||||
|
||||
// macro
|
||||
ecSynMacroRecord: SetSingle(VK_R,[ssShift, ssCtrl]);
|
||||
ecSynMacroPlay: SetSingle(VK_P,[ssShift, ssCtrl]);
|
||||
|
||||
ecIdePTmplEdNextCell: SetSingle(VK_RIGHT,[ssCtrl]);
|
||||
ecIdePTmplEdNextCellSel: SetSingle(VK_TAB,[]);
|
||||
ecIdePTmplEdNextCellRotate: SetSingle(VK_UNKNOWN,[]);
|
||||
@ -1635,6 +1643,10 @@ begin
|
||||
ecDesignerForwardOne: SetSingle(VK_PRIOR,[ssCtrl]);
|
||||
ecDesignerBackOne: SetSingle(VK_NEXT,[ssCtrl]);
|
||||
|
||||
// macro
|
||||
ecSynMacroRecord: SetSingle(VK_R,[ssShift, ssCtrl]);
|
||||
ecSynMacroPlay: SetSingle(VK_P,[ssShift, ssCtrl]);
|
||||
|
||||
// Edit template
|
||||
ecIdePTmplEdNextCell: SetSingle(VK_RIGHT,[ssCtrl]);
|
||||
ecIdePTmplEdNextCellSel: SetSingle(VK_TAB,[]);
|
||||
@ -2240,6 +2252,10 @@ begin
|
||||
ecDesignerForwardOne: SetSingle(VK_PRIOR,[ssMeta]);
|
||||
ecDesignerBackOne: SetSingle(VK_NEXT,[ssMeta]);
|
||||
|
||||
// macro
|
||||
ecSynMacroRecord: SetSingle(VK_R,[ssShift, ssCtrl]);
|
||||
ecSynMacroPlay: SetSingle(VK_P,[ssShift, ssCtrl]);
|
||||
|
||||
// Edit template
|
||||
ecIdePTmplEdNextCell: SetSingle(VK_RIGHT,[ssCtrl]);
|
||||
ecIdePTmplEdNextCellSel: SetSingle(VK_TAB,[]);
|
||||
@ -2608,6 +2624,11 @@ begin
|
||||
AddDefault(C, 'Find overloads', srkmecFindOverloads, ecFindOverloads);
|
||||
AddDefault(C, 'Make resource string', srkmecMakeResourceString, ecMakeResourceString);
|
||||
|
||||
// Macro editing
|
||||
C:=Categories[AddCategory('MacroRecording', srkmCatMacroRecording, IDECmdScopeSrcEditOnly)];
|
||||
AddDefault(C, 'Record Macro', srkmecSynMacroRecord, ecSynMacroRecord);
|
||||
AddDefault(C, 'Play Macro', srkmecSynMacroPlay, ecSynMacroPlay);
|
||||
|
||||
// Template editing
|
||||
C:=Categories[AddCategory('Edit Template', srkmCatTemplateEdit, IDECmdScopeSrcEditOnlyTmplEdit)];
|
||||
AddDefault(C, 'Edit Template Next Cell', srkmecSynPTmplEdNextCell, ecIdePTmplEdNextCell);
|
||||
|
@ -2376,6 +2376,7 @@ resourcestring
|
||||
ueFileROText2='" is not writable.';
|
||||
ueModified='Modified';
|
||||
ueLocked='Locked';
|
||||
ueMacroRecording = 'Recording';
|
||||
uepReadonly= 'Readonly';
|
||||
uepIns='INS';
|
||||
uepOvr='OVR';
|
||||
@ -2736,6 +2737,10 @@ resourcestring
|
||||
srkmecFindOverloads = 'Find Overloads';
|
||||
srkmecFindOverloadsCapt = 'Find Overloads ...';
|
||||
|
||||
// Macro edit
|
||||
srkmecSynMacroRecord = 'Record Macro';
|
||||
srkmecSynMacroPlay = 'Play Macro';
|
||||
|
||||
//Plugin template Edit
|
||||
srkmecSynPTmplEdNextCell = 'Next Cell';
|
||||
srkmecSynPTmplEdNextCellSel = 'Next Cell (all selected)';
|
||||
@ -2818,6 +2823,7 @@ resourcestring
|
||||
srkmCatFold = 'Text folding commands';
|
||||
lisKMSetFreeBookmark = 'Set free Bookmark';
|
||||
srkmCatCodeTools = 'CodeTools commands';
|
||||
srkmCatMacroRecording = 'Macros';
|
||||
srkmCatTemplateEdit = 'Template Editing';
|
||||
srkmCatTemplateEditOff= 'Template Editing (not in Cell)';
|
||||
srkmCatSyncroEdit = 'Syncron Editing';
|
||||
|
@ -53,7 +53,7 @@ uses
|
||||
SynEditHighlighter, SynEditAutoComplete, SynEditKeyCmds, SynCompletion,
|
||||
SynEditMiscClasses, SynEditMarkupHighAll, SynEditMarks,
|
||||
SynBeautifier, SynEditTextBase, LazSynEditText,
|
||||
SynPluginSyncronizedEditBase, SourceSynEditor,
|
||||
SynPluginSyncronizedEditBase, SourceSynEditor, SynMacroRecorder,
|
||||
// Intf
|
||||
SrcEditorIntf, MenuIntf, LazIDEIntf, PackageIntf, IDEHelpIntf, IDEImagesIntf,
|
||||
IDEWindowIntf, ProjectIntf,
|
||||
@ -917,10 +917,13 @@ type
|
||||
procedure DecUpdateLock;
|
||||
procedure ShowActiveWindowOnTop(Focus: Boolean = False);
|
||||
private
|
||||
FMacroRecorder: TSynMacroRecorder;
|
||||
FOnCurrentCodeBufferChanged: TNotifyEvent;
|
||||
procedure DoMacroRecorderState(Sender: TObject);
|
||||
public
|
||||
property OnCurrentCodeBufferChanged: TNotifyEvent
|
||||
read FOnCurrentCodeBufferChanged write FOnCurrentCodeBufferChanged;
|
||||
property MacroRecorder: TSynMacroRecorder read FMacroRecorder;
|
||||
end;
|
||||
|
||||
{ TSourceEditorManager }
|
||||
@ -4045,6 +4048,7 @@ Begin
|
||||
Parent := AParent;
|
||||
end;
|
||||
Manager.CodeTemplateModul.AddEditor(FEditor);
|
||||
Manager.MacroRecorder.AddEditor(FEditor);
|
||||
Manager.NewEditorCreated(self);
|
||||
FEditor.TemplateEdit.OnActivate := @EditorActivateSyncro;
|
||||
FEditor.TemplateEdit.OnDeactivate := @EditorDeactivateSyncro;
|
||||
@ -6948,6 +6952,14 @@ begin
|
||||
PanelFileMode := PanelFileMode + uepReadonly;
|
||||
end;
|
||||
|
||||
if (Manager.MacroRecorder.State = msRecording) and
|
||||
(Manager.MacroRecorder.CurrentEditor = CurEditor)
|
||||
then begin
|
||||
if PanelFileMode <> '' then
|
||||
PanelFileMode := PanelFileMode + lisUEModeSeparator;
|
||||
PanelFileMode := PanelFileMode + ueMacroRecording;
|
||||
end;
|
||||
|
||||
If TempEditor.IsLocked then begin
|
||||
if PanelFileMode <> '' then
|
||||
PanelFileMode := PanelFileMode + lisUEModeSeparator;
|
||||
@ -7657,6 +7669,14 @@ end;
|
||||
|
||||
{ TSourceEditorManagerBase }
|
||||
|
||||
procedure TSourceEditorManagerBase.DoMacroRecorderState(Sender: TObject);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
For i := 0 to SourceWindowCount - 1 do
|
||||
TSourceNotebook(SourceWindows[i]).UpdateStatusBar;
|
||||
end;
|
||||
|
||||
procedure TSourceEditorManagerBase.FreeSourceWindows;
|
||||
var
|
||||
s: TSourceEditorWindowInterface;
|
||||
@ -8086,6 +8106,14 @@ var
|
||||
i: TsemChangeReason;
|
||||
h: TSrcEditMangerHandlerType;
|
||||
begin
|
||||
FMacroRecorder := TSynMacroRecorder.Create(nil);
|
||||
FMacroRecorder.OnStateChange := @DoMacroRecorderState;
|
||||
FMacroRecorder.RecordCommandID := ecSynMacroRecord;
|
||||
FMacroRecorder.PlaybackCommandID := ecSynMacroPlay;
|
||||
FMacroRecorder.RecordShortCut := 0;
|
||||
FMacroRecorder.PlaybackShortCut := 0;
|
||||
|
||||
|
||||
FUpdateFlags := [];
|
||||
FAutoFocusLock := 0;
|
||||
for i := low(TsemChangeReason) to high(TsemChangeReason) do
|
||||
@ -8115,6 +8143,7 @@ begin
|
||||
FreeCompletionPlugins;
|
||||
FreeSourceWindows;
|
||||
SrcEditorIntf.SourceEditorManagerIntf := nil; // xx move down
|
||||
FreeAndNil(FMacroRecorder);
|
||||
FreeAndNil(FCompletionPlugins);
|
||||
FreeAndNil(FSourceWindowList);
|
||||
FreeAndNil(FSourceWindowByFocusList);
|
||||
|
@ -230,6 +230,10 @@ const
|
||||
ecPrevBookmark = ecFirstLazarus + 382;
|
||||
ecNextBookmark = ecFirstLazarus + 383;
|
||||
|
||||
// Macro
|
||||
ecSynMacroRecord = ecFirstLazarus + 390;
|
||||
ecSynMacroPlay = ecFirstLazarus + 391;
|
||||
|
||||
// run menu
|
||||
ecCompile = ecFirstLazarus + 400;
|
||||
ecBuild = ecFirstLazarus + 401;
|
||||
|
Loading…
Reference in New Issue
Block a user