SynEdit: Fix completion key handling (catch keys, routed to editor, if typed before completion form could open)

git-svn-id: trunk@35592 -
This commit is contained in:
martin 2012-02-25 13:29:59 +00:00
parent 7e7f7372d5
commit 7bf8c0ebe0
2 changed files with 166 additions and 3 deletions

View File

@ -136,6 +136,9 @@ type
FLongLineHintTime: Integer;
FLongLineHintType: TSynCompletionLongHintType;
FMouseWheelAccumulator: Integer;
procedure DoEditorKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure DoEditorKeyPress(Sender: TObject; var Key: char);
procedure DoEditorUtf8KeyPress(Sender: TObject; var UTF8Key: TUTF8Char);
procedure UTF8KeyPress(var UTF8Key: TUTF8Char); override;
procedure SetCurrentString(const Value: string);
procedure KeyDown(var Key: Word; Shift: TShiftState); override;
@ -923,6 +926,28 @@ begin
Position := Position - 1;
end;
procedure TSynBaseCompletionForm.DoEditorKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (not Visible) or (FCurrentEditor = nil) or (Sender <> FCurrentEditor) then exit;
KeyDown(Key, Shift);
Key := 0;
end;
procedure TSynBaseCompletionForm.DoEditorKeyPress(Sender: TObject; var Key: char);
begin
if (not Visible) or (FCurrentEditor = nil) or (Sender <> FCurrentEditor) then exit;
KeyPress(Key);
Key := #0;
end;
procedure TSynBaseCompletionForm.DoEditorUtf8KeyPress(Sender: TObject; var UTF8Key: TUTF8Char);
begin
if (not Visible) or (FCurrentEditor = nil) or (Sender <> FCurrentEditor) then exit;
UTF8KeyPress(UTF8Key);
UTF8Key := '';
end;
procedure TSynBaseCompletionForm.SDKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
@ -1084,17 +1109,27 @@ end;
procedure TSynBaseCompletionForm.RegisterHandlers(EditOnly: Boolean);
begin
if FCurrentEditor <> nil then
if FCurrentEditor <> nil then begin
FCurrentEditor.RegisterStatusChangedHandler
({$IFDEF FPC}@{$ENDIF}EditorStatusChanged, [scTopLine]);
// Catch Editor events. Some Widgetset may report keys to the editor,
// if the user types faster, then the app can open the form
FCurrentEditor.RegisterBeforeKeyDownHandler(@DoEditorKeyDown);
FCurrentEditor.RegisterBeforeKeyPressHandler(@DoEditorKeyPress);
FCurrentEditor.RegisterBeforeUtf8KeyPressHandler(@DoEditorUtf8KeyPress);
end;
if not EditOnly then
Application.AddOnDeactivateHandler({$IFDEF FPC}@{$ENDIF}AppDeactivated);
end;
procedure TSynBaseCompletionForm.UnRegisterHandlers(EditOnly: Boolean);
begin
if FCurrentEditor <> nil then
if FCurrentEditor <> nil then begin
FCurrentEditor.UnRegisterStatusChangedHandler({$IFDEF FPC}@{$ENDIF}EditorStatusChanged);
FCurrentEditor.UnregisterBeforeKeyDownHandler(@DoEditorKeyDown);
FCurrentEditor.UnregisterBeforeKeyPressHandler(@DoEditorKeyPress);
FCurrentEditor.UnregisterBeforeUtf8KeyPressHandler(@DoEditorUtf8KeyPress);
end;
if not EditOnly then
Application.RemoveOnDeactivateHandler({$IFDEF FPC}@{$ENDIF}AppDeactivated);
end;
@ -1126,12 +1161,13 @@ end;
procedure TSynBaseCompletionForm.SetVisible(Value: Boolean);
begin
if Visible = Value then exit;;
inherited SetVisible(Value);
if Value then
RegisterHandlers
else
UnRegisterHandlers;
inherited SetVisible(Value);
end;
procedure TSynBaseCompletionForm.IncHintLock;

