Browse Source

inspector: added box model

mattias 1 day ago
parent
commit
1fa315c412
1 changed files with 209 additions and 2 deletions
  1. 209 2
      src/base/fresnel.cssstyleinspector.pas

+ 209 - 2
src/base/fresnel.cssstyleinspector.pas

@@ -5,15 +5,41 @@ unit Fresnel.CSSStyleInspector;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, fpCSSTree, fpCSSResParser, fpCSSResolver, Fresnel.DOM, Fresnel.Classes,
-  Fresnel.Controls, Fresnel.Events, FCL.Events;
+  Classes, SysUtils, FPImage, fpCSSTree, fpCSSResParser, fpCSSResolver,
+  Fresnel.DOM, Fresnel.Classes, Fresnel.Controls, Fresnel.Events, FCL.Events;
 
 
 type
 type
 
 
+  { TCSSInspBoxModell }
+
+  TCSSInspBoxModell = class(TDiv)
+  private
+    FBorderColor: TFPColor;
+    FContentColor: TFPColor;
+    FMarginColor: TFPColor;
+    FPaddingColor: TFPColor;
+    FTarget: TFresnelElement;
+    procedure SetBorderColor(AValue: TFPColor);
+    procedure SetContentColor(AValue: TFPColor);
+    procedure SetMarginColor(AValue: TFPColor);
+    procedure SetPaddingColor(AValue: TFPColor);
+  protected
+    function FloatToCaption(f: TFresnelLength): string; virtual;
+    procedure DoRender(aRenderer: IFresnelRenderer); override;
+  public
+    constructor Create(AOwner: TComponent); override;
+    property MarginColor: TFPColor read FMarginColor write SetMarginColor;
+    property BorderColor: TFPColor read FBorderColor write SetBorderColor;
+    property PaddingColor: TFPColor read FPaddingColor write SetPaddingColor;
+    property ContentColor: TFPColor read FContentColor write SetContentColor;
+    property Target: TFresnelElement read FTarget write FTarget;
+  end;
+
   { TCSSStyleInspector }
   { TCSSStyleInspector }
 
 
   TCSSStyleInspector = class(TDiv)
   TCSSStyleInspector = class(TDiv)
   private
   private
+    FBoxModellDiv: TCSSInspBoxModell;
     FRulesDiv: TDiv;
     FRulesDiv: TDiv;
     FLock: integer;
     FLock: integer;
     FInspectNeeded: boolean;
     FInspectNeeded: boolean;
@@ -42,6 +68,7 @@ type
       DeclColonLabelClass = 'CSSStyleInspColon';
       DeclColonLabelClass = 'CSSStyleInspColon';
       DeclValueLabelClass = 'CSSStyleInspValue';
       DeclValueLabelClass = 'CSSStyleInspValue';
       SkippedClass = 'CSSStyleInspSkipped';
       SkippedClass = 'CSSStyleInspSkipped';
+      BoxModellDivClass = 'CSSStyleInspBoxModell';
       //
       //
       ElementStyleCaption = 'Element.Style';
       ElementStyleCaption = 'Element.Style';
   public
   public
@@ -52,10 +79,181 @@ type
     procedure EndUpdate;
     procedure EndUpdate;
     property Target: TFresnelElement read FTarget write SetTarget;
     property Target: TFresnelElement read FTarget write SetTarget;
     property RulesDiv: TDiv read FRulesDiv;
     property RulesDiv: TDiv read FRulesDiv;
+    property BoxModellDiv: TCSSInspBoxModell read FBoxModellDiv;
   end;
   end;
 
 
 implementation
 implementation
 
 
