1 {
2 *****************************************************************************
3 This file is part of the Lazarus Component Library (LCL)
4
5 See the file COPYING.modifiedLGPL.txt, included in this distribution,
6 for details about the license.
7 *****************************************************************************
8 }
9 unit ButtonPanel;
10
11 {$mode objfpc}{$h+}
12
13 interface
14
15 uses
16 Math, Types, SysUtils, Classes, LCLProc,Controls, ExtCtrls, StdCtrls, Buttons,
17 Forms, GraphType, Graphics, LMessages, Themes, LCLType;
18
19 type
20 TButtonOrder = (boDefault, boCloseCancelOK, boCloseOKCancel);
21 TPanelButton = (pbOK, pbCancel, pbClose, pbHelp);
22 TPanelButtons = set of TPanelButton;
23
24 const
25 DefShowButtons = [pbOK, pbCancel, pbClose, pbHelp];
26 DefShowGlyphs = [pbOK, pbCancel, pbClose, pbHelp];
27
28 type
29
30 { TPanelBitBtn }
31
32 TPanelBitBtn = class(TCustomBitBtn)
33 public
34 constructor Create(AOwner: TComponent); override;
35 published
36 // Caption is stored only if DefaultCaption = false
37 property Caption stored IsCaptionStored;
38 property DefaultCaption stored True;
39 property Left stored False;
40 property Top stored False;
41 property Width stored False;
42 property Height stored False;
43 property Enabled;
44 property Font;
45 property Glyph;
46 property Name stored True;
47 property PopupMenu;
48 property ShowHint;
49 property OnClick;
50 end;
51
52 { TCustomButtonPanel }
53
54 TCustomButtonPanel = class(TCustomPanel)
55 private
56 FShowBevel: Boolean;
57 FShowButtons: TPanelButtons;
58 FShowGlyphs: TPanelButtons;
59 FBevel: TBevel;
60 FGlyphs: array[TPanelButton] of TBitmap;
61 FButtons: array[TPanelButton] of TPanelBitBtn;
62 FButtonsWidth: Integer;
63 FButtonsHeight: Integer;
64 FButtonOrder: TButtonOrder;
65 FDefaultButton: TPanelButton;
66 FSpacing: TSpacingSize;
67 procedure CreateButton(AButton: TPanelButton);
68 procedure DoDefaultButton;
69 procedure DoShowButtons;
70 procedure DoShowGlyphs;
71 procedure SetButtonOrder(Value: TButtonOrder);
72 procedure SetDefaultButton(Value: TPanelButton);
73 procedure SetShowBevel(AValue: Boolean);
74 procedure SetShowButtons(Value: TPanelButtons);
75 procedure SetShowGlyphs(Value: TPanelButtons);
76 procedure SetSpacing(AValue: TSpacingSize);
77 procedure UpdateBevel;
78 procedure UpdateButtonOrder;
79 procedure UpdateSizes;
80 procedure UpdateButtonLayout;
81 procedure UpdateButtonSize;
IsLastButtonnull82 function IsLastButton(AControl: TControl): boolean;
83 protected
CreateControlBorderSpacingnull84 function CreateControlBorderSpacing: TControlBorderSpacing; override;
CustomAlignInsertBeforenull85 function CustomAlignInsertBefore(AControl1, AControl2: TControl): Boolean; override;
86 procedure CustomAlignPosition(AControl: TControl; var ANewLeft, ANewTop,
87 ANewWidth, ANewHeight: Integer; var AlignRect: TRect;
88 AlignInfo: TAlignInfo); override;
89 procedure CalculatePreferredSize(var PreferredWidth,
90 PreferredHeight: integer; WithThemeSpace: Boolean); override;
91 procedure Notification(AComponent: TComponent; Operation: TOperation); override;
92 procedure SetAlign(Value: TAlign); override;
93 procedure CMAppShowBtnGlyphChanged(var Message: TLMessage); message CM_APPSHOWBTNGLYPHCHANGED;
94 procedure CMShowingChanged(var Message: TLMessage); message CM_SHOWINGCHANGED;
95 public
96 constructor Create(AOwner: TComponent); override;
97 destructor Destroy; override;
98
99 property Align default alBottom;
100 property AutoSize default True;
101
102 property OKButton: TPanelBitBtn read FButtons[pbOK] default nil;
103 property HelpButton: TPanelBitBtn read FButtons[pbHelp] default nil;
104 property CloseButton: TPanelBitBtn read FButtons[pbClose] default nil;
105 property CancelButton: TPanelBitBtn read FButtons[pbCancel] default nil;
106 property ButtonOrder: TButtonOrder read FButtonOrder write SetButtonOrder default boDefault;
107
108 property DefaultButton: TPanelButton read FDefaultButton write SetDefaultButton default pbOK;
109 property ShowButtons: TPanelButtons read FShowButtons write SetShowButtons default DefShowButtons;
110 property ShowGlyphs: TPanelButtons read FShowGlyphs write SetShowGlyphs default DefShowGlyphs;
111 property ShowBevel: Boolean read FShowBevel write SetShowBevel default True;
112 property Spacing: TSpacingSize read FSpacing write SetSpacing default 6;
113 published
114 end;
115
116 { TButtonPanel }
117
118 TButtonPanel = class(TCustomButtonPanel)
119 published
120 property Align;
121 property Anchors;
122 property AutoSize;
123 property BorderSpacing;
124 property Constraints;
125 property Enabled;
126 property OKButton;
127 property HelpButton;
128 property CloseButton;
129 property CancelButton;
130 property Color;
131 property ButtonOrder;
132 property TabOrder;
133 property DefaultButton;
134 property Spacing;
135 property OnClick;
136 property OnDblClick;
137 property OnDragDrop;
138 property OnEnter;
139 property OnExit;
140 property OnKeyDown;
141 property OnKeyPress;
142 property OnKeyUp;
143 property OnMouseDown;
144 property OnMouseEnter;
145 property OnMouseLeave;
146 property OnMouseMove;
147 property OnMouseUp;
148 property OnMouseWheel;
149 property OnMouseWheelDown;
150 property OnMouseWheelUp;
151 property OnResize;
152 property OnUTF8KeyPress;
153 property ShowButtons;
154 property ShowGlyphs;
155 property ShowBevel;
156 property Visible;
157 end;
158
159 procedure Register;
160
161 implementation
162
163 const
164 DEFAULT_BUTTONPANEL_BORDERSPACING: TControlBorderSpacingDefault = (
165 Left:0; Top:0; Right:0; Bottom:0; Around:6;
166 );
167
168 procedure Register;
169 begin
170 RegisterComponents('Misc', [TButtonPanel]);
171 end;
172
173 { TPanelBitBtn }
174
175 constructor TPanelBitBtn.Create(AOwner: TComponent);
176 begin
177 inherited;
178
179 SetSubComponent(True);
180 end;
181
182 { TCustomButtonPanel }
183
184 procedure TCustomButtonPanel.DoShowButtons;
185 var
186 btn: TPanelButton;
187 aButton: TPanelBitBtn;
188 begin
189 DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomButtonPanel.DoShowButtons'){$ENDIF};
190
191 for btn := Low(btn) to High(btn) do
192 begin
193 if FButtons[btn] = nil
194 then CreateButton(btn);
195 aButton:=FButtons[btn];
196
197 if btn in FShowButtons
198 then begin
199 if csDesigning in ComponentState then
200 aButton.ControlStyle:=aButton.ControlStyle-[csNoDesignVisible];
201 aButton.Visible := True;
202 end
203 else begin
204 if csDesigning in ComponentState then
205 aButton.ControlStyle:=aButton.ControlStyle+[csNoDesignVisible];
206 aButton.Visible := False;
207 end;
208 end;
209
210 UpdateButtonOrder;
211 UpdateButtonLayout;
212 EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomButtonPanel.DoShowButtons'){$ENDIF};
213 end;
214
215 procedure TCustomButtonPanel.SetShowButtons(Value: TPanelButtons);
216 begin
217 if FShowButtons = Value then
218 Exit;
219
220 FShowButtons := Value;
221 InvalidatePreferredSize;
222 DoShowButtons;
223 end;
224
225 procedure TCustomButtonPanel.DoShowGlyphs;
226 var
227 btn: TPanelButton;
228 begin
229 DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomButtonPanel.DoShowGlyphs'){$ENDIF};
230 for btn := Low(btn) to High(btn) do
231 begin
232 if FButtons[btn] = nil then Continue;
233
234 if btn in FShowGlyphs
235 then begin
236 FButtons[btn].Glyph.Assign(FGlyphs[btn]);
237 end
238 else begin
239 FGlyphs[btn].Assign(FButtons[btn].Glyph);
240 FButtons[btn].Glyph.Assign(nil);
241 end;
242 end;
243 EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomButtonPanel.DoShowGlyphs'){$ENDIF};
244 end;
245
246 procedure TCustomButtonPanel.SetShowGlyphs(Value: TPanelButtons);
247 begin
248 if FShowGlyphs = Value then Exit;
249 FShowGlyphs := Value;
250 InvalidatePreferredSize;
251 DoShowGlyphs;
252 end;
253
254 procedure TCustomButtonPanel.SetSpacing(AValue: TSpacingSize);
255 begin
256 if FSpacing = AValue then Exit;
257 FSpacing := AValue;
258 InvalidatePreferredSize;
259 ReAlign;
260 end;
261
262 procedure TCustomButtonPanel.UpdateBevel;
263 begin
264 if FBevel = nil then Exit;
265
266 case Align of
267 alTop:
268 begin
269 FBevel.Shape := bsBottomLine;
270 FBevel.Align := alBottom;
271 end;
272 alLeft:
273 begin
274 FBevel.Shape := bsRightLine;
275 FBevel.Align := alRight;
276 end;
277 alRight:
278 begin
279 FBevel.Shape := bsLeftLine;
280 FBevel.Align := alLeft;
281 end
282 else
283 // default to bottom
284 FBevel.Shape := bsTopLine;
285 FBevel.Align := alTop;
286 end;
287
288 if Align in [alLeft, alRight]
289 then FBevel.Width := 2
290 else FBevel.Height := 2;
291 end;
292
293 procedure TCustomButtonPanel.UpdateSizes;
294 var
295 i: Integer;
296 BtnWidth, BtnHeight: Integer;
297 Details: TThemedElementDetails;
298 DefButtonSize: TSize;
299 begin
300 if csDestroying in ComponentState then
301 Exit;
302
303 Details := ThemeServices.GetElementDetails(tbPushButtonNormal);
304 DefButtonSize := ThemeServices.GetDetailSize(Details);
305 FButtonsWidth := DefButtonSize.cx;
306 FButtonsHeight := DefButtonSize.cy;
307
308 for i := 0 to ControlCount - 1 do
309 begin
310 if not (Controls[i] is TCustomButton) then Continue;
311 Controls[i].GetPreferredSize(BtnWidth, BtnHeight, True);
312 if Align in [alTop, alBottom] then
313 Controls[i].Width := BtnWidth;
314 if Align in [alLeft, alRight] then
315 Controls[i].Height := BtnHeight;
316 if BtnWidth > FButtonsWidth then
317 FButtonsWidth := BtnWidth;
318 if BtnHeight > FButtonsHeight then
319 FButtonsHeight := BtnHeight;
320 end;
321 end;
322
323 procedure TCustomButtonPanel.UpdateButtonLayout;
324 var
325 aButton: TPanelBitBtn;
326 btn: TPanelButton;
327 begin
328 for btn := Low(TPanelButton) to High(TPanelButton) do
329 begin
330 aButton:=FButtons[btn];
331 if aButton = nil then Continue;
332 aButton.Align := alCustom;
333 aButton.Default := FDefaultButton = btn;
334 end;
335 end;
336
IsLastButtonnull337 function TCustomButtonPanel.IsLastButton(AControl: TControl): boolean;
338 // returns true if AControl is the right/bottommost of the TPanelBitBtn
339 // Note: pbHelp could be the only button, then it is the last button
340 var
341 i: TPanelButton;
342 begin
343 if not AControl.IsControlVisible then exit(false);
344 if not (AControl is TPanelBitBtn) then exit(false);
345 for i:=low(FButtons) to pred(high(FButtons)) do
346 if (FButtons[i]<>nil) and FButtons[i].IsControlVisible
347 and (FButtons[i].TabOrder>TPanelBitBtn(AControl).TabOrder) then
348 exit(false); // there is a higher one
349 Result:=true;
350 end;
351
352 procedure TCustomButtonPanel.UpdateButtonOrder;
353 const
354 TabOrders: array[TButtonOrder, 0..3] of TPanelButton = (
355 {$IFDEF UNIX}
356 {boDefault } (pbOK, pbCancel, pbClose, pbHelp),
357 {$ELSE}
358 {boDefault } (pbCancel, pbOK, pbClose, pbHelp),
359 {$ENDIF}
360 {boCloseCancelOK} (pbOK, pbCancel, pbClose, pbHelp),
361 {boCloseOKCancel} (pbCancel, pbOK, pbClose, pbHelp)
362 );
363 var
364 i: Integer;
365 begin
366 //set taborder
367 for i := Low(TabOrders[FButtonOrder]) to High(TabOrders[FButtonOrder]) do
368 begin
369 if FButtons[TabOrders[FButtonOrder, i]] = nil then Continue;
370 FButtons[TabOrders[FButtonOrder, i]].TabOrder := High(TabOrders[FButtonOrder]) - i;
371 end;
372 AdjustSize;
373 end;
374
375 procedure TCustomButtonPanel.UpdateButtonSize;
376 var
377 AParent: TCustomDesignControl;
378 Details: TThemedElementDetails;
379 DefButtonSize: TSize;
380 btn: TPanelBitBtn;
381 begin
382 AParent := GetParentDesignControl(Self);
383 if AParent=nil then
384 Exit;
385
386 Details := ThemeServices.GetElementDetails(tbPushButtonNormal);
387 DefButtonSize := ThemeServices.GetDetailSize(Details);
388
389 DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomButtonPanel.UpdateButtonSize'){$ENDIF};
390 try
391 for btn in FButtons do
392 begin
393 if btn = nil then Continue;
394 if Application.Scaled and AParent.Scaled then
395 begin
396 btn.Constraints.MinWidth := MulDiv(DefButtonSize.cx, AParent.PixelsPerInch, ScreenInfo.PixelsPerInchX);
397 btn.Constraints.MinHeight := MulDiv(DefButtonSize.cy, AParent.PixelsPerInch, ScreenInfo.PixelsPerInchY);
398 end else
399 begin
400 btn.Constraints.MinWidth := DefButtonSize.cx;
401 btn.Constraints.MinHeight := DefButtonSize.cy;
402 end;
403 end;
404 finally
405 EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomButtonPanel.UpdateButtonSize'){$ENDIF};
406 end;
407 end;
408
409 procedure TCustomButtonPanel.SetAlign(Value: TAlign);
410 begin
411 DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomButtonPanel.SetAlign'){$ENDIF};
412 try
413 inherited SetAlign(Value);
414 UpdateButtonLayout;
415 UpdateBevel;
416 UpdateSizes;
417 finally
418 EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomButtonPanel.SetAlign'){$ENDIF};
419 end;
420 end;
421
422 procedure TCustomButtonPanel.CMAppShowBtnGlyphChanged(var Message: TLMessage);
423 begin
424 NotifyControls(Message.msg);
425 end;
426
427 procedure TCustomButtonPanel.CMShowingChanged(var Message: TLMessage);
428 begin
429 inherited;
430
431 UpdateButtonSize;
432 end;
433
434 procedure TCustomButtonPanel.SetButtonOrder(Value: TButtonOrder);
435 begin
436 if FButtonOrder = Value then Exit;
437 FButtonOrder := Value;
438 UpdateButtonOrder;
439 end;
440
441 procedure TCustomButtonPanel.DoDefaultButton;
442 var
443 btn: TPanelButton;
444 begin
445 for btn := Low(btn) to High(btn) do
446 begin
447 if FButtons[btn] = nil then Continue;
448 FButtons[btn].Default := FDefaultButton = btn;
449 end;
450 end;
451
452 procedure TCustomButtonPanel.SetDefaultButton(Value: TPanelButton);
453 begin
454 if FDefaultButton = Value then
455 Exit;
456
457 FDefaultButton := Value;
458
459 DoDefaultButton;
460 end;
461
462 procedure TCustomButtonPanel.SetShowBevel(AValue: Boolean);
463 begin
464 if FShowBevel = AValue then exit;
465 FShowBevel := AValue;
466
467 if not FShowBevel
468 then begin
469 FreeAndNil(FBevel);
470 Exit;
471 end;
472
473 DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomButtonPanel.SetShowBevel'){$ENDIF};
474 try
475 FBevel := TBevel.Create(Self);
476 FBevel.Parent := Self;
477 FBevel.Name := 'Bevel';
478
479 UpdateBevel;
480 finally
481 EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomButtonPanel.SetShowBevel'){$ENDIF};
482 end;
483 end;
484
485 procedure TCustomButtonPanel.Notification(AComponent: TComponent;
486 Operation: TOperation);
487 var
488 btn: TPanelButton;
489 begin
490 if Operation=opRemove
491 then begin
492 for btn := Low(btn) to High(btn) do
493 begin
494 if FButtons[btn] <> AComponent then Continue;
495 FButtons[btn] := nil;
496 Exclude(FShowButtons, btn);
497 end;
498 end;
499 inherited Notification(AComponent, Operation);
500 UpdateSizes;
501 end;
502
503 constructor TCustomButtonPanel.Create(AOwner: TComponent);
504 begin
505 inherited Create(AOwner);
506
507 ControlStyle := ControlStyle + [csOwnedChildrenNotSelectable];
508
509 Align := alBottom;
510 BevelInner := bvNone;
511 BevelOuter := bvNone;
512 Caption := '';
513 ControlStyle := ControlStyle - [csSetCaption];
514 AutoSize := True;
515 FSpacing := 6;
516 ShowBevel := True;
517
518
519 FDefaultButton := pbOK;
520 FButtonOrder := boDefault;
521 FShowButtons := DefShowButtons;
522 FShowGlyphs := DefShowGlyphs;
523
524 // create the buttons
525 DoShowButtons;
526 end;
527
528 procedure TCustomButtonPanel.CreateButton(AButton: TPanelButton);
529 const
530 NAMES: array[TPanelButton] of String = (
531 'OKButton', 'CancelButton', 'CloseButton', 'HelpButton'
532 );
533 KINDS: array[TPanelButton] of TBitBtnKind = (
534 bkOK, bkCancel, bkClose, bkHelp
535 );
536 begin
537 if FButtons[AButton] <> nil then Exit;
538
539 FButtons[AButton] := TPanelBitBtn.Create(Self);
540 with FButtons[AButton] do
541 begin
542 Name := NAMES[AButton];
543 Kind := KINDS[AButton];
544 AutoSize := true;
545 TabOrder := Ord(AButton); //initial order
546 Align := alCustom;
547 if FGlyphs[AButton] = nil
548 then begin
549 // first time
550 FGlyphs[AButton] := TBitmap.Create;
551 FGlyphs[AButton].Assign(Glyph);
552 end;
553 // (re)set the glyph if needed
554 if (AButton in FShowGlyphs)
555 then Glyph.Assign(FGlyphs[AButton])
556 else Glyph.Assign(nil);
557 // set default
558 Default := AButton = FDefaultButton;
559
560 Parent := Self;
561 end;
562 end;
563
CreateControlBorderSpacingnull564 function TCustomButtonPanel.CreateControlBorderSpacing: TControlBorderSpacing;
565 begin
566 Result := TControlBorderSpacing.Create(Self, @DEFAULT_BUTTONPANEL_BORDERSPACING);
567 end;
568
CustomAlignInsertBeforenull569 function TCustomButtonPanel.CustomAlignInsertBefore(AControl1, AControl2: TControl): Boolean;
570 begin
571 // bevel is always the very first
572 if AControl1 = FBevel then Exit(True);
573 if AControl2 = FBevel then Exit(False);
574 // the help button is the second
575 if AControl1 = FButtons[pbHelp] then Exit(True);
576 if AControl2 = FButtons[pbHelp] then Exit(False);
577 // user defined controls comes before the normal buttons
578 if (not (AControl1 is TPanelBitBtn)) and (AControl2 is TPanelBitBtn) then
579 Exit(True)
580 else if (AControl1 is TPanelBitBtn) and (not (AControl2 is TPanelBitBtn)) then
581 Exit(False);
582 // sort for taborder
583 Result := TWinControl(AControl2).TabOrder > TWinControl(AControl1).TabOrder;
584 end;
585
586 procedure TCustomButtonPanel.CustomAlignPosition(AControl: TControl;
587 var ANewLeft, ANewTop, ANewWidth, ANewHeight: Integer; var AlignRect: TRect;
588 AlignInfo: TAlignInfo);
589 var
590 BevelSpacing: TSpacingSize;
591 begin
592 //debugln(['TCustomButtonPanel.CustomAlignPosition ',DbgSName(Self),' AControl=',DbgSName(AControl),' AlignRect=',dbgs(AlignRect),' New=',ANewLeft,',',ANewTop,',',ANewWidth,'x',ANewHeight]);
593 inherited CustomAlignPosition(AControl, ANewLeft, ANewTop, ANewWidth,
594 ANewHeight, AlignRect, AlignInfo);
595
596 if Assigned(FBevel) and FBevel.IsControlVisible then
597 BevelSpacing := Spacing
598 else
599 BevelSpacing := 0;
600
601 if Align in [alLeft,alRight] then
602 begin
603 // put top or bottom
604 ANewLeft:=AlignRect.Left;
605 ANewWidth:=AControl.Constraints.MinMaxWidth(AlignRect.Right-ANewLeft-BevelSpacing);
606 if Align=alRight then
607 inc(ANewLeft,BevelSpacing);
608 if AControl=FButtons[pbHelp] then
609 begin
610 ANewTop:=AlignRect.Top; // no Spacing in front of the first button
611 AlignRect.Top:=Min(AlignRect.Bottom,ANewTop+ANewHeight);
612 end else begin
613 ANewTop:=AlignRect.Bottom-ANewHeight;
614 if not IsLastButton(AControl) then
615 dec(ANewTop,Spacing);
616 AlignRect.Bottom:=Max(AlignRect.Top,ANewTop);
617 end;
618 end else
619 begin
620 // put left or right
621 ANewTop:=AlignRect.Top;
622 ANewHeight:=AControl.Constraints.MinMaxHeight(AlignRect.Bottom-ANewTop-BevelSpacing);
623 if Align=alBottom then
624 inc(ANewTop,BevelSpacing);
625 if AControl=FButtons[pbHelp] then
626 begin
627 // put left
628 ANewLeft:=AlignRect.Left; // no Spacing in front of the first button
629 AlignRect.Left:=Min(AlignRect.Right,ANewLeft+ANewWidth);
630 end else begin
631 // put right
632 ANewLeft:=AlignRect.Right-ANewWidth;
633 if not IsLastButton(AControl) then
634 dec(ANewLeft,Spacing);
635 AlignRect.Right:=Max(AlignRect.Left,ANewLeft);
636 end;
637 end;
638 //debugln(['TCustomButtonPanel.CustomAlignPosition END ',DbgSName(Self),' AControl=',DbgSName(AControl),' AlignRect=',dbgs(AlignRect),' New=',ANewLeft,',',ANewTop,',',ANewWidth,'x',ANewHeight]);
639 end;
640
641 procedure TCustomButtonPanel.CalculatePreferredSize(var PreferredWidth,
642 PreferredHeight: integer; WithThemeSpace: Boolean);
643 var
644 i: Integer;
645 AControl: TControl;
646 MinWidth: Integer;
647 MinHeight: Integer;
648 CtrlPrefWidth, CtrlPrefHeight: integer;
649 begin
650 MinWidth:=0;
651 MinHeight:=0;
652 // add buttons
653 for i:=0 to ControlCount-1 do
654 begin
655 AControl:=Controls[i];
656 if (AControl.Align<>alCustom) or (not AControl.IsControlVisible) then continue;
657 if AControl=FBevel then continue;
658 CtrlPrefWidth:=0;
659 CtrlPrefHeight:=0;
660 AControl.GetPreferredSize(CtrlPrefWidth,CtrlPrefHeight);
661 //debugln(['TCustomButtonPanel.CalculatePreferredSize ',DbgSName(AControl),' ',CtrlPrefHeight]);
662 if Align in [alLeft,alRight] then
663 begin
664 inc(MinHeight,CtrlPrefHeight);
665 if not IsLastButton(AControl) then
666 inc(MinHeight,Spacing);
667 MinWidth:=Max(MinWidth,CtrlPrefWidth);
668 end
669 else begin
670 inc(MinWidth,CtrlPrefWidth);
671 if not IsLastButton(AControl) then
672 inc(MinWidth,Spacing);
673 MinHeight:=Max(MinHeight,CtrlPrefHeight);
674 end;
675 end;
676 // bevel
677 if (FBevel<>nil) and FBevel.IsControlVisible then
678 begin
679 if Align in [alLeft,alRight] then
680 inc(MinWidth,FBevel.Width+Spacing)
681 else
682 inc(MinHeight,FBevel.Height+Spacing);
683 end;
684 PreferredWidth:=MinWidth;
685 PreferredHeight:=MinHeight;
686 //debugln(['TCustomButtonPanel.CalculatePreferredSize ',DbgSName(Self),' ',PreferredWidth,'x',PreferredHeight]);
687 end;
688
689 destructor TCustomButtonPanel.Destroy;
690 var
691 btn: TPanelButton;
692 begin
693 for btn := Low(btn) to High(btn) do
694 FreeAndNil(FGlyphs[btn]);
695 inherited Destroy;
696 end;
697
698 end.
699