Thanks mate, it will look better - I did have border radius working the other day but I'm currently refactoring the code (with the base property, sub-property logic) - the skin colours are also horrible, purely for testing the transition animations with high contrast
ProGUI V3 Alpha 3 Ready for testing!
Re: ProGUI V3 Alpha 3 Ready for testing!
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
- electrochrisso
- Addict
- Posts: 989
- Joined: Mon May 14, 2007 2:13 am
- Location: Darling River
Re: ProGUI V3 Alpha 3 Ready for testing!
The transitions look nice and smooth. 

PureBasic! Purely the best 

Re: ProGUI V3 Alpha 3 Ready for testing!
Cheers mate!


ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha 3 Ready for testing!
Hi guys!
So after 4 days of refactoring, the architecture is a lot simpler now and easier to understand and maintain. The new code can now handle missing state properties (so you no longer need to explicitly specify all the css for each state) you can just do a SkinSetValue("testContainer.testWidget", "active:border-radius", "20px") without needing pairing of the other states or specifying the base property (border).
The code now detects a base property such as "border" and any sub properties e.g. "border-radius", "border-xxx" with sub-properties sharing the base property memory. So now a single map lookup for WidgetGetSkinBorder(Widget, Property.s) instead of multiple map lookups inside that command for "border-radius", "border-top-left-radius" etc..
There's also a slight syntax change with a colon designating the state e.g SkinSetValue("testContainer.testWidget", "hover:border-radius", "20px"). Previously it was "hover.border-radius" however this was becoming difficult to parse with ambeguities such as "circle.background-color", "hover.circle.background-color" - is 'circle' a state? now "hover:circle.background-color". So that also matches web CSS syntax more closely too (for programmatically seting skin properties).
And now border-radius animation transitions are working!
- this example also demonstrates 3 state transitions for the first time: normal, hover and active (so pretty much a button
):
https://www.youtube.com/watch?v=K5oNEk_ipvI
What's nice is the 'background-color' of the red widgets only has a hover state of green yet animates correctly when the state gets set to 'active' (left mouse down).
Cheers!
Chris.
So after 4 days of refactoring, the architecture is a lot simpler now and easier to understand and maintain. The new code can now handle missing state properties (so you no longer need to explicitly specify all the css for each state) you can just do a SkinSetValue("testContainer.testWidget", "active:border-radius", "20px") without needing pairing of the other states or specifying the base property (border).
Code: Select all
SkinSetValue("testContainer.testWidget", "background-color", "red")
SkinSetValue("testContainer.testWidget", "hover:background-color", "rgb(0, 255, 0)")
SkinSetValue("testContainer.testWidget", "border", "3px solid blue")
SkinSetValue("testContainer.testWidget", "hover:border-radius", "10px")
SkinSetValue("testContainer.testWidget", "active:border-radius", "20px")
SkinSetValue("testContainer.testWidget", "transition", "background-color 2s, border 1s, border-radius 1s")
There's also a slight syntax change with a colon designating the state e.g SkinSetValue("testContainer.testWidget", "hover:border-radius", "20px"). Previously it was "hover.border-radius" however this was becoming difficult to parse with ambeguities such as "circle.background-color", "hover.circle.background-color" - is 'circle' a state? now "hover:circle.background-color". So that also matches web CSS syntax more closely too (for programmatically seting skin properties).
And now border-radius animation transitions are working!



