Menu designer: Use TShortcutDisplayDlg from a new unit.

git-svn-id: trunk@51617 -
This commit is contained in:
juha 2016-02-13 13:09:37 +00:00
parent 073c2c50e9
commit 6fd4274fb1
3 changed files with 5 additions and 498 deletions

View File

@ -66,6 +66,7 @@ type
public public
constructor Create(AOwner: TComponent; aMenu: TMenu); reintroduce; constructor Create(AOwner: TComponent; aMenu: TMenu); reintroduce;
destructor Destroy; override; destructor Destroy; override;
procedure RefreshFakes; virtual; abstract;
procedure SetSelectedMenuItem(aMI: TMenuItem; procedure SetSelectedMenuItem(aMI: TMenuItem;
viaDesigner, prevWasDeleted: boolean); virtual; abstract; viaDesigner, prevWasDeleted: boolean); virtual; abstract;
procedure UpdateBoxLocationsAndSizes; virtual; abstract; procedure UpdateBoxLocationsAndSizes; virtual; abstract;

View File

@ -30,8 +30,6 @@ uses
Classes, SysUtils, Types, typinfo, Classes, SysUtils, Types, typinfo,
Controls, StdCtrls, ExtCtrls, Forms, Graphics, Buttons, Menus, ButtonPanel, Controls, StdCtrls, ExtCtrls, Forms, Graphics, Buttons, Menus, ButtonPanel,
ImgList, Themes, LCLintf, LCLProc, ImgList, Themes, LCLintf, LCLProc,
// LazUtils
LazUTF8,
// IdeIntf // IdeIntf
FormEditingIntf, PropEdits, FormEditingIntf, PropEdits,
// IDE // IDE
@ -107,23 +105,6 @@ type
//property AcceleratorMenuItemsCount: integer read FAcceleratorMenuItemsCount; //property AcceleratorMenuItemsCount: integer read FAcceleratorMenuItemsCount;
end; end;
{ TEditCaptionDialog }
TEditCaptionDialog = class(TForm)
strict private
FButtonPanel: TButtonPanel;
FEdit: TEdit;
FGBEdit: TGroupBox;
FMenuItem: TMenuItem;
FNewShortcut: TShortCut;
FOldShortcut: TShortCut;
procedure EditOnChange(Sender: TObject);
procedure OKButtonClick(Sender: TObject);
public
constructor CreateWithMenuItem(AOwner: TComponent; aMI: TMenuItem; aSC: TShortCut);
property NewShortcut: TShortCut read FNewShortcut;
end;
TRadioIconGroup = class; TRadioIconGroup = class;
TRadioIconState = (risUp, risDown, risPressed, risUncheckedHot, risCheckedHot); TRadioIconState = (risUp, risDown, risPressed, risUncheckedHot, risCheckedHot);
@ -191,7 +172,6 @@ type
end; end;
function GetNestingLevelDepth(aMenu: TMenu): integer; function GetNestingLevelDepth(aMenu: TMenu): integer;
function EditCaptionDlg(aMI: TMenuItem; var aShortcut: TShortCut): boolean;
function ChooseIconFromImageListDlg(anImageList: TCustomImageList): integer; function ChooseIconFromImageListDlg(anImageList: TCustomImageList): integer;
@ -221,20 +201,6 @@ begin
CheckLevel(aMenu.Items[i], 0); CheckLevel(aMenu.Items[i], 0);
end; end;
function EditCaptionDlg(aMI: TMenuItem; var aShortcut: TShortCut): boolean;
var
dlg: TEditCaptionDialog;
begin
dlg := TEditCaptionDialog.CreateWithMenuItem(nil, aMI, aShortcut);
try
Result := dlg.ShowModal = mrOK;
if Result then
aShortcut := dlg.NewShortcut;
finally
dlg.Free;
end;
end;
function ChooseIconFromImageListDlg(anImageList: TCustomImageList): integer; function ChooseIconFromImageListDlg(anImageList: TCustomImageList): integer;
var var
dlg: TdlgChooseIcon; dlg: TdlgChooseIcon;
@ -732,91 +698,6 @@ begin
end; end;
end; end;
{ TEditCaptionDialog }
constructor TEditCaptionDialog.CreateWithMenuItem(AOwner: TComponent;
aMI: TMenuItem; aSC: TShortCut);
var
key: word;
sstate: TShiftState;
p: integer;
ch: Char;
begin
inherited CreateNew(AOwner);
FMenuItem:=aMI;
FOldShortcut:=aSC;
ShortCutToKey(aSC, key, sstate);
Position:=poScreenCenter;
BorderStyle:=bsDialog;
Caption:=Format(lisMenuEditorEditingCaptionOfS, [FMenuItem.Name]);
FButtonPanel:=TButtonPanel.Create(Self);
with FButtonPanel do
begin
ShowButtons:=[pbOK, pbCancel];
OKButton.Name:='OKButton';
OKButton.DefaultCaption:=True;
OKButton.Enabled:=False;
OKButton.OnClick:=@OKButtonClick;
CancelButton.Name:='CancelButton';
CancelButton.DefaultCaption:=True;
ShowBevel:=False;
Parent:=Self;
end;
FGBEdit:=TGroupBox.Create(Self);
with FGBEdit do
begin
BorderSpacing.Around:=Margin;
p:=LazUTF8.UTF8Pos('&', aMI.Caption);
if (p > 0) and (p < LazUTF8.UTF8Length(aMI.Caption)) then
ch:=aMI.Caption[Succ(p)] // gets correct case of key
else
ch:=Chr(Ord(key)); // fallback
Caption:=Format(lisMenuEditorAcceleratorKeySNeedsChanging, [ch]);
Align:=alClient;
Parent:=Self;
end;
FEdit:=TEdit.Create(Self);
with FEdit do
begin;
BorderSpacing.Around:=Margin;
Text:=FMenuItem.Caption;
Align:=alClient;
OnChange:=@EditOnChange;
Parent:=FGBEdit;
end;
AutoSize:=True;
end;
procedure TEditCaptionDialog.EditOnChange(Sender: TObject);
var
hasAccel: boolean;
sc: TShortCut;
begin
if (FEdit.Text = '') then
begin
FEdit.Text:=lisMenuEditorCaptionShouldNotBeBlank;
FEdit.SetFocus;
end
else
begin
hasAccel:=HasAccelerator(FEdit.Text, sc);
if (not hasAccel) or (hasAccel and (sc <> FOldShortcut)) then
begin
FNewShortcut:=sc;
FButtonPanel.OKButton.Enabled:=True;
end;
end;
end;
procedure TEditCaptionDialog.OKButtonClick(Sender: TObject);
begin
FMenuItem.Caption:=FEdit.Text;
end;
{ TRadioIcon } { TRadioIcon }
constructor TRadioIcon.CreateWithGlyph(aRIGroup: TRadioIconGroup; constructor TRadioIcon.CreateWithGlyph(aRIGroup: TRadioIconGroup;

View File

@ -7,13 +7,13 @@ interface
uses uses
// FCL + LCL // FCL + LCL
Classes, SysUtils, Types, typinfo, Classes, SysUtils, Types, typinfo,
ActnList, ButtonPanel, Controls, Dialogs, StdCtrls, ExtCtrls, Menus, ActnList, Controls, Dialogs, StdCtrls, ExtCtrls, Menus,
Forms, Graphics, ImgList, Themes, LCLType, LCLIntf, LCLProc, Forms, Graphics, ImgList, Themes, LCLType, LCLIntf, LCLProc,
// IdeIntf // IdeIntf
FormEditingIntf, IDEWindowIntf, ComponentEditors, IDEDialogs, PropEdits, FormEditingIntf, IDEWindowIntf, ComponentEditors, IDEDialogs, PropEdits,
// IDE // IDE
LazarusIDEStrConsts, LazarusIDEStrConsts, MenuDesignerBase, MenuEditorForm, MenuShortcutDisplay,
MenuDesignerBase, MenuEditorForm, MenuShortcuts, MenuTemplates, MenuResolveConflicts; MenuTemplates, MenuResolveConflicts;
type type
@ -240,7 +240,7 @@ type
aSelect: TMenuItem; aWidth, aHeight: integer); reintroduce; aSelect: TMenuItem; aWidth, aHeight: integer); reintroduce;
destructor Destroy; override; destructor Destroy; override;
procedure HideBoxesAboveLevel(aLevel: integer); procedure HideBoxesAboveLevel(aLevel: integer);
procedure RefreshFakes; procedure RefreshFakes; override;
procedure SetSelectedMenuItem(aMI: TMenuItem; procedure SetSelectedMenuItem(aMI: TMenuItem;
viaDesigner, prevWasDeleted: boolean); override; viaDesigner, prevWasDeleted: boolean); override;
procedure UpdateBoxLocationsAndSizes; override; procedure UpdateBoxLocationsAndSizes; override;
@ -329,33 +329,6 @@ type
property EditedLine: string read GetEditedLine; property EditedLine: string read GetEditedLine;
end; end;
{ TShortcutDisplayDlg }
TShortcutDisplayDlg = class(TForm)
strict private
FLastSortIndex: integer;
FMenu: TMenu;
FscList: TStringList;
FSingleMenuOnly: boolean;
FShortcutsOnly: boolean;
FShortcuts: TMenuShortcuts;
FShadowMenu: TShadowMenu;
// GUI
FBPanel: TButtonPanel;
FDualDisplay: TDualDisplay;
FGBDisplay: TGroupBox;
FLabel: TLabel;
procedure AddSCitemToListRecursive(anItem: TMenuItem);
procedure DisplayAllDlgClick(isHeader: boolean; index: integer);
procedure DisplaySingleMenuClick(isHeader: boolean; index: integer);
procedure UpdateContents(singleMenuOnly: boolean=False);
procedure UpdateFromMenu(anIndex: integer= -1);
public
constructor CreateWithShortcutsOnly(aShortcuts: TMenuShortcuts; shortcutsOnly: boolean;
aShadowMenu: TShadowMenu; aMenu: TMenu=nil);
destructor Destroy; override;
end;
// utility functions // utility functions
function ItemStateToStr(aState: TShadowItemDisplayState): string; function ItemStateToStr(aState: TShadowItemDisplayState): string;
@ -465,21 +438,6 @@ begin
Inc(Result); Inc(Result);
end; end;
{function CommaTextIntoTwo(const aText: string; out a2ndHalf: string): string;
var
p, len: integer;
begin
a2ndHalf:='';
len:=Length(aText);
if (len = 0) then
Exit('');
p:=Pos(',', aText);
if (p = 0) then
Exit(aText);
Result:=Copy(aText, 1, Pred(p));
a2ndHalf:=Copy(aText, Succ(p), len - p);
end;}
function AIsDescendantOfB(miA, miB: TMenuItem): boolean; function AIsDescendantOfB(miA, miB: TMenuItem): boolean;
var var
tmp: TMenuItem; tmp: TMenuItem;
@ -538,33 +496,6 @@ begin
Result:=0; Result:=0;
end; end;
function ListShortCutDlg(aShortcuts: TMenuShortcuts; shortcutsOnly: boolean;
aShadowMenu: TShadowMenu; aMenu: TMenu): TModalResult;
var
dlg: TShortcutDisplayDlg;
begin
dlg:=TShortcutDisplayDlg.CreateWithShortcutsOnly(aShortcuts, shortcutsOnly,
aShadowMenu, aMenu);
try
Result:=dlg.ShowModal;
finally
FreeAndNil(dlg);
end;
end;
function SortByComponent(Item1, Item2: Pointer): Integer;
var
SCInfo1: TSCInfo absolute Item1;
SCInfo2: TSCInfo absolute Item2;
begin
if (SCInfo1.ComponentName > SCInfo2.ComponentName) then
Result:= +1
else if (SCInfo1.ComponentName < SCInfo2.ComponentName) then
Result:= -1
else
Result:=0;
end;
{ TAddFirstFake } { TAddFirstFake }
function TAddFirstFake.GetShouldBeVisible: boolean; function TAddFirstFake.GetShouldBeVisible: boolean;
@ -688,312 +619,6 @@ begin
end; end;
end; end;
{ TShortcutDisplayDlg }
constructor TShortcutDisplayDlg.CreateWithShortcutsOnly(aShortcuts: TMenuShortcuts;
shortcutsOnly: boolean; aShadowMenu: TShadowMenu; aMenu: TMenu);
var
s: string;
lurStr: string;
begin
inherited CreateNew(nil);
FShortcutsOnly:=shortcutsOnly;
FShortcuts:=aShortcuts;
FMenu:=aMenu;
FShadowMenu:=aShadowMenu;
FSingleMenuOnly:=(FMenu <> nil);
FLastSortIndex:= -1;
if FSingleMenuOnly then
Caption:=Format(lisMenuEditorShortcutsUsedInS, [FMenu.Name])
else begin
if shortcutsOnly then
s:=lisMenuEditorSShortcuts
else
s:=lisMenuEditorSShortcutsAndAcceleratorKeys;
lurStr:=TComponent(GlobalDesignHook.LookupRoot).Name;
Caption:=Format(s, [lurStr]);
end;
BorderStyle:=bsDialog;
Position:=poScreenCenter;
Constraints.MinWidth:=460;
Constraints.MaxHeight:=460;
FBPanel:=TButtonPanel.Create(Self);
with FBPanel do begin
ShowBevel:=False;
BorderSpacing.Around:=Spacing;
BorderSpacing.Right:=Spacing;
Constraints.MinHeight:=42;
ShowButtons:=[pbClose];
CloseButton.Constraints.MaxHeight:=30;
Parent:=Self;
end;
FLabel:=TLabel.Create(Self);
FLabel.WordWrap:=True;
FLabel.Constraints.MaxWidth:=340;
FLabel.BorderSpacing.Left:=Margin;
FLabel.AutoSize:=True;
FLabel.Parent:=FBPanel;
FGBDisplay:=TGroupBox.Create(Self);
with FGBDisplay do begin
Align:=alClient;
BorderSpacing.Around:=Margin*2;
AutoSize:=True;
Parent:=Self;
end;
FDualDisplay:=TDualDisplay.Create(Self);
with FDualDisplay do begin
Align:=alClient;
BorderSpacing.Around:=Margin;
Parent:=FGBDisplay;
if FSingleMenuOnly then begin
OnDisplayClick:=@DisplaySingleMenuClick;
AddHeader(lisMenuEditorShortcutSourceProperty);
Caption:=lisMenuEditorShortcuts;
end
else begin
OnDisplayClick:=@DisplayAllDlgClick;
if FShortcutsOnly then begin
AddHeader(lisMenuEditorShortcutSourceProperty);
Caption:=Format(lisMenuEditorSShortcuts, [lurStr]);
end
else begin
AddHeader(lisMenuEditorShortcutSourceProperty);
Caption:=Format(lisMenuEditorSShortcutsAndAcceleratorKeys, [lurStr]);
end;
end;
end;
UpdateContents(FSingleMenuOnly);
FLabel.Caption:=lisMenuEditorClickANonGreyedItemToEditItsShortcut;
AutoSize:=True;
end;
destructor TShortcutDisplayDlg.Destroy;
begin
FreeAndNil(FscList);
inherited Destroy;
end;
procedure TShortcutDisplayDlg.DisplaySingleMenuClick(isHeader: boolean; index: integer);
var
mi: TMenuItem;
sc: TShortCut;
result: boolean;
si: TShadowItemBase;
info: TSCInfo;
isMainSC: boolean;
begin
case isHeader of
True: begin // header click
if (FLastSortIndex = index) or (FscList.Count = 0) then
Exit;
FLastSortIndex:=index;
UpdateFromMenu(index);
end;
False: begin // contents click
info:=TSCInfo(FscList.Objects[index]);
mi:=info.MenuItem;
if (mi <> nil) then
begin
sc:=info.Shortcut;
isMainSC:=(info.Kind = scMenuItemSC);
result:=AddNewOrEditShortcutDlg(mi, isMainSC, sc);
if result then
begin
if isMainSC then
mi.ShortCut:=sc
else
mi.ShortCutKey2:=sc;
si:=FShadowMenu.GetShadowForMenuItem(mi);
if (si <> nil) then begin
FShadowMenu.UpdateBoxLocationsAndSizes;
si.Repaint;
end;
FShortcuts.UpdateShortcutList(False);
UpdateFromMenu;
GlobalDesignHook.RefreshPropertyValues;
GlobalDesignHook.Modified(mi);
FShadowMenu.RefreshFakes;
end;
end;
end;
end; // case
end;
procedure TShortcutDisplayDlg.DisplayAllDlgClick(isHeader: boolean; index: integer);
var
i: integer;
dt: TDisplayType;
inf: TSCInfo;
mi: TMenuItem;
sc: TShortCut;
isMainSC, isCaptionSC, result: boolean;
si: TShadowItemBase;
begin
case isHeader of
True: begin
if (FLastSortIndex = index) or (FDualDisplay.ContentsCount = 0) then
Exit;
FLastSortIndex:=index;
FDualDisplay.ClearContents;
case index of
0: FShortcuts.ShortcutList.ScanList.Sort;
1: FShortcuts.ShortcutList.SortByComponentPropertyName;
end;
for i:=0 to FShortcuts.ShortcutList.ScanList.Count-1 do
begin
inf:=TSCInfo(FShortcuts.ShortcutList.ScanList.Objects[i]);
if (inf.Kind in MenuItem_Kinds) then
dt:=dtBlack
else
dt:=dtGreyed;
FDualDisplay.AddLine(FShortcuts.ShortcutList.ScanList[i] + ',' +
inf.Component.Name+ '.' + KindToPropertyName(inf.Kind), dt);
end;
end;
False: begin
inf:=TSCInfo(FShortcuts.ShortcutList.ScanList.Objects[index]);
mi:=inf.MenuItem;
if (mi <> nil) then
begin
isMainSC:=(inf.Kind in ShortcutOnly_Kinds);
isCaptionSC:=(inf.Kind in Accelerator_Kinds);
sc:=inf.Shortcut;
if isCaptionSC then
result:=EditCaptionDlg(mi, sc)
else result:=AddNewOrEditShortcutDlg(mi, isMainSC, sc);
if result then
begin
if not isCaptionSC and isMainSC then
mi.ShortCut:=sc
else if not isCaptionSC then
mi.ShortCutKey2:=sc;
si:=FShadowMenu.GetShadowForMenuItem(mi);
if (si <> nil) then
begin
FShadowMenu.UpdateBoxLocationsAndSizes;
si.Repaint;
end;
FShortcuts.UpdateShortcutList(True);
UpdateContents;
GlobalDesignHook.RefreshPropertyValues;
GlobalDesignHook.Modified(mi);
FShadowMenu.RefreshFakes;
end;
end;
end;
end; // case
end;
procedure TShortcutDisplayDlg.UpdateContents(singleMenuOnly: boolean);
var
i: integer;
dt: TDisplayType;
kind: TSCKind;
inf: TSCInfo;
begin
FDualDisplay.ClearContents;
if singleMenuOnly then
UpdateFromMenu
else begin
FShortcuts.UpdateShortcutList(not FShortcutsOnly);
if (FShortcuts.ShortcutList.ScanList.Count = 0) then
begin
FDualDisplay.AddLine(lisMenuEditorNoneNone, dtGreyed);
if FShortcutsOnly then
FGBDisplay.Caption:=lisMenuEditorShortcuts
else
FGBDisplay.Caption:=lisMenuEditorShortcutsAndAcceleratorKeys;
end
else
begin
if FShortcutsOnly then
FGBDisplay.Caption:=Format(lisMenuEditorShortcutsD,
[FShortcuts.ShortcutList.ShortcutsInContainerCount])
else
FGBDisplay.Caption:=Format(lisMenuEditorShortcutsDAndAcceleratorKeysD,
[FShortcuts.ShortcutList.ShortcutsInContainerCount,
FShortcuts.ShortcutList.AcceleratorsInContainerCount]);
FDualDisplay.BeginUpdate;
for i:=0 to FShortcuts.ShortcutList.ScanList.Count-1 do
begin
inf:=TSCInfo(FShortcuts.ShortcutList.ScanList.Objects[i]);
kind:=inf.Kind;
if (kind in MenuItem_Kinds) then
dt:=dtBlack
else
dt:=dtGreyed;
FDualDisplay.AddLine(FShortcuts.ShortcutList.ScanList[i] + ',' +
inf.Component.Name + '.' + KindToPropertyName(inf.Kind), dt);
end;
FDualDisplay.EndUpdate;
end;
end;
end;
procedure TShortcutDisplayDlg.AddSCitemToListRecursive(anItem: TMenuItem);
var
inf: TSCInfo;
i: integer;
begin
if (anItem.ShortCut <> 0) then begin
inf:=TSCInfo.CreateWithParams(anItem, scMenuItemSC, anItem.ShortCut);
FscList.AddObject(ShortCutToText(anItem.ShortCut), TObject(inf));
end;
if (anItem.ShortCutKey2 <> 0) and (anItem.ShortCutKey2 <> anItem.ShortCut) then begin
inf:=TSCInfo.CreateWithParams(anItem, scMenuItemKey2, anItem.ShortCutKey2);
FscList.AddObject(ShortCutToText(anItem.ShortCutKey2), TObject(inf));
end;
for i:=0 to anItem.Count-1 do
AddSCitemToListRecursive(anItem[i]);
end;
procedure TShortcutDisplayDlg.UpdateFromMenu(anIndex: integer);
var
i: integer;
inf: TSCInfo;
begin
Assert(FMenu<>nil,'TShortcutDisplayDlg.UpdateFromMenu: FMenu is nil');
FreeAndNil(FscList);
FscList:=TStringList.Create;
FscList.CaseSensitive:=False;
FDualDisplay.ClearContents;
for i:=0 to FMenu.Items.Count-1 do
AddSCitemToListRecursive(FMenu.Items[i]);
if (FscList.Count = 0) then
begin
FDualDisplay.AddLine(lisMenuEditorNoneNone, dtGreyed);
FGBDisplay.Caption:=lisMenuEditorShortcuts;
end
else
begin
FGBDisplay.Caption := Format(lisMenuEditorShortcutsUsedInSD,
[FMenu.Name, FscList.Count]);
case anIndex of
-1: ; // unsorted
0: FscList.Sort;
1: FscList.CustomSort(@SortByComponentPropertyName);
end;
FDualDisplay.BeginUpdate;
for i:=0 to FscList.Count-1 do
begin
inf:=TSCInfo(FscList.Objects[i]);
FDualDisplay.AddLine(FscList[i] + ',' +
inf.Component.Name + '.' + KindToPropertyName(inf.Kind), dtBlack);
end;
FDualDisplay.EndUpdate;
FDualDisplay.InvalidateContents;
end;
end;
{ TLineEditor } { TLineEditor }
constructor TLineEditor.CreateWithShadowItem(aSI: TShadowItem); constructor TLineEditor.CreateWithShadowItem(aSI: TShadowItem);