Browse Source

scroll: started drawing buttons

mattias 5 tháng trước cách đây
mục cha
commit
3308f04365

+ 9 - 7
demo/ScrollBox/MainUnit.pas

@@ -42,15 +42,15 @@ type
     BothEdgesCheckBox: TDemoCheckBox;
     ColorCheckBox: TDemoCheckBox;
     procedure MainFormCreate(Sender: TObject);
-    procedure OnAutoHideClicked(Event : TAbstractEvent);
+    procedure OnAutoHideClicked({%H-}Event : TAbstractEvent);
     procedure OnOverflowXClicked(Event : TAbstractEvent);
     procedure OnOverflowYClicked(Event : TAbstractEvent);
-    procedure OnOverlayClicked(Event : TAbstractEvent);
-    procedure OnHaveButtonsClicked(Event : TAbstractEvent);
-    procedure OnRTLClicked(Event : TAbstractEvent);
-    procedure OnThinClicked(Event : TAbstractEvent);
-    procedure OnBothEdgesClicked(Event : TAbstractEvent);
-    procedure OnColorClicked(Event : TAbstractEvent);
+    procedure OnOverlayClicked({%H-}Event : TAbstractEvent);
+    procedure OnHaveButtonsClicked({%H-}Event : TAbstractEvent);
+    procedure OnRTLClicked({%H-}Event : TAbstractEvent);
+    procedure OnThinClicked({%H-}Event : TAbstractEvent);
+    procedure OnBothEdgesClicked({%H-}Event : TAbstractEvent);
+    procedure OnColorClicked({%H-}Event : TAbstractEvent);
   private
   public
     procedure ApplyScrollbarGutter;
@@ -73,6 +73,8 @@ begin
   OverflowXAuto.Checked:=true;
   OverflowYAuto.Checked:=true;
 
+  ScrollbarsHaveButtons:=true;
+
   AutoHideCheckBox.Checked:=ScrollbarsAutoHide;
   HaveButtonsCheckBox.Checked:=ScrollbarsHaveButtons;
   OverlayCheckBox.Checked:=ScrollbarsOverlay;

+ 3 - 0
src/base/fresnel.classes.pas

@@ -103,9 +103,11 @@ type
     function GetPointF: TPointF;
     function ToString : String;
   end;
+  PFresnelPoint = ^TFresnelPoint;
   TFLPoint = TFresnelPoint;
   TFresnelPointArray = array of TFresnelPoint;
 
+
   { TFresnelRect }
 
   TFresnelRect = packed record
@@ -159,6 +161,7 @@ type
   end;
   TFLRect = TFresnelRect;
   TFresnelRectDynArray = array of TFresnelRect;
+  PFresnelRect = ^TFresnelRect;
 
   { TFresnelComponent }
 

+ 34 - 34
src/base/fresnel.dom.pas

@@ -1599,7 +1599,7 @@ type
     procedure SetParent(const AValue: TFresnelElement); override;
   public type
     {$ScopedEnums on}
-    THit = (hNone, hButtonLT, hButtonRB, hThumb, hTrackLT, hTrackRB);
+    TSBHit = (hNone, hButtonLT, hButtonRB, hThumb, hTrackLT, hTrackRB);
     {$ScopedEnums off}
   public
     Position: TFresnelLength; // ScrollLeft/Top, When direction=rtl: Position=Size-Page+ScrollLeft
@@ -1609,11 +1609,12 @@ type
     HasColor: boolean;
     ThumbColor, TrackColor: TFPColor;
     Box: TFresnelRect; // same coord system as parent, e.g. parent.UsedBorderBox
-    MouseDownHit: THit;
+    MouseDownHit: TSBHit;
     MouseDownPosition, MouseDownGrabPos: TFresnelLength;
     constructor Create(TheElement: TFresnelElement; aHorizontal: boolean); overload;
-    function GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): THit; virtual; abstract;
-    procedure GetColors(out CurThumbColor, CurTrackColor: TFPColor);
+    function GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): TSBHit; virtual; abstract;
+    function GetThumbColor: TFPColor;
+    function GetTrackColor: TFPColor;
     property Horizontal: boolean read FHorizontal;
   end;
 
@@ -1723,14 +1724,14 @@ type
     function TrySetFocusControl(aControl : TFresnelElement) : Boolean;
   public type
       {$ScopedEnums on}