https://www.youtube.com/watch?v=K5oNEk_ipvI
What's nice is the 'background-color' of the red widgets only has a hover state of green yet animates correctly when the state gets set to 'active' (left mouse down).
Cheers!
Chris.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha 3 Ready for testing!
https://www.youtube.com/shorts/lPKJU4H3JSY
Hi guys!
Another major refactor of the core skin engine (third time lucky!), I was running into some issues with animation jumping (with different duration sub property transistions). There were also some issues with compositing a new state based on missing skin properties and how to build the new state in a cascading fashion.
A major under-the-hood refactor is the new internal command:
So this allows a dynamic way to define skin property handlers of both base properties and sub-properties in a hierarchical way.
The current internal skin_Init() command currently looks like this:
So in the demo the CSS for that is (notice the different transition / animation durations for border-top-left-radius and border-bottom-right-radius):
Hi guys!
Another major refactor of the core skin engine (third time lucky!), I was running into some issues with animation jumping (with different duration sub property transistions). There were also some issues with compositing a new state based on missing skin properties and how to build the new state in a cascading fashion.
A major under-the-hood refactor is the new internal command:
Code: Select all
registerSkinPropertyHandler(*parentProperty, Property.s, type.i, sizeOfData.i, *ParseFunction.skin_ValueParser, *AllocateFunction.skin_DataAllocateFunction, *CopyFunction.skin_DataCopyFunction, *FreeFunction.skin_DataFreeFunction, *TransitionFunction.skin_DataTransitionFunction = #Null, isParentTransition.b = #False)
The current internal skin_Init() command currently looks like this:
Code: Select all
Procedure skin_Init()
initColorNames()
initTransitionFunctionNames()
initBorderStyleNames()
SkinMutex = CreateMutex()
mutexName("SkinMutex") = SkinMutex
registerSkinPropertyHandler(#Null, "transition", #PG_Skin_ValueType_Transition, SizeOf(SkinValueTransition), @skinParse_Transition(), @skinAllocate_Transition(), @skinCopy_Transition(), @skinFree_Transition())
*border = registerSkinPropertyHandler(#Null, "border", #PG_Skin_ValueType_Border, SizeOf(SkinValueBorder), @skinParse_Border(), @skinAllocate_Border(), @skinCopy_Border(), @skinFree_Border())
registerSkinPropertyHandler(*border, "border-style", #PG_Skin_ValueType_Border_Style, SizeOf(SkinValueBorder), @skinParse_Border_Style(), @skinAllocate_Border(), @skinCopy_Border_Style(), @skinFree_Border())
*radius = registerSkinPropertyHandler(*border, "border-radius", #PG_Skin_ValueType_Border_Radius, SizeOf(SkinValueBorder), @skinParse_Border_Radius(), @skinAllocate_Border(), @skinCopy_Border_Radius(), @skinFree_Border())
registerSkinPropertyHandler(*radius, "border-top-left-radius", #PG_Skin_ValueType_Border_Radius_TopLeft, SizeOf(SkinValueBorder), @skinParse_Border_Radius_TopLeft(), @skinAllocate_Border(), @skinCopy_Border_Radius_TopLeft(), @skinFree_Border(), @skinTransition_Border_Radius_TopLeft(), #True)
registerSkinPropertyHandler(*radius, "border-top-right-radius", #PG_Skin_ValueType_Border_Radius_TopRight, SizeOf(SkinValueBorder), @skinParse_Border_Radius_TopRight(), @skinAllocate_Border(), @skinCopy_Border_Radius_TopRight(), @skinFree_Border(), @skinTransition_Border_Radius_TopRight(), #True)
registerSkinPropertyHandler(*radius, "border-bottom-left-radius", #PG_Skin_ValueType_Border_Radius_BottomLeft, SizeOf(SkinValueBorder), @skinParse_Border_Radius_BottomLeft(), @skinAllocate_Border(), @skinCopy_Border_Radius_BottomLeft(), @skinFree_Border(), @skinTransition_Border_Radius_BottomLeft(), #True)
registerSkinPropertyHandler(*radius, "border-bottom-right-radius", #PG_Skin_ValueType_Border_Radius_BottomRight, SizeOf(SkinValueBorder), @skinParse_Border_Radius_BottomRight(), @skinAllocate_Border(), @skinCopy_Border_Radius_BottomRight(), @skinFree_Border(), @skinTransition_Border_Radius_BottomRight(), #True)
*color = registerSkinPropertyHandler(*border, "border-color", #PG_Skin_ValueType_Border_Color, SizeOf(SkinValueBorder), @skinParse_Border_Color(), @skinAllocate_Border(), @skinCopy_Border_Color(), @skinFree_Border(), #Null, #True)
registerSkinPropertyHandler(*color, "border-top-color", #PG_Skin_ValueType_Border_Top_Color, SizeOf(SkinValueBorder), @skinParse_Border_Top_Color(), @skinAllocate_Border(), @skinCopy_Border_Top_Color(), @skinFree_Border(), @skinTransition_Border_Top_Color(), #True)
registerSkinPropertyHandler(*color, "border-right-color", #PG_Skin_ValueType_Border_Right_Color, SizeOf(SkinValueBorder), @skinParse_Border_Right_Color(), @skinAllocate_Border(), @skinCopy_Border_Right_Color(), @skinFree_Border(), @skinTransition_Border_Right_Color(), #True)
registerSkinPropertyHandler(*color, "border-bottom-color", #PG_Skin_ValueType_Border_Bottom_Color, SizeOf(SkinValueBorder), @skinParse_Border_Bottom_Color(), @skinAllocate_Border(), @skinCopy_Border_Bottom_Color(), @skinFree_Border(), @skinTransition_Border_Bottom_Color(), #True)
registerSkinPropertyHandler(*color, "border-left-color", #PG_Skin_ValueType_Border_Left_Color, SizeOf(SkinValueBorder), @skinParse_Border_Left_Color(), @skinAllocate_Border(), @skinCopy_Border_Left_Color(), @skinFree_Border(), @skinTransition_Border_Left_Color(), #True)
registerSkinPropertyHandler(*border, "border-top-width", #PG_Skin_ValueType_Border_Top_Width, SizeOf(SkinValueBorder), @skinParse_Border_Top_Width(), @skinAllocate_Border(), @skinCopy_Border_Top_Width(), @skinFree_Border(), @skinTransition_Border_Top_Width(), #True)
registerSkinPropertyHandler(*border, "border-right-width", #PG_Skin_ValueType_Border_Right_Width, SizeOf(SkinValueBorder), @skinParse_Border_Right_Width(), @skinAllocate_Border(), @skinCopy_Border_Right_Width(), @skinFree_Border(), @skinTransition_Border_Right_Width(), #True)
registerSkinPropertyHandler(*border, "border-bottom-width", #PG_Skin_ValueType_Border_Bottom_Width, SizeOf(SkinValueBorder), @skinParse_Border_Bottom_Width(), @skinAllocate_Border(), @skinCopy_Border_Bottom_Width(), @skinFree_Border(), @skinTransition_Border_Bottom_Width(), #True)
registerSkinPropertyHandler(*border, "border-left-width", #PG_Skin_ValueType_Border_Left_Width, SizeOf(SkinValueBorder), @skinParse_Border_Left_Width(), @skinAllocate_Border(), @skinCopy_Border_Left_Width(), @skinFree_Border(), @skinTransition_Border_Left_Width(), #True)
Global ProGUI_DefaultSkin
ProGUI_DefaultSkin = CreateSkin("Default")
EndProcedure
Code: Select all
SkinSetValue("testContainer.testWidget", "background-color", "red")
SkinSetValue("testContainer.testWidget", "hover:background-color", "rgb(0, 255, 0)")
SkinSetValue("testContainer.testWidget", "border", "3px solid blue")
SkinSetValue("testContainer.testWidget", "border-left-width", "10px")
SkinSetValue("testContainer.testWidget", "border-color", "blue yellow")
SkinSetValue("testContainer.testWidget", "hover:border-radius", "10px")
SkinSetValue("testContainer.testWidget", "hover:border-top-left-radius", "40px 20px")
SkinSetValue("testContainer.testWidget", "hover:border-bottom-right-radius", "40px 20px")
SkinSetValue("testContainer.testWidget", "active:border", "20px double blue")
SkinSetValue("testContainer.testWidget", "active:border-top-left-radius", "40px 40px")
SkinSetValue("testContainer.testWidget", "active:border-color", "pink yellow purple red")
SkinSetValue("testContainer.testWidget", "transition", "background-color 2s, border 1s, border-radius 1s, border-top-left-radius 3s, border-bottom-right-radius 3s")
SkinSetValue("testContainer.testWidget", "hover:transition", "background-color .5s, border 1s ease-out-bounce, border-radius 1s ease-out-bounce")
Last edited by PrincieD on Tue Feb 04, 2025 2:26 am, edited 1 time in total.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha 3 Ready for testing!
So for "border-top-left-radius" the skin parse function looks like this:
The skin copy function:
And the transition (animation) function looks like this:
And for the WidgetGetSkinBorder(Widget, Property.s) function:
Code: Select all
Procedure skinParse_Border_Radius_TopLeft(value.s, *data.SkinValueBorder)
Protected.d rx, ry
*data\tLeftRx = #Null
*data\tLeftRy = #Null
If parseBorderRadiusRxRy(value, @rx, @ry)
*data\tLeftRx = rx
*data\tLeftRy = ry
ProcedureReturn #True
EndIf
ProcedureReturn #False
EndProcedure
Code: Select all
Procedure skinCopy_Border_Radius_TopLeft(*source.SkinValueBorder, *destination.SkinValueBorder)
*destination\tLeftRx = *source\tLeftRx
*destination\tLeftRy = *source\tLeftRy
EndProcedure
Code: Select all
Procedure skinTransition_Border_Radius_TopLeft(*transition, *start.SkinValueBorder, *end.SkinValueBorder, *current.SkinValueBorder)
*current\tLeftRx = transition_Function(*transition, *start\tLeftRx, *end\tLeftRx)
*current\tLeftRy = transition_Function(*transition, *start\tLeftRy, *end\tLeftRy)
EndProcedure
Code: Select all
ProcedureDLL WidgetGetSkinBorder(Widget, Property.s)
If Not Widget Or Property = ""
ProcedureReturn #False
EndIf
If WidgetGetSkinData(Widget, Property, @*border.SkinValueBorder, @valueType) And valueType = #PG_Skin_ValueType_Border
If Not *border\border
*border\border = CreateBorder()
EndIf
;If Not *border\style
; ProcedureReturn #Null
;EndIf
BorderSetFlags(*border\border, *border\style)
BorderSetWidth(*border\border, *border\lwidth, *border\twidth, *border\rwidth, *border\bwidth)
BorderSetColor(*border\border, *border\lColor, *border\lOpacity, *border\tColor, *border\tOpacity, *border\rColor, *border\rOpacity, *border\bColor, *border\bOpacity)
BorderSetRadius(*border\border, *border\tLeftRx, *border\tLeftRy, *border\tRightRx, *border\tRightRy, *border\bLeftRx, *border\bLeftRy, *border\bRightRx, *border\bRightRy)
ProcedureReturn *border\border
EndIf
ProcedureReturn #False
EndProcedure
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha 3 Ready for testing!
Another slight refactor of the skin engine internals:
Previously:
Currently:
There were some issues with the previous parent / child hierarchy of the property handlers and how CSS works. It mostly worked but then ran into issues with properties like 'border-top', 'border-color'. 'border-top-color' can be a child of 'border-top' but 'border-top' can't be a child of 'border-color' (because 'border-top' sets the top border style, color and width). So now the new registerSkinSubProperty() command has a cascade order parameter and if it has a transition function defined there is an optional transitionOrder string parameter that is a comma separated list of fall-back transition parameters that can animate it. For example:
First 'border-top-width' is checked in the transition property (SkinSetValue("testContainer.testWidget", "transition", "background-color 2s, border 1s, border-radius 1s, border-top-left-radius 3s, border-bottom-right-radius 3s")) then 'border-top', 'border-width' and 'border'.
You shouldn't have to worry about this at all but I will be opening up these commands down the line for advanced usage (you need custom skin property handlers for some reason).
Previously:
Code: Select all
registerSkinPropertyHandler(#Null, "transition", #PG_Skin_ValueType_Transition, SizeOf(SkinValueTransition), @skinParse_Transition(), @skinAllocate_Transition(), @skinCopy_Transition(), @skinFree_Transition())
*border = registerSkinPropertyHandler(#Null, "border", #PG_Skin_ValueType_Border, SizeOf(SkinValueBorder), @skinParse_Border(), @skinAllocate_Border(), @skinCopy_Border(), @skinFree_Border())
registerSkinPropertyHandler(*border, "border-style", #PG_Skin_ValueType_Border_Style, SizeOf(SkinValueBorder), @skinParse_Border_Style(), @skinAllocate_Border(), @skinCopy_Border_Style(), @skinFree_Border())
*radius = registerSkinPropertyHandler(*border, "border-radius", #PG_Skin_ValueType_Border_Radius, SizeOf(SkinValueBorder), @skinParse_Border_Radius(), @skinAllocate_Border(), @skinCopy_Border_Radius(), @skinFree_Border())
registerSkinPropertyHandler(*radius, "border-top-left-radius", #PG_Skin_ValueType_Border_Radius_TopLeft, SizeOf(SkinValueBorder), @skinParse_Border_Radius_TopLeft(), @skinAllocate_Border(), @skinCopy_Border_Radius_TopLeft(), @skinFree_Border(), @skinTransition_Border_Radius_TopLeft(), #True)
registerSkinPropertyHandler(*radius, "border-top-right-radius", #PG_Skin_ValueType_Border_Radius_TopRight, SizeOf(SkinValueBorder), @skinParse_Border_Radius_TopRight(), @skinAllocate_Border(), @skinCopy_Border_Radius_TopRight(), @skinFree_Border(), @skinTransition_Border_Radius_TopRight(), #True)
registerSkinPropertyHandler(*radius, "border-bottom-left-radius", #PG_Skin_ValueType_Border_Radius_BottomLeft, SizeOf(SkinValueBorder), @skinParse_Border_Radius_BottomLeft(), @skinAllocate_Border(), @skinCopy_Border_Radius_BottomLeft(), @skinFree_Border(), @skinTransition_Border_Radius_BottomLeft(), #True)
registerSkinPropertyHandler(*radius, "border-bottom-right-radius", #PG_Skin_ValueType_Border_Radius_BottomRight, SizeOf(SkinValueBorder), @skinParse_Border_Radius_BottomRight(), @skinAllocate_Border(), @skinCopy_Border_Radius_BottomRight(), @skinFree_Border(), @skinTransition_Border_Radius_BottomRight(), #True)
*color = registerSkinPropertyHandler(*border, "border-color", #PG_Skin_ValueType_Border_Color, SizeOf(SkinValueBorder), @skinParse_Border_Color(), @skinAllocate_Border(), @skinCopy_Border_Color(), @skinFree_Border(), #Null, #True)
registerSkinPropertyHandler(*color, "border-top-color", #PG_Skin_ValueType_Border_Top_Color, SizeOf(SkinValueBorder), @skinParse_Border_Top_Color(), @skinAllocate_Border(), @skinCopy_Border_Top_Color(), @skinFree_Border(), @skinTransition_Border_Top_Color(), #True)
registerSkinPropertyHandler(*color, "border-right-color", #PG_Skin_ValueType_Border_Right_Color, SizeOf(SkinValueBorder), @skinParse_Border_Right_Color(), @skinAllocate_Border(), @skinCopy_Border_Right_Color(), @skinFree_Border(), @skinTransition_Border_Right_Color(), #True)
registerSkinPropertyHandler(*color, "border-bottom-color", #PG_Skin_ValueType_Border_Bottom_Color, SizeOf(SkinValueBorder), @skinParse_Border_Bottom_Color(), @skinAllocate_Border(), @skinCopy_Border_Bottom_Color(), @skinFree_Border(), @skinTransition_Border_Bottom_Color(), #True)
registerSkinPropertyHandler(*color, "border-left-color", #PG_Skin_ValueType_Border_Left_Color, SizeOf(SkinValueBorder), @skinParse_Border_Left_Color(), @skinAllocate_Border(), @skinCopy_Border_Left_Color(), @skinFree_Border(), @skinTransition_Border_Left_Color(), #True)
registerSkinPropertyHandler(*border, "border-top-width", #PG_Skin_ValueType_Border_Top_Width, SizeOf(SkinValueBorder), @skinParse_Border_Top_Width(), @skinAllocate_Border(), @skinCopy_Border_Top_Width(), @skinFree_Border(), @skinTransition_Border_Top_Width(), #True)
registerSkinPropertyHandler(*border, "border-right-width", #PG_Skin_ValueType_Border_Right_Width, SizeOf(SkinValueBorder), @skinParse_Border_Right_Width(), @skinAllocate_Border(), @skinCopy_Border_Right_Width(), @skinFree_Border(), @skinTransition_Border_Right_Width(), #True)
registerSkinPropertyHandler(*border, "border-bottom-width", #PG_Skin_ValueType_Border_Bottom_Width, SizeOf(SkinValueBorder), @skinParse_Border_Bottom_Width(), @skinAllocate_Border(), @skinCopy_Border_Bottom_Width(), @skinFree_Border(), @skinTransition_Border_Bottom_Width(), #True)
registerSkinPropertyHandler(*border, "border-left-width", #PG_Skin_ValueType_Border_Left_Width, SizeOf(SkinValueBorder), @skinParse_Border_Left_Width(), @skinAllocate_Border(), @skinCopy_Border_Left_Width(), @skinFree_Border(), @skinTransition_Border_Left_Width(), #True)
Code: Select all
registerSkinProperty("transition", #PG_Skin_Type_Transition, SizeOf(SkinValueTransition), @skinParse_Transition(), @skinAllocate_Transition(), @skinCopy_Transition(), @skinFree_Transition())
*border = registerSkinProperty("border", #PG_Skin_Type_Border, SizeOf(SkinValueBorder), @skinParse_Border(), @skinAllocate_Border(), @skinCopy_Border(), @skinFree_Border())
registerSkinSubProperty(*border, "border-style", 1, @skinParse_Border_Style(), @skinCopy_Border_Style())
registerSkinSubProperty(*border, "border-top-style", 2, @skinParse_Border_Top_Style(), @skinCopy_Border_Style())
registerSkinSubProperty(*border, "border-right-style", 2, @skinParse_Border_Right_Style(), @skinCopy_Border_Style())
registerSkinSubProperty(*border, "border-bottom-style", 2, @skinParse_Border_Bottom_Style(), @skinCopy_Border_Style())
registerSkinSubProperty(*border, "border-left-style", 2, @skinParse_Border_Left_Style(), @skinCopy_Border_Style())
registerSkinSubProperty(*border, "border-radius", 1, @skinParse_Border_Radius(), @skinCopy_Border_Radius())
registerSkinSubProperty(*border, "border-top-left-radius", 2, @skinParse_Border_Radius_TopLeft(), @skinCopy_Border_Radius_TopLeft(), @skinTransition_Border_Radius_TopLeft(), "border-radius")
registerSkinSubProperty(*border, "border-top-right-radius", 2, @skinParse_Border_Radius_TopRight(), @skinCopy_Border_Radius_TopRight(), @skinTransition_Border_Radius_TopRight(), "border-radius")
registerSkinSubProperty(*border, "border-bottom-left-radius", 2, @skinParse_Border_Radius_BottomLeft(), @skinCopy_Border_Radius_BottomLeft(), @skinTransition_Border_Radius_BottomLeft(), "border-radius")
registerSkinSubProperty(*border, "border-bottom-right-radius", 2, @skinParse_Border_Radius_BottomRight(), @skinCopy_Border_Radius_BottomRight(), @skinTransition_Border_Radius_BottomRight(), "border-radius")
registerSkinSubProperty(*border, "border-color", 1, @skinParse_Border_Color(), @skinCopy_Border_Color())
registerSkinSubProperty(*border, "border-top", 2, @skinParse_Border_Top(), @skinCopy_Border_Top())
registerSkinSubProperty(*border, "border-top-color", 3, @skinParse_Border_Top_Color(), @skinCopy_Border_Top_Color(), @skinTransition_Border_Top_Color(), "border-top, border-color, border")
registerSkinSubProperty(*border, "border-right-color", 3, @skinParse_Border_Right_Color(), @skinCopy_Border_Right_Color(), @skinTransition_Border_Right_Color(), "border-right, border-color, border")
registerSkinSubProperty(*border, "border-bottom-color", 3, @skinParse_Border_Bottom_Color(), @skinCopy_Border_Bottom_Color(), @skinTransition_Border_Bottom_Color(), "border-bottom, border-color, border")
registerSkinSubProperty(*border, "border-left-color", 3, @skinParse_Border_Left_Color(), @skinCopy_Border_Left_Color(), @skinTransition_Border_Left_Color(), "border-left, border-color, border")
registerSkinSubProperty(*border, "border-top-width", 3, @skinParse_Border_Top_Width(), @skinCopy_Border_Top_Width(), @skinTransition_Border_Top_Width(), "border-top, border-width, border")
registerSkinSubProperty(*border, "border-right-width", 3, @skinParse_Border_Right_Width(), @skinCopy_Border_Right_Width(), @skinTransition_Border_Right_Width(), "border-right, border-width, border")
registerSkinSubProperty(*border, "border-bottom-width", 3, @skinParse_Border_Bottom_Width(), @skinCopy_Border_Bottom_Width(), @skinTransition_Border_Bottom_Width(), "border-bottom, border-width, border")
registerSkinSubProperty(*border, "border-left-width", 3, @skinParse_Border_Left_Width(), @skinCopy_Border_Left_Width(), @skinTransition_Border_Left_Width(), "border-left, border-width, border")
Code: Select all
registerSkinSubProperty(*border, "border-top-width", 3, @skinParse_Border_Top_Width(), @skinCopy_Border_Top_Width(), @skinTransition_Border_Top_Width(), "border-top, border-width, border")
You shouldn't have to worry about this at all but I will be opening up these commands down the line for advanced usage (you need custom skin property handlers for some reason).
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha 3 Ready for testing!
I don't think I've shared this before but this is currently the source code include path for ProGUI V3:
So slightly better than the ProGUI V1.xx monolith 
Code: Select all
ProGUI_Animation.pbi
ProGUI_Core.pbi
ProGUI_Events.pbi
ProGUI_GFX.pbi
ProGUI_GFX_Cairo.pbi
ProGUI_GFX_Direct2D.pbi
ProGUI_GFX_Drivers.pbi
ProGUI_Layout.pbi
ProGUI_OS.pbi
ProGUI_OS_Linux.pbi
ProGUI_OS_Windows.pbi
ProGUI_OS_Windows_Capture.pbi
ProGUI_OS_Windows_Core.pbi
ProGUI_OS_Windows_Diverted.pbi
ProGUI_OS_Windows_ScrollBar.pbi
ProGUI_OS_Windows_Webview.pbi
ProGUI_Skin.pbi
ProGUI_Widget.pbi
ProGUI_Widget_ScrollBar.pbi
ProGUI_Widget_Webview.pbi
ProGUI_Window.pbi
ProGUI.pbi

ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha 3 Ready for testing!
Hi guys, the skin engine is progressing nicely. Border CSS is complete (and is exactly the same as web CSS). The first proper widget to use the skin engine is now the scrollbar widget (with class "scrollbar") which all layouts use. The scrollbar widget is now almost indistinguishable from the native OS Windows 10 scrollbar with animation transitions (except better consistent animation with a solid framerate, each native win32 control seems to have a slightly different implementation with animation tied to the main window message pump events - so framerate janky at times). So currently the default Windows 10 skin for scrollbars currently looks like this (default light theme):
I've made the SkinSetValue() command more explicit (slightly more verbose) as it will only be used really for dynamically changing skin property values (most of the time you will edit the skin CSS file directly) - this also allows string constants to be used instead of having to remember a markup language (which could change) so: SkinSetValue(ClassPath.s, State.s, Component.s, Property.s, Value.s, Skin = #Null)
Code: Select all
SkinSetValue("scrollbar", "", "", "background-color", "#F0F0F0")
SkinSetValue("scrollbar", "", "thumb1", "background-color", "#F0F0F0")
SkinSetValue("scrollbar", "", "thumb2", "background-color", "#F0F0F0")
SkinSetValue("scrollbar", "", "trackbar", "background-color", "#CDCDCD")
SkinSetValue("scrollbar", "hover", "thumb1", "background-color", "#DADADA")
SkinSetValue("scrollbar", "hover", "thumb2", "background-color", "#DADADA")
SkinSetValue("scrollbar", "hover", "trackbar", "background-color", "#A6A6A6")
SkinSetValue("scrollbar", "active", "thumb1", "background-color", "#606060")
SkinSetValue("scrollbar", "active", "thumb2", "background-color", "#606060")
SkinSetValue("scrollbar", "active", "trackbar", "background-color", "#606060")
SkinSetValue("scrollbar", "", "trackbar", "transition", "background-color 1s")
SkinSetValue("scrollbar", "hover", "trackbar", "transition", "background-color .3s")
SkinSetValue("scrollbar", "active", "trackbar", "transition", "background-color 0s")
SkinSetValue("scrollbar", "", "thumb1", "transition", "background-color 1s")
SkinSetValue("scrollbar", "hover", "thumb1", "transition", "background-color .3s")
SkinSetValue("scrollbar", "active", "thumb1", "transition", "background-color 0s")
SkinSetValue("scrollbar", "", "thumb2", "transition", "background-color 1s")
SkinSetValue("scrollbar", "hover", "thumb2", "transition", "background-color .3s")
SkinSetValue("scrollbar", "active", "thumb2", "transition", "background-color 0s")
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha 3 Ready for testing!
Skin background images are coming along nicely! 
https://www.youtube.com/shorts/aH8t5tpPQz0
The syntax is the same as Web CSS and you can have as many 'layers' as you want:
I'll be adding a new none-standard CSS "background-opacity" property too (that's animatiable) so cross-fading should be easy (Web CSS doesn't support this surprisingly).
The draw event handler for the widget looks like this:

https://www.youtube.com/shorts/aH8t5tpPQz0
The syntax is the same as Web CSS and you can have as many 'layers' as you want:
Code: Select all
SkinSetValue("testWidget3", "", "", "background-image", "url('icons/boingball.png'), url('icons/boingball2.png'), url('icons/background1.png')")
SkinSetValue("testWidget3", "", "", "background-position-x", "20px, 30px, 0px")
SkinSetValue("testWidget3", "hover", "", "background-position-x", "60px, 0px, -130px")
SkinSetValue("testWidget3", "", "", "transition", "background-position-x 1s")
The draw event handler for the widget looks like this:
Code: Select all
Procedure drawTestWidget(Widget, EventType, *eventData.PG_EventDraw)
DrawSkinBackground(Widget, "", 0, 0, *eventData\width, *eventData\height)
EndProcedure
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha 3 Ready for testing!
Background opacity is now working 
https://www.youtube.com/shorts/j__E1TUgmS0
Surprisingly the Web CSS specification doesn't support individual background opacity so this is an upgrade to standard CSS with the addition of a new 'background-opacity' property.
To do this in HTML and CSS you would need 4 Divs overlaid on top of each other and would have to alter the opacity of each Div (through JS probably).
So the CSS for the widget looks like this:
P.s I turned 43 today, old bastard now 

https://www.youtube.com/shorts/j__E1TUgmS0
Surprisingly the Web CSS specification doesn't support individual background opacity so this is an upgrade to standard CSS with the addition of a new 'background-opacity' property.
To do this in HTML and CSS you would need 4 Divs overlaid on top of each other and would have to alter the opacity of each Div (through JS probably).
So the CSS for the widget looks like this:
Code: Select all
SkinSetValue("testWidget3", "", "", "background-image", "url('icons/boingball.png'), url('icons/dccmanager/movie8_128x128.png'), url('icons/boingball2.png'), url('icons/background1.png')")
SkinSetValue("testWidget3", "", "", "background-position-x", "20px, 20px, 30px, 0px")
SkinSetValue("testWidget3", "hover", "", "background-position-x", "60px, 60px, 0px, -130px")
SkinSetValue("testWidget3", "", "", "background-opacity", "100%, 0%, 100%, 100%")
SkinSetValue("testWidget3", "hover", "", "background-opacity", "0%, 100%, 50%, 100%")
SkinSetValue("testWidget3", "active", "", "background-opacity", "0%, 100%, 0%, 0%")
SkinSetValue("testWidget3", "", "", "transition", "background-position-x 1s, background-opacity 1s")

ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha 3 Ready for testing!
https://www.youtube.com/shorts/kyvbpNEkozM
There was a slight animation pause in the previous example when transitioning midway from a hover state to active due to CRC32 checksums not being calculated correctly for the new skin properties that can have a 'list' of elements. The checksums are used when animating between states and let the animation system know whether the new skin state is the same as the previous and if so let the previous animation continue (if already animating). Ping-ponging is working correctly again now too, so when a transition is animating between 2 states and the states are flipped midway e.g. normal and hover when the mouse moves away and back again quickly.
There was a slight animation pause in the previous example when transitioning midway from a hover state to active due to CRC32 checksums not being calculated correctly for the new skin properties that can have a 'list' of elements. The checksums are used when animating between states and let the animation system know whether the new skin state is the same as the previous and if so let the previous animation continue (if already animating). Ping-ponging is working correctly again now too, so when a transition is animating between 2 states and the states are flipped midway e.g. normal and hover when the mouse moves away and back again quickly.
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha 3 Ready for testing!
happy birthday, I stick with 42, it has a nice ring to it! No need for Deep Thought on that one. 101010
Re: ProGUI V3 Alpha 3 Ready for testing!
Thanks mate haha I'm 38 if any ladies are asking

ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk
Re: ProGUI V3 Alpha 3 Ready for testing!
So for that demo, the mouse event handler looks like this:
"circle" is testing out sub elements / components for example the scrollbar widget currently has "thumb1", "thumb2" and "trackbar" component / elements
Code: Select all
Procedure testWidgetMouse(Widget, EventType, *eventData.PG_EventMouse)
Select EventType
Case #PG_Event_MouseLeftButtonDown, #PG_Event_MouseLeftDoubleClick
WidgetSetSkinState(Widget, "active")
Case #PG_Event_MouseLeftButtonUp
WidgetSetSkinState(Widget, "hover")
WidgetSetSkinState(Widget, "hover", "circle")
Case #PG_Event_MouseEnter
WidgetSetSkinState(Widget, "hover")
WidgetSetSkinState(Widget, "hover", "circle")
Case #PG_Event_MouseLeave
WidgetSetSkinState(Widget, "")
WidgetSetSkinState(Widget, "", "circle")
EndSelect
EndProcedure
ProGUI - Professional Graphical User Interface Library - http://www.progui.co.uk