SynEdit: Refactor SynPlugin / Make SynCompletion a SynPlugin

git-svn-id: trunk@35493 -
This commit is contained in:
martin 2012-02-19 19:27:58 +00:00
parent 7a3dbe9f15
commit 9c9f699f61
4 changed files with 207 additions and 240 deletions

View File

@ -43,7 +43,7 @@ interface
uses
LCLProc, LCLIntf, LCLType, LMessages, Classes, Graphics, Forms,
Controls, StdCtrls, ExtCtrls, Menus, SysUtils,
SynEditMiscProcs, SynEditKeyCmds, SynEdit, SynEditTypes;
SynEditMiscProcs, SynEditKeyCmds, SynEdit, SynEditTypes, SynEditPlugins;
type
TSynBaseCompletionPaintItem =
@ -141,7 +141,6 @@ type
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
procedure KeyPress(var Key: char); override;
procedure Paint; override;
function Focused: Boolean; override;
procedure AppDeactivated(Sender: TObject); // Because Form.Deactivate isn't called
procedure Deactivate; override;
procedure SelectPrec;
@ -162,7 +161,7 @@ type
procedure FontChanged(Sender: TObject); override;
procedure WMMouseWheel(var Msg: TLMMouseEvent); message LM_MOUSEWHEEL;
private
fCurrentEditor: TComponent;
FCurrentEditor: TCustomSynEdit; // Must only be set via TSynCompletion.SetEditor
FDoubleClickSelects: Boolean;
FDrawBorderWidth: Integer;
FOnDragResized: TNotifyEvent;
@ -170,12 +169,14 @@ type
FOnPositionChanged: TNotifyEvent;
FShowSizeDrag: Boolean;
FHintLock: Integer;
procedure SetCurrentEditor(const AValue: TComponent);
procedure SetCurrentEditor(const AValue: TCustomSynEdit);
procedure SetDrawBorderWidth(const AValue: Integer);
procedure SetLongLineHintTime(const AValue: Integer);
procedure EditorStatusChanged(Sender: TObject; Changes: TSynStatusChanges);
procedure SetShowSizeDrag(const AValue: Boolean);
protected
procedure RegisterHandlers(EditOnly: Boolean = False);
procedure UnRegisterHandlers(EditOnly: Boolean = False);
procedure SetVisible(Value: Boolean); override;
property DrawBorderWidth: Integer read FDrawBorderWidth write SetDrawBorderWidth;
procedure IncHintLock;
@ -184,8 +185,11 @@ type
public
constructor Create(AOwner: Tcomponent); override;
destructor Destroy; override;
function Focused: Boolean; override;
procedure ShowItemHint(AIndex: Integer);
procedure OnHintTimer(Sender: TObject);
// Must only be set via TSynCompletion.SetEditor
property CurrentEditor: TCustomSynEdit read FCurrentEditor;
published
property CurrentString: string read FCurrentString write SetCurrentString;
property OnKeyPress: TKeyPressEvent read FOnKeyPress write FOnKeyPress;
@ -202,7 +206,6 @@ type
write SetNbLinesInWindow;
property ClSelect: TColor read FClSelect write FClSelect;
property CaseSensitive: boolean read FCaseSensitive write FCaseSensitive;
property CurrentEditor: TComponent read fCurrentEditor write SetCurrentEditor;
property FontHeight:integer read FFontHeight;
property OnSearchPosition:TSynBaseCompletionSearchPosition
read FOnSearchPosition write FOnSearchPosition;
@ -225,7 +228,7 @@ type
{ TSynBaseCompletion }
TSynBaseCompletion = class(TComponent)
TSynBaseCompletion = class(TLazSynMultiEditPlugin)
private
Form: TSynBaseCompletionForm;
FAddedPersistentCaret: boolean;
@ -281,7 +284,6 @@ type
procedure SetOnKeyPrevChar(const AValue: TNotifyEvent);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Execute(s: string; x, y: integer); overload;
procedure Execute(s: string; TopLeft: TPoint); overload;
procedure Execute(s: string; TokenRect: TRect); overload; // Excute below or above the token // may be extended to adjust left corner too
@ -333,47 +335,45 @@ type
TSynCompletion = class(TSynBaseCompletion)
private
FShortCut: TShortCut;
fEditors: TList;
fEditstuffs: TList;
FExecCommandID: TSynEditorCommand;
FEndOfTokenChr: string;
FOnCodeCompletion: TCodeCompletionEvent;
procedure SetEditor(const Value: TCustomSynEdit);
procedure backspace(Sender: TObject);
procedure Cancel(Sender: TObject);
procedure Validate(Sender: TObject; KeyChar: TUTF8Char; Shift: TShiftState);
procedure UTF8KeyPress(Sender: TObject; var Key: TUTF8Char);
procedure EditorKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure EditorKeyPress(Sender: TObject; var Key: char);
procedure EditorUTF8KeyPress(Sender: TObject; var UTF8Key: TUTF8Char);
procedure UTF8KeyPress(Sender: TObject; var Key: TUTF8Char); // called by the form
function GetPreviousToken(FEditor: TCustomSynEdit): string;
function GetFEditor: TCustomSynEdit;
function GetEditor(i: integer): TCustomSynEdit;
protected
procedure OnFormPaint(Sender: TObject);
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
procedure SetEditor(const Value: TCustomSynEdit); override;
procedure DoEditorAdded(AValue: TCustomSynEdit); override;
procedure DoEditorRemoving(AValue: TCustomSynEdit); override; /////////////
procedure SetShortCut(Value: TShortCut);
procedure TranslateKey(Sender: TObject; Code: word; SState: TShiftState;
var Data: pointer; var IsStartOfCombo: boolean; var Handled: boolean;
var Command: TSynEditorCommand; FinishComboOnly: Boolean;
var ComboKeyStrokes: TSynEditKeyStrokes);
procedure ProcessSynCommand(Sender: TObject; AfterProcessing: boolean;
var Handled: boolean; var Command: TSynEditorCommand;
var AChar: TUTF8Char; Data: pointer; HandlerData: pointer);
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property Editors[i: integer]: TCustomSynEdit read GetEditor;
procedure AddEditor(aEditor: TCustomSynEdit);
function RemoveEditor(aEditor: TCustomSynEdit): boolean;
function EditorsCount: integer;
function EditorsCount: integer; deprecated; // use EditorCount
published
property ShortCut: TShortCut read FShortCut write SetShortCut;
property Editor: TCustomSynEdit read GetFEditor write SetEditor;
property EndOfTokenChr: string read FEndOfTokenChr write FEndOfTokenChr;
property OnCodeCompletion: TCodeCompletionEvent
read FOnCodeCompletion write FOnCodeCompletion;
property ExecCommandID: TSynEditorCommand read FExecCommandID write FExecCommandID;
end;
{ TSynAutoComplete }
TSynAutoComplete = class(TComponent)
private
fEditstuffs: TList;
FShortCut: TShortCut;
fEditors: TList;
fEditstuffs: TList;
fAutoCompleteList: TStrings;
FEndOfTokenChr: string;
procedure SetAutoCompleteList(List: TStrings);
@ -410,9 +410,16 @@ type
procedure PrettyTextOut(c: TCanvas; x, y: integer; s: string);
const
ecSynCompletionExecute = ecPluginFirst + 0;
ecSynCompletionCount = 1;
implementation
var
KeyOffset: integer;
{ TSynBaseCompletionFormSizeDrag }
procedure TSynBaseCompletionFormSizeDrag.MouseDown(Button: TMouseButton; Shift: TShiftState;
@ -588,6 +595,7 @@ end;
destructor TSynBaseCompletionForm.Destroy;
begin
UnRegisterHandlers;
FreeAndNil(Scroll);
FreeAndNil(SizeDrag);
FItemList.Free;
@ -1069,15 +1077,30 @@ begin
SizeDrag.Visible := AValue;
end;
procedure TSynBaseCompletionForm.SetCurrentEditor(const AValue: TComponent);
procedure TSynBaseCompletionForm.RegisterHandlers(EditOnly: Boolean);
begin
if fCurrentEditor = AValue then exit;
if fCurrentEditor <> nil then
TCustomSynEdit(fCurrentEditor).UnRegisterStatusChangedHandler({$IFDEF FPC}@{$ENDIF}EditorStatusChanged);
fCurrentEditor := AValue;
if (fCurrentEditor <> nil) and Visible then
TCustomSynEdit(fCurrentEditor).RegisterStatusChangedHandler({$IFDEF FPC}@{$ENDIF}EditorStatusChanged,
[scTopLine]);
if FCurrentEditor <> nil then
FCurrentEditor.RegisterStatusChangedHandler
({$IFDEF FPC}@{$ENDIF}EditorStatusChanged, [scTopLine]);
if not EditOnly then
Application.AddOnDeactivateHandler({$IFDEF FPC}@{$ENDIF}AppDeactivated);
end;
procedure TSynBaseCompletionForm.UnRegisterHandlers(EditOnly: Boolean);
begin
if FCurrentEditor <> nil then
FCurrentEditor.UnRegisterStatusChangedHandler({$IFDEF FPC}@{$ENDIF}EditorStatusChanged);
if not EditOnly then
Application.RemoveOnDeactivateHandler({$IFDEF FPC}@{$ENDIF}AppDeactivated);
end;
procedure TSynBaseCompletionForm.SetCurrentEditor(const AValue: TCustomSynEdit);
begin
if FCurrentEditor = AValue then exit;
UnRegisterHandlers(True);
FCurrentEditor := AValue;
if Visible then
RegisterHandlers(True);
end;
procedure TSynBaseCompletionForm.SetDrawBorderWidth(const AValue: Integer);
@ -1099,17 +1122,11 @@ procedure TSynBaseCompletionForm.SetVisible(Value: Boolean);
begin
if Visible = Value then exit;;
inherited SetVisible(Value);
if (fCurrentEditor <> nil) then begin
if Visible then
TCustomSynEdit(fCurrentEditor).RegisterStatusChangedHandler({$IFDEF FPC}@{$ENDIF}EditorStatusChanged,
[scTopLine])
else
TCustomSynEdit(fCurrentEditor).UnRegisterStatusChangedHandler({$IFDEF FPC}@{$ENDIF}EditorStatusChanged);
end;
if Value then
Application.AddOnDeactivateHandler({$IFDEF FPC}@{$ENDIF}AppDeactivated)
RegisterHandlers
else
Application.RemoveOnDeactivateHandler({$IFDEF FPC}@{$ENDIF}AppDeactivated);
UnRegisterHandlers;
end;
procedure TSynBaseCompletionForm.IncHintLock;
@ -1186,12 +1203,6 @@ begin
Form.Width := FWidth;
end;
destructor TSynBaseCompletion.Destroy;
begin
Form.Free;
inherited Destroy;
end;
function TSynBaseCompletion.GetOnUTF8KeyPress: TUTF8KeyPressEvent;
begin
Result:=Form.OnUTF8KeyPress;
@ -1683,21 +1694,6 @@ begin
end;
end;
procedure TSynCompletion.SetEditor(const Value: TCustomSynEdit);
begin
AddEditor(Value);
Form.FCurrentEditor:=Value;
end;
procedure TSynCompletion.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) and (fEditors <> nil) then
if (fEditors.IndexOf(AComponent) > -1) then
RemoveEditor(AComponent as TCustomSynEdit);
end;
constructor TSynCompletion.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
@ -1707,9 +1703,8 @@ begin
Form.OnCancel := {$IFDEF FPC}@{$ENDIF}Cancel;
Form.OnPaint:=@OnFormPaint;
FEndOfTokenChr := '()[].';
fEditors := TList.Create;
fEditstuffs := TList.Create;
fShortCut := Menus.ShortCut(Ord(' '), [ssCtrl]);
FExecCommandID := KeyOffset + ecSynCompletionExecute;
end;
procedure TSynCompletion.SetShortCut(Value: TShortCut);
@ -1717,39 +1712,50 @@ begin
FShortCut := Value;
end;
procedure TSynCompletion.EditorKeyDown(Sender: TObject;
var Key: Word; Shift: TShiftState);
procedure TSynCompletion.TranslateKey(Sender: TObject; Code: word; SState: TShiftState;
var Data: pointer; var IsStartOfCombo: boolean; var Handled: boolean;
var Command: TSynEditorCommand; FinishComboOnly: Boolean;
var ComboKeyStrokes: TSynEditKeyStrokes);
var
p: TPoint;
i: integer;
ShortCutKey: Word;
ShortCutShift: TShiftState;
begin
if Key=VK_UNKNOWN then exit;
//debugln('TSynCompletion.EditorKeyDown A ',dbgs(Key));
if (Form<>nil) and Form.Visible then begin
// completion form is visible, but the synedit got a key
// -> redirect to form
Form.KeyDown(Key,Shift);
//debugln('TSynCompletion.EditorKeyDown B ',dbgs(Key));
if (Code = VK_UNKNOWN) or Handled or FinishComboOnly or (FExecCommandID = ecNone) then exit;
i := IndexOfEditor(Sender as TCustomSynEdit);
if i >= 0 then begin
ShortCutToKey(FShortCut, ShortCutKey, ShortCutShift);
if (SState = ShortCutShift) and (Code = ShortCutKey) then begin
Command := FExecCommandID;
Handled := True;
end;
end;
i := fEditors.IndexOf(Sender);
if i <> -1 then begin
ShortCutToKey(FShortCut, ShortCutKey, ShortCutShift);
if (Shift = ShortCutShift) and (Key = ShortCutKey) then
end;
procedure TSynCompletion.ProcessSynCommand(Sender: TObject; AfterProcessing: boolean;
var Handled: boolean; var Command: TSynEditorCommand; var AChar: TUTF8Char; Data: pointer;
HandlerData: pointer);
var
p: TPoint;
i: integer;
begin
if Handled or (Command <> FExecCommandID) then
exit;
i := IndexOfEditor(Sender as TCustomSynEdit);
if i >= 0 then begin
with sender as TCustomSynEdit do begin
if not ReadOnly and (Shift = ShortCutShift) and (Key = ShortCutKey) then begin
if not ReadOnly then begin
p := ClientToScreen(Point(CaretXPix, CaretYPix + LineHeight + 1));
Form.CurrentEditor := Sender as TCustomSynEdit;
Editor := Sender as TCustomSynEdit; // Will set Form.SetCurrentEditor
Execute(GetPreviousToken(Sender as TCustomSynEdit), p.x, p.y);
// eat it
Key := VK_UNKNOWN;
Handled := True;
end;
end;
if Assigned(TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).KeyDown) then
TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).KeyDown(sender, key, shift);
end;
end;
function TSynCompletion.GetPreviousToken(FEditor: TCustomSynEdit): string;
@ -1774,95 +1780,35 @@ begin
result := '';
end;
procedure TSynCompletion.EditorKeyPress(Sender: TObject; var Key: char);
procedure TSynCompletion.DoEditorAdded(AValue: TCustomSynEdit);
begin
inherited DoEditorAdded(AValue);
AValue.RegisterCommandHandler(@ProcessSynCommand, nil);
AValue.RegisterKeyTranslationHandler(@TranslateKey);
end;
procedure TSynCompletion.DoEditorRemoving(AValue: TCustomSynEdit);
var
i: integer;
i: Integer;
begin
//debugln(['TSynCompletion.EditorKeyPress ']);
i := fEditors.IndexOf(Sender);
if i <> -1 then begin
if assigned(TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).KeyPress) then
TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).KeyPress(sender, key);
end;
inherited DoEditorRemoving(AValue);
if Form.CurrentEditor = AValue then
Form.SetCurrentEditor(nil);
AValue.UnregisterCommandHandler(@ProcessSynCommand);
AValue.UnRegisterKeyTranslationHandler(@TranslateKey);
end;
procedure TSynCompletion.EditorUTF8KeyPress(Sender: TObject;
var UTF8Key: TUTF8Char);
var
i: integer;
procedure TSynCompletion.SetEditor(const Value: TCustomSynEdit);
begin
//debugln(['TSynCompletion.EditorUTF8KeyPress ']);
i := fEditors.IndexOf(Sender);
if i <> -1 then begin
if assigned(TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).UTF8KeyPress) then
TRecordUsedToStoreEachEditorVars(fEditstuffs[i]^).UTF8KeyPress(sender,UTF8Key);
end;
end;
destructor TSynCompletion.Destroy;
begin
// necessary to get Notification called before fEditors is freed
Form.Free;
Form := nil;
while fEditors.Count <> 0 do
RemoveEditor(TCustomSynEdit(fEditors.last));
FreeAndNil(fEditors);
FreeAndNil(fEditstuffs);
inherited;
end;
function TSynCompletion.GetFEditor: TCustomSynEdit;
begin
Result:=TCustomSynEdit(Form.fCurrentEditor);
end;
procedure TSynCompletion.AddEditor(aEditor: TCustomSynEdit);
var
p: PRecordUsedToStoreEachEditorVars;
begin
if fEditors.IndexOf(aEditor) = -1 then begin
fEditors.Add(aEditor);
new(p);
p^.KeyPress := aEditor.OnKeyPress;
p^.UTF8KeyPress := aEditor.OnUTF8KeyPress;
p^.KeyDown := aEditor.OnKeyDown;
fEditstuffs.add(p);
aEditor.FreeNotification(self);
if not (csDesigning in ComponentState) then begin
aEditor.OnKeyDown := {$IFDEF FPC}@{$ENDIF}EditorKeyDown;
aEditor.OnKeyPress := {$IFDEF FPC}@{$ENDIF}EditorKeyPress;
aEditor.OnUTF8KeyPress := {$IFDEF FPC}@{$ENDIF}EditorUTF8KeyPress;
end;
end;
inherited SetEditor(Value);
Form.SetCurrentEditor(Value);
end;
function TSynCompletion.EditorsCount: integer;
begin
result := fEditors.count;
end;
function TSynCompletion.GetEditor(i: integer): TCustomSynEdit;
begin
if (i < 0) or (i >= EditorsCount) then
result := nil
else
result := TCustomSynEdit(fEditors[i]);
end;
function TSynCompletion.RemoveEditor(aEditor: TCustomSynEdit): boolean;
var
i: integer;
P : PRecordUsedToStoreEachEditorVars;
begin
i := fEditors.Remove(aEditor);
result := i <> -1;
if result then
begin
p := fEditStuffs[i]; //shane
dispose(p); //shane
// dispose(fEditstuffs[i]); //commented out by shane
fEditstuffs.delete(i);
end;
result := EditorCount;
end;
{ TSynAutoComplete }
@ -2184,5 +2130,8 @@ begin
Result := Rect(0, 0, Canvas.TextWidth(AHint) + 4, FCompletionForm.FontHeight);
end;
initialization
KeyOffset := AllocatePluginKeyRange(ecSynCompletionCount, True);
end.

