Skip to content

HowtoBuildYourCustomStyle

Carlo Barazzetta edited this page May 16, 2024 · 9 revisions

How to build your Custom Style

Available Style families

The structure of all StyledComponents is based on a “collection” of predefined styles (families).

By default these options are available in the StyleFamily property and can be:

Classic, Bootstrap, Angular-Light, Angular-Dark, Basic-Colors and SVG-Colors

To use these styles, simply open the "Component Editor", selecting the "StyleFamily" page, within which there are the other 2 levels: StyleAppearance and StyleClass, represented by a "groupbox" and the various buttons that embed the specific class.

As you can see in this example image, the “Angular-Light” family includes four button formats (Flat, Raised, Stroked, Basic), and seven classes are available (Basic, DeepPurple, Amber, Indigo, Pink, Warn, Link).

Component_Editor

Button states and how to customize a style

A button has five different states: Normal, Pressed, Selected, Hot, Disabled (Selected has no effect on the "Graphics" buttons because they have no "focus").

When you select a style for a button (Family/Class/Appearance) all its attributes are assigned to five complex properties, of type “TStyledButtonAttributes” such as:

ButtonStyleNormal, ButtonStylePressed, ButtonStyleSelected, ButtonStyleHot, ButtonStyleDisabled.

Each of these properties contains all the graphic attributes used for drawing the button in the specific state, such as:

DrawType, BorderWidth, BorderDrawStyle, ButtonDrawStyle, BorderColor, FontColor, FontStyle, ButtonColor, Radius, RoundedCorners.

This structure allows maximum flexibility. For example, it is possible to decide that the Font becomes Bold when the button is pressed or selected, or that the color becomes more vivid when the button is selected, or the border becomes larger when the button is pressed... and so on.

It is even possible to change the "shape" of the button, based on the state, by operating on StyleDrawType and StyleRadius.

When you change one of these attributes the UseCustomAttributes property becomes “True”: changing it to “False” resets the attributes using those defined by Family/Class/Appearance.

How to create your own “Family” of styles

To write your own StyledFamily of "Custom" styles, an example unit is available from which to start, in order to have a ready-made guideline:

{InstallDir}\source\Vcl.TemplateButtonStyles.pas

This unit contains an example of a family of Semaphoric button styles (StyleFamily=Semaphore) which can take two shapes (Normal and Outline) and four classes (SemGreen, SemYellow, SemRed, SemOff).

First you need to give your style family a name (StyleFamily) and establish how many "categories" to define (StyleAppearance) and how many classes (StyleClasses). It is useful, as in the example unit, to define constants...

  //Name of Family
  BTN_FAMILY = 'Semaphore';

  //Name of Classes
  BTN_GREEN = 'SemGreen';
  BTN_YELLOW = 'SemYellow';
  BTN_RED = 'SemRed';
  BTN_OFF = 'SemOff';

  //Name of Appearance
  BTN_NORMAL = 'Normal';
  BTN_OUTLINE = 'Outline';

...in such a way as to allow the developer to create the buttons at "Run-Time" by calling the CreateStyled constructor which requires passing the three values, for example:

LMyButton := TStyledButton.CreateStyled(Self, BTN_FAMILY, BTN_GREEN, BTN_NORMAL);

These constants must then be initialized by creating global unit variables in the implementation section, generally ButtonClasses and ButtonAppearances are always used:

implementation
var
  ButtonClasses: TButtonClasses;
  ButtonAppearances: TButtonAppearances;

and initialized appropriately in the Initialization section of the unit:

initialization
  SetLength(ButtonClasses, 4);
  ButtonClasses[0] := BTN_GREEN;
  ButtonClasses[1] := BTN_YELLOW;
  ButtonClasses[2] := BTN_RED;
  ButtonClasses[3] := BTN_OFF;
  SetLength(ButtonAppearances, 2);
  ButtonAppearances[0] := BTN_NORMAL;
  ButtonAppearances[1] := BTN_OUTLINE;
  RegisterButtonFamily(TSemaphoreButtonStyles.Create);

Then it is necessary to define a class that derives from TInterfacedObject and which implements an IStyledButtonAttributes interface...

  TSemaphoreButtonStyles = class(TInterfacedObject, IStyledButtonAttributes)
  private
    procedure UpdateAttributes(
      const AFamily:  TStyledButtonFamily;
      const AClass: TStyledButtonClass;
      const AAppearance: TStyledButtonAppearance;
      var ANormalStyle, APressedStyle, ASelectedStyle,
      AHotStyle, ADisabledStyle: TStyledButtonAttributes);
    function ButtonFamilyName: string;
    function GetButtonClasses: TButtonClasses;
    function GetButtonAppearances: TButtonAppearances;
    procedure GetStyleByModalResult(
      const AModalResult: System.UITypes.TModalResult;
      var AStyleClass: TStyledButtonClass;
      var AStyleAppearance: TStyledButtonAppearance);
  end;

...which includes these methods:

procedure UpdateAttributes
    function ButtonFamilyName
    function GetButtonClasses
    function GetButtonAppearances
    procedure GetStyleByModalResult

Clone this wiki locally