+{ TCSSInspBoxModell }
+
+procedure TCSSInspBoxModell.SetMarginColor(AValue: TFPColor);
+begin
+  if FMarginColor=AValue then Exit;
+  FMarginColor:=AValue;
+  Invalidate;
+end;
+
+procedure TCSSInspBoxModell.SetPaddingColor(AValue: TFPColor);
+begin
+  if FPaddingColor=AValue then Exit;
+  FPaddingColor:=AValue;
+  Invalidate;
+end;
+
+function TCSSInspBoxModell.FloatToCaption(f: TFresnelLength): string;
+var
+  p, EndP: SizeInt;
+begin
+  Result:=FloatToStr(f,FresnelCSSFormatSettings);
+  p:=Pos(FresnelCSSFormatSettings.DecimalSeparator,Result);
+  if p>0 then
+  begin
+    inc(p);
+    EndP:=p;
+    while (EndP<length(Result)) and (Result[EndP] in ['0'..'9']) do
+      inc(EndP);
+    if EndP>p+1 then
+      System.Delete(Result,p+1,EndP-p-1);
+  end;
+end;
+
+procedure TCSSInspBoxModell.SetBorderColor(AValue: TFPColor);
+begin
+  if FBorderColor=AValue then Exit;
+  FBorderColor:=AValue;
+  Invalidate;
+end;
+
+procedure TCSSInspBoxModell.SetContentColor(AValue: TFPColor);
+begin
+  if FContentColor=AValue then Exit;
+  FContentColor:=AValue;
+  Invalidate;
+end;
+
+procedure TCSSInspBoxModell.DoRender(aRenderer: IFresnelRenderer);
+var
+  MarginRect, BorderRect, PaddingRect, ContentRect: TFresnelRect;
+  L, T, W, cx, cy: TFresnelLength;
+  Size0, MarginLeftSize, MarginRightSize, BorderLeftSize,
+    BorderRightSize, PaddingLeftSize, PaddingRightSize,
+    MarginTopSize, MarginBottomSize,
+    BorderTopSize, BorderBottomSize, PaddingTopSize,
+    PaddingBottomSize, ContentCaptionSize: TFresnelPoint;
+  F: IFresnelFont;
+  TextCol: TFPColor;
+  ContentCaption, MarginLeftCaption, MarginRightCaption,
+    MarginTopCaption, MarginBottomCaption, BorderBottomCaption,
+    BorderRightCaption, BorderTopCaption, BorderLeftCaption,
+    PaddingLeftCaption, PaddingRightCaption, PaddingTopCaption,
+    PaddingBottomCaption: String;
+  LNode: TFresnelLayoutNode;
+begin
+  inherited DoRender(aRenderer);
+  if Target=nil then exit;
+  LNode:=Target.LayoutNode;
+  if LNode=nil then exit;
+  if LNode.SkipLayout then exit;
+
+  L:=UsedClientBox.Left;
+  T:=UsedClientBox.Top;
+  W:=UsedClientBox.Width;
+  writeln('TFresnelBoxModell.DoRender ',UsedClientBox.ToString);
+  F:=Font;
+  Size0:=F.TextSize('0');
+  TextCol:=colWhite;
+  ContentCaption:=FloatToCaption(Target.UsedContentBox.Width)
+             +'x'+FloatToCaption(Target.UsedContentBox.Height);
+
+  MarginLeftCaption:=FloatToCaption(LNode.MarginLeft);
+  MarginLeftSize:=F.TextSize(MarginLeftCaption);
+  MarginRightCaption:=FloatToCaption(LNode.MarginRight);
+  MarginRightSize:=F.TextSize(MarginRightCaption);
+  MarginTopCaption:=FloatToCaption(LNode.MarginTop);
+  MarginTopSize:=F.TextSize(MarginTopCaption);
+  MarginBottomCaption:=FloatToCaption(LNode.MarginBottom);
+  MarginBottomSize:=F.TextSize(MarginBottomCaption);
+  BorderLeftCaption:=FloatToCaption(LNode.BorderLeft);
+  BorderLeftSize:=F.TextSize(BorderLeftCaption);
+  BorderRightCaption:=FloatToCaption(LNode.BorderRight);
+  BorderRightSize:=F.TextSize(BorderRightCaption);
+  BorderTopCaption:=FloatToCaption(LNode.BorderTop);
+  BorderTopSize:=F.TextSize(BorderTopCaption);
+  BorderBottomCaption:=FloatToCaption(LNode.BorderBottom);
+  BorderBottomSize:=F.TextSize(BorderBottomCaption);
+  PaddingLeftCaption:=FloatToCaption(LNode.PaddingLeft);
+  PaddingLeftSize:=F.TextSize(PaddingLeftCaption);
+  PaddingRightCaption:=FloatToCaption(LNode.PaddingRight);
+  PaddingRightSize:=F.TextSize(PaddingRightCaption);
+  PaddingTopCaption:=FloatToCaption(LNode.PaddingTop);
+  PaddingTopSize:=F.TextSize(PaddingTopCaption);
+  PaddingBottomCaption:=FloatToCaption(LNode.PaddingBottom);
+  PaddingBottomSize:=F.TextSize(PaddingBottomCaption);
+  ContentCaptionSize:=F.TextSize(ContentCaption);
+
+  MarginRect.Left:=L+W*0.15;
+  MarginRect.Right:=L+W*0.85;
+  MarginRect.Top:=T+Size0.Y*1.5;
+  MarginRect.Bottom:=T+Size0.Y*12;
+  aRenderer.FillRect(MarginColor,MarginRect);
+
+  BorderRect.Left:=MarginRect.Left+MarginLeftSize.X+Size0.X;
+  BorderRect.Right:=MarginRect.Right-MarginRightSize.X-Size0.X;
+  BorderRect.Top:=MarginRect.Top+Size0.Y*1.5;
+  BorderRect.Bottom:=MarginRect.Bottom-Size0.Y*1.5;
+  aRenderer.FillRect(BorderColor,BorderRect);
+
+  PaddingRect.Left:=BorderRect.Left+BorderLeftSize.X+Size0.X;
+  PaddingRect.Right:=BorderRect.Right-BorderRightSize.X-Size0.X;
+  PaddingRect.Top:=BorderRect.Top+Size0.Y*1.5;
+  PaddingRect.Bottom:=BorderRect.Bottom-Size0.Y*1.5;
+  aRenderer.FillRect(PaddingColor,PaddingRect);
+
+  ContentRect.Left:=PaddingRect.Left+PaddingLeftSize.X+Size0.X*1.5;
+  ContentRect.Right:=PaddingRect.Right-PaddingRightSize.X-Size0.X*1.5;
+  ContentRect.Top:=PaddingRect.Top+Size0.Y*1.5;
+  ContentRect.Bottom:=PaddingRect.Bottom-Size0.Y*1.5;
+  aRenderer.FillRect(ContentColor,ContentRect);
+
+  cx:=L+W*0.5;
+  cy:=(ContentRect.Top+ContentRect.Bottom)*0.5;
+
+  // captions
+  aRenderer.TextOut(L+Size0.X,T+Size0.Y*0.3,F,TextCol,'Box Model');
+  aRenderer.TextOut(MarginRect.Left+Size0.X,MarginRect.Top+Size0.Y*0.3,F,TextCol,'margin');
+  aRenderer.TextOut(BorderRect.Left+Size0.X,BorderRect.Top+Size0.Y*0.3,F,TextCol,'border');
+  aRenderer.TextOut(PaddingRect.Left+Size0.X,PaddingRect.Top+Size0.Y*0.3,
+    F,TextCol,'padding');
+  aRenderer.TextOut(ContentRect.Left+(ContentRect.Width-ContentCaptionSize.X)*0.5,
+                    cy-ContentCaptionSize.Y*0.5,F,TextCol,ContentCaption);
+
+  // values
+  aRenderer.TextOut(MarginRect.Left+Size0.X*0.5,cy-Size0.Y*0.5,F,TextCol,MarginLeftCaption);
+  aRenderer.TextOut(BorderRect.Left+Size0.X*0.5,cy-Size0.Y*0.5,F,TextCol,BorderLeftCaption);
+  aRenderer.TextOut(PaddingRect.Left+Size0.X*0.5,cy-Size0.Y*0.5,F,TextCol,PaddingLeftCaption);
+
+  aRenderer.TextOut(ContentRect.Right+Size0.X*0.5,cy-Size0.Y*0.5,F,TextCol,PaddingRightCaption);
+  aRenderer.TextOut(PaddingRect.Right+Size0.X*0.5,cy-Size0.Y*0.5,F,TextCol,BorderRightCaption);
+  aRenderer.TextOut(BorderRect.Right+Size0.X*0.5,cy-Size0.Y*0.5,F,TextCol,MarginRightCaption);
+
+  aRenderer.TextOut(cx-MarginTopSize.X*0.5,MarginRect.Top+Size0.Y*0.2,F,TextCol,MarginTopCaption);
+  aRenderer.TextOut(cx-BorderTopSize.X*0.5,BorderRect.Top+Size0.Y*0.2,F,TextCol,BorderTopCaption);
+  aRenderer.TextOut(cx-PaddingTopSize.X*0.5,PaddingRect.Top+Size0.Y*0.2,F,TextCol,PaddingTopCaption);
+
+  aRenderer.TextOut(cx-PaddingBottomSize.X*0.5,PaddingRect.Bottom-Size0.Y*1.2,F,TextCol,PaddingBottomCaption);
+  aRenderer.TextOut(cx-BorderBottomSize.X*0.5,BorderRect.Bottom-Size0.Y*1.2,F,TextCol,BorderBottomCaption);
+  aRenderer.TextOut(cx-MarginBottomSize.X*0.5,MarginRect.Bottom-Size0.Y*1.2,F,TextCol,MarginBottomCaption);
+end;
+
+constructor TCSSInspBoxModell.Create(AOwner: TComponent);
+begin
+  inherited Create(AOwner);
+  FMarginColor:=FPColor($bbbb,$bbbb,0);
+  FBorderColor:=FPColor($3333,$3333,$3333);
+  FPaddingColor:=FPColor($bbbb,$8080,$bbbb);
+  FContentColor:=FPColor(0,$8080,$bbbb);
+end;
+
 { TCSSStyleInspector }
 { TCSSStyleInspector }
 
 
 procedure TCSSStyleInspector.SetTarget(const AValue: TFresnelElement);
 procedure TCSSStyleInspector.SetTarget(const AValue: TFresnelElement);
