瀏覽代碼

scrollbar-color

mattias 4 月之前
父節點
當前提交
9ee2c5046b

+ 0 - 1
demo/Edit/editdemolcl.lpi

@@ -10,7 +10,6 @@
       </Flags>
       </Flags>
       <SessionStorage Value="InProjectDir"/>
       <SessionStorage Value="InProjectDir"/>
       <Title Value="EditDemoLCL"/>
       <Title Value="EditDemoLCL"/>
-      <UseAppBundle Value="False"/>
       <ResourceType Value="res"/>
       <ResourceType Value="res"/>
       <Icon Value="0"/>
       <Icon Value="0"/>
     </General>
     </General>

+ 1 - 1
demo/RadioGroup/.gitignore

@@ -1,2 +1,2 @@
 RadioGroupDemo1
 RadioGroupDemo1
-RadioGroupLCLDemo1
+RadioGroupDemoLCL1

二進制
demo/RadioGroup/RadioGroupDemoLCL1


+ 0 - 3
demo/RadioGroup/RadioGroupDemoLCL1.lpi

@@ -14,9 +14,6 @@
     </General>
     </General>
     <BuildModes>
     <BuildModes>
       <Item Name="Default" Default="True"/>
       <Item Name="Default" Default="True"/>
-      <SharedMatrixOptions Count="1">
-        <Item1 ID="000962466024" Type="IDEMacro" MacroName="FresnelLCLRenderer" Value="skia"/>
-      </SharedMatrixOptions>
     </BuildModes>
     </BuildModes>
     <PublishOptions>
     <PublishOptions>
       <Version Value="2"/>
       <Version Value="2"/>

+ 13 - 8
demo/ScrollBox/MainUnit.lfm

@@ -43,14 +43,14 @@ object MainForm: TMainForm
         Caption = 'visible'
         Caption = 'visible'
         OnClick = OnOverflowXClicked
         OnClick = OnOverflowXClicked
       end
       end
-      object OverflowXHidden: TDemoRadioButton
-        Caption = 'hidden'
-        OnClick = OnOverflowXClicked
-      end
       object OverflowXClip: TDemoRadioButton
       object OverflowXClip: TDemoRadioButton
         Caption = 'clip'
         Caption = 'clip'
         OnClick = OnOverflowXClicked
         OnClick = OnOverflowXClicked
       end
       end
+      object OverflowXHidden: TDemoRadioButton
+        Caption = 'hidden'
+        OnClick = OnOverflowXClicked
+      end
       object OverflowXScroll: TDemoRadioButton
       object OverflowXScroll: TDemoRadioButton
         Caption = 'scroll'
         Caption = 'scroll'
         OnClick = OnOverflowXClicked
         OnClick = OnOverflowXClicked
@@ -71,14 +71,14 @@ object MainForm: TMainForm
         Caption = 'visible'
         Caption = 'visible'
         OnClick = OnOverflowYClicked
         OnClick = OnOverflowYClicked
       end
       end
-      object OverflowYHidden: TDemoRadioButton
-        Caption = 'hidden'
-        OnClick = OnOverflowYClicked
-      end
       object OverflowYClip: TDemoRadioButton
       object OverflowYClip: TDemoRadioButton
         Caption = 'clip'
         Caption = 'clip'
         OnClick = OnOverflowYClicked
         OnClick = OnOverflowYClicked
       end
       end
+      object OverflowYHidden: TDemoRadioButton
+        Caption = 'hidden'
+        OnClick = OnOverflowYClicked
+      end
       object OverflowYScroll: TDemoRadioButton
       object OverflowYScroll: TDemoRadioButton
         Caption = 'scroll'
         Caption = 'scroll'
         OnClick = OnOverflowYClicked
         OnClick = OnOverflowYClicked
@@ -110,6 +110,11 @@ object MainForm: TMainForm
         Caption = 'RTL (direction)'
         Caption = 'RTL (direction)'
         OnClick = OnRTLClicked
         OnClick = OnRTLClicked
       end
       end
+      object BothEdgesCheckBox: TDemoCheckBox
+        Style = 'margin: 6px;'
+        Caption = 'Both Edges (scrollbar-gutter)'
+        OnClick = OnBothEdgesClicked
+      end
     end
     end
   end
   end
 end
 end

+ 19 - 4
demo/ScrollBox/MainUnit.pas

@@ -38,6 +38,7 @@ type
     OverlayCheckBox: TDemoCheckBox;
     OverlayCheckBox: TDemoCheckBox;
     ThinCheckBox: TDemoCheckBox;
     ThinCheckBox: TDemoCheckBox;
     RTLCheckBox: TDemoCheckBox;
     RTLCheckBox: TDemoCheckBox;
+    BothEdgesCheckBox: TDemoCheckBox;
     procedure MainFormCreate(Sender: TObject);
     procedure MainFormCreate(Sender: TObject);
     procedure OnAutoHideClicked(Event : TAbstractEvent);
     procedure OnAutoHideClicked(Event : TAbstractEvent);
     procedure OnOverflowXClicked(Event : TAbstractEvent);
     procedure OnOverflowXClicked(Event : TAbstractEvent);