View File

@ -389,6 +389,28 @@ type
);
end;
{ TLazSynKeyDownEventList }
TLazSynKeyDownEventList = Class(TMethodList)
public
procedure CallKeyDownHandlers(Sender: TObject; var Key: Word; Shift: TShiftState);
end;
{ TLazSynKeyPressEventList }
TLazSynKeyPressEventList = Class(TMethodList)
public
procedure CallKeyPressHandlers(Sender: TObject; var Key: char);
end;
{ TLazSynUtf8KeyPressEventList }
TLazSynUtf8KeyPressEventList = Class(TMethodList)
public
procedure CallUtf8KeyPressHandlers(Sender: TObject; var UTF8Key: TUTF8Char);
end;
TSynMouseLinkEvent = procedure (
Sender: TObject; X, Y: Integer; var AllowMouseLink: Boolean) of object;
@ -514,6 +536,9 @@ type
fTSearch: TSynEditSearch;
fHookedCommandHandlers: TList;
FHookedKeyTranslationList: TSynHookedKeyTranslationList;
FKeyDownEventList: TLazSynKeyDownEventList;
FKeyPressEventList: TLazSynKeyPressEventList;
FUtf8KeyPressEventList: TLazSynUtf8KeyPressEventList;
FStatusChangedList: TObject;
FPlugins: TList;
fScrollTimer: TTimer;
@ -968,6 +993,13 @@ type
procedure RegisterStatusChangedHandler(AStatusChangeProc: TStatusChangeEvent; AChanges: TSynStatusChanges);
procedure UnRegisterStatusChangedHandler(AStatusChangeProc: TStatusChangeEvent);
procedure RegisterBeforeKeyDownHandler(AHandlerProc: TKeyEvent);
procedure UnregisterBeforeKeyDownHandler(AHandlerProc: TKeyEvent);
procedure RegisterBeforeKeyPressHandler(AHandlerProc: TKeyPressEvent);
procedure UnregisterBeforeKeyPressHandler(AHandlerProc: TKeyPressEvent);
procedure RegisterBeforeUtf8KeyPressHandler(AHandlerProc: TUTF8KeyPressEvent);
procedure UnregisterBeforeUtf8KeyPressHandler(AHandlerProc: TUTF8KeyPressEvent);
function SearchReplace(const ASearch, AReplace: string;
AOptions: TSynSearchOptions): integer;
function SearchReplaceEx(const ASearch, AReplace: string;
@ -2283,6 +2315,9 @@ begin
FreeAndNil(FStatusChangedList);
FBeautifier := nil;
FreeAndNil(FDefaultBeautifier);
FreeAndNil(FKeyDownEventList);
FreeAndNil(FKeyPressEventList);
FreeAndNil(FUtf8KeyPressEventList);
inherited Destroy;
end;
@ -2600,6 +2635,12 @@ begin
{$IFDEF VerboseKeys}
DebugLn('[TCustomSynEdit.KeyDown] ',dbgs(Key),' ',dbgs(Shift));
{$ENDIF}
// Run even before OnKeyDown
if FKeyDownEventList <> nil then
FKeyDownEventList.CallKeyDownHandlers(Self, Key, Shift);
if Key=0 then exit;
inherited;
if assigned(fMarkupCtrlMouse) then
fMarkupCtrlMouse.UpdateCtrlState(Shift);
@ -2708,6 +2749,12 @@ end;
procedure TCustomSynEdit.UTF8KeyPress(var Key: TUTF8Char);
begin
if Key='' then exit;
// Run even before OnKeyPress
if FUtf8KeyPressEventList <> nil then
FUtf8KeyPressEventList.CallUtf8KeyPressHandlers(Self, Key);
if Key='' then exit;
// don't fire the event if key is to be ignored
if not (sfIgnoreNextChar in fStateFlags) then begin
Include(FStateFlags, sfHideCursor);
@ -2734,6 +2781,12 @@ end;
procedure TCustomSynEdit.KeyPress(var Key: Char);
begin
if Key=#0 then exit;
// Run even before OnKeyPress
if FKeyPressEventList <> nil then
FKeyPressEventList.CallKeyPressHandlers(Self, Key);
if Key=#0 then exit;
// don't fire the event if key is to be ignored
if not (sfIgnoreNextChar in fStateFlags) then begin
Include(FStateFlags, sfHideCursor);
@ -8529,6 +8582,45 @@ begin
TSynStatusChangedHandlerList(FStatusChangedList).Remove(AStatusChangeProc);
end;
procedure TCustomSynEdit.RegisterBeforeKeyDownHandler(AHandlerProc: TKeyEvent);
begin
if FKeyDownEventList = nil then
FKeyDownEventList := TLazSynKeyDownEventList.Create;
FKeyDownEventList.Add(TMethod(AHandlerProc));
end;
procedure TCustomSynEdit.UnregisterBeforeKeyDownHandler(AHandlerProc: TKeyEvent);
begin
if FKeyDownEventList <> nil then
FKeyDownEventList.Remove(TMethod(AHandlerProc));
end;
procedure TCustomSynEdit.RegisterBeforeKeyPressHandler(AHandlerProc: TKeyPressEvent);
begin
if FKeyPressEventList = nil then
FKeyPressEventList := TLazSynKeyPressEventList.Create;
FKeyPressEventList.Add(TMethod(AHandlerProc));
end;
procedure TCustomSynEdit.UnregisterBeforeKeyPressHandler(AHandlerProc: TKeyPressEvent);
begin
if FKeyPressEventList <> nil then
FKeyPressEventList.Remove(TMethod(AHandlerProc));
end;
procedure TCustomSynEdit.RegisterBeforeUtf8KeyPressHandler(AHandlerProc: TUTF8KeyPressEvent);
begin
if FUtf8KeyPressEventList = nil then
FUtf8KeyPressEventList := TLazSynUtf8KeyPressEventList.Create;
FUtf8KeyPressEventList.Add(TMethod(AHandlerProc));
end;
procedure TCustomSynEdit.UnregisterBeforeUtf8KeyPressHandler(AHandlerProc: TUTF8KeyPressEvent);
begin
if FUtf8KeyPressEventList <> nil then
FUtf8KeyPressEventList.Remove(TMethod(AHandlerProc));
end;
procedure TCustomSynEdit.NotifyHookedCommandHandlers(var Command: TSynEditorCommand;
var AChar: TUTF8Char; Data: pointer; ATime: THookedCommandFlag);
var
@ -8793,6 +8885,41 @@ begin
end;
end;
{ TLazSynUtf8KeyPressEventList }
procedure TLazSynUtf8KeyPressEventList.CallUtf8KeyPressHandlers(Sender: TObject;
var UTF8Key: TUTF8Char);
var
i: LongInt;
begin
i:=Count;
while NextDownIndex(i) do
TUTF8KeyPressEvent(Items[i])(Sender, UTF8Key);
end;
{ TLazSynKeyPressEventList }
procedure TLazSynKeyPressEventList.CallKeyPressHandlers(Sender: TObject; var Key: char);
var
i: LongInt;
begin
i:=Count;
while NextDownIndex(i) do
TKeyPressEvent(Items[i])(Sender, Key);
end;
{ TLazSynKeyDownEventList }
procedure TLazSynKeyDownEventList.CallKeyDownHandlers(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
i: LongInt;
begin
i:=Count;
while NextDownIndex(i) do
TKeyEvent(Items[i])(Sender, Key, Shift);
end;
{ TSynStatusChangedHandlerList }
procedure TSynStatusChangedHandlerList.Add(AHandler: TStatusChangeEvent;
Changes: TSynStatusChanges);