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
constructor Create(AOwner: TComponent; aMenu: TMenu); reintroduce;
destructor Destroy; override;
procedure RefreshFakes; virtual; abstract;
procedure SetSelectedMenuItem(aMI: TMenuItem;
viaDesigner, prevWasDeleted: boolean); virtual; abstract;
procedure UpdateBoxLocationsAndSizes; virtual; abstract;

View File

@ -30,8 +30,6 @@ uses
Classes, SysUtils, Types, typinfo,
Controls, StdCtrls, ExtCtrls, Forms, Graphics, Buttons, Menus, ButtonPanel,
ImgList, Themes, LCLintf, LCLProc,
// LazUtils
LazUTF8,
// IdeIntf
FormEditingIntf, PropEdits,
// IDE
@ -107,23 +105,6 @@ type
//property AcceleratorMenuItemsCount: integer read FAcceleratorMenuItemsCount;
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;
TRadioIconState = (risUp, risDown, risPressed, risUncheckedHot, risCheckedHot);
@ -191,7 +172,6 @@ type
end;
function GetNestingLevelDepth(aMenu: TMenu): integer;
function EditCaptionDlg(aMI: TMenuItem; var aShortcut: TShortCut): boolean;
function ChooseIconFromImageListDlg(anImageList: TCustomImageList): integer;
@ -221,20 +201,6 @@ begin
CheckLevel(aMenu.Items[i], 0);
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;
var
dlg: TdlgChooseIcon;
@ -732,91 +698,6 @@ begin
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 }
constructor TRadioIcon.CreateWithGlyph(aRIGroup: TRadioIconGroup;

View File

@ -7,13 +7,13 @@ interface
uses
// FCL + LCL
Classes, SysUtils, Types, typinfo,
ActnList, ButtonPanel, Controls, Dialogs, StdCtrls, ExtCtrls, Menus,
ActnList, Controls, Dialogs, StdCtrls, ExtCtrls, Menus,
Forms, Graphics, ImgList, Themes, LCLType, LCLIntf, LCLProc,
// IdeIntf
FormEditingIntf, IDEWindowIntf, ComponentEditors, IDEDialogs, PropEdits,
// IDE
LazarusIDEStrConsts,
MenuDesignerBase, MenuEditorForm, MenuShortcuts, MenuTemplates, MenuResolveConflicts;
LazarusIDEStrConsts, MenuDesignerBase, MenuEditorForm, MenuShortcutDisplay,
MenuTemplates, MenuResolveConflicts;
type
@ -240,7 +240,7 @@ type
aSelect: TMenuItem; aWidth, aHeight: integer); reintroduce;
destructor Destroy; override;
procedure HideBoxesAboveLevel(aLevel: integer);
procedure RefreshFakes;
procedure RefreshFakes; override;
procedure SetSelectedMenuItem(aMI: TMenuItem;
viaDesigner, prevWasDeleted: boolean); override;
procedure UpdateBoxLocationsAndSizes; override;
@ -329,33 +329,6 @@ type
property EditedLine: string read GetEditedLine;
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
function ItemStateToStr(aState: TShadowItemDisplayState): string;
@ -465,21 +438,6 @@ begin
Inc(Result);
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;
var
tmp: TMenuItem;
@ -538,33 +496,6 @@ begin
Result:=0;
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 }
function TAddFirstFake.GetShouldBeVisible: boolean;
@ -688,312 +619,6 @@ begin
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 }
constructor TLineEditor.CreateWithShadowItem(aSI: TShadowItem);