@@ -45,8 +46,10 @@ type
     procedure OnOverlayClicked(Event : TAbstractEvent);
     procedure OnOverlayClicked(Event : TAbstractEvent);
     procedure OnThinClicked(Event : TAbstractEvent);
     procedure OnThinClicked(Event : TAbstractEvent);
     procedure OnRTLClicked(Event : TAbstractEvent);
     procedure OnRTLClicked(Event : TAbstractEvent);
+    procedure OnBothEdgesClicked(Event : TAbstractEvent);
   private
   private
   public
   public
+    procedure ApplyScrollbarGutter;
   end;
   end;
 
 
 var
 var
@@ -71,10 +74,7 @@ begin
 
 
   // todo: step buttons
   // todo: step buttons
   // todo: stable
   // todo: stable
-  // todo: both edges
-  // todo: css color
-  // todo: default thumb+track color, hover/not hover
-  // todo: rtl
+  // todo: scrollbar-color: red #f004
 end;
 end;
 
 
 procedure TMainForm.OnAutoHideClicked(Event: TAbstractEvent);
 procedure TMainForm.OnAutoHideClicked(Event: TAbstractEvent);
@@ -121,5 +121,20 @@ begin
     ScrollDiv1.SetStyleAttr('direction','');
     ScrollDiv1.SetStyleAttr('direction','');
 end;
 end;
 
 
+procedure TMainForm.OnBothEdgesClicked(Event: TAbstractEvent);
+begin
+  ApplyScrollbarGutter;
+end;
+
+procedure TMainForm.ApplyScrollbarGutter;
+var
+  s: String;
+begin
+  s:='';
+  if BothEdgesCheckBox.Checked then
+    s:=s+' both-edges';
+  ScrollDiv1.SetStyleAttr('scrollbar-gutter',s);
+end;
+
 end.
 end.
 
 

+ 0 - 6
demo/lcl/ButtonGenerator/ButtonGeneratorLCLDemo.lpi

@@ -45,12 +45,6 @@
         <Filename Value="ButtonGeneratorLCLDemo.lpr"/>
         <Filename Value="ButtonGeneratorLCLDemo.lpr"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>
       </Unit>
       </Unit>
-      <Unit>
-        <Filename Value="UnitLCLForm1.pas"/>
-        <IsPartOfProject Value="True"/>
-        <ComponentName Value="Form1"/>
-        <ResourceBaseClass Value="Form"/>
-      </Unit>
       <Unit>
       <Unit>
         <Filename Value="FresForm1.pas"/>
         <Filename Value="FresForm1.pas"/>
         <IsPartOfProject Value="True"/>
         <IsPartOfProject Value="True"/>

+ 1 - 2
demo/lcl/ButtonGenerator/ButtonGeneratorLCLDemo.lpr

@@ -10,7 +10,7 @@ uses
   athreads,
   athreads,
   {$ENDIF}
   {$ENDIF}
   Interfaces, // this includes the LCL widgetset
   Interfaces, // this includes the LCL widgetset
-  Forms, UnitLCLForm1, FresForm1,
+  Forms, FresForm1,
   Fresnel
   Fresnel
   { you can add units after this };
   { you can add units after this };
 
 
@@ -20,7 +20,6 @@ begin
   RequireDerivedFormResource:=True;
   RequireDerivedFormResource:=True;
   Application.Scaled:=True;
   Application.Scaled:=True;
   Application.Initialize;
   Application.Initialize;
-  Application.CreateForm(TForm1, Form1);
   Application.CreateForm(TFresnelForm1, FresnelForm1);
   Application.CreateForm(TFresnelForm1, FresnelForm1);
   Application.Run;
   Application.Run;
 end.
 end.

+ 3 - 2
demo/lcl/ButtonGenerator/FresForm1.lfm

@@ -1,7 +1,8 @@
 object FresnelForm1: TFresnelForm1
 object FresnelForm1: TFresnelForm1
   FormLeft = 274
   FormLeft = 274
-  FormTop = 225
+  FormTop = 125
   FormWidth = 395
   FormWidth = 395
-  FormHeight = 620
+  FormHeight = 630
   OnCreate = FresnelForm1Create
   OnCreate = FresnelForm1Create
+  Visible = true
 end
 end

+ 2 - 2
demo/lcl/ButtonGenerator/FresForm1.pas

@@ -5,8 +5,7 @@ unit FresForm1;
 interface
 interface
 
 
 uses
 uses
-  Classes, SysUtils, Fresnel.Forms, Fresnel.DOM,
-    Fresnel.Controls, DemoButtonGenerator;
+  Classes, SysUtils, Fresnel.Forms, Fresnel.DOM, Fresnel.Controls, DemoButtonGenerator;
 
 
 type
 type
 
 
@@ -33,6 +32,7 @@ begin
   ButtonGenerator:=TDemoButtonGenerator.Create(Self);
   ButtonGenerator:=TDemoButtonGenerator.Create(Self);
   with ButtonGenerator do begin
   with ButtonGenerator do begin
     Name:='ButtonGenerator';
     Name:='ButtonGenerator';
