1{%MainUnit ../comctrls.pp} 2 3{****************************************************************************** 4 TCoolBar 5 ****************************************************************************** 6 7 ***************************************************************************** 8 This file is part of the Lazarus Component Library (LCL) 9 10 See the file COPYING.modifiedLGPL.txt, included in this distribution, 11 for details about the license. 12 ***************************************************************************** 13 14} 15 16{ TCoolBand } 17 18constructor TCoolBand.Create(aCollection: TCollection); 19begin 20 FBreak := True; 21 FColor := clDefault; 22 FControl := Nil; 23 FFixedBackground := True; 24 FImageIndex := -1; 25 FMinHeight := cDefMinHeight; 26 FMinWidth := cDefMinWidth; 27 FParentBitmap := True; 28 FParentColor := True; 29 FVisible := True; 30 FWidth := cDefWidth; 31 inherited Create(aCollection); 32 Assert(aCollection is TCoolBands, 'TCoolBand.Create: aCollection is not TCoolBands'); 33 FCoolBar := TCoolBands(aCollection).FCoolBar; 34 FBitmap := TBitmap.Create; 35 FBitmap.OnChange := @InvalidateCoolBar; 36end; 37 38destructor TCoolBand.Destroy; 39begin 40 FBitmap.Free; 41 inherited Destroy; 42end; 43 44procedure TCoolBand.Assign(aSource: TPersistent); 45var src: TCoolBand; 46 SrcCtrl: TWinControl; 47begin 48 if aSource is TCoolBand then begin 49 src := TCoolBand(aSource); 50 Bitmap := src.Bitmap; 51 Break := src.Break; 52 Color := src.Color; 53 FixedBackground := src.FixedBackground; 54 FixedSize := src.FixedSize; 55 HorizontalOnly := src.HorizontalOnly; 56 ImageIndex := src.ImageIndex; 57 MinHeight := src.MinHeight; 58 MinWidth := src.MinWidth; 59 ParentBitmap := src.ParentBitmap; 60 ParentColor := src.ParentColor; 61 Text := src.Text; 62 Visible := src.Visible; 63 SrcCtrl := Nil; 64 if Assigned(src.Control) then 65 SrcCtrl := FCoolBar.Owner.FindComponent(src.Control.Name) as TWinControl; 66 Control := SrcCtrl; 67 end else 68 inherited Assign(aSource); 69end; 70 71procedure TCoolBand.AutosizeWidth; 72var h, w: Integer; 73begin 74 if Assigned(FControl) and FControl.AutoSize then begin 75 FControl.GetPreferredSize(w, h); 76 if FCoolBar.Vertical then w := h; 77 inc(w, CalcControlLeft+FCoolBar.HorizontalSpacing+cDivider); 78 Width := Math.max(FMinWidth, w); 79 end; 80end; 81 82function TCoolBand.CalcControlLeft: Integer; 83var aImageSize, xHelp: Integer; 84begin 85 Result := cGrabIndent+FCoolBar.GrabWidth+FCoolBar.HorizontalSpacing; 86 xHelp := Result; 87 if (Text <> '') and FCoolBar.ShowText then 88 inc(Result, FTextWidth+FCoolBar.HorizontalSpacing); 89 if Assigned(FCoolBar.Images) then begin 90 if not FCoolBar.Vertical then 91 aImageSize := FCoolBar.Images.WidthForPPI[FCoolBar.ImagesWidth, FCoolBar.Font.PixelsPerInch] 92 else 93 aImageSize := FCoolBar.Images.HeightForPPI[FCoolBar.ImagesWidth, FCoolBar.Font.PixelsPerInch]; 94 if ImageIndex >= 0 then 95 inc(Result, aImageSize+FCoolBar.HorizontalSpacing); 96 end; 97 if Result = xHelp then inc(Result, FCoolBar.HorizontalSpacing); 98end; 99 100function TCoolBand.CalcPreferredHeight: Integer; 101begin 102 Result := FMinHeight; 103 if not FCoolBar.Vertical then begin 104 if Assigned(FControl) then 105 Result := max(Result, FControl.Height+2*FCoolBar.VerticalSpacing); 106 if Assigned(FCoolBar.Images) and (ImageIndex >= 0) then 107 Result := max(Result, FCoolBar.Images.HeightForPPI[FCoolBar.ImagesWidth, FCoolBar.Font.PixelsPerInch]+2*FCoolBar.VerticalSpacing); 108 end else begin 109 if Assigned(FControl) then 110 Result := max(Result, FControl.Width+2*FCoolBar.VerticalSpacing); 111 if Assigned(FCoolBar.Images) and (ImageIndex >= 0) then 112 Result := max(Result, FCoolBar.Images.WidthForPPI[FCoolBar.ImagesWidth, FCoolBar.Font.PixelsPerInch]+2*FCoolBar.VerticalSpacing); 113 end; 114 if FCoolBar.FShowText then 115 Result := max(Result, FCoolBar.FTextHeight+2*FCoolBar.VerticalSpacing); 116 //DebugLn('CalcPreferredHeight ', CalcPreferredHeightHor); 117end; 118 119function TCoolBand.CalcPreferredWidth: Integer; 120begin 121 Result := CalcControlLeft; 122 if Assigned(Control) then inc(Result, Control.Width+FCoolBar.HorizontalSpacing); 123 inc(Result, cDivider); 124 Result := max(FMinWidth, Result); 125end; 126 127procedure TCoolBand.CalcTextWidth; 128begin 129 if Assigned(FCoolBar) and not (csLoading in FCoolBar.ComponentState) then 130 FTextWidth := FCoolBar.Canvas.TextWidth(FText); 131end; 132 133function TCoolBand.GetDisplayName: string; 134begin 135 Result := Text; 136 if Result = '' then Result := ClassName; 137end; 138 139function TCoolBand.GetRight: Integer; 140begin 141 Result := FLeft+FWidth; 142end; 143 144function TCoolBand.IsBitmapStored: Boolean; 145begin 146 Result := not ParentBitmap; 147end; 148 149function TCoolBand.IsColorStored: Boolean; 150begin 151 Result := not ParentColor; 152end; 153 154procedure TCoolBand.InvalidateCoolBar(Sender: TObject); 155begin 156 Changed(False); 157end; 158 159function TCoolBand.GetVisible: Boolean; 160begin 161 Result := FVisible and not (FCoolBar.Vertical and FHorizontalOnly); 162end; 163 164procedure TCoolBand.SetBitmap(AValue: TBitmap); 165begin 166 FParentBitmap := False; 167 FBitmap.Assign(AValue); 168 Changed(False); 169end; 170 171procedure TCoolBand.SetBorderStyle(AValue: TBorderStyle); 172begin 173 if FBorderStyle = AValue then Exit; 174 FBorderStyle := AValue; 175 Changed(False); 176end; 177 178procedure TCoolBand.SetBreak(AValue: Boolean); 179begin 180 if FBreak = AValue then Exit; 181 FBreak := AValue; 182 Changed(True); 183end; 184 185procedure TCoolBand.SetColor(AValue: TColor); 186begin 187 if FColor = AValue then Exit; 188 FColor := AValue; 189 FParentColor := False; 190 Changed(False); 191end; 192 193procedure TCoolBand.SetControl(AValue: TControl); 194var aBand: TCoolBand; 195begin 196 if FControl = AValue then Exit; 197 FControl := AValue; 198 if Assigned(AValue) then begin 199 AValue.Align := alNone; 200 aBand := TCoolBands(Collection).FindBand(AValue); 201 if Assigned(aBand) and (aBand <> Self) then aBand.SetControl(Nil); //remove old association 202 AValue.Parent := FCoolBar; 203 end; 204 Changed(True); 205end; 206 207procedure TCoolBand.SetFixedBackground(AValue: Boolean); 208begin 209 if FFixedBackground = AValue then Exit; 210 FFixedBackground := AValue; 211 Changed(False); 212end; 213 214procedure TCoolBand.SetHorizontalOnly(AValue: Boolean); 215begin 216 if FHorizontalOnly = AValue then Exit; 217 FHorizontalOnly := AValue; 218 Changed(FCoolBar.Vertical); 219end; 220 221procedure TCoolBand.SetImageIndex(AValue: TImageIndex); 222begin 223 if FImageIndex = AValue then Exit; 224 FImageIndex := AValue; 225 Changed(True); 226end; 227 228procedure TCoolBand.SetMinHeight(AValue: Integer); 229begin 230 if FMinHeight = AValue then Exit; 231 FMinHeight := AValue; 232 Changed(False); 233end; 234 235procedure TCoolBand.SetMinWidth(AValue: Integer); 236begin 237 if FMinWidth = AValue then Exit; 238 FMinWidth := AValue; 239 Changed(False); 240end; 241 242procedure TCoolBand.SetParentBitmap(AValue: Boolean); 243begin 244 if FParentBitmap = AValue then Exit; 245 FParentBitmap := AValue; 246 Changed(False); 247end; 248 249procedure TCoolBand.SetParentColor(AValue: Boolean); 250begin 251 if FParentColor = AValue then Exit; 252 FParentColor := AValue; 253 Changed(False); 254end; 255 256procedure TCoolBand.SetText(const AValue: TTranslateString); 257begin 258 if AValue = FText then Exit; 259 FText := AValue; 260 CalcTextWidth; 261 Changed(True); 262end; 263 264procedure TCoolBand.SetVisible(AValue: Boolean); 265begin 266 if FVisible = AValue then Exit; 267 FVisible := AValue; 268 if Assigned(FControl) then FControl.Visible := AValue; 269 Changed(True); 270end; 271 272procedure TCoolBand.SetWidth(AValue: Integer); 273begin 274 if AValue = FWidth then Exit; 275 if AValue < FMinWidth then AValue := FMinWidth; 276 FWidth := AValue; 277 Changed(True); 278end; 279 280{ TCoolBands } 281 282constructor TCoolBands.Create(ACoolBar: TCustomCoolBar); 283begin 284 inherited Create(TCoolBand); 285 FCoolBar := ACoolBar; 286end; 287 288function TCoolBands.Add: TCoolBand; 289begin 290 Result := TCoolBand(inherited Add); 291 //DebugLn('TCoolBands.Add'); 292end; 293 294function TCoolBands.FindBand(AControl: TControl): TCoolBand; 295var i: Integer; 296begin 297 Result := Nil; 298 for i := 0 to Count-1 do 299 if GetItem(i).FControl = AControl then 300 Exit(GetItem(i)); 301end; 302 303function TCoolBands.FindBandindex(AControl: TControl): Integer; 304var i: Integer; 305begin 306 Result := -1; 307 for i := 0 to Count-1 do 308 if GetItem(i).FControl = AControl then 309 Exit(i); 310end; 311 312procedure TCoolBands.Notify(aItem: TCollectionItem; aAction: TCollectionNotification); 313begin 314 inherited Notify(aItem, aAction); 315 if aAction = cnAdded then begin 316 //DebugLn('TCoolBands.Notify: aAction = cnAdded'); 317 TCoolBand(aItem).FCoolBar := FCoolBar; 318 end; 319end; 320 321procedure TCoolBands.Update(aItem: TCollectionItem); 322begin 323 inherited Update(aItem); 324 if Assigned(FCoolBar) then begin 325 //DebugLn('Bands.Update calls CalcAndAlign'); 326 if not Assigned(aItem) then FCoolBar.CalculateAndAlign; 327 FCoolBar.Invalidate; 328 end; 329end; 330 331function TCoolBands.GetItem(Index: Integer): TCoolBand; 332begin 333 Result := TCoolBand(inherited GetItem(Index)); 334end; 335 336function TCoolBands.GetOwner: TPersistent; 337begin 338 Result := FCoolBar; 339end; 340 341procedure TCoolBands.SetItem(Index: Integer; Value: TCoolBand); 342begin 343 inherited SetItem(Index, Value); 344end; 345 346{ TCustomCoolBar } 347 348constructor TCustomCoolBar.Create(AOwner: TComponent); 349begin 350 FBands := TCoolBands.Create(Self); 351 inherited Create(AOwner); 352 ControlStyle := ControlStyle-[csSetCaption] 353 +[csAcceptsControls, csNoFocus, csOpaque, csParentBackground, csReplicatable]; 354 Align := alTop; 355 Height := 75; 356 ParentColor := True; 357 ParentFont := True; 358 FBandBorderStyle := bsSingle; 359 FBandMaximize := bmClick; 360 FBitmap := TBitmap.Create; 361 FBitmap.OnChange := @BitmapOrImageListChange; 362 FBorderEdges := EdgeBorders; 363 FBorderLeft := 2; 364 FBorderTop := 2; 365 FBorderRight := 2; 366 FBorderBottom := 2; 367 FBorderWidth := 2; 368 FGrabStyle := cDefGrabStyle; 369 FGrabWidth := cDefGrabWidth; 370 FHorizontalSpacing := cDefHorSpacing; 371 FImageChangeLink := TChangeLink.Create; 372 FImageChangeLink.OnChange := @BitmapOrImageListChange; 373 FShowText := True; 374 FThemed := True; 375 FVerticalSpacing := cDefVertSpacing; 376 UseDockManager := True; 377end; 378 379destructor TCustomCoolBar.Destroy; 380begin 381 FImageChangeLink.Free; 382 FBitmap.Free; 383 FBands.Free; 384 inherited Destroy; 385end; 386 387function TCustomCoolBar.GetAlign: TAlign; 388begin 389 Result := inherited Align; 390end; 391 392procedure TCustomCoolBar.SetAlign(aValue: TAlign); 393var Old: TAlign; 394begin 395 Old := inherited Align; 396 if aValue = Old then Exit; 397 inherited Align := aValue; 398 if csReading in ComponentState then Exit; 399 Vertical := (aValue in [alLeft, alRight]); 400end; 401 402procedure TCustomCoolBar.SetAutoSize(Value: Boolean); 403begin 404 inherited SetAutoSize(Value); 405 if Value then CalculateAndAlign; 406 Invalidate; 407end; 408 409procedure TCustomCoolBar.SetBandBorderStyle(AValue: TBorderStyle); 410begin 411 if FBandBorderStyle = AValue then Exit; 412 FBandBorderStyle := AValue; 413 Invalidate; 414end; 415 416procedure TCustomCoolBar.SetBands(AValue: TCoolBands); 417begin 418 FBands.Assign(AValue); 419end; 420 421procedure TCustomCoolBar.SetBitmap(AValue: TBitmap); 422begin 423 FBitmap.Assign(AValue); 424end; 425 426procedure TCustomCoolBar.SetCursor(Value: TCursor); 427begin 428 inherited SetCursor(Value); 429 if not FLockCursor then FCursorBkgnd:=Value; 430end; 431 432procedure TCustomCoolBar.SetGrabStyle(AValue: TGrabStyle); 433begin 434 if FGrabStyle = AValue then Exit; 435 FGrabStyle := AValue; 436 Invalidate; 437end; 438 439procedure TCustomCoolBar.SetGrabWidth(AValue: Integer); 440begin 441 if FGrabWidth = AValue then Exit; 442 FGrabWidth := AValue; 443 CalculateAndAlign; 444 Invalidate; 445end; 446 447procedure TCustomCoolBar.SetHorizontalSpacing(AValue: Integer); 448begin 449 if FHorizontalSpacing=AValue then Exit; 450 FHorizontalSpacing:=AValue; 451 CalculateAndAlign; 452 Invalidate; 453end; 454 455procedure TCustomCoolBar.SetImages(AValue: TCustomImageList); 456begin 457 if Assigned(FImages) then 458 FImages.UnRegisterChanges(FImageChangeLink); 459 FImages := AValue; 460 if Assigned(FImages) then begin 461 AValue.RegisterChanges(FImageChangeLink); 462 AValue.FreeNotification(Self); 463 end; 464 CalculateAndAlign; 465 Invalidate; 466end; 467 468procedure TCustomCoolBar.SetImagesWidth(const aImagesWidth: Integer); 469begin 470 if FImagesWidth = aImagesWidth then Exit; 471 FImagesWidth := aImagesWidth; 472 CalculateAndAlign; 473 Invalidate; 474end; 475 476procedure TCustomCoolBar.SetShowText(AValue: Boolean); 477begin 478 if FShowText = AValue then Exit; 479 FShowText := AValue; 480 CalculateAndAlign; 481 Invalidate; 482end; 483 484procedure TCustomCoolBar.SetThemed(AValue: Boolean); 485begin 486 if FThemed = AValue then Exit; 487 FThemed := AValue; 488 Invalidate; 489end; 490 491 492procedure TCustomCoolBar.SetVertical(AValue: Boolean); 493var aRect: TRect; 494begin 495 if FVertical = aValue then Exit; 496 FVertical := AValue; 497 AdjustSize; 498 CalculateAndAlign; 499 Invalidate; 500end; 501 502procedure TCustomCoolBar.SetVerticalSpacing(AValue: Integer); 503begin 504 if FVerticalSpacing=AValue then Exit; 505 FVerticalSpacing:=AValue; 506 CalculateAndAlign; 507 Invalidate; 508end; 509 510procedure TCustomCoolBar.AlignControls(AControl: TControl; var RemainingClientRect: TRect); 511var aAnchor: TAnchorKind; 512 i: Integer; 513begin 514 //DebugLn('AlignControls'); 515 if wcfAligningControls in FWinControlFlags then Exit; 516 if not FRightToLeft then 517 aAnchor := akLeft 518 else 519 aAnchor := akRight; 520 for i := 0 to Bands.Count-1 do 521 if Assigned(Bands[i].FControl) then begin 522 Bands[i].Control.Align := alNone; 523 Bands[i].FControl.BorderSpacing.Around := 0; 524 Bands[i].FControl.Anchors := [akTop, aAnchor]; 525 if not Vertical then begin 526 Bands[i].FControl.AnchorParallel(aAnchor, Bands[i].FControlLeft, Self); 527 Bands[i].FControl.AnchorParallel(akTop, Bands[i].FControlTop, Self); 528 end else begin 529 Bands[i].FControl.AnchorParallel(akTop, Bands[i].FControlLeft, Self); 530 Bands[i].FControl.AnchorParallel(aAnchor, Bands[i].FControlTop, Self); 531 end; 532 end; 533 inherited AlignControls(AControl, RemainingClientRect); 534end; 535 536procedure TCustomCoolBar.AutosizeBands; 537var i: Integer; 538begin 539 BeginUpdate; 540 for i := 0 to Bands.Count-1 do 541 Bands[i].AutosizeWidth; 542 EndUpdate; 543end; 544 545procedure TCustomCoolBar.BitmapOrImageListChange(Sender: TObject); 546begin 547 Invalidate; 548end; 549 550procedure TCustomCoolBar.CalculateAndAlign; 551var i, x, y, aBandHeight, aBorderLeft, aCountM1, aLeft, 552 aPrefSize, aStartIndex, aTop, aWidth, NewWidth,NewHeight: Integer; 553 aRowEnd: Boolean; 554begin 555 //DebugLn('CalculateAndAlign'); 556 if (FUpdateCount > 0) or ([csLoading, csDestroying] * ComponentState <> []) then Exit; 557 aCountM1 := FBands.Count-1; 558 x := 0; 559 for i := 0 to aCountM1 do 560 if FBands[i].Visible then inc(x); 561 SetLength(FVisiBands, x); 562 x := 0; 563 for i := 0 to aCountM1 do 564 if FBands[i].Visible then begin 565 FVisiBands[x] := FBands[i]; 566 inc(x); 567 end; 568 aCountM1 := x-1; 569 if not Vertical then begin 570 if not FRightToLeft then 571 aBorderLeft := FBorderLeft 572 else 573 aBorderLeft := FBorderRight; 574 aPrefSize := FBorderTop+FBorderBottom; 575 end else begin 576 aBorderLeft := FBorderTop; 577 aPrefSize := FBorderLeft+FBorderRight-TCoolBand.cDivider; 578 end; 579 //do not use FBands from this point, only FVisiBands 580 aBandHeight := 0; 581 aStartIndex := 0; 582 //set all Bands in row to uniform height 583 aRowEnd := True; 584 aLeft := aBorderLeft; 585 for i := 0 to aCountM1 do begin 586 if aRowEnd or FVisiBands[i].Break then 587 aLeft := aBorderLeft; 588 if FVisiBands[i].Control is TToolBar then 589 begin 590 if TToolBar(FVisiBands[i].Control).IsVertical then 591 TToolBar(FVisiBands[i].Control).WrapButtons(Height,NewWidth,NewHeight,true) 592 else 593 TToolBar(FVisiBands[i].Control).WrapButtons(Width,NewWidth,NewHeight,true); 594 FVisiBands[i].Control.Width:=NewWidth; 595 FVisiBands[i].Control.Height:=NewHeight; 596 end; 597 aBandHeight := Max(aBandHeight, FVisiBands[i].CalcPreferredHeight); 598 aRowEnd := (i = aCountM1); 599 inc(aLeft, FVisiBands[i].Width); 600 aRowEnd := aRowEnd or ((i < aCountM1) and RowEndHelper(ALeft, i)); 601 if aRowEnd then begin 602 inc(aPrefSize, aBandHeight+TCoolBand.cDivider); 603 for y := aStartIndex to i do 604 FVisiBands[y].FHeight := aBandHeight; 605 aBandHeight := 0; 606 aStartIndex := i+1; 607 end; 608 end; 609 if not Vertical then 610 aTop := FBorderTop 611 else begin 612 if not FRightToLeft then 613 aTop := FBorderLeft 614 else begin 615 aTop := FBorderRight; 616 if not AutoSize then aPrefSize := Width; 617 end; 618 end; 619 aRowEnd := True; 620 include(FWinControlFlags, wcfAligningControls); 621 for i := 0 to aCountM1 do begin 622 if aRowEnd or FVisiBands[i].Break then 623 aLeft := aBorderLeft; 624 if not FRightToLeft or Vertical then 625 FVisiBands[i].FLeft := aLeft 626 else 627 FVisiBands[i].FLeft := Width-aLeft-FVisiBands[i].Width; 628 FVisiBands[i].FRealLeft := FVisiBands[i].FLeft; 629 if not Vertical or not FRightToLeft then 630 FVisiBands[i].FTop := aTop 631 else 632 FVisiBands[i].FTop := Width-aTop-FVisiBands[i].Height; 633 if Assigned(FVisiBands[i].Control) then begin 634 x := FVisiBands[i].CalcControlLeft; 635 aWidth := FVisiBands[i].Width-x-HorizontalSpacing-TCoolBand.cDivider; 636 if not FRightToLeft then begin 637 inc(x, aLeft); 638 if not Vertical then 639 FVisiBands[i].Control.Left := x 640 else 641 FVisiBands[i].Control.Top := x; 642 FVisiBands[i].FControlLeft := x-aBorderLeft; 643 end else begin 644 if not Vertical then begin 645 x := FVisiBands[i].FLeft+TCoolBand.cDivider+HorizontalSpacing; 646 FVisiBands[i].Control.Left := x; 647 FVisiBands[i].FControlLeft := Width-x-Bands[i].FControl.Width-aBorderLeft; 648 end else begin 649 inc(x, aLeft); 650 FVisiBands[i].Control.Top := x; 651 FVisiBands[i].FControlLeft := x-aBorderLeft; 652 end; 653 end; 654 if not Vertical then begin 655 y := aTop+(FVisiBands[i].FHeight-FVisiBands[i].Control.Height) div 2; 656 FVisiBands[i].FControlTop := y-FBorderTop; 657 FVisiBands[i].Control.Top := FVisiBands[i].FControlTop+FBorderTop; 658 FVisiBands[i].Control.Width := aWidth; 659 end else begin 660 y := aTop+(FVisiBands[i].FHeight-FVisiBands[i].Control.Width) div 2; 661 if not FRightToLeft then begin 662 FVisiBands[i].Control.Left := y; 663 FVisiBands[i].FControlTop := y-FBorderLeft; 664 end else begin 665 FVisiBands[i].Control.Left := aPrefSize-y-FVisiBands[i].Control.Width; 666 FVisiBands[i].FControlTop := y-FBorderRight; 667 end; 668 FVisiBands[i].Control.Height := aWidth; 669 end; 670 end; 671 x := FVisiBands[i].Width; 672 inc(aLeft, x); 673 aRowEnd := IsRowEnd(aLeft, i); 674 if aRowEnd or (i = aCountM1) then begin 675 if not Vertical then begin 676 FVisiBands[i].FRealWidth := x+Width-aLeft-FBorderRight; 677 if FRightToLeft then FVisiBands[i].FRealLeft := FBorderLeft; 678 end else 679 FVisiBands[i].FRealWidth := x+Height-aLeft-FBorderBottom; 680 end else 681 FVisiBands[i].FRealWidth := x; 682 if aRowEnd then inc(aTop, FVisiBands[i].FHeight+TCoolBand.cDivider); 683 end; 684 if AutoSize then begin 685 if aCountM1 >= 0 then DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomCoolBar.CalculateAndAlign'){$ENDIF}; 686 inc(FUpdateCount); 687 try 688 InvalidatePreferredSize; 689 AdjustSize; 690 finally 691 if aCountM1 >= 0 then EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomCoolBar.CalculateAndAlign'){$ENDIF}; 692 dec(FUpdateCount); 693 end; 694 end; 695 exclude(FWinControlFlags, wcfAligningControls); 696end; 697 698procedure TCustomCoolBar.CalculatePreferredSize(var PreferredWidth, 699 PreferredHeight: integer; WithThemeSpace: Boolean); 700var i, x, aCountM1: Integer; 701begin 702 aCountM1 := length(FVisiBands)-1; 703 if not Vertical then begin 704 if aCountM1 >= 0 then 705 PreferredHeight := FVisiBands[aCountM1].FTop+FVisiBands[aCountM1].FHeight+FBorderBottom 706 else 707 PreferredHeight := FBorderTop+FBorderBottom; 708 PreferredWidth := 0 709 end else begin 710 PreferredHeight := 0; 711 if aCountM1 >= 0 then begin 712 if not FRightToLeft then 713 PreferredWidth := FVisiBands[aCountM1].FTop+FVisiBands[aCountM1].FHeight+FBorderRight 714 else begin 715 PreferredWidth := FBorderLeft+FVisiBands[0].FTop+FVisiBands[0].FHeight-FVisiBands[aCountM1].FTop+FBorderRight; 716 x := FVisiBands[aCountM1].FTop-FBorderLeft; 717 for i := 0 to aCountM1 do 718 FVisiBands[i].FTop := FVisiBands[i].FTop-x; 719 end; 720 end else 721 PreferredWidth := FBorderLeft+FBorderRight; 722 end; 723end; 724 725function TCustomCoolBar.CalculateRealIndex(AVisibleIndex: Integer): Integer; 726var i, aInvisibles, aVisibles: Integer; 727begin 728 aInvisibles := 0; 729 aVisibles := 0; 730 for i:=0 to FBands.Count-1 do begin 731 if not FBands[i].Visible then 732 inc(aInvisibles) 733 else 734 inc(aVisibles); 735 if aVisibles > AVisibleIndex then break; 736 end; 737 Result := AVisibleIndex+aInvisibles; 738end; 739 740procedure TCustomCoolBar.ChangeCursor(ABand, AGrabber: Boolean); 741begin 742 FLockCursor := True; 743 if ABand then begin 744 if not AGrabber then 745 Cursor := crDefault 746 else 747 if not Vertical then 748 Cursor := crHSplit 749 else 750 Cursor := crVSplit; 751 end else 752 Cursor := FCursorBkgnd; 753 FLockCursor := False; 754end; 755 756procedure TCustomCoolBar.CMBiDiModeChanged(var Message: TLMessage); 757begin 758 inherited CMBiDiModeChanged(Message); 759 FRightToLeft := IsRightToLeft; 760 CalculateAndAlign; 761end; 762 763procedure TCustomCoolBar.CreateWnd; 764begin 765 inherited CreateWnd; 766 FCursorBkgnd := Cursor; 767 DoFontChanged; 768 CalculateAndAlign; 769end; 770 771procedure TCustomCoolBar.DoFontChanged; 772var i: Integer; 773begin 774 if not Canvas.HandleAllocated then 775 Exit; 776 FTextHeight := Canvas.TextHeight('Žy|'); 777 for i := 0 to FBands.Count-1 do 778 FBands[i].CalcTextWidth; 779end; 780 781procedure TCustomCoolBar.DrawTiledBitmap(ARect: TRect; ABitmap: TBitmap); 782var i, j, x, y, aWidth, aHeight: Integer; 783begin 784 aWidth := ABitmap.Width; 785 aHeight := ABitmap.Height; 786 x := (ARect.Right-ARect.Left) div aWidth; 787 y := (ARect.Bottom-ARect.Top) div aHeight; 788 if ((ARect.Right-ARect.Left) mod aWidth) =0 then dec(x); 789 if ((ARect.Bottom-ARect.Top) mod aHeight) =0 then dec(y); 790 Canvas.Clipping := True; 791 Canvas.ClipRect := ARect; 792 for i := 0 to x do 793 for j := 0 to y do 794 Canvas.Draw(ARect.Left+i*aWidth, ARect.Top+j*aHeight, ABitmap); 795 Canvas.Clipping := False; 796end; 797 798procedure TCustomCoolBar.EndUpdate; 799begin 800 inherited EndUpdate; 801 //DebugLn('EndUpdate calls CalculateAndAlign'); 802 if FUpdateCount = 0 then begin 803 DisableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomCoolBar.EndUpdate'){$ENDIF}; 804 try 805 CalculateAndAlign; 806 finally 807 EnableAutoSizing{$IFDEF DebugDisableAutoSizing}('TCustomCoolBar.EndUpdate'){$ENDIF}; 808 end; 809 Invalidate; 810 end; 811end; 812 813procedure TCustomCoolBar.FontChanged(Sender: TObject); 814begin 815 inherited FontChanged(Sender); 816 DoFontChanged; 817 //DebugLn('FontChanged calls CalculateAndAlign'); 818 CalculateAndAlign; 819end; 820 821procedure TCustomCoolBar.InsertControl(AControl: TControl; Index: integer); 822var aBand: TCoolBand; 823begin 824 inherited InsertControl(AControl, Index); 825 //DebugLn('TCustomCoolBar.InsertControl '+inttostr(FUpdateCount)); 826 if (AControl is TWinControl) and not (csLoading in ComponentState) then begin 827 aBand := Bands.FindBand(AControl); 828 if aBand = Nil then begin 829 //DebugLn('TCoolBar.InsertControl: Adding band for Comp=' + AControl.Name + ', class=' + AControl.ClassName); 830 BeginUpdate; 831 aBand := FBands.Add; 832 aBand.Control := AControl; 833 aBand.Width := aBand.CalcPreferredWidth; 834 EndUpdate; 835 end; 836 end; 837end; 838 839procedure TCustomCoolBar.Invalidate; 840var aBorderWidth: Integer; 841begin 842 aBorderWidth := 0; 843 if EdgeOuter <> esNone then inc(aBorderWidth); 844 if EdgeInner <> esNone then inc(aBorderWidth); 845 if (FBorderWidth <> aBorderWidth) or (FBorderEdges <> EdgeBorders) then begin 846 FBorderWidth := aBorderWidth; 847 FBorderEdges := EdgeBorders; 848 if ebLeft in EdgeBorders then 849 FBorderLeft := aBorderWidth 850 else 851 FBorderLeft := 0; 852 if ebTop in EdgeBorders then 853 FBorderTop := aBorderWidth 854 else 855 FBorderTop := 0; 856 if ebRight in EdgeBorders then 857 FBorderRight := aBorderWidth 858 else 859 FBorderRight := 0; 860 if ebBottom in EdgeBorders then 861 FBorderBottom := aBorderWidth 862 else 863 FBorderBottom := 0; 864 CalculateAndAlign; 865 //DebugLn('Change BorderEdge'); 866 end; 867 inherited Invalidate; 868end; 869 870function TCustomCoolBar.IsFirstAtRow(ABand: Integer): Boolean; 871begin 872 if not Vertical then begin 873 if not FRightToLeft then 874 Result := (FVisiBands[ABand].FLeft = FBorderLeft) 875 else 876 Result := (FVisiBands[ABand].Right = Width-FBorderRight); 877 end else 878 Result := (FVisiBands[ABand].FLeft = FBorderTop); 879end; 880 881function TCustomCoolBar.IsRowEnd(ALeft, AVisibleIndex: Integer): Boolean; 882begin 883 Result := (AVisibleIndex < length(FVisiBands)-1) and RowEndHelper(ALeft, AVisibleIndex); 884end; 885 886procedure TCustomCoolBar.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 887var aBand: Integer; 888 aGrabber: Boolean; 889begin 890 inherited MouseDown(Button, Shift, X, Y); 891 if Button = mbRight then 892 begin 893 Cursor := crDefault; 894 Exit; 895 end; 896 MouseToBandPos(X, Y, aBand, aGrabber); 897 FDraggedBandIndex := aBand; 898 if (aBand >= 0) and (length(FVisiBands) >= 1) then begin //hit any Band 899 if not aGrabber or IsFirstAtRow(aBand) 900 or FFixedSize or FVisiBands[aBand-1].FFixedSize then begin 901 if not FFixedOrder then FDragBand := dbMove; //move Band 902 end else begin //resize Band 903 if not FFixedSize and not FVisiBands[aBand-1].FFixedSize then begin 904 FDragBand := dbResize; 905 if not Vertical then begin 906 if not FRightToLeft then 907 FDragInitPos := X-FVisiBands[aBand-1].FWidth-FVisiBands[aBand-1].FLeft 908 else 909 FDragInitPos := FVisiBands[aBand-1].FLeft-X; 910 end else 911 FDragInitPos := Y-FVisiBands[aBand-1].FWidth-FVisiBands[aBand-1].FLeft; 912 end; 913 end; 914 end; 915end; 916 917procedure TCustomCoolBar.MouseMove(Shift: TShiftState; X, Y: Integer); 918var aBand: Integer; 919 aGrabber: Boolean; 920begin 921 inherited MouseMove(Shift, X, Y); 922 if length(FVisiBands) > 0 then begin 923 case FDragBand of 924 dbNone: begin 925 MouseToBandPos(X, Y, aBand, aGrabber); 926 if aBand >= 0 then begin 927 if aGrabber and (aBand > 0) and not FVisiBands[aBand-1].FixedSize 928 and not FFixedSize and not IsFirstAtRow(aBand) then 929 ChangeCursor(True, True) 930 else 931 if length(FVisiBands) > 1 then ChangeCursor(not FixedOrder, False); 932 end else 933 ChangeCursor(False, False); 934 end; 935 dbResize: begin 936 if not Vertical then begin 937 if not FRightToLeft then 938 FVisiBands[FDraggedBandIndex-1].Width := 939 X-FDragInitPos-FVisiBands[FDraggedBandIndex-1].FLeft 940 else 941 FVisiBands[FDraggedBandIndex-1].Width := 942 -X-FDragInitPos+FVisiBands[FDraggedBandIndex-1].Right; 943 end else 944 FVisiBands[FDraggedBandIndex-1].Width := 945 Y-FDragInitPos-FVisiBands[FDraggedBandIndex-1].FLeft 946 end; 947 dbMove: begin 948 if FDraggedBandIndex>-1 then begin 949 Cursor := crDrag; 950 if DragManager.CanStartDragging(self,-1,X,Y) then 951 begin 952 DragManager.DragStart(FVisiBands[FDraggedBandIndex].Control, True, -1, True); 953 Cursor := crDefault; 954 FDraggedBandIndex := -1; 955 end; 956 end; 957 end; 958 end; 959 end; 960end; 961 962procedure TCustomCoolBar.MouseToBandPos(X, Y: Integer; out ABand: Integer; out AGrabber: Boolean); 963var i, aCountM1, aLeft, aTop: Integer; 964begin 965 ABand := low(Integer); 966 AGrabber := False; 967 aCountM1 := length(FVisiBands)-1; 968 if Vertical then begin 969 i := Y; 970 Y := X; 971 X := i; 972 end; 973 if aCountM1 >= 0 then begin 974 if not Vertical or not FRightToLeft then begin 975 if Y > (FVisiBands[aCountM1].Top+FVisiBands[aCountM1].Height+TCoolBand.cDivider) then 976 ABand := cNewRowBelow //new row, i.e. free space below the last row 977 else 978 if Y < 0 then ABand := cNewRowAbove; //new row, i.e. free space above the first row 979 end else begin 980 if Y < (FVisiBands[aCountM1].Top) then 981 ABand := cNewRowBelow //new row, i.e. free space below the last row 982 else 983 if Y > Width then ABand := cNewRowAbove; //new row, i.e. free space space above the first row 984 end; 985 if ABand = low(Integer) then 986 for i := 0 to aCountM1 do begin 987 aLeft := FVisiBands[i].FRealLeft; 988 aTop := FVisiBands[i].FTop; 989 if PtInRect(Rect(aLeft, aTop, aLeft+FVisiBands[i].FRealWidth, 990 aTop+FVisiBands[i].FHeight), Point(X, Y)) then begin 991 ABand := i; 992 //DebugLn('Mouse over Band ', i); 993 if not FRightToLeft or Vertical then 994 AGrabber := (X <= (aLeft+GrabWidth+1)) 995 else 996 AGrabber := (X >= (FVisiBands[i].FLeft+FVisiBands[i].Width-GrabWidth-1)); 997 //DebugLn('Grabber '+BoolToStr(AGrabber), ' hit', ' not hit'); 998 Exit; //Exit! 999 end; 1000 end; 1001 end; 1002end; 1003 1004procedure TCustomCoolBar.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 1005var aBand, w, h, offs: Integer; 1006 newRowBelow, needRecalc, needBandMaximize, aGrabber: Boolean; 1007begin 1008 inherited MouseUp(Button, Shift, X, Y); 1009 if FBandMaximize<>bmNone then begin 1010 case FBandMaximize of 1011 bmClick: needBandMaximize:=true; 1012 bmDblClick:needBandMaximize:=ssDouble in Shift; 1013 else needBandMaximize:=false; 1014 end; 1015 if needBandMaximize then begin 1016 MouseToBandPos(X, Y, aBand, aGrabber); 1017 if aGrabber and Assigned(FVisiBands[aBand].control) then begin 1018 w:=0; 1019 h:=0; 1020 FVisiBands[aBand].control.GetPreferredSize(w,h); 1021 offs:=FVisiBands[aBand].CalcControlLeft 1022 +FVisiBands[aBand].cDivider + HorizontalSpacing; 1023 if vertical then 1024 FVisiBands[aBand].width:=offs+h 1025 else 1026 FVisiBands[aBand].width:=offs+w; 1027 FDraggedBandIndex:=-1; 1028 end; 1029 end; 1030 end; 1031 if (FDragBand = dbMove) and (FDraggedBandIndex <> -1) then begin 1032 needRecalc := False; 1033 MouseToBandPos(X, Y, aBand, newRowBelow); //newRowBelow is NOT used here 1034 if aBand >= cNewRowAbove then begin 1035 if aBand = cNewRowAbove then begin 1036 if FDraggedBandIndex = 0 then begin 1037 if FVisiBands[0].FTop = FVisiBands[1].FTop then begin 1038 FVisiBands[1].FBreak := True; 1039 needRecalc := True; 1040 end; 1041 end else begin 1042 FVisiBands[1].FBreak := True; 1043 FVisiBands[FDraggedBandIndex].Index := 0; 1044 end; 1045 end else begin 1046 newRowBelow := (aBand = cNewRowBelow); 1047 if newRowBelow then aBand := length(FVisiBands)-1; 1048 if Vertical then X := Y; 1049 if aBand <> FDraggedBandIndex then begin //move to new position 1050 if FVisiBands[FDraggedBandIndex].FBreak and (FDraggedBandIndex < (length(FVisiBands)-1)) 1051 then FVisiBands[FDraggedBandIndex+1].FBreak := True; 1052 if not newRowBelow and (((not FRightToLeft or Vertical) 1053 and (X > (FVisiBands[aBand].FLeft+FVisiBands[aBand].Width))) 1054 or ((FRightToLeft and not Vertical) 1055 and (X < FVisiBands[aBand].FLeft))) then begin //beyond the last band in row 1056 FVisiBands[FDraggedBandIndex].FBreak := False; 1057 if FDraggedBandIndex > aBand then 1058 FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand+1) 1059 else 1060 FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand); 1061 needRecalc := (FDraggedBandIndex = (aBand+1)); 1062 end else begin //on another Band 1063 FVisiBands[FDraggedBandIndex].FBreak := FVisiBands[aBand].Break; 1064 if FDraggedBandIndex > aBand then begin //move up or left 1065 FVisiBands[aBand].FBreak := False; 1066 FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand); 1067 end else begin //move down or right 1068 if not newRowBelow then begin 1069 if (FVisiBands[FDraggedBandIndex].FTop = FVisiBands[aBand].FTop) then begin //the same row 1070 FVisiBands[FDraggedBandIndex].FBreak := False; 1071 FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand); 1072 end else begin //other row 1073 FVisiBands[aBand].FBreak := False; 1074 FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand-1); 1075 needRecalc := (FDraggedBandIndex = (aBand-1)); 1076 end; 1077 end else begin //new row 1078 FVisiBands[FDraggedBandIndex].FBreak := True; 1079 FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand); 1080 end; 1081 end; 1082 end; 1083 end else 1084 if newRowBelow then begin //last Band in last row moved to new row 1085 FVisiBands[aBand].FBreak := True; 1086 needRecalc:= True; 1087 end; 1088 end; 1089 if needRecalc then begin //necessary only when no Index is changed 1090 CalculateAndAlign; 1091 Invalidate; 1092 end; 1093 end; 1094 Cursor := crDefault; 1095 if Assigned(FOnChange) then 1096 FOnChange(Self); 1097 end; 1098 FDragBand := dbNone; 1099end; 1100 1101procedure TCustomCoolBar.Notification(AComponent: TComponent; Operation: TOperation); 1102begin 1103 inherited Notification(AComponent, Operation); 1104 if csDestroying in ComponentState then Exit; 1105 if Operation = opRemove then begin 1106 //DebugLn('TCoolBar.Notification: Operation = opRemove'); 1107 if AComponent = FImages then Images := Nil; 1108 end; 1109end; 1110 1111procedure TCustomCoolBar.Paint; 1112var i: Integer; 1113 aGrabDetails,aBackground: TThemedElementDetails; 1114 aGrabStyle: TGrabStyle; 1115 aRaisedBevel: Boolean; 1116 aRect: TRect; 1117const arBevel: array[False..True] of TColor = (clBtnShadow, clBtnHighlight); 1118 1119 function GetCaptionColorDisabled: TColor; 1120 var r1, g1, b1: Byte; 1121 aColor: TColor; 1122 begin 1123 aColor := Font.Color; 1124 if aColor = clDefault then aColor := clBtnText; 1125 GetRGBValues(ColorToRGB(aColor), r1, g1, b1); 1126 i := r1 div 3 + g1 div 3 + b1 div 3; 1127 GetRGBValues(ColorToRGB(Brush.Color), r1, g1, b1); 1128 i := (i+(r1 div 3 + g1 div 3 + b1 div 3)) div 2; 1129 Result := RGBToColor(i, i, i); 1130 end; 1131 1132 procedure PaintGrabber(aRect: TRect); 1133 var l, w: SmallInt; 1134 begin 1135 case aGrabStyle of 1136 gsSimple: begin 1137 Canvas.Pen.Color := clBtnHighlight; 1138 Canvas.Line(aRect.Left, aRect.Top, aRect.Right, aRect.Top); 1139 Canvas.Line(aRect.Left, aRect.Top, aRect.Left, aRect.Bottom+1); 1140 Canvas.Pen.Color := clBtnShadow; 1141 Canvas.Line(aRect.Left, aRect.Bottom, aRect.Right, aRect.Bottom); 1142 Canvas.Line(aRect.Right, aRect.Top, aRect.Right, aRect.Bottom+1); 1143 end; 1144 gsDouble: begin 1145 w := (FGrabWidth-2) div 2; 1146 Canvas.Pen.Color := clBtnHighlight; 1147 if not Vertical then begin 1148 Canvas.Line(aRect.Left, aRect.Top, aRect.Left+w, aRect.Top); 1149 Canvas.Line(aRect.Left, aRect.Top, aRect.Left, aRect.Bottom+1); 1150 Canvas.Line(aRect.Right-w, aRect.Top, aRect.Right, aRect.Top); 1151 Canvas.Line(aRect.Right-w, aRect.Top, aRect.Right-w, aRect.Bottom+1); 1152 end else begin 1153 Canvas.Line(aRect.Left, aRect.Top, aRect.Left, aRect.Top+w); 1154 Canvas.Line(aRect.Left, aRect.Top, aRect.Right+1, aRect.Top); 1155 Canvas.Line(aRect.Left, aRect.Bottom-w, aRect.Right, aRect.Bottom-w); 1156 Canvas.Line(aRect.Left, aRect.Bottom-w, aRect.Left, aRect.Bottom+1); 1157 end; 1158 Canvas.Pen.Color := clBtnShadow; 1159 if not Vertical then begin 1160 Canvas.Line(aRect.Left, aRect.Bottom, aRect.Left+w, aRect.Bottom); 1161 Canvas.Line(aRect.Left+w, aRect.Top, aRect.Left+w, aRect.Bottom+1); 1162 Canvas.Line(aRect.Right-w, aRect.Bottom, aRect.Right, aRect.Bottom); 1163 Canvas.Line(aRect.Right, aRect.Top, aRect.Right, aRect.Bottom+1); 1164 end else begin 1165 Canvas.Line(aRect.Left, aRect.Top+w, aRect.Right, aRect.Top+w); 1166 Canvas.Line(aRect.Right, aRect.Top, aRect.Right, aRect.Top+w+1); 1167 Canvas.Line(aRect.Left, aRect.Bottom, aRect.Right, aRect.Bottom); 1168 Canvas.Line(aRect.Right, aRect.Bottom-w, aRect.Right, aRect.Bottom+1); 1169 end; 1170 end; 1171 gsHorLines: begin 1172 l := (aRect.Bottom-aRect.Top+1) div 3; 1173 inc(aRect.Top); 1174 Canvas.Pen.Color := clBtnShadow; 1175 for w := 0 to l-1 do 1176 Canvas.Line(aRect.Left, aRect.Top+w*3, aRect.Right, aRect.Top+w*3); 1177 Canvas.Pen.Color := clBtnHighlight; 1178 inc(aRect.Top); 1179 for w := 0 to l-1 do 1180 Canvas.Line(aRect.Left, aRect.Top+w*3, aRect.Right, aRect.Top+w*3); 1181 end; 1182 gsVerLines: begin 1183 l := (aRect.Right-aRect.Left+1) div 3; 1184 inc(aRect.Left); 1185 Canvas.Pen.Color := clBtnShadow; 1186 for w := 0 to l-1 do 1187 Canvas.Line(aRect.Left+w*3, aRect.Top, aRect.Left+w*3, aRect.Bottom+1); 1188 Canvas.Pen.Color := clBtnHighlight; 1189 inc(aRect.Left); 1190 for w := 0 to l-1 do 1191 Canvas.Line(aRect.Left+w*3, aRect.Top, aRect.Left+w*3, aRect.Bottom+1); 1192 end; 1193 gsGripper: begin 1194 dec(aRect.Top); 1195 inc(aRect.Bottom); 1196 Canvas.ClipRect := aRect; 1197 Canvas.Clipping := True; 1198 ThemeServices.DrawElement(Canvas.Handle, aGrabDetails, aRect); 1199 Canvas.Clipping := False; 1200 end; 1201 gsButton: begin 1202 dec(aRect.Top); 1203 inc(aRect.Bottom); 1204 ThemeServices.DrawElement(Canvas.Handle, aGrabDetails, aRect); 1205 end; 1206 end; 1207 end; 1208 1209 procedure PaintSeparator(Y: Integer); 1210 begin 1211 //DebugLn('PaintSeparator'); 1212 if not Vertical then begin 1213 Canvas.Pen.Color := arBevel[aRaisedBevel]; 1214 Canvas.Line(FBorderLeft, Y, Width-FBorderRight, Y); 1215 inc(Y); 1216 Canvas.Pen.Color := arBevel[not aRaisedBevel]; 1217 Canvas.Line(FBorderLeft, Y, Width-FBorderRight, Y); 1218 end else begin 1219 Canvas.Pen.Color := arBevel[aRaisedBevel]; 1220 Canvas.Line(Y, FBorderTop, Y, Height-FBorderBottom); 1221 inc(Y); 1222 Canvas.Pen.Color := arBevel[not aRaisedBevel]; 1223 Canvas.Line(Y, FBorderTop, Y, Height-FBorderBottom); 1224 end; 1225 end; 1226 1227var k, x, aCountM1, aLeft, aTop: Integer; 1228 aRowEnd: Boolean; 1229 aColor: TColor; 1230 aDetails: TThemedElementDetails; 1231 aFlags: Cardinal; 1232 aImageSize: TSize; 1233begin 1234 inherited Paint; 1235 if Assigned(FImages) then 1236 aImageSize := FImages.SizeForPPI[ImagesWidth, Font.PixelsPerInch]; 1237 //DebugLn('TCoolBar.Paint'); 1238 //draw Bitmap Background 1239 if FBitmap.Width > 0 then 1240 DrawTiledBitmap(ClientRect, FBitmap) 1241 else begin 1242 if FThemed then begin 1243 aBackground:=ThemeServices.GetElementDetails(trRebarRoot); 1244 ThemeServices.DrawElement(Canvas.Handle,aBackground,ClientRect); 1245 end; 1246 end; 1247 aCountM1 := length(FVisiBands)-1; 1248 if aCountM1 >= 0 then begin 1249 aRaisedBevel := (FBandBorderStyle = bsSingle) and 1250 (EdgeInner = esLowered) and (EdgeOuter = esRaised); 1251 aRowEnd := False; 1252 aGrabStyle := GrabStyle; 1253 if Vertical then 1254 case aGrabStyle of 1255 gsHorLines: aGrabStyle := gsVerLines; 1256 gsVerLines: aGrabStyle := gsHorLines; 1257 end; 1258 case aGrabStyle of 1259 gsGripper: if not Vertical then 1260 aGrabDetails := ThemeServices.GetElementDetails(trGripper) 1261 else 1262 aGrabDetails := ThemeServices.GetElementDetails(trGripperVert); 1263 gsButton: aGrabDetails := ThemeServices.GetElementDetails(tbPushButtonNormal); 1264 end; 1265 if FShowText or Assigned(FImages) then begin 1266 if IsEnabled then 1267 aDetails := ThemeServices.GetElementDetails(tbPushButtonNormal) 1268 else 1269 aDetails := ThemeServices.GetElementDetails(tbPushButtonDisabled); 1270 aFlags := DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX; 1271 if FRightToLeft then aFlags := aFlags or DT_RTLREADING; 1272 end; 1273 if FShowText then begin 1274 if IsEnabled then 1275 Canvas.Font.Color := Font.Color 1276 else 1277 Canvas.Font.Color := GetCaptionColorDisabled; 1278 end; 1279 for i := 0 to aCountM1 do begin 1280 aLeft := FVisiBands[i].FLeft; 1281 aTop := FVisiBands[i].FTop; 1282 aRect := Rect(aLeft, aTop, aLeft+FVisiBands[i].FRealWidth+1, aTop+FVisiBands[i].FHeight); 1283 //paint Band Background 1284 if FVisiBands[i].Bitmap.Width > 0 then 1285 DrawTiledBitmap(aRect, FVisiBands[i].Bitmap) 1286 else begin 1287 if not FVisiBands[i].FixedBackground and FVisiBands[i].ParentBitmap 1288 and (Bitmap.Width > 0) then 1289 DrawTiledBitmap(aRect, Bitmap) 1290 else begin 1291 aColor := FVisiBands[i].FColor; 1292 if (aColor <> clDefault) and (aColor <> clNone) then begin 1293 Canvas.Brush.Color := aColor; 1294 Canvas.FillRect(aRect); 1295 end; 1296 end; 1297 end; 1298 //paint a Grabber 1299 if not FRightToLeft or Vertical then 1300 x := aLeft+TCoolBand.cGrabIndent 1301 else 1302 x := aLeft+FVisiBands[i].Width-GrabWidth-TCoolBand.cGrabIndent; 1303 if not Vertical then 1304 PaintGrabber(Rect(x, aTop+2, x+GrabWidth-1, aTop+FVisiBands[i].FHeight-3)) 1305 else 1306 PaintGrabber(Rect(aTop+2, x, aTop+FVisiBands[i].FHeight-3, x+GrabWidth-1)); 1307 if not FRightToLeft or Vertical then 1308 x := x+GrabWidth+HorizontalSpacing 1309 else 1310 x := x-HorizontalSpacing; 1311 //paint Image 1312 if Assigned(FImages) and (FVisiBands[i].ImageIndex >= 0) then begin 1313 if FRightToLeft and not Vertical then dec(x, aImageSize.cx); 1314 if not Vertical then 1315 ThemeServices.DrawIcon(Canvas, aDetails, 1316 Point(x, aTop+(FVisiBands[i].FHeight-aImageSize.cy) div 2), 1317 FImages, FVisiBands[i].ImageIndex) 1318 else 1319 ThemeServices.DrawIcon(Canvas, aDetails, 1320 Point(aTop+(FVisiBands[i].FHeight-aImageSize.cx) div 2, x), 1321 FImages, FVisiBands[i].ImageIndex); 1322 if not FRightToLeft or Vertical then 1323 inc(x, aImageSize.cx+HorizontalSpacing) 1324 else 1325 dec(x, HorizontalSpacing); 1326 end; 1327 //paint Text 1328 if FShowText then begin 1329 k := aTop + (FVisiBands[i].FHeight - FTextHeight) div 2; 1330 if not Vertical then begin 1331 if FRightToLeft then dec(x, FVisiBands[i].FTextWidth); 1332 Canvas.Font.Orientation := 0; 1333 aRect := Rect(x, k, x+FVisiBands[i].FTextWidth, k+FTextHeight); 1334 end else begin 1335 Canvas.Font.Orientation := 900; 1336 aRect := Rect(k, x+FVisiBands[i].FTextWidth, k+FVisiBands[i].FTextWidth, x+2*FVisiBands[i].FTextWidth); 1337 end; 1338 Canvas.Brush.Style := bsClear; 1339 Canvas.TextOut(aRect.Left, aRect.Top, FVisiBands[i].Text); 1340 end; 1341 if not FRightToLeft or Vertical then 1342 aRowEnd := IsRowEnd(aLeft, i) 1343 else 1344 aRowEnd := IsRowEnd(Width-x, i); 1345 if BandBorderStyle = bsSingle then begin 1346 //paint a Separator border below the row of bands ____ 1347 x := aLeft; 1348 inc(aLeft, FVisiBands[i].Width); 1349 if (aRowEnd or ((i = aCountM1) and not AutoSize)) then begin 1350 if not Vertical or not FRightToLeft then 1351 PaintSeparator(aTop+FVisiBands[i].FHeight) 1352 else 1353 PaintSeparator(aTop-TCoolBand.cDivider); 1354 end; 1355 if not aRowEnd and (i < aCountM1) then begin 1356 //paint Divider | 1357 if not FRightToLeft or Vertical then x := aLeft-TCoolBand.cDivider; 1358 Canvas.Pen.Color := arBevel[not aRaisedBevel]; 1359 if not Vertical then 1360 Canvas.Line(x+1, aTop+1, x+1, aTop+FVisiBands[i].FHeight-1) 1361 else 1362 Canvas.Line(aTop+1, x+1, aTop+FVisiBands[i].FHeight-1, x+1); 1363 Canvas.Pen.Color := arBevel[aRaisedBevel]; 1364 if not Vertical then 1365 Canvas.Line(x, aTop+1, x, aTop+FVisiBands[i].FHeight-1) 1366 else 1367 Canvas.Line(aTop+1, x, aTop+FVisiBands[i].FHeight-1, x); 1368 end; 1369 end; 1370 end; 1371 end; 1372end; 1373 1374procedure TCustomCoolBar.RemoveControl(AControl: TControl); 1375var aBandIndex:Integer; 1376begin 1377 inherited RemoveControl(AControl); 1378 aBandIndex := Bands.FindBandIndex(AControl); 1379 if aBandIndex > -1 then 1380 begin 1381 //DebugLn('TCoolBar.RemoveControl: Comp=' + AControl.Name + ', class=' + AControl.ClassName); 1382 Bands.Items[aBandIndex].Control := Nil; 1383 FDragBand:=dbNone; 1384 FDraggedBandIndex:=-1; 1385 Bands.Delete(aBandIndex); 1386 CalculateAndAlign; 1387 Invalidate; 1388 end; 1389end; 1390 1391function TCustomCoolBar.RowEndHelper(ALeft, AVisibleIdx: Integer): Boolean; 1392var aLimit: Integer; 1393begin 1394 if not Vertical then 1395 aLimit := Width 1396 else 1397 aLimit := Height; 1398 Result := FVisiBands[AVisibleIdx+1].Break or 1399 (ALeft+FVisiBands[AVisibleIdx+1].Width-TCoolBand.cDivider >= aLimit); 1400end; 1401 1402procedure TCustomCoolBar.WMSize(var Message: TLMSize); 1403begin 1404 //DebugLn('WMSize'); 1405 inherited WMSize(Message); 1406 CalculateAndAlign; 1407 Invalidate; //required by GTK2 and WINDOWS 1408end; 1409 1410