Explorar o código

TFresnelLCLControl: automatically trigger layout and rendering

mattias %!s(int64=2) %!d(string=hai) anos
pai
achega
4b568421e0

+ 0 - 1
demo/DivAndSpan/FresnelDivAndSpan1.lpi

@@ -74,7 +74,6 @@
       <OtherDefines Count="1">
         <Define0 Value="VerboseFresnelLayouter"/>
       </OtherDefines>
-      <CompilerPath Value="/usr/local/lib/fpc/3.3.1/ppcx64"/>
     </Other>
   </CompilerOptions>
   <Debugging>

+ 0 - 4
demo/DivAndSpan/mainunit.pas

@@ -86,10 +86,6 @@ begin
     Parent:=Body1;
     Style:='border-color: black; height:50px; position: absolute; left: 30px; top: 100px; width: 50px; height: 60px;';
   end;
-
-  ViewPort.ApplyCSS;
-  Layouter.WriteLayoutTree;
-  Layouter.Apply(ViewPort);
 end;
 
 end.

+ 8 - 4
design/fresneldsgn.lpk

@@ -1,19 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
   <Package Version="5">
-    <Name Value="fresneldsgn"/>
-    <Type Value="RunAndDesignTime"/>
+    <Name Value="FresnelDsgn"/>
+    <Type Value="DesignTime"/>
+    <Author Value="Mattias Gaertner"/>
     <CompilerOptions>
       <Version Value="11"/>
       <SearchPaths>
-        <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)/"/>
+        <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
       </SearchPaths>
     </CompilerOptions>
+    <Description Value="Lazarus IDE addon for Fresnel forms."/>
+    <License Value="Modied LGPL-2"/>
+    <Version Minor="2"/>
     <Files>
       <Item>
         <Filename Value="fresnelregister.pas"/>
         <HasRegisterProc Value="True"/>
-        <UnitName Value="fresnelregister"/>
+        <UnitName Value="FresnelRegister"/>
       </Item>
     </Files>
     <RequiredPkgs>

+ 22 - 0
design/fresneldsgn.pas

@@ -0,0 +1,22 @@
+{ This file was automatically created by Lazarus. Do not edit!
+  This source is only used to compile and install the package.
+ }
+
+unit FresnelDsgn;
+
+{$warn 5023 off : no warning about unused units}
+interface
+
+uses
+  FresnelRegister, LazarusPackageIntf;
+
+implementation
+
+procedure Register;
+begin
+  RegisterUnit('FresnelRegister', @FresnelRegister.Register);
+end;
+
+initialization
+  RegisterPackage('FresnelDsgn', @Register);
+end.

+ 51 - 17
design/fresnelregister.pas

@@ -16,7 +16,7 @@ interface
 
 uses
   LCLProc, LCLType, Classes, SysUtils, FormEditingIntf, LCLIntf, Graphics,
-  ProjectIntf, FresnelDOM, FresnelLCLControls;
+  Controls, ProjectIntf, FresnelDOM, FresnelControls, FresnelLCLControls;
 
 type
 
@@ -33,21 +33,24 @@ type
     class function CreateMediator(TheOwner, aForm: TComponent): TDesignerMediator;
       override;
     class function FormClass: TComponentClass; override;
+    constructor Create(AOwner: TComponent); override;
+    destructor Destroy; override;
     procedure GetBounds(AComponent: TComponent; out CurBounds: TRect); override;
     procedure SetBounds(AComponent: TComponent; NewBounds: TRect); override;
     procedure GetClientArea(AComponent: TComponent; out
             CurClientArea: TRect; out ScrollOffset: TPoint); override;
+    function GetComponentOriginOnForm(AComponent: TComponent): TPoint; override;
     procedure Paint; override;
     function ComponentIsIcon(AComponent: TComponent): boolean; override;
+    function ComponentIsVisible(AComponent: TComponent): Boolean; override;
+    function ComponentAtPos(p: TPoint; MinClass: TComponentClass;
+      Flags: TDMCompAtPosFlags): TComponent; override;
     function ParentAcceptsChild(Parent: TComponent;
                 Child: TComponentClass): boolean; override;
   public
-    // needed by TFresnelElement
-    constructor Create(AOwner: TComponent); override;
-    destructor Destroy; override;
+    // needed by Renderer
     procedure InvalidateRect(Sender: TObject; ARect: TRect; Erase: boolean);
     property DsgnForm: TFresnelForm read FDsgnForm;
