dexed/src/ce_shortcutseditor.pas

435 lines
10 KiB
Plaintext

unit ce_shortcutseditor;
{$I ce_defines.inc}
interface
uses
Classes, SysUtils, FileUtil, TreeFilterEdit, Forms, Controls, Menus, Graphics,
ExtCtrls, LCLProc, ComCtrls, StdCtrls, Buttons, LCLType,
ce_observer, ce_interfaces, ce_common, ce_writableComponent;
type
TShortcutItem = class(TCollectionItem)
private
fIdentifier: string;
fData: TShortcut;
fDeclarator: ICEEditableShortCut;
property declarator: ICEEditableShortCut read fDeclarator write fDeclarator;
published
property identifier: string read fIdentifier write fIdentifier;
property data: TShortcut read fData write fData;
public
function combination: string;
procedure assign(aValue: TPersistent); override;
end;
TShortCutCollection = class(TWritableLfmTextComponent)
private
fItems: TCollection;
procedure setItems(aValue: TCollection);
function getCount: Integer;
function getItem(index: Integer): TShortcutItem;
published
property items: TCollection read fItems write setItems;
public
constructor create(AOwner: TComponent); override;
destructor destroy; override;
procedure assign(aValue: TPersistent); override;
//
function findIdentifier(const identifier: string): boolean;
function findShortcut(aShortcut: Word): boolean;
//
property count: Integer read getCount;
property item[index: Integer]: TShortcutItem read getItem; default;
end;
{ TCEShortcutEditor }
TCEShortcutEditor = class(TFrame, ICEEditableOptions)
btnClear: TSpeedButton;
shortcutCatcher: TEdit;
Panel1: TPanel;
fltItems: TTreeFilterEdit;
Panel2: TPanel;
schrtText: TStaticText;
btnActivate: TSpeedButton;
tree: TTreeView;
procedure btnActivateClick(Sender: TObject);
procedure btnClearClick(Sender: TObject);
procedure LabeledEdit1KeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);
procedure shortcutCatcherExit(Sender: TObject);
procedure shortcutCatcherMouseLeave(Sender: TObject);
procedure treeSelectionChanged(Sender: TObject);
private
fObservers: TCEEditableShortCutSubject;
fShortcuts: TShortCutCollection;
fBackup: TShortCutCollection;
fHasChanged: boolean;
//
function optionedWantCategory(): string;
function optionedWantEditorKind: TOptionEditorKind;
function optionedWantContainer: TPersistent;
procedure optionedEvent(anEvent: TOptionEditorEvent);
function optionedOptionsModified: boolean;
//
function findCategory(const aName: string; aData: Pointer): TTreeNode;
function findCategory(const aShortcutItem: TShortcutItem): string;
function sortCategories(Cat1, Cat2: TTreeNode): integer;
procedure receiveShortcuts;
procedure updateEditCtrls;
procedure sendShortcuts;
protected
procedure UpdateShowing; override;
public
constructor create(TheOwner: TComponent); override;
destructor destroy; override;
end;
implementation
{$R *.lfm}
var
CEShortcutEditor: TCEShortcutEditor;
{$REGION TShortCutCollection ---------------------------------------------------}
function TShortcutItem.combination: string;
begin
result := ShortCutToText(fData);
end;
procedure TShortcutItem.assign(aValue: TPersistent);
var
src: TShortcutItem;
begin
if aValue is TShortcutItem then
begin
src := TShortcutItem(aValue);
fData:= src.fData;
fIdentifier:= src.fIdentifier;
fDeclarator := src.fDeclarator;
end
else inherited;
end;
constructor TShortCutCollection.create(AOwner: TComponent);
begin
inherited;
fItems := TCollection.Create(TShortcutItem);
end;
destructor TShortCutCollection.destroy;
begin
fItems.Free;
inherited;
end;
procedure TShortCutCollection.assign(aValue: TPersistent);
begin
if aValue is TShortCutCollection then
fItems.Assign(TShortCutCollection(aValue).fItems)
else
inherited;
end;
procedure TShortCutCollection.setItems(aValue: TCollection);
begin
fItems.Assign(aValue);
end;
function TShortCutCollection.getCount: Integer;
begin
exit(fItems.Count);
end;
function TShortCutCollection.getItem(index: Integer): TShortcutItem;
begin
exit(TShortcutItem(fItems.Items[index]));
end;
function TShortCutCollection.findIdentifier(const identifier: string): boolean;
var
i: Integer;
begin
result := false;
for i := 0 to count-1 do
if item[i].identifier = identifier then
exit(true);
end;
function TShortCutCollection.findShortcut(aShortcut: Word): boolean;
var
i: Integer;
begin
result := false;
for i := 0 to count-1 do
if item[i].data = aShortcut then
exit(true);
end;
{$ENDREGION}
{$REGION Standard Comp/Object things -------------------------------------------}
constructor TCEShortcutEditor.create(TheOwner: TComponent);
var
png: TPortableNetworkGraphic;
begin
inherited;
fObservers := TCEEditableShortCutSubject.create;
fShortcuts := TShortCutCollection.create(self);
fBackup := TShortCutCollection.create(self);
//
png := TPortableNetworkGraphic.Create;
try
png.LoadFromLazarusResource('clean');
btnClear.Glyph.Assign(png);
finally
png.free;
end;
//
EntitiesConnector.addObserver(self);
end;
destructor TCEShortcutEditor.destroy;
begin
fObservers.Free;
inherited;
end;
procedure TCEShortcutEditor.UpdateShowing;
var
png : TPortableNetworkGraphic;
begin
inherited;
if not visible then exit;
//
png := TPortableNetworkGraphic.Create;
try
png.LoadFromLazarusResource('keyboard_pencil');
btnActivate.Glyph.Assign(png);
finally
png.free;
end;
end;
{$ENDREGION}
{$REGION ICEEditableOptions ----------------------------------------------------}
function TCEShortcutEditor.optionedWantCategory(): string;
begin
exit('Shortcuts');
end;
function TCEShortcutEditor.optionedWantEditorKind: TOptionEditorKind;
begin
exit(oekControl);
end;
function TCEShortcutEditor.optionedWantContainer: TPersistent;
begin
receiveShortcuts;
exit(self);
end;
procedure TCEShortcutEditor.optionedEvent(anEvent: TOptionEditorEvent);
begin
case anEvent of
oeeSelectCat: receiveShortcuts;
oeeCancel:
begin
fShortcuts.assign(fBackup);
sendShortcuts;
fHasChanged := false;
end;
oeeAccept:
begin
fBackup.assign(fShortcuts);
sendShortcuts;
fHasChanged := false;
end;
end;
end;
function TCEShortcutEditor.optionedOptionsModified: boolean;
begin
exit(fHasChanged);
end;
{$ENDREGION}
{$REGION shortcut editor things ------------------------------------------------}
procedure TCEShortcutEditor.treeSelectionChanged(Sender: TObject);
begin
updateEditCtrls;
end;
procedure TCEShortcutEditor.shortcutCatcherExit(Sender: TObject);
begin
shortcutCatcher.Enabled := false;
updateEditCtrls;
end;
procedure TCEShortcutEditor.shortcutCatcherMouseLeave(Sender: TObject);
begin
shortcutCatcher.Enabled := false;
updateEditCtrls;
end;
procedure TCEShortcutEditor.btnActivateClick(Sender: TObject);
begin
if tree.Selected = nil then exit;
if tree.Selected.Level = 0 then exit;
if tree.Selected.Data = nil then exit;
//
shortcutCatcher.Enabled := not shortcutCatcher.Enabled;
end;
procedure TCEShortcutEditor.btnClearClick(Sender: TObject);
begin
if tree.Selected = nil then exit;
if tree.Selected.Level = 0 then exit;
if tree.Selected.Data = nil then exit;
//
if TShortcutItem(tree.Selected.Data).data <> 0 then
begin
TShortcutItem(tree.Selected.Data).data := 0;
fHasChanged := true;
end;
//
updateEditCtrls;
end;
procedure TCEShortcutEditor.LabeledEdit1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
var
sh: TShortCut;
begin
if tree.Selected = nil then exit;
if tree.Selected.Level = 0 then exit;
if tree.Selected.Data = nil then exit;
//
if Key = VK_RETURN then
shortcutCatcher.Enabled := false
else
begin
sh := Shortcut(Key, Shift);
if TShortcutItem(tree.Selected.Data).data <> sh then
begin
TShortcutItem(tree.Selected.Data).data := sh;
fHasChanged := true;
end;
end;
//
updateEditCtrls;
end;
procedure TCEShortcutEditor.updateEditCtrls;
begin
schrtText.Caption := '';
//
if tree.Selected = nil then exit;
if tree.Selected.Level = 0 then exit;
if tree.Selected.Data = nil then exit;
//
schrtText.Caption := TShortcutItem(tree.Selected.Data).combination;
shortcutCatcher.Text := '';
end;
function TCEShortcutEditor.findCategory(const aName: string; aData: Pointer): TTreeNode;
var
i: integer;
begin
result := nil;
for i:= 0 to tree.Items.Count-1 do
if tree.Items[i].Text = aName then
if tree.Items[i].Data = aData then
exit(tree.Items[i]);
end;
function TCEShortcutEditor.findCategory(const aShortcutItem: TShortcutItem): string;
var
i, j: integer;
begin
result := '';
for i := 0 to tree.Items.Count-1 do
for j:= 0 to tree.Items.Item[i].Count-1 do
if tree.Items.Item[i].Items[j].Data = Pointer(aShortcutItem) then
exit(tree.Items.Item[i].Text);
end;
function TCEShortcutEditor.sortCategories(Cat1, Cat2: TTreeNode): integer;
begin
result := CompareText(Cat1.Text, Cat2.Text);
end;
procedure TCEShortcutEditor.receiveShortcuts;
var
i: Integer;
obs: ICEEditableShortCut;
cat: string;
sht: word;
idt: string;
itm: TShortcutItem;
procedure addItem();
var
prt: TTreeNode;
begin
// root category
if cat = '' then exit;
if idt = '' then exit;
prt := findCategory(cat, obs);
if prt = nil then
prt := tree.Items.AddObject(nil, cat, obs);
// item as child
itm := TShortcutItem(fShortcuts.items.Add);
itm.identifier := idt;
itm.data:= sht;
itm.declarator := obs;
tree.Items.AddChildObject(prt, idt, itm);
cat := '';
idt := '';
end;
begin
tree.Items.Clear;
fShortcuts.items.Clear;
fBackup.items.Clear;
cat := '';
idt := '';
for i:= 0 to fObservers.observersCount-1 do
begin
obs := fObservers.observers[i] as ICEEditableShortCut;
if obs.scedWantFirst then
begin
while obs.scedWantNext(cat, idt, sht) do
addItem();
addItem();
end;
end;
tree.Items.SortTopLevelNodes(@sortCategories);
fBackup.Assign(fShortcuts);
end;
procedure TCEShortcutEditor.sendShortcuts;
var
i: integer;
shc: TShortcutItem;
cat: string;
begin
for i := 0 to fShortcuts.count-1 do
begin
shc := fShortcuts[i];
cat := findCategory(shc);
if cat = '' then
continue;
if shc.declarator = nil then
continue;
shc.declarator.scedSendItem(cat, shc.identifier, shc.data);
end;
end;
{$ENDREGION}
initialization
CEShortcutEditor := TCEShortcutEditor.Create(nil);
finalization
CEShortcutEditor.Free;
end.