+    Style:='font-size: 14px;';
     Parent:=Self;
     Parent:=Self;
   end;
   end;
 end;
 end;

+ 1 - 1
design/fresnel.register.pas

@@ -48,7 +48,7 @@ type
     constructor Create(AOwner: TComponent); override;
     constructor Create(AOwner: TComponent); override;
     destructor Destroy; override;
     destructor Destroy; override;
     function ComponentAtPos(p: TPoint; MinClass: TComponentClass;
     function ComponentAtPos(p: TPoint; MinClass: TComponentClass;
-                                Flags: TDMCompAtPosFlags): TComponent; override;
+                            Flags: TDMCompAtPosFlags): TComponent; override;
     function ComponentIsIcon(AComponent: TComponent): boolean; override;
     function ComponentIsIcon(AComponent: TComponent): boolean; override;
     function ComponentIsVisible(AComponent: TComponent): Boolean; override;
     function ComponentIsVisible(AComponent: TComponent): Boolean; override;
     function GetComponentOriginOnForm(AComponent: TComponent): TPoint; override;
     function GetComponentOriginOnForm(AComponent: TComponent): TPoint; override;

+ 124 - 27
src/base/fresnel.dom.pas

@@ -1470,6 +1470,8 @@ type
     function GetComputedBorderWidth(Attr: TFresnelCSSAttribute): TFresnelLength; virtual;
     function GetComputedBorderWidth(Attr: TFresnelCSSAttribute): TFresnelLength; virtual;
     function GetComputedBorderRadius(Corner: TFresnelCSSCorner): TFresnelPoint; virtual; // on fail returns 0
     function GetComputedBorderRadius(Corner: TFresnelCSSCorner): TFresnelPoint; virtual; // on fail returns 0
     function GetComputedColor(Attr: TFresnelCSSAttribute; const CurrentColor: TFPColor): TFPColor; virtual; // on fail returns transparent
     function GetComputedColor(Attr: TFresnelCSSAttribute; const CurrentColor: TFPColor): TFPColor; virtual; // on fail returns transparent
+    function GetComputedColorValue(const s: string; const CurComp: TCSSResCompValue; out Col: TFPColor): boolean; virtual;
+    function GetComputedScrollbarColor(out aThumbColor, aTrackColor: TFPColor): boolean; virtual;
     function GetComputedKeyword(Attr: TFresnelCSSAttribute; const AllowedKeywords: TCSSNumericalIDArray): TCSSNumericalID; virtual;
     function GetComputedKeyword(Attr: TFresnelCSSAttribute; const AllowedKeywords: TCSSNumericalIDArray): TCSSNumericalID; virtual;
     function GetComputedJustifyContent(out SubKW: TCSSNumericalID): TCSSNumericalID; virtual;
     function GetComputedJustifyContent(out SubKW: TCSSNumericalID): TCSSNumericalID; virtual;
     function GetComputedJustifyItems(out SubKW: TCSSNumericalID): TCSSNumericalID; virtual;
     function GetComputedJustifyItems(out SubKW: TCSSNumericalID): TCSSNumericalID; virtual;
@@ -1604,12 +1606,14 @@ type
                               // can be negative or bigger than Size
                               // can be negative or bigger than Size
     Size: TFresnelLength; // ScrollWidth/Height
     Size: TFresnelLength; // ScrollWidth/Height
     Page: TFresnelLength; // ClientWidth/Height
     Page: TFresnelLength; // ClientWidth/Height
-    Color: TFPColor;
+    HasColor: boolean;
+    ThumbColor, TrackColor: TFPColor;
     Box: TFresnelRect; // same coord system as parent, e.g. parent.UsedBorderBox
     Box: TFresnelRect; // same coord system as parent, e.g. parent.UsedBorderBox
     MouseDownHit: THit;
     MouseDownHit: THit;
     MouseDownPosition, MouseDownGrabPos: TFresnelLength;
     MouseDownPosition, MouseDownGrabPos: TFresnelLength;
     constructor Create(TheElement: TFresnelElement; aHorizontal: boolean); overload;
     constructor Create(TheElement: TFresnelElement; aHorizontal: boolean); overload;
     function GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): THit; virtual; abstract;
     function GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): THit; virtual; abstract;
+    procedure GetColors(out CurThumbColor, CurTrackColor: TFPColor);
     property Horizontal: boolean read FHorizontal;
     property Horizontal: boolean read FHorizontal;
   end;
   end;
 
 
@@ -1652,6 +1656,14 @@ type
     );
     );
   TFresnelViewportLengths = set of TFresnelViewportLength;
   TFresnelViewportLengths = set of TFresnelViewportLength;
 
 
+  TFresnelScrollbarColor = (
+    vscThumbNormal,
+    vscThumbHover,
+    vscTrackNormal,
+    vscTrackHover
+    );
+  TFresnelScrollbarColors = set of TFresnelScrollbarColor;
+
   { TFresnelViewport }
   { TFresnelViewport }
 
 
   TFresnelViewport = class(TFresnelElement)
   TFresnelViewport = class(TFresnelElement)