-      THit = (
-        hNone,
-        hElement,
-        hScrollbarHorz,
-        hScrollbarVert
+      TVPHit = (
+        hitNone,
+        hitElement,
+        hitScrollbarHorz,
+        hitScrollbarVert
         );
       {$ScopedEnums off}
-      THits = set of THit;
+      THits = set of TVPHit;
 
       { TBubbleMouseClickEvent }
 
@@ -1799,7 +1800,7 @@ type
     function GetElementsAt(const x, y: TFresnelLength): TFresnelElementArray;
     // returns in stacking order top to bottom aka child to parents
     procedure GetElementsAt(const x, y: TFresnelLength; OnlyLast: boolean;
-      out Arr: TFresnelElementArray; out Hit: THit); virtual; // viewport coords
+      out Arr: TFresnelElementArray; out Hit: TVPHit); virtual; // viewport coords
     function ClientPosToViewport(El: TFresnelElement; const x, y: TFresnelLength): TFresnelPoint; overload; // child coord to viewport
     function ViewportToClientPos(El: TFresnelElement; const x, y: TFresnelLength): TFresnelPoint; overload; // viewport to child coord
     function ViewportToClientPos(El: TFresnelElement; const p: TFresnelPoint): TFresnelPoint; overload; // viewport to child coord
@@ -6642,25 +6643,24 @@ begin
     Parent.FScrollBarVertical:=Self;
 end;
 
-procedure TPseudoElScrollBar.GetColors(out CurThumbColor,
-  CurTrackColor: TFPColor);
-var
-  ElHovered: Boolean;
+function TPseudoElScrollBar.GetThumbColor: TFPColor;
 begin
-  ElHovered:=Parent.IsHovered;
   if HasColor then
-    CurTrackColor:=TrackColor
-  else if ElHovered then
-    CurTrackColor:=Viewport.ScrollbarsColors[vscTrackHover]
+    Result:=ThumbColor
+  else if Parent.IsHovered then
+    Result:=Viewport.ScrollbarsColors[vscThumbHover]
   else
-    CurTrackColor:=Viewport.ScrollbarsColors[vscTrackNormal];
+    Result:=Viewport.ScrollbarsColors[vscThumbNormal];
+end;
 
+function TPseudoElScrollBar.GetTrackColor: TFPColor;
+begin
   if HasColor then
-    CurThumbColor:=ThumbColor
-  else if ElHovered then
-    CurThumbColor:=Viewport.ScrollbarsColors[vscThumbHover]
+    Result:=TrackColor
+  else if Parent.IsHovered then
+    Result:=Viewport.ScrollbarsColors[vscTrackHover]
   else
-    CurThumbColor:=Viewport.ScrollbarsColors[vscThumbNormal];
+    Result:=Viewport.ScrollbarsColors[vscTrackNormal];
 end;
 
 { TFresnelFontDesc }
@@ -7123,7 +7123,7 @@ function TFresnelViewport.GetElementAt(const x, y: TFresnelLength
   ): TFresnelElement;
 var
   Arr: TFresnelElementArray;
-  Hit: THit;
+  Hit: TVPHit;
 begin
   GetElementsAt(x,y,true,Arr,Hit);
   if Arr<>nil then
@@ -7135,13 +7135,13 @@ end;
 function TFresnelViewport.GetElementsAt(const x, y: TFresnelLength
   ): TFresnelElementArray;
 var
-  Hit: THit;
+  Hit: TVPHit;
 begin
   GetElementsAt(x,y,false,Result,Hit);
 end;
 
 procedure TFresnelViewport.GetElementsAt(const x, y: TFresnelLength; OnlyLast: boolean; out
-  Arr: TFresnelElementArray; out Hit: THit);
+  Arr: TFresnelElementArray; out Hit: TVPHit);
 
   function Check(Node: TFresnelLayoutNode; const dx, dy: TFresnelLength): boolean;
   var