-  public
   end;
 
   { TFileDescPascalUnitWithFresnelForm }
@@ -67,7 +70,7 @@ implementation
 procedure Register;
 begin
   FormEditingHook.RegisterDesignerMediator(TFresnelFormMediator);
-  RegisterComponents('Fresnel',[TFresnelDiv,TFresnelSpan,TFresnelLabel]);
+  RegisterComponents('Fresnel',[TFresnelDiv,TFresnelSpan,TFresnelLabel,TFresnelBody]);
   RegisterProjectFileDescriptor(TFileDescPascalUnitWithFresnelForm.Create,
                                 FileDescGroupName);
 end;
@@ -96,8 +99,7 @@ begin
   Result:=inherited CreateMediator(TheOwner,aForm);
   Mediator:=TFresnelFormMediator(Result);
   Mediator.FDsgnForm:=aForm as TFresnelForm;
-  Mediator.FDsgnForm.FreeNotification(Mediator);
-  Mediator.FDsgnForm.Designer:=Mediator;
+  Mediator.FreeNotification(aForm);
 end;
 
 class function TFresnelFormMediator.FormClass: TComponentClass;
@@ -132,6 +134,24 @@ begin
   inherited GetClientArea(AComponent, CurClientArea, ScrollOffset);
 end;
 
+function TFresnelFormMediator.GetComponentOriginOnForm(AComponent: TComponent
+  ): TPoint;
+var
+  El: TFresnelElement;
+  BorderBox: TFresnelRect;
+begin
+  if AComponent is TFresnelElement then
+  begin
+    El:=TFresnelElement(AComponent);
+    if not El.Rendered then
+      exit(Point(0,0));
+    BorderBox:=El.RenderedBorderBox;
+    Result.X:=round(BorderBox.Left);
+    Result.Y:=round(BorderBox.Top);
+  end else
+    Result:=inherited GetComponentOriginOnForm(AComponent);
+end;
+
 procedure TFresnelFormMediator.Paint;
 begin
   inherited Paint;
@@ -145,20 +165,34 @@ begin
     Result:=inherited ComponentIsIcon(AComponent);
 end;
 
+function TFresnelFormMediator.ComponentIsVisible(AComponent: TComponent
+  ): Boolean;
+begin
+  if AComponent is TFresnelElement then
+    Result:=TFresnelElement(AComponent).Rendered
+  else
+    Result:=true;
+end;
+
+function TFresnelFormMediator.ComponentAtPos(p: TPoint;
+  MinClass: TComponentClass; Flags: TDMCompAtPosFlags): TComponent;
+begin
+  Result:=DsgnForm.Viewport.GetElementAt(p.X,p.Y);
+end;
+
 function TFresnelFormMediator.ParentAcceptsChild(Parent: TComponent;
   Child: TComponentClass): boolean;
-var
-  ChildEl: TFresnelElement;
 begin
-  if Child.InheritsFrom(TFresnelElement) then
+  if Child.InheritsFrom(TControl) then
+    Result:=false
+  else if Child.InheritsFrom(TFresnelViewport) then
+    Result:=false
+  else if Parent is TFresnelElement then
   begin
-    if Child.InheritsFrom(TFresnelViewport) then
+    if Parent is TFresnelReplacedElement then
       exit(false);
-    ChildEl:=TFresnelElement(Child);
-    Result:=ChildEl.AcceptChildrenAtDesignTime;
-  end else if Child.InheritsFrom(TControl) then
-    Result:=false
-  else
+    Result:=Child.InheritsFrom(TFresnelElement);
+  end else
     Result:=inherited ParentAcceptsChild(Parent, Child);
 end;
 

+ 2 - 0
src/fresnelcontrols.pas

@@ -1,7 +1,9 @@
 unit FresnelControls;
 
 {$mode ObjFPC}{$H+}
+{$IF FPC_FULLVERSION>30300}
 {$WARN 6060 off} // Case statement does not handle all possible cases
+{$ENDIF}
 
 interface
 

+ 85 - 7
src/fresneldom.pas

@@ -11,14 +11,14 @@ ToDo:
 - speed up GetCSSDepth
 - speed up GetCSSNextOfType
 - speed up GetCSSPreviousOfType
-- invalid CSS values must be skipped, so validity check must be done during css resolver
-   e.g. negative border-left-width is ignored
--
+
 }
 unit FresnelDOM;
 
 {$mode ObjFPC}{$H+}