@@ -1665,16 +1677,20 @@ type
     FOnDomChanged: TNotifyEvent;
     FOnDomChanged: TNotifyEvent;
     FScrollbarsAutoHide: boolean;
     FScrollbarsAutoHide: boolean;
     FScrollbarsOverlay: boolean;
     FScrollbarsOverlay: boolean;
-    FScrollbarThinWidth: array[boolean] of TFresnelLength;
-    FScrollbarWidth: array[boolean] of TFresnelLength;
+    FScrollbarsThinWidth: array[boolean] of TFresnelLength;
+    FScrollbarsWidth: array[boolean] of TFresnelLength;
+    FScrollbarsColor: array[TFresnelScrollbarColor] of TFPColor;
     FStylesheet: TStrings;
     FStylesheet: TStrings;
     FStylesheetResolverStamp: TCSSNumericalID;
     FStylesheetResolverStamp: TCSSNumericalID;
     FStylesheetStamp: TCSSNumericalID;
     FStylesheetStamp: TCSSNumericalID;
     FWidth: TFresnelLength;
     FWidth: TFresnelLength;
     procedure CSSResolverLog(Sender: TObject; Entry: TCSSResolverLogEntry);
     procedure CSSResolverLog(Sender: TObject; Entry: TCSSResolverLogEntry);
     function GetFocusedElement: TFresnelElement;
     function GetFocusedElement: TFresnelElement;
+    function GetScrollbarsColors(Col: TFresnelScrollbarColor): TFPColor;
     procedure SetFocusedElement(const aValue: TFresnelElement);
     procedure SetFocusedElement(const aValue: TFresnelElement);
     procedure SetScrollbarsAutoHide(AValue: boolean);
     procedure SetScrollbarsAutoHide(AValue: boolean);
+    procedure SetScrollbarsColors(Col: TFresnelScrollbarColor; AValue: TFPColor
+      );
   protected
   protected
     class var FFresnelEventsRegistered: boolean;
     class var FFresnelEventsRegistered: boolean;
   protected
   protected
@@ -1802,10 +1818,13 @@ type
     function WSInput(WSData: TFresnelInputEventInit) : boolean; virtual;
     function WSInput(WSData: TFresnelInputEventInit) : boolean; virtual;
     property VPApplication: IFresnelVPApplication read FVPApplication;
     property VPApplication: IFresnelVPApplication read FVPApplication;
     property DPI[IsHorizontal: boolean]: TFresnelLength read GetDPI write SetDPI;
     property DPI[IsHorizontal: boolean]: TFresnelLength read GetDPI write SetDPI;
+
     property ScrollbarsAutoHide: boolean read FScrollbarsAutoHide write SetScrollbarsAutoHide;
     property ScrollbarsAutoHide: boolean read FScrollbarsAutoHide write SetScrollbarsAutoHide;
     property ScrollbarsOverlay: boolean read FScrollbarsOverlay write SetScrollbarsOverlay;
     property ScrollbarsOverlay: boolean read FScrollbarsOverlay write SetScrollbarsOverlay;
     property ScrollbarsWidth[IsHorizontal: boolean]: TFresnelLength read GetScrollbarsWidth write SetScrollbarsWidth;
     property ScrollbarsWidth[IsHorizontal: boolean]: TFresnelLength read GetScrollbarsWidth write SetScrollbarsWidth;
     property ScrollbarsThinWidth[IsHorizontal: boolean]: TFresnelLength read GetScrollbarsThinWidth write SetScrollbarsThinWidth;
     property ScrollbarsThinWidth[IsHorizontal: boolean]: TFresnelLength read GetScrollbarsThinWidth write SetScrollbarsThinWidth;
+    property ScrollbarsColors[Col: TFresnelScrollbarColor]: TFPColor read GetScrollbarsColors write SetScrollbarsColors;
+
     property VPLength[l: TFresnelViewportLength]: TFresnelLength read GetVPLength write SetVPLength;
     property VPLength[l: TFresnelViewportLength]: TFresnelLength read GetVPLength write SetVPLength;
     property Resolver: TCSSResolver read FResolver;
     property Resolver: TCSSResolver read FResolver;
     property Stylesheet: TStrings read FStylesheet write SetStylesheet; // CSS origin author
     property Stylesheet: TStrings read FStylesheet write SetStylesheet; // CSS origin author
@@ -2855,7 +2874,7 @@ begin
     Result:=Resolver.CurComp.Kind=rvkNone;
     Result:=Resolver.CurComp.Kind=rvkNone;
     exit;
     exit;
   end;
   end;
-  // check for two colors
+  // check for exactly two colors
   for i:=1 to 2 do
   for i:=1 to 2 do
   begin
   begin
     if IsColor(Resolver.CurComp) then
     if IsColor(Resolver.CurComp) then
@@ -2865,6 +2884,7 @@ begin
       exit(true)
       exit(true)
     else
     else
       exit; // todo warn
       exit; // todo warn
