How to access nested style control

991 views Asked by At

I have custom styled FireMonkey control. Its style contains several levels of nested controls.

I need to access those controls and change some style properties at run-time. To do that I am using FindStyleResource<T> method.

I have no problem in retrieving first level of controls inside style. But accessing controls on second level with FindStyleResource fails if control parent is descendant of TStyledControl.

Question is how to access those nested style controls regardless of their parent type?

Style:

object TStyleContainer
  object TLayout
    StyleName = 'MyHeader'
    Align = Center
    Size.Width = 100.000000000000000000
    Size.Height = 50.000000000000000000
    Size.PlatformDefault = False
    Visible = False
    TabOrder = 0
    object TLabel
      StyleName = 'title'
      Align = Client
      StyledSettings = [Style]
      Size.Width = 36.000000000000000000
      Size.Height = 50.000000000000000000
      Size.PlatformDefault = False
      TextSettings.HorzAlign = Center
      Text = 'Title'
    end
    object TLayout
      StyleName = 'green'
      Align = MostLeft
      Size.Width = 32.000000000000000000
      Size.Height = 50.000000000000000000
      Size.PlatformDefault = False
      object TPath
        StyleName = 'greenpath'
        Align = Fit
        Data.Path = {
          07000000000000000000404100000041010000000000C0400000604101000000
          B81EED405C8F76410100000000004041AE472D410100000052B884415C8F7641
          010000000000904100006041030000000000404100000041}
        Fill.Color = claGreen
        HitTest = False
        Size.Width = 32.000000000000000000
        Size.Height = 50.000000000000000000
        Size.PlatformDefault = False
        Stroke.Kind = None
        WrapMode = Fit
      end
    end
    object TSpeedButton
      StyleName = 'red'
      Align = MostRight
      Position.X = 68.000000000000000000
      Size.Width = 32.000000000000000000
      Size.Height = 50.000000000000000000
      Size.PlatformDefault = False
      object TPath
        StyleName = 'redpath'
        Align = Fit
        Data.Path = {
          07000000000000000000404100000041010000000000C0400000604101000000
          B81EED405C8F76410100000000004041AE472D410100000052B884415C8F7641
          010000000000904100006041030000000000404100000041}
        Fill.Color = claRed
        HitTest = False
        Size.Width = 32.000000000000000000
        Size.Height = 32.571426391601560000
        Size.PlatformDefault = False
        Stroke.Kind = None
        WrapMode = Fit
      end
    end
  end
end

Control:

type
  TMyHeader = class(TStyledControl)
  protected
    procedure ApplyStyle; override;
    function GetDefaultStyleLookupName: string; override;
   end;

procedure TMyHeader.ApplyStyle;
var
  LGreen: TLayout;
  LGreenPath: TPath;
  LRed: TSpeedButton;
  LRedPath: TPath;
begin
  inherited;
  if FindStyleResource<TLayout>('green', LGreen) then
    begin
      // following call will find greenpath control 
      if FindStyleResource<TPath>('greenpath', LGreenPath) then
        LGreenPath.Fill.Color := TAlphaColorRec.Blue;
    end;

  if FindStyleResource<TSpeedButton>('red', LRed) then
    begin 
      // following call will fail to find find redpath control  
      if FindStyleResource<TPath>('redpath', LRedPath) then
        LRedPath.Fill.Color := TAlphaColorRec.Blue;

      // this variant also fails
      if LRed.FindStyleResource<TPath>('redpath', LRedPath) then
        LRedPath.Fill.Color := TAlphaColorRec.Blue;
    end;
end;

function TMyHeader.GetDefaultStyleLookupName: string;
begin
  Result := 'MyHeader';
end;

Original style:

enter image description here

Changed style (only green arrow color was successfully changed)

enter image description here

In ApplyStyle method I can access greenpath from the style and change its color to blue. Hoewever, I cannot get redpath using FindStyleResource method.

1

There are 1 answers

2
John Kouraklis On

The standard way to access style elements is via TFMXObject and iterate the children style objects.

Try this:

procedure TMyHeader.ApplyStyle;
var
  objFMX,
  inObjFMX: TFMXObject;
  LRed: TSpeedButton;
  LRedPath: TPath;
begin
  inherited;
  objFMX:=FindStyleResource('red');
  if assigned(objFMX) and (objFMX is TSpeedButton) then
  begin
    LRed:=objFMX as TSpeedButton;
    inObjFMX:=LRed.FindStyleResource('redpath');
    if assigned(inObjFMX) and (inObjFMX is TPath) then
    begin
      LRedPath:=inObjFMX as TPath;
     LRedPath.Fill.Color := TAlphaColorRec.Blue;
   end;
  end
end;

Updated Code: The FindStyleResource does not work in the above code. A different approach is followed below.

procedure TMyHeader.ApplyStyle;
var
  objFMX,
  inObjFMX: TFMXObject;
  LRedPath: TPath;
begin
  inherited;
  objFMX:=FindStyleResource('red');
  if assigned(objFMX) and (objFMX is TSpeedButton) then
  begin
    for inObjFMX in objFMX.Children do
    begin
      if inObjFMX is TPath then
      begin
        LRedPath:=inObjFMX as TPath;
        LRedPath.Fill.Color:=TAlphaColorRec.Blue;
        Break;
      end;
    end;
  end;
end;

That works on 10.2