+{$IF FPC_FULLVERSION>30300}
 {$WARN 6060 off} // Case statement does not handle all possible cases
+{$ENDIF}
 
 interface
 
@@ -283,7 +283,7 @@ type
 
   { TFresnelElement }
 
-  TFresnelElement = class(TComponent, ICSSNode)
+  TFresnelElement = class(TComponent, ICSSNode, IFPObserver)
   private
     function GetCSSPseudo(Pseudo: TFresnelCSSPseudo): string;
     function GetNodeCount: integer;
@@ -390,6 +390,8 @@ type
     function GetRoot: TFresnelElement;
     function GetPath: string; virtual;
     function AcceptChildrenAtDesignTime: boolean; virtual;
+    procedure FPOObservedChanged(ASender: TObject; Operation: TFPObservedOperation; Data: Pointer); virtual;
+    procedure DomChanged; virtual;
     property Parent: TFresnelElement read FParent write SetParent;
     property NodeCount: integer read GetNodeCount;
     property Nodes[Index: integer]: TFresnelElement read GetNodes; default;
@@ -450,10 +452,8 @@ type
     procedure UpdateRenderedAttributes; virtual;
     function GetRenderedCSSLength(Attr: TFresnelCSSAttribute; UseInherited: boolean; UseNaNOnFail: boolean = false): TFresnelLength; virtual; // on fail returns NaN
     function GetRenderedCSString(Attr: TFresnelCSSAttribute; UseInherited: boolean): string; virtual;
-    //function GetRenderedContentBox: TFresnelRect; virtual;
-    //function GetRenderedBorderBox: TFresnelRect; virtual;
-    property RenderedBorderBox: TFresnelRect read FRenderedBorderBox write FRenderedBorderBox;
     property Rendered: boolean read FRendered write FRendered;
+    property RenderedBorderBox: TFresnelRect read FRenderedBorderBox write FRenderedBorderBox; // relative to layout parent
     property CSSRenderedAttribute[Attr: TFresnelCSSAttribute]: string read GetCSSRenderedAttribute write SetCSSRenderedAttribute;
     // font
     property Font: IFresnelFont read GetFont write FFont;
@@ -487,6 +487,7 @@ type
     FCSSResolver: TCSSResolver;
     FFontEngine: TFresnelFontEngine;
     FLayouter: TFresnelLayouter;
+    FOnDomChanged: TNotifyEvent;
     FStylesheetElements: TCSSElement;
     FStylesheet: TStrings;
     FDPI: array[boolean] of TFresnelLength;
@@ -525,7 +526,9 @@ type
     destructor Destroy; override;
     procedure ApplyCSS; virtual;
     procedure ClearCSSValues; override;
+    procedure DomChanged; override;
     function AllocateFont(const Desc: TFresnelFontDesc): IFresnelFont; virtual;
+    function GetElementAt(const x, y: TFresnelLength): TFresnelElement; virtual;
     property DPI[IsHorizontal: boolean]: TFresnelLength read GetDPI write SetDPI;
     property FontMinSize: TFresnelLength read FFontMinSize write SetFontMinSize;
     property ScrollbarWidth[IsHorizontal: boolean]: TFresnelLength read GetScrollbarWidth write SetScrollbarWidth;
@@ -538,6 +541,12 @@ type
     property MaxPreferredWidth: TFresnelLength read GetMaxPreferredWidth write SetMaxPreferredWidth;
     property Layouter: TFresnelLayouter read FLayouter write FLayouter;
     property FontEngine: TFresnelFontEngine read FFontEngine write FFontEngine;
+    property OnDomChanged: TNotifyEvent read FOnDomChanged write FOnDomChanged;
+  end;
+
+  IFresnelStreamRoot = interface
+    ['{A53F44CF-3BFB-42F6-A711-8C555E835E7F}']
+    function GetViewport: TFresnelViewport;
   end;
 
 const
@@ -916,6 +925,12 @@ begin
   FCSSComputed[fcaFontSize]:='12';
 end;
 
+procedure TFresnelViewport.DomChanged;
+begin
+  if assigned(OnDomChanged) then
+    OnDomChanged(Self);
+end;
+
 function TFresnelViewport.AllocateFont(const Desc: TFresnelFontDesc
   ): IFresnelFont;
 begin
@@ -925,6 +940,41 @@ begin
     raise EFresnelFont.Create('TFresnelViewport.AllocateFont no FontEngine');
 end;
 