@@ -7178,14 +7178,14 @@ procedure TFresnelViewport.GetElementsAt(const x, y: TFresnelLength; OnlyLast: b
       if (aBar<>nil) and aBar.Box.Contains(dx,dy) then
       begin
         Arr:=[El];
-        Hit:=THit.hScrollbarHorz;
+        Hit:=TVPHit.hitScrollbarHorz;
         exit(true);
       end;
       aBar:=El.ScrollBarVertical;
       if (aBar<>nil) and aBar.Box.Contains(dx,dy) then
       begin
         Arr:=[El];
-        Hit:=THit.hScrollbarVert;
+        Hit:=TVPHit.hitScrollbarVert;
         exit(true);
       end;
     end;
@@ -7206,7 +7206,7 @@ procedure TFresnelViewport.GetElementsAt(const x, y: TFresnelLength; OnlyLast: b
       if length(Arr)=0 then
       begin
         Arr:=[El];
-        Hit:=THit.hElement;
+        Hit:=TVPHit.hitElement;
       end else begin
         System.Insert(El,Arr,length(Arr));
       end;
@@ -7216,7 +7216,7 @@ procedure TFresnelViewport.GetElementsAt(const x, y: TFresnelLength; OnlyLast: b
 
 begin
   Arr:=[];
-  Hit:=THit.hNone;
+  Hit:=TVPHit.hitNone;
   Check(LayoutNode,x,y);
   //writeln('TFresnelViewport.GetElementsAt END ',Hit);
 end;
@@ -7438,7 +7438,7 @@ var
   NewViewportXY, OldViewportXY, NewPageXY: TFresnelPoint;
   i: Integer;
   j: SizeInt;
-  Hit: THit;
+  Hit: TVPHit;
 begin
   if not (MouseEventId in [evtMouseDown,evtMouseUp,evtMouseMove,evtMouseEnter,evtMouseLeave]) then
     exit;
@@ -7534,8 +7534,8 @@ begin
     begin
       El:=NewHoverElements[0];
       case Hit of
-      THit.hScrollbarHorz: El:=El.ScrollBarHorizontal;
-      THit.hScrollbarVert: El:=El.ScrollBarVertical;
+      TVPHit.hitScrollbarHorz: El:=El.ScrollBarHorizontal;
+      TVPHit.hitScrollbarVert: El:=El.ScrollBarVertical;
       end;
     end else
       El:=Self;

+ 220 - 60
src/base/fresnel.renderer.pas

@@ -39,11 +39,17 @@ type
   protected
     procedure MouseHandler(Event: TAbstractEvent); virtual;
   public
-    Border: TFresnelLength;
+    Padding: TFresnelLength;
+    ThumbArea: TFresnelRect;
+    TrackArea: TFresnelRect;
+    ButtonLT: TFresnelRect;
+    ButtonRB: TFresnelRect;
     constructor Create(AOwner: TComponent); override; overload;
+    procedure Layout; virtual;
     procedure Draw(Renderer: TFresnelRenderer); virtual;
+    procedure DrawButton(Renderer: TFresnelRenderer; LT: boolean); virtual;
     procedure DrawCorner(Renderer: TFresnelRenderer; const r: TFresnelRect); virtual;
-    function GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): THit; override;
+    function GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): TSBHit; override;
   end;
 
   { TFresnelRenderer }
@@ -135,6 +141,8 @@ type
     procedure FillRect(const aColor: TFPColor; const aRect: TFresnelRect); virtual; abstract;
     // Draw a line from point A (x1,y1) to B (x2,y2) using given color.
     procedure Line(const aColor: TFPColor; const x1, y1, x2, y2: TFresnelLength); virtual; abstract;
+    // Draw a filled polygon
+    procedure Polygon(const aColor: TFPColor; const p: PFresnelPoint; Count: integer); virtual; abstract;
     // Restores a saved state of clipping and matrix.
     procedure Restore; virtual; abstract;
     // Draw (and optionally fill) a rounded rectangle with given boundaries and color.
@@ -408,7 +416,7 @@ procedure TRendererScrollBar.MouseHandler(Event: TAbstractEvent);
 var
   MouseEvt: TFresnelMouseEvent absolute Event;
   X, Y, p, NewPos: TFresnelLength;
-  Hit: THit;
+  Hit: TSBHit;
 begin
   // the mouse event has the coord of the Parent's clientbox
   // -> translate to GrandParent's child box
@@ -429,17 +437,17 @@ begin
       writeln('TRendererScrollBar.MouseHandler Mouse Down ',Parent.Name,' Horz=',Horizontal,' Hit=',MouseDownHit,' p=',FloatToCSSStr(MouseDownGrabPos));
       {$ENDIF}
       case MouseDownHit of
-      THit.hButtonLT: ;
-      THit.hButtonRB: ;
-      THit.hThumb:
+      TSBHit.hButtonLT: ;
+      TSBHit.hButtonRB: ;
+      TSBHit.hThumb:
         begin
           SetPointerCapture((MouseEvt as TFresnelMouseDownEvent).PointerId);
           exit;
         end;
-      THit.hTrackLT:
+      TSBHit.hTrackLT:
         // scroll one page left/top
         NewPos:=Position-Page;
-      THit.hTrackRB:
+      TSBHit.hTrackRB:
         // scroll one page right/bottom
         NewPos:=Position+Page;
       else exit;
@@ -451,11 +459,11 @@ begin
     if (MouseEvt.Button=mbLeft) then
     begin
       Hit:=GetHit(X,Y,p);
-      if Hit=THit.hNone then ;
+      if Hit=TSBHit.hNone then ;
       {$IFDEF VerboseFresnelScrolling}
       writeln('TRendererScrollBar.MouseHandler Mouse Move ',Parent.Name,' Horz=',Horizontal,' Hit=',Hit,' p=',FloatToCSSStr(p),' GrabPos=',FloatToCSSStr(MouseDownGrabPos));
       {$ENDIF}
-      if MouseDownHit=THit.hThumb then
+      if MouseDownHit=TSBHit.hThumb then
       begin
         // move thumb
         NewPos:=MouseDownPosition+(p-MouseDownGrabPos);
@@ -471,7 +479,7 @@ begin
       writeln('TRendererScrollBar.MouseHandler Mouse Up ',Parent.Name,' Horz=',Horizontal,' Hit=',Hit,' p=',FloatToCSSStr(p));
       {$ENDIF}
       MouseDownGrabPos:=0;
-      MouseDownHit:=THit.hNone;
+      MouseDownHit:=TSBHit.hNone;
       ReleasePointerCapture((MouseEvt as TFresnelMouseUpEvent).PointerId);
     end;
   end;
@@ -485,85 +493,237 @@ begin
   AddEventListener(evtMouseUp,@MouseHandler);
 end;
 
-procedure TRendererScrollBar.Draw(Renderer: TFresnelRenderer);
+procedure TRendererScrollBar.Layout;
 var
-  CurTrackColor, CurThumbColor: TFPColor;
-  FromPos, ToPos, l, Radius: TFresnelLength;
   r: TFresnelRect;
-  ThumbR: TFresnelRoundRect;
-  c: TFresnelCSSCorner;
+  aBarLength, aBarWidth, BtnSize, FromPos, ToPos, l: TFresnelLength;
 begin
   r:=Box;
+  ThumbArea:=Default(TFresnelRect);
+  TrackArea:=Default(TFresnelRect);
+  ButtonLT:=Default(TFresnelRect);
+  ButtonRB:=Default(TFresnelRect);
+  Padding:=0;
 
-  GetColors(CurThumbColor,CurTrackColor);
-  // draw track
-  Renderer.FillRect(CurTrackColor,r);
-  if Size<1 then
-    exit;
+  if r.IsEmpty then exit;
+
+  if Horizontal then
+  begin
+    aBarLength:=r.Width;
+    aBarWidth:=r.Height;
+  end else begin
+    aBarLength:=r.Height;
+    aBarWidth:=r.Width;
+  end;
+  Padding:=round(Min(aBarLength,aBarWidth)/6);
+
+  if Viewport.ScrollbarsHaveButtons then
+  begin
+    BtnSize:=Min(aBarLength/2,aBarWidth)-2*Padding;
+    if BtnSize<1 then exit;
+    if Horizontal then
+    begin
+      ButtonLT.Left:=r.Left+Padding;
+      ButtonLT.Right:=ButtonLT.Left+BtnSize;
+      ButtonLT.Top:=r.Top+(aBarWidth-BtnSize)/2;
+      ButtonLT.Bottom:=ButtonLT.Top+BtnSize;
+
+      ButtonRB.Right:=r.Right-Padding;
+      ButtonRB.Left:=ButtonRB.Right-BtnSize;
+      ButtonRB.Top:=ButtonLT.Top;
+      ButtonRB.Bottom:=ButtonLT.Bottom;
+
+      TrackArea.Left:=ButtonLT.Right+Padding;
+      TrackArea.Right:=ButtonRB.Left-Padding;
+      TrackArea.Top:=r.Top+Padding;
+      TrackArea.Bottom:=r.Bottom-Padding;
+    end else begin
+      ButtonLT.Left:=r.Left+(aBarWidth-BtnSize)/2;
+      ButtonLT.Right:=ButtonLT.Left+BtnSize;
+      ButtonLT.Top:=r.Top+Padding;
+      ButtonLT.Bottom:=ButtonLT.Top+BtnSize;
+
+      ButtonRB.Left:=ButtonLT.Left;
+      ButtonRB.Right:=ButtonLT.Right;
+      ButtonRB.Bottom:=r.Bottom-Padding;
+      ButtonRB.Top:=ButtonRB.Bottom-BtnSize;
+
+      TrackArea.Left:=r.Left+Padding;
+      TrackArea.Right:=r.Right-Padding;
+      TrackArea.Top:=ButtonLT.Bottom+Padding;
+      TrackArea.Bottom:=ButtonRB.Top-Padding;
+    end;
+  end else begin
+    TrackArea.Left:=r.Left+Padding;
+    TrackArea.Top:=r.Top+Padding;
+    TrackArea.Right:=r.Right-Padding;
+    TrackArea.Bottom:=r.Bottom-Padding;
+  end;
+  if TrackArea.IsEmpty then
+    TrackArea:=Default(TFresnelRect);
 
-  // draw thumb
   FromPos:=Position/Size;
   if FromPos<0 then FromPos:=0;
   if FromPos>1 then FromPos:=1;
   ToPos:=(Position+Page)/Size;
   if ToPos<0 then ToPos:=0;
   if ToPos>1 then ToPos:=1;
+
+  ThumbArea:=TrackArea;
   if Horizontal then
   begin
-    if r.Width<r.Height then exit;
-    Border:=round(r.Height/6);
+    l:=ThumbArea.Width;
+    FromPos:=FromPos*l;
+    ToPos:=ToPos*l;
+    ThumbArea.Left:=ThumbArea.Left+FromPos;
+    ThumbArea.Right:=ThumbArea.Left+ToPos-FromPos;
   end else begin
-    if r.Height<r.Width then exit;
-    Border:=round(r.Width/6);
+    l:=ThumbArea.Height;
+    FromPos:=FromPos*l;
+    ToPos:=ToPos*l;
+    ThumbArea.Top:=ThumbArea.Top+FromPos;
+    ThumbArea.Bottom:=ThumbArea.Top+ToPos-FromPos;
   end;
-  Radius:=Border*2;
-  for c in TFresnelCSSCorner do begin
-    ThumbR.Radii[c].X:=Radius;
-    ThumbR.Radii[c].Y:=Radius;
+end;
+
+procedure TRendererScrollBar.Draw(Renderer: TFresnelRenderer);
+var
+  FromPos, ToPos, l, RadiusX, RadiusY: TFresnelLength;
+  r: TFresnelRect;
+  ThumbR: TFresnelRoundRect;
+  c: TFresnelCSSCorner;
+begin
+  Layout;
+  r:=Box;
+
+  // draw track
+  Renderer.FillRect(GetTrackColor,r);
+  if Size<1 then
+    exit;
+
+  //writeln('TRendererScrollBar.Draw Horz=',Horizontal,' Box=',Box.ToString,' ButtonLT=',ButtonLT.ToString,' Track=',TrackArea.ToString,' Thumb=',ThumbArea.ToString,' ButtonRB=',ButtonRB.ToString);
+
+  // draw thumb
+  if (ThumbArea.Width>=1) and (ThumbArea.Height>=1) then
+  begin
+    RadiusX:=Min(2*Padding,ThumbArea.Width/2);
+    RadiusY:=Min(2*Padding,ThumbArea.Height/2);
+    //writeln('TRendererScrollBar.Draw ',FloatToCSSStr(RadiusX),' Padding=',FloatToCSSStr(Padding));
+    if (RadiusX>1) and (RadiusY>1) then
+    begin
+      // round corners
+      ThumbR.Box:=ThumbArea;
+      for c in TFresnelCSSCorner do
+      begin
+        ThumbR.Radii[c].X:=RadiusX;
+        ThumbR.Radii[c].Y:=RadiusY;
+      end;
+      //writeln('TRendererScrollBar.Draw ROUND ',ThumbR.Box.ToString,' ',FloatToCSSStr(RadiusX));
+      Renderer.RoundRect(GetThumbColor,ThumbR,true);
+    end else begin
+      // rect
+      Renderer.FillRect(GetThumbColor,ThumbArea);
+    end;
   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 Horizontal then
+    DrawButton(Renderer,true);
+  //DrawButton(Renderer,false);
+end;
+
+procedure TRendererScrollBar.DrawButton(Renderer: TFresnelRenderer; LT: boolean);
+var
+  r: TFresnelRect;
+  p: TFresnelPointArray;
+  w, h: TFresnelLength;
+begin
+  // draw a triangular arrow, starting with the tip
+  p:=[];
+  SetLength(p,3);
+  if LT then
   begin
-    l:=ThumbR.Box.Width;
-    ThumbR.Box.Left:=ThumbR.Box.Left+FromPos*l;
-    ThumbR.Box.Right:=ThumbR.Box.Left+Max((ToPos-FromPos)*l,2*Radius);
-  end else begin
-    l:=ThumbR.Box.Height;
-    ThumbR.Box.Top:=ThumbR.Box.Top+FromPos*l;
-    ThumbR.Box.Bottom:=ThumbR.Box.Top+Max((ToPos-FromPOs)*l,2*Radius);
+    r:=ButtonLT;
+    w:=r.Right-r.Left;
+    h:=r.Bottom-r.Top;
+    if Horizontal then
+    begin
+      // left arrow
+      p[0].X:=r.Left+w/4;
+      p[0].Y:=r.Top+h/2;
+      p[1].X:=r.Right-w/4;
+      p[1].Y:=r.Top;
+      p[2].X:=p[1].X;
+      p[2].Y:=r.Bottom;
+    end else begin
+      // right arrow
+      p[0].X:=r.Right-w/4;
+      p[0].Y:=r.Top+h/2;
+      p[1].X:=r.Right-w/2;
+      p[1].Y:=r.Bottom;
+      p[2].X:=p[1].X;
+      p[2].Y:=r.Top;
+    end;
+  end
+  else begin
+    r:=ButtonRB;
+    if Horizontal then
+    begin
+      // top arrow
+      p[0].X:=r.Left+w/2;
+      p[0].Y:=r.Top+h/4;
+      p[1].X:=r.Right;
+      p[1].Y:=r.Bottom-h/4;
+      p[2].X:=r.Left;
+      p[2].Y:=p[1].Y;
+    end else begin
+      // bottom arrow
+      p[0].X:=r.Left+w/2;
+      p[0].Y:=r.Bottom-h/4;
+      p[1].X:=r.Left;
+      p[1].Y:=r.Top+h/4;
+      p[2].X:=r.Right;
+      p[2].Y:=p[1].Y;
+    end;
   end;
 
-  Renderer.RoundRect(CurThumbColor,ThumbR,true);
+  //writeln('TRendererScrollBar.DrawButton Horz=',Horizontal,' LT=',LT,' r=',r.ToString,' p0=',p[0].ToString,' ',p[1].ToString,' ',p[2].ToString);
+  Renderer.Polygon(GetThumbColor,@p[0],3);
 end;
 
 procedure TRendererScrollBar.DrawCorner(Renderer: TFresnelRenderer; const r: TFresnelRect);
-var
-  CurThumbColor, CurTrackColor: TFPColor;
 begin
-  GetColors(CurThumbColor,CurTrackColor);
-  Renderer.FillRect(CurTrackColor,r);
+  Renderer.FillRect(GetTrackColor,r);
 end;
 
-function TRendererScrollBar.GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): THit;
+function TRendererScrollBar.GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): TSBHit;
 var
