lazarus/ide/keymapping.pp
lazarus c9e180acac TPanel implemented.
Basic graphic primitives split into GraphType package, so that we can
reference it from interface (GTK, Win32) units.
New Frame3d canvas method that uses native (themed) drawing (GTK only).
New overloaded Canvas.TextRect method.
LCLLinux and Graphics was split, so a bunch of files had to be modified.

git-svn-id: trunk@653 -
2002-02-03 00:24:02 +00:00

1197 lines
40 KiB
ObjectPascal

{
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
Author: Mattias Gaertner
Abstract:
Contains classes to store key-command relationships, can update
TSynEditKeyStrokes and provides a dialog for editing a single
commandkey.
ToDo:
}
unit keymapping;
{$mode objfpc}{$H+}
interface
uses
LCLLinux,
LCLType,
Forms, Classes, SysUtils, Buttons, LResources, StdCtrls, Controls,
SynEdit, SynEditKeyCmds, XMLCfg, Dialogs;
const
// editor commands constants. see syneditkeycmds.pp for more
ecFind = ecUserFirst + 1;
ecFindAgain = ecUserFirst + 2;
ecFindNext = ecFindAgain;
ecReplace = ecUserFirst + 3;
ecFindProcedureDefinition = ecUserFirst + 4;
ecFindProcedureMethod = ecUserFirst + 5;
ecGotoLineNumber = ecUserFirst + 6;
ecNextEditor = ecUserFirst + 7;
ecPrevEditor = ecUserFirst + 8;
ecPeriod = ecUserFirst + 9;
ecFindPrevious = ecUserFirst + 10;
ecFindInFiles = ecUserFirst + 11;
ecJumpBack = ecUserFirst + 12;
ecJumpForward = ecUserFirst + 13;
ecAddJumpPoint = ecUserFirst + 14;
ecViewJumpHistory = ecUserFirst + 15;
ecFindDeclaration = ecUserFirst + 20;
ecFindBlockOtherEnd = ecUserFirst + 21;
ecFindBlockStart = ecUserFirst + 22;
ecWordCompletion = ecUserFirst + 100;
ecCompleteCode = ecUserFirst + 101;
ecIdentCompletion = ecUserFirst + 102;
ecSyntaxCheck = ecUserFirst + 103;
ecGuessUnclosedBlock = ecUserFirst + 104;
ecSave = ecUserFirst + 200;
ecOpen = ecSave + 1;
ecClose = ecOpen + 1;
ecBuild = ecClose + 1;
ecRun = ecBuild + 1;
ecPause = ecRun + 1;
ecStepInto = ecPause + 1;
ecStepOver = ecStepInto + 1;
ecRunToCursor = ecStepOver + 1;
ecStopProgram = ecRunToCursor + 1;
ecBuildAll = ecStopProgram + 1;
ecBuildLazarus = ecBuildAll + 1;
ecJumpToEditor = ecUserFirst + 300;
ecToggleFormUnit = ecUserFirst + 301;
ecExtToolFirst = ecUserFirst + 400;
ecExtToolLast = ecUserFirst + 499;
ecGotoEditor1 = ecUserFirst + 2000;
ecGotoEditor2 = ecGotoEditor1 + 1;
ecGotoEditor3 = ecGotoEditor2 + 1;
ecGotoEditor4 = ecGotoEditor3 + 1;
ecGotoEditor5 = ecGotoEditor4 + 1;
ecGotoEditor6 = ecGotoEditor5 + 1;
ecGotoEditor7 = ecGotoEditor6 + 1;
ecGotoEditor8 = ecGotoEditor7 + 1;
ecGotoEditor9 = ecGotoEditor8 + 1;
ecGotoEditor0 = ecGotoEditor9 + 1;
type
//---------------------------------------------------------------------------
// class for storing the keys of a single command (key-command relationship)
TKeyCommandRelation = class
private
public
Name:ShortString;
Command:TSynEditorCommand; // see the ecXXX constants above
Key1:word;
Shift1:TShiftState;
Key2:word;
Shift2:TShiftState;
constructor Create(AName:ShortString;ACommand:TSynEditorCommand;
AKey1:Word;AShift1:TShiftState;AKey2:Word;AShift2:TShiftState);
end;
//---------------------------------------------------------------------------
// class for a list of key - command relations
TKeyCommandRelationList = class
private
fRelations:TList;
fExtToolCount: integer;
function GetRelation(Index:integer):TKeyCommandRelation;
function Add(Name:shortstring;Command:TSynEditorCommand;
Key1:Word; Shift1:TShiftState;
Key2:Word; Shift2:TShiftState):integer;
function ShiftStateToStr(Shift:TShiftState):AnsiString;
procedure SetExtToolCount(NewCount: integer);
public
function Count:integer;
function Find(AKey:Word; AShiftState:TShiftState):TKeyCommandRelation;
function FindByCommand(ACommand:TSynEditorCommand):TKeyCommandRelation;
function LoadFromXMLConfig(XMLConfig:TXMLConfig; Prefix:AnsiString):boolean;
function SaveToXMLConfig(XMLConfig:TXMLConfig; Prefix:AnsiString):boolean;
procedure AssignTo(ASynEditKeyStrokes:TSynEditKeyStrokes);
constructor Create;
destructor Destroy; override;
property ExtToolCount: integer read fExtToolCount write SetExtToolCount;
property Relations[Index:integer]:TKeyCommandRelation read GetRelation;
end;
//---------------------------------------------------------------------------
// form for editing one command - key relationship
TKeyMappingEditForm = class(TForm)
OkButton: TButton;
CancelButton: TButton;
CommandLabel: TLabel;
Key1GroupBox: TGroupBox;
Key1CtrlCheckBox: TCheckBox;
Key1AltCheckBox: TCheckBox;
Key1ShiftCheckBox: TCheckBox;
Key1KeyComboBox: TComboBox;
Key1GrabButton: TButton;
Key2GroupBox: TGroupBox;
Key2CtrlCheckBox: TCheckBox;
Key2AltCheckBox: TCheckBox;
Key2ShiftCheckBox: TCheckBox;
Key2KeyComboBox: TComboBox;
Key2GrabButton: TButton;
procedure OkButtonClick(Sender: TObject);
procedure CancelButtonClick(Sender: TObject);
procedure Key1GrabButtonClick(Sender: TObject);
procedure Key2GrabButtonClick(Sender: TObject);
procedure FormKeyUp(Sender: TObject; var Key: Word; Shift:TShiftState);
private
GrabbingKey: integer; // 0=none, 1=Default key, 2=Alternative key
procedure ActivateGrabbing(AGrabbingKey: integer);
procedure DeactivateGrabbing;
procedure SetComboBox(AComboBox: TComboBox; AValue: string);
public
constructor Create(AOwner:TComponent); override;
KeyCommandRelationList:TKeyCommandRelationList;
KeyIndex:integer;
end;
function KeyAndShiftStateToStr(Key:Word; ShiftState:TShiftState):AnsiString;
function ShowKeyMappingEditForm(Index:integer;
AKeyCommandRelationList:TKeyCommandRelationList):TModalResult;
function KeyStrokesConsistencyErrors(ASynEditKeyStrokes:TSynEditKeyStrokes;
Protocol: TStrings; var Index1,Index2:integer):integer;
function EditorCommandToDescriptionString(cmd: TSynEditorCommand):AnsiString;
function StrToVKCode(s: string): integer;
var KeyMappingEditForm: TKeyMappingEditForm;
implementation
function StrToVKCode(s: string): integer;
var i: integer;
begin
if copy(s,1,6)='Word(''' then
Result:=StrToIntDef(copy(s,7,length(s)-8),VK_UNKNOWN)
else if s<>'none' then begin
for i:=1 to 200 do
if KeyAndShiftStateToStr(i,[])=s then
Result:=i;
end else
Result:=VK_UNKNOWN;
end;
function ShowKeyMappingEditForm(Index:integer;
AKeyCommandRelationList:TKeyCommandRelationList):TModalResult;
procedure InitComboBox(AComboBox: TComboBox; AKey: integer);
var s: string;
i: integer;
begin
s:=KeyAndShiftStateToStr(AKey,[]);
i:=AComboBox.Items.IndexOf(s);
if i>=0 then
AComboBox.ItemIndex:=i
else if lowercase(copy(s,1,5))='word(' then begin
AComboBox.Items.Add(s);
AComboBox.ItemIndex:=AComboBox.Items.IndexOf(s);
end else
AComboBox.ItemIndex:=0;
end;
begin
Result:=mrCancel;
if KeyMappingEditForm<>nil then exit;
KeyMappingEditForm:=TKeyMappingEditForm.Create(Application);
with KeyMappingEditForm do
try
KeyCommandRelationList:=AKeyCommandRelationList;
KeyIndex:=Index;
Caption:='Edit Keys';
with KeyCommandRelationList.Relations[Index] do begin
CommandLabel.Caption:='Command: '+Name;
if Key1<>VK_UNKNOWN then begin
Key1CtrlCheckBox.Checked:=ssCtrl in Shift1;
Key1AltCheckBox.Checked:=ssAlt in Shift1;
Key1ShiftCheckBox.Checked:=ssShift in Shift1;
InitComboBox(Key1KeyComboBox,Key1);
end;
if Key2<>VK_UNKNOWN then begin
Key2CtrlCheckBox.Checked:=ssCtrl in Shift2;
Key2AltCheckBox.Checked:=ssAlt in Shift2;
Key2ShiftCheckBox.Checked:=ssShift in Shift2;
InitComboBox(Key2KeyComboBox,Key2);
end;
end;
Result:=ShowModal;
finally
Free;
KeyMappingEditForm:=nil;
end;
end;
function EditorCommandToDescriptionString(cmd: TSynEditorCommand):AnsiString;
begin
case cmd of
ecNone: Result:= 'None';
ecLeft: Result:= 'Left';
ecRight: Result:= 'Right';
ecUp: Result:= 'Up';
ecDown: Result:= 'Down';
ecWordLeft: Result:= 'WordLeft';
ecWordRight: Result:= 'WordRight';
ecLineStart: Result:= 'LineStart';
ecLineEnd: Result:= 'LineEnd';
ecPageUp: Result:= 'PageUp';
ecPageDown: Result:= 'PageDown';
ecPageLeft: Result:= 'PageLeft';
ecPageRight: Result:= 'PageRight';
ecPageTop: Result:= 'PageTop';
ecPageBottom: Result:= 'PageBottom';
ecEditorTop: Result:= 'EditorTop';
ecEditorBottom: Result:= 'EditorBottom';
ecGotoXY: Result:= 'GotoXY';
ecSelLeft: Result:= 'SelLeft';
ecSelRight: Result:= 'SelRight';
ecSelUp: Result:= 'SelUp';
ecSelDown: Result:= 'SelDown';
ecSelWordLeft: Result:= 'SelWordLeft';
ecSelWordRight: Result:= 'SelWordRight';
ecSelLineStart: Result:= 'SelLineStart';
ecSelLineEnd: Result:= 'SelLineEnd';
ecSelPageUp: Result:= 'SelPageUp';
ecSelPageDown: Result:= 'SelPageDown';
ecSelPageLeft: Result:= 'SelPageLeft';
ecSelPageRight: Result:= 'SelPageRight';
ecSelPageTop: Result:= 'SelPageTop';
ecSelPageBottom: Result:= 'SelPageBottom';
ecSelEditorTop: Result:= 'SelEditorTop';
ecSelEditorBottom: Result:= 'SelEditorBottom';
ecSelGotoXY: Result:= 'SelGotoXY';
ecSelectAll: Result:= 'SelectAll';
ecDeleteLastChar: Result:= 'DeleteLastChar';
ecDeleteChar: Result:= 'DeleteChar';
ecDeleteWord: Result:= 'DeleteWord';
ecDeleteLastWord: Result:= 'DeleteLastWord';
ecDeleteBOL: Result:= 'DeleteBOL';
ecDeleteEOL: Result:= 'DeleteEOL';
ecDeleteLine: Result:= 'DeleteLine';
ecClearAll: Result:= 'ClearAll';
ecLineBreak: Result:= 'LineBreak';
ecInsertLine: Result:= 'InsertLine';
ecChar: Result:= 'Char';
ecImeStr: Result:= 'ImeStr';
ecUndo: Result:= 'Undo';
ecRedo: Result:= 'Redo';
ecCut: Result:= 'Cut';
ecCopy: Result:= 'Copy';
ecPaste: Result:= 'Paste';
ecScrollUp: Result:= 'ScrollUp';
ecScrollDown: Result:= 'ScrollDown';
ecScrollLeft: Result:= 'ScrollLeft';
ecScrollRight: Result:= 'ScrollRight';
ecInsertMode: Result:= 'InsertMode';
ecOverwriteMode: Result:= 'OverwriteMode';
ecToggleMode: Result:= 'ToggleMode';
ecBlockIndent: Result:= 'BlockIndent';
ecBlockUnindent: Result:= 'BlockUnindent';
ecTab: Result:= 'Tab';
ecShiftTab: Result:= 'ShiftTab';
ecMatchBracket: Result:= 'MatchBracket';
ecNormalSelect: Result:= 'NormalSelect';
ecColumnSelect: Result:= 'ColumnSelect';
ecLineSelect: Result:= 'LineSelect';
ecAutoCompletion: Result:= 'AutoCompletion';
ecUserFirst: Result:= 'UserFirst';
ecGotoMarker0: Result:= 'GotoMarker0';
ecGotoMarker1: Result:= 'GotoMarker1';
ecGotoMarker2: Result:= 'GotoMarker2';
ecGotoMarker3: Result:= 'GotoMarker3';
ecGotoMarker4: Result:= 'GotoMarker4';
ecGotoMarker5: Result:= 'GotoMarker5';
ecGotoMarker6: Result:= 'GotoMarker6';
ecGotoMarker7: Result:= 'GotoMarker7';
ecGotoMarker8: Result:= 'GotoMarker8';
ecGotoMarker9: Result:= 'GotoMarker9';
ecSetMarker0: Result:= 'SetMarker0';
ecSetMarker1: Result:= 'SetMarker1';
ecSetMarker2: Result:= 'SetMarker2';
ecSetMarker3: Result:= 'SetMarker3';
ecSetMarker4: Result:= 'SetMarker4';
ecSetMarker5: Result:= 'SetMarker5';
ecSetMarker6: Result:= 'SetMarker6';
ecSetMarker7: Result:= 'SetMarker7';
ecSetMarker8: Result:= 'SetMarker8';
ecSetMarker9: Result:= 'SetMarker9';
ecFind: Result:= 'Find text';
ecFindNext: Result:= 'Find next';
ecFindPrevious: Result:= 'Find previous';
ecFindInFiles: Result:= 'Find in files';
ecReplace: Result:= 'Replace text';
ecFindProcedureDefinition: Result:= 'find procedure definition';
ecFindProcedureMethod: Result:= 'find procedure method';
ecGotoLineNumber: Result:= 'goto line number';
ecJumpBack: Result:='jump back';
ecJumpForward: Result:='jump forward';
ecAddJumpPoint: Result:='add jump point';
ecViewJumpHistory: Result:='view jump history';
ecFindDeclaration: Result:='find declaration';
ecFindBlockOtherEnd: Result:='find block other end';
ecFindBlockStart: Result:='find block start';
ecNextEditor: Result:= 'next editor';
ecPrevEditor: Result:= 'previous editor';
ecPeriod: Result:= 'period';
ecWordCompletion: Result:= 'word completion';
ecCompleteCode: Result:= 'complete code';
ecIdentCompletion: Result:= 'identifier completion';
ecSyntaxCheck: Result:='syntax check';
ecGuessUnclosedBlock: Result:='guess unclosed block';
ecSave: Result:= 'save';
ecOpen: Result:= 'open';
ecClose: Result:= 'close';
ecBuild: Result:= 'build program/project';
ecBuildAll: Result:= 'build all files of program/project';
ecBuildLazarus: Result:= 'build lazarus';
ecRun: Result:= 'run program';
ecPause: Result:= 'pause program';
ecStepInto: Result:= 'step into';
ecStepOver: Result:= 'step over';
ecRunToCursor: Result:= 'run to cursor';
ecStopProgram: Result:= 'stop program';
ecJumpToEditor: Result:='jump to editor';
ecToggleFormUnit: Result:='toggle between form and unit';
ecGotoEditor1: Result:='goto editor 1';
ecGotoEditor2: Result:='goto editor 2';
ecGotoEditor3: Result:='goto editor 3';
ecGotoEditor4: Result:='goto editor 4';
ecGotoEditor5: Result:='goto editor 5';
ecGotoEditor6: Result:='goto editor 6';
ecGotoEditor7: Result:='goto editor 7';
ecGotoEditor8: Result:='goto editor 8';
ecGotoEditor9: Result:='goto editor 9';
ecGotoEditor0: Result:='goto editor 10';
ecExtToolFirst..ecExtToolLast:
Result:='external tool '+IntToStr(cmd-ecExtToolFirst+1);
else
Result:='unknown editor command';
end;
end;
function KeyStrokesConsistencyErrors(ASynEditKeyStrokes:TSynEditKeyStrokes;
Protocol: TStrings; var Index1,Index2:integer):integer;
// 0 = ok, no errors
// >0 number of errors found
var a,b:integer;
Key1,Key2:TSynEditKeyStroke;
begin
Result:=0;
for a:=0 to ASynEditKeyStrokes.Count-1 do begin
Key1:=ASynEditKeyStrokes[a];
for b:=a+1 to ASynEditKeyStrokes.Count-1 do begin
Key2:=ASynEditKeyStrokes[b];
if (Key1.Command<>Key2.Command)
and (Key1.Key<>VK_UNKNOWN)
and (Key1.Key=Key2.Key) and (Key1.Shift=Key2.Shift) then begin
if (Key1.Key2=VK_UNKNOWN) or (Key2.Key2=VK_UNKNOWN)
or ((Key1.Key2=Key2.Key2) and (Key1.Shift2=Key2.Shift2)) then begin
// consistency error
if Result=0 then begin
Index1:=a;
Index2:=b;
end;
inc(Result);
if Protocol<>nil then begin
Protocol.Add('Conflict '+IntToStr(Result));
Protocol.Add(' command1 "'
+EditorCommandToDescriptionString(Key1.Command)+'"'
+'->'+KeyAndShiftStateToStr(Key1.Key,Key1.Shift));
Protocol.Add(' conflicts with ');
Protocol.Add(' command2 "'
+EditorCommandToDescriptionString(Key2.Command)+'"'
+'->'+KeyAndShiftStateToStr(Key2.Key,Key2.Shift)
);
Protocol.Add('');
end;
end;
end;
end;
end;
end;
function KeyAndShiftStateToStr(Key:Word; ShiftState:TShiftState):AnsiString;
begin
Result:='';
if ssCtrl in ShiftState then Result:=Result+'+Ctrl';
if ssAlt in ShiftState then Result:=Result+'+Alt';
if ssShift in ShiftState then Result:=Result+'+Shift';
if Result<>'' then
Result:=copy(Result,2,length(Result)-1)+'+';
case Key of
VK_UNKNOWN :Result:=Result+'Unknown';
VK_LBUTTON :Result:=Result+'Mouse Button Left';
VK_RBUTTON :Result:=Result+'Mouse Button Right';
VK_CANCEL :Result:=Result+'Cancel';
VK_MBUTTON :Result:=Result+'Mouse Button Middle';
VK_BACK :Result:=Result+'Backspace';
VK_TAB :Result:=Result+'Tab';
VK_CLEAR :Result:=Result+'Clear';
VK_RETURN :Result:=Result+'Return';
VK_SHIFT :Result:=Result+'Shift';
VK_CONTROL :Result:=Result+'Control';
VK_MENU :Result:=Result+'Menu';
VK_PAUSE :Result:=Result+'Pause';
VK_CAPITAL :Result:=Result+'Capital';
VK_KANA :Result:=Result+'Kana';
// VK_HANGUL :Result:=Result+'Hangul';
VK_JUNJA :Result:=Result+'Junja';
VK_FINAL :Result:=Result+'Final';
VK_HANJA :Result:=Result+'Hanja';
// VK_KANJI :Result:=Result+'Kanji';
VK_ESCAPE :Result:=Result+'Escape';
VK_CONVERT :Result:=Result+'Convert';
VK_NONCONVERT :Result:=Result+'Nonconvert';
VK_ACCEPT :Result:=Result+'Accept';
VK_MODECHANGE :Result:=Result+'Mode Change';
VK_SPACE :Result:=Result+'Space';
VK_PRIOR :Result:=Result+'Prior';
VK_NEXT :Result:=Result+'Next';
VK_END :Result:=Result+'End';
VK_HOME :Result:=Result+'Home';
VK_LEFT :Result:=Result+'Left';
VK_UP :Result:=Result+'Up';
VK_RIGHT :Result:=Result+'Right';
VK_DOWN :Result:=Result+'Down';
VK_SELECT :Result:=Result+'Select';
VK_PRINT :Result:=Result+'Print';
VK_EXECUTE :Result:=Result+'Execute';
VK_SNAPSHOT :Result:=Result+'Snapshot';
VK_INSERT :Result:=Result+'Insert';
VK_DELETE :Result:=Result+'Delete';
VK_HELP :Result:=Result+'Help';
VK_0..VK_9 :Result:=Result+IntToStr(Key-VK_0);
VK_A..VK_Z :Result:=Result+chr(ord('A')+Key-VK_A);
VK_LWIN :Result:=Result+'left windows key';
VK_RWIN :Result:=Result+'right windows key';
VK_APPS :Result:=Result+'application key';
VK_NUMPAD0..VK_NUMPAD9:Result:=Result+'Numpad '+IntToStr(Key-VK_NUMPAD0);
VK_MULTIPLY :Result:=Result+'*';
VK_ADD :Result:=Result+'+';
VK_SEPARATOR :Result:=Result+'|';
VK_SUBTRACT :Result:=Result+'-';
VK_DECIMAL :Result:=Result+'.';
VK_DIVIDE :Result:=Result+'/';
VK_F1..VK_F24 :Result:=Result+'F'+IntToStr(Key-VK_F1+1);
VK_NUMLOCK :Result:=Result+'Numlock';
VK_SCROLL :Result:=Result+'Scroll';
VK_EQUAL :Result:=Result+'=';
VK_COMMA :Result:=Result+',';
VK_POINT :Result:=Result+'.';
VK_SLASH :Result:=Result+'/';
else
Result:=Result+'Word('''+IntToStr(Key)+''')';
end;
end;
{ TKeyMappingEditForm }
constructor TKeyMappingEditForm.Create(AOwner:TComponent);
var a:integer;
s:AnsiString;
begin
inherited Create(AOwner);
if LazarusResources.Find(ClassName)=nil then begin
SetBounds((Screen.Width-200) div 2,(Screen.Height-270) div 2,216,310);
Caption:='Edit keys for command';
OnKeyUp:=@FormKeyUp;
OkButton:=TButton.Create(Self);
with OkButton do begin
Name:='OkButton';
Parent:=Self;
Caption:='Ok';
Left:=15;
Top:=Self.ClientHeight-Height-15;
Width:=80;
OnClick:=@OkButtonClick;
Show;
end;
CancelButton:=TButton.Create(Self);
with CancelButton do begin
Name:='CancelButton';
Parent:=Self;
Caption:='Cancel';
Left:=125;
Top:=OkButton.Top;
Width:=OkButton.Width;
OnClick:=@CancelButtonClick;
Show;
end;
CommandLabel:=TLabel.Create(Self);
with CommandLabel do begin
Name:='CommandLabel';
Parent:=Self;
Caption:='Command';
Left:=5;
Top:=5;
Width:=Self.ClientWidth-Left-Left;
Height:=20;
Show;
end;
Key1GroupBox:=TGroupBox.Create(Self);
with Key1GroupBox do begin
Name:='Key1GroupBox';
Parent:=Self;
Caption:='Key';
Left:=5;
Top:=CommandLabel.Top+CommandLabel.Height+8;
Width:=Self.ClientWidth-Left-Left;
Height:=110;
Show;
end;
Key1CtrlCheckBox:=TCheckBox.Create(Self);
with Key1CtrlCheckBox do begin
Name:='Key1CtrlCheckBox';
Parent:=Key1GroupBox;
Caption:='Ctrl';
Left:=5;
Top:=2;
Width:=55;
Height:=20;
Show;
end;
Key1AltCheckBox:=TCheckBox.Create(Self);
with Key1AltCheckBox do begin
Name:='Key1AltCheckBox';
Parent:=Key1GroupBox;
Caption:='Alt';
Left:=Key1CtrlCheckBox.Left+Key1CtrlCheckBox.Width+10;
Top:=Key1CtrlCheckBox.Top;
Height:=20;
Width:=Key1CtrlCheckBox.Width;
Show;
end;
Key1ShiftCheckBox:=TCheckBox.Create(Self);
with Key1ShiftCheckBox do begin
Name:='Key1ShiftCheckBox';
Parent:=Key1GroupBox;
Caption:='Shift';
Left:=Key1AltCheckBox.Left+Key1AltCheckBox.Width+10;
Top:=Key1CtrlCheckBox.Top;
Height:=20;
Width:=Key1CtrlCheckBox.Width;
Show;
end;
Key1KeyComboBox:=TComboBox.Create(Self);
with Key1KeyComboBox do begin
Name:='Key1KeyComboBox';
Parent:=Key1GroupBox;
Left:=5;
Top:=Key1CtrlCheckBox.Top+Key1CtrlCheckBox.Height+5;
Width:=190;
Items.BeginUpdate;
Items.Add('none');
for a:=1 to 145 do begin
s:=KeyAndShiftStateToStr(a,[]);
if lowercase(copy(s,1,5))<>'word(' then
Items.Add(s);
end;
Items.EndUpdate;
ItemIndex:=0;
Show;
end;
Key1GrabButton:=TButton.Create(Self);
with Key1GrabButton do begin
Parent:=Key1GroupBox;
Left:=5;
Top:=Key1KeyComboBox.Top+Key1KeyComboBox.Height+5;
Width:=Key1KeyComboBox.Width;
Height:=25;
Caption:='Grab Key';
Name:='Key1GrabButton';
OnClick:=@Key1GrabButtonClick;
Show;
end;
Key2GroupBox:=TGroupBox.Create(Self);
with Key2GroupBox do begin
Name:='Key2GroupBox';
Parent:=Self;
Caption:='Alternative Key';
Left:=5;
Top:=Key1GroupBox.Top+Key1GroupBox.Height+8;
Width:=Key1GroupBox.Width;
Height:=110;
Show;
end;
Key2CtrlCheckBox:=TCheckBox.Create(Self);
with Key2CtrlCheckBox do begin
Name:='Key2CtrlCheckBox';
Parent:=Key2GroupBox;
Caption:='Ctrl';
Left:=5;
Top:=2;
Width:=55;
Height:=20;
Show;
end;
Key2AltCheckBox:=TCheckBox.Create(Self);
with Key2AltCheckBox do begin
Name:='Key2AltCheckBox';
Parent:=Key2GroupBox;
Caption:='Alt';
Left:=Key2CtrlCheckBox.Left+Key2CtrlCheckBox.Width+10;
Top:=Key2CtrlCheckBox.Top;
Height:=20;
Width:=Key2CtrlCheckBox.Width;
Show;
end;
Key2ShiftCheckBox:=TCheckBox.Create(Self);
with Key2ShiftCheckBox do begin
Name:='Key2ShiftCheckBox';
Parent:=Key2GroupBox;
Caption:='Shift';
Left:=Key2AltCheckBox.Left+Key2AltCheckBox.Width+10;
Top:=Key2CtrlCheckBox.Top;
Height:=20;
Width:=Key2CtrlCheckBox.Width;
Show;
end;
Key2KeyComboBox:=TComboBox.Create(Self);
with Key2KeyComboBox do begin
Name:='Key2KeyComboBox';
Parent:=Key2GroupBox;
Left:=5;
Top:=Key2CtrlCheckBox.Top+Key2CtrlCheckBox.Height+5;
Width:=190;
Items.BeginUpdate;
Items.Add('none');
for a:=1 to 145 do begin
s:=KeyAndShiftStateToStr(a,[]);
if lowercase(copy(s,1,5))<>'word(' then
Items.Add(s);
end;
Items.EndUpdate;
ItemIndex:=0;
Show;
end;
Key2GrabButton:=TButton.Create(Self);
with Key2GrabButton do begin
Parent:=Key2GroupBox;
Left:=5;
Top:=Key2KeyComboBox.Top+Key2KeyComboBox.Height+5;
Width:=Key2KeyComboBox.Width;
Height:=25;
Caption:='Grab Key';
Name:='Key2GrabButton';
OnClick:=@Key2GrabButtonClick;
Show;
end;
end;
GrabbingKey:=0;
end;
procedure TKeyMappingEditForm.OkButtonClick(Sender:TObject);
var NewKey1,NewKey2:integer;
NewShiftState1,NewShiftState2:TShiftState;
ACaption,AText:AnsiString;
DummyRelation:TKeyCommandRelation;
begin
NewKey1:=VK_UNKNOWN;
NewShiftState1:=[];
NewKey2:=VK_UNKNOWN;
NewShiftState2:=[];
NewKey1:=StrToVKCode(Key1KeyComboBox.Text);
if NewKey1<>VK_UNKNOWN then begin
if Key1CtrlCheckBox.Checked then include(NewShiftState1,ssCtrl);
if Key1AltCheckBox.Checked then include(NewShiftState1,ssAlt);
if Key1ShiftCheckBox.Checked then include(NewShiftState1,ssShift);
end;
DummyRelation:=KeyCommandRelationList.Find(NewKey1,NewShiftState1);
if (DummyRelation<>nil)
and (DummyRelation<>KeyCommandRelationList.Relations[KeyIndex]) then begin
ACaption:='No No No';
AText:=' The key "'+KeyAndShiftStateToStr(NewKey1,NewShiftState1)+'"'
+' is already connected to "'+DummyRelation.Name+'".';
// Application.MessageBox(PChar(AText),PChar(ACaption),0);
MessageDlg(ACaption,AText,mterror,[mbok],0);
exit;
end;
NewKey2:=StrToVKCode(Key2KeyComboBox.Text);
if (NewKey1=NewKey2) and (NewShiftState1=NewShiftState2) then
NewKey2:=VK_UNKNOWN;
if NewKey2<>VK_UNKNOWN then begin
if Key2CtrlCheckBox.Checked then include(NewShiftState2,ssCtrl);
if Key2AltCheckBox.Checked then include(NewShiftState2,ssAlt);
if Key2ShiftCheckBox.Checked then include(NewShiftState2,ssShift);
end;
DummyRelation:=KeyCommandRelationList.Find(NewKey2,NewShiftState2);
if (DummyRelation<>nil)
and (DummyRelation<>KeyCommandRelationList.Relations[KeyIndex]) then begin
ACaption:='No No No';
AText:=' The key "'+KeyAndShiftStateToStr(NewKey2,NewShiftState2)+'"'
+' is already connected to "'+DummyRelation.Name+'".';
MessageDlg(ACaption,AText,mterror,[mbok],0);
exit;
end;
if NewKey1=VK_UNKNOWN then begin
NewKey1:=NewKey2;
NewShiftState1:=NewShiftState2;
NewKey2:=VK_UNKNOWN;
end;
with KeyCommandRelationList.Relations[KeyIndex] do begin
Key1:=NewKey1;
Shift1:=NewShiftState1;
Key2:=NewKey2;
Shift2:=NewShiftState2;
end;
ModalResult:=mrOk;
end;
procedure TKeyMappingEditForm.CancelButtonClick(Sender:TObject);
begin
ModalResult:=mrCancel;
end;
procedure TKeyMappingEditForm.Key1GrabButtonClick(Sender: TObject);
begin
ActivateGrabbing(1);
end;
procedure TKeyMappingEditForm.Key2GrabButtonClick(Sender: TObject);
begin
ActivateGrabbing(2);
end;
procedure TKeyMappingEditForm.DeactivateGrabbing;
var i: integer;
begin
if GrabbingKey=0 then exit;
// enable all components
for i:=0 to ComponentCount-1 do begin
if (Components[i] is TWinControl) then
TWinControl(Components[i]).Enabled:=true;
end;
if GrabbingKey=1 then
Key1GrabButton.Caption:='Grab Key'
else if GrabbingKey=2 then
Key2GrabButton.Caption:='Grab Key';
GrabbingKey:=0;
end;
procedure TKeyMappingEditForm.SetComboBox(AComboBox: TComboBox; AValue: string);
var i: integer;
begin
i:=AComboBox.Items.IndexOf(AValue);
if i>=0 then
AComboBox.ItemIndex:=i
else begin
AComboBox.Items.Add(AValue);
AComboBox.ItemIndex:=AComboBox.Items.IndexOf(AValue);
end;
end;
procedure TKeyMappingEditForm.ActivateGrabbing(AGrabbingKey: integer);
var i: integer;
begin
if GrabbingKey>0 then exit;
GrabbingKey:=AGrabbingKey;
if GrabbingKey=0 then exit;
// disable all components
for i:=0 to ComponentCount-1 do begin
if (Components[i] is TWinControl) then begin
if ((GrabbingKey=1) and (Components[i]<>Key1GrabButton)
and (Components[i]<>Key1GroupBox))
or ((GrabbingKey=2) and (Components[i]<>Key2GrabButton)
and (Components[i]<>Key2GroupBox)) then
TWinControl(Components[i]).Enabled:=false;
end;
end;
if GrabbingKey=1 then
Key1GrabButton.Caption:='Please press a key ...'
else if GrabbingKey=2 then
Key2GrabButton.Caption:='Please press a key ...';
end;
procedure TKeyMappingEditForm.FormKeyUp(Sender: TObject; var Key: Word;
Shift:TShiftState);
begin
//writeln('TKeyMappingEditForm.FormKeyUp Sender=',Classname
// ,' Key=',Key,' Ctrl=',ssCtrl in Shift,' Shift=',ssShift in Shift
// ,' Alt=',ssAlt in Shift,' AsString=',KeyAndShiftStateToStr(Key,Shift)
// );
if Key in [VK_CONTROL, VK_SHIFT, VK_LCONTROL, VK_RCONTROl,
VK_LSHIFT, VK_RSHIFT] then exit;
if (GrabbingKey in [1,2]) then begin
if GrabbingKey=1 then begin
Key1CtrlCheckBox.Checked:=(ssCtrl in Shift);
Key1ShiftCheckBox.Checked:=(ssShift in Shift);
Key1AltCheckBox.Checked:=(ssAlt in Shift);
SetComboBox(Key1KeyComboBox,KeyAndShiftStateToStr(Key,[]));
end else if GrabbingKey=2 then begin
Key2CtrlCheckBox.Checked:=(ssCtrl in Shift);
Key2ShiftCheckBox.Checked:=(ssShift in Shift);
Key2AltCheckBox.Checked:=(ssAlt in Shift);
SetComboBox(Key2KeyComboBox,KeyAndShiftStateToStr(Key,[]));
end;
DeactivateGrabbing;
end;
end;
{ TKeyCommandRelation }
constructor TKeyCommandRelation.Create(AName:ShortString;
ACommand:TSynEditorCommand;
AKey1:Word;AShift1:TShiftState;AKey2:Word;AShift2:TShiftState);
begin
Name:=AName;
Command:=ACommand;
Key1:=AKey1;
Shift1:=AShift1;
Key2:=AKey2;
Shift2:=AShift2;
end;
{ TKeyCommandRelationList }
constructor TKeyCommandRelationList.Create;
begin
inherited Create;
FRelations:=TList.Create;
fExtToolCount:=0;
// normal synedit commands
Add('Select All',ecSelectAll,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Copy selection to clipboard',ecCopy,VK_C,[ssCtrl],VK_Insert,[ssCtrl]);
Add('Cut selection to clipboard',ecCut,VK_X,[ssCtrl],VK_Delete,[ssShift]);
Add('Paste clipboard to current position',ecPaste,VK_V,[ssCtrl],VK_Insert,[ssShift]);
Add('Undo',ecUndo,VK_Z,[ssCtrl],VK_UNKNOWN,[]);
Add('Redo',ecRedo,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Normal selection mode',ecNormalSelect,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Column selection mode',ecColumnSelect,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Line selection mode',ecLineSelect,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Go to matching bracket',ecMatchBracket,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Indent block',ecBlockIndent,VK_I,[ssCtrl],VK_UNKNOWN,[]);
Add('Unindent block',ecBlockUnindent,VK_U,[ssCtrl],VK_UNKNOWN,[]);
Add('Go to marker 0',ecGotoMarker0,VK_0,[ssCtrl],VK_UNKNOWN,[]);
Add('Go to marker 1',ecGotoMarker1,VK_1,[ssCtrl],VK_UNKNOWN,[]);
Add('Go to marker 2',ecGotoMarker2,VK_2,[ssCtrl],VK_UNKNOWN,[]);
Add('Go to marker 3',ecGotoMarker3,VK_3,[ssCtrl],VK_UNKNOWN,[]);
Add('Go to marker 4',ecGotoMarker4,VK_4,[ssCtrl],VK_UNKNOWN,[]);
Add('Go to marker 5',ecGotoMarker5,VK_5,[ssCtrl],VK_UNKNOWN,[]);
Add('Go to marker 6',ecGotoMarker6,VK_6,[ssCtrl],VK_UNKNOWN,[]);
Add('Go to marker 7',ecGotoMarker7,VK_7,[ssCtrl],VK_UNKNOWN,[]);
Add('Go to marker 8',ecGotoMarker8,VK_8,[ssCtrl],VK_UNKNOWN,[]);
Add('Go to marker 9',ecGotoMarker9,VK_9,[ssCtrl],VK_UNKNOWN,[]);
Add('Set marker 0',ecSetMarker0,VK_0,[ssShift,ssCtrl],VK_UNKNOWN,[]);
Add('Set marker 1',ecSetMarker1,VK_1,[ssShift,ssCtrl],VK_UNKNOWN,[]);
Add('Set marker 2',ecSetMarker2,VK_2,[ssShift,ssCtrl],VK_UNKNOWN,[]);
Add('Set marker 3',ecSetMarker3,VK_3,[ssShift,ssCtrl],VK_UNKNOWN,[]);
Add('Set marker 4',ecSetMarker4,VK_4,[ssShift,ssCtrl],VK_UNKNOWN,[]);
Add('Set marker 5',ecSetMarker5,VK_5,[ssShift,ssCtrl],VK_UNKNOWN,[]);
Add('Set marker 6',ecSetMarker6,VK_6,[ssShift,ssCtrl],VK_UNKNOWN,[]);
Add('Set marker 7',ecSetMarker7,VK_7,[ssShift,ssCtrl],VK_UNKNOWN,[]);
Add('Set marker 8',ecSetMarker8,VK_8,[ssShift,ssCtrl],VK_UNKNOWN,[]);
Add('Set marker 9',ecSetMarker9,VK_9,[ssShift,ssCtrl],VK_UNKNOWN,[]);
Add('Code template completion',ecAutoCompletion,VK_J,[ssCtrl],VK_UNKNOWN,[]);
// user defined commands
Add('Word completion',ecWordCompletion,VK_W,[ssCtrl],VK_UNKNOWN,[]);
Add('Complete code',ecCompleteCode,VK_C,[ssCtrl,ssShift],VK_UNKNOWN,[]);
Add('Identifier completion',ecIdentCompletion,VK_SPACE,[ssCtrl],VK_UNKNOWN,[]);
Add('Syntax check',ecSyntaxCheck,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Guess unclosed block',ecGuessUnclosedBlock,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Find text',ecFind,VK_F,[SSCtrl],VK_UNKNOWN,[]);
Add('Find next',ecFindNext,VK_F3,[],VK_UNKNOWN,[]);
Add('Find previous',ecFindPrevious,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Find in files',ecFindInFiles,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Replace text',ecReplace,VK_R,[SSCtrl],VK_UNKNOWN,[]);
Add('Find procedure definiton',ecFindProcedureDefinition,
VK_UP,[ssShift,SSCtrl],VK_UNKNOWN,[]);
Add('Find procedure method',ecFindProcedureMethod,
VK_DOWN,[ssShift,SSCtrl],VK_UNKNOWN,[]);
Add('Find declaration',ecFindDeclaration,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Find block other end',ecFindBlockOtherEnd,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Find block start',ecFindBlockStart,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Go to line number',ecGotoLineNumber,VK_G,[ssCtrl],VK_UNKNOWN,[]);
Add('Jump back',ecJumpBack,VK_H,[ssCtrl],VK_UNKNOWN,[]);
Add('Jump forward',ecJumpForward,VK_H,[ssCtrl,ssShift],VK_UNKNOWN,[]);
Add('Add jump point',ecAddJumpPoint,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('View jump history',ecViewJumpHistory,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Go to next editor',ecNextEditor, VK_S, [ssShift,ssCtrl], VK_UNKNOWN, []);
Add('Go to prior editor',ecPrevEditor, VK_A, [ssShift,ssCtrl], VK_UNKNOWN, []);
Add('Save',ecSave,VK_S,[ssCtrl],VK_UNKNOWN,[]);
Add('Open',ecOpen,VK_O,[ssCtrl],VK_UNKNOWN,[]);
Add('Close',ecClose,VK_F4,[ssCtrl],VK_UNKNOWN,[]);
Add('Build project/program',ecBuild,VK_F9,[ssCtrl],VK_UNKNOWN,[]);
Add('Build all files of project/program',ecBuildAll,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Build Lazarus',ecBuildLazarus,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Run program',ecRun,VK_F9,[],VK_UNKNOWN,[]);
Add('Pause program',ecPause,VK_UNKNOWN,[],VK_UNKNOWN,[]);
Add('Step into',ecStepInto,VK_F7,[],VK_UNKNOWN,[]);
Add('Step over',ecStepOver,VK_F8,[],VK_UNKNOWN,[]);
Add('Run to cursor',ecStepOver,VK_F4,[],VK_UNKNOWN,[]);
Add('Stop program',ecStepOver,VK_F2,[SSCtrl],VK_UNKNOWN,[]);
Add('Go to source editor 1',ecGotoEditor0,VK_1,[ssAlt],VK_UNKNOWN,[]);
Add('Go to source editor 2',ecGotoEditor0,VK_2,[ssAlt],VK_UNKNOWN,[]);
Add('Go to source editor 3',ecGotoEditor0,VK_3,[ssAlt],VK_UNKNOWN,[]);
Add('Go to source editor 4',ecGotoEditor0,VK_4,[ssAlt],VK_UNKNOWN,[]);
Add('Go to source editor 5',ecGotoEditor0,VK_5,[ssAlt],VK_UNKNOWN,[]);
Add('Go to source editor 6',ecGotoEditor0,VK_6,[ssAlt],VK_UNKNOWN,[]);
Add('Go to source editor 7',ecGotoEditor0,VK_7,[ssAlt],VK_UNKNOWN,[]);
Add('Go to source editor 8',ecGotoEditor0,VK_8,[ssAlt],VK_UNKNOWN,[]);
Add('Go to source editor 9',ecGotoEditor0,VK_9,[ssAlt],VK_UNKNOWN,[]);
Add('Go to source editor 10',ecGotoEditor0,VK_0,[ssAlt],VK_UNKNOWN,[]);
Add('Toggle between Unit and Form',ecToggleFormUnit,VK_F12,[],VK_UNKNOWN,[]);
end;
destructor TKeyCommandRelationList.Destroy;
var a:integer;
begin
for a:=0 to FRelations.Count-1 do
Relations[a].Free;
FRelations.Free;
inherited Destroy;
end;
function TKeyCommandRelationList.GetRelation(
Index:integer):TKeyCommandRelation;
begin
if (Index<0) or (Index>=Count) then begin
writeln('[TKeyCommandRelationList.GetRelation] Index out of bounds '
,Index,' Count=',Count);
Halt;
end;
Result:= TKeyCommandRelation(FRelations[Index]);
end;
function TKeyCommandRelationList.Count:integer;
begin
Result:=FRelations.Count;
end;
function TKeyCommandRelationList.Add(Name:shortstring;
Command:TSynEditorCommand;
Key1:Word; Shift1:TShiftState; Key2:Word; Shift2:TShiftState):integer;
begin
Result:=FRelations.Add(TKeyCommandRelation.Create(Name,Command
,Key1,Shift1,Key2,Shift2));
end;
procedure TKeyCommandRelationList.SetExtToolCount(NewCount: integer);
var i: integer;
begin
if NewCount=fExtToolCount then exit;
if NewCount>fExtToolCount then begin
// increase available external tool commands
while NewCount>fExtToolCount do begin
Add('External tool '+IntToStr(fExtToolCount),
ecExtToolFirst+fExtToolCount,VK_UNKNOWN,[],VK_UNKNOWN,[]);
inc(fExtToolCount);
end;
end else begin
// decrease available external tool commands
i:=Count-1;
while (i>=0) and (fExtToolCount>NewCount) do begin
if (Relations[i].Command>=ecExtToolFirst)
and (Relations[i].Command<=ecExtToolLast) then begin
fRelations.Delete(i);
dec(fExtToolCount);
end;
dec(i);
end;
end;
end;
function TKeyCommandRelationList.LoadFromXMLConfig(
XMLConfig:TXMLConfig; Prefix:AnsiString):boolean;
var a,b,p:integer;
Name:ShortString;
DefaultStr,NewValue:AnsiString;
function ReadNextInt:integer;
begin
Result:=0;
while (p<=length(NewValue)) and (not (NewValue[p] in ['0'..'9']))
do inc(p);
while (p<=length(NewValue)) and (NewValue[p] in ['0'..'9'])
and (Result<$10000)do begin
Result:=Result*10+ord(NewValue[p])-ord('0');
inc(p);
end;
end;
function IntToShiftState(i:integer):TShiftState;
begin
Result:=[];
if (i and 1)>0 then Include(Result,ssCtrl);
if (i and 2)>0 then Include(Result,ssShift);
if (i and 4)>0 then Include(Result,ssAlt);
end;
// LoadFromXMLConfig
begin
ExtToolCount:=XMLConfig.GetValue(Prefix+'ExternalToolCount/Value',0);
for a:=0 to FRelations.Count-1 do begin
Name:=lowercase(Relations[a].Name);
for b:=1 to length(Name) do
if Name[b]=' ' then Name[b]:='_';
with Relations[a] do
DefaultStr:=IntToStr(Key1)+','+ShiftStateToStr(Shift1)
+','+IntToStr(Key2)+','+ShiftStateToStr(Shift2);
NewValue:=XMLConfig.GetValue(Prefix+Name,DefaultStr);
p:=1;
with Relations[a] do begin
Key1:=ReadNextInt;
Shift1:=IntToShiftState(ReadNextInt);
Key2:=ReadNextInt;
Shift2:=IntToShiftState(ReadNextInt);
end;
end;
Result:=true;
end;
function TKeyCommandRelationList.SaveToXMLConfig(
XMLConfig:TXMLConfig; Prefix:AnsiString):boolean;
var a,b:integer;
Name:ShortString;
s:AnsiString;
begin
XMLConfig.SetValue(Prefix+'ExternalToolCount/Value',ExtToolCount);
for a:=0 to FRelations.Count-1 do begin
Name:=lowercase(Relations[a].Name);
for b:=1 to length(Name) do
if Name[b]=' ' then Name[b]:='_';
with Relations[a] do
s:=IntToStr(Key1)+','+ShiftStateToStr(Shift1)
+','+IntToStr(Key2)+','+ShiftStateToStr(Shift2);
XMLConfig.SetValue(Prefix+Name,s);
end;
Result:=true;
end;
function TKeyCommandRelationList.ShiftStateToStr(Shift:TShiftState):AnsiString;
var i:integer;
begin
i:=0;
if ssCtrl in Shift then inc(i,1);
if ssShift in Shift then inc(i,2);
if ssAlt in Shift then inc(i,4);
Result:=IntToStr(i);
end;
function TKeyCommandRelationList.Find(AKey:Word; AShiftState:TShiftState
):TKeyCommandRelation;
var a:integer;
begin
Result:=nil;
if AKey=VK_UNKNOWN then exit;
for a:=0 to FRelations.Count-1 do with Relations[a] do
if ((Key1=AKey) and (Shift1=AShiftState))
or ((Key2=AKey) and (Shift2=AShiftState)) then begin
Result:=Relations[a];
exit;
end;
end;
function TKeyCommandRelationList.FindByCommand(
ACommand:TSynEditorCommand):TKeyCommandRelation;
var a:integer;
begin
Result:=nil;
for a:=0 to FRelations.Count-1 do with Relations[a] do
if (Command=ACommand) then begin
Result:=Relations[a];
exit;
end;
end;
procedure TKeyCommandRelationList.AssignTo(
ASynEditKeyStrokes:TSynEditKeyStrokes);
var a,b,MaxKeyCnt,KeyCnt:integer;
Key:TSynEditKeyStroke;
begin
for a:=0 to FRelations.Count-1 do begin
if Relations[a].Key1=VK_UNKNOWN then MaxKeyCnt:=0
else if Relations[a].Key2=VK_UNKNOWN then MaxKeyCnt:=1
else MaxKeyCnt:=2;
KeyCnt:=1;
b:=0;
while b<ASynEditKeyStrokes.Count do begin
if ASynEditKeyStrokes[b].Command=Relations[a].Command then begin
if KeyCnt>MaxKeyCnt then begin
ASynEditKeyStrokes[b].Free;
end else if KeyCnt=1 then begin
ASynEditKeyStrokes[b].Key:=Relations[a].Key1;
ASynEditKeyStrokes[b].Shift:=Relations[a].Shift1;
ASynEditKeyStrokes[b].Key2:=VK_UNKNOWN;
ASynEditKeyStrokes[b].Shift2:=[];
inc(b);
end else if KeyCnt=2 then begin
ASynEditKeyStrokes[b].Key:=Relations[a].Key2;
ASynEditKeyStrokes[b].Shift:=Relations[a].Shift2;
ASynEditKeyStrokes[b].Key2:=VK_UNKNOWN;
ASynEditKeyStrokes[b].Shift2:=[];
inc(b);
end;
inc(KeyCnt);
end else inc(b);
end;
while KeyCnt<=MaxKeyCnt do begin
Key:=ASynEditKeyStrokes.Add;
Key.Command:=Relations[a].Command;
if KeyCnt=1 then begin
Key.Key:=Relations[a].Key1;
Key.Shift:=Relations[a].Shift1;
end else begin
Key.Key:=Relations[a].Key2;
Key.Shift:=Relations[a].Shift2;
end;
Key.Key2:=VK_UNKNOWN;
Key.Shift2:=[];
inc(KeyCnt);
end;
end;
end;
initialization
KeyMappingEditForm:=nil;
end.