EditorOpts: Fixed Keymaps, combo strokes in plugins

git-svn-id: trunk@35406 -
This commit is contained in:
martin 2012-02-17 01:58:06 +00:00
parent ce0c730b46
commit a1ff712f8b
4 changed files with 137 additions and 74 deletions

View File

@ -381,7 +381,10 @@ type
procedure CallHookedKeyTranslationHandlers(Sender: TObject;
Code: word; SState: TShiftState; var Data: pointer;
var IsStartOfCombo: boolean; var Handled: boolean;
var Command: TSynEditorCommand; var ComboKeyStrokes: TSynEditKeyStrokes);
var Command: TSynEditorCommand;
// ComboKeyStrokes decides, either FinishComboOnly, or new stroke
var ComboKeyStrokes: TSynEditKeyStrokes
);
end;
TSynMouseLinkEvent = procedure (
@ -488,7 +491,8 @@ type
fHideSelection: boolean;
fOverwriteCaret: TSynEditCaretType;
fInsertCaret: TSynEditCaretType;
FKeyStrokes, FLastKeyStrokes: TSynEditKeyStrokes;
FKeyStrokes: TSynEditKeyStrokes;
FCurrentComboKeyStrokes: TSynEditKeyStrokes; // Holding info about the keystroke(s) already received for a mult-stroke-combo
FMouseActions, FMouseSelActions, FMouseTextActions: TSynEditMouseInternalActions;
FMouseActionSearchHandlerList: TSynEditMouseActionSearchList;
FMouseActionExecHandlerList: TSynEditMouseActionExecList;
@ -1989,7 +1993,7 @@ begin
fInsertCaret := ctVerticalLine;
fOverwriteCaret := ctBlock;
FKeystrokes := TSynEditKeyStrokes.Create(Self);
FLastKeyStrokes := nil;
FCurrentComboKeyStrokes := nil;
if assigned(Owner) and not (csLoading in Owner.ComponentState) then begin
SetDefaultKeystrokes;
end;
@ -2597,28 +2601,65 @@ begin
inherited;
if assigned(fMarkupCtrlMouse) then
fMarkupCtrlMouse.UpdateCtrlState(Shift);
if Key in [VK_SHIFT, VK_CONTROL, VK_MENU,
VK_LSHIFT, VK_LCONTROL, VK_LMENU,
VK_RSHIFT, VK_RCONTROL, VK_RMENU,
VK_LWIN, VK_RWIN]
then
exit;
Data := nil;
C := #0;
try
IsStartOfCombo := False;
Handled := False;
// If the translations requires Data, memory will be allocated for it via a
// GetMem call. The client must call FreeMem on Data if it is not NIL.
if FLastKeyStrokes = FKeyStrokes then begin
Cmd := KeyStrokes.FindKeycodeEx(Key, Shift, Data, IsStartOfCombo, True);
Handled := Cmd <> ecNone;
end;
// Hooked
if not Handled then
IsStartOfCombo := False;
Handled := False;
// Check 2nd stroke in SynEdit.KeyStrokes
if FCurrentComboKeyStrokes <> nil then begin
// Run hooked first, it might want to "steal" the key(s)
FHookedKeyTranslationList.CallHookedKeyTranslationHandlers(self,
Key, Shift, Data, IsStartOfCombo, Handled, Cmd, FLastKeyStrokes);
Key, Shift, Data, IsStartOfCombo, Handled, Cmd, FCurrentComboKeyStrokes);
if not Handled then begin
Cmd := KeyStrokes.FindKeycodeEx(Key, Shift, Data, IsStartOfCombo, True, FCurrentComboKeyStrokes);
if IsStartOfCombo then
FCurrentComboKeyStrokes := FKeyStrokes;
Handled := (Cmd <> ecNone) or IsStartOfCombo;
end;
if not IsStartOfCombo then begin
FCurrentComboKeyStrokes.ResetKeyCombo;
FCurrentComboKeyStrokes := nil;
end;
end;
assert(Handled or (FCurrentComboKeyStrokes=nil), 'FCurrentComboKeyStrokes<>nil, should be handled');
// Check 1st/single stroke in Hooked KeyStrokes
if not Handled then begin
FCurrentComboKeyStrokes := nil;
FHookedKeyTranslationList.CallHookedKeyTranslationHandlers(self,
Key, Shift, Data, IsStartOfCombo, Handled, Cmd, FCurrentComboKeyStrokes);
if (not IsStartOfCombo) and (FCurrentComboKeyStrokes <> nil) then
FCurrentComboKeyStrokes.ResetKeyCombo; // should not happen
end;
// Check 1st/single stroke in SynEdit.KeyStrokes
if not Handled then begin
FKeyStrokes.ResetKeyCombo;
Cmd := KeyStrokes.FindKeycodeEx(Key, Shift, Data, IsStartOfCombo);
if IsStartOfCombo then
FLastKeyStrokes := FKeyStrokes;
FCurrentComboKeyStrokes := FKeyStrokes;
end;
if Cmd <> ecNone then begin
// Reset FCurrentComboKeyStrokes => no open combo
assert(FCurrentComboKeyStrokes=nil, 'FCurrentComboKeyStrokes<>nil, should be ecNone');
if FCurrentComboKeyStrokes <> nil then
FCurrentComboKeyStrokes.ResetKeyCombo;
FCurrentComboKeyStrokes := nil;
Include(FStateFlags, sfHideCursor);
LastMouseCaret := Point(-1,-1); // includes update cursor
//DebugLn(['[TCustomSynEdit.KeyDown] key translated ',cmd]);
@ -8722,16 +8763,18 @@ procedure TSynHookedKeyTranslationList.CallHookedKeyTranslationHandlers(Sender:
var
i: Integer;
begin
// Finish Combo ?
for i := 0 to Count - 1 do
THookedKeyTranslationEvent(Items[i])(Sender, Code, SState, Data,
IsStartOfCombo, Handled, Command, True, ComboKeyStrokes);
if Handled then
exit;
// New Stroke ?
for i := 0 to Count - 1 do
THookedKeyTranslationEvent(Items[i])(Sender, Code, SState, Data,
IsStartOfCombo, Handled, Command, False, ComboKeyStrokes);
if ComboKeyStrokes <> nil then begin
// Finish Combo
for i := 0 to Count - 1 do
THookedKeyTranslationEvent(Items[i])(Sender, Code, SState, Data,
IsStartOfCombo, Handled, Command, True, ComboKeyStrokes);
end
else begin
// New Stroke
for i := 0 to Count - 1 do
THookedKeyTranslationEvent(Items[i])(Sender, Code, SState, Data,
IsStartOfCombo, Handled, Command, False, ComboKeyStrokes);
end;
end;
{ TSynStatusChangedHandlerList }

View File

@ -357,7 +357,8 @@ type
function FindKeycode(Code: word; SS: TShiftState): integer;
function FindKeycodeEx(Code: word; SS: TShiftState; var Data: pointer;
out IsStartOfCombo: boolean;
FinishComboOnly: Boolean = False): TSynEditorCommand;
FinishComboOnly: Boolean = False;
ComboStart: TSynEditKeyStrokes = nil): TSynEditorCommand;
procedure ResetKeyCombo;
function FindShortcut(SC: TShortcut): integer;
function FindShortcut2(SC, SC2: TShortcut): integer;
@ -921,34 +922,70 @@ begin
end;
end;
function TSynEditKeyStrokes.FindKeycodeEx(Code: word; SS: TShiftState; var Data: pointer; out
IsStartOfCombo: boolean; FinishComboOnly: Boolean = False): TSynEditorCommand;
function TSynEditKeyStrokes.FindKeycodeEx(Code: word; SS: TShiftState; var Data: pointer;
out IsStartOfCombo: boolean;
FinishComboOnly: Boolean; ComboStart: TSynEditKeyStrokes): TSynEditorCommand;
var
i: integer;
LK: Word;
LS: TShiftState;
CurComboStart: TSynEditKeyStrokes;
{$IFNDEF SYN_COMPILER_3_UP}
const
VK_ACCEPT = $30;
{$ENDIF}
begin
i := FindKeycode2(fLastKey, fLastShiftState, Code, SS);
if (i < 0) and not FinishComboOnly then
i := FindKeycode(Code, SS);
if i >= 0 then
Result := Items[i].Command
else
Result := ecNone;
(* if FinishComboOnly=True then ComboStart are the KeyStrokes, which have the
already received keys.
If several TSynEditKeyStrokes have combos, starting with the same key(s)
only one needs to keep the info. The others chek, if they have a matching combo
*)
if (Result = ecNone) and (Code >= VK_ACCEPT) and (Code <= VK_SCROLL) and
(FindKeycode2Start(Code, SS) >= 0) and not FinishComboOnly then
Result := ecNone;
IsStartOfCombo := False;
if ComboStart = nil then
CurComboStart := self
else
CurComboStart := ComboStart;
if CurComboStart.fLastKey <> 0 then begin
// Try to finish the combo
i := FindKeycode2(CurComboStart.fLastKey, CurComboStart.fLastShiftState, Code, SS);
if (i >= 0) then begin
Result := Items[i].Command;
CurComboStart.ResetKeyCombo;
exit;
end;
end;
if FinishComboOnly then
exit;
// Check for single stroke
i := FindKeycode(Code, SS);
if i >= 0 then begin
Result := Items[i].Command;
ResetKeyCombo;
if (ComboStart <> nil) and (ComboStart <> self) then
ComboStart.ResetKeyCombo;
exit;
end;
if (FindKeycode2Start(Code, SS) >= 0) and not FinishComboOnly then
begin
fLastKey := Code;
fLastShiftState := SS;
IsStartOfCombo := True;
end else begin
fLastKey := 0;
fLastShiftState := [];
IsStartOfCombo := False;
end;
// Now this is the start of combo
if (ComboStart <> nil) and (ComboStart <> self) then
ComboStart.ResetKeyCombo;
end
else begin
// Nothing was found.
// Keep CurComboStart.fLastKey. It may be ued by another TSynEditKeyStrokes
if (ComboStart <> self) then
ResetKeyCombo; // reset self, if not CurComboStart
end
end;
procedure TSynEditKeyStrokes.ResetKeyCombo;