-  LT, RB: TFresnelLength;
+  LT, RB, l: TFresnelLength;
 begin
-  Result:=THit.hNone;
+  Result:=TSBHit.hNone;
   aPosition:=0;
   if Horizontal then
   begin
-    LT:=Box.Left+Border;
-    RB:=Box.Right-Border;
-    if LT>RB-1 then exit;
-    aPosition:=(X-LT) / (RB-LT);
+    if (ButtonLT.Width>0) and (X<=ButtonLT.Right+Padding/2) then
+      exit(TSBHit.hButtonLT);
+    if (ButtonRB.Width>0) and (X>=ButtonRB.Left-Padding/2) then
+      exit(TSBHit.hButtonRB);
+    l:=TrackArea.Width;
+    if l<=0 then exit;
+    if l>=1 then
+      aPosition:=(X-TrackArea.Left) / l
+    else if X>Box.Right then
+      aPosition:=1;
   end else begin
-    LT:=Box.Top+Border;
-    RB:=Box.Bottom-Border;
-    if LT>RB-1 then exit;
-    aPosition:=(Y-LT) / (RB-LT);
+    if (ButtonLT.Height>0) and (Y<=ButtonLT.Bottom+Padding/2) then
+      exit(TSBHit.hButtonLT);
+    if (ButtonRB.Height>0) and (Y>=ButtonRB.Top-Padding/2) then
+      exit(TSBHit.hButtonRB);
+    l:=TrackArea.Height;
+    if l<=0 then exit;
+    if l>=1 then
+      aPosition:=(Y-TrackArea.Top) / l
+    else if Y>Box.Bottom then
+      aPosition:=1;
   end;
   if aPosition<0 then aPosition:=0;
   if aPosition>1 then aPosition:=1;