View File

@ -359,6 +359,8 @@ type
TLazSynEditPlugin = class(TSynEditFriend)
protected
procedure BeforeEditorChange; virtual;
procedure AfterEditorChange; virtual;
procedure RegisterToEditor(AValue: TCustomSynEdit);
procedure UnRegisterFromEditor(AValue: TCustomSynEdit);
procedure SetEditor(const AValue: TCustomSynEdit); virtual;
@ -366,8 +368,8 @@ type
function OwnedByEditor: Boolean; virtual; // if true, this will be destroyed by synedit
procedure DoEditorDestroyed(const AValue: TCustomSynEdit); virtual;
procedure DoAddEditor(AValue: TCustomSynEdit); virtual;
procedure DoRemoveEditor(AValue: TCustomSynEdit); virtual;
procedure DoEditorAdded(AValue: TCustomSynEdit); virtual;
procedure DoEditorRemoving(AValue: TCustomSynEdit); virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
@ -8670,6 +8672,22 @@ begin
inherited Destroy;
end;
procedure TLazSynEditPlugin.BeforeEditorChange;
begin
if (Editor <> nil) then begin
DoEditorRemoving(Editor);
UnRegisterFromEditor(Editor);
end;
end;
procedure TLazSynEditPlugin.AfterEditorChange;
begin
if Editor <> nil then begin
RegisterToEditor(Editor);
DoEditorAdded(Editor);
end;
end;
procedure TLazSynEditPlugin.RegisterToEditor(AValue: TCustomSynEdit);
begin
if AValue.fPlugins <> nil then
@ -8686,17 +8704,9 @@ procedure TLazSynEditPlugin.SetEditor(const AValue: TCustomSynEdit);
begin
if AValue = FriendEdit then exit;
if (FriendEdit <> nil) then begin
DoRemoveEditor(Editor);
UnRegisterFromEditor(Editor);
end;
BeforeEditorChange;
FriendEdit := AValue;
if FriendEdit <> nil then begin
RegisterToEditor(Editor);
DoAddEditor(Editor);
end;
AfterEditorChange;
end;
function TLazSynEditPlugin.GetEditor: TCustomSynEdit;
@ -8718,12 +8728,12 @@ begin
Editor := nil;
end;
procedure TLazSynEditPlugin.DoAddEditor(AValue: TCustomSynEdit);
procedure TLazSynEditPlugin.DoEditorAdded(AValue: TCustomSynEdit);
begin
//
end;
procedure TLazSynEditPlugin.DoRemoveEditor(AValue: TCustomSynEdit);
procedure TLazSynEditPlugin.DoEditorRemoving(AValue: TCustomSynEdit);
begin
//
end;