View File

@ -1326,38 +1326,30 @@ begin
exit;
keys := nil;
if Mode = spseSelecting then
keys := FKeystrokesSelecting;
if Mode = spseEditing then begin
if CurrentCell < 0 then begin
keys := FKeyStrokesOffCell;
FKeyStrokes.ResetKeyCombo;
end
else begin
if CurrentCell < 0 then
keys := FKeyStrokesOffCell
else
keys := FKeyStrokes;
FKeyStrokesOffCell.ResetKeyCombo;
end;
end;
if keys = nil then exit;
if (FinishComboOnly and (ComboKeyStrokes <> keys)) then begin
keys.ResetKeyCombo;
exit;
end;
IsStartOfCombo := False;
try
keys.UsePluginOffset := True;
Command := keys.FindKeycodeEx(Code, SState, Data, IsStartOfCombo,
FinishComboOnly);
if not FinishComboOnly then
keys.ResetKeyCombo;
Command := keys.FindKeycodeEx(Code, SState, Data, IsStartOfCombo, FinishComboOnly, ComboKeyStrokes);
finally
keys.UsePluginOffset := False;
end;
Handled := (Command <> ecNone) or IsStartOfCombo;
if Handled then begin
if IsStartOfCombo then
ComboKeyStrokes := keys;
end;
end;
procedure TSynPluginSyncroEdit.ProcessSynCommand(Sender: TObject; AfterProcessing: boolean;

View File

@ -199,32 +199,23 @@ begin
if (not Active) or Handled then
exit;
if CurrentCell < 0 then begin
keys := FKeyStrokesOffCell;
FKeyStrokes.ResetKeyCombo;
end
else begin
if CurrentCell < 0 then
keys := FKeyStrokesOffCell
else
keys := FKeyStrokes;
FKeyStrokesOffCell.ResetKeyCombo;
end;
if (FinishComboOnly and (ComboKeyStrokes <> keys)) then begin
keys.ResetKeyCombo;
exit;
end;
IsStartOfCombo := False;
try
keys.UsePluginOffset := True;
Command := keys.FindKeycodeEx(Code, SState, Data, IsStartOfCombo,
FinishComboOnly);
if not FinishComboOnly then
keys.ResetKeyCombo;
Command := keys.FindKeycodeEx(Code, SState, Data, IsStartOfCombo, FinishComboOnly, ComboKeyStrokes);
finally
keys.UsePluginOffset := False;
end;
Handled := (Command <> ecNone) or IsStartOfCombo;
if Handled then begin
if IsStartOfCombo then
ComboKeyStrokes := keys;
end;
end;
procedure TSynPluginTemplateEdit.ProcessSynCommand(Sender: TObject; AfterProcessing: boolean;