@@ -572,11 +732,11 @@ begin
   //writeln('TRendererScrollBar.GetHit Horz=',Horizontal,' aPosition=',FloatToCSSStr(aPosition),' Position=',FloatToCSSStr(Position),' Size=',FloatToCSSStr(Size),' LT=',FloatToCSSStr(LT),' RB=',FloatToCSSStr(RB),' Y=',FloatToCSSStr(Y));
 
   if aPosition<Position then
-    Result:=THit.hTrackLT
+    Result:=TSBHit.hTrackLT
   else if aPosition>=Position+Page then
-    Result:=THit.hTrackRB
+    Result:=TSBHit.hTrackRB
   else
-    Result:=THit.hThumb;
+    Result:=TSBHit.hThumb;
 end;
 
 { TFresnelRenderer }

+ 26 - 0
src/skia/fresnel.skiarenderer.pas

@@ -155,6 +155,7 @@ type
       const aImage: TFPCustomImage); override;
     procedure FillRect(const aColor: TFPColor; const aRect: TFresnelRect); override;
     procedure Line(const aColor: TFPColor; const x1, y1, x2, y2: TFresnelLength); override;
+    procedure Polygon(const aColor: TFPColor; const p: PFresnelPoint; Count: integer); override;
     procedure Restore; override;
     procedure RoundRect(const aColor: TFPColor; const aRect: TFresnelRoundRect;
       Fill: Boolean); override;