View File

@ -50,16 +50,27 @@ type
TLazSynMultiEditPlugin = class(TLazSynEditPlugin)
private
FEditors: TList;
FEditorWasAdded: Boolean;
function GetEditorCount: integer;
function GetEditors(aIndex: integer): TCustomSynEdit;
protected
FEditors: TList;
procedure SetEditor(const AValue: TCustomSynEdit); override;
procedure DoEditorDestroyed(const AValue: TCustomSynEdit); override;
function IndexOfEditor(const AValue: TCustomSynEdit): integer;
procedure BeforeEditorChange; override;
procedure AfterEditorChange; override;
function DoRemoveEditor(AValue: TCustomSynEdit): integer;
procedure DoEditorDestroyed(const AValue: TCustomSynEdit); override;
public
destructor Destroy; override;
(* Add/RemoveEditor versus Editor
Unless stated otherwise Plugins inherting from TLazSynMultiEditPlugin can
either use Add/RemoveEditor or Editor (single-editor-property).
If Editors are added via AddEditor, then an Editor only set via "Editor:="
may be lost/ignored.
If using AddEditor, the "Editor" property may be used to set/read the
current Editor (out of those in the list). This does however depend on the
inherited class.
*)
function AddEditor(AValue: TCustomSynEdit): integer;
function RemoveEditor(AValue: TCustomSynEdit): integer;
property Editors[aIndex: integer]: TCustomSynEdit read GetEditors;
@ -92,8 +103,8 @@ type
fCurrentEditor: TCustomSynEdit;
fShortCut: TShortCut;
class function DefaultShortCut: TShortCut; virtual;
procedure DoAddEditor(aEditor: TCustomSynEdit); override;
procedure DoRemoveEditor(aEditor: TCustomSynEdit); override;
procedure DoEditorAdded(aEditor: TCustomSynEdit); override;
procedure DoEditorRemoving(aEditor: TCustomSynEdit); override;
{}
procedure DoExecute; virtual; abstract;
procedure DoAccept; virtual; abstract;
@ -165,40 +176,6 @@ begin
Result := TCustomSynEdit(FEditors[aIndex]);
end;
procedure TLazSynMultiEditPlugin.SetEditor(const AValue: TCustomSynEdit);
var
i: Integer;
begin
if AValue = FriendEdit then exit;
if (not FEditorWasAdded) and (Editor <> nil) then
RemoveEditor(Editor);
FEditorWasAdded := False;
i := IndexOfEditor(AValue);
if (i < 0) then
inherited SetEditor(nil)
else
FriendEdit := nil; // keep registered / do not call EditorRemoved
if AValue = nil then
exit;
FEditorWasAdded := i >= 0;
if not FEditorWasAdded then
inherited SetEditor(AValue)
else
FriendEdit := AValue; // alreade registered / do not call EditorAdded
end;
procedure TLazSynMultiEditPlugin.DoEditorDestroyed(const AValue: TCustomSynEdit);
begin
RemoveEditor(AValue);
inherited DoEditorDestroyed(AValue);
end;
function TLazSynMultiEditPlugin.IndexOfEditor(const AValue: TCustomSynEdit): integer;
begin
if FEditors = nil then
@ -207,6 +184,48 @@ begin
Result := FEditors.IndexOf(AValue);
end;
procedure TLazSynMultiEditPlugin.BeforeEditorChange;
begin
if (Editor = nil) or FEditorWasAdded then
exit;
// Current Editor was not explicitly added by user via "AddEditor"
DoRemoveEditor(Editor);
end;
procedure TLazSynMultiEditPlugin.AfterEditorChange;
begin
if (Editor = nil) then
exit;
FEditorWasAdded := IndexOfEditor(Editor) >= 0;
if FEditorWasAdded then
exit;
// Current Editor was not explicitly added by user via "AddEditor"
// Temporary add it
AddEditor(Editor);
FEditorWasAdded := False; // Reset Flag, after AddEditor
end;
function TLazSynMultiEditPlugin.DoRemoveEditor(AValue: TCustomSynEdit): integer;
begin
if IndexOfEditor(AValue) < 0 then begin
Result := -1;
Exit;
end;
DoEditorRemoving(AValue);
UnRegisterFromEditor(AValue);
Result := FEditors.Remove(AValue);
end;
procedure TLazSynMultiEditPlugin.DoEditorDestroyed(const AValue: TCustomSynEdit);
begin
RemoveEditor(AValue);
if EditorCount = 0 then
inherited DoEditorDestroyed(nil); // Editor is nil now, so pass nil as param too
end;
function TLazSynMultiEditPlugin.AddEditor(AValue: TCustomSynEdit): integer;
begin
if AValue = Editor then
@ -219,28 +238,17 @@ begin
if FEditors = nil then
FEditors := TList.Create;
Result := FEditors.Add(AValue);
RegisterToEditor(AValue);
DoAddEditor( AValue );
DoEditorAdded(AValue);
end;
function TLazSynMultiEditPlugin.RemoveEditor(AValue: TCustomSynEdit): integer;
begin
if AValue = Editor then
FEditorWasAdded := False;
if IndexOfEditor(AValue) < 0 then begin
Result := -1;
Exit;
end;
Editor := nil;
DoRemoveEditor(AValue);
UnRegisterFromEditor(AValue);
Result := FEditors.Remove( AValue );
if AValue = Editor then
FriendEdit := nil;
end;
destructor TLazSynMultiEditPlugin.Destroy;
@ -355,7 +363,7 @@ begin
inherited;
end;
procedure TAbstractSynSingleHookPlugin.DoAddEditor(
procedure TAbstractSynSingleHookPlugin.DoEditorAdded(
aEditor: TCustomSynEdit);
begin
if ShortCut <> 0 then
@ -388,7 +396,7 @@ begin
Result := fShortCut <> DefaultShortCut;
end;
procedure TAbstractSynSingleHookPlugin.DoRemoveEditor(aEditor: TCustomSynEdit);
procedure TAbstractSynSingleHookPlugin.DoEditorRemoving(aEditor: TCustomSynEdit);
begin
if ShortCut <> 0 then
UnHookEditor( aEditor, CommandID, ShortCut );

View File

@ -202,8 +202,8 @@ type
procedure SetShortCut(const Index: Integer; const Value: TShortCut);
function GetIsEmpty: boolean;
procedure StateChanged;
procedure DoAddEditor(aEditor: TCustomSynEdit); override;
procedure DoRemoveEditor(aEditor: TCustomSynEdit); override;
procedure DoEditorAdded(aEditor: TCustomSynEdit); override;
procedure DoEditorRemoving(aEditor: TCustomSynEdit); override;
procedure OnCommand(Sender: TObject; AfterProcessing: boolean;
var Handled: boolean; var Command: TSynEditorCommand;
var aChar: TUTF8Char;
@ -431,7 +431,7 @@ begin
inherited;
end;
procedure TCustomSynMacroRecorder.DoAddEditor(aEditor: TCustomSynEdit);
procedure TCustomSynMacroRecorder.DoEditorAdded(aEditor: TCustomSynEdit);
begin
if (RecordCommandID <> ecNone) and (RecordShortCut <> 0) then
HookEditor( aEditor, RecordCommandID, 0, RecordShortCut, []);
@ -443,7 +443,7 @@ begin
aEditor.RegisterCommandHandler( {$IFDEF FPC}@{$ENDIF}OnFinishCommand, Self, [hcfFinish]);
end;
procedure TCustomSynMacroRecorder.DoRemoveEditor(aEditor: TCustomSynEdit);
procedure TCustomSynMacroRecorder.DoEditorRemoving(aEditor: TCustomSynEdit);
begin
if RecordCommandID <> ecNone then
UnHookEditor( aEditor, RecordCommandID, RecordShortCut );
@ -779,7 +779,7 @@ var
c: TSynEditorCommand;
begin
c := GetCommandIDs(ord(ACmd));
if (not Assigned(fEditors)) or (c = ecNone) then
if (c = ecNone) then
exit;
if fShortCuts[ACmd] = 0 then begin
@ -787,7 +787,7 @@ begin
exit;
end;
for cEditor := 0 to fEditors.Count -1 do
for cEditor := 0 to EditorCount -1 do
HookEditor(Editors[cEditor], c, AnOldShortCut, fShortCuts[ACmd], []);
end;
@ -797,10 +797,10 @@ var
cEditor: Integer;
begin
c := GetCommandIDs(ord(ACmd));
if (not Assigned(fEditors)) or (c = ecNone) then
if (c = ecNone) then
exit;
for cEditor := 0 to fEditors.Count -1 do
for cEditor := 0 to EditorCount -1 do
UnHookEditor(Editors[cEditor], c, fShortCuts[ACmd]);
end;