+function TFresnelViewport.GetElementAt(const x, y: TFresnelLength
+  ): TFresnelElement;
+
+  function Check(Node: TFresnelLayoutNode; const dx, dy: TFresnelLength): TFresnelElement;
+  var
+    El: TFresnelElement;
+    i: Integer;
+    aLeft, aTop: TFresnelLength;
+    BorderBox: TFresnelRect;
+  begin
+    Result:=nil;
+    if Node=nil then exit;
+    El:=Node.Element;
+    if not El.Rendered then exit;
+    if Node.NodeCount>0 then begin
+      aLeft:=El.GetRenderedCSSLength(fcaLeft,false);
+      aTop:=El.GetRenderedCSSLength(fcaTop,false);
+      for i:=Node.NodeCount-1 downto 0 do
+      begin
+        Result:=Check(Node.Nodes[i],dx+aLeft,dy+aTop);
+        if Result<>nil then exit;
+      end;
+    end;
+    BorderBox:=El.RenderedBorderBox;
+    if (x>=BorderBox.Left+dx) and (y>=BorderBox.Top+dy)
+        and (x<=BorderBox.Right+dx) and (y<=BorderBox.Right+dy) then
+      Result:=El
+    else
+      Result:=nil;
+  end;
+
+begin
+  Result:=Check(LayoutNode,0,0);
+end;
+
 constructor TFresnelViewport.Create(AOwner: TComponent);
 begin
   inherited Create(AOwner);
@@ -986,6 +1036,7 @@ begin
     FCSSClasses.Assign(AValue);
     FCSSClasses.Delimiter:=' ';
   end;