@@ -66,6 +264,8 @@ begin
   if FTarget<>nil then
   if FTarget<>nil then
     RemoveFreeNotification(FTarget);
     RemoveFreeNotification(FTarget);
   FTarget:=AValue;
   FTarget:=AValue;
+  if BoxModellDiv<>nil then
+    BoxModellDiv.Target:=Target;
   if FTarget<>nil then
   if FTarget<>nil then
   begin
   begin
     if (FTarget=Self) or Contains(FTarget) then
     if (FTarget=Self) or Contains(FTarget) then
@@ -402,6 +602,12 @@ begin
     Parent:=Self;
     Parent:=Self;
   end;
   end;
 
 
+  FBoxModellDiv:=TCSSInspBoxModell.Create(Self);
+  with BoxModellDiv do begin
+    CSSClasses.Text:=BoxModellDivClass;
+    Parent:=Self;
+  end;
+
   Inspect;
   Inspect;
 end;
 end;
 
 
@@ -422,6 +628,7 @@ begin
     +'.'+DeclKeyLabelClass+' { color: cyan; }'+LineEnding
     +'.'+DeclKeyLabelClass+' { color: cyan; }'+LineEnding
     +'.'+DeclColonLabelClass+' { margin-right: 1ch; }'+LineEnding
     +'.'+DeclColonLabelClass+' { margin-right: 1ch; }'+LineEnding
     +'.'+SkippedClass+' { color: #aaa; }'+LineEnding
     +'.'+SkippedClass+' { color: #aaa; }'+LineEnding
+    +'.'+BoxModellDivClass+' { color: #fff; font-size: 10px; background-color: #222; padding: 6px; }'+LineEnding
     ;
     ;
 end;
 end;