| 1 | { Customizable component which using BGRABitmap for drawing. Control mostly rendered
|
|---|
| 2 | using framework.
|
|---|
| 3 |
|
|---|
| 4 | Functionality:
|
|---|
| 5 | - Gradients
|
|---|
| 6 | - Double gradients
|
|---|
| 7 | - Rounding
|
|---|
| 8 | - Drop down list
|
|---|
| 9 | - Glyph
|
|---|
| 10 | - States (normal, hover, clicked)
|
|---|
| 11 | - Caption with shadow
|
|---|
| 12 | - Full alpha and antialias support
|
|---|
| 13 |
|
|---|
| 14 | Copyright (C) 2012 Krzysztof Dibowski dibowski at interia.pl
|
|---|
| 15 |
|
|---|
| 16 | This library is free software; you can redistribute it and/or modify it
|
|---|
| 17 | under the terms of the GNU Library General Public License as published by
|
|---|
| 18 | the Free Software Foundation; either version 2 of the License, or (at your
|
|---|
| 19 | option) any later version with the following modification:
|
|---|
| 20 |
|
|---|
| 21 | As a special exception, the copyright holders of this library give you
|
|---|
| 22 | permission to link this library with independent modules to produce an
|
|---|
| 23 | executable, regardless of the license terms of these independent modules,and
|
|---|
| 24 | to copy and distribute the resulting executable under terms of your choice,
|
|---|
| 25 | provided that you also meet, for each linked independent module, the terms
|
|---|
| 26 | and conditions of the license of that module. An independent module is a
|
|---|
| 27 | module which is not derived from or based on this library. If you modify
|
|---|
| 28 | this library, you may extend this exception to your version of the library,
|
|---|
| 29 | but you are not obligated to do so. If you do not wish to do so, delete this
|
|---|
| 30 | exception statement from your version.
|
|---|
| 31 |
|
|---|
| 32 | This program is distributed in the hope that it will be useful, but WITHOUT
|
|---|
| 33 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|---|
| 34 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
|
|---|
| 35 | for more details.
|
|---|
| 36 |
|
|---|
| 37 | You should have received a copy of the GNU Library General Public License
|
|---|
| 38 | along with this library; if not, write to the Free Software Foundation,
|
|---|
| 39 | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|---|
| 40 | }
|
|---|
| 41 |
|
|---|
| 42 | unit BCButton;
|
|---|
| 43 |
|
|---|
| 44 | {$mode objfpc}{$H+}
|
|---|
| 45 |
|
|---|
| 46 | interface
|
|---|
| 47 |
|
|---|
| 48 | uses
|
|---|
| 49 | Classes, LResources, Controls, Dialogs, BGRABitmap, BGRABitmapTypes,
|
|---|
| 50 | Buttons, Graphics, LCLType, types, BCTypes, Forms, BCBasectrls;
|
|---|
| 51 |
|
|---|
| 52 | {off $DEFINE DEBUG}
|
|---|
| 53 |
|
|---|
| 54 | type
|
|---|
| 55 |
|
|---|
| 56 | TBCButtonState = class;
|
|---|
| 57 | TBCButtonStyle = (bbtButton, bbtDropDown);
|
|---|
| 58 | TOnAfterRenderBCButton = procedure(Sender: TObject; const ABGRA: TBGRABitmap;
|
|---|
| 59 | AState: TBCButtonState; ARect: TRect) of object;
|
|---|
| 60 | TBCButtonPropertyData = (pdNone, pdUpdateSize);
|
|---|
| 61 |
|
|---|
| 62 | { TBCButtonState }
|
|---|
| 63 |
|
|---|
| 64 | TBCButtonState = class(TBCProperty)
|
|---|
| 65 | private
|
|---|
| 66 | FBackground: TBCBackground;
|
|---|
| 67 | FBorder: TBCBorder;
|
|---|
| 68 | FFontEx: TBCFont;
|
|---|
| 69 | procedure OnChangeFont(Sender: TObject; AData: PtrInt);
|
|---|
| 70 | procedure OnChangeChildProperty(Sender: TObject; AData: PtrInt);
|
|---|
| 71 | procedure SetBackground(AValue: TBCBackground);
|
|---|
| 72 | procedure SetBorder(AValue: TBCBorder);
|
|---|
| 73 | procedure SetFontEx(const AValue: TBCFont);
|
|---|
| 74 | public
|
|---|
| 75 | constructor Create(AControl: TControl); override;
|
|---|
| 76 | destructor Destroy; override;
|
|---|
| 77 |
|
|---|
| 78 | procedure Assign(Source: TPersistent); override;
|
|---|
| 79 | published
|
|---|
| 80 | property Background: TBCBackground read FBackground write SetBackground;
|
|---|
| 81 | property Border: TBCBorder read FBorder write SetBorder;
|
|---|
| 82 | property FontEx: TBCFont read FFontEx write SetFontEx;
|
|---|
| 83 | end;
|
|---|
| 84 |
|
|---|
| 85 | { TCustomBCButton }
|
|---|
| 86 |
|
|---|
| 87 | TCustomBCButton = class(TBCStyleGraphicControl)
|
|---|
| 88 | private
|
|---|
| 89 | { Private declarations }
|
|---|
| 90 | {$IFDEF DEBUG}
|
|---|
| 91 | FRenderCount: Integer;
|
|---|
| 92 | {$ENDIF}
|
|---|
| 93 | FDropDownArrowSize: Integer;
|
|---|
| 94 | FDropDownWidth: Integer;
|
|---|
| 95 | FFlipArrow: boolean;
|
|---|
| 96 | FActiveButt: TBCButtonStyle;
|
|---|
| 97 | FBGRANormal, FBGRAHover, FBGRAClick: TBGRABitmapEx;
|
|---|
| 98 | FRounding: TBCRounding;
|
|---|
| 99 | FRoundingDropDown: TBCRounding;
|
|---|
| 100 | FStateClicked: TBCButtonState;
|
|---|
| 101 | FStateHover: TBCButtonState;
|
|---|
| 102 | FStateNormal: TBCButtonState;
|
|---|
| 103 | FDown: boolean;
|
|---|
| 104 | FGlyph: TBitmap;
|
|---|
| 105 | FGlyphMargin: integer;
|
|---|
| 106 | FButtonState: TBCMouseState;
|
|---|
| 107 | FDownButtonState: TBCMouseState;
|
|---|
| 108 | FOnAfterRenderBCButton: TOnAfterRenderBCButton;
|
|---|
| 109 | FOnButtonClick: TNotifyEvent;
|
|---|
| 110 | FStaticButton: boolean;
|
|---|
| 111 | FStyle: TBCButtonStyle;
|
|---|
| 112 | FGlobalOpacity: byte;
|
|---|
| 113 | FTextApplyGlobalOpacity: boolean;
|
|---|
| 114 | AutoSizeExtraY: integer;
|
|---|
| 115 | AutoSizeExtraX: integer;
|
|---|
| 116 | procedure AssignDefaultStyle;
|
|---|
| 117 | procedure CalculateGlyphSize(var NeededWidth, NeededHeight: integer);
|
|---|
| 118 | procedure ConvertToGrayScale(ABGRA: TBGRABitmap);
|
|---|
| 119 | procedure Render(ABGRA: TBGRABitmapEx; AState: TBCButtonState);
|
|---|
| 120 | procedure RenderState(ABGRA: TBGRABitmapEx; AState: TBCButtonState;
|
|---|
| 121 | const ARect: TRect; ARounding: TBCRounding);
|
|---|
| 122 | procedure RenderAll(ANow: Boolean = False);
|
|---|
| 123 | function GetButtonRect: TRect;
|
|---|
| 124 | function GetDropDownWidth(AFull: boolean = True): integer;
|
|---|
| 125 | function GetDropDownRect(AFull: Boolean = True): TRect;
|
|---|
| 126 | procedure SeTBCButtonStateClicked(const AValue: TBCButtonState);
|
|---|
| 127 | procedure SeTBCButtonStateHover(const AValue: TBCButtonState);
|
|---|
| 128 | procedure SeTBCButtonStateNormal(const AValue: TBCButtonState);
|
|---|
| 129 | procedure SetDown(AValue: boolean);
|
|---|
| 130 | procedure SetDropDownArrowSize(AValue: Integer);
|
|---|
| 131 | procedure SetDropDownWidth(AValue: Integer);
|
|---|
| 132 | procedure SetFlipArrow(AValue: boolean);
|
|---|
| 133 | procedure SetGlyph(const AValue: TBitmap);
|
|---|
| 134 | procedure SetGlyphMargin(const AValue: integer);
|
|---|
| 135 | procedure SetRounding(AValue: TBCRounding);
|
|---|
| 136 | procedure SetRoundingDropDown(AValue: TBCRounding);
|
|---|
| 137 | procedure SetStaticButton(const AValue: boolean);
|
|---|
| 138 | procedure SetStyle(const AValue: TBCButtonStyle);
|
|---|
| 139 | procedure SetGlobalOpacity(const AValue: byte);
|
|---|
| 140 | procedure SetTextApplyGlobalOpacity(const AValue: boolean);
|
|---|
| 141 | procedure UpdateSize;
|
|---|
| 142 | procedure OnChangeGlyph(Sender: TObject);
|
|---|
| 143 | procedure OnChangeState(Sender: TObject; AData: PtrInt);
|
|---|
| 144 | protected
|
|---|
| 145 | { Protected declarations }
|
|---|
| 146 | procedure CalculatePreferredSize(var PreferredWidth, PreferredHeight: integer;
|
|---|
| 147 | WithThemeSpace: boolean); override;
|
|---|
| 148 | class function GetControlClassDefaultSize: TSize; override;
|
|---|
| 149 | procedure Click; override;
|
|---|
| 150 | procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|---|
| 151 | X, Y: integer); override;
|
|---|
| 152 | procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: integer); override;
|
|---|
| 153 | procedure MouseEnter; override;
|
|---|
| 154 | procedure MouseLeave; override;
|
|---|
| 155 | procedure MouseMove(Shift: TShiftState; X, Y: integer); override;
|
|---|
| 156 | procedure SetEnabled(Value: boolean); override;
|
|---|
| 157 | procedure TextChanged; override;
|
|---|
| 158 | protected
|
|---|
| 159 | {$IFDEF DEBUG}
|
|---|
| 160 | function GetDebugText: String; override;
|
|---|
| 161 | {$ENDIF}
|
|---|
| 162 | function GetStyleExtension: String; override;
|
|---|
| 163 | procedure DrawControl; override;
|
|---|
| 164 | procedure RenderControl; override;
|
|---|
| 165 | protected
|
|---|
| 166 | property AutoSizeExtraVertical: integer read AutoSizeExtraY;
|
|---|
| 167 | property AutoSizeExtraHorizontal: integer read AutoSizeExtraX;
|
|---|
| 168 | property StateNormal: TBCButtonState read FStateNormal write SeTBCButtonStateNormal;
|
|---|
| 169 | property StateHover: TBCButtonState read FStateHover write SeTBCButtonStateHover;
|
|---|
| 170 | property StateClicked: TBCButtonState read FStateClicked write SeTBCButtonStateClicked;
|
|---|
| 171 | property Down: boolean read FDown write SetDown default False;
|
|---|
| 172 | property DropDownWidth: Integer read FDropDownWidth write SetDropDownWidth;
|
|---|
| 173 | property DropDownArrowSize: Integer read FDropDownArrowSize write SetDropDownArrowSize;
|
|---|
| 174 | property FlipArrow: boolean read FFlipArrow write SetFlipArrow;
|
|---|
| 175 | property Glyph: TBitmap read FGlyph write SetGlyph;
|
|---|
| 176 | property GlyphMargin: integer read FGlyphMargin write SetGlyphMargin default 5;
|
|---|
| 177 | property Style: TBCButtonStyle read FStyle write SetStyle default bbtButton;
|
|---|
| 178 | property StaticButton: boolean
|
|---|
| 179 | read FStaticButton write SetStaticButton default False;
|
|---|
| 180 | property GlobalOpacity: byte read FGlobalOpacity write SetGlobalOpacity;
|
|---|
| 181 | property Rounding: TBCRounding read FRounding write SetRounding;
|
|---|
| 182 | property RoundingDropDown: TBCRounding read FRoundingDropDown write SetRoundingDropDown;
|
|---|
| 183 | property TextApplyGlobalOpacity: boolean
|
|---|
| 184 | read FTextApplyGlobalOpacity write SetTextApplyGlobalOpacity;
|
|---|
| 185 | property OnAfterRenderBCButton: TOnAfterRenderBCButton
|
|---|
| 186 | read FOnAfterRenderBCButton write FOnAfterRenderBCButton;
|
|---|
| 187 | property OnButtonClick: TNotifyEvent read FOnButtonClick write FOnButtonClick;
|
|---|
| 188 | public
|
|---|
| 189 | { Public declarations }
|
|---|
| 190 | constructor Create(AOwner: TComponent); override;
|
|---|
| 191 | destructor Destroy; override;
|
|---|
| 192 | procedure Assign(Source: TPersistent); override;
|
|---|
| 193 | procedure SetSizeVariables(newDropDownWidth, newDropDownArrowSize,
|
|---|
| 194 | newAutoSizeExtraVertical, newAutoSizeExtraHorizontal: integer);
|
|---|
| 195 | procedure UpdateControl; override; // Called by EndUpdate
|
|---|
| 196 | end;
|
|---|
| 197 |
|
|---|
| 198 | TBCButton = class(TCustomBCButton)
|
|---|
| 199 | published
|
|---|
| 200 | property Action;
|
|---|
| 201 | property Align;
|
|---|
| 202 | property Anchors;
|
|---|
| 203 | property AssignStyle;
|
|---|
| 204 | property AutoSize;
|
|---|
| 205 | property StateClicked;
|
|---|
| 206 | property StateHover;
|
|---|
| 207 | property StateNormal;
|
|---|
| 208 | property BorderSpacing;
|
|---|
| 209 | property Caption;
|
|---|
| 210 | property Color;
|
|---|
| 211 | property Down;
|
|---|
| 212 | property DropDownWidth;
|
|---|
| 213 | property DropDownArrowSize;
|
|---|
| 214 | property Enabled;
|
|---|
| 215 | property FlipArrow;
|
|---|
| 216 | property GlobalOpacity;
|
|---|
| 217 | property Glyph;
|
|---|
| 218 | property GlyphMargin;
|
|---|
| 219 | property OnAfterRenderBCButton;
|
|---|
| 220 | property OnButtonClick;
|
|---|
| 221 | property OnClick;
|
|---|
| 222 | property OnDblClick;
|
|---|
| 223 | property OnMouseDown;
|
|---|
| 224 | property OnMouseEnter;
|
|---|
| 225 | property OnMouseLeave;
|
|---|
| 226 | property OnMouseMove;
|
|---|
| 227 | property OnMouseUp;
|
|---|
| 228 | property ParentColor;
|
|---|
| 229 | property PopupMenu;
|
|---|
| 230 | property Rounding;
|
|---|
| 231 | property RoundingDropDown;
|
|---|
| 232 | property StaticButton;
|
|---|
| 233 | property Style;
|
|---|
| 234 | property TextApplyGlobalOpacity;
|
|---|
| 235 | property Visible;
|
|---|
| 236 | end;
|
|---|
| 237 |
|
|---|
| 238 | procedure Register;
|
|---|
| 239 |
|
|---|
| 240 | implementation
|
|---|
| 241 |
|
|---|
| 242 | uses LCLIntf, Math, LCLProc, BGRAPolygon, BCTools, SysUtils;
|
|---|
| 243 |
|
|---|
| 244 | procedure Register;
|
|---|
| 245 | begin
|
|---|
| 246 | {$I bcbutton_icon.lrs}
|
|---|
| 247 | RegisterComponents('BGRA Controls', [TBCButton]);
|
|---|
| 248 | end;
|
|---|
| 249 |
|
|---|
| 250 | { TBCButtonState }
|
|---|
| 251 |
|
|---|
| 252 | procedure TBCButtonState.SetFontEx(const AValue: TBCFont);
|
|---|
| 253 | begin
|
|---|
| 254 | if FFontEx = AValue then
|
|---|
| 255 | exit;
|
|---|
| 256 | FFontEx.Assign(AValue);
|
|---|
| 257 |
|
|---|
| 258 | Change;
|
|---|
| 259 | end;
|
|---|
| 260 |
|
|---|
| 261 | procedure TBCButtonState.OnChangeFont(Sender: TObject; AData: PtrInt);
|
|---|
| 262 | begin
|
|---|
| 263 | Change(PtrInt(pdUpdateSize));
|
|---|
| 264 | end;
|
|---|
| 265 |
|
|---|
| 266 | procedure TBCButtonState.OnChangeChildProperty(Sender: TObject; AData: PtrInt);
|
|---|
| 267 | begin
|
|---|
| 268 | Change(AData);
|
|---|
| 269 | end;
|
|---|
| 270 |
|
|---|
| 271 | procedure TBCButtonState.SetBackground(AValue: TBCBackground);
|
|---|
| 272 | begin
|
|---|
| 273 | if FBackground = AValue then Exit;
|
|---|
| 274 | FBackground.Assign(AValue);
|
|---|
| 275 |
|
|---|
| 276 | Change;
|
|---|
| 277 | end;
|
|---|
| 278 |
|
|---|
| 279 | procedure TBCButtonState.SetBorder(AValue: TBCBorder);
|
|---|
| 280 | begin
|
|---|
| 281 | if FBorder = AValue then Exit;
|
|---|
| 282 | FBorder.Assign(AValue);
|
|---|
| 283 |
|
|---|
| 284 | Change;
|
|---|
| 285 | end;
|
|---|
| 286 |
|
|---|
| 287 | constructor TBCButtonState.Create(AControl: TControl);
|
|---|
| 288 | begin
|
|---|
| 289 | FBackground := TBCBackground.Create(AControl);
|
|---|
| 290 | FBorder := TBCBorder.Create(AControl);
|
|---|
| 291 | FFontEx := TBCFont.Create(AControl);
|
|---|
| 292 |
|
|---|
| 293 | FBackground.OnChange := @OnChangeChildProperty;
|
|---|
| 294 | FBorder.OnChange := @OnChangeChildProperty;
|
|---|
| 295 | FFontEx.OnChange := @OnChangeFont;
|
|---|
| 296 |
|
|---|
| 297 | inherited Create(AControl);
|
|---|
| 298 | end;
|
|---|
| 299 |
|
|---|
| 300 | destructor TBCButtonState.Destroy;
|
|---|
| 301 | begin
|
|---|
| 302 | FBackground.Free;
|
|---|
| 303 | FBorder.Free;
|
|---|
| 304 | FFontEx.Free;
|
|---|
| 305 | inherited Destroy;
|
|---|
| 306 | end;
|
|---|
| 307 |
|
|---|
| 308 | procedure TBCButtonState.Assign(Source: TPersistent);
|
|---|
| 309 | begin
|
|---|
| 310 | if Source is TBCButtonState then
|
|---|
| 311 | begin
|
|---|
| 312 | FBackground.Assign(TBCButtonState(Source).FBackground);
|
|---|
| 313 | FBorder.Assign(TBCButtonState(Source).FBorder);
|
|---|
| 314 | FFontEx.Assign(TBCButtonState(Source).FFontEx);
|
|---|
| 315 |
|
|---|
| 316 | Change(PtrInt(pdUpdateSize));
|
|---|
| 317 | end
|
|---|
| 318 | else
|
|---|
| 319 | inherited Assign(Source);
|
|---|
| 320 | end;
|
|---|
| 321 |
|
|---|
| 322 | { TCustomBCButton }
|
|---|
| 323 |
|
|---|
| 324 | procedure TCustomBCButton.AssignDefaultStyle;
|
|---|
| 325 | begin
|
|---|
| 326 | FRounding.RoundX := 12;
|
|---|
| 327 | FRounding.RoundY := 12;
|
|---|
| 328 | // Normal
|
|---|
| 329 | with StateNormal do
|
|---|
| 330 | begin
|
|---|
| 331 | Border.Style := bboNone;
|
|---|
| 332 | FontEx.Color := RGBToColor(230,230,255);
|
|---|
| 333 | FontEx.Style := [fsBold];
|
|---|
| 334 | FontEx.Shadow := True;
|
|---|
| 335 | FontEx.ShadowOffsetX := 1;
|
|---|
| 336 | FontEx.ShadowOffsetY := 1;
|
|---|
| 337 | FontEx.ShadowRadius := 2;
|
|---|
| 338 | Background.Gradient1EndPercent := 60;
|
|---|
| 339 | Background.Style := bbsGradient;
|
|---|
| 340 | // Gradient1
|
|---|
| 341 | with Background.Gradient1 do
|
|---|
| 342 | begin
|
|---|
| 343 | EndColor := RGBToColor(64,64,128);
|
|---|
| 344 | StartColor := RGBToColor(0,0,64);
|
|---|
| 345 | end;
|
|---|
| 346 | // Gradient2
|
|---|
| 347 | with Background.Gradient2 do
|
|---|
| 348 | begin
|
|---|
| 349 | EndColor := RGBToColor(0,0,64);
|
|---|
| 350 | GradientType := gtRadial;
|
|---|
| 351 | Point1XPercent := 50;
|
|---|
| 352 | Point1YPercent := 100;
|
|---|
| 353 | Point2YPercent := 0;
|
|---|
| 354 | StartColor := RGBToColor(64,64,128);
|
|---|
| 355 | end;
|
|---|
| 356 | end;
|
|---|
| 357 | // Hover
|
|---|
| 358 | with StateHover do
|
|---|
| 359 | begin
|
|---|
| 360 | Border.Style := bboNone;
|
|---|
| 361 | FontEx.Color := RGBToColor(255,255,255);
|
|---|
| 362 | FontEx.Style := [fsBold];
|
|---|
| 363 | FontEx.Shadow := True;
|
|---|
| 364 | FontEx.ShadowOffsetX := 1;
|
|---|
| 365 | FontEx.ShadowOffsetY := 1;
|
|---|
| 366 | FontEx.ShadowRadius := 2;
|
|---|
| 367 | Background.Gradient1EndPercent := 100;
|
|---|
| 368 | Background.Style := bbsGradient;
|
|---|
| 369 | // Gradient1
|
|---|
| 370 | with Background.Gradient1 do
|
|---|
| 371 | begin
|
|---|
| 372 | EndColor := RGBToColor(0,64,128);
|
|---|
| 373 | GradientType := gtRadial;
|
|---|
| 374 | Point1XPercent := 50;
|
|---|
| 375 | Point1YPercent := 100;
|
|---|
| 376 | Point2YPercent := 0;
|
|---|
| 377 | StartColor := RGBToColor(0,128,255);
|
|---|
| 378 | end;
|
|---|
| 379 | end;
|
|---|
| 380 | // Clicked
|
|---|
| 381 | with StateClicked do
|
|---|
| 382 | begin
|
|---|
| 383 | Border.Style := bboNone;
|
|---|
| 384 | FontEx.Color := RGBToColor(230,230,255);
|
|---|
| 385 | FontEx.Style := [fsBold];
|
|---|
| 386 | FontEx.Shadow := True;
|
|---|
| 387 | FontEx.ShadowOffsetX := 1;
|
|---|
| 388 | FontEx.ShadowOffsetY := 1;
|
|---|
| 389 | FontEx.ShadowRadius := 2;
|
|---|
| 390 | Background.Gradient1EndPercent := 100;
|
|---|
| 391 | Background.Style := bbsGradient;
|
|---|
| 392 | // Gradient1
|
|---|
| 393 | with Background.Gradient1 do
|
|---|
| 394 | begin
|
|---|
| 395 | EndColor := RGBToColor(0,0,64);
|
|---|
| 396 | GradientType := gtRadial;
|
|---|
| 397 | Point1XPercent := 50;
|
|---|
| 398 | Point1YPercent := 100;
|
|---|
| 399 | Point2YPercent := 0;
|
|---|
| 400 | StartColor := RGBToColor(0,64,128);
|
|---|
| 401 | end;
|
|---|
| 402 | end;
|
|---|
| 403 | end;
|
|---|
| 404 |
|
|---|
| 405 | procedure TCustomBCButton.CalculateGlyphSize(var NeededWidth, NeededHeight: integer);
|
|---|
| 406 | begin
|
|---|
| 407 | if FGlyph = nil then
|
|---|
| 408 | begin
|
|---|
| 409 | NeededHeight := 0;
|
|---|
| 410 | NeededWidth := 0;
|
|---|
| 411 | Exit;
|
|---|
| 412 | end;
|
|---|
| 413 |
|
|---|
| 414 | NeededWidth := FGlyph.Width;
|
|---|
| 415 | NeededHeight := FGlyph.Height;
|
|---|
| 416 | end;
|
|---|
| 417 |
|
|---|
| 418 | procedure TCustomBCButton.ConvertToGrayScale(ABGRA: TBGRABitmap);
|
|---|
| 419 | var
|
|---|
| 420 | bounds: TRect;
|
|---|
| 421 | px: PBGRAPixel;
|
|---|
| 422 | xb, yb: integer;
|
|---|
| 423 | begin
|
|---|
| 424 | bounds := ABGRA.GetImageBounds;
|
|---|
| 425 | if (bounds.Right <= bounds.Left) or (bounds.Bottom <= Bounds.Top) then
|
|---|
| 426 | exit;
|
|---|
| 427 |
|
|---|
| 428 | for yb := bounds.Top to bounds.bottom - 1 do
|
|---|
| 429 | begin
|
|---|
| 430 | px := ABGRA.scanline[yb] + bounds.left;
|
|---|
| 431 | for xb := bounds.left to bounds.right - 1 do
|
|---|
| 432 | begin
|
|---|
| 433 | px^ := BGRAToGrayscale(px^);
|
|---|
| 434 | Inc(px);
|
|---|
| 435 | end;
|
|---|
| 436 | end;
|
|---|
| 437 | ABGRA.InvalidateBitmap;
|
|---|
| 438 | end;
|
|---|
| 439 |
|
|---|
| 440 | procedure TCustomBCButton.RenderAll(ANow: Boolean);
|
|---|
| 441 | begin
|
|---|
| 442 | if (csCreating in FControlState) or IsUpdating or (FBGRANormal=nil) then
|
|---|
| 443 | Exit;
|
|---|
| 444 |
|
|---|
| 445 | if ANow then
|
|---|
| 446 | begin
|
|---|
| 447 | Render(FBGRANormal, FStateNormal);
|
|---|
| 448 | Render(FBGRAHover, FStateHover);
|
|---|
| 449 | Render(FBGRAClick, FStateClicked);
|
|---|
| 450 | end else
|
|---|
| 451 | begin
|
|---|
| 452 | FBGRANormal.NeedRender := True;
|
|---|
| 453 | FBGRAHover.NeedRender := True;
|
|---|
| 454 | FBGRAClick.NeedRender := True;
|
|---|
| 455 | end;
|
|---|
| 456 | end;
|
|---|
| 457 |
|
|---|
| 458 | function TCustomBCButton.GetButtonRect: TRect;
|
|---|
| 459 | begin
|
|---|
| 460 | Result := GetClientRect;
|
|---|
| 461 | if FStyle=bbtDropDown then
|
|---|
| 462 | Dec(Result.Right,GetDropDownWidth(False));
|
|---|
| 463 | end;
|
|---|
| 464 |
|
|---|
| 465 | function TCustomBCButton.GetDropDownWidth(AFull: boolean): integer;
|
|---|
| 466 | begin
|
|---|
| 467 | Result := FDropDownWidth + (ifthen(AFull, 2, 1) * FStateNormal.FBorder.Width);
|
|---|
| 468 | end;
|
|---|
| 469 |
|
|---|
| 470 | function TCustomBCButton.GetDropDownRect(AFull: Boolean): TRect;
|
|---|
| 471 | begin
|
|---|
| 472 | Result := GetClientRect;
|
|---|
| 473 | Result.Left := Result.Right - GetDropDownWidth(AFull);
|
|---|
| 474 | end;
|
|---|
| 475 |
|
|---|
| 476 | procedure TCustomBCButton.Render(ABGRA: TBGRABitmapEx;
|
|---|
| 477 | AState: TBCButtonState);
|
|---|
| 478 | var
|
|---|
| 479 | r,r_a: TRect;
|
|---|
| 480 |
|
|---|
| 481 | { TODO: Create customizable glyph position by creating TBCGlyph type
|
|---|
| 482 | and method in BCTools which render it }
|
|---|
| 483 | procedure _RenderGlyph;
|
|---|
| 484 | var
|
|---|
| 485 | w, h, t, l: Integer;
|
|---|
| 486 | g: TBGRABitmap;
|
|---|
| 487 | begin
|
|---|
| 488 | if (FGlyph<>nil) and (not FGlyph.Empty) then
|
|---|
| 489 | begin
|
|---|
| 490 | CalculateTextSize(Caption,AState.FontEx,w,h);
|
|---|
| 491 | l := r.Right - Round(((r.Right-r.Left) + w + FGlyph.Width)/2);
|
|---|
| 492 | t := r.Bottom - Round(((r.Bottom-r.Top) + FGlyph.Height) / 2);
|
|---|
| 493 | g := TBGRABitmap.Create(Glyph);
|
|---|
| 494 | ABGRA.PutImage(l,t,g,dmDrawWithTransparency);
|
|---|
| 495 | g.Free;
|
|---|
| 496 | Inc(r.Left,l+FGlyph.Width+FGlyphMargin);
|
|---|
| 497 | end;
|
|---|
| 498 | end;
|
|---|
| 499 |
|
|---|
| 500 | begin
|
|---|
| 501 | if (csCreating in FControlState) or IsUpdating then
|
|---|
| 502 | Exit;
|
|---|
| 503 |
|
|---|
| 504 | ABGRA.NeedRender := False;
|
|---|
| 505 |
|
|---|
| 506 | { Refreshing size }
|
|---|
| 507 | ABGRA.SetSize(Width, Height);
|
|---|
| 508 |
|
|---|
| 509 | { Calculating rect }
|
|---|
| 510 | r := GetButtonRect;
|
|---|
| 511 | CalculateBorderRect(AState.Border,r);
|
|---|
| 512 |
|
|---|
| 513 | if FStyle = bbtDropDown then
|
|---|
| 514 | begin
|
|---|
| 515 | r_a := GetDropDownRect;
|
|---|
| 516 | CalculateBorderRect(AState.Border,r_a);
|
|---|
| 517 | end;
|
|---|
| 518 |
|
|---|
| 519 | { Clearing previous paint }
|
|---|
| 520 | ABGRA.Fill(BGRAPixelTransparent);
|
|---|
| 521 | { Basic body }
|
|---|
| 522 | RenderState(ABGRA, AState, r, FRounding);
|
|---|
| 523 | if FStyle = bbtDropDown then
|
|---|
| 524 | begin
|
|---|
| 525 | RenderState(ABGRA, AState, r_a, FRoundingDropDown);
|
|---|
| 526 | // Click offset for arrow
|
|---|
| 527 | if AState=FStateClicked then
|
|---|
| 528 | begin
|
|---|
| 529 | Inc(r_a.Left,2);
|
|---|
| 530 | Inc(r_a.Top,2);
|
|---|
| 531 | end;
|
|---|
| 532 |
|
|---|
| 533 | if FFlipArrow then
|
|---|
| 534 | RenderArrow(TBGRABitmap(ABGRA),r_a,FDropDownArrowSize,badUp,AState.FontEx.Color)
|
|---|
| 535 | else
|
|---|
| 536 | RenderArrow(TBGRABitmap(ABGRA),r_a,FDropDownArrowSize,badDown,AState.FontEx.Color);
|
|---|
| 537 | end;
|
|---|
| 538 |
|
|---|
| 539 | // Click offset for text and glyph
|
|---|
| 540 | if AState=FStateClicked then
|
|---|
| 541 | begin
|
|---|
| 542 | Inc(r.Left,2);
|
|---|
| 543 | Inc(r.Top,2);
|
|---|
| 544 | end;
|
|---|
| 545 |
|
|---|
| 546 | if FTextApplyGlobalOpacity then
|
|---|
| 547 | begin
|
|---|
| 548 | { Drawing text }
|
|---|
| 549 | _RenderGlyph;
|
|---|
| 550 | RenderText(r,AState.FontEx,Self.Caption,TBGRABitmap(ABGRA));
|
|---|
| 551 |
|
|---|
| 552 | { Set global opacity }
|
|---|
| 553 | ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
|
|---|
| 554 | end
|
|---|
| 555 | else
|
|---|
| 556 | begin
|
|---|
| 557 | { Set global opacity }
|
|---|
| 558 | ABGRA.ApplyGlobalOpacity(FGlobalOpacity);
|
|---|
| 559 | { Drawing text }
|
|---|
| 560 | _RenderGlyph;
|
|---|
| 561 | RenderText(r,AState.FontEx,Self.Caption,TBGRABitmap(ABGRA));
|
|---|
| 562 | end;
|
|---|
| 563 |
|
|---|
| 564 | { Convert to gray if not enabled }
|
|---|
| 565 | if not Enabled then
|
|---|
| 566 | ConvertToGrayScale(ABGRA);
|
|---|
| 567 |
|
|---|
| 568 | if Assigned(FOnAfterRenderBCButton) then
|
|---|
| 569 | FOnAfterRenderBCButton(Self, ABGRA, AState, r);
|
|---|
| 570 |
|
|---|
| 571 | {$IFDEF DEBUG}
|
|---|
| 572 | FRenderCount += 1;
|
|---|
| 573 | {$ENDIF}
|
|---|
| 574 | end;
|
|---|
| 575 |
|
|---|
| 576 | procedure TCustomBCButton.RenderState(ABGRA: TBGRABitmapEx;
|
|---|
| 577 | AState: TBCButtonState; const ARect: TRect; ARounding: TBCRounding);
|
|---|
| 578 | begin
|
|---|
| 579 | RenderBackground(ARect, AState.FBackground, TBGRABitmap(ABGRA), ARounding);
|
|---|
| 580 | RenderBorder(ARect, AState.FBorder, TBGRABitmap(ABGRA), ARounding);
|
|---|
| 581 | end;
|
|---|
| 582 |
|
|---|
| 583 | procedure TCustomBCButton.OnChangeGlyph(Sender: TObject);
|
|---|
| 584 | begin
|
|---|
| 585 | RenderControl;
|
|---|
| 586 | UpdateSize;
|
|---|
| 587 | Invalidate;
|
|---|
| 588 | end;
|
|---|
| 589 |
|
|---|
| 590 | procedure TCustomBCButton.OnChangeState(Sender: TObject; AData: PtrInt);
|
|---|
| 591 | begin
|
|---|
| 592 | RenderControl;
|
|---|
| 593 | if TBCButtonPropertyData(AData)=pdUpdateSize then
|
|---|
| 594 | UpdateSize;
|
|---|
| 595 | Invalidate;
|
|---|
| 596 | end;
|
|---|
| 597 |
|
|---|
| 598 | procedure TCustomBCButton.SeTBCButtonStateClicked(const AValue: TBCButtonState);
|
|---|
| 599 | begin
|
|---|
| 600 | if FStateClicked = AValue then
|
|---|
| 601 | exit;
|
|---|
| 602 | FStateClicked.Assign(AValue);
|
|---|
| 603 |
|
|---|
| 604 | RenderControl;
|
|---|
| 605 | Invalidate;
|
|---|
| 606 | end;
|
|---|
| 607 |
|
|---|
| 608 | procedure TCustomBCButton.SeTBCButtonStateHover(const AValue: TBCButtonState);
|
|---|
| 609 | begin
|
|---|
| 610 | if FStateHover = AValue then
|
|---|
| 611 | exit;
|
|---|
| 612 | FStateHover.Assign(AValue);
|
|---|
| 613 |
|
|---|
| 614 | RenderControl;
|
|---|
| 615 | Invalidate;
|
|---|
| 616 | end;
|
|---|
| 617 |
|
|---|
| 618 | procedure TCustomBCButton.SeTBCButtonStateNormal(const AValue: TBCButtonState);
|
|---|
| 619 | begin
|
|---|
| 620 | if FStateNormal = AValue then
|
|---|
| 621 | exit;
|
|---|
| 622 | FStateNormal.Assign(AValue);
|
|---|
| 623 |
|
|---|
| 624 | RenderControl;
|
|---|
| 625 | Invalidate;
|
|---|
| 626 | end;
|
|---|
| 627 |
|
|---|
| 628 | procedure TCustomBCButton.SetDown(AValue: boolean);
|
|---|
| 629 | begin
|
|---|
| 630 | if FDown = AValue then
|
|---|
| 631 | exit;
|
|---|
| 632 | FDown := AValue;
|
|---|
| 633 | if FDown
|
|---|
| 634 | then FButtonState := msClicked
|
|---|
| 635 | else FButtonState := msNone;
|
|---|
| 636 | RenderControl;
|
|---|
| 637 | Invalidate;
|
|---|
| 638 | end;
|
|---|
| 639 |
|
|---|
| 640 | procedure TCustomBCButton.SetDropDownArrowSize(AValue: Integer);
|
|---|
| 641 | begin
|
|---|
| 642 | if FDropDownArrowSize = AValue then Exit;
|
|---|
| 643 | FDropDownArrowSize := AValue;
|
|---|
| 644 |
|
|---|
| 645 | RenderControl;
|
|---|
| 646 | Invalidate;
|
|---|
| 647 | end;
|
|---|
| 648 |
|
|---|
| 649 | procedure TCustomBCButton.SetDropDownWidth(AValue: Integer);
|
|---|
| 650 | begin
|
|---|
| 651 | if FDropDownWidth = AValue then Exit;
|
|---|
| 652 | FDropDownWidth := AValue;
|
|---|
| 653 |
|
|---|
| 654 | RenderControl;
|
|---|
| 655 | UpdateSize;
|
|---|
| 656 | Invalidate;
|
|---|
| 657 | end;
|
|---|
| 658 |
|
|---|
| 659 | procedure TCustomBCButton.SetFlipArrow(AValue: boolean);
|
|---|
| 660 | begin
|
|---|
| 661 | if FFlipArrow = AValue then
|
|---|
| 662 | Exit;
|
|---|
| 663 | FFlipArrow := AValue;
|
|---|
| 664 |
|
|---|
| 665 | RenderControl;
|
|---|
| 666 | Invalidate;
|
|---|
| 667 | end;
|
|---|
| 668 |
|
|---|
| 669 | procedure TCustomBCButton.SetGlyph(const AValue: TBitmap);
|
|---|
| 670 | begin
|
|---|
| 671 | if (FGlyph <> nil) and (FGlyph = AValue) then
|
|---|
| 672 | exit;
|
|---|
| 673 |
|
|---|
| 674 | FGlyph.Assign(AValue);
|
|---|
| 675 |
|
|---|
| 676 | RenderControl;
|
|---|
| 677 | UpdateSize;
|
|---|
| 678 | Invalidate;
|
|---|
| 679 | end;
|
|---|
| 680 |
|
|---|
| 681 | procedure TCustomBCButton.SetGlyphMargin(const AValue: integer);
|
|---|
| 682 | begin
|
|---|
| 683 | if FGlyphMargin = AValue then
|
|---|
| 684 | exit;
|
|---|
| 685 | FGlyphMargin := AValue;
|
|---|
| 686 |
|
|---|
| 687 | RenderControl;
|
|---|
| 688 | UpdateSize;
|
|---|
| 689 | Invalidate;
|
|---|
| 690 | end;
|
|---|
| 691 |
|
|---|
| 692 | procedure TCustomBCButton.SetRounding(AValue: TBCRounding);
|
|---|
| 693 | begin
|
|---|
| 694 | if FRounding = AValue then Exit;
|
|---|
| 695 | FRounding.Assign(AValue);
|
|---|
| 696 |
|
|---|
| 697 | RenderControl;
|
|---|
| 698 | Invalidate;
|
|---|
| 699 | end;
|
|---|
| 700 |
|
|---|
| 701 | procedure TCustomBCButton.SetRoundingDropDown(AValue: TBCRounding);
|
|---|
| 702 | begin
|
|---|
| 703 | if FRoundingDropDown = AValue then Exit;
|
|---|
| 704 | FRoundingDropDown.Assign(AValue);
|
|---|
| 705 |
|
|---|
| 706 | RenderControl;
|
|---|
| 707 | Invalidate;
|
|---|
| 708 | end;
|
|---|
| 709 |
|
|---|
| 710 | procedure TCustomBCButton.SetStaticButton(const AValue: boolean);
|
|---|
| 711 | begin
|
|---|
| 712 | if FStaticButton = AValue then
|
|---|
| 713 | exit;
|
|---|
| 714 | FStaticButton := AValue;
|
|---|
| 715 |
|
|---|
| 716 | RenderControl;
|
|---|
| 717 | Invalidate;
|
|---|
| 718 | end;
|
|---|
| 719 |
|
|---|
| 720 | procedure TCustomBCButton.SetStyle(const AValue: TBCButtonStyle);
|
|---|
| 721 | begin
|
|---|
| 722 | if FStyle = AValue then
|
|---|
| 723 | exit;
|
|---|
| 724 | FStyle := AValue;
|
|---|
| 725 |
|
|---|
| 726 | RenderControl;
|
|---|
| 727 | UpdateSize;
|
|---|
| 728 | Invalidate;
|
|---|
| 729 | end;
|
|---|
| 730 |
|
|---|
| 731 | procedure TCustomBCButton.UpdateSize;
|
|---|
| 732 | begin
|
|---|
| 733 | InvalidatePreferredSize;
|
|---|
| 734 | AdjustSize;
|
|---|
| 735 | end;
|
|---|
| 736 |
|
|---|
| 737 | procedure TCustomBCButton.CalculatePreferredSize(
|
|---|
| 738 | var PreferredWidth, PreferredHeight: integer; WithThemeSpace: boolean);
|
|---|
| 739 | var
|
|---|
| 740 | AWidth: integer;
|
|---|
| 741 | gh: integer = 0;
|
|---|
| 742 | gw: integer = 0;
|
|---|
| 743 | begin
|
|---|
| 744 | if (Parent = nil) or (not Parent.HandleAllocated) then
|
|---|
| 745 | Exit;
|
|---|
| 746 | if WidthIsAnchored then
|
|---|
| 747 | AWidth := Width
|
|---|
| 748 | else
|
|---|
| 749 | AWidth := 10000;
|
|---|
| 750 |
|
|---|
| 751 | CalculateTextSize(Caption, FStateNormal.FontEx, PreferredWidth, PreferredHeight);
|
|---|
| 752 |
|
|---|
| 753 | // Extra pixels for DropDown
|
|---|
| 754 | if Style = bbtDropDown then
|
|---|
| 755 | Inc(PreferredWidth, GetDropDownWidth);
|
|---|
| 756 |
|
|---|
| 757 | CalculateGlyphSize(gw, gh);
|
|---|
| 758 |
|
|---|
| 759 | if (FGlyph <> nil) and (not FGlyph.Empty) then
|
|---|
| 760 | begin
|
|---|
| 761 | if Caption = '' then
|
|---|
| 762 | begin
|
|---|
| 763 | Inc(PreferredWidth, gw{ - AutoSizeExtraY * 2});
|
|---|
| 764 | Inc(PreferredHeight, gh);
|
|---|
| 765 | end
|
|---|
| 766 | else
|
|---|
| 767 | begin
|
|---|
| 768 | Inc(PreferredWidth, gw + FGlyphMargin);
|
|---|
| 769 | if gh > PreferredHeight then
|
|---|
| 770 | PreferredHeight := gh;
|
|---|
| 771 | end;
|
|---|
| 772 | end;
|
|---|
| 773 |
|
|---|
| 774 | // Extra pixels for AutoSize
|
|---|
| 775 | Inc(PreferredWidth, AutoSizeExtraX);
|
|---|
| 776 | Inc(PreferredHeight, AutoSizeExtraY);
|
|---|
| 777 | end;
|
|---|
| 778 |
|
|---|
| 779 | class function TCustomBCButton.GetControlClassDefaultSize: TSize;
|
|---|
| 780 | begin
|
|---|
| 781 | Result.CX := 123;
|
|---|
| 782 | Result.CY := 33;
|
|---|
| 783 | end;
|
|---|
| 784 |
|
|---|
| 785 | procedure TCustomBCButton.Click;
|
|---|
| 786 | begin
|
|---|
| 787 | if (FActiveButt = bbtDropDown) and Assigned(FOnButtonClick) then
|
|---|
| 788 | begin
|
|---|
| 789 | FOnButtonClick(Self);
|
|---|
| 790 | Exit;
|
|---|
| 791 | end;
|
|---|
| 792 | inherited Click;
|
|---|
| 793 | end;
|
|---|
| 794 |
|
|---|
| 795 | procedure TCustomBCButton.MouseDown(Button: TMouseButton; Shift: TShiftState;
|
|---|
| 796 | X, Y: integer);
|
|---|
| 797 | begin
|
|---|
| 798 | inherited MouseDown(Button, Shift, X, Y);
|
|---|
| 799 | if csDesigning in ComponentState then
|
|---|
| 800 | exit;
|
|---|
| 801 |
|
|---|
| 802 | if (Button = mbLeft) and Enabled {and (not (FButtonState = msClicked)) }then
|
|---|
| 803 | begin
|
|---|
| 804 | case FActiveButt of
|
|---|
| 805 | bbtButton:
|
|---|
| 806 | if not (FButtonState=msClicked) then
|
|---|
| 807 | begin
|
|---|
| 808 | FButtonState := msClicked;
|
|---|
| 809 | FDownButtonState := msNone;
|
|---|
| 810 | Invalidate;
|
|---|
| 811 | end;
|
|---|
| 812 | bbtDropDown:
|
|---|
| 813 | if not (FDownButtonState=msClicked) then
|
|---|
| 814 | begin
|
|---|
| 815 | FButtonState := msNone;
|
|---|
| 816 | FDownButtonState := msClicked;
|
|---|
| 817 | Invalidate;
|
|---|
| 818 | end;
|
|---|
| 819 | end;
|
|---|
| 820 | // Old
|
|---|
| 821 | {FButtonState := msClicked;
|
|---|
| 822 | Invalidate;}
|
|---|
| 823 | end;
|
|---|
| 824 | end;
|
|---|
| 825 |
|
|---|
| 826 | procedure TCustomBCButton.MouseUp(Button: TMouseButton; Shift: TShiftState;
|
|---|
| 827 | X, Y: integer);
|
|---|
| 828 | var
|
|---|
| 829 | p: TPoint;
|
|---|
| 830 | begin
|
|---|
| 831 | inherited MouseUp(Button, Shift, X, Y);
|
|---|
| 832 | if csDesigning in ComponentState then
|
|---|
| 833 | exit;
|
|---|
| 834 |
|
|---|
| 835 | if (Button = mbLeft) and Enabled {and (FButtonState = msClicked)} then
|
|---|
| 836 | begin
|
|---|
| 837 | case FActiveButt of
|
|---|
| 838 | bbtButton:
|
|---|
| 839 | if FButtonState=msClicked then
|
|---|
| 840 | begin
|
|---|
| 841 | FButtonState := msHover;
|
|---|
| 842 | FDownButtonState := msNone;
|
|---|
| 843 | Invalidate;
|
|---|
| 844 | end;
|
|---|
| 845 | bbtDropDown:
|
|---|
| 846 | if FDownButtonState = msClicked then
|
|---|
| 847 | begin
|
|---|
| 848 | FDownButtonState := msHover;
|
|---|
| 849 | FButtonState := msNone;
|
|---|
| 850 | Invalidate;
|
|---|
| 851 | end;
|
|---|
| 852 | end;
|
|---|
| 853 | // Old
|
|---|
| 854 | {FButtonState := msHover;
|
|---|
| 855 | Invalidate;}
|
|---|
| 856 | end;
|
|---|
| 857 |
|
|---|
| 858 | if (FActiveButt = bbtDropDown) and (PopupMenu <> nil) and Enabled then
|
|---|
| 859 | begin
|
|---|
| 860 | if FFlipArrow then
|
|---|
| 861 | p := ClientToScreen(Point(Width - FDropDownWidth - (FStateNormal.FBorder.Width * 2),
|
|---|
| 862 | {PopupMenu.Height} -1))
|
|---|
| 863 | else
|
|---|
| 864 | p := ClientToScreen(Point(Width - FDropDownWidth - (FStateNormal.FBorder.Width * 2), Height + 1));
|
|---|
| 865 |
|
|---|
| 866 | PopupMenu.PopUp(p.x, p.y);
|
|---|
| 867 | //p := ClientToScreen(Point(X, Y));
|
|---|
| 868 | //PopupMenu.PopUp(p.x, p.y);
|
|---|
| 869 | end;
|
|---|
| 870 | end;
|
|---|
| 871 |
|
|---|
| 872 | procedure TCustomBCButton.MouseEnter;
|
|---|
| 873 | begin
|
|---|
| 874 | if csDesigning in ComponentState then
|
|---|
| 875 | exit;
|
|---|
| 876 | case FActiveButt of
|
|---|
| 877 | bbtButton:
|
|---|
| 878 | begin
|
|---|
| 879 | if FDown
|
|---|
| 880 | then FButtonState := msClicked
|
|---|
| 881 | else FButtonState := msHover;
|
|---|
| 882 | FDownButtonState := msNone;
|
|---|
| 883 | end;
|
|---|
| 884 | bbtDropDown:
|
|---|
| 885 | begin
|
|---|
| 886 | if FDown
|
|---|
| 887 | then FButtonState := msClicked
|
|---|
| 888 | else FButtonState := msNone;
|
|---|
| 889 | FDownButtonState := msHover;
|
|---|
| 890 | end;
|
|---|
| 891 | end;
|
|---|
| 892 | Invalidate;
|
|---|
| 893 | // Old
|
|---|
| 894 | {FButtonState := msHover;
|
|---|
| 895 | Invalidate;}
|
|---|
| 896 | inherited MouseEnter;
|
|---|
| 897 | end;
|
|---|
| 898 |
|
|---|
| 899 | procedure TCustomBCButton.MouseLeave;
|
|---|
| 900 | begin
|
|---|
| 901 | if csDesigning in ComponentState then
|
|---|
| 902 | exit;
|
|---|
| 903 | if FDown then
|
|---|
| 904 | begin
|
|---|
| 905 | FButtonState := msClicked;
|
|---|
| 906 | FActiveButt := bbtButton;
|
|---|
| 907 | end
|
|---|
| 908 | else
|
|---|
| 909 | FButtonState := msNone;
|
|---|
| 910 | FDownButtonState := msNone;
|
|---|
| 911 | Invalidate;
|
|---|
| 912 | inherited MouseLeave;
|
|---|
| 913 | end;
|
|---|
| 914 |
|
|---|
| 915 | procedure TCustomBCButton.MouseMove(Shift: TShiftState; X, Y: integer);
|
|---|
| 916 | begin
|
|---|
| 917 | inherited MouseMove(Shift, X, Y);
|
|---|
| 918 |
|
|---|
| 919 | if FStyle=bbtButton then
|
|---|
| 920 | FActiveButt := bbtButton
|
|---|
| 921 | else
|
|---|
| 922 | begin
|
|---|
| 923 | // Calling invalidate only when active button changed. Otherwise, we leave
|
|---|
| 924 | // this for LCL. This reduce paint call
|
|---|
| 925 | if (FActiveButt=bbtButton) and (x>GetButtonRect.Right) then
|
|---|
| 926 | begin
|
|---|
| 927 | FActiveButt := bbtDropDown;
|
|---|
| 928 | FDownButtonState := msHover;
|
|---|
| 929 | if FDown
|
|---|
| 930 | then FButtonState := msClicked
|
|---|
| 931 | else FButtonState := msNone;
|
|---|
| 932 | Invalidate;
|
|---|
| 933 | end else
|
|---|
| 934 | if (FActiveButt=bbtDropDown) and (x<=GetButtonRect.Right) then
|
|---|
| 935 | begin
|
|---|
| 936 | FActiveButt := bbtButton;
|
|---|
| 937 | if FDown
|
|---|
| 938 | then FButtonState := msClicked
|
|---|
| 939 | else FButtonState := msHover;
|
|---|
| 940 | FDownButtonState := msNone;
|
|---|
| 941 | Invalidate;
|
|---|
| 942 | end;
|
|---|
| 943 | end;
|
|---|
| 944 | end;
|
|---|
| 945 |
|
|---|
| 946 | procedure TCustomBCButton.SetEnabled(Value: boolean);
|
|---|
| 947 | begin
|
|---|
| 948 | inherited SetEnabled(Value);
|
|---|
| 949 |
|
|---|
| 950 | RenderControl;
|
|---|
| 951 | Invalidate;
|
|---|
| 952 | end;
|
|---|
| 953 |
|
|---|
| 954 | procedure TCustomBCButton.TextChanged;
|
|---|
| 955 | begin
|
|---|
| 956 | inherited TextChanged;
|
|---|
| 957 | RenderControl;
|
|---|
| 958 | UpdateSize;
|
|---|
| 959 | Invalidate;
|
|---|
| 960 | end;
|
|---|
| 961 |
|
|---|
| 962 | procedure TCustomBCButton.UpdateControl;
|
|---|
| 963 | begin
|
|---|
| 964 | RenderControl;
|
|---|
| 965 | inherited UpdateControl; // indalidate
|
|---|
| 966 | end;
|
|---|
| 967 |
|
|---|
| 968 | {$IFDEF DEBUG}
|
|---|
| 969 | function TCustomBCButton.GetDebugText: String;
|
|---|
| 970 | begin
|
|---|
| 971 | Result := 'R: '+IntToStr(FRenderCount);
|
|---|
| 972 | end;
|
|---|
| 973 | {$ENDIF}
|
|---|
| 974 |
|
|---|
| 975 | procedure TCustomBCButton.DrawControl;
|
|---|
| 976 | var
|
|---|
| 977 | bgra: TBGRABitmapEx;
|
|---|
| 978 | begin
|
|---|
| 979 |
|
|---|
| 980 | // If style is without dropdown button or state of each button
|
|---|
| 981 | // is the same (possible only for msNone) or static button then
|
|---|
| 982 | // we can draw whole BGRABitmap
|
|---|
| 983 | if (FStyle=bbtButton) or (FButtonState=FDownButtonState) or FStaticButton
|
|---|
| 984 | then
|
|---|
| 985 | begin
|
|---|
| 986 | // Main button
|
|---|
| 987 | if FStaticButton then
|
|---|
| 988 | bgra := FBGRANormal
|
|---|
| 989 | else
|
|---|
| 990 | if FDown then
|
|---|
| 991 | bgra := FBGRAClick
|
|---|
| 992 | else
|
|---|
| 993 | case FButtonState of
|
|---|
| 994 | msNone: bgra := FBGRANormal;
|
|---|
| 995 | msHover: bgra := FBGRAHover;
|
|---|
| 996 | msClicked: bgra := FBGRAClick;
|
|---|
| 997 | end;
|
|---|
| 998 | if bgra.NeedRender then
|
|---|
| 999 | Render(bgra,TBCButtonState(bgra.CustomData));
|
|---|
| 1000 | bgra.Draw(Self.Canvas, 0, 0, False);
|
|---|
| 1001 | end
|
|---|
| 1002 | // Otherwise we must draw part of state for each button
|
|---|
| 1003 | else
|
|---|
| 1004 | begin
|
|---|
| 1005 | // The active button must be draw as last because right edge of button and
|
|---|
| 1006 | // left edge of dropdown are overlapping each other, so we must draw edge
|
|---|
| 1007 | // for current state of active button
|
|---|
| 1008 | case FActiveButt of
|
|---|
| 1009 | bbtButton:
|
|---|
| 1010 | begin
|
|---|
| 1011 | // Drop down button
|
|---|
| 1012 | case FDownButtonState of
|
|---|
| 1013 | msNone: bgra := FBGRANormal;
|
|---|
| 1014 | msHover: bgra := FBGRAHover;
|
|---|
| 1015 | msClicked: bgra := FBGRAClick;
|
|---|
| 1016 | end;
|
|---|
| 1017 | if bgra.NeedRender then
|
|---|
| 1018 | Render(bgra,TBCButtonState(bgra.CustomData));
|
|---|
| 1019 | bgra.DrawPart(GetDropDownRect,Self.Canvas,GetDropDownRect.Left,0,False);
|
|---|
| 1020 | // Main button
|
|---|
| 1021 | if FDown then
|
|---|
| 1022 | bgra := FBGRAClick
|
|---|
| 1023 | else
|
|---|
| 1024 | case FButtonState of
|
|---|
| 1025 | msNone: bgra := FBGRANormal;
|
|---|
| 1026 | msHover: bgra := FBGRAHover;
|
|---|
| 1027 | msClicked: bgra := FBGRAClick;
|
|---|
| 1028 | end;
|
|---|
| 1029 | if bgra.NeedRender then
|
|---|
| 1030 | Render(bgra,TBCButtonState(bgra.CustomData));
|
|---|
| 1031 | bgra.DrawPart(GetButtonRect, Self.Canvas, 0, 0, False);
|
|---|
| 1032 | end;
|
|---|
| 1033 | bbtDropDown:
|
|---|
| 1034 | begin
|
|---|
| 1035 | // Main button
|
|---|
| 1036 | if FDown then
|
|---|
| 1037 | bgra := FBGRAClick
|
|---|
| 1038 | else
|
|---|
| 1039 | case FButtonState of
|
|---|
| 1040 | msNone: bgra := FBGRANormal;
|
|---|
| 1041 | msHover: bgra := FBGRAHover;
|
|---|
| 1042 | msClicked: bgra := FBGRAClick;
|
|---|
| 1043 | end;
|
|---|
| 1044 | if bgra.NeedRender then
|
|---|
| 1045 | Render(bgra,TBCButtonState(bgra.CustomData));
|
|---|
| 1046 | bgra.DrawPart(GetButtonRect, Self.Canvas, 0, 0, False);
|
|---|
| 1047 | // Drop down button
|
|---|
| 1048 | case FDownButtonState of
|
|---|
| 1049 | msNone: bgra := FBGRANormal;
|
|---|
| 1050 | msHover: bgra := FBGRAHover;
|
|---|
| 1051 | msClicked: bgra := FBGRAClick;
|
|---|
| 1052 | end;
|
|---|
| 1053 | if bgra.NeedRender then
|
|---|
| 1054 | Render(bgra,TBCButtonState(bgra.CustomData));
|
|---|
| 1055 | bgra.DrawPart(GetDropDownRect,Self.Canvas,GetDropDownRect.Left,0,False);
|
|---|
| 1056 | end;
|
|---|
| 1057 | end;
|
|---|
| 1058 | end;
|
|---|
| 1059 | end;
|
|---|
| 1060 |
|
|---|
| 1061 | procedure TCustomBCButton.RenderControl;
|
|---|
| 1062 | begin
|
|---|
| 1063 | inherited RenderControl;
|
|---|
| 1064 | RenderAll;
|
|---|
| 1065 | end;
|
|---|
| 1066 |
|
|---|
| 1067 | procedure TCustomBCButton.SetGlobalOpacity(const AValue: byte);
|
|---|
| 1068 | begin
|
|---|
| 1069 | if FGlobalOpacity = AValue then
|
|---|
| 1070 | exit;
|
|---|
| 1071 | FGlobalOpacity := AValue;
|
|---|
| 1072 |
|
|---|
| 1073 | RenderControl;
|
|---|
| 1074 | Invalidate;
|
|---|
| 1075 | end;
|
|---|
| 1076 |
|
|---|
| 1077 | procedure TCustomBCButton.SetTextApplyGlobalOpacity(const AValue: boolean);
|
|---|
| 1078 | begin
|
|---|
| 1079 | if FTextApplyGlobalOpacity = AValue then
|
|---|
| 1080 | exit;
|
|---|
| 1081 | FTextApplyGlobalOpacity := AValue;
|
|---|
| 1082 |
|
|---|
| 1083 | RenderControl;
|
|---|
| 1084 | Invalidate;
|
|---|
| 1085 | end;
|
|---|
| 1086 |
|
|---|
| 1087 | constructor TCustomBCButton.Create(AOwner: TComponent);
|
|---|
| 1088 | begin
|
|---|
| 1089 | inherited Create(AOwner);
|
|---|
| 1090 | {$IFDEF DEBUG}
|
|---|
| 1091 | FRenderCount := 0;
|
|---|
| 1092 | {$ENDIF}
|
|---|
| 1093 | DisableAutoSizing;
|
|---|
| 1094 | Include(FControlState, csCreating);
|
|---|
| 1095 | //{$IFDEF WINDOWS}
|
|---|
| 1096 | // default sizes under different dpi settings
|
|---|
| 1097 | //SetSizeVariables(ScaleX(8,96), ScaleX(16,96), ScaleY(8,96), ScaleX(24,96));
|
|---|
| 1098 | //{$ELSE}
|
|---|
| 1099 | // default sizes
|
|---|
| 1100 | SetSizeVariables(16, 8, 8, 24);
|
|---|
| 1101 | //{$ENDIF}
|
|---|
| 1102 | BeginUpdate;
|
|---|
| 1103 | try
|
|---|
| 1104 | with GetControlClassDefaultSize do
|
|---|
| 1105 | SetInitialBounds(0, 0, CX, CY);
|
|---|
| 1106 | ControlStyle := ControlStyle + [csAcceptsControls];
|
|---|
| 1107 | FBGRANormal := TBGRABitmapEx.Create(Width, Height, BGRAPixelTransparent);
|
|---|
| 1108 | FBGRAHover := TBGRABitmapEx.Create(Width, Height, BGRAPixelTransparent);
|
|---|
| 1109 | FBGRAClick := TBGRABitmapEx.Create(Width, Height, BGRAPixelTransparent);
|
|---|
| 1110 |
|
|---|
| 1111 | ParentColor := False;
|
|---|
| 1112 | Color := clNone;
|
|---|
| 1113 |
|
|---|
| 1114 | FStateNormal := TBCButtonState.Create(Self);
|
|---|
| 1115 | FStateHover := TBCButtonState.Create(Self);
|
|---|
| 1116 | FStateClicked := TBCButtonState.Create(Self);
|
|---|
| 1117 | FStateNormal.OnChange := @OnChangeState;
|
|---|
| 1118 | FStateHover.OnChange := @OnChangeState;
|
|---|
| 1119 | FStateClicked.OnChange := @OnChangeState;
|
|---|
| 1120 |
|
|---|
| 1121 | FRounding := TBCRounding.Create(Self);
|
|---|
| 1122 | FRounding.OnChange := @OnChangeState;
|
|---|
| 1123 |
|
|---|
| 1124 | FRoundingDropDown := TBCRounding.Create(Self);
|
|---|
| 1125 | FRoundingDropDown.OnChange := @OnChangeState;
|
|---|
| 1126 |
|
|---|
| 1127 | { Connecting bitmaps with states property to easy call and access }
|
|---|
| 1128 | FBGRANormal.CustomData := PtrInt(FStateNormal);
|
|---|
| 1129 | FBGRAHover.CustomData := PtrInt(FStateHover);
|
|---|
| 1130 | FBGRAClick.CustomData := PtrInt(FStateClicked);
|
|---|
| 1131 |
|
|---|
| 1132 | FButtonState := msNone;
|
|---|
| 1133 | FDownButtonState := msNone;
|
|---|
| 1134 | FFlipArrow := False;
|
|---|
| 1135 | FGlyph := TBitmap.Create;
|
|---|
| 1136 | FGlyph.OnChange := @OnChangeGlyph;
|
|---|
| 1137 | FGlyphMargin := 5;
|
|---|
| 1138 | FStyle := bbtButton;
|
|---|
| 1139 | FStaticButton := False;
|
|---|
| 1140 | FActiveButt := bbtButton;
|
|---|
| 1141 | FGlobalOpacity := 255;
|
|---|
| 1142 | FTextApplyGlobalOpacity := False;
|
|---|
| 1143 | //FStates := [];
|
|---|
| 1144 | FDown := False;
|
|---|
| 1145 |
|
|---|
| 1146 | { Default style }
|
|---|
| 1147 | AssignDefaultStyle;
|
|---|
| 1148 | finally
|
|---|
| 1149 | Exclude(FControlState, csCreating);
|
|---|
| 1150 | EnableAutoSizing;
|
|---|
| 1151 | EndUpdate;
|
|---|
| 1152 | end;
|
|---|
| 1153 | end;
|
|---|
| 1154 |
|
|---|
| 1155 | destructor TCustomBCButton.Destroy;
|
|---|
| 1156 | begin
|
|---|
| 1157 | FStateNormal.Free;
|
|---|
| 1158 | FStateHover.Free;
|
|---|
| 1159 | FStateClicked.Free;
|
|---|
| 1160 | FBGRANormal.Free;
|
|---|
| 1161 | FBGRAHover.Free;
|
|---|
| 1162 | FBGRAClick.Free;
|
|---|
| 1163 | FreeThenNil(FGlyph);
|
|---|
| 1164 | FRounding.Free;
|
|---|
| 1165 | FRoundingDropDown.Free;
|
|---|
| 1166 | inherited Destroy;
|
|---|
| 1167 | end;
|
|---|
| 1168 |
|
|---|
| 1169 | procedure TCustomBCButton.Assign(Source: TPersistent);
|
|---|
| 1170 | begin
|
|---|
| 1171 | if Source is TCustomBCButton then
|
|---|
| 1172 | begin
|
|---|
| 1173 | Glyph := TCustomBCButton(Source).Glyph;
|
|---|
| 1174 | FGlyphMargin := TCustomBCButton(Source).FGlyphMargin;
|
|---|
| 1175 | FStyle := TCustomBCButton(Source).FStyle;
|
|---|
| 1176 | FFlipArrow := TCustomBCButton(Source).FFlipArrow;
|
|---|
| 1177 | FStaticButton := TCustomBCButton(Source).FStaticButton;
|
|---|
| 1178 | FGlobalOpacity := TCustomBCButton(Source).FGlobalOpacity;
|
|---|
| 1179 | FTextApplyGlobalOpacity := TCustomBCButton(Source).FTextApplyGlobalOpacity;
|
|---|
| 1180 | FStateNormal.Assign(TCustomBCButton(Source).FStateNormal);
|
|---|
| 1181 | FStateHover.Assign(TCustomBCButton(Source).FStateHover);
|
|---|
| 1182 | FStateClicked.Assign(TCustomBCButton(Source).FStateClicked);
|
|---|
| 1183 | FDropDownArrowSize := TCustomBCButton(Source).FDropDownArrowSize;
|
|---|
| 1184 | FDropDownWidth := TCustomBCButton(Source).FDropDownWidth;
|
|---|
| 1185 | AutoSizeExtraX := TCustomBCButton(Source).AutoSizeExtraX;
|
|---|
| 1186 | AutoSizeExtraY := TCustomBCButton(Source).AutoSizeExtraY;
|
|---|
| 1187 | FDown := TCustomBCButton(Source).FDown;
|
|---|
| 1188 | FRounding.Assign(TCustomBCButton(Source).FRounding);
|
|---|
| 1189 | FRoundingDropDown.Assign(TCustomBCButton(Source).FRoundingDropDown);
|
|---|
| 1190 |
|
|---|
| 1191 | RenderControl;
|
|---|
| 1192 | Invalidate;
|
|---|
| 1193 | UpdateSize;
|
|---|
| 1194 | end
|
|---|
| 1195 | else
|
|---|
| 1196 | inherited Assign(Source);
|
|---|
| 1197 | end;
|
|---|
| 1198 |
|
|---|
| 1199 | procedure TCustomBCButton.SetSizeVariables(newDropDownWidth, newDropDownArrowSize,
|
|---|
| 1200 | newAutoSizeExtraVertical, newAutoSizeExtraHorizontal: integer);
|
|---|
| 1201 | begin
|
|---|
| 1202 | FDropDownArrowSize := newDropDownArrowSize;
|
|---|
| 1203 | FDropDownWidth := newDropDownWidth;
|
|---|
| 1204 | AutoSizeExtraY := newAutoSizeExtraVertical;
|
|---|
| 1205 | AutoSizeExtraX := newAutoSizeExtraHorizontal;
|
|---|
| 1206 |
|
|---|
| 1207 | if csCreating in ControlState then
|
|---|
| 1208 | Exit;
|
|---|
| 1209 |
|
|---|
| 1210 | RenderControl;
|
|---|
| 1211 | UpdateSize;
|
|---|
| 1212 | Invalidate;
|
|---|
| 1213 | end;
|
|---|
| 1214 |
|
|---|
| 1215 | function TCustomBCButton.GetStyleExtension: String;
|
|---|
| 1216 | begin
|
|---|
| 1217 | Result := 'bcbtn';
|
|---|
| 1218 | end;
|
|---|
| 1219 |
|
|---|
| 1220 | end.
|
|---|