diff --git a/lcl/comctrls.pp b/lcl/comctrls.pp index b2c0cd8c2b..d80a5c1eab 100644 --- a/lcl/comctrls.pp +++ b/lcl/comctrls.pp @@ -2215,81 +2215,89 @@ type property OnStartDrag; end; - { TCoolBar } + TGrabStyle = (gsSimple, gsDouble, gsHorLines, gsVerLines, gsGripper, gsButton); + TDragBand = (dbNone, dbMove, dbResize); + TCustomCoolBar = class; + { TCoolBand } + TCoolBand = class(TCollectionItem) private FCoolBar: TCustomCoolBar; FControl: TControl; // Associated control - FTextLabel: TLabel; // Possible text is shown in a Label + FBitmap: TBitmap; FBorderStyle: TBorderStyle; FBreak: Boolean; + FColor: TColor; + FFixedBackground: Boolean; FFixedSize: Boolean; - FVisible: Boolean; + FHeight: Integer; FHorizontalOnly: Boolean; FImageIndex: TImageIndex; - FFixedBackground: Boolean; FMinHeight: Integer; FMinWidth: Integer; - FColor: TColor; - FParentColor: Boolean; FParentBitmap: Boolean; - FBitmap: TBitmap; + FParentColor: Boolean; + FText: TTranslateString; + FVisible: Boolean; + FWidth: Integer; + FLeft: Integer; FTop: Integer; - fCreatingTextLabel: Boolean; - function GetText: string; - function GetWidth: Integer; + FRealWidth: Integer; function IsBitmapStored: Boolean; function IsColorStored: Boolean; - function GetHeight: Integer; function GetVisible: Boolean; - procedure SetBorderStyle(aValue: TBorderStyle); - procedure SetBreak(aValue: Boolean); - procedure SetFixedSize(aValue: Boolean); - procedure SetMinHeight(aValue: Integer); - procedure SetMinWidth(aValue: Integer); - procedure SetVisible(aValue: Boolean); - procedure SetHorizontalOnly(aValue: Boolean); - procedure SetImageIndex(aValue: TImageIndex); - procedure SetFixedBackground(aValue: Boolean); - procedure SetColor(aValue: TColor); - procedure SetControlWidth; - procedure ResetControlProps; - procedure UpdControl(aLabelWidth: integer); - procedure SetControl(aValue: TControl); - procedure SetParentColor(aValue: Boolean); - procedure SetParentBitmap(aValue: Boolean); - procedure SetBitmap(aValue: TBitmap); - procedure SetText(const aValue: string); - procedure SetWidth(aValue: Integer); + procedure SetBitmap(AValue: TBitmap); + procedure SetBorderStyle(AValue: TBorderStyle); + procedure SetBreak(AValue: Boolean); + procedure SetColor(AValue: TColor); + procedure SetControl(AValue: TControl); + procedure SetFixedBackground(AValue: Boolean); + procedure SetHorizontalOnly(AValue: Boolean); + procedure SetImageIndex(AValue: TImageIndex); + procedure SetMinHeight(AValue: Integer); + procedure SetMinWidth(AValue: Integer); + procedure SetParentBitmap(AValue: Boolean); + procedure SetParentColor(AValue: Boolean); + procedure SetText(const AValue: TTranslateString); + procedure SetVisible(AValue: Boolean); + procedure SetWidth(AValue: Integer); + protected const + cDefMinHeight = 25; + cDefMinWidth = 100; + cDefWidth = 180; + cHorSpacing = 7; + cVertSpacing = 3; protected + function CalcPreferredHeight: Integer; + function CalcPrefferedWidth: Integer; function GetDisplayName: string; override; - procedure SetIndex(aValue: Integer); override; public constructor Create(aCollection: TCollection); override; destructor Destroy; override; + procedure InvalidateCoolBar(Sender: TObject); procedure Assign(aSource: TPersistent); override; - property Height: Integer read GetHeight; + property Height: Integer read FHeight; published property Bitmap: TBitmap read FBitmap write SetBitmap stored IsBitmapStored; property BorderStyle: TBorderStyle read FBorderStyle write SetBorderStyle default bsNone; property Break: Boolean read FBreak write SetBreak default True; - property Color: TColor read FColor write SetColor stored IsColorStored default clBtnFace; + property Color: TColor read FColor write SetColor stored IsColorStored default clDefault; property Control: TControl read FControl write SetControl; property FixedBackground: Boolean read FFixedBackground write SetFixedBackground default True; - property FixedSize: Boolean read FFixedSize write SetFixedSize default False; + property FixedSize: Boolean read FFixedSize write FFixedSize default False; property HorizontalOnly: Boolean read FHorizontalOnly write SetHorizontalOnly default False; - property ImageIndex: TImageIndex read FImageIndex write SetImageIndex; - property MinHeight: Integer read FMinHeight write SetMinHeight default 25; - property MinWidth: Integer read FMinWidth write SetMinWidth default 0; + property ImageIndex: TImageIndex read FImageIndex write SetImageIndex default -1; + property MinHeight: Integer read FMinHeight write SetMinHeight default cDefMinHeight; + property MinWidth: Integer read FMinWidth write SetMinWidth default cDefMinWidth; property ParentColor: Boolean read FParentColor write SetParentColor default True; property ParentBitmap: Boolean read FParentBitmap write SetParentBitmap default True; - property Text: string read GetText write SetText; + property Text: TTranslateString read FText write SetText; property Visible: Boolean read GetVisible write SetVisible default True; - property Width: Integer read GetWidth write SetWidth; + property Width: Integer read FWidth write SetWidth default cDefWidth; end; { TCoolBands } @@ -2297,22 +2305,19 @@ type TCoolBands = class(TCollection) private FCoolBar: TCustomCoolBar; - FVisibleCount: Longword; function GetItem(Index: Integer): TCoolBand; procedure SetItem(Index: Integer; aValue: TCoolBand); - procedure CalcPreferredSize(aAlsoUpdate: Boolean; var aPrefWidth, aPrefHeight: integer); protected function GetOwner: TPersistent; override; procedure Update(aItem: TCollectionItem); override; procedure Notify(aItem: TCollectionItem; aAction: TCollectionNotification); override; public - constructor Create(aCoolBar: TCustomCoolBar); + constructor Create(ACoolBar: TCustomCoolBar); function Add: TCoolBand; - function FindBand(aControl: TControl): TCoolBand; + function FindBand(AControl: TControl): TCoolBand; property Items[Index: Integer]: TCoolBand read GetItem write SetItem; default; end; - // BandMaximize is not used now but is needed for Delphi compatibility. // It is not used in Delphi's TCoolBar either. TCoolBandMaximize = (bmNone, bmClick, bmDblClick); @@ -2327,44 +2332,73 @@ type FBitmap: TBitmap; FFixedSize: Boolean; FFixedOrder: Boolean; + FGrabStyle: TGrabStyle; + FGrabWidth: Integer; FImages: TCustomImageList; FImageChangeLink: TChangeLink; FShowText: Boolean; FVertical: Boolean; FOnChange: TNotifyEvent; - function GrabLeft: integer; function GetAlign: TAlign; - procedure SetAlign(aValue: TAlign); reintroduce; - procedure SetBands(aValue: TCoolBands); + procedure SetBandBorderStyle(AValue: TBorderStyle); + procedure SetBands(AValue: TCoolBands); procedure SetBitmap(aValue: TBitmap); - procedure SetImages(aValue: TCustomImageList); - procedure SetShowText(aValue: Boolean); + procedure SetGrabStyle(AValue: TGrabStyle); + procedure SetGrabWidth(AValue: Integer); + procedure SetImages(AValue: TCustomImageList); + procedure SetShowText(AValue: Boolean); procedure SetVertical(aValue: Boolean); - procedure ImageListChange(Sender: TObject); + protected const + cBorderWidth = 2; + cDefGrabStyle = gsDouble; + cDefGrabWidth = 10; protected - procedure AlignControls(aControl: TControl; var aRect: TRect); override; + FVisiBands: array of TCoolBand; + FDefCursor: TCursor; + FDragBand: TDragBand; + FDraggedBandIndex: Integer; // -1 .. space below the last row; other negative .. invalid area + FDragInitPos: Integer; // Initial mouse X - position (for resizing Bands) + FPrevHeight: Integer; + FPrevWidth: Integer; + FTextHeight: Integer; + procedure BitmapOrImageListChange(Sender: TObject); procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer; - WithThemeSpace: Boolean); override; - procedure Notification(AComponent: TComponent; Operation: TOperation); override; + {%H-}WithThemeSpace: Boolean); override; + procedure CalculateAndAlign; + function CalculateRealIndex(AVisibleIndex: Integer): Integer; + procedure DoFontChanged; + procedure CreateWnd; override; + procedure DrawTiledBitmap(ARect: TRect; ABitmap: TBitmap); + procedure FontChanged(Sender: TObject); override; + function IsRowEnd(ALeft, AVisibleIndex: Integer): Boolean; procedure Loaded; override; + procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure MouseEnter; override; + procedure MouseLeave; override; + procedure MouseMove(Shift: TShiftState; X, Y: Integer); override; + procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override; + procedure Notification(AComponent: TComponent; Operation: TOperation); override; procedure Paint; override; procedure Resize; override; + procedure SetAlign(aValue: TAlign); reintroduce; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; - procedure BeginUpdate; override; procedure EndUpdate; override; + procedure MouseToBandPos(X, Y: Integer; out ABand: Integer; out AGrabber: Boolean); procedure InsertControl(AControl: TControl; Index: integer); override; procedure RemoveControl(AControl: TControl); override; public property Align read GetAlign write SetAlign default alTop; - property BandBorderStyle: TBorderStyle read FBandBorderStyle write FBandBorderStyle default bsSingle; + property BandBorderStyle: TBorderStyle read FBandBorderStyle write SetBandBorderStyle default bsSingle; property BandMaximize: TCoolBandMaximize read FBandMaximize write FBandMaximize default bmClick; property Bands: TCoolBands read FBands write SetBands; + property Bitmap: TBitmap read FBitmap write SetBitmap; property FixedSize: Boolean read FFixedSize write FFixedSize default False; property FixedOrder: Boolean read FFixedOrder write FFixedOrder default False; + property GrabStyle: TGrabStyle read FGrabStyle write SetGrabStyle default cDefGrabStyle; + property GrabWidth: Integer read FGrabWidth write SetGrabWidth default cDefGrabWidth; property Images: TCustomImageList read FImages write SetImages; - property Bitmap: TBitmap read FBitmap write SetBitmap; property ShowText: Boolean read FShowText write SetShowText default True; property Vertical: Boolean read FVertical write SetVertical default False; property OnChange: TNotifyEvent read FOnChange write FOnChange; @@ -2395,6 +2429,8 @@ type property FixedSize; property FixedOrder; property Font; + property GrabStyle; + property GrabWidth; property Images; property ParentColor; property ParentFont; diff --git a/lcl/include/coolbar.inc b/lcl/include/coolbar.inc index 3705a184e8..60feedd5ae 100644 --- a/lcl/include/coolbar.inc +++ b/lcl/include/coolbar.inc @@ -12,26 +12,28 @@ ***************************************************************************** } -const - GrabWidth = 9; { TCoolBand } constructor TCoolBand.Create(aCollection: TCollection); begin + FBreak := True; + FColor := clDefault; + FControl := nil; + FFixedBackground := True; + FImageIndex := -1; + FMinHeight := cDefMinHeight; + FMinWidth := cDefMinWidth; + FParentBitmap := True; + FParentColor := True; + FVisible := True; + FWidth := cDefWidth; + inherited Create(aCollection); Assert(aCollection is TCoolBands, 'TCoolBand.Create: aCollection is not TCoolBands'); FCoolBar := TCoolBands(aCollection).FCoolBar; - Width := 100; - FBreak := True; - FColor := clBtnFace; - FFixedBackground := True; - FImageIndex := -1; - FMinHeight := 25; - FParentColor := True; - FParentBitmap := True; FBitmap := TBitmap.Create; - FVisible := True; + FBitmap.OnChange := @InvalidateCoolBar; end; destructor TCoolBand.Destroy; @@ -40,293 +42,11 @@ begin inherited Destroy; end; -function TCoolBand.GetWidth: Integer; -begin - Result := FCoolBar.Width; -end; - -function TCoolBand.GetText: string; -begin - if Assigned(FTextLabel) then - Result := FTextLabel.Caption - else - Result := ''; -end; - -function TCoolBand.IsBitmapStored: Boolean; -begin - Result := not ParentBitmap; -end; - -function TCoolBand.IsColorStored: Boolean; -begin - Result := not ParentColor; -end; - -function TCoolBand.GetHeight: Integer; -begin - if Assigned(FControl) then - Result := FControl.Height - else - Result := 20; -end; - -function TCoolBand.GetVisible: Boolean; -begin - Result := FVisible and not (FCoolBar.Vertical and FHorizontalOnly); -end; - -procedure TCoolBand.ResetControlProps; -begin - FControl.AnchorSide[akLeft].Control := Nil; - FControl.AnchorSide[akRight].Control := Nil; - FControl.BorderSpacing.Left := 0; - FControl.BorderSpacing.Right := 0; - FControl.Anchors := []; - if FCoolBar.BiDiMode = bdLeftToRight then - FControl.Left := FCoolBar.GrabLeft + GrabWidth + 6 - else - FControl.Left := FCoolBar.GrabLeft - FControl.Width - 6; -end; - -procedure TCoolBand.SetBorderStyle(aValue: TBorderStyle); -begin - if FBorderStyle = aValue then Exit; - FBorderStyle := aValue; - Changed(False); -end; - -procedure TCoolBand.SetBreak(aValue: Boolean); -begin - if FBreak = aValue then Exit; - FBreak := aValue; - Changed(False); -end; - -procedure TCoolBand.SetFixedSize(aValue: Boolean); -begin - if FFixedSize = aValue then Exit; - FFixedSize := aValue; - if FFixedSize then - FBreak := False; - Changed(FFixedSize); -end; - -procedure TCoolBand.SetMinHeight(aValue: Integer); -begin - if FMinHeight = aValue then Exit; - FMinHeight := aValue; - Changed(False); -end; - -procedure TCoolBand.SetMinWidth(aValue: Integer); -begin - // No operation currently. Client's width is used for band's width -end; - -procedure TCoolBand.SetVisible(aValue: Boolean); -begin - if FVisible = aValue then Exit; - FVisible := aValue; - Changed(True); -end; - -procedure TCoolBand.SetHorizontalOnly(aValue: Boolean); -begin - if FHorizontalOnly = aValue then Exit; - FHorizontalOnly := aValue; - Changed(FCoolBar.Vertical); -end; - -procedure TCoolBand.SetImageIndex(aValue: TImageIndex); -begin - if FImageIndex = aValue then Exit; - FImageIndex := aValue; - Changed(False); -end; - -procedure TCoolBand.SetFixedBackground(aValue: Boolean); -begin - if FFixedBackground = aValue then Exit; - FFixedBackground := aValue; - Changed(False); -end; - -procedure TCoolBand.SetColor(aValue: TColor); -begin - if FColor = aValue then Exit; - FColor := aValue; - FParentColor := False; - Changed(False); -end; - -procedure TCoolBand.SetControlWidth; -var - www: Integer; -begin - if FControl is TCustomCheckBox then Exit; - // Calculate width in different situations. - if FCoolBar.BiDiMode = bdLeftToRight then - www := Width - FControl.Left - 6 // LeftToRight - else if Assigned(FTextLabel) then - www := FTextLabel.Left - 12 // RightToLeft with TextLabel - else - www := FCoolBar.GrabLeft - 12; // RightToLeft without TextLabel - // Control's width can go negative if CoolBar's width < TextLabel's width. - if www < 0 then - www := 0; - FControl.Width := www; -end; - -procedure TCoolBand.UpdControl(aLabelWidth: integer); -begin - if FCoolBar = Nil then Exit; - FCoolBar.DisableAlign; - try - Inc(FCoolBar.FUpdateCount); - if Assigned(FTextLabel) then - begin - if Assigned(FControl) then - FTextLabel.Top := FTop+4 // Adjust text position for the control (which is higher). - else - FTextLabel.Top := FTop+1; - if FCoolBar.BiDiMode = bdLeftToRight then - FTextLabel.Left := FCoolBar.GrabLeft + GrabWidth + 6 - else - FTextLabel.Left := FCoolBar.GrabLeft - aLabelWidth - 6; - FTextLabel.Visible := FCoolBar.ShowText; - end; - if Assigned(FControl) then - begin - // Calculate left positions and anchoring for text label and control - FControl.Align := alNone; // alCustom does not work here - FControl.FreeNotification(FCoolBar); - FControl.Top := FTop; - if Assigned(FTextLabel) and FCoolBar.ShowText then - begin - if FCoolBar.BiDiMode = bdLeftToRight then - begin - FControl.AnchorSide[akRight].Control := Nil; - FControl.AnchorSide[akLeft].Control := FTextLabel; - FControl.AnchorSide[akLeft].Side := asrRight; - FControl.BorderSpacing.Left := 7; - FControl.Anchors := [akLeft]; - end - else begin - FControl.AnchorSide[akLeft].Control := Nil; - FControl.AnchorSide[akRight].Control := FTextLabel; - FControl.AnchorSide[akRight].Side := asrLeft; - FControl.BorderSpacing.Right := 7; - FControl.Anchors := [akRight]; - end; - end - else - ResetControlProps; - // Make sure other Anchors a Nil - FControl.AnchorSide[akBottom].Control := Nil; - FControl.AnchorSide[akTop].Control := Nil; - FControl.Parent := FCoolBar; - SetControlWidth; - end; - Dec(FCoolBar.FUpdateCount); - finally - FCoolBar.EnableAlign; - end; -end; - -procedure TCoolBand.SetControl(aValue: TControl); -var - Band: TCoolBand; -begin - if FControl = aValue then Exit; - FCoolBar.BeginUpdate; - try - if Assigned(aValue) then - begin - Band := TCoolBands(Collection).FindBand(aValue); - if Assigned(Band) and (Band <> Self) then - begin - Band.ResetControlProps; - Band.SetControl(Nil); // Remove old association - end; - aValue.Parent := Nil; - end; - FControl := aValue; - Changed(True); - finally - FCoolBar.EndUpdate; - end; -end; - -procedure TCoolBand.SetParentColor(aValue: Boolean); -begin - if FParentColor = aValue then Exit; - FParentColor := aValue; - Changed(False); -end; - -procedure TCoolBand.SetParentBitmap(aValue: Boolean); -begin - if FParentBitmap = aValue then Exit; - FParentBitmap := aValue; -end; - -procedure TCoolBand.SetBitmap(aValue: TBitmap); -begin - FParentBitmap := False; - FBitmap.Assign(aValue); - Changed(True); -end; - -procedure TCoolBand.SetText(const aValue: string); -begin - if aValue <> '' then - begin - if FTextLabel = Nil then - begin - Inc(FCoolBar.FUpdateCount); - FTextLabel := TLabel.Create(FCoolBar); - FTextLabel.Name := Format('TextLabel%d', [Index]); - FTextLabel.AutoSize := True; - FTextLabel.FreeNotification(FCoolBar); - FTextLabel.Align := alCustom; - FTextLabel.Parent := FCoolBar; - Dec(FCoolBar.FUpdateCount); - end - else if FTextLabel.Caption = aValue then Exit; - FTextLabel.Caption := aValue; - end - else begin - if Assigned(FTextLabel) then - FreeAndNil(FTextLabel); - end; - Changed(True); -end; - -procedure TCoolBand.SetWidth(aValue: Integer); -begin - // No operation currently -end; - -function TCoolBand.GetDisplayName: string; -begin - Result := Text; - if Result = '' then - Result := ClassName; -end; - -procedure TCoolBand.SetIndex(aValue: Integer); -begin - inherited SetIndex(aValue); -end; - procedure TCoolBand.Assign(aSource: TPersistent); -var - src: TCoolBand; - SrcCtrl: TWinControl; +var src: TCoolBand; + SrcCtrl: TWinControl; begin - if aSource is TCoolBand then - begin + if aSource is TCoolBand then begin src := TCoolBand(aSource); Bitmap := src.Bitmap; Break := src.Break; @@ -341,74 +61,199 @@ begin ParentColor := src.ParentColor; Text := src.Text; Visible := src.Visible; -// Width := src.Width; SrcCtrl := Nil; if Assigned(src.Control) then SrcCtrl := FCoolBar.Owner.FindComponent(src.Control.Name) as TWinControl; Control := SrcCtrl; - end - else + end else inherited Assign(aSource); end; +function TCoolBand.CalcPreferredHeight: Integer; +begin + Result := FMinHeight; + if assigned(FControl) then + Result := max(Result, FControl.Height+2*cVertSpacing); + if FCoolBar.FShowText then + Result := max(Result, FCoolBar.FTextHeight+2*cVertSpacing); + if assigned(FCoolBar.Images) and (ImageIndex >= 0) then + Result := max(Result, FCoolBar.Images.Height+2*cVertSpacing); +end; + +function TCoolBand.CalcPrefferedWidth: Integer; +begin + Result := FCoolBar.GrabWidth+2*cHorSpacing; + if assigned(Control) then + inc(Result, Control.Width+cHorSpacing); + if (FText <> '') and FCoolBar.FShowText then + inc(Result, FCoolBar.Canvas.TextWidth(FText)+cHorSpacing); + Result := max(FMinWidth, Result); +end; + +function TCoolBand.GetDisplayName: string; +begin + Result := Text; + if Result = '' then Result := ClassName; +end; + +function TCoolBand.IsBitmapStored: Boolean; +begin + Result := not ParentBitmap; +end; + +function TCoolBand.IsColorStored: Boolean; +begin + Result := not ParentColor; +end; + +procedure TCoolBand.InvalidateCoolBar(Sender: TObject); +begin + Changed(False); +end; + +function TCoolBand.GetVisible: Boolean; +begin + Result := FVisible and not (FCoolBar.Vertical and FHorizontalOnly); +end; + +procedure TCoolBand.SetBitmap(AValue: TBitmap); +begin + FParentBitmap := False; + FBitmap.Assign(AValue); + Changed(False); +end; + +procedure TCoolBand.SetBorderStyle(AValue: TBorderStyle); +begin + if FBorderStyle = AValue then Exit; + FBorderStyle := AValue; + Changed(False); +end; + +procedure TCoolBand.SetBreak(AValue: Boolean); +begin + if FBreak = AValue then Exit; + FBreak := AValue; + Changed(True); +end; + +procedure TCoolBand.SetColor(AValue: TColor); +begin + if FColor = AValue then Exit; + FColor := AValue; + FParentColor := False; + Changed(False); +end; + +procedure TCoolBand.SetControl(AValue: TControl); +var aBand: TCoolBand; +begin + if FControl = AValue then Exit; + FCoolBar.BeginUpdate; + try + if assigned(AValue) then + begin + AValue.Align := alNone; + aBand := TCoolBands(Collection).FindBand(AValue); + if assigned(aBand) and (aBand <> Self) then + aBand.SetControl(Nil); // Remove old association + AValue.Parent := FCoolBar; + end; + FControl := AValue; + Changed(True); + finally + FCoolBar.EndUpdate; + end; +end; + +procedure TCoolBand.SetFixedBackground(AValue: Boolean); +begin + if FFixedBackground = AValue then Exit; + FFixedBackground := AValue; + Changed(False); +end; + +procedure TCoolBand.SetHorizontalOnly(AValue: Boolean); +begin + if FHorizontalOnly = AValue then Exit; + FHorizontalOnly := AValue; + Changed(FCoolBar.Vertical); +end; + +procedure TCoolBand.SetImageIndex(AValue: TImageIndex); +begin + if FImageIndex = AValue then Exit; + FImageIndex := AValue; + Changed(True); +end; + +procedure TCoolBand.SetMinHeight(AValue: Integer); +begin + if FMinHeight = AValue then Exit; + FMinHeight := AValue; + Changed(False); +end; + +procedure TCoolBand.SetMinWidth(AValue: Integer); +begin + if FMinWidth = AValue then Exit; + FMinWidth := AValue; + Changed(False); +end; + +procedure TCoolBand.SetParentBitmap(AValue: Boolean); +begin + if FParentBitmap = AValue then Exit; + FParentBitmap := AValue; + Changed(False); +end; + +procedure TCoolBand.SetParentColor(AValue: Boolean); +begin + if FParentColor = AValue then Exit; + FParentColor := AValue; + Changed(False); +end; + +procedure TCoolBand.SetText(const AValue: TTranslateString); +begin + if AValue = FText then exit; + FText := AValue; + Changed(True); +end; + +procedure TCoolBand.SetVisible(AValue: Boolean); +begin + if FVisible = AValue then Exit; + FVisible := AValue; + if assigned(FControl) then FControl.Visible := AValue; + Changed(True); +end; + +procedure TCoolBand.SetWidth(AValue: Integer); +begin + if AValue = FWidth then Exit; + if AValue < FMinWidth then AValue := FMinWidth; + FWidth := AValue; + Changed(True); +end; + { TCoolBands } -constructor TCoolBands.Create(aCoolBar: TCustomCoolBar); +constructor TCoolBands.Create(ACoolBar: TCustomCoolBar); begin inherited Create(TCoolBand); - FCoolBar := aCoolBar; -end; - -function TCoolBands.GetItem(Index: Integer): TCoolBand; -begin - Result := TCoolBand(inherited GetItem(Index)); -end; - -procedure TCoolBands.SetItem(Index: Integer; aValue: TCoolBand); -begin - inherited SetItem(Index, aValue); -end; - -function TCoolBands.GetOwner: TPersistent; -begin - Result := FCoolBar; -end; - -procedure TCoolBands.Update(aItem: TCollectionItem); -var - PrefWidth, PrefHeight: integer; -begin - inherited Update(aItem); - if FCoolBar = Nil then Exit; - if csDestroying in FCoolBar.ComponentState then Exit; - if FCoolBar.FUpdateCount = 0 then - CalcPreferredSize(True, PrefWidth, PrefHeight); // Calculate control positions -end; - -procedure TCoolBands.Notify(aItem: TCollectionItem; aAction: TCollectionNotification); -begin - inherited Notify(aItem, aAction); - case aAction of - cnAdded: begin end; - cnExtracting: begin - DebugLn('TCoolBands.Notify: aAction = cnExtracting'); - FreeAndNil(TCoolBand(aItem).FTextLabel); - end; - cnDeleting: begin - DebugLn('TCoolBands.Notify: aAction = cnDeleting'); - end; - end; + FCoolBar := ACoolBar; end; function TCoolBands.Add: TCoolBand; begin Result := TCoolBand(inherited Add); - DebugLn('TCoolBands.Add'); + //DebugLn('TCoolBands.Add'); end; -function TCoolBands.FindBand(aControl: TControl): TCoolBand; -var - i: Integer; +function TCoolBands.FindBand(AControl: TControl): TCoolBand; +var i: Integer; begin Result := nil; for i := 0 to Count-1 do @@ -416,70 +261,69 @@ begin Exit(GetItem(i)); end; -procedure TCoolBands.CalcPreferredSize(aAlsoUpdate: Boolean; var aPrefWidth, aPrefHeight: integer); -var - i, BndWidth, hh: Integer; - LabWidth, CtrlWidth, xHeight: integer; - Band: TCoolBand; +procedure TCoolBands.Notify(aItem: TCollectionItem; aAction: TCollectionNotification); begin - aPrefWidth := 0; - aPrefHeight := 3; - for i := 0 to Count-1 do - begin - Band := Items[i]; - - // Calculate width - BndWidth := 0; - LabWidth := 0; - if Assigned(Band.FTextLabel) and FCoolBar.ShowText then - begin - //DebugLn('TCoolBands.CalcPreferredSize: Calling FTextLabel.GetPreferredSize'); - xHeight := 0; - Band.FTextLabel.GetPreferredSize(LabWidth, xHeight); - BndWidth := LabWidth; + inherited Notify(aItem, aAction); + case aAction of + cnAdded: begin + //DebugLn('TCoolBands.Notify: aAction = cnAdded'); + TCoolBand(aItem).FCoolBar:=FCoolBar; end; - if Assigned(Band.FControl) then - begin - //DebugLn('TCoolBands.CalcPreferredSize: Calling FControl.GetPreferredSize'); - CtrlWidth := 0; - xHeight := 0; - Band.FControl.GetPreferredSize(CtrlWidth, xHeight); - Inc(BndWidth, CtrlWidth); + cnExtracting: begin + //DebugLn('TCoolBands.Notify: aAction = cnExtracting'); end; - aPrefWidth := Max(aPrefWidth, BndWidth); // Select the widest band - - // Calculate height - hh := Band.Height; - if FCoolBar.BandBorderStyle = bsSingle then - Inc(hh, 2); - if aAlsoUpdate then - begin - Band.FTop := aPrefHeight; - Band.UpdControl(LabWidth); // Set control's location + cnDeleting: begin + //DebugLn('TCoolBands.Notify: aAction = cnDeleting'); end; - Inc(aPrefHeight, hh+3); // Height is cumulative - end; end; +procedure TCoolBands.Update(aItem: TCollectionItem); +begin + inherited Update(aItem); + if assigned(FCoolBar) then begin + //DebugLn('Bands.Update calls CalcAndAlign'); + if not assigned(aItem) then FCoolBar.CalculateAndAlign; + FCoolBar.Invalidate; + end; +end; + +function TCoolBands.GetItem(Index: Integer): TCoolBand; +begin + Result := TCoolBand(inherited GetItem(Index)); +end; + +function TCoolBands.GetOwner: TPersistent; +begin + Result := FCoolBar; +end; + +procedure TCoolBands.SetItem(Index: Integer; aValue: TCoolBand); +begin + inherited SetItem(Index, aValue); +end; + { TCustomCoolBar } constructor TCustomCoolBar.Create(AOwner: TComponent); begin inherited Create(AOwner); - ControlStyle := [csAcceptsControls, csCaptureMouse, csClickEvents, csOpaque, csDoubleClicks]; - DragMode := dmAutomatic; - Height := 75; + ControlStyle := ControlStyle - [csSetCaption] + + [csAcceptsControls, csNoFocus, csOpaque, csParentBackground, csReplicatable]; Align := alTop; + Height := 75; ParentColor := True; ParentFont := True; FBandBorderStyle := bsSingle; FBandMaximize := bmClick; FBands := TCoolBands.Create(Self); FBitmap := TBitmap.Create; - FShowText := True; + FBitmap.OnChange:=@BitmapOrImageListChange; + FGrabStyle := cDefGrabStyle; + FGrabWidth := cDefGrabWidth; FImageChangeLink := TChangeLink.Create; - FImageChangeLink.OnChange := @ImageListChange; + FImageChangeLink.OnChange := @BitmapOrImageListChange; + FShowText := True; end; destructor TCustomCoolBar.Destroy; @@ -490,46 +334,31 @@ begin inherited Destroy; end; -procedure TCustomCoolBar.BeginUpdate; -begin - DisableAlign; - inherited BeginUpdate; -end; - -procedure TCustomCoolBar.EndUpdate; -begin - inherited EndUpdate; - EnableAlign; -end; - -function TCustomCoolBar.GrabLeft: integer; -begin - Result := 2; - if BiDiMode <> bdLeftToRight then - Result := Width - GrabWidth - Result; -end; - function TCustomCoolBar.GetAlign: TAlign; begin Result := inherited Align; end; procedure TCustomCoolBar.SetAlign(aValue: TAlign); -var - Old: TAlign; +var Old: TAlign; begin Old := inherited Align; + if aValue = Old then Exit; inherited Align := aValue; - if (csReading in ComponentState) or (aValue = Old) then Exit; - if aValue in [alLeft, alRight] then - Vertical := True - else if aValue in [alTop, alBottom] then - Vertical := False; + if csReading in ComponentState then Exit; + Vertical := (aValue in [alLeft, alRight]); end; -procedure TCustomCoolBar.SetBands(aValue: TCoolBands); +procedure TCustomCoolBar.SetBandBorderStyle(AValue: TBorderStyle); begin - FBands.Assign(aValue); + if FBandBorderStyle = AValue then Exit; + FBandBorderStyle := AValue; + Invalidate; +end; + +procedure TCustomCoolBar.SetBands(AValue: TCoolBands); +begin + FBands.Assign(AValue); end; procedure TCustomCoolBar.SetBitmap(aValue: TBitmap); @@ -537,102 +366,253 @@ begin FBitmap.Assign(aValue); end; -procedure TCustomCoolBar.SetImages(aValue: TCustomImageList); +procedure TCustomCoolBar.SetGrabStyle(AValue: TGrabStyle); begin - if Assigned(FImages) then - FImages.UnRegisterChanges(FImageChangeLink); - FImages := aValue; - if Assigned(FImages) then - begin - FImages.RegisterChanges(FImageChangeLink); - FImages.FreeNotification(Self); - end; + if FGrabStyle = AValue then Exit; + FGrabStyle := AValue; Invalidate; end; -procedure TCustomCoolBar.SetShowText(aValue: Boolean); +procedure TCustomCoolBar.SetGrabWidth(AValue: Integer); begin - if FShowText = aValue then Exit; - FShowText := aValue; - if not (csLoading in ComponentState) then - FBands.Update(Nil); + if FGrabWidth = AValue then Exit; + FGrabWidth := AValue; + CalculateAndAlign; + Invalidate; +end; + +procedure TCustomCoolBar.SetImages(AValue: TCustomImageList); +begin + if Assigned(FImages) then + FImages.UnRegisterChanges(FImageChangeLink); + FImages := AValue; + if Assigned(FImages) then begin + AValue.RegisterChanges(FImageChangeLink); + AValue.FreeNotification(Self); + end; + CalculateAndAlign; + Invalidate; +end; + +procedure TCustomCoolBar.SetShowText(AValue: Boolean); +begin + if FShowText = AValue then Exit; + FShowText := AValue; + CalculateAndAlign; + Invalidate; end; procedure TCustomCoolBar.SetVertical(aValue: Boolean); begin if FVertical = aValue then Exit; + FVertical := aValue; Invalidate; end; -procedure TCustomCoolBar.ImageListChange(Sender: TObject); +procedure TCustomCoolBar.BitmapOrImageListChange(Sender: TObject); begin Invalidate; end; -procedure TCustomCoolBar.AlignControls(aControl: TControl; var aRect: TRect); -var - PrefWidth, PrefHeight: integer; +procedure TCustomCoolBar.CalculateAndAlign; +var i, x, y, aCountM1, aHeight, aLeft, aStartIndex, aTop, aWidth: Integer; + aRowEnd: Boolean; begin - //DebugLn('TCoolBar.AlignControls'); - if FUpdateCount = 0 then + if (FUpdateCount > 0) or ([csLoading, csDestroying] * ComponentState <> []) then exit; + //DebugLn('CalculateAndAlign'); + aCountM1 := FBands.Count-1; + x := 0; + for i := 0 to aCountM1 do + if FBands[i].Visible then inc(x); + SetLength(FVisiBands, x); + x := 0; + for i := 0 to aCountM1 do + if FBands[i].Visible then begin + FVisiBands[x] := FBands[i]; + inc(x); + end; + aCountM1 := x-1; + //Do not use FBands from this point, only FVisiBands + aHeight := 0; + aStartIndex := 0; + aRowEnd := True; + if AutoSize and (aCountM1 >= 0) then DisableAutoSizing; + for i := 0 to aCountM1 do begin - FBands.CalcPreferredSize(True, PrefWidth, PrefHeight); - inherited AlignControls(aControl, aRect); + if (FVisiBands[i].Break or Vertical) or aRowEnd then aLeft := cBorderWidth; + aHeight := Max(aHeight, FVisiBands[i].CalcPreferredHeight); + inc(aLeft, FVisiBands[i].Width); + aRowEnd := (i = aCountM1) or ((i < aCountM1) + and ((FVisiBands[i+1].Break or Vertical) + or ((aLeft+FVisiBands[i+1].Width) > (ClientWidth-2*cBorderWidth)))); + //Set all Bands in row to uniform height + if aRowEnd then begin + for y := aStartIndex to i do + FVisiBands[y].FHeight := aHeight; + aHeight := 0; + aStartIndex := i+1; + end; end; + aTop := cBorderWidth; + aRowEnd := True; + for i := 0 to aCountM1 do + begin + if aRowEnd or (FVisiBands[i].Break or Vertical) then aLeft := cBorderWidth; + FVisiBands[i].FLeft := aLeft; + FVisiBands[i].FTop := aTop; + if assigned(FVisiBands[i].Control) then begin + x := 2+GrabWidth+TCoolBand.cHorSpacing; + if (FVisiBands[i].Text<>'') and FShowText then + inc(x, Canvas.TextWidth(FVisiBands[i].Text)+TCoolBand.cHorSpacing); + if assigned(FImages) and (FVisiBands[i].ImageIndex >=0) then + inc(x, FImages.Width+TCoolBand.cHorSpacing); + aWidth := FVisiBands[i].Width-x-TCoolBand.cHorSpacing-cBorderWidth; + inc(x, aLeft); + y := aTop+(FVisiBands[i].FHeight-FVisiBands[i].Control.Height) div 2; + FVisiBands[i].Control.Width:=aWidth; + FVisiBands[i].Control.AnchorParallel(akLeft, x-cBorderWidth, self); + FVisiBands[i].Control.AnchorParallel(akTop, y-cBorderWidth, self); + end; + x := FVisiBands[i].Width; + inc(aLeft, x); + aRowEnd := IsRowEnd(aLeft, i); + if aRowEnd or (i = aCountM1) then + FVisiBands[i].FRealWidth := x+ClientWidth-aLeft-cBorderWidth + else + FVisiBands[i].FRealWidth := x; + if aRowEnd then + inc(aTop, FVisiBands[i].FHeight+cBorderWidth); + end; + if AutoSize then begin + inc(FUpdateCount); + InvalidatePreferredSize; + AdjustSize; + if aCountM1 >= 0 then EnableAutoSizing; + dec(FUpdateCount); + end; + FPrevWidth := Width; + FPrevHeight := Height; end; -procedure TCustomCoolBar.CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer; +procedure TCustomCoolBar.CalculatePreferredSize(var PreferredWidth, PreferredHeight: Integer; WithThemeSpace: Boolean); -var - MinWidth, MinHeight: Integer; - PrefWidth, PrefHeight: Integer; +var i, aCountM1, aPrefWidth: Integer; begin - // Calculate preferred width and height - FBands.CalcPreferredSize(False, PrefWidth, PrefHeight); - PreferredWidth := Max(PreferredWidth, PrefWidth); - PreferredHeight := Max(PreferredHeight, PrefHeight); + aCountM1 := length(FVisiBands)-1; + if aCountM1 >= 0 then + PreferredHeight := FVisiBands[aCountM1].FTop+FVisiBands[aCountM1].FHeight+2 + else + PreferredHeight := TCoolBand.cDefMinHeight+4; + if not FVertical then + PreferredWidth := 0 + else begin + aPrefWidth := TCoolBand.cDefMinHeight+4; //min. Width is ~ 25 pixels + for i := 0 to aCountM1 do + aPrefWidth := max(aPrefWidth, FVisiBands[i].Width); + PreferredWidth := aPrefWidth; + end; end; -procedure TCustomCoolBar.Notification(AComponent: TComponent; Operation: TOperation); +function TCustomCoolBar.CalculateRealIndex(AVisibleIndex: Integer): Integer; +var i, aInvisibles, aVisibles: Integer; begin - inherited Notification(AComponent, Operation); - if csDestroying in ComponentState then Exit; - if Operation = opRemove then + aInvisibles := 0; + aVisibles := 0; + for i:=0 to FBands.Count-1 do begin - DebugLn('TCoolBar.Notification: Operation = opRemove'); - if AComponent = FImages then - Images := nil; + if not FBands[i].Visible then + inc(aInvisibles) + else + inc(aVisibles); + if aVisibles > AVisibleIndex then break; end; + Result := AVisibleIndex+aInvisibles; +end; + +procedure TCustomCoolBar.CreateWnd; +begin + inherited CreateWnd; + FDefCursor := Cursor; + DoFontChanged; +end; + +procedure TCustomCoolBar.DrawTiledBitmap(ARect: TRect; ABitmap: TBitmap); +var i, j, x, y, aWidth, aHeight: Integer; +begin + aWidth := ABitmap.Width; + aHeight := ABitmap.Height; + x := (ARect.Right-ARect.Left) div aWidth; + y := (ARect.Bottom-ARect.Top) div aHeight; + if ((ARect.Right-ARect.Left) mod aWidth) =0 then dec(x); + if ((ARect.Bottom-ARect.Top) mod aHeight) =0 then dec(y); + Canvas.Clipping := True; + Canvas.ClipRect := ARect; + for i := 0 to x do + for j := 0 to y do + Canvas.Draw(ARect.Left+i*aWidth, ARect.Top+j*aHeight, ABitmap); + Canvas.Clipping := False; +end; + +procedure TCustomCoolBar.DoFontChanged; +begin + FTextHeight := Canvas.TextHeight('Žy|'); +end; + +procedure TCustomCoolBar.EndUpdate; +begin + inherited EndUpdate; + //DebugLn('EndUpdate calls CalculateAndAlign'); + CalculateAndAlign; + Invalidate; +end; + +procedure TCustomCoolBar.FontChanged(Sender: TObject); +begin + inherited FontChanged(Sender); + DoFontChanged; + //DebugLn('FontChanged calls CalculateAndAlign'); + CalculateAndAlign; +end; + +function TCustomCoolBar.IsRowEnd(ALeft, AVisibleIndex: Integer): Boolean; +begin + Result := (AVisibleIndex < (length(FVisiBands)-1)) + and ((FVisiBands[AVisibleIndex+1].Break or Vertical) + or ((ALeft+FVisiBands[AVisibleIndex+1].Width) > ClientWidth)); end; procedure TCustomCoolBar.InsertControl(AControl: TControl; Index: integer); -var - Band: TCoolBand; +var aBand: TCoolBand; begin inherited InsertControl(AControl, Index); - if (FUpdateCount = 0) - and (AControl is TWinControl) and not (csLoading in ComponentState) then - begin - Band := Bands.FindBand(AControl); - if Band = Nil then + //DebugLn('TCustomCoolBar.InsertControl'); + if (FUpdateCount = 0) and (AControl is TWinControl) and + not (csLoading in ComponentState) then begin - DebugLn('TCoolBar.InsertControl: Adding band for Comp=' + AControl.Name + ', class=' + AControl.ClassName); - Band := FBands.Add; - Band.Control := AControl; + aBand := Bands.FindBand(AControl); + if aBand = Nil then + begin + //DebugLn('TCoolBar.InsertControl: Adding band for Comp=' + AControl.Name + ', class=' + AControl.ClassName); + BeginUpdate; + aBand := FBands.Add; + aBand.Control := AControl; + aBand.Width := aBand.CalcPrefferedWidth; + EndUpdate; + end; end; - end; end; procedure TCustomCoolBar.RemoveControl(AControl: TControl); -var - Band: TCoolBand; +var aBand: TCoolBand; begin - Band := Bands.FindBand(AControl); - if Assigned(Band) then begin - DebugLn('TCoolBar.RemoveControl: Comp=' + AControl.Name + ', class=' + AControl.ClassName); - Band.FControl := nil; - end; inherited RemoveControl(AControl); + aBand := Bands.FindBand(AControl); + if assigned(aBand) then begin + //DebugLn('TCoolBar.RemoveControl: Comp=' + AControl.Name + ', class=' + AControl.ClassName); + aBand.FControl := nil; + CalculateAndAlign; + Invalidate; + end; end; procedure TCustomCoolBar.Loaded; @@ -642,49 +622,336 @@ begin FBands.Update(Nil); end; +procedure TCustomCoolBar.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var aBand: Integer; + aGrabber: Boolean; +begin + inherited MouseDown(Button, Shift, X, Y); + MouseToBandPos(X, Y, aBand, aGrabber); + FDraggedBandIndex := aBand; + if aBand >= 0 then begin //Hit any Band + if not aGrabber or (FVisiBands[aBand].FLeft = cBorderWidth) + or FFixedSize or FVisiBands[aBand-1].FFixedSize then begin + if not FFixedOrder then begin //Move Band + FDragBand := dbMove; + Cursor := crDrag; + end; + end else begin //Resize Band + if not FFixedSize and not FVisiBands[aBand-1].FFixedSize then begin + FDragBand := dbResize; + FDragInitPos := X-FVisiBands[aBand-1].FWidth-FVisiBands[aBand-1].FLeft; + end; + end; + end; +end; + +procedure TCustomCoolBar.MouseEnter; +begin + inherited MouseEnter; + FDefCursor := Cursor; +end; + +procedure TCustomCoolBar.MouseLeave; +begin + inherited MouseLeave; + Cursor := FDefCursor; +end; + +procedure TCustomCoolBar.MouseMove(Shift: TShiftState; X, Y: Integer); +var aBand: Integer; + aGrabber: Boolean; +begin + inherited MouseMove(Shift, X, Y); + if (FDragBand = dbNone) and not FFixedSize then begin + MouseToBandPos(X, Y, aBand, aGrabber); + if (aBand >= 1) and not FVisiBands[aBand-1].FFixedSize then begin + if aGrabber and (aBand > 0) and (FVisiBands[aBand].FLeft > cBorderWidth) then + Cursor := crHSplit + else + Cursor := FDefCursor; + end; + end else + if FDragBand = dbResize then begin + FVisiBands[FDraggedBandIndex-1].Width := X-FDragInitPos-FVisiBands[FDraggedBandIndex-1].FLeft; + end; +end; + +procedure TCustomCoolBar.MouseToBandPos(X, Y: Integer; out ABand: Integer; out AGrabber: Boolean); +var i, aCountM1, aLeft, aTop: Integer; +begin + ABand := low(Integer); + AGrabber := False; + aCountM1 := length(FVisiBands)-1; + if aCountM1 >= 0 then begin + if Y > (FVisiBands[aCountM1].FTop+FVisiBands[aCountM1].FHeight+cBorderWidth) then + ABand := -1 // new row, i.e. free space below the last row + else + for i := 0 to aCountM1 do + begin + aLeft := FVisiBands[i].FLeft; + aTop := FVisiBands[i].FTop; + if PtInRect(Rect(aLeft, aTop, aLeft+FVisiBands[i].FRealWidth, + aTop+FVisiBands[i].FHeight), Point(X, Y)) then + begin + ABand := i; + //DebugLn('Mouse over Band ', i); + AGrabber := (X <= (aLeft+GrabWidth+1)); + //DebugLn('Grabber '+BoolToStr(AGrabber), ' hit', ' not hit'); + exit; // EXIT! + end; + end; + end; +end; + +procedure TCustomCoolBar.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); +var aBand: Integer; + newRow, needRecalc: Boolean; +begin + inherited MouseUp(Button, Shift, X, Y); + if FDragBand = dbMove then begin + needRecalc := False; + MouseToBandPos(X, Y, aBand, newRow); //newRow is NOT used here + if aBand >= -1 then begin + newRow := (aBand = -1); + if newRow then aBand := length(FVisiBands)-1; + if aBand <> FDraggedBandIndex then begin //move to new position + if (FVisiBands[FDraggedBandIndex].Break or Vertical) + and (FDraggedBandIndex < (length(FVisiBands)-1)) + then FVisiBands[FDraggedBandIndex+1].FBreak := True; + if (X > (FVisiBands[aBand].FLeft+FVisiBands[aBand].Width)) then begin //beyond the last band in row + FVisiBands[FDraggedBandIndex].FBreak := False; + if FDraggedBandIndex > aBand then + FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand+1) + else + FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand); + if FDraggedBandIndex = (aBand+1) then needRecalc := True; + end else begin //on another Band + FVisiBands[FDraggedBandIndex].FBreak := FVisiBands[aBand].Break; + if FDraggedBandIndex > aBand then begin //move up or left + FVisiBands[aBand].FBreak := False; + FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand); + end else begin //move down or right + if not newRow then begin + if (FVisiBands[FDraggedBandIndex].FTop = FVisiBands[aBand].FTop) then begin //the same row + FVisiBands[FDraggedBandIndex].FBreak := False; + FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand); + end else begin //other row + if (not FVertical) and (FVisiBands[FDraggedBandIndex].FLeft > cBorderWidth) then + FVisiBands[aBand].FBreak := False; + if (FVisiBands[FDraggedBandIndex].FLeft = cBorderWidth) + and (FVisiBands[aBand].FLeft = cBorderWidth) + and (FVertical or ((aBand-FDraggedBandIndex) = 1) + or (length(FVisiBands) = (aBand+1)) + or (FVisiBands[aBand+1].FLeft = cBorderWidth)) then + FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand) + else + FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand-1); + if FDraggedBandIndex = (aBand-1) then needRecalc := True; + end; + end else begin //new row + FVisiBands[FDraggedBandIndex].FBreak := True; + FVisiBands[FDraggedBandIndex].Index := CalculateRealIndex(aBand); + end; + end; + end; + end else + if newRow then begin //last Band in last row moved to new row + FVisiBands[aBand].FBreak := True; + needRecalc:= True; + end; + if needRecalc then begin //necessary only when no Index is changed + CalculateAndAlign; + Invalidate; + end; + end; + end; + if FDragBand > dbNone then begin + Cursor := FDefCursor; + FDragBand := dbNone; + end; +end; + +procedure TCustomCoolBar.Notification(AComponent: TComponent; Operation: TOperation); +begin + inherited Notification(AComponent, Operation); + if csDestroying in ComponentState then Exit; + if Operation = opRemove then begin + //DebugLn('TCoolBar.Notification: Operation = opRemove'); + if AComponent = FImages then Images := nil; + end; +end; + procedure TCustomCoolBar.Paint; +var i, x, aCountM1, aLeft, aTop: Integer; + aRowEnd, aRaisedBevel: Boolean; + aColor: TColor; + aDetails, aGrabDetails: TThemedElementDetails; + aFlags: Cardinal; + aRect: TRect; + +const arBevel: array[False..True] of TColor = (clBtnShadow, clBtnHighlight); procedure PaintGrabber(aRect: TRect); + var l, w: SmallInt; begin - Canvas.Pen.Color := clBtnHighlight; - Canvas.MoveTo(aRect.Left+2, aRect.Top); - Canvas.LineTo(aRect.Left, aRect.Top); - Canvas.LineTo(aRect.Left, aRect.Bottom+1); - Canvas.Pen.Color := clBtnShadow; - Canvas.MoveTo(aRect.Right, aRect.Top); - Canvas.LineTo(aRect.Right, aRect.Bottom); - Canvas.LineTo(aRect.Left, aRect.Bottom); + case FGrabStyle of + gsSimple: begin + Canvas.Pen.Color := clBtnHighlight; + Canvas.Line(aRect.Left, aRect.Top, aRect.Right, aRect.Top); + Canvas.Line(aRect.Left, aRect.Top, aRect.Left, aRect.Bottom+1); + Canvas.Pen.Color := clBtnShadow; + Canvas.Line(aRect.Left, aRect.Bottom, aRect.Right, aRect.Bottom); + Canvas.Line(aRect.Right, aRect.Top, aRect.Right, aRect.Bottom+1); + end; + gsDouble: begin + w := (FGrabWidth-2) div 2; + Canvas.Pen.Color := clBtnHighlight; + Canvas.Line(aRect.Left, aRect.Top, aRect.Left+w, aRect.Top); + Canvas.Line(aRect.Left, aRect.Top, aRect.Left, aRect.Bottom+1); + Canvas.Line(aRect.Right-w, aRect.Top, aRect.Right, aRect.Top); + Canvas.Line(aRect.Right-w, aRect.Top, aRect.Right-w, aRect.Bottom+1); + Canvas.Pen.Color := clBtnShadow; + Canvas.Line(aRect.Left, aRect.Bottom, aRect.Left+w, aRect.Bottom); + Canvas.Line(aRect.Left+w, aRect.Top, aRect.Left+w, aRect.Bottom+1); + Canvas.Line(aRect.Right-w, aRect.Bottom, aRect.Right, aRect.Bottom); + Canvas.Line(aRect.Right, aRect.Top, aRect.Right, aRect.Bottom+1); + end; + gsHorLines: begin + l := (aRect.Bottom-aRect.Top+1) div 3; + inc(aRect.Top); + Canvas.Pen.Color := clBtnShadow; + for w := 0 to l-1 do + Canvas.Line(aRect.Left, aRect.Top+w*3, aRect.Right, aRect.Top+w*3); + Canvas.Pen.Color := clBtnHighlight; + inc(aRect.Top); + for w := 0 to l-1 do + Canvas.Line(aRect.Left, aRect.Top+w*3, aRect.Right, aRect.Top+w*3); + end; + gsVerLines: begin + l := (aRect.Right-aRect.Left+1) div 3; + inc(aRect.Left); + Canvas.Pen.Color := clBtnShadow; + for w := 0 to l-1 do + Canvas.Line(aRect.Left+w*3, aRect.Top, aRect.Left+w*3, aRect.Bottom+1); + Canvas.Pen.Color := clBtnHighlight; + inc(aRect.Left); + for w := 0 to l-1 do + Canvas.Line(aRect.Left+w*3, aRect.Top, aRect.Left+w*3, aRect.Bottom+1); + end; + gsGripper: begin + dec(aRect.Top); + inc(aRect.Bottom); + Canvas.ClipRect := aRect; + Canvas.Clipping := True; + ThemeServices.DrawElement(Canvas.Handle, aGrabDetails, aRect); + Canvas.Clipping := False; + end; + gsButton: begin + dec(aRect.Top); + inc(aRect.Bottom); + ThemeServices.DrawElement(Canvas.Handle, aGrabDetails, aRect); + end; + end; + end; + + procedure PaintSeparator(Y: Integer); + begin + //DebugLn('PaintSeparator'); + Canvas.Pen.Color := arBevel[aRaisedBevel]; + Canvas.Line(1, Y, ClientWidth-2, Y); + inc(Y); + Canvas.Pen.Color := arBevel[not aRaisedBevel]; + Canvas.Line(2, Y, ClientWidth-2, Y); end; -var - i, BottomY: Integer; begin inherited Paint; //DebugLn('TCoolBar.Paint'); - for i := 0 to FBands.Count-1 do - begin - BottomY := FBands[i].FTop+FBands[i].Height+2; - // Paint a grabber - PaintGrabber(Rect(GrabLeft, FBands[i].FTop, GrabLeft+GrabWidth, BottomY-1)); - // Paint a separator border below the band. + //Draw Bitmap Background + if FBitmap.Width > 0 then DrawTiledBitmap(ClientRect, FBitmap); + aCountM1 := length(FVisiBands)-1; + if aCountM1 >= 0 then begin if FBandBorderStyle = bsSingle then + aRaisedBevel := ((EdgeInner = esLowered) and (EdgeOuter = esRaised)); + aRowEnd := False; + case GrabStyle of + gsGripper: aGrabDetails := ThemeServices.GetElementDetails(trGripper); + gsButton: aGrabDetails := ThemeServices.GetElementDetails(tbPushButtonDisabled); + end; + if FShowText or assigned(FImages) then begin + if IsEnabled then + aDetails := ThemeServices.GetElementDetails(tbPushButtonNormal) + else + aDetails := ThemeServices.GetElementDetails(tbPushButtonDisabled); + aFlags := DT_SINGLELINE or DT_VCENTER or DT_NOPREFIX; + if IsRightToLeft then aFlags := aFlags or DT_RTLREADING; + end; + for i := 0 to aCountM1 do begin - Canvas.Line(3, BottomY, Width-3, BottomY); - Canvas.Pen.Color := clBtnHighlight; - Canvas.Line(3, BottomY+1, Width-3, BottomY+1); + aLeft := FVisiBands[i].FLeft; + aTop := FVisiBands[i].FTop; + aRect := Rect(aLeft, aTop, aLeft+FVisiBands[i].FRealWidth+1, aTop+FVisiBands[i].FHeight); + //Paint Band Background + if FVisiBands[i].Bitmap.Width > 0 then begin + DrawTiledBitmap(aRect, FVisiBands[i].Bitmap); + end else begin + if not FVisiBands[i].FixedBackground and FVisiBands[i].ParentBitmap + and (Bitmap.Width > 0) then + DrawTiledBitmap(aRect, Bitmap) + else begin + aColor := FVisiBands[i].FColor; + if (aColor <> clDefault) and (aColor <> clNone) then begin + Canvas.Brush.Color := aColor; + Canvas.FillRect(aRect); + end; + end; + end; + //Paint a Grabber + x := aLeft+2; + PaintGrabber(Rect(x, aTop+2, x+GrabWidth-1, aTop+FVisiBands[i].FHeight-3)); + //Paint Image + x := aLeft+GrabWidth+2+TCoolBand.cHorSpacing; + if assigned(FImages) and (FVisiBands[i].ImageIndex >= 0) then begin + ThemeServices.DrawIcon(Canvas, aDetails, + Point(x, aTop+(FVisiBands[i].FHeight-FImages.Height) div 2), + FImages, FVisiBands[i].ImageIndex); + inc(x, FImages.Width+TCoolBand.cHorSpacing); + end; + //Paint Text + if FShowText then begin + aRect := Rect(x, aTop, x+FVisiBands[i].Width, aTop+FVisiBands[i].FHeight); + ThemeServices.DrawText(Canvas, aDetails, FVisiBands[i].Text, aRect, aFlags, 0); + end; + // Paint a Separator border below the row of bands ____ + inc(aLeft, FVisiBands[i].Width); + aRowEnd := IsRowEnd(aLeft, i); + if (aRowEnd or ((i = aCountM1) and not AutoSize) or (Align in [alLeft, alRight])) + and (FBandBorderStyle = bsSingle) + then PaintSeparator(aTop+FVisiBands[i].FHeight); + if not aRowEnd and (i < aCountM1) and (FBandBorderStyle = bsSingle) then begin + //Paint Divider | + Canvas.Pen.Color := arBevel[not aRaisedBevel]; + Canvas.Line(aLeft-1, aTop+1, aLeft-1, aTop+FVisiBands[i].FHeight-1); + Canvas.Pen.Color := arBevel[aRaisedBevel]; + Canvas.Line(aLeft-2, aTop+1, aLeft-2, aTop+FVisiBands[i].FHeight-1); + end; end; end; end; procedure TCustomCoolBar.Resize; -var - i: Integer; +var aWidth, aHeight: Integer; begin + //DebugLn('Resize'); inherited Resize; - if [csLoading, csDestroying] * ComponentState <> [] then Exit; - if (FUpdateCount = 0) and Assigned(FBands) then - for i := 0 to FBands.Count-1 do - if Assigned(FBands[i].FControl) then - FBands[i].SetControlWidth; + aWidth := Width; + aHeight := Height; + if ((aWidth <> FPrevWidth) or (aHeight <> FPrevHeight)) + and (aWidth*aHeight > 0) and HandleAllocated then + begin + //DebugLn('Resize calls CalcAndAlign'); + CalculateAndAlign; + Invalidate; //Required by GTK2 + end; end;