+  DomChanged;
 end;
 
 function TFresnelElement.GetCSSPseudo(
@@ -1869,12 +1920,14 @@ begin
   if FParent<>nil then
   begin
     FParent.FChildren.Remove(Self);
+    FParent.DomChanged;
   end;
   FParent:=AValue;
   if FParent<>nil then
   begin
     FParent.FChildren.Add(Self);
     FreeNotification(FParent);
+    FParent.DomChanged;
   end;
 end;
 
@@ -1894,6 +1947,7 @@ begin
   finally
     aParser.Free;
   end;
+  DomChanged;
 end;
 
 procedure TFresnelElement.SetStyleElements(const AValue: TCSSElement);
@@ -1901,6 +1955,7 @@ begin
   if FStyleElements=AValue then Exit;
   FreeAndNil(FStyleElements);
   FStyleElements:=AValue;
+  DomChanged;
 end;
 
 class function TFresnelElement.RegisterCSSType(const aName: string
@@ -2391,15 +2446,29 @@ begin
   Result:=FFont;
 end;
 
+procedure TFresnelElement.DomChanged;
+begin
+  if FParent<>nil then
+    FParent.DomChanged;
+end;
+
 function TFresnelElement.HasParent: Boolean;
 begin
   Result:=Parent<>nil;
 end;
 
 procedure TFresnelElement.SetParentComponent(Value: TComponent);
+var
+  aStreamRoot: IFresnelStreamRoot;
 begin
+  debugln(['TFresnelElement.SetParentComponent Self=',DbgSName(Self),' NewParent=',DbgSName(Value)]);
   if Value is TFresnelElement then
     Parent:=TFresnelElement(Value)
+  else if Supports(Value,IFresnelStreamRoot,aStreamRoot) then
+  begin
+    debugln(['TFresnelElement.SetParentComponent Self=',DbgSName(Self),' redirecting to viewport']);
+    Parent:=aStreamRoot.GetViewport;
+  end
   else
     raise EFresnel.Create('TFresnelElement.SetParentComponent Self='+DbgSName(Self)+' NewParentComponent='+DbgSName(Value));
 end;
@@ -2429,11 +2498,13 @@ begin
   FChildren:=TFPList.Create;
   FCSSClasses:=TStringList.Create;
   FCSSClasses.Delimiter:=' ';
+  FCSSClasses.FPOAttachObserver(Self);
 end;
 
 destructor TFresnelElement.Destroy;
 begin
   Clear;
+  FCSSClasses.FPOAttachObserver(Self);
   FreeAndNil(FLayoutNode);
   FreeAndNil(FChildren);
   FreeAndNil(FCSSClasses);
@@ -2474,6 +2545,13 @@ begin
   Result:=true;
 end;
 
+procedure TFresnelElement.FPOObservedChanged(ASender: TObject;
+  Operation: TFPObservedOperation; Data: Pointer);
+begin
+  if ASender=FCSSClasses then
+    DomChanged;
+end;
+
 class constructor TFresnelElement.InitFresnelElementClass;
 var
   Kind: TCSSNumericalIDKind;

+ 103 - 8
src/fresnellclcontrols.pas

@@ -75,11 +75,16 @@ type
 
   TFresnelLCLControl = class(TCustomControl)
   private
+    FClearing: boolean;
     FFontEngine: TFresnelLCLFontEngine;
     FLayouter: TSimpleFresnelLayouter;
+    FLayoutQueued: boolean;
     FRenderer: TFresnelLCLRenderer;
     FViewport: TFresnelViewport;
+    procedure OnDomChanged(Sender: TObject);
+    procedure OnQueuedLayout(Data: PtrInt);
     procedure SetLayouter(const AValue: TSimpleFresnelLayouter);
+    procedure SetLayoutQueued(const AValue: boolean);
     procedure SetViewport(const AValue: TFresnelViewport);
   protected
     procedure Notification(AComponent: TComponent; Operation: TOperation);
@@ -92,32 +97,39 @@ type
     property Layouter: TSimpleFresnelLayouter read FLayouter write SetLayouter;
     property FontEngine: TFresnelLCLFontEngine read FFontEngine;
     property Renderer: TFresnelLCLRenderer read FRenderer;
+    property LayoutQueued: boolean read FLayoutQueued write SetLayoutQueued;
   end;
 
   { TFresnelCustomForm }
 
-  TFresnelCustomForm = class(TCustomForm)
+  TFresnelCustomForm = class(TCustomForm,IFresnelStreamRoot)
   private
-    FBody: TFresnelBody;
     FFontEngine: TFresnelLCLFontEngine;
     FLayouter: TSimpleFresnelLayouter;
     FRenderer: TFresnelLCLRenderer;
     FViewport: TFresnelViewport;
+    FLayoutQueued: boolean;
+    FClearing: boolean;
     function GetStylesheet: TStrings;
+    procedure OnDomChanged(Sender: TObject);
+    procedure OnQueuedLayout(Data: PtrInt);
+    procedure SetLayoutQueued(const AValue: boolean);
     procedure SetStylesheet(const AValue: TStrings);
   protected
     procedure Notification(AComponent: TComponent; Operation: TOperation);
       override;
     procedure Paint; override;
+    function GetViewport: TFresnelViewport; virtual;
   public
     constructor Create(AOwner: TComponent); override;
     destructor Destroy; override;
+    procedure GetChildren(Proc: TGetChildProc; Root: TComponent); override;
     property Viewport: TFresnelViewport read FViewport;
     property Layouter: TSimpleFresnelLayouter read FLayouter;
     property FontEngine: TFresnelLCLFontEngine read FFontEngine;
     property Renderer: TFresnelLCLRenderer read FRenderer;
     property Stylesheet: TStrings read GetStylesheet write SetStylesheet;
-    property Body: TFresnelBody read FBody;
+    property LayoutQueued: boolean read FLayoutQueued write SetLayoutQueued;
   end;
 
   { TFresnelForm }
@@ -228,6 +240,30 @@ begin
   Result:=Viewport.Stylesheet;
 end;
 
+procedure TFresnelCustomForm.OnDomChanged(Sender: TObject);
+begin
+  LayoutQueued:=true;
+end;
+
+procedure TFresnelCustomForm.OnQueuedLayout(Data: PtrInt);
+begin
+  ViewPort.ApplyCSS;
+  //Layouter.WriteLayoutTree;
+  Layouter.Apply(ViewPort);
+  Invalidate;
+end;
+
+procedure TFresnelCustomForm.SetLayoutQueued(const AValue: boolean);
+begin
+  if FLayoutQueued=AValue then Exit;
+  if FClearing then exit;
+  if csDestroyingHandle in ControlState then exit;
+  if csDestroying in ComponentState then exit;
+  FLayoutQueued:=AValue;
+  if FLayoutQueued then
+    Application.QueueAsyncCall(@OnQueuedLayout,0);
+end;
+
 procedure TFresnelCustomForm.SetStylesheet(const AValue: TStrings);
 begin
   Viewport.Stylesheet:=AValue;
@@ -241,12 +277,16 @@ begin
   begin
     if AComponent=FViewport then
       FViewport:=nil;
+    if AComponent=FFontEngine then
+      FFontEngine:=nil;
     if AComponent=FLayouter then
     begin
       FLayouter:=nil;
       if FViewport<>nil then
         FViewport.Layouter:=nil;
     end;
+    if AComponent=FRenderer then
+      FRenderer:=nil;
   end;
 end;
 
@@ -256,33 +296,62 @@ begin
   Renderer.Draw(Viewport);
 end;
 
+function TFresnelCustomForm.GetViewport: TFresnelViewport;
+begin
+  Result:=FViewport;
+end;
+
 constructor TFresnelCustomForm.Create(AOwner: TComponent);
 begin
   inherited Create(AOwner);
   FViewport:=TFresnelViewport.Create(nil);
+  FViewport.Name:='Viewport';
+  FViewport.OnDomChanged:=@OnDomChanged;
   FFontEngine:=TFresnelLCLFontEngine.Create(nil);
   FViewport.FontEngine:=FontEngine;
   FontEngine.Canvas:=Canvas;
-  FViewport.Name:='Viewport';
   FLayouter:=TSimpleFresnelLayouter.Create(nil);
   Layouter.Viewport:=ViewPort;
   FRenderer:=TFresnelLCLRenderer.Create(nil);
   FRenderer.Canvas:=Canvas;
-
-  FBody:=TFresnelBody.Create(nil);
-  FBody.Parent:=FViewport;
 end;
 
 destructor TFresnelCustomForm.Destroy;
 begin
-  FreeAndNil(FBody);
+  FClearing:=true;
   FreeAndNil(FRenderer);
   FreeAndNil(FLayouter);
   FreeAndNil(FViewport);
   FreeAndNil(FFontEngine);
+  Application.RemoveAllHandlersOfObject(Self);
   inherited Destroy;
 end;
 
+procedure TFresnelCustomForm.GetChildren(Proc: TGetChildProc; Root: TComponent);
+var
+  i: Integer;
+  OwnedComponent: TComponent;
+  ChildEl: TFresnelElement;
+begin
+  if Root=Self then
+  begin
+    // first all children of Viewport
+    for i:=0 to Viewport.NodeCount-1 do
+    begin
+      ChildEl:=Viewport.Nodes[i];
+      if ChildEl.Owner=Root then
+        Proc(ChildEl);
+    end;
+    // then all non visual components
+    for i := 0 to ComponentCount - 1 do
+    begin
+      OwnedComponent := Components[i];
+      if not OwnedComponent.HasParent then
+        Proc(OwnedComponent);
+    end;
+  end;
+end;
+
 { TFresnelLCLControl }
 
 procedure TFresnelLCLControl.SetViewport(const AValue: TFresnelViewport);
@@ -299,6 +368,30 @@ begin
     FViewport.Layouter:=FLayouter;
 end;
 
+procedure TFresnelLCLControl.SetLayoutQueued(const AValue: boolean);
+begin
+  if FLayoutQueued=AValue then Exit;
+  if FClearing then exit;
+  if csDestroyingHandle in ControlState then exit;
+  if csDestroying in ComponentState then exit;
+  FLayoutQueued:=AValue;
+  if FLayoutQueued then
+    Application.QueueAsyncCall(@OnQueuedLayout,0);
+end;
+
+procedure TFresnelLCLControl.OnDomChanged(Sender: TObject);
+begin
+  LayoutQueued:=true;
+end;
+
+procedure TFresnelLCLControl.OnQueuedLayout(Data: PtrInt);
+begin
+  ViewPort.ApplyCSS;
+  //Layouter.WriteLayoutTree;
+  Layouter.Apply(ViewPort);
+  Invalidate;
+end;
+
 procedure TFresnelLCLControl.Notification(AComponent: TComponent;
   Operation: TOperation);
 begin
@@ -327,6 +420,7 @@ constructor TFresnelLCLControl.Create(AOwner: TComponent);
 begin
   inherited Create(AOwner);
   FViewport:=TFresnelViewport.Create(nil);
+  FViewport.OnDomChanged:=@OnDomChanged;
   FFontEngine:=TFresnelLCLFontEngine.Create(nil);
   FViewport.FontEngine:=FontEngine;
   FontEngine.Canvas:=Canvas;
@@ -339,6 +433,7 @@ end;
 
 destructor TFresnelLCLControl.Destroy;
 begin
+  FClearing:=true;
   FreeAndNil(FRenderer);
   FreeAndNil(FLayouter);
   FreeAndNil(FViewport);