+    Resolver.ReadNext;
   end;
   end;
   Result:=Resolver.CurComp.Kind=rvkNone;
   Result:=Resolver.CurComp.Kind=rvkNone;
 end;
 end;
@@ -6619,6 +6639,27 @@ begin
     Parent.FScrollBarVertical:=Self;
     Parent.FScrollBarVertical:=Self;
 end;
 end;
 
 
+procedure TPseudoElScrollBar.GetColors(out CurThumbColor,
+  CurTrackColor: TFPColor);
+var
+  ElHovered: Boolean;
+begin
+  ElHovered:=Parent.IsHovered;
+  if HasColor then
+    CurTrackColor:=TrackColor
+  else if ElHovered then
+    CurTrackColor:=Viewport.ScrollbarsColors[vscTrackHover]
+  else
+    CurTrackColor:=Viewport.ScrollbarsColors[vscTrackNormal];
+
+  if HasColor then
+    CurThumbColor:=ThumbColor
+  else if ElHovered then
+    CurThumbColor:=Viewport.ScrollbarsColors[vscThumbHover]
+  else
+    CurThumbColor:=Viewport.ScrollbarsColors[vscThumbNormal];
+end;
+
 { TFresnelFontDesc }
 { TFresnelFontDesc }
 
 
 function TFresnelFontDesc.Compare(const Desc: TFresnelFontDesc): integer;
 function TFresnelFontDesc.Compare(const Desc: TFresnelFontDesc): integer;
@@ -6671,6 +6712,12 @@ begin
   Result:=FFocusedElement;
   Result:=FFocusedElement;
 end;
 end;
 
 
+function TFresnelViewport.GetScrollbarsColors(Col: TFresnelScrollbarColor
+  ): TFPColor;
+begin
+  Result:=FScrollbarsColor[Col];
+end;
+
 procedure TFresnelViewport.SetFocusedElement(const aValue: TFresnelElement);
 procedure TFresnelViewport.SetFocusedElement(const aValue: TFresnelElement);
 begin
 begin
   TrySetFocusControl(aValue);
   TrySetFocusControl(aValue);
@@ -6683,6 +6730,14 @@ begin
   Invalidate;
   Invalidate;
 end;
 end;
 
 
+procedure TFresnelViewport.SetScrollbarsColors(Col: TFresnelScrollbarColor;
+  AValue: TFPColor);
+begin
+  if FScrollbarsColor[Col]=AValue then exit;
+  FScrollbarsColor[Col]:=AValue;
+  Invalidate;
+end;
+
 function TFresnelViewport.GetDPI(IsHorizontal: boolean): TFresnelLength;
 function TFresnelViewport.GetDPI(IsHorizontal: boolean): TFresnelLength;
 begin
 begin
   Result:=FDPI[IsHorizontal];
   Result:=FDPI[IsHorizontal];
@@ -6691,12 +6746,12 @@ end;
 function TFresnelViewport.GetScrollbarsWidth(IsHorizontal: boolean
 function TFresnelViewport.GetScrollbarsWidth(IsHorizontal: boolean
   ): TFresnelLength;
   ): TFresnelLength;
 begin
 begin
-  Result:=FScrollbarWidth[IsHorizontal];
+  Result:=FScrollbarsWidth[IsHorizontal];
 end;
 end;
 
 
 function TFresnelViewport.GetScrollbarsThinWidth(IsHorizontal: boolean): TFresnelLength;
 function TFresnelViewport.GetScrollbarsThinWidth(IsHorizontal: boolean): TFresnelLength;
 begin
 begin
-  Result:=FScrollbarThinWidth[IsHorizontal];
+  Result:=FScrollbarsThinWidth[IsHorizontal];
 end;
 end;
 
 
 function TFresnelViewport.GetHeight: TFresnelLength;
 function TFresnelViewport.GetHeight: TFresnelLength;
@@ -6711,10 +6766,10 @@ begin
   case l of
   case l of
     vlDPIHorizontal: Result:=FDPI[true];
     vlDPIHorizontal: Result:=FDPI[true];
     vlDPIVertical: Result:=FDPI[false];
     vlDPIVertical: Result:=FDPI[false];
-    vlHorizontalScrollbarWidth: Result:=FScrollbarWidth[true];
-    vlVerticalScrollbarWidth: Result:=FScrollbarWidth[false];
-    vlHorizontalScrollbarThinWidth: Result:=FScrollbarThinWidth[true];
-    vlVerticalScrollbarThinWidth: Result:=FScrollbarThinWidth[false];
+    vlHorizontalScrollbarWidth: Result:=FScrollbarsWidth[true];
+    vlVerticalScrollbarWidth: Result:=FScrollbarsWidth[false];
+    vlHorizontalScrollbarThinWidth: Result:=FScrollbarsThinWidth[true];
+    vlVerticalScrollbarThinWidth: Result:=FScrollbarsThinWidth[false];
   end;
   end;
 end;
 end;
 
 
