1 {
2  *****************************************************************************
3   See the file COPYING.modifiedLGPL.txt, included in this distribution,
4   for details about the license.
5  *****************************************************************************
6 
7   Author: Ondrej Pokorny
8 
9   Abstract:
10     Interface to the IDE toolbars.
11 }
12 unit ToolBarIntf;
13 
14 {$mode objfpc}{$H+}
15 
16 interface
17 
18 uses
19   Classes,
20   // LCL
21   Controls, ComCtrls, Menus,
22   // LazUtils
23   LazUTF8,
24   // IdeIntf
25   IDECommands, MenuIntf, IDEImagesIntf, SrcEditorIntf;
26 
27 type
28   TIDEToolButton = class;
29   TIDEToolButtonClass = class of TIDEToolButton;
30   TIDEToolButtons = class;
31 
32   TIDEButtonCommand = class(TIDESpecialCommand)
33   private
34     FTag: PtrInt;
35     FToolButtonClass: TIDEToolButtonClass;
36     FToolButtons: TIDEToolButtons;
37   protected
38     procedure SetName(const aName: string); override;
39     procedure SetEnabled(const aEnabled: Boolean); override;
40     procedure SetChecked(const aChecked: Boolean); override;
41     procedure SetCaption(aCaption: string); override;
42     procedure SetHint(const aHint: string); override;
43     procedure SetImageIndex(const aImageIndex: Integer); override;
44     procedure SetResourceName(const aResourceName: string); override;
45     procedure ShortCutsUpdated(const aShortCut, aShortCutKey2: TShortCut); override;
46   public
47     procedure ToolButtonAdded(const aBtn: TIDEToolButton);
48   public
49     constructor Create(const TheName: string); override;
50     destructor Destroy; override;
51   public
52     property Tag: PtrInt read FTag write FTag;
53     property ToolButtonClass: TIDEToolButtonClass read FToolButtonClass write FToolButtonClass;
54     property ToolButtons: TIDEToolButtons read FToolButtons;
55   end;
56 
57   { TIDEToolButton }
58 
59   TIDEToolButton = class(TToolButton)
60   private
61     FItem: TIDEButtonCommand;
62   protected
63     procedure DoOnShowHint(HintInfo: PHintInfo); override;
64   public
65     procedure DoOnAdded; virtual;
66 
67     procedure Click; override;
68     property Item: TIDEButtonCommand read FItem write FItem;
69   end;
70 
71   {%region *** Classes for toolbuttons with arrow *** }
72 
73   TIDEToolButton_WithArrow_Class = class of TIDEToolButton_WithArrow;
74   TIDEToolButton_ButtonDrop_Class = class of TIDEToolButton_ButtonDrop;
75   TIDEToolButton_DropDown_Class = class of TIDEToolButton_DropDown;
76 
77   { TIDEToolButton_WithArrow }    // [  ][▼], [ ▼]
78 
79   TIDEToolButton_WithArrow = class(TIDEToolButton)
80   private
GetSectionnull81     function GetSection: TIDEMenuSection;
82   protected
83     procedure DoOnMenuPopup(Sender: TObject);
84     procedure RefreshMenu; virtual;
85     property Section: TIDEMenuSection read GetSection;
86   public
87     constructor Create(AOwner: TComponent); override;
88   end;
89 
90   { TIDEToolButton_DropDown }    // [  ][▼]
91 
92   TIDEToolButton_DropDown = class(TIDEToolButton_WithArrow)
93   public
94     procedure DoOnAdded; override;
95   end;
96 
97   { TIDEToolButton_ButtonDrop }    // [ ▼]
98 
99   TIDEToolButton_ButtonDrop = class(TIDEToolButton_WithArrow)
100   protected
101     procedure PopUpAloneMenu(Sender: TObject);
102   public
103     procedure DoOnAdded; override;
104   end;
105   {%endregion}
106 
107   TIDEToolButtonCategory = class
108   private
109     FButtons: TFPList;
110     FDescription: string;
111     FName: string;
GetButtonsnull112     function GetButtons(Index: Integer): TIDEButtonCommand;
113   public
114     constructor Create;
115     destructor Destroy; override;
116   public
117     property Description: string read FDescription write FDescription;
118     property Name: string read FName write FName;
ButtonCountnull119     function ButtonCount: Integer;
120     property Buttons[Index: Integer]: TIDEButtonCommand read GetButtons; default;
121   end;
122 
123   TIDEToolButtonCategories = class
124   private
125     FButtonNames: TStringListUTF8Fast;
126     FCategories: TStringListUTF8Fast;
GetItemsnull127     function GetItems(Index: Integer): TIDEToolButtonCategory;
128   public
129     constructor Create;
130     destructor Destroy; override;
131   public
Countnull132     function Count: Integer;
AddButtonnull133     function AddButton(const aCategory: TIDEToolButtonCategory; const aName: string;
134       const aCommand: TIDECommand): TIDEButtonCommand; overload;
AddButtonnull135     function AddButton(const aCommand: TIDECommand): TIDEButtonCommand; overload;
FindCategorynull136     function FindCategory(const aName: string): TIDEToolButtonCategory;
FindCreateCategorynull137     function FindCreateCategory(const aName, aDescription: string): TIDEToolButtonCategory;
FindItemByNamenull138     function FindItemByName(const aName: string): TIDEButtonCommand;
FindItemByMenuPathOrNamenull139     function FindItemByMenuPathOrName(var aName: string): TIDEButtonCommand;
FindItemByCommandnull140     function FindItemByCommand(const aCommand: TIDECommand): TIDEButtonCommand;
FindItemByCommandnull141     function FindItemByCommand(const aCommand: Word): TIDEButtonCommand;
142     property Items[Index: Integer]: TIDEToolButtonCategory read GetItems; default;
143   end;
144 
145   TIDEToolButtonsEnumerator = class
146   private
147     FList: TIDEToolButtons;
148     FPosition: Integer;
149   public
150     constructor Create(AButtons: TIDEToolButtons);
GetCurrentnull151     function GetCurrent: TIDEToolButton;
MoveNextnull152     function MoveNext: Boolean;
153     property Current: TIDEToolButton read GetCurrent;
154   end;
155 
156   TIDEToolButtons = class(TComponent)
157   private
158     FList: TFPList;
GetCountnull159     function GetCount: Integer;
GetItemsnull160     function GetItems(Index: Integer): TIDEToolButton;
161   protected
162     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
163   public
164     constructor Create(aOwner: TComponent); override;
165     destructor Destroy; override;
166   public
GetEnumeratornull167     function GetEnumerator: TIDEToolButtonsEnumerator;
168     procedure Add(const aBtn: TIDEToolButton);
169 
170     property Count: Integer read GetCount;
171     property Items[Index: Integer]: TIDEToolButton read GetItems; default;
172   end;
173 
174 
175 var
176   IDEToolButtonCategories: TIDEToolButtonCategories = nil;// created by the IDE
177 
178 
RegisterIDEButtonCategorynull179 function RegisterIDEButtonCategory(const aName, aDescription: string): TIDEToolButtonCategory;
RegisterIDEButtonCommandnull180 function RegisterIDEButtonCommand(const aCategory: TIDEToolButtonCategory; const aName: string;
181   const aCommand: TIDECommand): TIDEButtonCommand;
RegisterIDEButtonCommandnull182 function RegisterIDEButtonCommand(const aCommand: TIDECommand): TIDEButtonCommand;
183 
GetCommand_DropDownnull184 function GetCommand_DropDown(ACommand: Word; AMenuSection: TIDEMenuSection;
185     AButtonClass: TIDEToolButton_DropDown_Class=nil): TIDECommand;
GetCommand_ButtonDropnull186 function GetCommand_ButtonDrop(ACommand: Word; AMenuSection: TIDEMenuSection;
187     AButtonClass: TIDEToolButton_ButtonDrop_Class=nil): TIDECommand;
188 
189 
190 implementation
191 
RegisterIDEButtonCategorynull192 function RegisterIDEButtonCategory(const aName, aDescription: string): TIDEToolButtonCategory;
193 begin
194   Result := IDEToolButtonCategories.FindCreateCategory(aName, aDescription);
195 end;
196 
RegisterIDEButtonCommandnull197 function RegisterIDEButtonCommand(const aCategory: TIDEToolButtonCategory;
198   const aName: string; const aCommand: TIDECommand): TIDEButtonCommand;
199 begin
200   Result := IDEToolButtonCategories.AddButton(aCategory, aName, aCommand);
201 end;
202 
RegisterIDEButtonCommandnull203 function RegisterIDEButtonCommand(const aCommand: TIDECommand): TIDEButtonCommand;
204 begin
205   Result := IDEToolButtonCategories.AddButton(aCommand);
206 end;
207 
208 {%region *** Functions and classes for toolbuttons with arrow *** }
209 
GetCommand_BtnWithArrownull210 function GetCommand_BtnWithArrow(ACommand: Word; AMenuSection: TIDEMenuSection;  // not in Interface
211            AButtonClass: TIDEToolButton_WithArrow_Class): TIDECommand;
212 var
213   ButtonCommand: TIDEButtonCommand;
214 begin
215   Result:=IDECommandList.FindIDECommand(ACommand);
216   if Result=nil then
217     Exit(nil);
218   ButtonCommand:=RegisterIDEButtonCommand(Result);
219   ButtonCommand.ToolButtonClass:=AButtonClass;
220   if AButtonClass.InheritsFrom(TIDEToolButton_ButtonDrop) then
221     ButtonCommand.ImageIndex:=AMenuSection.ImageIndex;
222   ButtonCommand.Tag:=PtrInt(AMenuSection);
223 end;
224 
GetCommand_DropDownnull225 function GetCommand_DropDown(ACommand: Word; AMenuSection: TIDEMenuSection;
226     AButtonClass: TIDEToolButton_DropDown_Class=nil): TIDECommand;
227 begin
228   if AButtonClass=nil then
229     AButtonClass:=TIDEToolButton_DropDown;
230   Result:=GetCommand_BtnWithArrow(ACommand, AMenuSection, AButtonClass);
231 end;
232 
GetCommand_ButtonDropnull233 function GetCommand_ButtonDrop(ACommand: Word; AMenuSection: TIDEMenuSection;
234     AButtonClass: TIDEToolButton_ButtonDrop_Class=nil): TIDECommand;
235 begin
236   if AButtonClass=nil then
237     AButtonClass:=TIDEToolButton_ButtonDrop;
238   Result:=GetCommand_BtnWithArrow(ACommand, AMenuSection, AButtonClass);
239 end;
240 
241 { TIDEToolButton_WithArrow }
242 
243 constructor TIDEToolButton_WithArrow.Create(AOwner: TComponent);
244 begin
245   inherited Create(AOwner);
246   DropdownMenu := TPopupMenu.Create(Self);
247   DropdownMenu.Images := IDEImages.Images_16;
248   DropdownMenu.OnPopup := @DoOnMenuPopup;
249 end;
250 
GetSectionnull251 function TIDEToolButton_WithArrow.GetSection: TIDEMenuSection;
252 begin
253   Result:=nil;
254   if (Item<>nil) then
255     Result:=TIDEMenuSection(Item.Tag);
256 end;
257 
258 procedure TIDEToolButton_WithArrow.DoOnMenuPopup(Sender: TObject);
259 begin
260   DropdownMenu.Items.Clear;
261   RefreshMenu;
262 end;
263 
264 procedure TIDEToolButton_WithArrow.RefreshMenu;
265 begin
266   if Section=nil then
267     Exit;
268   if Section.MenuItem=nil then
269     Section.GetRoot.CreateMenuItem;  // this forces creating menu (it is necessary
270                                      // for TPopupMenu before first popup)
271   if Section.MenuItem<>nil then
272     DropdownMenu.Items.Assign(Section.MenuItem);
273 end;
274 
275 { TIDEToolButton_DropDown }
276 
277 procedure TIDEToolButton_DropDown.DoOnAdded;
278 begin
279   Style := tbsDropDown;  // not in constructor
280 end;
281 
282 { TIDEToolButton_ButtonDrop }
283 
284 procedure TIDEToolButton_ButtonDrop.DoOnAdded;
285 begin
286   Style := tbsButtonDrop;  // not in constructor
287   if (Item<>nil) then
288     if (Item.Command<>nil) then
289       Item.Command.OnExecute:=@PopUpAloneMenu;
290 end;
291 
292 procedure TIDEToolButton_ButtonDrop.PopUpAloneMenu(Sender: TObject);
293 var
294   ActiveEditor: TSourceEditorInterface;
295   ScreenXY: TPoint;
296 begin
297   ActiveEditor := SourceEditorManagerIntf.ActiveEditor;
298   if ActiveEditor=nil then
299     Exit;
300   ScreenXY := ActiveEditor.EditorControl.ClientToScreen(Point(0, 0));
301   DropdownMenu.PopUp(ScreenXY.X, ScreenXY.Y);
302 end;
303 {%endregion}
304 
305 { TIDEToolButtonsEnumerator }
306 
307 constructor TIDEToolButtonsEnumerator.Create(AButtons: TIDEToolButtons);
308 begin
309   inherited Create;
310   FList := AButtons;
311   FPosition := -1;
312 end;
313 
314 
GetCurrentnull315 function TIDEToolButtonsEnumerator.GetCurrent: TIDEToolButton;
316 begin
317   Result := FList[FPosition];
318 end;
319 
TIDEToolButtonsEnumerator.MoveNextnull320 function TIDEToolButtonsEnumerator.MoveNext: Boolean;
321 begin
322   Inc(FPosition);
323   Result := FPosition < FList.Count;
324 end;
325 
326 { TIDEToolButtons }
327 
328 procedure TIDEToolButtons.Add(const aBtn: TIDEToolButton);
329 begin
330   FList.Add(aBtn);
331   aBtn.FreeNotification(Self);
332 end;
333 
334 constructor TIDEToolButtons.Create(aOwner: TComponent);
335 begin
336   inherited Create(aOwner);
337   FList := TFPList.Create;
338 end;
339 
340 destructor TIDEToolButtons.Destroy;
341 var
342   I: Integer;
343 begin
344   for I := 0 to Count-1 do
345     Items[I].RemoveFreeNotification(Self);
346   FList.Free;
347   inherited Destroy;
348 end;
349 
GetCountnull350 function TIDEToolButtons.GetCount: Integer;
351 begin
352   Result := FList.Count;
353 end;
354 
GetEnumeratornull355 function TIDEToolButtons.GetEnumerator: TIDEToolButtonsEnumerator;
356 begin
357   Result := TIDEToolButtonsEnumerator.Create(Self);
358 end;
359 
TIDEToolButtons.GetItemsnull360 function TIDEToolButtons.GetItems(Index: Integer): TIDEToolButton;
361 begin
362   Result := TIDEToolButton(FList[Index]);
363 end;
364 
365 procedure TIDEToolButtons.Notification(AComponent: TComponent; Operation: TOperation);
366 var
367   xIndex: Integer;
368 begin
369   inherited Notification(AComponent, Operation);
370   if (Operation = opRemove) then
371   begin
372     xIndex := FList.IndexOf(AComponent);
373     if xIndex >= 0 then
374       FList.Delete(xIndex);
375   end;
376 end;
377 
378 { TIDEButtonCommand }
379 
380 constructor TIDEButtonCommand.Create(const TheName: string);
381 begin
382   inherited Create(TheName);
383   FToolButtonClass := TIDEToolButton;
384   FToolButtons := TIDEToolButtons.Create(nil);
385 end;
386 
387 destructor TIDEButtonCommand.Destroy;
388 begin
389   FToolButtons.Free;
390   inherited Destroy;
391 end;
392 
393 procedure TIDEButtonCommand.SetEnabled(const aEnabled: Boolean);
394 var
395   xBtn: TIDEToolButton;
396 begin
397   inherited SetEnabled(aEnabled);
398   for xBtn in FToolButtons do
399     xBtn.Enabled:=Enabled;
400 end;
401 
402 procedure TIDEButtonCommand.SetHint(const aHint: string);
403 var
404   xBtn: TIDEToolButton;
405 begin
406   inherited SetHint(aHint);
407   for xBtn in FToolButtons do
408     xBtn.Hint:=GetHintOrCaptionWithShortCut;
409 end;
410 
411 procedure TIDEButtonCommand.SetImageIndex(const aImageIndex: Integer);
412 var
413   xBtn: TIDEToolButton;
414 begin
415   inherited SetImageIndex(aImageIndex);
416   for xBtn in FToolButtons do
417     xBtn.ImageIndex:=ImageIndex;
418 end;
419 
420 procedure TIDEButtonCommand.SetName(const aName: string);
421 var
422   i: Integer;
423 begin
424   if Name=aName then Exit;
425   i:=IDEToolButtonCategories.FButtonNames.IndexOf(Name);
426   inherited SetName(aName);
427   if (i>=0) and (IDEToolButtonCategories.FButtonNames.Objects[i] = Self) then
428   begin
429     IDEToolButtonCategories.FButtonNames.Delete(i);
430     IDEToolButtonCategories.FButtonNames.AddObject(aName,  Self);
431   end;
432 end;
433 
434 procedure TIDEButtonCommand.SetCaption(aCaption: string);
435 var
436   xBtn: TIDEToolButton;
437 begin
438   inherited SetCaption(aCaption);
439   for xBtn in FToolButtons do
440     xBtn.Hint:=GetHintOrCaptionWithShortCut;
441 end;
442 
443 procedure TIDEButtonCommand.SetChecked(const aChecked: Boolean);
444 var
445   xBtn: TIDEToolButton;
446 begin
447   inherited SetChecked(aChecked);
448   for xBtn in FToolButtons do
449     xBtn.Down:=Checked;
450 end;
451 
452 procedure TIDEButtonCommand.SetResourceName(const aResourceName: string);
453 var
454   xBtn: TIDEToolButton;
455 begin
456   inherited SetResourceName(aResourceName);
457   for xBtn in FToolButtons do
458     xBtn.ImageIndex:=ImageIndex;
459 end;
460 
461 procedure TIDEButtonCommand.ShortCutsUpdated(const aShortCut, aShortCutKey2: TShortCut);
462 var
463   xBtn: TIDEToolButton;
464 begin
465   inherited ShortCutsUpdated(aShortCut, aShortCutKey2);
466   for xBtn in FToolButtons do
467     xBtn.Hint:=GetHintOrCaptionWithShortCut;
468 end;
469 
470 procedure TIDEButtonCommand.ToolButtonAdded(const aBtn: TIDEToolButton);
471 begin
472   FToolButtons.Add(aBtn);
473   aBtn.DoOnAdded;
474 end;
475 
476 { TIDEToolButtonCategory }
477 
ButtonCountnull478 function TIDEToolButtonCategory.ButtonCount: Integer;
479 begin
480   Result := FButtons.Count;
481 end;
482 
483 constructor TIDEToolButtonCategory.Create;
484 begin
485   FButtons := TFPList.Create;
486 end;
487 
488 destructor TIDEToolButtonCategory.Destroy;
489 var
490   i: Integer;
491 begin
492   for i := 0 to ButtonCount-1 do
493     Buttons[i].Free;
494   FButtons.Free;
495   inherited Destroy;
496 end;
497 
TIDEToolButtonCategory.GetButtonsnull498 function TIDEToolButtonCategory.GetButtons(Index: Integer): TIDEButtonCommand;
499 begin
500   Result := TIDEButtonCommand(FButtons[Index]);
501 end;
502 
503 { TIDEToolButtonCategories }
504 
AddButtonnull505 function TIDEToolButtonCategories.AddButton(const aCommand: TIDECommand): TIDEButtonCommand;
506 var
507   xCategory: TIDEToolButtonCategory;
508 begin
509   Assert(aCommand<>nil, 'TIDEToolButtonCategories.AddButton: aCommand=nil');
510   xCategory := RegisterIDEButtonCategory(aCommand.Category.Name, aCommand.Category.Description);
511   Result := RegisterIDEButtonCommand(xCategory,  aCommand.Name, aCommand);
512 end;
513 
AddButtonnull514 function TIDEToolButtonCategories.AddButton(
515   const aCategory: TIDEToolButtonCategory; const aName: string;
516   const aCommand: TIDECommand): TIDEButtonCommand;
517 begin
518   Result := FindItemByName(aName);
519   if Result=nil then
520   begin
521     Result := TIDEButtonCommand.Create(aName);
522     FButtonNames.AddObject(aName, Result);
523     aCategory.FButtons.Add(Result);
524     Result.Command:=aCommand;
525   end;
526 end;
527 
TIDEToolButtonCategories.Countnull528 function TIDEToolButtonCategories.Count: Integer;
529 begin
530   Result := FCategories.Count;
531 end;
532 
533 constructor TIDEToolButtonCategories.Create;
534 begin
535   FButtonNames := TStringListUTF8Fast.Create;
536   FButtonNames.Sorted := True;
537   FButtonNames.Duplicates := dupIgnore;
538   FCategories := TStringListUTF8Fast.Create;
539   FCategories.Sorted := True;
540   FCategories.Duplicates := dupIgnore;
541   FCategories.OwnsObjects := True;
542 end;
543 
544 destructor TIDEToolButtonCategories.Destroy;
545 begin
546   FButtonNames.Free;
547   FCategories.Free;
548   inherited Destroy;
549 end;
550 
FindCategorynull551 function TIDEToolButtonCategories.FindCategory(const aName: string
552   ): TIDEToolButtonCategory;
553 var
554   i: Integer;
555 begin
556   i := FCategories.IndexOf(aName);
557   if (i>=0) and (FCategories.Objects[i]<>nil) then
558     Result := FCategories.Objects[i] as TIDEToolButtonCategory
559   else
560     Result := nil;
561 end;
562 
FindItemByMenuPathOrNamenull563 function TIDEToolButtonCategories.FindItemByMenuPathOrName(var aName: string
564   ): TIDEButtonCommand;
565 var
566   xMI: TIDEMenuItem;
567 begin
568   Result := FindItemByName(aName);
569   if Result<>nil then Exit;
570 
571   //find by path from aName (backwards compatibility)
572   xMI := IDEMenuRoots.FindByPath(aName, False);
573   if Assigned(xMI) and Assigned(xMI.Command) then
574   begin
575     Result := FindItemByCommand(xMI.Command);
576     if Assigned(Result) then
577       aName := xMI.Command.Name;
578   end;
579 end;
580 
FindCreateCategorynull581 function TIDEToolButtonCategories.FindCreateCategory(const aName,
582   aDescription: string): TIDEToolButtonCategory;
583 var
584   i: Integer;
585 begin
586   i := FCategories.IndexOf(aName);
587   if (i>=0) and (FCategories.Objects[i]<>nil) then
588     Result := FCategories.Objects[i] as TIDEToolButtonCategory
589   else
590   begin
591     Result := TIDEToolButtonCategory.Create;
592     Result.Name := aName;
593     Result.Description := aDescription;
594     FCategories.AddObject(aName, Result);
595   end;
596 end;
597 
FindItemByCommandnull598 function TIDEToolButtonCategories.FindItemByCommand(const aCommand: TIDECommand
599   ): TIDEButtonCommand;
600 var
601   i, l: Integer;
602 begin
603   for i := 0 to Count-1 do
604     for l := 0 to Items[i].ButtonCount-1 do
605       if Items[i].Buttons[l].Command = aCommand then
606         Exit(Items[i].Buttons[l]);
607 
608   Result := nil;
609 end;
610 
FindItemByCommandnull611 function TIDEToolButtonCategories.FindItemByCommand(const aCommand: Word
612   ): TIDEButtonCommand;
613 var
614   i, l: Integer;
615 begin
616   for i := 0 to Count-1 do
617     for l := 0 to Items[i].ButtonCount-1 do
618       if Items[i].Buttons[l].Command.Command = aCommand then
619         Exit(Items[i].Buttons[l]);
620 
621   Result := nil;
622 end;
623 
TIDEToolButtonCategories.FindItemByNamenull624 function TIDEToolButtonCategories.FindItemByName(const aName: string
625   ): TIDEButtonCommand;
626 var
627   i: Integer;
628 begin
629   i := FButtonNames.IndexOf(aName);
630   if (i>=0) and (FButtonNames.Objects[i]<>nil) then
631     Result := FButtonNames.Objects[i] as TIDEButtonCommand
632   else
633     Result := nil;
634 end;
635 
TIDEToolButtonCategories.GetItemsnull636 function TIDEToolButtonCategories.GetItems(Index: Integer): TIDEToolButtonCategory;
637 begin
638   Result := TIDEToolButtonCategory(FCategories.Objects[Index]);
639 end;
640 
641 { TIDEToolButton }
642 
643 procedure TIDEToolButton.Click;
644 begin
645   inherited Click;
646   if Assigned(FItem) then
647     FItem.DoOnClick;
648 end;
649 
650 procedure TIDEToolButton.DoOnAdded;
651 begin
652   //override in descendants
653 end;
654 
655 procedure TIDEToolButton.DoOnShowHint(HintInfo: PHintInfo);
656 begin
657   inherited DoOnShowHint(HintInfo);
658   if Assigned(FItem) and FItem.DoOnRequestCaption(Self) then
659     HintInfo^.HintStr := FItem.GetHintOrCaptionWithShortCut;
660 end;
661 
662 end.
663 
664