From a401e01dd991070ef3003ae339df8a3e28502eaa Mon Sep 17 00:00:00 2001 From: Mark van Renswoude Date: Mon, 17 Apr 2006 18:41:43 +0000 Subject: [PATCH] Added: CursorGroup/Item properties Added: OnSelectedChanging/OnSelectedChanged events Added: design-time editor Fixed: drawing of disabled items in the unaMenuBarPainter --- Packages/X2CLMBEditors.pas | 51 +++ Packages/X2CLMBReg.pas | 5 +- Packages/X2CLMenuBarEditor.dfm | 253 +++++++++++++ Packages/X2CLMenuBarEditor.pas | 503 +++++++++++++++++++++++++ Resources/Icons/MenuBar/Add Group.ico | Bin 0 -> 1406 bytes Resources/Icons/MenuBar/Add Item.ico | Bin 0 -> 1406 bytes Resources/Icons/MenuBar/Delete.ico | Bin 0 -> 1406 bytes Source/X2CLMenuBar.pas | 369 +++++++++++++----- Source/X2CLmusikCubeMenuBarPainter.pas | 33 +- Source/X2CLunaMenuBarPainter.pas | 21 +- Test/MenuBar/MainForm.dfm | 125 ++++-- Test/MenuBar/MainForm.pas | 81 ++++ 12 files changed, 1303 insertions(+), 138 deletions(-) create mode 100644 Packages/X2CLMBEditors.pas create mode 100644 Packages/X2CLMenuBarEditor.dfm create mode 100644 Packages/X2CLMenuBarEditor.pas create mode 100644 Resources/Icons/MenuBar/Add Group.ico create mode 100644 Resources/Icons/MenuBar/Add Item.ico create mode 100644 Resources/Icons/MenuBar/Delete.ico diff --git a/Packages/X2CLMBEditors.pas b/Packages/X2CLMBEditors.pas new file mode 100644 index 0000000..39557a0 --- /dev/null +++ b/Packages/X2CLMBEditors.pas @@ -0,0 +1,51 @@ +{ + :: Contains the design-time editor for the MenuBar + :: + :: Last changed: $Date$ + :: Revision: $Rev$ + :: Author: $Author$ +} +unit X2CLMBEditors; + +interface +uses + DesignEditors; + +type + TX2MenuBarComponentEditor = class(TComponentEditor) + public + procedure Edit(); override; + procedure ExecuteVerb(Index: Integer); override; + function GetVerb(Index: Integer): string; override; + function GetVerbCount(): Integer; override; + end; + +implementation +uses + X2CLMenuBar, + X2CLMenuBarEditor; + + +{ TX2MenuBarComponentEditor } +procedure TX2MenuBarComponentEditor.Edit(); +begin + if Assigned(Component) and (Component is TX2CustomMenuBar) then + TfrmMenuBarEditor.Execute(TX2CustomMenuBar(Component), Designer); +end; + +procedure TX2MenuBarComponentEditor.ExecuteVerb(Index: Integer); +begin + Edit(); +end; + +function TX2MenuBarComponentEditor.GetVerb(Index: Integer): string; +begin + Result := 'Edit...'; +end; + +function TX2MenuBarComponentEditor.GetVerbCount(): Integer; +begin + Result := 1; +end; + +end. diff --git a/Packages/X2CLMBReg.pas b/Packages/X2CLMBReg.pas index 4837781..f5bc439 100644 --- a/Packages/X2CLMBReg.pas +++ b/Packages/X2CLMBReg.pas @@ -16,7 +16,8 @@ uses DesignIntf, X2CLMenuBar, X2CLmusikCubeMenuBarPainter, - X2CLunaMenuBarPainter; + X2CLunaMenuBarPainter, + X2CLMBEditors; {.$R ..\Resources\MenuBar.dcr} @@ -25,6 +26,8 @@ begin RegisterComponents('X2Software', [TX2MenuBar, TX2MenuBarmusikCubePainter, TX2MenuBarunaPainter]); + + RegisterComponentEditor(TX2CustomMenuBar, TX2MenuBarComponentEditor); end; end. diff --git a/Packages/X2CLMenuBarEditor.dfm b/Packages/X2CLMenuBarEditor.dfm new file mode 100644 index 0000000..af3b639 --- /dev/null +++ b/Packages/X2CLMenuBarEditor.dfm @@ -0,0 +1,253 @@ +object frmMenuBarEditor: TfrmMenuBarEditor + Left = 0 + Top = 0 + BorderIcons = [biSystemMenu] + Caption = 'Editing' + ClientHeight = 376 + ClientWidth = 276 + Color = clBtnFace + Font.Charset = DEFAULT_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'Tahoma' + Font.Style = [] + FormStyle = fsStayOnTop + OldCreateOrder = False + Position = poOwnerFormCenter + OnClose = FormClose + OnCreate = FormCreate + OnDestroy = FormDestroy + PixelsPerInch = 96 + TextHeight = 13 + object tvMenu: TTreeView + Left = 0 + Top = 26 + Width = 276 + Height = 331 + Align = alClient + HideSelection = False + Indent = 19 + ReadOnly = True + TabOrder = 0 + OnChange = tvMenuChange + ExplicitTop = 20 + ExplicitWidth = 252 + ExplicitHeight = 281 + end + object sbStatus: TStatusBar + Left = 0 + Top = 357 + Width = 276 + Height = 19 + Panels = < + item + Width = 50 + end> + ExplicitTop = 307 + ExplicitWidth = 252 + end + object tbMenu: TToolBar + Left = 0 + Top = 0 + Width = 276 + Height = 26 + AutoSize = True + ButtonWidth = 84 + EdgeBorders = [ebTop, ebBottom] + Images = ilsActions + List = True + ShowCaptions = True + TabOrder = 2 + ExplicitWidth = 252 + object tbAddGroup: TToolButton + Left = 0 + Top = 0 + Action = actAddGroup + AutoSize = True + end + object tbAddItem: TToolButton + Left = 81 + Top = 0 + Action = actAddItem + AutoSize = True + end + object tbDelete: TToolButton + Left = 154 + Top = 0 + Action = actDelete + AutoSize = True + end + end + object ilsActions: TImageList + Left = 8 + Top = 32 + Bitmap = { + 494C010103000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600 + 0000000000003600000028000000400000001000000001002000000000000010 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000007FA5 + B8000B70A0001678A4004487A700000000000000000000000000007500000075 + 0000006D000000000000000000000000000000000000000000009B7C6B009B7C + 6B009B7C6B009B7C6B009B7C6B009B7C6B009B7C6B00BFABA100007500000075 + 0000006D0000BFABA100000000000000000000000000000000002427AE00161C + AC005A5AA90000000000000000000000000000000000000000005353A9004F4F + A200000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000002F94 + BD000079AC004CD9F7000CA3D20097CBDF0095C6DB008FBACF00007D000044DD + 77000075000000000000000000000000000000000000000000009B776600FFFF + FF00FCF6ED00FCF6ED00FCF6ED00FCF6ED00FAF3E700FCF8F100007D000044DD + 770000750000BDA99D000000000000000000000000004E4EAB001844F600194D + F8001031D2002427AE000000000000000000000000004E4EAB000928D700092E + D7000313B3004E4EAB0000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000689BAF001989 + B700007EB10090EFFF0030E0FF007AEEFF0000860000008600000086000048E1 + 7B00007500000075000000750000000000000000000000000000A27F6F00FFFF + FF00DDC1B400DDC1B400DDC1B400E9D6CD0000860000008600000086000048E1 + 7B0000750000007500000075000000000000000000002022B1002451F9001F51 + FF00194DF8001744E8001017AF00000000004545AD00092ED7001142F9000D3D + F5000D3DF500041ABC006F6FAA00000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000003B92B4003B9F + C600007EB1009FF1FF0046E2FF0090EFFF00008D00005EF791005AF38D0053EC + 860048E17B0045DE780000750000000000000000000000000000A3807000FFFF + FF00DBC4BD00DBC4BD00DDC1B400EBDCD600008D00005EF791005AF38D0053EC + 860048E17B0045DE7800007500000000000000000000000000001832DB00285A + FF002451F9002451F9001A4AF100060EAF000F30DD00164AFE001142F9001041 + F6000D3DF5000D3DF5002C2CA200000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000074A0B1000E84B700B6F5 + FB000081B400B6F5FB005EECFF00A3F3FF0000910000008D0000008D00005AF3 + 8D0000860000007D0000007D0000000000000000000000000000A9877800FFFF + FF00DBC6C200DBC4BD00DBC4BD00EBDCD60000910000008D0000008D00005AF3 + 8D0000860000007D0000007D000000000000000000007777B3001832DB004170 + FF002D5DFF00285AFF00285AFF001F51FF00194DF800194DF8001142F9001142 + F9000F3DF200161CAC0000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000004596B40044A5C900DDFF + FF000084B700C0FBFF0077F4FF00B6F5FB00ADF6FF00ADF6FF00008D00005EF7 + 910000860000C3F1F80061A8C700000000000000000000000000AB897A00FFFF + FF00DBC6C200DBC6C200DBC4BD00EBDED900EBDCD600EBDCD600008D00005EF7 + 910000860000C8B7AE00000000000000000000000000000000006969B8001A25 + C5003A6DFF003668FF00285AFF00285AFF002451F900194DF8001F51FF00123D + ED002427AE000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000002790B800ABDCEA00E6FE + FE000084B700D2FFFF008EFDFF0089FAFF0082F6FF00B0F7FF00009100000091 + 0000008D0000C1FDFF000072A500000000000000000000000000AB897A00FFFF + FF00DBC6C200DBC4BD00DBC4BD00DBC4BD00DBBFB400EBDCD600009100000091 + 0000008D0000BFABA10000000000000000000000000000000000000000000000 + 00002F2FB3002E4EE7003668FF00285AFF00285AFF002451F900123DED002C2C + A200000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000000000000A8CBC00C9F6FA00F1FF + FF000088BB00DDFFFF00A1FFFF00A1FFFF0094F8FF00C0FBFF00C0FBFF00B0F7 + FF00C3EDF500DDFFFF000072A500000000000000000000000000B1908000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FCF8F100FFFFFF00FCF8F100FFFFFF00FCF8 + F100FCF6ED009B7C6B0000000000000000000000000000000000000000000000 + 000000000000253FDF003A6DFF003668FF002D5DFF00285AFF001B46EA002427 + AE00000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000018DC0000F92C1007EC4 + DD000088BB00C3EDF5007ADBEA0085E3EF0092F0F800A1FFFF0094F8FF0065D2 + E700ADF6FF00DDFFFF000079AC00000000000000000000000000AF8F8000FFFF + FF00DFCDCB00DFCDCB00DBC6C200DECAC600DDC1B400DDC1B400DEBEAD00DEBE + AD00FCF6ED009B7C6B0000000000000000000000000000000000000000000000 + 00002B2CC0004B7CFF004170FF003A6DFF003A6DFF00285AFF00285AFF001031 + D2004A4AB2000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000018DC000F1FFFF00C3F1F800ABE7F10081D4E60065C6DF0065C6DF005FC2 + DB00D2FFFF00E6FEFE000079AC00000000000000000000000000B1908000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FCF8F100FCF8F100F9F4 + EE00F0E8E0009C7D6D0000000000000000000000000000000000000000000000 + 0000253FDF00527CFA004170FF003668FF000C13C1003A6DFF00285AFF002451 + F9000B1DC2000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00001A96C50031A5CD004AB0D30083CDE200D0EFF600E6FEFE00F1FFFF00E6FE + FE00DDFFFF00F1FFFF000079AC00000000000000000000000000B1908000FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00A3807000A782 + 7000A7827000A380700000000000000000000000000000000000000000004F4F + BD00527CFA005080FF004B7CFF00181FC500000000001B22C4003A6DFF00285A + FF001A4AF1001419B10000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000589FBA003298BE002390BC00158FBF00FFFF + FF00FFFFFF00FFFFFF00007EB100000000000000000000000000B8988800FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FCF8F100FFFFFF00A7827000F5E2 + D900B1908000AB9E98000000000000000000000000000000000000000000252D + D6006A9CFF005788FF002E4EE7007070B90000000000000000001621C7002D5D + FF002451F9001439DD004545AD00000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000000088BB00EDF6 + FA00FFFFFF00FFFFFF00007EB100000000000000000000000000B8988800FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00A7827000B08E + 7D00AB9E98000000000000000000000000000000000000000000000000004B4B + C8003951E2005080FF002929C600000000000000000000000000000000001628 + D300285AFF000F2EE3002123B500000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000002F99C3000084 + B7000084B7000081B4004388A900000000000000000000000000B8988800B898 + 8800B1908000B1908000B1908000B08E7D00AC887700AC887700A7827000AB9E + 9800000000000000000000000000000000000000000000000000000000000000 + 0000000000003E3EB90000000000000000000000000000000000000000006B6B + B6002E2EB5000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 000000000000000000000000000000000000424D3E000000000000003E000000 + 2800000040000000100000000100010000000000800000000000000000000000 + 000000000000000000000000FFFFFF00FFFFFFFFFFFF0000E1C7C003C7CF0000 + E007C00383830000C001C00181010000C001C001C00100008001C00180030000 + 8001C003C00700008001C003F00F00008001C003F80F00008001C003F0070000 + F001C003F0070000F001C003E0830000FE01C003E0C10000FFC1C007E1E10000 + FFC1C00FFBE70000FFFFFFFFFFFF000000000000000000000000000000000000 + 000000000000} + end + object alMenu: TActionList + Images = ilsActions + Left = 36 + Top = 32 + object actAddGroup: TAction + Caption = '&Add group' + ImageIndex = 0 + ShortCut = 45 + SecondaryShortCuts.Strings = ( + 'Ctrl+N') + OnExecute = actAddGroupExecute + end + object actAddItem: TAction + Caption = '&Add item' + ImageIndex = 1 + ShortCut = 45 + SecondaryShortCuts.Strings = ( + 'Ctrl+N') + OnExecute = actAddItemExecute + end + object actDelete: TAction + Caption = '&Delete' + ImageIndex = 2 + ShortCut = 46 + SecondaryShortCuts.Strings = ( + 'Ctrl+Del') + OnExecute = actDeleteExecute + end + end +end diff --git a/Packages/X2CLMenuBarEditor.pas b/Packages/X2CLMenuBarEditor.pas new file mode 100644 index 0000000..1b0266b --- /dev/null +++ b/Packages/X2CLMenuBarEditor.pas @@ -0,0 +1,503 @@ +unit X2CLMenuBarEditor; + +interface +uses + ActnList, + Classes, + ComCtrls, + Controls, + DesignIntf, + Forms, + ImgList, + ToolWin, + + X2CLMenuBar; + +type + TfrmMenuBarEditor = class(TForm, IX2MenuBarDesigner) + actAddGroup: TAction; + actAddItem: TAction; + actDelete: TAction; + alMenu: TActionList; + ilsActions: TImageList; + sbStatus: TStatusBar; + tbAddGroup: TToolButton; + tbAddItem: TToolButton; + tbDelete: TToolButton; + tbMenu: TToolBar; + tvMenu: TTreeView; + + procedure actDeleteExecute(Sender: TObject); + procedure actAddItemExecute(Sender: TObject); + procedure actAddGroupExecute(Sender: TObject); + procedure FormCreate(Sender: TObject); + + procedure FormClose(Sender: TObject; var Action: TCloseAction); + procedure FormDestroy(Sender: TObject); + procedure tvMenuChange(Sender: TObject; Node: TTreeNode); + private + FDesigner: IDesigner; + FMenuBar: TX2CustomMenuBar; + FDesignerAttached: Boolean; + + procedure SetMenuBar(const Value: TX2CustomMenuBar); + + procedure AttachDesigner(); + procedure DetachDesigner(); + + function GetSelectedItem(): TX2CustomMenuBarItem; + function GetItemNode(AItem: TX2CustomMenuBarItem): TTreeNode; + protected + procedure Notification(AComponent: TComponent; Operation: TOperation); override; + procedure ItemAdded(AItem: TX2CustomMenuBarItem); + procedure ItemModified(AItem: TX2CustomMenuBarItem); + procedure ItemDeleting(AItem: TX2CustomMenuBarItem); + protected + procedure RefreshMenu(); + function AddGroup(AGroup: TX2MenuBarGroup): TTreeNode; + function AddItem(ANode: TTreeNode; AItem: TX2MenuBarItem): TTreeNode; + + procedure UpdateNode(ANode: TTreeNode); + procedure UpdateUI(); + procedure Modified(); + + property Designer: IDesigner read FDesigner write FDesigner; + property MenuBar: TX2CustomMenuBar read FMenuBar write SetMenuBar; + public + class procedure Execute(AMenuBar: TX2CustomMenuBar; ADesigner: IDesigner); + end; + +implementation +uses + Contnrs, + SysUtils; + +var + GEditors: TObjectBucketList; + +type + TProtectedX2CustomMenuBar = class(TX2CustomMenuBar); + + +{$R *.dfm} + +{ TfrmMenuBarEditor } +class procedure TfrmMenuBarEditor.Execute(AMenuBar: TX2CustomMenuBar; ADesigner: IDesigner); +var + editorForm: TfrmMenuBarEditor; + +begin + if not Assigned(GEditors) then + GEditors := TObjectBucketList.Create(); + + editorForm := nil; + if GEditors.Exists(AMenuBar) then + editorForm := TfrmMenuBarEditor(GEditors.Data[AMenuBar]); + + if not Assigned(editorForm) then + begin + editorForm := TfrmMenuBarEditor.Create(Application); + editorForm.MenuBar := AMenuBar; + editorForm.Designer := ADesigner; + GEditors.Add(AMenuBar, editorForm); + end; + + editorForm.Show(); +end; + +procedure TfrmMenuBarEditor.FormCreate(Sender: TObject); +begin + {$IFDEF VER180} + // Delphi (BDS) 2006 + tbMenu.EdgeBorders := []; + tbMenu.DrawingStyle := dsGradient; + {$ENDIF} +end; + +procedure TfrmMenuBarEditor.FormClose(Sender: TObject; var Action: TCloseAction); +begin + if Assigned(Designer) and Assigned(MenuBar) then + Designer.SelectComponent(MenuBar); + + Action := caFree; +end; + +procedure TfrmMenuBarEditor.FormDestroy(Sender: TObject); +begin + if Assigned(MenuBar) then + begin + DetachDesigner(); + + if GEditors.Exists(MenuBar) then + GEditors.Remove(MenuBar); + end; +end; + + +procedure TfrmMenuBarEditor.tvMenuChange(Sender: TObject; Node: TTreeNode); +var + item: TX2CustomMenuBarItem; + +begin + if Assigned(Node) then + begin + item := TX2CustomMenuBarItem(Node.Data); + + if Assigned(Designer) then + Designer.SelectComponent(item); + end; + + UpdateUI(); +end; + + +procedure TfrmMenuBarEditor.RefreshMenu(); +var + groupIndex: Integer; + +begin + tvMenu.Items.BeginUpdate(); + try + tvMenu.Items.Clear(); + + if Assigned(MenuBar) then + for groupIndex := 0 to Pred(MenuBar.Groups.Count) do + AddGroup(MenuBar.Groups[groupIndex]); + finally + tvMenu.Items.EndUpdate(); + UpdateUI(); + end; +end; + + +procedure TfrmMenuBarEditor.actAddGroupExecute(Sender: TObject); +begin + MenuBar.Groups.Add(); + Modified(); +end; + +procedure TfrmMenuBarEditor.actAddItemExecute(Sender: TObject); +var + menuItem: TX2CustomMenuBarItem; + group: TX2MenuBarGroup; + +begin + menuItem := GetSelectedItem(); + if Assigned(menuItem) then + begin + group := nil; + + if menuItem is TX2MenuBarGroup then + group := TX2MenuBarGroup(menuItem) + else if menuItem is TX2MenuBarItem then + group := TX2MenuBarItem(menuItem).Group; + + if Assigned(group) then + begin + group.Items.Add(); + if group.Items.Count = 1 then + group.Expanded := True; + + Modified(); + end; + end; +end; + +procedure TfrmMenuBarEditor.actDeleteExecute(Sender: TObject); +var + menuItem: TX2CustomMenuBarItem; + +begin + menuItem := GetSelectedItem(); + if Assigned(menuItem) and Assigned(menuItem.Collection) then + begin + menuItem.Collection.Delete(menuItem.Index); + Modified(); + end; +end; + + +function TfrmMenuBarEditor.AddGroup(AGroup: TX2MenuBarGroup): TTreeNode; +var + itemIndex: Integer; + siblingGroup: TX2MenuBarGroup; + siblingNode: TTreeNode; + groupNode: TTreeNode; + +begin + tvMenu.Items.BeginUpdate(); + try + siblingGroup := nil; + siblingNode := nil; + + { Make sure the group is inserted in the correct position by searching + for it's sibling group. Note: do NOT use Items[x] in a loop; TTreeView + emulates this by using GetFirst/GetNext. } + if AGroup.Index > 0 then + siblingGroup := TX2MenuBarGroup(AGroup.Collection.Items[Pred(AGroup.Index)]); + + if Assigned(siblingGroup) then + begin + siblingNode := tvMenu.Items.GetFirstNode(); + while Assigned(siblingNode) do + begin + if siblingNode.Data = siblingGroup then + break; + + siblingNode := siblingNode.GetNextSibling(); + end; + end; + + if Assigned(siblingNode) then + groupNode := tvMenu.Items.Add(siblingNode, '') + else + groupNode := tvMenu.Items.AddFirst(nil, ''); + + groupNode.Data := AGroup; + UpdateNode(groupNode); + + { Add items } + for itemIndex := 0 to Pred(AGroup.Items.Count) do + AddItem(groupNode, AGroup.Items[itemIndex]); + + groupNode.Expand(False); + Result := groupNode; + finally + tvMenu.Items.EndUpdate(); + end; +end; + +function TfrmMenuBarEditor.AddItem(ANode: TTreeNode; AItem: TX2MenuBarItem): TTreeNode; +var + siblingItem: TX2MenuBarItem; + siblingNode: TTreeNode; + itemNode: TTreeNode; + +begin + tvMenu.Items.BeginUpdate(); + try + siblingItem := nil; + siblingNode := nil; + + { See AddGroup } + if AItem.Index > 0 then + siblingItem := TX2MenuBarItem(AItem.Collection.Items[Pred(AItem.Index)]); + + if Assigned(siblingItem) then + begin + siblingNode := ANode.GetFirstChild(); + while Assigned(siblingNode) do + begin + if siblingNode.Data = siblingItem then + break; + + siblingNode := siblingNode.GetNextSibling(); + end; + end; + + if Assigned(siblingNode) then + itemNode := tvMenu.Items.Add(siblingNode, '') + else + itemNode := tvMenu.Items.AddChildFirst(ANode, ''); + + itemNode.Data := AItem; + UpdateNode(itemNode); + + Result := itemNode; + finally + tvMenu.Items.EndUpdate(); + end; +end; + +procedure TfrmMenuBarEditor.UpdateNode(ANode: TTreeNode); +var + menuItem: TX2CustomMenuBarItem; + +begin + menuItem := TX2CustomMenuBarItem(ANode.Data); + ANode.Text := menuItem.Caption; + ANode.ImageIndex := menuItem.ImageIndex; + ANode.SelectedIndex := ANode.ImageIndex; +end; + +procedure TfrmMenuBarEditor.UpdateUI(); +var + itemSelected: Boolean; + +begin + itemSelected := Assigned(tvMenu.Selected); + actAddGroup.Enabled := Assigned(MenuBar); + actAddItem.Enabled := itemSelected; + actDelete.Enabled := itemSelected; +end; + +procedure TfrmMenuBarEditor.Modified(); +begin + if Assigned(Designer) then + Designer.Modified(); + + UpdateUI(); +end; + + +procedure TfrmMenuBarEditor.Notification(AComponent: TComponent; Operation: TOperation); +begin + if (Operation = opRemove) and (AComponent = MenuBar) then + begin + DetachDesigner(); + Release(); + end; + + inherited; +end; + +procedure TfrmMenuBarEditor.ItemAdded(AItem: TX2CustomMenuBarItem); +var + group: TX2MenuBarGroup; + groupNode: TTreeNode; + treeNode: TTreeNode; + +begin + treeNode := nil; + + if AItem is TX2MenuBarGroup then + treeNode := AddGroup(TX2MenuBarGroup(AItem)) + else if AItem is TX2MenuBarItem then + begin + group := TX2MenuBarItem(AItem).Group; + groupNode := nil; + + if Assigned(group) then + groupNode := GetItemNode(group); + + if Assigned(groupNode) then + treeNode := AddItem(groupNode, TX2MenuBarItem(AItem)); + end; + + if Assigned(treeNode) then + tvMenu.Selected := treeNode; +end; + +procedure TfrmMenuBarEditor.ItemModified(AItem: TX2CustomMenuBarItem); +var + treeNode: TTreeNode; + +begin + tvMenu.Items.BeginUpdate(); + try + treeNode := tvMenu.Items.GetFirstNode(); + while Assigned(treeNode) do + begin + UpdateNode(treeNode); + treeNode := treeNode.GetNext(); + end; + finally + tvMenu.Items.EndUpdate(); + end; +end; + +procedure TfrmMenuBarEditor.ItemDeleting(AItem: TX2CustomMenuBarItem); +var + treeNode: TTreeNode; + +begin + treeNode := GetItemNode(AItem); + if Assigned(treeNode) then + tvMenu.Items.Delete(treeNode); +end; + + +procedure TfrmMenuBarEditor.AttachDesigner(); +begin + if FDesignerAttached or (not Assigned(MenuBar)) then + exit; + + TProtectedX2CustomMenuBar(MenuBar).Designer := Self; + FDesignerAttached := True; +end; + +procedure TfrmMenuBarEditor.DetachDesigner(); +begin + if not FDesignerAttached then + exit; + + FDesignerAttached := False; + if Assigned(MenuBar) then + TProtectedX2CustomMenuBar(MenuBar).Designer := nil; +end; + + +function TfrmMenuBarEditor.GetSelectedItem(): TX2CustomMenuBarItem; +begin + Result := nil; + if Assigned(tvMenu.Selected) then + Result := TX2CustomMenuBarItem(tvMenu.Selected.Data); +end; + +function TfrmMenuBarEditor.GetItemNode(AItem: TX2CustomMenuBarItem): TTreeNode; +var + treeNode: TTreeNode; + +begin + Result := nil; + treeNode := tvMenu.Items.GetFirstNode(); + while Assigned(treeNode) do + begin + if treeNode.Data = AItem then + begin + Result := treeNode; + break; + end; + + treeNode := treeNode.GetNext(); + end; +end; + + +procedure TfrmMenuBarEditor.SetMenuBar(const Value: TX2CustomMenuBar); +begin + if Value <> FMenuBar then + begin + if Assigned(FMenuBar) then + begin + DetachDesigner(); + FMenuBar.RemoveFreeNotification(Self); + end; + + FMenuBar := Value; + + if Assigned(FMenuBar) then + begin + tvMenu.Images := FMenuBar.Images; + Self.Caption := 'Editing ' + FMenuBar.Name; + + AttachDesigner(); + FMenuBar.FreeNotification(Self); + end else + begin + Self.Caption := ''; + tvMenu.Images := nil; + end; + + RefreshMenu(); + end; +end; + + +procedure FreeEditor(AInfo, AItem, AData: Pointer; out AContinue: Boolean); +begin + with (TObject(AData) as TfrmMenuBarEditor) do + begin + MenuBar := nil; + Free(); + end; +end; + +initialization +finalization + if Assigned(GEditors) then + GEditors.ForEach(FreeEditor); + + FreeAndNil(GEditors); + +end. diff --git a/Resources/Icons/MenuBar/Add Group.ico b/Resources/Icons/MenuBar/Add Group.ico new file mode 100644 index 0000000000000000000000000000000000000000..47cf0750c64baa29810f2ee2aa516e07469ee625 GIT binary patch literal 1406 zcmeH{dq~q!6vw|ZY;8UgXXP!Ip=aOmjgJ^=jH~Q zXClrK5CZTbNWwzGs@sNxefeYm_D_-$Pn;&s5a)?hB8|9CWD+@mtSu3NUy~5raTYkG z0}=}16rT?y7E|66;9Mz$NsoY(a>}m&u2jO6K-zO4{RP#k!HgSv@NeodH=`1Qte5c2 zu7XFl9+KP|NHrDkzgr90wL%1>7a=gO0*AHLh`V2kg#2<`&{ZLGP&68$YBD0_bsIuIS)gd` zMzWy?L7fayy$s1e7!rpVvZ~+VcB27z-WqYar4y+iyHN6_2UoxKBfFm=kGM3nDR|U<6tdL+%K}1JX*mO{o1oh=M_e;-OI#nHio^{6og@%sh@V3$3FJRTQfy8v4w5 z-#?57(+HY}$51!UP)~JRDgHCjM)Z;1H8BAb+0$eC2L8tlu&LkDO1IfdsXT`>*&Y_V zZ&|Z5DA3V~W7~B3d_m~O04|s7!r@pIkJW+$+e3Li-m6@k$zL%iLKv~*5TD2M<~mX{ z@?57BDP$3HInRe1vw<2?h)NW@Z||N+KA(5o6_|HSEmnqyhba`1(Ms|qzMI9-+jj2{ z58EnNy4!Y?sACT9l1ewls_ees+V#OlRce(|ZTBh2YssPobR2;#-ad&>{OkLRM8ai% f{kNOeE9htf+POd-9oWjnDHtHl$^^mcC!yS5B#Qy= literal 0 HcmV?d00001 diff --git a/Resources/Icons/MenuBar/Add Item.ico b/Resources/Icons/MenuBar/Add Item.ico new file mode 100644 index 0000000000000000000000000000000000000000..6fc8bc8c296754c472de5458deed2d5ef98bb2ba GIT binary patch literal 1406 zcmeH{-%C?r7{|ZkFs(Rj%N-4~4owX`a2QFf5_DGv-FMeTml3GAo0z70E7dC!`4;eVjd%jbR1_xW*n-sj>4Otfq^ z(0&4U%|HQwa)MmAKybfdrp$5hoz?Z^@eucjCc+2wdGDaFrIx6}b6-6MS{r}|6blfK ziB6&$sEK)TU2nvV&&?S0doc9SgOLs|hT9tvd~_dUU9EWC<-^Ty0o>Z^#O>W~j6Lz= z%~L-@J#83&){eKm9SHXKVq*9O!oioA9e)M=Ly#DS77iiyF$8V$9rUU9(55C3oeo2r znM7r+fol*^(h z<_Us8+Rju}aaqn4oy|MVbpdm#s>^Dz6p3bfjBtiIo$3`AWr!C^a;>Urxyx#`82^{4 z4d&*nI+w@Kvx*AmB}FMK%V;A`8SbiUCwcs@W_C%kbM4^uR4!eWi~niHq(Vc&;gDsy gFh5_)NS^Ya@exF*Z3B7_BU!S(!%pfmVg-2ZAKyU8CIA2c literal 0 HcmV?d00001 diff --git a/Resources/Icons/MenuBar/Delete.ico b/Resources/Icons/MenuBar/Delete.ico new file mode 100644 index 0000000000000000000000000000000000000000..7db8d4dfc32ce83fc03bb2aebcdba8d45efc74f6 GIT binary patch literal 1406 zcmeH{%}bO~6vlt1eV89JIyyO{HXqL9nB(|SO_?*AgENcKc}-tQb4WB3)Ck>#n-+a+ z`XgGo%F+fCqo6<|vt3Y-L`Yf-LkKKLQnA~8M~i~C?Yu9~dCqyxz30NYF9#Cjr`IFx zK6-b95pYRJ39E#r$5+A@{r0!xJ?Sy@2V!KHVi@yANimvA^nBr=Aoj?msdBIElq|Ac{o zJ6yc@fWE$m3=K^%IQWQE!!#-RPsy>&V6@GWYk!8>IYY8*j%3dqX`XqEuGi?w=FykG z!r+}Fr{W!!ek2(u44@Uz!dq8DZGg}BFIw&mL@@QXbF$9L}k+l z98GK3nm4hx2pnewht3LI?ShhX0`K{C%6bGxCA_@?fBy!R{eqL11U`xS`WMs=3WArV ze?`!IWu4aR8=Sr>XuT=uza{>7s2z8w1OKN3Lj3DLOHDGxugfvSDf?8&ohrTTLf7tW z$>~ZsE8z3($&-RdRg~I<;$Wc0=aX~B;^}Bn)o>^j2vj9$6%HPXwyCNT3ZKx* zXiMLq2`9FPk`#_b+gjA>UunuaJEBolb(`b6WxA`Q%@$P^`&OLW)!kWuGpg3^jSEM5 zE;Lxd(V~=PX~MZkcZJ4>Rj*EC$c)?kj5z&mv=+?1gc~>Dnw*DI5?2!?%i1gQ_;-mF T&6ik^dlsf)aS=9_Ks);rN^Q0Y literal 0 HcmV?d00001 diff --git a/Source/X2CLMenuBar.pas b/Source/X2CLMenuBar.pas index b29d201..8a27f82 100644 --- a/Source/X2CLMenuBar.pas +++ b/Source/X2CLMenuBar.pas @@ -31,10 +31,7 @@ const type // #ToDo1 (MvR) 25-3-2006: various Select methods for key support // #ToDo1 (MvR) 1-4-2006: scroll wheel support - // #ToDo1 (MvR) 2-4-2006: OnSelectionChanging event - // #ToDo1 (MvR) 2-4-2006: OnSelectionChanged event - // #ToDo1 (MvR) 2-4-2006: disabled drawing - // #ToDo1 (MvR) 2-4-2006: OnGetAnimationClass event + // #ToDo1 (MvR) 2-4-2006: OnGetAnimationClass event? TX2CustomMenuBarAnimatorClass = class of TX2CustomMenuBarAnimator; TX2CustomMenuBarAnimator = class; TX2CustomMenuBarPainterClass = class of TX2CustomMenuBarPainter; @@ -44,34 +41,41 @@ type TX2MenuBarGroup = class; TX2CustomMenuBar = class; + IX2MenuBarDesigner = interface + ['{F648CFD2-771D-4531-84D0-621FD7597E48}'] + procedure ItemAdded(AItem: TX2CustomMenuBarItem); + procedure ItemModified(AItem: TX2CustomMenuBarItem); + procedure ItemDeleting(AItem: TX2CustomMenuBarItem); + end; + TX2MenuBarHitTest = record HitTestCode: Integer; Item: TX2CustomMenuBarItem; end; - TX2MenuBarDrawState = (mdsHot, mdsSelected, mdsGroupHot, - mdsGroupSelected); - TX2MenuBarDrawStates = set of TX2MenuBarDrawState; + TX2MenuBarDrawState = (mdsHot, mdsSelected, mdsGroupHot, mdsGroupSelected); + TX2MenuBarDrawStates = set of TX2MenuBarDrawState; - TX2MenuBarSpacingElement = (seBeforeGroupHeader, seAfterGroupHeader, - seBeforeFirstItem, seAfterLastItem, - seBeforeItem, seAfterItem); + TX2MenuBarSpacingElement = (seBeforeGroupHeader, seAfterGroupHeader, + seBeforeFirstItem, seAfterLastItem, + seBeforeItem, seAfterItem); - TX2MenuBarOnExpandingEvent = procedure(Sender: TObject; - Group: TX2MenuBarGroup; - var Allowed: Boolean) of object; - TX2MenuBarOnExpandedEvent = procedure(Sender: TObject; - Group: TX2MenuBarGroup) of object; + TX2MenuBarSelectAction = (saBefore, saAfter, saBoth); - TX2MenuBarItemBoundsProc = procedure(Sender: TObject; - Item: TX2CustomMenuBarItem; - const MenuBounds: TRect; - const ItemBounds: TRect; - Data: Pointer; - var Abort: Boolean) of object; + TX2MenuBarExpandingEvent = procedure(Sender: TObject; Group: TX2MenuBarGroup; var Allowed: Boolean) of object; + TX2MenuBarExpandedEvent = procedure(Sender: TObject; Group: TX2MenuBarGroup) of object; + TX2MenuBarSelectedChangingEvent = procedure(Sender: TObject; Item, NewItem: TX2CustomMenUBarItem; var Allowed: Boolean) of object; + TX2MenuBarSelectedChangedEvent = procedure(Sender: TObject; Item: TX2CustomMenUBarItem) of object; - TCollectionUpdateEvent = procedure(Sender: TObject; - Item: TCollectionItem) of object; + TX2MenuBarItemBoundsProc = procedure(Sender: TObject; + Item: TX2CustomMenuBarItem; + const MenuBounds: TRect; + const ItemBounds: TRect; + Data: Pointer; + var Abort: Boolean) of object; + + TCollectionNotifyEvent = procedure(Sender: TObject; Item: TCollectionItem; Action: TCollectionNotification) of object; + TCollectionUpdateEvent = procedure(Sender: TObject; Item: TCollectionItem) of object; IX2MenuBarPainterObserver = interface ['{22DE60C9-49A1-4E7D-B547-901BEDCC0FB7}'] @@ -193,11 +197,14 @@ type } TX2CustomMenuBarItems = class(TOwnedCollection) private - FOnUpdate: TCollectionUpdateEvent; + FOnNotify: TCollectionNotifyEvent; + FOnUpdate: TCollectionUpdateEvent; protected + procedure Notify(Item: TCollectionItem; Action: TCollectionNotification); override; procedure Update(Item: TCollectionItem); override; - property OnUpdate: TCollectionUpdateEvent read FOnUpdate write FOnUpdate; + property OnNotify: TCollectionNotifyEvent read FOnNotify write FOnNotify; + property OnUpdate: TCollectionUpdateEvent read FOnUpdate write FOnUpdate; end; { @@ -207,6 +214,8 @@ type private function GetGroup(): TX2MenuBarGroup; public + constructor Create(Collection: TCollection); override; + property Group: TX2MenuBarGroup read GetGroup; end; @@ -241,6 +250,7 @@ type procedure SetEnabled(const Value: Boolean); override; procedure InternalSetExpanded(const Value: Boolean); + procedure ItemsNotify(Sender: TObject; Item: TCollectionItem; Action: TCollectionNotification); procedure ItemsUpdate(Sender: TObject; Item: TCollectionItem); property SelectedItem: Integer read GetSelectedItem write FSelectedItem; @@ -278,27 +288,32 @@ type } TX2CustomMenuBar = class(TCustomControl, IX2MenuBarPainterObserver) private - FAllowCollapseAll: Boolean; - FAnimationStyle: TX2MenuBarAnimationStyle; - FAnimationTime: Cardinal; - FAnimator: TX2CustomMenuBarAnimator; - FAutoCollapse: Boolean; - FAutoSelectItem: Boolean; - FBorderStyle: TBorderStyle; - FExpandingGroups: TStringList; - FGroups: TX2MenuBarGroups; - FHideScrollbar: Boolean; - FHotItem: TX2CustomMenuBarItem; - FImageList: TCustomImageList; - FLastMousePos: TPoint; - FOnCollapsed: TX2MenuBarOnExpandedEvent; - FOnCollapsing: TX2MenuBarOnExpandingEvent; - FOnExpanded: TX2MenuBarOnExpandedEvent; - FOnExpanding: TX2MenuBarOnExpandingEvent; - FPainter: TX2CustomMenuBarPainter; - FScrollbar: Boolean; - FScrollOffset: Integer; - FSelectedItem: TX2CustomMenuBarItem; + FAllowCollapseAll: Boolean; + FAnimationStyle: TX2MenuBarAnimationStyle; + FAnimationTime: Cardinal; + FAnimator: TX2CustomMenuBarAnimator; + FAutoCollapse: Boolean; + FAutoSelectItem: Boolean; + FBorderStyle: TBorderStyle; + FCursorGroup: TCursor; + FCursorItem: TCursor; + FDesigner: IX2MenuBarDesigner; + FExpandingGroups: TStringList; + FGroups: TX2MenuBarGroups; + FHideScrollbar: Boolean; + FHotItem: TX2CustomMenuBarItem; + FImages: TCustomImageList; + FLastMousePos: TPoint; + FOnCollapsed: TX2MenuBarExpandedEvent; + FOnCollapsing: TX2MenuBarExpandingEvent; + FOnExpanded: TX2MenuBarExpandedEvent; + FOnExpanding: TX2MenuBarExpandingEvent; + FOnSelectedChanged: TX2MenuBarSelectedChangedEvent; + FOnSelectedChanging: TX2MenuBarSelectedChangingEvent; + FPainter: TX2CustomMenuBarPainter; + FScrollbar: Boolean; + FScrollOffset: Integer; + FSelectedItem: TX2CustomMenuBarItem; procedure SetAllowCollapseAll(const Value: Boolean); procedure SetAnimator(const Value: TX2CustomMenuBarAnimator); @@ -307,12 +322,14 @@ type procedure SetBorderStyle(const Value: TBorderStyle); procedure SetGroups(const Value: TX2MenuBarGroups); procedure SetHideScrollbar(const Value: Boolean); - procedure SetImageList(const Value: TCustomImageList); + procedure SetImages(const Value: TCustomImageList); procedure SetScrollbar(const Value: Boolean); + procedure SetSelectedItem(const Value: TX2CustomMenuBarItem); protected procedure CreateParams(var Params: TCreateParams); override; procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure PainterUpdate(Sender: TX2CustomMenuBarPainter); + procedure GroupsNotify(Sender: TObject; Item: TCollectionItem; Action: TCollectionNotification); procedure GroupsUpdate(Sender: TObject; Item: TCollectionItem); procedure UpdateScrollbar(); @@ -325,6 +342,8 @@ type procedure TestMousePos(); virtual; function GetMenuHeight(): Integer; virtual; + + property Designer: IX2MenuBarDesigner read FDesigner write FDesigner; protected procedure SetPainter(const Value: TX2CustomMenuBarPainter); virtual; @@ -343,25 +362,31 @@ type function AllowInteraction(): Boolean; virtual; function ItemVisible(AItem: TX2CustomMenuBarItem): Boolean; virtual; - property AllowCollapseAll: Boolean read FAllowCollapseAll write SetAllowCollapseAll default True; - property AnimationStyle: TX2MenuBarAnimationStyle read FAnimationStyle write FAnimationStyle default DefaultAnimationStyle; - property AnimationTime: Cardinal read FAnimationTime write FAnimationTime default DefaultAnimationTime; - property Animator: TX2CustomMenuBarAnimator read FAnimator write SetAnimator; - property AutoCollapse: Boolean read FAutoCollapse write SetAutoCollapse default False; - property AutoSelectItem: Boolean read FAutoSelectItem write SetAutoSelectItem default False; - property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsNone; - property HideScrollbar: Boolean read FHideScrollbar write SetHideScrollbar default True; - property OnCollapsed: TX2MenuBarOnExpandedEvent read FOnCollapsed write FOnCollapsed; - property OnCollapsing: TX2MenuBarOnExpandingEvent read FOnCollapsing write FOnCollapsing; - property OnExpanded: TX2MenuBarOnExpandedEvent read FOnExpanded write FOnExpanded; - property OnExpanding: TX2MenuBarOnExpandingEvent read FOnExpanding write FOnExpanding; - property Scrollbar: Boolean read FScrollbar write SetScrollbar default True; + property AllowCollapseAll: Boolean read FAllowCollapseAll write SetAllowCollapseAll default True; + property AnimationStyle: TX2MenuBarAnimationStyle read FAnimationStyle write FAnimationStyle default DefaultAnimationStyle; + property AnimationTime: Cardinal read FAnimationTime write FAnimationTime default DefaultAnimationTime; + property Animator: TX2CustomMenuBarAnimator read FAnimator write SetAnimator; + property AutoCollapse: Boolean read FAutoCollapse write SetAutoCollapse default False; + property AutoSelectItem: Boolean read FAutoSelectItem write SetAutoSelectItem default False; + property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsNone; + property CursorGroup: TCursor read FCursorGroup write FCursorGroup default crDefault; + property CursorItem: TCursor read FCursorItem write FCursorItem default crDefault; + property HideScrollbar: Boolean read FHideScrollbar write SetHideScrollbar default True; + property OnCollapsed: TX2MenuBarExpandedEvent read FOnCollapsed write FOnCollapsed; + property OnCollapsing: TX2MenuBarExpandingEvent read FOnCollapsing write FOnCollapsing; + property OnExpanded: TX2MenuBarExpandedEvent read FOnExpanded write FOnExpanded; + property OnExpanding: TX2MenuBarExpandingEvent read FOnExpanding write FOnExpanding; + property OnSelectedChanged: TX2MenuBarSelectedChangedEvent read FOnSelectedChanged write FOnSelectedChanged; + property OnSelectedChanging: TX2MenuBarSelectedChangingEvent read FOnSelectedChanging write FOnSelectedChanging; + property Scrollbar: Boolean read FScrollbar write SetScrollbar default True; protected - procedure DoAutoCollapse(AGroup: TX2MenuBarGroup); - procedure DoAutoSelectItem(AGroup: TX2MenuBarGroup); - procedure DoExpand(AGroup: TX2MenuBarGroup; AExpanding: Boolean); + procedure DoAutoCollapse(AGroup: TX2MenuBarGroup); virtual; + function DoAutoSelectItem(AGroup: TX2MenuBarGroup; AAction: TX2MenuBarSelectAction): Boolean; virtual; + procedure DoExpand(AGroup: TX2MenuBarGroup; AExpanding: Boolean); virtual; procedure DoExpandedChanging(AGroup: TX2MenuBarGroup; AExpanding: Boolean); virtual; procedure DoExpandedChanged(AGroup: TX2MenuBarGroup); virtual; + procedure DoSelectedChanging(ANewItem: TX2CustomMenuBarItem; var AAllowed: Boolean); virtual; + procedure DoSelectedChanged(); virtual; public constructor Create(AOwner: TComponent); override; destructor Destroy(); override; @@ -369,9 +394,10 @@ type function HitTest(const APoint: TPoint): TX2MenuBarHitTest; overload; function HitTest(AX, AY: Integer): TX2MenuBarHitTest; overload; - property Groups: TX2MenuBarGroups read FGroups write SetGroups; - property ImageList: TCustomImageList read FImageList write SetImageList; - property Painter: TX2CustomMenuBarPainter read FPainter write SetPainter; + property Groups: TX2MenuBarGroups read FGroups write SetGroups; + property Images: TCustomImageList read FImages write SetImages; + property Painter: TX2CustomMenuBarPainter read FPainter write SetPainter; + property SelectedItem: TX2CustomMenuBarItem read FSelectedItem write SetSelectedItem; end; { @@ -391,9 +417,11 @@ type property BevelOuter; property BorderStyle; property BorderWidth; + property CursorGroup; + property CursorItem; property Groups; property HideScrollbar; - property ImageList; + property Images; property OnClick; property OnCollapsed; property OnCollapsing; @@ -402,6 +430,8 @@ type property OnExit; property OnExpanded; property OnExpanding; + property OnSelectedChanged; + property OnSelectedChanging; property OnMouseActivate; property OnMouseDown; property OnMouseEnter; @@ -741,13 +771,12 @@ end; { TX2CustomMenuBarItem } constructor TX2CustomMenuBarItem.Create(Collection: TCollection); begin - inherited; - - FCaption := SDefaultItemCaption; FEnabled := True; FImageIndex := -1; FOwnsData := True; FVisible := True; + + inherited; end; destructor TX2CustomMenuBarItem.Destroy(); @@ -848,6 +877,14 @@ end; { TX2CustomMenuBarItems } +procedure TX2CustomMenuBarItems.Notify(Item: TCollectionItem; Action: TCollectionNotification); +begin + if Assigned(FOnNotify) then + FOnNotify(Self, Item, Action); + + inherited; +end; + procedure TX2CustomMenuBarItems.Update(Item: TCollectionItem); begin inherited; @@ -858,6 +895,13 @@ end; { TX2MenuBarItem } +constructor TX2MenuBarItem.Create(Collection: TCollection); +begin + Caption := SDefaultItemCaption; + + inherited; +end; + function TX2MenuBarItem.GetGroup(): TX2MenuBarGroup; begin Result := nil; @@ -878,7 +922,9 @@ end; function TX2MenuBarItems.Add(const ACaption: TCaption): TX2MenuBarItem; begin Result := TX2MenuBarItem(inherited Add()); - Result.Caption := ACaption; + + if Length(ACaption) > 0 then + Result.Caption := ACaption; end; @@ -896,11 +942,14 @@ end; { TX2MenuBarGroup } constructor TX2MenuBarGroup.Create(Collection: TCollection); begin - inherited; - - FCaption := SDefaultGroupCaption; + Caption := SDefaultGroupCaption; FItems := TX2MenuBarItems.Create(Self); + FItems.OnNotify := ItemsNotify; FItems.OnUpdate := ItemsUpdate; + + { This results in the Collection's Notification being called, which needs to + be after we create our Items property. } + inherited; end; destructor TX2MenuBarGroup.Destroy(); @@ -953,6 +1002,12 @@ begin end; end; +procedure TX2MenuBarGroup.ItemsNotify(Sender: TObject; Item: TCollectionItem; Action: TCollectionNotification); +begin + if Assigned(Self.Collection) then + TProtectedCollection(Self.Collection).Notify(Item, Action); +end; + procedure TX2MenuBarGroup.ItemsUpdate(Sender: TObject; Item: TCollectionItem); var groupCollection: TProtectedCollection; @@ -1008,6 +1063,7 @@ end; function TX2MenuBarGroups.Add(const ACaption: TCaption): TX2MenuBarGroup; begin Result := TX2MenuBarGroup(inherited Add()); + if Length(ACaption) > 0 then Result.Caption := ACaption; end; @@ -1033,8 +1089,11 @@ begin FAnimationStyle := DefaultAnimationStyle; FAnimationTime := DefaultAnimationTime; FBorderStyle := bsNone; + FCursorGroup := crDefault; + FCursorItem := crDefault; FExpandingGroups := TStringList.Create(); FGroups := TX2MenuBarGroups.Create(Self); + FGroups.OnNotify := GroupsNotify; FGroups.OnUpdate := GroupsUpdate; FHideScrollbar := True; FScrollbar := True; @@ -1132,7 +1191,7 @@ begin group := TX2MenuBarGroup(FExpandingGroups.Objects[0]); FExpandingGroups.Delete(0); - group.Expanded := expand; + DoExpand(group, expand); end; end else @@ -1154,13 +1213,13 @@ begin if AItem = FHotItem then Include(Result, mdsHot); - if AItem = FSelectedItem then + if AItem = SelectedItem then Include(Result, mdsSelected); if Assigned(FHotItem) and (AItem = ItemGroup(FHotItem)) then Include(Result, mdsGroupHot); - if Assigned(FSelectedItem) and (AItem = ItemGroup(FSelectedItem)) then + if Assigned(SelectedItem) and (AItem = ItemGroup(SelectedItem)) then Include(Result, mdsGroupSelected); end; @@ -1384,9 +1443,11 @@ begin if not allowed then exit; - { Auto select item } + { Pretend to auto select item - required for proper functioning of + the OnSelectedChanging event } if AutoSelectItem then - DoAutoSelectItem(AGroup); + if not DoAutoSelectItem(AGroup, saBefore) then + exit; { Allow collapse all } if not (AExpanding or AllowCollapseAll) then @@ -1405,6 +1466,10 @@ procedure TX2CustomMenuBar.DoExpandedChanged(AGroup: TX2MenuBarGroup); begin if AGroup.Expanded then begin + { Auto select item } + if AutoSelectItem then + DoAutoSelectItem(AGroup, saAfter); + if Assigned(FOnExpanded) then FOnExpanded(Self, AGroup); end else @@ -1412,6 +1477,19 @@ begin FOnCollapsed(Self, AGroup); end; +procedure TX2CustomMenuBar.DoSelectedChanging(ANewItem: TX2CustomMenuBarItem; + var AAllowed: Boolean); +begin + if Assigned(FOnSelectedChanging) then + FOnSelectedChanging(Self, SelectedItem, ANewItem, AAllowed); +end; + +procedure TX2CustomMenuBar.DoSelectedChanged(); +begin + if Assigned(FOnSelectedChanged) then + FOnSelectedChanged(Self, SelectedItem); +end; + function TX2CustomMenuBar.AllowInteraction(): Boolean; begin @@ -1424,7 +1502,8 @@ begin end; -procedure TX2CustomMenuBar.DoExpand(AGroup: TX2MenuBarGroup; AExpanding: Boolean); +procedure TX2CustomMenuBar.DoExpand(AGroup: TX2MenuBarGroup; + AExpanding: Boolean); var animatorClass: TX2CustomMenuBarAnimatorClass; itemsBuffer: Graphics.TBitmap; @@ -1511,13 +1590,16 @@ begin end; end; -procedure TX2CustomMenuBar.DoAutoSelectItem(AGroup: TX2MenuBarGroup); +function TX2CustomMenuBar.DoAutoSelectItem(AGroup: TX2MenuBarGroup; + AAction: TX2MenuBarSelectAction): Boolean; var group: TX2MenuBarGroup; groupIndex: Integer; + newItem: TX2CustomMenuBarItem; begin - group := AGroup; + Result := True; + group := AGroup; if not Assigned(group) then begin for groupIndex := 0 to Pred(Groups.Count) do @@ -1539,8 +1621,21 @@ begin if group.Items.Count > 0 then begin - FSelectedItem := group.Items[group.SelectedItem]; - Invalidate(); + newItem := group.Items[group.SelectedItem]; + + if newItem <> SelectedItem then + begin + if AAction in [saBefore, saBoth] then + DoSelectedChanging(newItem, Result); + + if Result and (AAction in [saAfter, saBoth]) then + begin + FSelectedItem := newItem; + DoSelectedChanged(); + + Invalidate(); + end; + end; end; end; @@ -1578,9 +1673,9 @@ begin begin FPainter := nil; Invalidate(); - end else if AComponent = FImageList then + end else if AComponent = FImages then begin - FImageList := nil; + FImages := nil; Invalidate(); end; @@ -1592,10 +1687,31 @@ begin Invalidate(); end; +procedure TX2CustomMenuBar.GroupsNotify(Sender: TObject; Item: TCollectionItem; Action: TCollectionNotification); +begin + if Action = cnDeleting then + if Item = SelectedItem then + SelectedItem := nil + else if Item = FHotItem then + FHotItem := nil; + + if Assigned(Designer) then + case Action of + cnAdded: Designer.ItemAdded(Item as TX2CustomMenuBarItem); + cnDeleting: Designer.ItemDeleting(Item as TX2CustomMenuBarItem); + end; + + if TProtectedCollection(Item.Collection).UpdateCount = 0 then + Invalidate(); +end; + procedure TX2CustomMenuBar.GroupsUpdate(Sender: TObject; Item: TCollectionItem); begin - if Assigned(FSelectedItem) and (not FSelectedItem.Enabled) then - FSelectedItem := nil; + if Assigned(SelectedItem) and (not SelectedItem.Enabled) then + SelectedItem := nil; + + if Assigned(Designer) then + Designer.ItemModified(Item as TX2CustomMenuBarItem); Invalidate(); end; @@ -1619,19 +1735,15 @@ begin if group.Enabled and (group.Items.Count > 0) then begin group.Expanded := not group.Expanded; - hitTest.Item := FSelectedItem; + hitTest.Item := SelectedItem; Invalidate(); end; end; - if Assigned(hitTest.Item) and (hitTest.Item <> FSelectedItem) and + if Assigned(hitTest.Item) and (hitTest.Item <> SelectedItem) and hitTest.Item.Enabled then begin - if hitTest.HitTestCode = htItem then - TX2MenuBarItem(hitTest.Item).Group.SelectedItem := hitTest.Item.Index; - - FSelectedItem := hitTest.Item; - Invalidate(); + SelectedItem := hitTest.Item; end; end; @@ -1639,10 +1751,26 @@ begin end; procedure TX2CustomMenuBar.MouseMove(Shift: TShiftState; X, Y: Integer); +var + cursor: TCursor; + begin FLastMousePos := Point(X, Y); TestMousePos(); + cursor := crDefault; + if Assigned(FHotItem) then + if FHotItem is TX2MenuBarGroup then + cursor := CursorGroup + else if FHotItem is TX2MenuBarItem then + cursor := CursorItem; + + if (cursor <> crDefault) and FHotItem.Enabled then + begin + Windows.SetCursor(Screen.Cursors[cursor]); + exit; + end; + inherited; end; @@ -1875,8 +2003,8 @@ begin begin FAutoSelectItem := Value; - if Value and (not Assigned(FSelectedItem)) then - DoAutoSelectItem(nil); + if Value and (not Assigned(SelectedItem)) then + DoAutoSelectItem(nil, saBoth); end; end; @@ -1904,17 +2032,17 @@ begin end; end; -procedure TX2CustomMenuBar.SetImageList(const Value: TCustomImageList); +procedure TX2CustomMenuBar.SetImages(const Value: TCustomImageList); begin - if Value <> FImageList then + if Value <> FImages then begin - if Assigned(FImageList) then - FImageList.RemoveFreeNotification(Self); + if Assigned(FImages) then + FImages.RemoveFreeNotification(Self); - FImageList := Value; + FImages := Value; - if Assigned(FImageList) then - FImageList.FreeNotification(Self); + if Assigned(FImages) then + FImages.FreeNotification(Self); Invalidate(); end; @@ -1952,5 +2080,38 @@ begin end; end; +procedure TX2CustomMenuBar.SetSelectedItem(const Value: TX2CustomMenuBarItem); +var + allowed: Boolean; + group: TX2MenuBarGroup; + +begin + if Value <> FSelectedItem then + begin + allowed := True; + DoSelectedChanging(Value, allowed); + + if allowed then + begin + FSelectedItem := Value; + + if Value is TX2MenuBarItem then + begin + group := TX2MenuBarItem(Value).Group; + if Assigned(group) then + begin + group.SelectedItem := Value.Index; + + if not group.Expanded then + group.Expanded := True; + end; + end; + + DoSelectedChanged(); + Invalidate(); + end; + end; +end; + end. diff --git a/Source/X2CLmusikCubeMenuBarPainter.pas b/Source/X2CLmusikCubeMenuBarPainter.pas index 68275dd..5892bf5 100644 --- a/Source/X2CLmusikCubeMenuBarPainter.pas +++ b/Source/X2CLmusikCubeMenuBarPainter.pas @@ -39,6 +39,8 @@ type property OnChange: TNotifyEvent read FOnChange write FOnChange; public constructor Create(); + + procedure Assign(Source: TPersistent); override; function MixBorder(AColor: TColor): TColor; function MixFill(AColor: TColor): TColor; @@ -67,6 +69,8 @@ type public constructor Create(); destructor Destroy(); override; + + procedure Assign(Source: TPersistent); override; published property Hot: TX2MenuBarmCColor read FHot write SetHot; property Normal: TX2MenuBarmCColor read FNormal write SetNormal; @@ -350,7 +354,7 @@ begin textBounds := itemBounds; Inc(textBounds.Left, 4); - imageList := MenuBar.ImageList; + imageList := MenuBar.Images; if Assigned(imageList) then begin if AItem.ImageIndex > -1 then @@ -453,6 +457,20 @@ begin FFillColor := clNone; end; +procedure TX2MenuBarmCColor.Assign(Source: TPersistent); +begin + if Source is TX2MenuBarmCColor then + with TX2MenuBarmCColor(Source) do + begin + Self.BorderColor := BorderColor; + Self.BorderAlpha := BorderAlpha; + Self.FillColor := FillColor; + Self.FillAlpha := FillAlpha; + end + else + inherited; +end; + procedure TX2MenuBarmCColor.DoChange(); begin @@ -559,6 +577,19 @@ begin inherited; end; +procedure TX2MenuBarmCColors.Assign(Source: TPersistent); +begin + if Source is TX2MenuBarmCColors then + with TX2MenuBarmCColors(Source) do + begin + Self.Hot.Assign(Hot); + Self.Normal.Assign(Normal); + Self.Selected.Assign(Selected); + end + else + inherited; +end; + procedure TX2MenuBarmCColors.DoChange(); begin diff --git a/Source/X2CLunaMenuBarPainter.pas b/Source/X2CLunaMenuBarPainter.pas index 085ccb8..d7c11ca 100644 --- a/Source/X2CLunaMenuBarPainter.pas +++ b/Source/X2CLunaMenuBarPainter.pas @@ -240,21 +240,25 @@ begin ACanvas.Brush.Color := $00E9E9E9; { Rounded rectangle } - if (mdsSelected in AState) or (mdsHot in AState) or - (mdsGroupSelected in AState) then + if AGroup.Enabled and ((mdsSelected in AState) or (mdsHot in AState) or + (mdsGroupSelected in AState)) then ACanvas.Pen.Color := $00BE6363 else ACanvas.Pen.Color := clBlack; - ACanvas.Font.Color := ACanvas.Pen.Color; ACanvas.RoundRect(ABounds.Left, ABounds.Top, ABounds.Right, ABounds.Bottom, 5, 5); + if AGroup.Enabled then + ACanvas.Font.Color := ACanvas.Pen.Color + else + ACanvas.Font.Color := clGray; + textRect := ABounds; Inc(textRect.Left, 4); Dec(textRect.Right, 4); { Image } - imageList := AGroup.MenuBar.ImageList; + imageList := AGroup.MenuBar.Images; if Assigned(imageList) then begin if AGroup.ImageIndex > -1 then @@ -304,10 +308,13 @@ begin end; { Text } - if (mdsSelected in AState) or (mdsHot in AState) then - ACanvas.Font.Color := clBlack + if AItem.Enabled then + if (mdsSelected in AState) or (mdsHot in AState) then + ACanvas.Font.Color := clBlack + else + ACanvas.Font.Color := $00404040 else - ACanvas.Font.Color := $00404040; + ACanvas.Font.Color := clSilver; textBounds := focusBounds; Inc(textBounds.Left, 4); diff --git a/Test/MenuBar/MainForm.dfm b/Test/MenuBar/MainForm.dfm index cf8e553..c7b30a6 100644 --- a/Test/MenuBar/MainForm.dfm +++ b/Test/MenuBar/MainForm.dfm @@ -3,7 +3,7 @@ object frmMain: TfrmMain Top = 219 Caption = 'X2MenuBar Test' ClientHeight = 379 - ClientWidth = 548 + ClientWidth = 589 Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText @@ -26,8 +26,8 @@ object frmMain: TfrmMain ExplicitTop = -4 end object lblAnimationTime: TLabel - Left = 356 - Top = 24 + Left = 424 + Top = 20 Width = 98 Height = 13 Caption = 'Animation time (ms):' @@ -38,8 +38,15 @@ object frmMain: TfrmMain Width = 125 Height = 379 Align = alLeft - AnimationStyle = asSlide - AnimationTime = 250 + Groups = <> + Images = glMenu + OnCollapsed = mbTestCollapsed + OnCollapsing = mbTestCollapsing + OnExpanded = mbTestExpanded + OnExpanding = mbTestExpanding + OnSelectedChanged = mbTestSelectedChanged + OnSelectedChanging = mbTestSelectedChanging + Painter = mcPainter Groups = < item Caption = 'Share' @@ -169,13 +176,10 @@ object frmMain: TfrmMain Caption = 'Menu Item' end> end> - ImageList = glMenu - Painter = mcPainter - ExplicitLeft = 8 end object seAnimationTime: TJvSpinEdit - Left = 356 - Top = 40 + Left = 424 + Top = 36 Width = 81 Height = 21 CheckMinValue = True @@ -185,8 +189,8 @@ object frmMain: TfrmMain OnChange = seAnimationTimeChange end object Panel1: TPanel - Left = 212 - Top = 72 + Left = 280 + Top = 68 Width = 133 Height = 77 BevelOuter = bvNone @@ -222,9 +226,9 @@ object frmMain: TfrmMain end end object Panel2: TPanel - Left = 356 - Top = 72 - Width = 169 + Left = 424 + Top = 68 + Width = 153 Height = 101 BevelOuter = bvNone TabOrder = 3 @@ -277,8 +281,8 @@ object frmMain: TfrmMain end end object chkAutoCollapse: TCheckBox - Left = 212 - Top = 200 + Left = 280 + Top = 196 Width = 89 Height = 17 Caption = 'Auto collapse' @@ -286,8 +290,8 @@ object frmMain: TfrmMain OnClick = chkAutoCollapseClick end object chkAllowCollapseAll: TCheckBox - Left = 212 - Top = 240 + Left = 280 + Top = 236 Width = 101 Height = 17 Caption = 'Allow collapse all' @@ -295,8 +299,8 @@ object frmMain: TfrmMain OnClick = chkAllowCollapseAllClick end object chkAutoSelectItem: TCheckBox - Left = 212 - Top = 220 + Left = 280 + Top = 216 Width = 101 Height = 17 Caption = 'Auto select item' @@ -304,8 +308,8 @@ object frmMain: TfrmMain OnClick = chkAutoSelectItemClick end object chkScrollbar: TCheckBox - Left = 356 - Top = 200 + Left = 424 + Top = 196 Width = 121 Height = 17 Caption = 'Scrollbar' @@ -315,8 +319,8 @@ object frmMain: TfrmMain OnClick = chkScrollbarClick end object chkHideScrollbar: TCheckBox - Left = 356 - Top = 221 + Left = 424 + Top = 217 Width = 121 Height = 17 Caption = 'Hide Scrollbar' @@ -325,6 +329,77 @@ object frmMain: TfrmMain TabOrder = 8 OnClick = chkHideScrollbarClick end + object lbEvents: TListBox + Left = 152 + Top = 267 + Width = 421 + Height = 93 + ItemHeight = 13 + TabOrder = 9 + end + object Button1: TButton + Left = 152 + Top = 68 + Width = 113 + Height = 25 + Caption = 'SelectFirst' + Enabled = False + TabOrder = 10 + end + object Button2: TButton + Left = 152 + Top = 96 + Width = 113 + Height = 25 + Caption = 'SelectPrior' + Enabled = False + TabOrder = 11 + end + object Button3: TButton + Left = 152 + Top = 124 + Width = 113 + Height = 25 + Caption = 'SelectNext' + Enabled = False + TabOrder = 12 + end + object Button4: TButton + Left = 152 + Top = 152 + Width = 113 + Height = 25 + Caption = 'SelectLast' + Enabled = False + TabOrder = 13 + end + object Button5: TButton + Left = 152 + Top = 180 + Width = 113 + Height = 25 + Caption = 'SelectGroupByIndex' + Enabled = False + TabOrder = 14 + end + object Button6: TButton + Left = 152 + Top = 208 + Width = 113 + Height = 25 + Caption = 'SelectItemByIndex' + Enabled = False + TabOrder = 15 + end + object chkHotHand: TCheckBox + Left = 424 + Top = 236 + Width = 149 + Height = 17 + Caption = 'Hand cursor for hot items' + TabOrder = 16 + OnClick = chkHotHandClick + end object gcMenu: TX2GraphicContainer Graphics = < item diff --git a/Test/MenuBar/MainForm.pas b/Test/MenuBar/MainForm.pas index 296fdab..69fde7d 100644 --- a/Test/MenuBar/MainForm.pas +++ b/Test/MenuBar/MainForm.pas @@ -44,6 +44,22 @@ type chkScrollbar: TCheckBox; chkHideScrollbar: TCheckBox; rbSlideFade: TRadioButton; + lbEvents: TListBox; + Button2: TButton; + Button3: TButton; + Button4: TButton; + Button5: TButton; + Button6: TButton; + chkHotHand: TCheckBox; + procedure mbTestSelectedChanging(Sender: TObject; Item, + NewItem: TX2CustomMenuBarItem; var Allowed: Boolean); + procedure mbTestSelectedChanged(Sender: TObject; + Item: TX2CustomMenuBarItem); + procedure chkHotHandClick(Sender: TObject); + procedure mbTestExpanding(Sender: TObject; Group: TX2MenuBarGroup; var Allowed: Boolean); + procedure mbTestExpanded(Sender: TObject; Group: TX2MenuBarGroup); + procedure mbTestCollapsing(Sender: TObject; Group: TX2MenuBarGroup; var Allowed: Boolean); + procedure mbTestCollapsed(Sender: TObject; Group: TX2MenuBarGroup); procedure chkHideScrollbarClick(Sender: TObject); procedure chkScrollbarClick(Sender: TObject); procedure chkBlurShadowClick(Sender: TObject); @@ -54,9 +70,13 @@ type procedure PainterClick(Sender: TObject); procedure AnimationClick(Sender: TObject); procedure seAnimationTimeChange(Sender: TObject); + private + procedure Event(const AMsg: String); end; implementation +uses + X2UtHandCursor; {$R *.dfm} @@ -104,11 +124,29 @@ begin mbTest.HideScrollbar := chkHideScrollbar.Checked; end; +procedure TfrmMain.chkHotHandClick(Sender: TObject); +begin + if chkHotHand.Checked then + begin + mbTest.CursorGroup := crHandPoint; + mbTest.CursorItem := crHandPoint; + end else + begin + mbTest.CursorGroup := crDefault; + mbTest.CursorItem := crDefault; + end; +end; + procedure TfrmMain.chkScrollbarClick(Sender: TObject); begin mbTest.Scrollbar := chkScrollbar.Checked; end; +procedure TfrmMain.Event(const AMsg: String); +begin + lbEvents.ItemIndex := lbEvents.Items.Add(AMsg); +end; + procedure TfrmMain.FormCreate(Sender: TObject); begin chkAutoCollapse.Checked := mbTest.AutoCollapse; @@ -118,6 +156,49 @@ begin chkHideScrollbar.Checked := mbTest.HideScrollbar; end; +procedure TfrmMain.mbTestCollapsed(Sender: TObject; Group: TX2MenuBarGroup); +begin + Event('OnCollapsed(' + Group.Caption + ')'); +end; + +procedure TfrmMain.mbTestCollapsing(Sender: TObject; Group: TX2MenuBarGroup; var Allowed: Boolean); +begin + Event('OnCollapsing(' + Group.Caption + ')'); +end; + +procedure TfrmMain.mbTestExpanded(Sender: TObject; Group: TX2MenuBarGroup); +begin + Event('OnExpanded(' + Group.Caption + ')'); +end; + +procedure TfrmMain.mbTestExpanding(Sender: TObject; Group: TX2MenuBarGroup; var Allowed: Boolean); +begin + Event('OnExpanding(' + Group.Caption + ')'); +end; + +procedure TfrmMain.mbTestSelectedChanged(Sender: TObject; Item: TX2CustomMenuBarItem); +begin + Event('OnSelectedChanged(' + Item.Caption + ')'); +end; + +procedure TfrmMain.mbTestSelectedChanging(Sender: TObject; Item, NewItem: TX2CustomMenuBarItem; var Allowed: Boolean); +var + itemCaption: String; + newItemCaption: String; + +begin + itemCaption := ''; + newItemCaption := ''; + + if Assigned(Item) then + itemCaption := Item.Caption; + + if Assigned(NewItem) then + newItemCaption := NewItem.Caption; + + Event('OnSelectedChanging(' + itemCaption + ', ' + newItemCaption + ')'); +end; + procedure TfrmMain.PainterClick(Sender: TObject); begin if rbmusikCube.Checked then