@@ -6881,16 +6936,16 @@ end;
 procedure TFresnelViewport.SetScrollbarsWidth(IsHorizontal: boolean;
 procedure TFresnelViewport.SetScrollbarsWidth(IsHorizontal: boolean;
   const AValue: TFresnelLength);
   const AValue: TFresnelLength);
 begin
 begin
-  if FScrollbarWidth[IsHorizontal]=AValue then exit;
-  FScrollbarWidth[IsHorizontal]:=AValue;
+  if FScrollbarsWidth[IsHorizontal]=AValue then exit;
+  FScrollbarsWidth[IsHorizontal]:=AValue;
   DomChanged;
   DomChanged;
 end;
 end;
 
 
 procedure TFresnelViewport.SetScrollbarsThinWidth(IsHorizontal: boolean;
 procedure TFresnelViewport.SetScrollbarsThinWidth(IsHorizontal: boolean;
   const AValue: TFresnelLength);
   const AValue: TFresnelLength);
 begin
 begin
-  if FScrollbarThinWidth[IsHorizontal]=AValue then exit;
-  FScrollbarThinWidth[IsHorizontal]:=AValue;
+  if FScrollbarsThinWidth[IsHorizontal]=AValue then exit;
+  FScrollbarsThinWidth[IsHorizontal]:=AValue;
   DomChanged;
   DomChanged;
 end;
 end;
 
 
@@ -7626,6 +7681,8 @@ constructor TFresnelViewport.Create(AOwner: TComponent);
     TFresnelEventDispatcher.FresnelRegistry.RegisterEventWithID(aClass.FresnelEventID,aClass);
     TFresnelEventDispatcher.FresnelRegistry.RegisterEventWithID(aClass.FresnelEventID,aClass);
   end;
   end;
 
 
+var
+  c: TFPColor;
 begin
 begin
   inherited Create(AOwner);
   inherited Create(AOwner);
   FViewPort:=Self;
   FViewPort:=Self;
@@ -7633,10 +7690,18 @@ begin
   FHeight:=600;
   FHeight:=600;
   FDPI[false]:=FresnelDefaultDPI;
   FDPI[false]:=FresnelDefaultDPI;
   FDPI[true]:=FresnelDefaultDPI;
   FDPI[true]:=FresnelDefaultDPI;
-  FScrollbarWidth[False]:=12;
-  FScrollbarWidth[true]:=12;
-  FScrollbarThinWidth[False]:=6;
-  FScrollbarThinWidth[true]:=6;
+  FScrollbarsWidth[False]:=12;
+  FScrollbarsWidth[true]:=12;
+  FScrollbarsThinWidth[False]:=6;
+  FScrollbarsThinWidth[true]:=6;
+  c:=colDkGray;
+  FScrollbarsColor[vscThumbHover]:=c;
+  c.Alpha:=$8000;
+  FScrollbarsColor[vscThumbNormal]:=c;
+  c:=colLtGray;
+  FScrollbarsColor[vscTrackHover]:=c;
+  c.Alpha:=$8000;
+  FScrollbarsColor[vscTrackNormal]:=c;
 
 
   FResolver:=TCSSResolver.Create(nil);
   FResolver:=TCSSResolver.Create(nil);
   FResolver.OnLog:=@CSSResolverLog;
   FResolver.OnLog:=@CSSResolverLog;