@@ -803,6 +804,31 @@ begin
   Canvas.DrawLine(Origin.X+x1,Origin.Y+y1,Origin.X+x2,Origin.Y+y2, SkPaint);
 end;
 
+procedure TFresnelSkiaRenderer.Polygon(const aColor: TFPColor; const p: PFresnelPoint;
+  Count: integer);
+var
+  a: TPolygon;
+  SkPaint: ISkPaint;
+  i: Integer;
+  //SkPath: ISkPath;
+  //SkPathBuilder: ISkPathBuilder;
+begin
+  if Count<=2 then exit;
+  SkPaint:=TSkPaint.Create(TSkPaintStyle.Stroke);
+  SkPaint.setColor(FPColorToSkia(aColor));
+  SetLength(a{%H-},Count);
+  for i:=0 to Count-1 do
+  begin
+    a[i].x:=Origin.X+p[i].X;
+    a[i].y:=Origin.Y+p[i].Y;
+    //writeln('TFresnelSkiaRenderer.Polygon ',i,' ',FloatToCSSStr(a[i].X),',',FloatToCSSStr(a[i].Y));
+  end;
+  //SkPathBuilder:=TSkPathBuilder.Create;
+  //SkPathBuilder.AddPolygon(a,true);
+
+  Canvas.DrawPoints(TSkDrawPointsMode.Polygon,a,SkPaint);
+end;
+
 procedure TFresnelSkiaRenderer.Restore;
 begin
   Canvas.Restore;