|
@@ -30,6 +30,8 @@ const
|
|
|
|
|
|
type
|
|
|
|
|
|
+ { TFresnelRenderer }
|
|
|
+
|
|
|
TFresnelRenderer = class(TComponent,IFresnelRenderer)
|
|
|
private
|
|
|
FSubPixel: boolean;
|
|
@@ -40,7 +42,7 @@ type
|
|
|
{ TBorderAndBackground }
|
|
|
|
|
|
TBorderAndBackground = class
|
|
|
- Private
|
|
|
+ private
|
|
|
FHasBorder : TCalcBoolean;
|
|
|
FHasRadius : TCalcBoolean;
|
|
|
FSameBorderWidth : TCalcBoolean;
|
|
@@ -60,6 +62,22 @@ type
|
|
|
function HasRadius : Boolean;
|
|
|
property Renderer : TFresnelRenderer read FRenderer;
|
|
|
end;
|
|
|
+
|
|
|
+ { TScrollBar }
|
|
|
+
|
|
|
+ TScrollBar = class
|
|
|
+ private
|
|
|
+ FRenderer : TFresnelRenderer;
|
|
|
+ public
|
|
|
+ Box: TFresnelRect;
|
|
|
+ Horizontal: boolean;
|
|
|
+ Position: TFresnelLength; // ScrollLeft/Top
|
|
|
+ Size: TFresnelLength; // ScrollWidth/Height
|
|
|
+ Page: TFresnelLength; // ClientWidth/Height
|
|
|
+ Color: TFPColor;
|
|
|
+ constructor Create(aRenderer: TFresnelRenderer);
|
|
|
+ property Renderer: TFresnelRenderer read FRenderer;
|
|
|
+ end;
|
|
|
protected
|
|
|
// Not in IFresnelRenderer
|
|
|
// Create backend-specific TBorderAndBackground if needed
|
|
@@ -70,6 +88,11 @@ type
|
|
|
procedure DrawElBackground(El: TFresnelElement; Params: TBorderAndBackground); virtual;
|
|
|
// Draw the border of the element. This is called after drawing the background. Not called if PrepareBackgroundBorder returned False.
|
|
|
procedure DrawElBorder(El: TFresnelElement; Params: TBorderAndBackground); virtual;
|
|
|
+ function CreateScrollBar : TScrollBar; virtual;
|
|
|
+ // Draw the scrollbars of the element. Called after drawing borders.
|
|
|
+ procedure DrawScrollBar(El: TFresnelElement; aBar: TScrollBar); virtual;
|
|
|
+ procedure DrawScrollBarCorner(El: TFresnelElement; const r: TFresnelRect); virtual;
|
|
|
+ procedure DrawScrollBars(El: TFresnelElement); virtual;
|
|
|
// Draw an element
|
|
|
procedure DrawElement(El: TFresnelElement); virtual;
|
|
|
// Draw the children of the element
|
|
@@ -485,6 +508,184 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
+function TFresnelRenderer.CreateScrollBar: TScrollBar;
|
|
|
+begin
|
|
|
+ Result:=TScrollBar.Create(Self);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TFresnelRenderer.DrawScrollBar(El: TFresnelElement; aBar: TScrollBar);
|
|
|
+var
|
|
|
+ TrackColor, ThumbColor: TFPColor;
|
|
|
+ FromPos, ToPos, l: TFresnelLength;
|
|
|
+ r: TFresnelRect;
|
|
|
+ Border, Radius: integer;
|
|
|
+ ThumbR: TFresnelRoundRect;
|
|
|
+ c: TFresnelCSSCorner;
|
|
|
+begin
|
|
|
+ if El=nil then ;
|
|
|
+ r:=aBar.Box;
|
|
|
+
|
|
|
+ // draw track
|
|
|
+ TrackColor:=colLtGray;
|
|
|
+ FillRect(TrackColor,r);
|
|
|
+ if aBar.Size<1 then
|
|
|
+ exit;
|
|
|
+
|
|
|
+ // draw thumb
|
|
|
+ ThumbColor:=colDkGray;
|
|
|
+ FromPos:=aBar.Position/aBar.Size;
|
|
|
+ if FromPos<0 then FromPos:=0;
|
|
|
+ if FromPos>1 then FromPos:=1;
|
|
|
+ ToPos:=(aBar.Position+aBar.Page)/aBar.Size;
|
|
|
+ if ToPos<0 then ToPos:=0;
|
|
|
+ if ToPos>1 then ToPos:=1;
|
|
|
+ if aBar.Horizontal then
|
|
|
+ begin
|
|
|
+ if r.Width<r.Height then exit;
|
|
|
+ Border:=round(r.Height/6);
|
|
|
+ end else begin
|
|
|
+ if r.Height<r.Width then exit;
|
|
|
+ Border:=round(r.Width/6);
|
|
|
+ end;
|
|
|
+ Radius:=Border*2;
|
|
|
+ for c in TFresnelCSSCorner do begin
|
|
|
+ ThumbR.Radii[c].X:=Radius;
|
|
|
+ ThumbR.Radii[c].Y:=Radius;
|
|
|
+ end;
|
|
|
+ ThumbR.Box.Left:=r.Left+Border;
|
|
|
+ ThumbR.Box.Top:=r.Top+Border;
|
|
|
+ ThumbR.Box.Right:=r.Right-Border;
|
|
|
+ ThumbR.Box.Bottom:=r.Bottom-Border;
|
|
|
+ if aBar.Horizontal then
|
|
|
+ begin
|
|
|
+ l:=ThumbR.Box.Width-2*Radius;
|
|
|
+ ThumbR.Box.Left:=ThumbR.Box.Left+FromPos*l;
|
|
|
+ ThumbR.Box.Right:=ThumbR.Box.Left+2*Radius+ToPos*l;
|
|
|
+ end else begin
|
|
|
+ l:=ThumbR.Box.Height-2*Radius;
|
|
|
+ ThumbR.Box.Top:=ThumbR.Box.Top+FromPos*l;
|
|
|
+ ThumbR.Box.Bottom:=ThumbR.Box.Top+2*Radius+ToPos*l;
|
|
|
+ end;
|
|
|
+
|
|
|
+ RoundRect(ThumbColor,ThumbR,true);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TFresnelRenderer.DrawScrollBarCorner(El: TFresnelElement; const r: TFresnelRect);
|
|
|
+var
|
|
|
+ TrackColor: TFPColor;
|
|
|
+begin
|
|
|
+ if El=nil then ;
|
|
|
+ TrackColor:=colLtGray;
|
|
|
+ FillRect(TrackColor,r);
|
|
|
+end;
|
|
|
+
|
|
|
+procedure TFresnelRenderer.DrawScrollBars(El: TFresnelElement);
|
|
|
+var
|
|
|
+ LNode: TUsedLayoutNode;
|
|
|
+ BarWidth, BarHeight: TFresnelLength;
|
|
|
+ r, aPaddingBox: TFresnelRect;
|
|
|
+ aScrollbar: TScrollBar;
|
|
|
+ IsLeft, HasVertBar, HasHorzBar: Boolean;
|
|
|
+begin
|
|
|
+ LNode:=TUsedLayoutNode(El.LayoutNode);
|
|
|
+ IsLeft:=false;
|
|
|
+ HasVertBar:=flfVerticalScrollbar in LNode.Flags;
|
|
|
+ HasHorzBar:=flfHorizontalScrollbar in LNode.Flags;
|
|
|
+ if HasVertBar then
|
|
|
+ begin
|
|
|
+ case LNode.ScrollbarWidth of
|
|
|
+ CSSRegistry.kwThin: BarWidth:=El.Viewport.ScrollbarsThinWidth[false];
|
|
|
+ else BarWidth:=El.Viewport.ScrollbarsWidth[false];
|
|
|
+ end;
|
|
|
+ IsLeft:=El.ComputedDirection=CSSRegistry.kwRTL;
|
|
|
+ end;
|
|
|
+ if HasHorzBar then
|
|
|
+ case LNode.ScrollbarWidth of
|
|
|
+ CSSRegistry.kwThin: BarHeight:=El.Viewport.ScrollbarsThinWidth[true];
|
|
|
+ else BarHeight:=El.Viewport.ScrollbarsWidth[true];
|
|
|
+ end;
|
|
|
+ aPaddingBox:=El.GetRenderedPaddingBox;
|
|
|
+
|
|
|
+ if HasVertBar then
|
|
|
+ begin
|
|
|
+ r:=aPaddingBox;
|
|
|
+ if IsLeft then
|
|
|
+ r.Right:=Min(r.Right,r.Left+BarWidth)
|
|
|
+ else
|
|
|
+ r.Left:=Max(r.Left,r.Right-BarWidth);
|
|
|
+ if HasHorzBar then
|
|
|
+ r.Bottom:=Max(r.Top,r.Bottom-BarHeight);
|
|
|
+
|
|
|
+ if not r.IsEmpty then
|
|
|
+ begin
|
|
|
+ aScrollbar:=CreateScrollBar;
|
|
|
+ try
|
|
|
+ aScrollbar.Horizontal:=false;
|
|
|
+ aScrollbar.Size:=LNode.ScrollHeight;
|
|
|
+ aScrollbar.Position:=El.ScrollTop;
|
|
|
+ aScrollbar.Page:=El.ClientHeight;
|
|
|
+ aScrollbar.Box:=r;
|
|
|
+ aScrollbar.Color:=El.GetComputedColor(fcaScrollbarColor,colGray);
|
|
|
+
|
|
|
+ {$IFDEF VerboseFresnelScrolling}
|
|
|
+ writeln('TFresnelRenderer.DrawScrollBars ',El.Name,' ScrollHeight=',FloatToCSSStr(El.ScrollHeight),' ClientHeight',FloatToCSSStr(El.ClientHeight),' ScrollTop=',FloatToCSSStr(El.ScrollTop)+' BarWidth='+FloatToCSSStr(BarWidth));
|
|
|
+ {$ENDIF}
|
|
|
+ DrawScrollBar(El,aScrollbar);
|
|
|
+ finally
|
|
|
+ aScrollbar.Free;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ if HasHorzBar then
|
|
|
+ begin
|
|
|
+ r:=aPaddingBox;
|
|
|
+ r.Top:=Max(r.Top,r.Bottom-BarHeight);
|
|
|
+ if HasVertBar then
|
|
|
+ begin
|
|
|
+ if IsLeft then
|
|
|
+ r.Left:=r.Left+BarWidth
|
|
|
+ else
|
|
|
+ r.Right:=r.Right-BarWidth;
|
|
|
+ end;
|
|
|
+
|
|
|
+ if not r.IsEmpty then
|
|
|
+ begin
|
|
|
+ aScrollbar:=CreateScrollBar;
|
|
|
+ try
|
|
|
+ aScrollbar.Horizontal:=true;
|
|
|
+ aScrollbar.Size:=LNode.ScrollWidth;
|
|
|
+ aScrollbar.Position:=El.ScrollLeft;
|
|
|
+ aScrollbar.Page:=El.ClientWidth;
|
|
|
+ aScrollbar.Box:=r;
|
|
|
+ aScrollbar.Color:=El.GetComputedColor(fcaScrollbarColor,colGray);
|
|
|
+
|
|
|
+ {$IFDEF VerboseFresnelScrolling}
|
|
|
+ writeln('TFresnelRenderer.DrawScrollBars ',El.Name,' ScrollWidth=',FloatToCSSStr(El.ScrollWidth),' ClientWidth=',FloatToCSSStr(El.ClientWidth),' ScrollLeft=',FloatToCSSStr(El.ScrollLeft)+' BarHeight='+FloatToCSSStr(BarHeight));
|
|
|
+ {$ENDIF}
|
|
|
+ DrawScrollBar(El,aScrollbar);
|
|
|
+ finally
|
|
|
+ aScrollbar.Free;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+ end;
|
|
|
+
|
|
|
+ if HasVertBar and HasHorzBar then
|
|
|
+ begin
|
|
|
+ r.Bottom:=aPaddingBox.Bottom;
|
|
|
+ r.Top:=Max(aPaddingBox.Top,r.Bottom-BarHeight);
|
|
|
+ if IsLeft then
|
|
|
+ begin
|
|
|
+ r.Left:=aPaddingBox.Left;
|
|
|
+ r.Right:=Min(aPaddingBox.Right,r.Left+BarWidth);
|
|
|
+ end else begin
|
|
|
+ r.Right:=aPaddingBox.Right;
|
|
|
+ r.Left:=Max(aPaddingBox.Left,r.Right-BarWidth);
|
|
|
+ end;
|
|
|
+ if not r.IsEmpty then
|
|
|
+ DrawScrollbarCorner(El,r);
|
|
|
+ end;
|
|
|
+end;
|
|
|
+
|
|
|
procedure TFresnelRenderer.DrawElement(El: TFresnelElement);
|
|
|
var
|
|
|
LNode: TUsedLayoutNode;
|
|
@@ -550,7 +751,7 @@ begin
|
|
|
end;
|
|
|
|
|
|
// draw scrollbars
|
|
|
-
|
|
|
+ DrawScrollBars(El);
|
|
|
|
|
|
// Give element a chance to draw itself (on top of background and border)
|
|
|
aRenderable.Render(Self as IFresnelRenderer);
|
|
@@ -713,5 +914,12 @@ begin
|
|
|
Result:=FHasRadius;
|
|
|
end;
|
|
|
|
|
|
+{ TFresnelRenderer.TScrollBar }
|
|
|
+
|
|
|
+constructor TFresnelRenderer.TScrollBar.Create(aRenderer: TFresnelRenderer);
|
|
|
+begin
|
|
|
+ FRenderer:=aRenderer;
|
|
|
+end;
|
|
|
+
|
|
|
end.
|
|
|
|