@@ -8754,7 +8819,7 @@ function TFresnelElement.GetComputedColor(Attr: TFresnelCSSAttribute; const Curr
 var
 var
   Complete: boolean;
   Complete: boolean;
   CurComp: TCSSResCompValue;
   CurComp: TCSSResCompValue;
-  AttrID, KW: TCSSNumericalID;
+  AttrID: TCSSNumericalID;
   s: String;
   s: String;
 begin
 begin
   Result:=CurrentColor;
   Result:=CurrentColor;
@@ -8763,6 +8828,20 @@ begin
   CurComp.EndP:=PChar(s);
   CurComp.EndP:=PChar(s);
   if not Resolver.ReadComp(CurComp) then exit;
   if not Resolver.ReadComp(CurComp) then exit;
 
 
+  if GetComputedColorValue(s,CurComp,Result) then
+  begin
+    if not Resolver.ReadNext then
+      exit;
+  end;
+  Result:=CurrentColor;
+end;
+
+function TFresnelElement.GetComputedColorValue(const s: string;
+  const CurComp: TCSSResCompValue; out Col: TFPColor): boolean;
+var
+  KW: TCSSNumericalID;
+begin
+  Result:=false;
   case CurComp.Kind of
   case CurComp.Kind of
   rvkKeyword:
   rvkKeyword:
     begin
     begin
@@ -8770,12 +8849,9 @@ begin
       if (KW>=CSSRegistry.kwFirstColor)
       if (KW>=CSSRegistry.kwFirstColor)
           and (KW<=CSSRegistry.kwLastColor)
           and (KW<=CSSRegistry.kwLastColor)
       then begin
       then begin
-        //writeln('TFresnelElement.GetComputedColor ',s,' KW=',KW,' ',CSSRegistry.kwFirstColor,' ',CSSRegistry.kwLastColor, ' ',CSSRegistry.GetKeywordColor(KW));
-        Result:=FPColor(CSSRegistry.GetKeywordColor(KW));
-        exit;
+        Col:=FPColor(CSSRegistry.GetKeywordColor(KW));
+        exit(true);
       end;
       end;
-      if KW=CSSRegistry.kwCurrentcolor then
-        exit;
     end;
     end;
   rvkFunction:
   rvkFunction:
     begin
     begin
@@ -8783,13 +8859,34 @@ begin
     end;
     end;
   rvkHexColor:
   rvkHexColor:
     begin
     begin
-      if not CSSToFPColor(copy(s,CurComp.StartP-PChar(s),CurComp.EndP-CurComp.StartP),Result) then
-        Result:=CurrentColor;
-      exit;
+      Result:=CSSToFPColor(copy(s,CurComp.StartP-PChar(s)+1,CurComp.EndP-CurComp.StartP),Col);
     end;
     end;
   end;
   end;
 end;
 end;
 
 
+function TFresnelElement.GetComputedScrollbarColor(out aThumbColor,
+  aTrackColor: TFPColor): boolean;
+var
+  AttrID: TCSSNumericalID;
+  s: String;
+  CurComp: TCSSResCompValue;
+  Complete: boolean;
+begin
+  Result:=false;
+  aThumbColor:=colLtGray;
+  aTrackColor:=colGray;
+  AttrID:=CSSRegistry.FresnelAttrs[fcaScrollbarColor].Index;
+  s:=GetCSSString(AttrID,false,Complete);
+  CurComp.EndP:=PChar(s);
+  if not Resolver.ReadComp(CurComp) then exit;
+
+  if not GetComputedColorValue(s,CurComp,aThumbColor) then exit;
+  if not Resolver.ReadComp(CurComp) then exit;
+  if not GetComputedColorValue(s,CurComp,aTrackColor) then exit;
+  if Resolver.ReadComp(CurComp) then exit;
+  Result:=true;
+end;
+
 function TFresnelElement.GetComputedKeyword(Attr: TFresnelCSSAttribute;
 function TFresnelElement.GetComputedKeyword(Attr: TFresnelCSSAttribute;
   const AllowedKeywords: TCSSNumericalIDArray): TCSSNumericalID;
   const AllowedKeywords: TCSSNumericalIDArray): TCSSNumericalID;
 begin
 begin

+ 3 - 2
src/base/fresnel.forms.pas

@@ -508,7 +508,7 @@ begin
   //FLLog(etDebug,['TFresnelCustomForm.OnQueuedLayout ',Name,':',ClassName,' LayoutQueued=',BoolToStr(LayoutQueued,true)]);
   //FLLog(etDebug,['TFresnelCustomForm.OnQueuedLayout ',Name,':',ClassName,' LayoutQueued=',BoolToStr(LayoutQueued,true)]);
   if not LayoutQueued then exit;
   if not LayoutQueued then exit;
   try
   try
-    if WSForm=nil then
+    if (Designer=nil) and (WSForm=nil) then
       exit; // creating WSForm failed
       exit; // creating WSForm failed
     ApplyCSS;
     ApplyCSS;
     //Layouter.WriteLayoutTree;
     //Layouter.WriteLayoutTree;
@@ -637,7 +637,8 @@ procedure TFresnelCustomForm.SetPointerCapture(const aPointerId: TFreHandle);
 begin
 begin
   if csDestroying in ComponentState then
   if csDestroying in ComponentState then
     raise Exception.Create('20250324191514');
     raise Exception.Create('20250324191514');
-  WSForm.SetPointerCapture(aPointerId);
+  if WSFormAllocated then
+    WSForm.SetPointerCapture(aPointerId);
 end;
 end;
 
 
 procedure TFresnelCustomForm.ReleasePointerCapture(const aPointerId: TFreHandle);
 procedure TFresnelCustomForm.ReleasePointerCapture(const aPointerId: TFreHandle);

+ 9 - 18
src/base/fresnel.renderer.pas

@@ -487,28 +487,21 @@ end;
 
 
 procedure TRendererScrollBar.Draw(Renderer: TFresnelRenderer);
 procedure TRendererScrollBar.Draw(Renderer: TFresnelRenderer);
 var
 var
-  TrackColor, ThumbColor: TFPColor;
+  CurTrackColor, CurThumbColor: TFPColor;
   FromPos, ToPos, l, Radius: TFresnelLength;
   FromPos, ToPos, l, Radius: TFresnelLength;
   r: TFresnelRect;
   r: TFresnelRect;
   ThumbR: TFresnelRoundRect;
   ThumbR: TFresnelRoundRect;
   c: TFresnelCSSCorner;
   c: TFresnelCSSCorner;
-  ElHovered: Boolean;
 begin
 begin
   r:=Box;
   r:=Box;
-  ElHovered:=Parent.IsHovered;
 
 
+  GetColors(CurThumbColor,CurTrackColor);
   // draw track
   // draw track
-  TrackColor:=colLtGray;
-  if not Parent.IsHovered then
-    TrackColor.Alpha:=$8000;
-  Renderer.FillRect(TrackColor,r);
+  Renderer.FillRect(CurTrackColor,r);
   if Size<1 then
   if Size<1 then
     exit;
     exit;
 
 
   // draw thumb
   // draw thumb
-  ThumbColor:=colDkGray;
-  if not ElHovered then
-    ThumbColor.Alpha:=$8000;
   FromPos:=Position/Size;
   FromPos:=Position/Size;
   if FromPos<0 then FromPos:=0;
   if FromPos<0 then FromPos:=0;
   if FromPos>1 then FromPos:=1;
   if FromPos>1 then FromPos:=1;
@@ -543,17 +536,15 @@ begin
     ThumbR.Box.Bottom:=ThumbR.Box.Top+Max((ToPos-FromPOs)*l,2*Radius);
     ThumbR.Box.Bottom:=ThumbR.Box.Top+Max((ToPos-FromPOs)*l,2*Radius);
   end;
   end;
 
 
-  Renderer.RoundRect(ThumbColor,ThumbR,true);
+  Renderer.RoundRect(CurThumbColor,ThumbR,true);
 end;
 end;
 
 
 procedure TRendererScrollBar.DrawCorner(Renderer: TFresnelRenderer; const r: TFresnelRect);
 procedure TRendererScrollBar.DrawCorner(Renderer: TFresnelRenderer; const r: TFresnelRect);
 var
 var
-  TrackColor: TFPColor;
+  CurThumbColor, CurTrackColor: TFPColor;
 begin
 begin
-  TrackColor:=colLtGray;
-  if not Parent.IsHovered then
-    TrackColor.Alpha:=$8000;
-  Renderer.FillRect(TrackColor,r);
+  GetColors(CurThumbColor,CurTrackColor);
+  Renderer.FillRect(CurTrackColor,r);
 end;
 end;
 
 
 function TRendererScrollBar.GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): THit;
 function TRendererScrollBar.GetHit(const X, Y: TFresnelLength; out aPosition: TFresnelLength): THit;
@@ -770,7 +761,7 @@ begin
       aScrollbar.Page:=El.ClientHeight;
       aScrollbar.Page:=El.ClientHeight;
       aScrollbar.Position:=El.ScrollTop;
       aScrollbar.Position:=El.ScrollTop;
       aScrollbar.Box:=r;
       aScrollbar.Box:=r;
-      aScrollbar.Color:=El.GetComputedColor(fcaScrollbarColor,colGray);
+      aScrollbar.HasColor:=El.GetComputedScrollbarColor(aScrollbar.ThumbColor,aScrollbar.TrackColor);
 
 
       {$IFDEF VerboseFresnelScrolling}
       {$IFDEF VerboseFresnelScrolling}
       writeln('TFresnelRenderer.DrawScrollBars ',El.Name,' Vertical ScrollHeight=',FloatToCSSStr(El.ScrollHeight),' ClientHeight=',FloatToCSSStr(El.ClientHeight),' ScrollTop=',FloatToCSSStr(El.ScrollTop)+' BarWidth='+FloatToCSSStr(BarWidth)+' r='+r.ToString);
       writeln('TFresnelRenderer.DrawScrollBars ',El.Name,' Vertical ScrollHeight=',FloatToCSSStr(El.ScrollHeight),' ClientHeight=',FloatToCSSStr(El.ClientHeight),' ScrollTop=',FloatToCSSStr(El.ScrollTop)+' BarWidth='+FloatToCSSStr(BarWidth)+' r='+r.ToString);
@@ -804,7 +795,7 @@ begin
       else
       else
         aScrollbar.Position:=El.ScrollLeft;
         aScrollbar.Position:=El.ScrollLeft;
       aScrollbar.Box:=r;
       aScrollbar.Box:=r;
-      aScrollbar.Color:=El.GetComputedColor(fcaScrollbarColor,colGray);
+      aScrollbar.HasColor:=El.GetComputedScrollbarColor(aScrollbar.ThumbColor,aScrollbar.TrackColor);
 
 
       {$IFDEF VerboseFresnelScrolling}
       {$IFDEF VerboseFresnelScrolling}
       writeln('TFresnelRenderer.DrawScrollBars ',El.Name,' Horizontal ScrollWidth=',FloatToCSSStr(El.ScrollWidth),' ClientWidth=',FloatToCSSStr(El.ClientWidth),' ScrollLeft=',FloatToCSSStr(El.ScrollLeft)+' BarHeight='+FloatToCSSStr(BarHeight)+' r='+r.ToString);
       writeln('TFresnelRenderer.DrawScrollBars ',El.Name,' Horizontal ScrollWidth=',FloatToCSSStr(El.ScrollWidth),' ClientWidth=',FloatToCSSStr(El.ClientWidth),' ScrollLeft=',FloatToCSSStr(El.ScrollLeft)+' BarHeight='+FloatToCSSStr(BarHeight)+' r='+r.ToString);