modern style switchgadget

Developed or developing a new product in PureBasic? Tell the world about it.
Mesa
Enthusiast
Enthusiast
Posts: 349
Joined: Fri Feb 24, 2012 10:19 am

modern style switchgadget

Post by Mesa »

My first gadget, based on the PB ImageGadget to use transparancy.

It's just a simple switch, with a modern style.
Could you test it and tell me if there are problems, with dpi, 4k, linux, macos, etc.

Thanks.
Image

[Edit] Add ChangeModernSwitchGadgetState(Gadget.i) and modify SetModernSwitchGadgetState(Gadget.i, State.i)
[Edit] Fix Memory leak (Stargate), fix Stopdrawing (Stargate), add CheckerBoard by netmaestro

Simple ModernSwitchGadget (no Focus, no keyboard)

Code: Select all

;- TOP

;.-------------------------------------------------------------------------------------------------
;|
;|  Title            : ModernSwitchGadget
;|  Version          : v0.5.5 Beta
;|  Author					 : Mesa
;|  Copyright        : 
;|                     
;|  PureBasic        : 5.70+
;|  
;|  Operating System : Windows (XP to W11+), Linux, MacOS
;|  Processor        : x86, x64
;|
;|  API							 : No api used
;|
;|-------------------------------------------------------------------------------------------------
;|
;|  Description      : Switch Gadget with a "modern" style
;|
;|  Forum Topic      : http://www.purebasic.fr/french/viewtopic.php?t=18876
;|                     http://www.purebasic.fr/english/viewtopic.php?t=80957
;|  Website          : 
;|
;|  Documentation    : 
;|
;|	Date 						 : 02/2023
;|
;|  Misc.						 : I confess to being inspired (in a shameless way) in large part by the robust 
;|										 code of Stargate's TabBar gadget. So, if you have analyzed his code then mine 
;|										 will be very easy to understand and improve.
;|
;.-------------------------------------------------------------------------------------------------



;.-------------------------------------------------------------------------------------------------
;|
;|  How to  use 		 : 1) Add ModernSwitchGadget(...)
;|  			           : 2) Nothing else, except using these PB standard event type inside the loop : 
;|  				         : 		#PB_EventType_Change, 
;| 												#PB_EventType_LeftClick, #PB_EventType_RightClick, 
;|												#PB_EventType_LeftDoubleClick, #PB_EventType_RightDoubleClick	
;|																		...
;|                     
;|  Color theme      : To add or modify a color theme
;|									 : -> Modify the Macro ModernSwitchGadget_UseColorTheme()
;|
;|	Shape						 : To modify the gadget shape
;|									 : 1) Add Constants and Modify the Structures if needed
;|									 : 2) Modify the procedure ModernSwitchGadget_Layout() if needed
;|									 : 3) Modify the Procedure ModernSwitchGadget_Update(...) if needed 
;|									 : 4) Modify the Procedure ModernSwitchGadget_Draw(...) 
;|
;.-------------------------------------------------------------------------------------------------

;.-------------------------------------------------------------------------------------------------
;|
;|  License Mesa.
;|  The license Mesa is, do what you like but make the World better, easier and enjoyable.
;|
;|
;|
;| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;| SOFTWARE.
;| 
;.-------------------------------------------------------------------------------------------------





CompilerIf #PB_Compiler_IsMainFile
	EnableExplicit
CompilerEndIf




;-  1     .:Constantes:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


; Gadget Attributes
EnumerationBinary Attributes
	#ModernSwitchGadget_None 
	#ModernSwitchGadget_Border						
	#ModernSwitchGadget_Raised 
	#ModernSwitchGadget_Vertical
	#ModernSwitchGadget_Mirrored         
	#ModernSwitchGadget_Disabled	
EndEnumeration

; Gadget States
Enumeration States
	#ModernSwitchGadgetState_OFF
	#ModernSwitchGadgetState_ON
EndEnumeration

;Gadget Color Types
Enumeration Color_Types
	#ModernSwitchGadgetColor_Background									;
	#ModernSwitchGadgetColor_ButtonOn
	#ModernSwitchGadgetColor_ButtonOff
	#ModernSwitchGadgetColor_CurrentButton
EndEnumeration

; Gadget Events; No Public EventType
Enumeration Events #PB_EventType_FirstCustomValue
	#ModernSwitchGadget_EventType_Updated      ; The gadget has updated (internal)
EndEnumeration


;-  2     .:Structures:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

Structure ModernSwitchGadget_Layout
	;RoundedBox layout
	x.i			; The position and size of the RoundedBox in the current drawing output. 
	y.i
	w.i
	h.i
	arcx.i	;The radius of the rounded corners in the x and y direction. 
	arcy.i
	
	;Cicle button layout
	xc.i		; The position and size of the circle = button on/off
	yc.i
	r.i
EndStructure

Structure ModernSwitchGadget
	Number.i                          ; Gadget ID, position and size
	X.i
	Y.i
	W.i
	H.i
	W2.i															; W*2 used for antialiasing
	H2.i															; H*2	used for antialiasing
	Window.i													; Window parent ID
	ImageID.i													; Image twice as large as needed for antialiasing
	AAImageID.i											; Image will be scaled to the correct size while taking advantage of antialiasing
	DataValue.i												; Used with GadgetData()
	Attributes.i											; Attributes
	State.i														; 0=Left=OFF, 1=Right=ON
	Disabled.i												; 0=Enabled,  1=Disabled
	ColorBackground.i									; Background Color
	ColorButtonOn.i										;	Button color when gadget is ON
	ColorButtonOff.i									; Button color when gadget is OFF
	ColorBackgroundDisabled.i					; Special color when the gadget is disabled
	ColorButtonDisabled.i							; Special color when the gadget is disabled 
	CurrentColorBackground.i					; Current colors
	CurrentColorButtonOn.i
	CurrentColorButtonOff.i
	CurrentColorButton.i
	MarginButton.i										; Button margin on the left/right
	UpdatePosted.i										; 0=Do nothing, 1=Do a gadget update 																	; 	
	Events.i													; EventData() with a custom Event
	Layout.ModernSwitchGadget_Layout	; Layout
EndStructure


;-  3     .:Initializations:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
; NOTHING... because there are NO GLOBAL variables
; No Declares
; Everything is in the GadgetData
; And "initializations" are made inside the Procedure ModernSwitchGadget()


;-  4     .:Procedures & Macros:. 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;-  4.1  .:Private procedures for internal calculations ! Not for use !:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;StartDrawing
Procedure.i ModernSwitchGadget_StartDrawing(*ModernSwitchGadget.ModernSwitchGadget)
	ProcedureReturn StartDrawing(ImageOutput(*ModernSwitchGadget\ImageID))
EndProcedure

;StopDrawing
Procedure.i ModernSwitchGadget_StopDrawing(*ModernSwitchGadget.ModernSwitchGadget)
	StopDrawing()
EndProcedure

;AntiAliasing
Procedure ModernSwitchGadget_Antialiasing(*ModernSwitchGadget.ModernSwitchGadget)
	
	With *ModernSwitchGadget 
		
		;Stop drawing because of the antialiasing which is made in resizing the image
		ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
		
		;Antialiasing by resizing the image
		\AAImageID=CopyImage(\ImageID,#PB_Any)
		ResizeImage(\AAImageID,\W,\H)
		
		ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
		
	EndWith
	
EndProcedure

;Layout
Procedure ModernSwitchGadget_Layout(*ModernSwitchGadget.ModernSwitchGadget)
	
	Protected x, y, w, h, arcx, arcy, xc, yc, r
	
	With *ModernSwitchGadget
		
		x=0
		y=0
		w=\w2
		h=\h2
		
		Select \State
			Case 0
				;OFF
				If (\Attributes & #ModernSwitchGadget_Vertical) * (\Attributes & #ModernSwitchGadget_Mirrored)
					arcx=\w:arcy=\w:xc=\w:yc=\h*2-\w:r=\w-\MarginButton					
				ElseIf 	\Attributes & #ModernSwitchGadget_Vertical
					arcx=\w:arcy=\w:xc=\w:yc=\w:r=\w-\MarginButton
				ElseIf \Attributes & #ModernSwitchGadget_Mirrored
					arcx=\h:arcy=\h:xc=\w*2-\h:yc=\h:r=\h-\MarginButton
				Else
					arcx=\h:arcy=\h:xc=\h:yc=\h:r=\h-\MarginButton
				EndIf
				
			Case 1
				;ON
				If \Attributes & #ModernSwitchGadget_Vertical * \Attributes & #ModernSwitchGadget_Mirrored
					arcx=\w:arcy=\w:xc=\w:yc=\w:r=\w-\MarginButton
				ElseIf \Attributes & #ModernSwitchGadget_Vertical
					arcx=\w:arcy=\w:xc=\w:yc=\h*2-\w:r=\w-\MarginButton
				ElseIf \Attributes & #ModernSwitchGadget_Mirrored
					arcx=\h:arcy=\h:xc=\h:yc=\h:r=\h-\MarginButton		
				Else
					arcx=\h:arcy=\h:xc=\w*2-\h:yc=\h:r=\h-\MarginButton
				EndIf
		EndSelect
		
		
		\Layout\x = x
		\Layout\y = y
		\Layout\w = w
		\Layout\h = h
		\Layout\arcx = arcx
		\Layout\arcy = arcy
		\Layout\xc = xc
		\Layout\yc = yc
		\Layout\r = r
		
	EndWith
	
EndProcedure

;Events
Procedure ModernSwitchGadget_Examine(*ModernSwitchGadget.ModernSwitchGadget)
	
	With *ModernSwitchGadget
		
		If \Disabled = #False
			Select EventType()
					
				Case #PB_EventType_LeftDoubleClick 
					\State = \State!1
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
					
				Case #PB_EventType_LeftClick 
					\State = \State!1
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
					
			EndSelect
		EndIf	
		
	EndWith
	
EndProcedure

;Internal gadget update
Procedure ModernSwitchGadget_Update(*ModernSwitchGadget.ModernSwitchGadget) 
	
	With *ModernSwitchGadget
		
		;Colors
		If \Disabled
			\CurrentColorBackground = \ColorBackgroundDisabled
			\CurrentColorButtonOff = \ColorButtonDisabled
			\CurrentColorButtonOn = \ColorButtonDisabled
			If \State = #ModernSwitchGadgetState_OFF
				\CurrentColorButton = \ColorButtonDisabled
			Else
				\CurrentColorButton = \ColorButtonDisabled
			EndIf
		Else
			\CurrentColorBackground = \ColorBackground
			\CurrentColorButtonOff = \ColorButtonOff
			\CurrentColorButtonOn = \ColorButtonOn
			If \State = #ModernSwitchGadgetState_OFF
				\CurrentColorButton = \CurrentColorButtonOff
			Else
				\CurrentColorButton = \CurrentColorButtonOn
			EndIf
			
		EndIf
		
		;Layout
		ModernSwitchGadget_Layout(*ModernSwitchGadget)
		
		
		*ModernSwitchGadget\UpdatePosted = #False
		
	EndWith
	
EndProcedure

;Draw the gadget
Procedure ModernSwitchGadget_Draw(*ModernSwitchGadget.ModernSwitchGadget)
	
	With *ModernSwitchGadget
		
		DrawingMode(#PB_2DDrawing_AllChannels)
		RoundBox(\Layout\x,\Layout\y,\Layout\w,\Layout\h,\Layout\arcx,\Layout\arcy, \CurrentColorBackground)
		DrawingMode(#PB_2DDrawing_AlphaBlend)
		RoundBox(\Layout\x,\Layout\y,\Layout\w,\Layout\h,\Layout\arcx,\Layout\arcy,\CurrentColorBackground)
		Circle(\Layout\xc,\Layout\yc,\Layout\r,\CurrentColorButton)
		
		ModernSwitchGadget_Antialiasing(*ModernSwitchGadget)
		
		SetGadgetState(\Number, ImageID(\AAImageID));
		
		If IsImage(\AAImageID) 
			FreeImage(\AAImageID)
		EndIf
		
	EndWith
	
EndProcedure

;Send an update event to update the gadget (used with Setters and Getters)
Procedure ModernSwitchGadget_PostUpdate(*ModernSwitchGadget.ModernSwitchGadget) 
	
	If *ModernSwitchGadget\UpdatePosted = #False
		*ModernSwitchGadget\UpdatePosted = #True
		PostEvent(#PB_Event_Gadget, *ModernSwitchGadget\Window, *ModernSwitchGadget\Number, #ModernSwitchGadget_EventType_Updated, -1)
	EndIf
	
EndProcedure

;Callback
Procedure ModernSwitchGadget_Callback() 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(EventGadget())
	
	If *ModernSwitchGadget = #Null
		ProcedureReturn
	EndIf
	
	If EventType() >= #PB_EventType_FirstCustomValue
		*ModernSwitchGadget\Events = EventData()
		
		Select EventType()
				
			Case #ModernSwitchGadget_EventType_Updated
				If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
					ModernSwitchGadget_Update(*ModernSwitchGadget)
					ModernSwitchGadget_Draw(*ModernSwitchGadget)
					ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
				Else
					*ModernSwitchGadget\UpdatePosted = #False
				EndIf
				
		EndSelect
		
	Else
		
		If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
			ModernSwitchGadget_Examine(*ModernSwitchGadget)
			ModernSwitchGadget_Update(*ModernSwitchGadget)
			ModernSwitchGadget_Draw(*ModernSwitchGadget)
			ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
		EndIf
		
	EndIf
	
EndProcedure


;-  4.2  .:Public Procedures for the Gadget:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;Update and redraw the gadget
Procedure UpdateModernSwitchGadget(Gadget.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
		ModernSwitchGadget_Update(*ModernSwitchGadget)
		ModernSwitchGadget_Draw(*ModernSwitchGadget)
		ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
	EndIf
	
EndProcedure

;Free the gadget
Procedure FreeModernSwitchGadget(Gadget.i)
	
	If Not IsGadget(Gadget)
		ProcedureReturn
	EndIf
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	SetGadgetData(Gadget, #Null)
	UnbindGadgetEvent(*ModernSwitchGadget\Number, @ModernSwitchGadget_Callback())
	FreeGadget(Gadget)
	
	If *ModernSwitchGadget\ImageID
		FreeImage(*ModernSwitchGadget\ImageID)
	EndIf
	If *ModernSwitchGadget\AAImageID
		FreeImage(*ModernSwitchGadget\AAImageID)
	EndIf
	
	ClearStructure(*ModernSwitchGadget, ModernSwitchGadget)
	FreeMemory(*ModernSwitchGadget)
	
EndProcedure

;Disable the gadget and change colors
Procedure DisableModernSwitchGadget(Gadget.i, Value.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	With	*ModernSwitchGadget
		
		Select Value
			Case 0
				\Disabled = 0
			Case 1
				\Disabled  = 1	
		EndSelect
		
	EndWith
	
	ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
	
EndProcedure

;Select the color theme
Macro ModernSwitchGadget_UseColorTheme()
	
	Select UCase(ColorTheme$)
			
		Case "", "STANDARD"
			*ModernSwitchGadget\ColorBackground = $FFBC7000
			*ModernSwitchGadget\ColorButtonOn = $FFFFFFFF
			*ModernSwitchGadget\ColorButtonOff = $FFFFFFFF
			*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
			*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
			
		Case "DARK"
			*ModernSwitchGadget\ColorBackground = $FF000000
			*ModernSwitchGadget\ColorButtonOn = $FFAAAAAA
			*ModernSwitchGadget\ColorButtonOff = $FFAAAAAA
			*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
			*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
			
		Default
			;Like "", "STANDARD"
			*ModernSwitchGadget\ColorBackground = $FFBC7000
			*ModernSwitchGadget\ColorButtonOn = $FFFFFFFF
			*ModernSwitchGadget\ColorButtonOff = $FFFFFFFF
			*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
			*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
	EndSelect
	
EndMacro

;Create the gadget
Procedure ModernSwitchGadget(Gadget, x, y, w, h, Attributes, Window, ColorTheme$="STANDARD")
	
	; 	Attributes:
	;   -----------	
	; 	#ModernSwitchGadget_None 
	; 	#ModernSwitchGadget_Border						
	; 	#ModernSwitchGadget_Raised 
	; 	#ModernSwitchGadget_Vertical
	; 	#ModernSwitchGadget_Mirrored 
	; 
	; 	ColorTheme$:
	;   ------------
	; 	"STANDARD"
	; 	"DARK"
	
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = AllocateMemory(SizeOf(ModernSwitchGadget))
	Protected Result.i, OldGadgetList.i, DummyGadget.i
	
	InitializeStructure(*ModernSwitchGadget, ModernSwitchGadget)
	OldGadgetList = UseGadgetList(WindowID(Window))
	
	;Create gadget with attributes Border/Raised
	If Attributes & #ModernSwitchGadget_Border
		Result = ImageGadget(Gadget, X, Y, W, H, 0, #PB_Image_Border)
	ElseIf Attributes & #ModernSwitchGadget_Raised
		Result = ImageGadget(Gadget, X, Y, W, H, 0, #PB_Image_Raised)
	Else
		Result = ImageGadget(Gadget, X, Y, W, H, 0)
	EndIf
	
	UseGadgetList(OldGadgetList)
	If Gadget = #PB_Any
		Gadget = Result
	EndIf
	SetGadgetData(Gadget, *ModernSwitchGadget)
	
	;Fills the structures
	With *ModernSwitchGadget
		
		;Gadget
		\Number = Gadget 
		\X = x
		\Y = y
		\W = w
		\H = h
		\W2 = w*2
		\H2 = h*2
		\Window = Window																						
		\Attributes = Attributes
		\ImageID =	CreateImage(#PB_Any,\W2,\H2,32,#PB_Image_Transparent)
		\MarginButton = DesktopScaledX(6)
		
		;Layout
		\Layout\x = \X
		\Layout\y = \Y
		\Layout\w = \W
		\Layout\h = \H
		
	EndWith
	
	;Color Theme
	ModernSwitchGadget_UseColorTheme()
	
	BindGadgetEvent(Gadget, @ModernSwitchGadget_Callback())
	
	UpdateModernSwitchGadget(Gadget)
	
	ProcedureReturn Result
	
EndProcedure


;-  4.3  .:Set & Get Procedures:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

;Get an attribute value.
Procedure.i GetModernSwitchGadgetAttribute(Gadget.i, Attribute.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select Attribute
		Case 	#ModernSwitchGadget_Vertical,
		     	#ModernSwitchGadget_Border,						
		     	#ModernSwitchGadget_Raised, 
		     	#ModernSwitchGadget_Mirrored,         
		     	#ModernSwitchGadget_Disabled
			
			If *ModernSwitchGadget\Attributes & Attribute
				ProcedureReturn #True
			Else
				ProcedureReturn #False
			EndIf
			
		Default
			ProcedureReturn -1
			
	EndSelect
	
EndProcedure

;Set/Change the data value of the gadget. 
Procedure SetModernSwitchGadgetData(Gadget.i, DataValue.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	*ModernSwitchGadget\DataValue = DataValue
	
EndProcedure

;Get the data value of the gadget.
Procedure.i GetModernSwitchGadgetData(Gadget.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	ProcedureReturn *ModernSwitchGadget\DataValue
	
EndProcedure

;Change the state of the gadget (ON/OFF).
Procedure ChangeModernSwitchGadgetState(Gadget.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select *ModernSwitchGadget\State
		Case #ModernSwitchGadgetState_OFF
			*ModernSwitchGadget\State = #ModernSwitchGadgetState_ON	
		Case #ModernSwitchGadgetState_ON
			*ModernSwitchGadget\State = #ModernSwitchGadgetState_OFF	
	EndSelect
	
	ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
	
EndProcedure

;Set the state of the gadget (ON/OFF).
Procedure SetModernSwitchGadgetState(Gadget.i, State.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select State
			
		Case 0,1
			*ModernSwitchGadget\State = State	
			
	EndSelect
	
	ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
	
EndProcedure

;Get the state of the gadget.
Procedure.i GetModernSwitchGadgetState(Gadget.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	ProcedureReturn *ModernSwitchGadget\State
	
EndProcedure

;Set/Change gadget color by type
Procedure SetModernSwitchGadgetColor(Gadget.i, Type.i, ColorRGBA.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select Type
		Case #ModernSwitchGadgetColor_Background
			*ModernSwitchGadget\ColorBackground = ColorRGBA
		Case #ModernSwitchGadgetColor_ButtonOff
			*ModernSwitchGadget\ColorButtonOff = ColorRGBA
		Case #ModernSwitchGadgetColor_ButtonOn
			*ModernSwitchGadget\ColorButtonOn = ColorRGBA		
	EndSelect
	
	ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
	
EndProcedure

;Set/Change gadget all colors
Procedure.i SetModernSwitchGadgetColors(Gadget.i, ColorBackgroundRGBA.i, ColorButtonOffRGBA.i, ColorButtonOnRGBA.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	*ModernSwitchGadget\ColorBackground = ColorBackgroundRGBA
	*ModernSwitchGadget\ColorButtonOff = ColorButtonOffRGBA
	*ModernSwitchGadget\ColorButtonOn = ColorButtonOnRGBA	
	
	ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
	
EndProcedure

;Set/Change gadget color theme
Procedure SetModernSwitchGadgetColorTheme(Gadget.i, ColorTheme.s) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	With	*ModernSwitchGadget
		
		;Color Theme
		Select UCase(ColorTheme)	
			Case "", "STANDARD"
				\ColorBackground = $FFBC7000
				\ColorButtonOn = $FFFFFFFF
				\ColorButtonOff = $FFFFFFFF
				\ColorBackgroundDisabled = $FF808080								;
				\ColorButtonDisabled = $FFC0C0C0
				
			Case "DARK"
				\ColorBackground = $FF000000
				\ColorButtonOn = $FFAAAAAA
				\ColorButtonOff = $FFAAAAAA
				\ColorBackgroundDisabled = $FF808080								;
				\ColorButtonDisabled = $FFC0C0C0
				
			Default
				DebuggerError("Color Theme Unknown !")
				
		EndSelect
		
	EndWith
	
	ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
	
EndProcedure 

;- BOTTOM
;- END
;-


;- Test
CompilerIf #PB_Compiler_IsMainFile
	
	Enumeration 1
		#imgGadget
		#imgGadgetDARK
		#imgGadgetV
		#imgGadgetM
		#imgGadgetMV
		#imgGadgetDisabled
		#btn
	EndEnumeration
	
	Macro CheckerBoard(cb_imgIn,cb_szBlock) ; netmaestro 2023
		cb_chex = CreateImage(#PB_Any,2,2,24,#White)
		StartDrawing(ImageOutput(cb_chex))
		Plot(1,0,$C8C8C8):Plot(0,1,$C8C8C8)
		StopDrawing()
		ResizeImage(cb_chex,cb_szBlock*2,cb_szBlock*2,#PB_Image_Raw)
		StartVectorDrawing(ImageVectorOutput(cb_imgIn))
		VectorSourceImage(ImageID(cb_chex),255,cb_szBlock*2,cb_szBlock*2,#PB_VectorImage_Repeat)
		FillVectorOutput()
		StopVectorDrawing()
		FreeImage(cb_chex)
	EndMacro
	
	
	;Test DPI
	Define W
	ExamineDesktops()
	W=DesktopWidth(0)/2
	
	
	Define.i cb_bkgnd, cb_chex ; Checkerboard background
	
	If OpenWindow(0, 0, 0, W, 400, "ModernSwitchGadget Tests", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
		
		cb_bkgnd=CreateImage(#PB_Any,w,400)         ; checkerboard background
		checkerboard(cb_bkgnd,10)										;       "          "
		ImageGadget(0,0,0,w,400,ImageID(cb_bkgnd))	;       "          "
		DisableGadget(0,1)
		
		
		ModernSwitchGadget(#imgGadget, 10, 60, 60, 30, #ModernSwitchGadget_None,0);
		ModernSwitchGadget(#imgGadgetDARK,  10, 100, 60, 30, #ModernSwitchGadget_None,0,"DARK")
		ModernSwitchGadget(#imgGadgetV, 100, 60, 30, 60, #ModernSwitchGadget_Vertical,0)
		ModernSwitchGadget(#imgGadgetM, 10, 160, 60, 30, #ModernSwitchGadget_Mirrored,0)
		ModernSwitchGadget(#imgGadgetMV, 100, 160, 30, 60, #ModernSwitchGadget_Vertical|#ModernSwitchGadget_Mirrored,0)
		ModernSwitchGadget(#imgGadgetDisabled, 10, 200, 40, 20, #ModernSwitchGadget_None,0);
		
		ButtonGadget(#btn,10,240,60,30,"ok")
		
		GadgetToolTip(#imgGadget, "STANDARD")
		GadgetToolTip(#imgGadgetDARK, "DARK")
		GadgetToolTip(#imgGadgetV, "VERTICAL (and customized)")
		GadgetToolTip(#imgGadgetM, "MIRRORED")
		GadgetToolTip(#imgGadgetMV, "VERTICAL & MIRRORED")
		GadgetToolTip(#imgGadgetDisabled, "Disabled")
		
		DisableModernSwitchGadget(#imgGadgetDisabled, #True)
		
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_Background, $801977F3)
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_ButtonOn, $FF3FDC30) 
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_ButtonOff, $800D26FF) 
		
		
		
		
		Define Event
		
		Repeat
			
			Event = WaitWindowEvent()
			
			Select Event
					
				Case #PB_Event_Gadget
					;- Events
					Select EventGadget()
						Case #imgGadget
							Select EventType()
									;No Test custom event => No public custom events
									
									
									;Test PB events
								Case #PB_EventType_Change          
									Debug "Changed"
									If GetModernSwitchGadgetState(#imgGadget) = 1
										Debug "ON"
										DisableModernSwitchGadget(#imgGadgetDisabled, #False)
									Else
										Debug "OFF"
										DisableModernSwitchGadget(#imgGadgetDisabled, #True)
									EndIf
								Case #PB_EventType_LeftClick 
									;Debug "LeftClick";ok
									
								Case #PB_EventType_RightClick
									;Debug "RightClick";ok
									
								Case #PB_EventType_LeftDoubleClick
									;Debug "DoubleClick";ok
									
								Case #PB_EventType_RightDoubleClick
									;Debug "RightDoubleClick";ok
									
							EndSelect
					EndSelect
			EndSelect
			
		Until Event = #PB_Event_CloseWindow
	EndIf
	
CompilerEndIf




M.
Last edited by Mesa on Sat Mar 04, 2023 11:02 am, edited 3 times in total.
User avatar
STARGÅTE
Addict
Addict
Posts: 2086
Joined: Thu Jan 10, 2008 1:30 pm
Location: Germany, Glienicke
Contact:

Re: modern style switchgadget

Post by STARGÅTE »

Hi Mesa,

there is a memory leak in your code:
Each time you call ModernSwitchGadget_Draw() you create a copy of an image (\TempImageID) without releasing it.
Here you need something like if IsImage(\TempImageID) : FreeImage(\TempImageID).

A disadvantage of this "ImageGadget"-solution is, your gadget is not selectable by tab and keyboard.

Edit:
An other issue: You call ModernSwitchGadget_StopDrawing() in the ModernSwitchGadget_Draw() itself but also after ModernSwitchGadget_Draw() in the UpdateModernSwitchGadget() procedure.
Last edited by STARGÅTE on Tue Feb 28, 2023 8:30 am, edited 1 time in total.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Lizard - Script language for symbolic calculations and moreTypeface - Sprite-based font include/module
Denis
Enthusiast
Enthusiast
Posts: 704
Joined: Fri Apr 25, 2003 5:10 pm
Location: Doubs - France

Re: modern style switchgadget

Post by Denis »

Salut Mesa,

6.00 LTS X86 WIN 11 ASM backend : with or witout debbugger : Ok
6.00 LTS X64 WIN 11 ASM backend : with or witout debbugger : Ok

6.01b4 LTS X86 WIN 11 ASM backend : with or witout debbugger : Ok
6.01b4 LTS X86 WIN 11 C backend : with or witout debbugger : Ok

6.01b4 LTS X64 WIN 11 ASM backend : with or witout debbugger : Ok
6.01b4 LTS X64 WIN 11 C backend : with or witout debbugger : Ok
A+
Denis
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8433
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Re: modern style switchgadget

Post by netmaestro »

Very nice work Mesa! Here's your test code with a checkerboard background to better show your alpha transparency. I made no changes to your code, just a couple of additions which you can find with edit->find/replace->'checkerboard'. Again, good job (after you implement STARGÅTE fixes) :mrgreen:

Code: Select all

;- TOP

;.-------------------------------------------------------------------------------------------------
;|
;|  Title            : ModernSwitchGadget
;|  Version          : v0.5.2 Beta
;|  Author					 : Mesa
;|  Copyright        : 
;|                     
;|  PureBasic        : 5.70+
;|  
;|  Operating System : Windows, Linux, MacOS
;|  Processor        : x86, x64
;|
;|-------------------------------------------------------------------------------------------------
;|
;|  Description      : Switch Gadget with a "modern" style
;|
;|  Forum Topic      : http://www.purebasic.fr/french/viewtopic.php?f=
;|                     http://www.purebasic.fr/english/viewtopic.php?f=
;|  Website          : 
;|
;|  Documentation    : 
;|
;|	Date 						 : 02/2023
;|
;|  Misc.						 : I confess to being inspired (in a shameless way) in large part by the robust 
;|										 code of Stargate's TabBar gadget. So, if you have analyzed his code then mine 
;|										 will be very easy to understand and improve.
;|
;.-------------------------------------------------------------------------------------------------



;.-------------------------------------------------------------------------------------------------
;|
;|  How to  use 		 : 1) Add ModernSwitchGadget(Gadget, bla...)
;|  			           : 2) Inside the loop, add GetModernSwitchGadgetState(Gadget)
;|  				         : 		Ex. ...
;|															Select EventType()
;|																Case #ModernSwitchGadget_EventType_Change
;|																	Debug "Changed"
;|																		...
;|                     
;|  Color theme      : To add or modify a color theme
;|									 : -> Modify the Macro ModernSwitchGadget_UseColorTheme()
;|
;|	Shape						 : To modify the gadget shape
;|									 : 1) Add Constants and Modify the Structures if needed
;|									 : 2) Modify the procedure ModernSwitchGadget_Layout() if needed
;|									 : 3) Modify the Procedure ModernSwitchGadget_Update(...) if needed 
;|									 : 4) Modify the Procedure ModernSwitchGadget_Draw(...) 
;|
;.-------------------------------------------------------------------------------------------------

;.-------------------------------------------------------------------------------------------------
;|
;|  License Mesa.
;|  The license Mesa is, do what you like but make the World better, easier and enjoyable.
;|
;|
;|
;| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;| SOFTWARE.
;| 
;.-------------------------------------------------------------------------------------------------

; Checkerboard background
Macro CheckerBoard(cb_imgIn,cb_szBlock) ; netmaestro 2023
  cb_chex = CreateImage(#PB_Any,2,2,24,#White)
  StartDrawing(ImageOutput(cb_chex))
    Plot(1,0,$C8C8C8):Plot(0,1,$C8C8C8)
  StopDrawing()
  ResizeImage(cb_chex,cb_szBlock*2,cb_szBlock*2,#PB_Image_Raw)
  StartVectorDrawing(ImageVectorOutput(cb_imgIn))
    VectorSourceImage(ImageID(cb_chex),255,cb_szBlock*2,cb_szBlock*2,#PB_VectorImage_Repeat)
    FillVectorOutput()
  StopVectorDrawing()
  FreeImage(cb_chex)
EndMacro


CompilerIf #PB_Compiler_IsMainFile
  EnableExplicit
CompilerEndIf




;-  1     .:Constantes:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


; Gadget Attributes
EnumerationBinary
  #ModernSwitchGadget_None 
  #ModernSwitchGadget_Border						
  #ModernSwitchGadget_Raised 
  #ModernSwitchGadget_Vertical
  #ModernSwitchGadget_Mirrored         
  #ModernSwitchGadget_Disabled	
EndEnumeration

; Gadget States
Enumeration
  #ModernSwitchGadgetState_OFF
  #ModernSwitchGadgetState_ON
EndEnumeration

;Gadget Color Types
Enumeration
  #ModernSwitchGadgetColor_Background									;
  #ModernSwitchGadgetColor_ButtonOn
  #ModernSwitchGadgetColor_ButtonOff
  #ModernSwitchGadgetColor_CurrentButton
EndEnumeration

; Gadget Events
Enumeration #PB_EventType_FirstCustomValue
  #ModernSwitchGadget_EventType_Updated      ; The gadget has updated (internal)
  #ModernSwitchGadget_EventType_Change       ; The state has changed
EndEnumeration


;-  2     .:Structures:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

Structure ModernSwitchGadget_Layout
  ;RoundedBox layout
  x.i			; The position and size of the RoundedBox in the current drawing output. 
  y.i
  w.i
  h.i
  arcx.i	;The radius of the rounded corners in the x and y direction. 
  arcy.i
  
  ;Cicle button layout
  xc.i		; The position and size of the circle = button on/off
  yc.i
  r.i
EndStructure

Structure ModernSwitchGadget
  Number.i                          ; Gadget ID, position and size
  X.i
  Y.i
  W.i
  H.i
  W2.i															; W*2 used for antialiasing
  H2.i                              ; H*2	used for antialiasing
  Window.i                          ; Window parent ID
  ImageID.i                         ; Image twice as large as needed for antialiasing
  TempImageID.i                     ; Image will be scaled to the correct size while taking advantage of antialiasing
  DataValue.i                       ; Used with GadgetData()
  Attributes.i                      ; Attributes
  State.i                           ; 0=Left=OFF, 1=Right=ON
  Disabled.i                        ; 0=Enabled,  1=Disabled
  ColorBackground.i                 ; Background Color
  ColorButtonOn.i                   ;	Button color when gadget is ON
  ColorButtonOff.i                  ; Button color when gadget is OFF
  ColorBackgroundDisabled.i         ; Special color when the gadget is disabled
  ColorButtonDisabled.i             ; Special color when the gadget is disabled 
  CurrentColorBackground.i          ; Current colors
  CurrentColorButtonOn.i
  CurrentColorButtonOff.i
  CurrentColorButton.i
  MarginButton.i										; Button margin on the left/right
  UpdatePosted.i                    ; 0=Do nothing, 1=Do a gadget update 																	; 	
  Events.i                          ; EventData() with a custom Event
  Layout.ModernSwitchGadget_Layout  ; Layout
EndStructure


;-  3     .:Initializations:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
; NOTHING... because there are NO GLOBAL variables
; No Declares
; Everything is in the GadgetData
; And "initializations" are made inside the Procedure ModernSwitchGadget()


;-  4     .:Procedures & Macros:. 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;-  4.1  .:Private procedures for internal calculations ! Not for use !:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;StartDrawing
Procedure.i ModernSwitchGadget_StartDrawing(*ModernSwitchGadget.ModernSwitchGadget)
  ProcedureReturn StartDrawing(ImageOutput(*ModernSwitchGadget\ImageID))
EndProcedure

;StopDrawing
Procedure.i ModernSwitchGadget_StopDrawing(*ModernSwitchGadget.ModernSwitchGadget)
  StopDrawing()
EndProcedure

;Layout
Procedure ModernSwitchGadget_Layout(*ModernSwitchGadget.ModernSwitchGadget)
	
	Protected x, y, w, h, arcx, arcy, xc, yc, r
	
	With *ModernSwitchGadget
		
		x=0
    y=0
    w=\w2
    h=\h2
    
    Select \State
      Case 0
        ;OFF
        If (\Attributes & #ModernSwitchGadget_Vertical) * (\Attributes & #ModernSwitchGadget_Mirrored)
          arcx=\w:arcy=\w:xc=\w:yc=\h*2-\w:r=\w-\MarginButton					
        ElseIf 	\Attributes & #ModernSwitchGadget_Vertical
          arcx=\w:arcy=\w:xc=\w:yc=\w:r=\w-\MarginButton
        ElseIf \Attributes & #ModernSwitchGadget_Mirrored
          arcx=\h:arcy=\h:xc=\w*2-\h:yc=\h:r=\h-\MarginButton
        Else
          arcx=\h:arcy=\h:xc=\h:yc=\h:r=\h-\MarginButton
        EndIf
        
      Case 1
        ;ON
        If \Attributes & #ModernSwitchGadget_Vertical * \Attributes & #ModernSwitchGadget_Mirrored
          arcx=\w:arcy=\w:xc=\w:yc=\w:r=\w-\MarginButton
        ElseIf \Attributes & #ModernSwitchGadget_Vertical
          arcx=\w:arcy=\w:xc=\w:yc=\h*2-\w:r=\w-\MarginButton
        ElseIf \Attributes & #ModernSwitchGadget_Mirrored
          arcx=\h:arcy=\h:xc=\h:yc=\h:r=\h-\MarginButton		
        Else
          arcx=\h:arcy=\h:xc=\w*2-\h:yc=\h:r=\h-\MarginButton
        EndIf
    EndSelect
    
    
    \Layout\x = x
    \Layout\y = y
    \Layout\w = w
    \Layout\h = h
    \Layout\arcx = arcx
    \Layout\arcy = arcy
    \Layout\xc = xc
    \Layout\yc = yc
    \Layout\r = r
    
  EndWith
  
	EndProcedure
	
;Events
Procedure ModernSwitchGadget_Examine(*ModernSwitchGadget.ModernSwitchGadget)
  
  With *ModernSwitchGadget
    
    If \Disabled = #False
      Select EventType()
          
        Case #PB_EventType_LeftDoubleClick 
          \State = \State!1
          PostEvent(#PB_Event_Gadget, \Window, \Number, #ModernSwitchGadget_EventType_Change, 0)
          
        Case #PB_EventType_LeftClick 
          \State = \State!1
          PostEvent(#PB_Event_Gadget, \Window, \Number, #ModernSwitchGadget_EventType_Change, 0)
          
          ; 				Case #PB_EventType_RightClick      
          ; 				Case #PB_EventType_Change	
          ; 				Case #PB_EventType_RightDoubleClick
          ; 				Case #PB_EventType_DragStart
          
      EndSelect
    EndIf	
    
  EndWith
  
EndProcedure

;Internal gadget update
Procedure ModernSwitchGadget_Update(*ModernSwitchGadget.ModernSwitchGadget) 
  
  With *ModernSwitchGadget
  	
  	;Colors
    If \Disabled
      \CurrentColorBackground = \ColorBackgroundDisabled
      \CurrentColorButtonOff = \ColorButtonDisabled
      \CurrentColorButtonOn = \ColorButtonDisabled
      If \State = #ModernSwitchGadgetState_OFF
        \CurrentColorButton = \ColorButtonDisabled
      Else
        \CurrentColorButton = \ColorButtonDisabled
      EndIf
    Else
      \CurrentColorBackground = \ColorBackground
      \CurrentColorButtonOff = \ColorButtonOff
      \CurrentColorButtonOn = \ColorButtonOn
      If \State = #ModernSwitchGadgetState_OFF
        \CurrentColorButton = \CurrentColorButtonOff
      Else
        \CurrentColorButton = \CurrentColorButtonOn
      EndIf
      
    EndIf
    
    ;Layout
    ModernSwitchGadget_Layout(*ModernSwitchGadget)
    
    
    *ModernSwitchGadget\UpdatePosted = #False
    
  EndWith
  
EndProcedure

;Draw the gadget
Procedure ModernSwitchGadget_Draw(*ModernSwitchGadget.ModernSwitchGadget)
  
  With *ModernSwitchGadget
    
    DrawingMode(#PB_2DDrawing_AllChannels)
    RoundBox(\Layout\x,\Layout\y,\Layout\w,\Layout\h,\Layout\arcx,\Layout\arcy, \CurrentColorBackground)
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    RoundBox(\Layout\x,\Layout\y,\Layout\w,\Layout\h,\Layout\arcx,\Layout\arcy,\CurrentColorBackground)
    Circle(\Layout\xc,\Layout\yc,\Layout\r,\CurrentColorButton)
    
    ;Stop drawing because of the antialiasing-resizing (see under...)
    ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
    
    ;Antialiasing by resizing the image
    \TempImageID=CopyImage(\ImageID,#PB_Any)
    ResizeImage(\TempImageID,\W,\H)
    
    SetGadgetState(\Number, ImageID(\TempImageID));
    
    ;StartDrawing() not needed again because nothing else to draw ha, ha, and the CallBack() does it.
    
  EndWith
  
EndProcedure

;Send an update event to update the gadget (used with Setters and Getters)
Procedure ModernSwitchGadget_PostUpdate(*ModernSwitchGadget.ModernSwitchGadget) 
  
  If *ModernSwitchGadget\UpdatePosted = #False
    *ModernSwitchGadget\UpdatePosted = #True
    PostEvent(#PB_Event_Gadget, *ModernSwitchGadget\Window, *ModernSwitchGadget\Number, #ModernSwitchGadget_EventType_Updated, -1)
  EndIf
  
EndProcedure

;Callback
Procedure ModernSwitchGadget_Callback() 
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(EventGadget())
  
  If *ModernSwitchGadget = #Null
    ProcedureReturn
  EndIf
  
  If EventType() >= #PB_EventType_FirstCustomValue
  	*ModernSwitchGadget\Events = EventData()
  	
  	Select EventType()
  			
      Case #ModernSwitchGadget_EventType_Updated
        If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
          ModernSwitchGadget_Update(*ModernSwitchGadget)
          ModernSwitchGadget_Draw(*ModernSwitchGadget)
          ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
        Else
          *ModernSwitchGadget\UpdatePosted = #False
        EndIf
        
    EndSelect
    
  Else
  	
    If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
      ModernSwitchGadget_Examine(*ModernSwitchGadget)
      ModernSwitchGadget_Update(*ModernSwitchGadget)
      ModernSwitchGadget_Draw(*ModernSwitchGadget)
      ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
    EndIf
    
  EndIf
  
EndProcedure


;-  4.2  .:Public Procedures for the Gadget:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;Update and redraw the gadget
Procedure UpdateModernSwitchGadget(Gadget.i)
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
  
  If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
    ModernSwitchGadget_Update(*ModernSwitchGadget)
    ModernSwitchGadget_Draw(*ModernSwitchGadget)
    ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
  EndIf
  
EndProcedure

;Free the gadget
Procedure FreeModernSwitchGadget(Gadget.i)
  
  If Not IsGadget(Gadget)
    ProcedureReturn
  EndIf
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
  
  SetGadgetData(Gadget, #Null)
  UnbindGadgetEvent(*ModernSwitchGadget\Number, @ModernSwitchGadget_Callback())
  FreeGadget(Gadget)
  
  If *ModernSwitchGadget\ImageID
		FreeImage(*ModernSwitchGadget\ImageID)
	EndIf
	If *ModernSwitchGadget\TempImageID
		FreeImage(*ModernSwitchGadget\TempImageID)
	EndIf
  
  ClearStructure(*ModernSwitchGadget, ModernSwitchGadget)
  FreeMemory(*ModernSwitchGadget)
  
EndProcedure

;Select the color theme
Macro ModernSwitchGadget_UseColorTheme()
  
  Select UCase(ColorTheme$)
      
    Case "", "STANDARD"
      *ModernSwitchGadget\ColorBackground = $FFBC7000
      *ModernSwitchGadget\ColorButtonOn = $FFFFFFFF
      *ModernSwitchGadget\ColorButtonOff = $FFFFFFFF
      *ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
      *ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
      
    Case "DARK"
      *ModernSwitchGadget\ColorBackground = $FF000000
      *ModernSwitchGadget\ColorButtonOn = $FFAAAAAA
      *ModernSwitchGadget\ColorButtonOff = $FFAAAAAA
      *ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
      *ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
      
    Default
      ;Like "", "STANDARD"
      *ModernSwitchGadget\ColorBackground = $FFBC7000
      *ModernSwitchGadget\ColorButtonOn = $FFFFFFFF
      *ModernSwitchGadget\ColorButtonOff = $FFFFFFFF
      *ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
      *ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
  EndSelect
  
EndMacro

;Create the gadget
Procedure ModernSwitchGadget(Gadget, x, y, w, h, Attributes, Window, ColorTheme$="STANDARD")
  
  ; 	Attributes:
  ;   -----------	
  ; 	#ModernSwitchGadget_None 
  ; 	#ModernSwitchGadget_Border						
  ; 	#ModernSwitchGadget_Raised 
  ; 	#ModernSwitchGadget_Vertical
  ; 	#ModernSwitchGadget_Mirrored 
  ; 
  ; 	ColorTheme$:
  ;   ------------
  ; 	"STANDARD"
  ; 	"DARK"
  
   
  Protected *ModernSwitchGadget.ModernSwitchGadget = AllocateMemory(SizeOf(ModernSwitchGadget))
  Protected Result.i, OldGadgetList.i, DummyGadget.i
  
  InitializeStructure(*ModernSwitchGadget, ModernSwitchGadget)
  OldGadgetList = UseGadgetList(WindowID(Window))
  
  ;Create gadget with attributes Border/Raised
  If Attributes & #ModernSwitchGadget_Border
    Result = ImageGadget(Gadget, X, Y, W, H, 0, #PB_Image_Border)
  ElseIf Attributes & #ModernSwitchGadget_Raised
    Result = ImageGadget(Gadget, X, Y, W, H, 0, #PB_Image_Raised)
  Else
    Result = ImageGadget(Gadget, X, Y, W, H, 0)
  EndIf
  
  UseGadgetList(OldGadgetList)
  If Gadget = #PB_Any
    Gadget = Result
  EndIf
  SetGadgetData(Gadget, *ModernSwitchGadget)
  
  ;Fills the structures
  With *ModernSwitchGadget
    
    ;Gadget
    \Number = Gadget 
    \X = x
    \Y = y
    \W = w
    \H = h
    \W2 = w*2
    \H2 = h*2
    \Window = Window																						
    \Attributes = Attributes
    \ImageID =	CreateImage(#PB_Any,\W2,\H2,32,#PB_Image_Transparent)
    \MarginButton = DesktopScaledX(6)
    
    ;Layout
    \Layout\x = \X
    \Layout\y = \Y
    \Layout\w = \W
    \Layout\h = \H
    
  EndWith
  
  ;Color Theme
  ModernSwitchGadget_UseColorTheme()
  
  BindGadgetEvent(Gadget, @ModernSwitchGadget_Callback())
  
  UpdateModernSwitchGadget(Gadget)
  
  ProcedureReturn Result
  
EndProcedure


;-  4.3  .:Set & Get Procedures:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

;Disable the gadget and change colors
Procedure DisableModernSwitchGadget(Gadget.i, Value.i)
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
  
  With	*ModernSwitchGadget
    
    Select Value
      Case 0
        \Disabled = 0
      Case 1
        \Disabled  = 1	
    EndSelect
    
  EndWith
  
  ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
  
EndProcedure

;Get an attribute value.
Procedure.i GetModernSwitchGadgetAttribute(Gadget.i, Attribute.i) 
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
  
  Select Attribute
    Case 	#ModernSwitchGadget_Vertical,
         	#ModernSwitchGadget_Border,						
         	#ModernSwitchGadget_Raised, 
         	#ModernSwitchGadget_Mirrored,         
         	#ModernSwitchGadget_Disabled
      
      If *ModernSwitchGadget\Attributes & Attribute
        ProcedureReturn #True
      Else
        ProcedureReturn #False
      EndIf
      
    Default
      ProcedureReturn -1
      
  EndSelect
  
EndProcedure

;Set/Change the data value of the gadget. 
Procedure SetModernSwitchGadgetData(Gadget.i, DataValue.i)
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
  
  *ModernSwitchGadget\DataValue = DataValue
  
EndProcedure

;Get the data value of the gadget.
Procedure.i GetModernSwitchGadgetData(Gadget.i) 
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
  
  ProcedureReturn *ModernSwitchGadget\DataValue
  
EndProcedure

;Change the state of the gadget (ON/OFF).
Procedure ChangeModernSwitchGadgetState(Gadget.i) 
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
  
  Select *ModernSwitchGadget\State
    Case #ModernSwitchGadgetState_OFF
      *ModernSwitchGadget\State = #ModernSwitchGadgetState_ON	
    Case #ModernSwitchGadgetState_ON
      *ModernSwitchGadget\State = #ModernSwitchGadgetState_OFF	
  EndSelect
  
  ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
  
EndProcedure

;Set the state of the gadget (ON/OFF).
Procedure SetModernSwitchGadgetState(Gadget.i, State.i) 
  
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select State
			
		Case 0,1
			*ModernSwitchGadget\State = State	
			
	EndSelect
	
	ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
  
EndProcedure

;Get the state of the gadget.
Procedure.i GetModernSwitchGadgetState(Gadget.i) 
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
  
  ProcedureReturn *ModernSwitchGadget\State
  
EndProcedure

;Set/Change gadget color by type
Procedure SetModernSwitchGadgetColor(Gadget.i, Type.i, ColorRGBA.i) 
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
  
  Select Type
    Case #ModernSwitchGadgetColor_Background
      *ModernSwitchGadget\ColorBackground = ColorRGBA
    Case #ModernSwitchGadgetColor_ButtonOff
      *ModernSwitchGadget\ColorButtonOff = ColorRGBA
    Case #ModernSwitchGadgetColor_ButtonOn
      *ModernSwitchGadget\ColorButtonOn = ColorRGBA		
  EndSelect
  
  ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
  
EndProcedure

;Set/Change gadget all colors
Procedure.i SetModernSwitchGadgetColors(Gadget.i, ColorBackgroundRGBA.i, ColorButtonOffRGBA.i, ColorButtonOnRGBA.i)
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
  
  *ModernSwitchGadget\ColorBackground = ColorBackgroundRGBA
  *ModernSwitchGadget\ColorButtonOff = ColorButtonOffRGBA
  *ModernSwitchGadget\ColorButtonOn = ColorButtonOnRGBA	
  
  ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
  
EndProcedure

;Set/Change gadget color theme
Procedure SetModernSwitchGadgetColorTheme(Gadget.i, ColorTheme.s) 
  
  Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
  
  With	*ModernSwitchGadget
    
    ;Color Theme
    Select UCase(ColorTheme)	
      Case "", "STANDARD"
        \ColorBackground = $FFBC7000
        \ColorButtonOn = $FFFFFFFF
        \ColorButtonOff = $FFFFFFFF
        \ColorBackgroundDisabled = $FF808080								;
        \ColorButtonDisabled = $FFC0C0C0
        
      Case "DARK"
        \ColorBackground = $FF000000
        \ColorButtonOn = $FFAAAAAA
        \ColorButtonOff = $FFAAAAAA
        \ColorBackgroundDisabled = $FF808080								;
        \ColorButtonDisabled = $FFC0C0C0
        
      Default
        DebuggerError("Color Theme Unknown !")
        
    EndSelect
    
  EndWith
  
  ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
  
EndProcedure 

;- BOTTOM
;- END
;-


;- Test
CompilerIf #PB_Compiler_IsMainFile
  
  Enumeration 1
    #imgGadget
    #imgGadgetDARK
    #imgGadgetV
    #imgGadgetM
    #imgGadgetMV
    #imgGadgetDisabled
    #btn
  EndEnumeration
  
  ;Test DPI
  Define W
  ExamineDesktops()
  W=DesktopWidth(0)/2
  
  Define.i cb_bkgnd, cb_chex ; Checkerboard background
  If OpenWindow(0, 0, 0, W, 400, "ModernSwitchGadget Tests", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ; 	If OpenWindow(0, 0, 0, DesktopUnscaledX(W), DesktopUnscaledY(400), "ModernSwitchGadget Tests", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
    ;SetWindowColor(0,#White)
    cb_bkgnd=CreateImage(#PB_Any,w,400)         ; checkerboard background
    checkerboard(cb_bkgnd,10)                   ;       "          "
    ImageGadget(0,0,0,w,400,ImageID(cb_bkgnd))  ;       "          "
    DisableGadget(0,1)                          ;       "          "
    
    
    ModernSwitchGadget(#imgGadget, 10, 60, 60, 30, #ModernSwitchGadget_None,0);
    ModernSwitchGadget(#imgGadgetDARK,  10, 100, 60, 30, #ModernSwitchGadget_None,0,"DARK")
    ModernSwitchGadget(#imgGadgetV, 100, 60, 30, 60, #ModernSwitchGadget_Vertical,0)
    ModernSwitchGadget(#imgGadgetM, 10, 160, 60, 30, #ModernSwitchGadget_Mirrored,0)
    ModernSwitchGadget(#imgGadgetMV, 100, 160, 30, 60, #ModernSwitchGadget_Vertical|#ModernSwitchGadget_Mirrored,0)
    ModernSwitchGadget(#imgGadgetDisabled, 10, 200, 40, 20, #ModernSwitchGadget_None,0);
    
    ButtonGadget(#btn,10,240,60,30,"ok")
    
    GadgetToolTip(#imgGadget, "STANDARD")
    GadgetToolTip(#imgGadgetDARK, "DARK")
    GadgetToolTip(#imgGadgetV, "VERTICAL (and customized)")
    GadgetToolTip(#imgGadgetM, "MIRRORED")
    GadgetToolTip(#imgGadgetMV, "VERTICAL & MIRRORED")
    GadgetToolTip(#imgGadgetDisabled, "Disabled")
    
    
    
    
    
    ;Test Free gadget
		; 	FreeModernSwitchGadget(#imgGadgetDARK);OK
    
    ;Tests PB procedures
    ; 	GadgetToolTip(#imgGadget, "Tooltip");ok	
    ; 	SetActiveGadget(#imgGadget);ok
    ; 	DisableGadget(#imgGadget, 1);Disabled but colors are not changed
    ; 	HideGadget(#imgGadget, 1);ok
    ; 	Debug GadgetX(#imgGadget, #PB_Gadget_ContainerCoordinate );ok
    ; 	Debug GadgetX(#imgGadget, #PB_Gadget_WindowCoordinate);ok
    ; 	Debug GadgetX(#imgGadget, #PB_Gadget_ScreenCoordinate);ok
    ;		idem GadgetY, GadgetWidth, GadgetHeight;ok
    
    
    ;Test attributes
    ; 	Debug GetModernSwitchGadgetAttribute(#imgGadgetMV, #ModernSwitchGadget_Vertical);ok
    ; 	Debug GetModernSwitchGadgetAttribute(#imgGadget,   #ModernSwitchGadget_Border);ok						
    ; 	Debug GetModernSwitchGadgetAttribute(#imgGadget,   #ModernSwitchGadget_Raised);ok 
    ; 	Debug GetModernSwitchGadgetAttribute(#imgGadgetMV, #ModernSwitchGadget_Mirrored);ok       
    ; 	Debug GetModernSwitchGadgetAttribute(#imgGadget,   #ModernSwitchGadget_Disabled);ok
    DisableModernSwitchGadget(#imgGadgetDisabled, #True);ok
    
    ; 	DisableModernSwitchGadget(#imgGadget, #False);ok
    ; 	SetModernSwitchGadgetData(#imgGadget, 10);ok
    ; 	Debug GetModernSwitchGadgetData(#imgGadget);ok
    ; 	SetModernSwitchGadgetState(#imgGadget, 1);ok
    ; 	Debug GetModernSwitchGadgetState(#imgGadget);ok
    
    ;Tests colors
    ; 	a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_Background);ok
    ; 	a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_ButtonOn);ok
    ; 	a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_ButtonOff);ok
    ; 	a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_CurrentButton);ok
    ; 		Debug a;
    ; 		Debug Red(a)
    ; 		Debug Green(a)
    ; 		Debug Blue(a)
    ; 		Debug Alpha(a)		
    ; 	\ColorBackground = $FFBC7000
    ; 	\ColorButtonOn = $FFFFFFFF
    ; 	\ColorButtonOff = $FFFFFFFF
    ; 	\ColorBackgroundDisabled = $FF808080								;
    ; 	\ColorButtonDisabled = $FFC0C0C0
    ; 	ShowMemoryViewer(@a,20)
    SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_Background, $801977F3);ok
    SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_ButtonOn, $FF3FDC30)  ;ok
    SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_ButtonOff, $800D26FF) ;ok
    
    ; 	SetModernSwitchGadgetColors(#imgGadgetMV, $801977F3, $FF3FDC30, $800D26FF);ok
    ; 	SetModernSwitchGadgetColorTheme(#imgGadgetMV, "DARK");ok
    ; 	SetModernSwitchGadgetColorTheme(#imgGadgetMV, "ZARK.");Raise an error => ok 
    
		;		ChangeModernSwitchGadgetState(#imgGadget);ok
		;   SetModernSwitchGadgetState(#imgGadget, #ModernSwitchGadgetState_ON);ok
		;   SetModernSwitchGadgetState(#imgGadget, #ModernSwitchGadgetState_OFF);ok
    
    ;Strange DPI...
    ;Test with the compilator dpi switch on/off
    ; ; ModernSwitchGadget(#imgGadget, DesktopUnscaledX(10), 60, DesktopUnscaledX(60), 30, #ModernSwitchGadget_None, 0);
    ; ; ModernSwitchGadget(#imgGadgetDARK,  DesktopScaledX(10), 100, DesktopScaledX(60), 30, #ModernSwitchGadget_None, 0, "DARK")
    ;  StartDrawing(WindowOutput(0))
    ;  LineXY(10, 0, 10, 400, #Red)
    ;  LineXY(DesktopUnscaledX(10+60), 0, DesktopUnscaledX(10+60), 400, #Blue)
    ;  LineXY(DesktopScaledX(10+60), 0, DesktopScaledX(10+60), 400, #Green)
    ;  LineXY(10+60, 0, 10+60, 400, #Red)
    ;  LineXY(0, 0, 0, DesktopScaledY(400), #Green)
    ;  LineXY(DesktopScaledX(W)-1, 0, DesktopScaledX(W)-1, DesktopScaledY(400), #Green)
    ;  DrawText(300, 50, "Normal", #Red, #White)
    ;  DrawText(300, 100, "Unscaled", #Blue, #White)
    ;  DrawText(300, 150, "Scaled", #Green, #White)
    ;  StopDrawing()
    
    
    
    
    Define Event
    
    Repeat
      
      Event = WaitWindowEvent()
      
      Select Event
          
        Case #PB_Event_Gadget
          ;- Events
          Select EventGadget()
            Case #imgGadget
              Select EventType()
                  ;Test custom event
                Case #ModernSwitchGadget_EventType_Change
                  Debug "Changed"
                  If GetModernSwitchGadgetState(#imgGadget) = 1
                    Debug "ON"
                    DisableModernSwitchGadget(#imgGadgetDisabled, #False)
                  Else
                    Debug "OFF"
                    DisableModernSwitchGadget(#imgGadgetDisabled, #True)
                  EndIf
                  
                  ;Test PB events
                Case #PB_EventType_LeftClick 
                  ;Debug "LeftClick";ok
                  
                Case #PB_EventType_RightClick
                  ;Debug "RightClick";ok
                  
                Case #PB_EventType_LeftDoubleClick
                  ;Debug "DoubleClick";ok
                  
                Case #PB_EventType_RightDoubleClick
                  ;Debug "RightDoubleClick";ok
                     
              EndSelect
          EndSelect
      EndSelect
      
    Until Event = #PB_Event_CloseWindow
  EndIf
  
CompilerEndIf

BERESHEIT
mrbungle
Enthusiast
Enthusiast
Posts: 117
Joined: Wed Dec 30, 2020 3:18 am

Re: modern style switchgadget

Post by mrbungle »

Agree, very nice! Thanks for sharing.
Mesa
Enthusiast
Enthusiast
Posts: 349
Joined: Fri Feb 24, 2012 10:19 am

Re: modern style switchgadget

Post by Mesa »

Thank you very much,

This is a new version, with keyboard (Tab key, Shift Tab key and Spacebar) enhancement, focus, and a lot of enhancement.

So it needs some tests :oops:

New ModernSwichGadget

Code: Select all

;- TOP

;.-------------------------------------------------------------------------------------------------
;|
;|  Title            : ModernSwitchGadget
;|  Version          : v0.9.0 Beta
;|  Author					 : Mesa
;|  Copyright        : 
;|                     
;|  PureBasic        : 5.70+
;|  
;|  Operating System : Windows (XP to W11+), Linux, MacOS
;|  Processor        : x86, x64
;|
;|  API							 : No api used
;|
;|-------------------------------------------------------------------------------------------------
;|
;|  Description      : Switch Gadget with a "modern" style
;|
;|  Forum Topic      : https://www.purebasic.fr/french/viewtopic.php?t=18876
;|                     https://www.purebasic.fr/english/viewtopic.php?t=80957
;|  Website          : 
;|
;|  Documentation    : 
;|
;|	Date 						 : 02/2023
;|
;|  Misc.						 : I confess to being inspired (in a shameless way) in large part by the robust 
;|										 code of Stargate's TabBar gadget. So, if you have analyzed his code then mine 
;|										 will be very easy to understand and improve.
;|
;.-------------------------------------------------------------------------------------------------


;.-------------------------------------------------------------------------------------------------
;|
;|  How to  use 		 : 1) Add ModernSwitchGadget(...)
;|  			           : 2) Nothing else, except using the PB standard event type inside the loop : 
;|  				         : 		#PB_EventType_Change, #PB_EventType_Focus, #PB_EventType_LostFocus,
;| 												#PB_EventType_LeftClick, #PB_EventType_RightClick, 
;|												#PB_EventType_LeftDoubleClick, #PB_EventType_RightDoubleClick																																																																...
;|                     
;|  Color theme      : To add or modify a color theme
;|									 : -> Modify the Macro ModernSwitchGadget_UseColorTheme()
;|
;|  Selected gadget  : To modify the way the gadget is selected
;|										 -> Modify the Procedure ModernSwitchGadget_DrawFocus()
;|
;|	Shape						 : To modify the gadget shape
;|									 : 1) Add Constants and Modify the Structures if needed
;|									 : 2) Modify the procedure ModernSwitchGadget_Layout() if needed
;|									 : 3) Modify the Procedure ModernSwitchGadget_Update() if needed 
;|									 : 4) Modify the Procedure ModernSwitchGadget_Draw() 
;|
;.-------------------------------------------------------------------------------------------------

;.-------------------------------------------------------------------------------------------------
;|
;|  License Mesa.
;|  The license Mesa is, do what you like but make the World better, easier and enjoyable.
;|
;|
;|
;| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;| SOFTWARE.
;| 
;.-------------------------------------------------------------------------------------------------





CompilerIf #PB_Compiler_IsMainFile
	EnableExplicit
CompilerEndIf




;-  1     .:Constantes:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


; Gadget Attributes
EnumerationBinary Attributes
	#ModernSwitchGadget_None 
	#ModernSwitchGadget_Border						
	#ModernSwitchGadget_Raised 
	#ModernSwitchGadget_Vertical
	#ModernSwitchGadget_Mirrored         
	#ModernSwitchGadget_Disabled	
EndEnumeration

; Gadget States
Enumeration States
	#ModernSwitchGadgetState_OFF
	#ModernSwitchGadgetState_ON
EndEnumeration

;Gadget Color Types
Enumeration Color_Types
	;Theme colors
	#ModernSwitchGadgetColor_Background									;
	#ModernSwitchGadgetColor_ButtonOff
	#ModernSwitchGadgetColor_ButtonOn
	#ModernSwitchGadgetColor_Selected
	#ModernSwitchGadgetColor_BackgroundDisabled
	#ModernSwitchGadgetColor_ButtonDisabled
	;Current colors
	#ModernSwitchGadgetColor_CurrentColorBackground
	#ModernSwitchGadgetColor_CurrentColorButtonOn
	#ModernSwitchGadgetColor_CurrentColorButtonOff
	#ModernSwitchGadgetColor_CurrentColorSelected
EndEnumeration

; Gadget Events; No Public EventType 
Enumeration Events #PB_EventType_FirstCustomValue
	#ModernSwitchGadget_EventType_Updated      ; The gadget has updated (internal)																						      
EndEnumeration


;-  2     .:Structures:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

Structure ModernSwitchGadget_Layout
	;RoundedBox layout
	x.i			; The position and size of the RoundedBox in the current drawing output. 
	y.i
	w.i
	h.i
	arcx.i	;The radius of the rounded corners in the x and y direction. 
	arcy.i
	
	;Cicle button layout
	xc.i		; The position and size of the circle = button on/off
	yc.i
	r.i
EndStructure

Structure ModernSwitchGadget
	Number.i                          ; Gadget ID, position and size
	NumberDummyGadget.i								;	StringGadget with a size=0: Trick to use keyboard (Tab and Space keys)
	X.i
	Y.i
	W.i
	H.i
	W2.i															; W*2 used for antialiasing
	H2.i															; H*2	used for antialiasing
	Window.i													; Window parent ID
	ImageID.i													; Image twice as large as needed for antialiasing
	AAImageID.i											; Image will be scaled to the correct size while taking advantage of antialiasing
	DataValue.i												; Used with GadgetData()
	Attributes.i											; Attributes
	State.i														; 0=Left=OFF, 1=Right=ON
	Disabled.i												; 0=Enabled,  1=Disabled
	Focus.i														;	0=No Focus,	1=Focus
	ColorBackground.i									; Background Color
	ColorButtonOn.i										;	Button color when gadget is ON
	ColorButtonOff.i									; Button color when gadget is OFF
	ColorBackgroundDisabled.i					; Special color when the gadget is disabled
	ColorButtonDisabled.i							; Special color when the gadget is disabled
	ColorSelected.i										; Special color when the gadget is selected
	CurrentColorBackground.i					; Current colors
	CurrentColorButtonOn.i
	CurrentColorButtonOff.i
	CurrentColorButton.i
	CurrentColorSelected.i
	MarginButton.i										; Button margin on the left/right
	UpdatePosted.i										; 0=Do nothing, 1=Do a gadget update 																	; 	
	Events.i													; EventData() with a custom Event
	Layout.ModernSwitchGadget_Layout	; Layout
	ColorThemeName$
EndStructure


;-  3     .:Initializations:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
; NOTHING... because there are NO GLOBAL variables
; No Declares
; Everything is in the GadgetData
; And "initializations" are made inside the Procedure ModernSwitchGadget()


;-  4     .:Procedures & Macros:. 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;-  4.1  .:Private procedures for internal calculations ! Not for use !:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;StartDrawing
Procedure.i ModernSwitchGadget_StartDrawing(*ModernSwitchGadget.ModernSwitchGadget)
	ProcedureReturn StartDrawing(ImageOutput(*ModernSwitchGadget\ImageID))
EndProcedure

;StopDrawing
Procedure.i ModernSwitchGadget_StopDrawing(*ModernSwitchGadget.ModernSwitchGadget)
	StopDrawing()
EndProcedure

;AntiAliasing
Procedure ModernSwitchGadget_Antialiasing(*ModernSwitchGadget.ModernSwitchGadget)
	
	With *ModernSwitchGadget 
		
	;Stop drawing because of the antialiasing which is made in resizing the image
		ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
		
		;Antialiasing by resizing the image
		\AAImageID=CopyImage(\ImageID,#PB_Any)
		ResizeImage(\AAImageID,\W,\H)
		
		ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
		
	EndWith
	
EndProcedure

;Layout
Procedure ModernSwitchGadget_Layout(*ModernSwitchGadget.ModernSwitchGadget)
	
	If *ModernSwitchGadget\Disabled = #False
		
		Protected x, y, w, h, arcx, arcy, xc, yc, r
		
		With *ModernSwitchGadget
			
			x=0
			y=0
			w=\w2
			h=\h2
			
			Select \State
				Case #ModernSwitchGadgetState_OFF
					;OFF
					If (\Attributes & #ModernSwitchGadget_Vertical) * (\Attributes & #ModernSwitchGadget_Mirrored)
						arcx=\w:arcy=\w:xc=\w:yc=\h*2-\w:r=\w-\MarginButton					
					ElseIf 	\Attributes & #ModernSwitchGadget_Vertical
						arcx=\w:arcy=\w:xc=\w:yc=\w:r=\w-\MarginButton
					ElseIf \Attributes & #ModernSwitchGadget_Mirrored
						arcx=\h:arcy=\h:xc=\w*2-\h:yc=\h:r=\h-\MarginButton
					Else
						arcx=\h:arcy=\h:xc=\h:yc=\h:r=\h-\MarginButton
					EndIf
					
				Case #ModernSwitchGadgetState_ON
					;ON
					If \Attributes & #ModernSwitchGadget_Vertical * \Attributes & #ModernSwitchGadget_Mirrored
						arcx=\w:arcy=\w:xc=\w:yc=\w:r=\w-\MarginButton
					ElseIf \Attributes & #ModernSwitchGadget_Vertical
						arcx=\w:arcy=\w:xc=\w:yc=\h*2-\w:r=\w-\MarginButton
					ElseIf \Attributes & #ModernSwitchGadget_Mirrored
						arcx=\h:arcy=\h:xc=\h:yc=\h:r=\h-\MarginButton		
					Else
						arcx=\h:arcy=\h:xc=\w*2-\h:yc=\h:r=\h-\MarginButton
					EndIf
			EndSelect
			
			
			\Layout\x = x
			\Layout\y = y
			\Layout\w = w
			\Layout\h = h
			\Layout\arcx = arcx
			\Layout\arcy = arcy
			\Layout\xc = xc
			\Layout\yc = yc
			\Layout\r = r
			
		EndWith
		
	EndIf
	
EndProcedure

;Set Focus ON/OFF
Procedure 	ModernSwitchGadget_SetFocus(*ModernSwitchGadget.ModernSwitchGadget, Focus.i = #True)
	
	With *ModernSwitchGadget
		
		Select  Focus
				
			Case #True
				\Focus = #True
				SetActiveGadget(\NumberDummyGadget)
				SetGadgetText(\NumberDummyGadget, "")
				
			Case #False
				\Focus = #False
				
		EndSelect
		
	EndWith
	
EndProcedure

;Events
Procedure ModernSwitchGadget_Examine(*ModernSwitchGadget.ModernSwitchGadget)
	
	With *ModernSwitchGadget
		
		If \Disabled = #False
			Select EventType()
					
				Case #PB_EventType_LeftDoubleClick 
					\State = \State!1
					ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Focus, 0)
										
				Case #PB_EventType_LeftClick 
					\State = \State!1
					ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Focus, 0)
					
			EndSelect
		EndIf	
		
	EndWith
	
EndProcedure

;Internal gadget update
Procedure ModernSwitchGadget_Update(*ModernSwitchGadget.ModernSwitchGadget) 
	
	With *ModernSwitchGadget
		
		;Colors
		If \Disabled
			\CurrentColorBackground = \ColorBackgroundDisabled
			\CurrentColorButtonOff = \ColorButtonDisabled
			\CurrentColorButtonOn = \ColorButtonDisabled
			\CurrentColorSelected = \ColorButtonDisabled
			If \State = #ModernSwitchGadgetState_OFF
				\CurrentColorButton = \ColorButtonDisabled
			Else
				\CurrentColorButton = \ColorButtonDisabled
			EndIf
		Else
			\CurrentColorBackground = \ColorBackground
			\CurrentColorButtonOff = \ColorButtonOff
			\CurrentColorButtonOn = \ColorButtonOn
			\CurrentColorSelected = \ColorSelected
			If \State = #ModernSwitchGadgetState_OFF
				\CurrentColorButton = \CurrentColorButtonOff
			Else
				\CurrentColorButton = \CurrentColorButtonOn
			EndIf
			
		EndIf
		
		;Layout
		ModernSwitchGadget_Layout(*ModernSwitchGadget)
		
		
		*ModernSwitchGadget\UpdatePosted = #False
		
	EndWith
	
EndProcedure

;Draw focus = Just draw a circle as focus
Procedure  ModernSwitchGadget_DrawFocus(*ModernSwitchGadget.ModernSwitchGadget)
	
	With *ModernSwitchGadget
		
		Circle(\Layout\xc,\Layout\yc,\Layout\r - DesktopScaledX(6), \CurrentColorSelected)
		
	EndWith
	
EndProcedure

;Draw the gadget
Procedure ModernSwitchGadget_Draw(*ModernSwitchGadget.ModernSwitchGadget)
	
	With *ModernSwitchGadget
		
		DrawingMode(#PB_2DDrawing_AllChannels)
		RoundBox(\Layout\x,\Layout\y,\Layout\w,\Layout\h,\Layout\arcx,\Layout\arcy, \CurrentColorBackground)
		DrawingMode(#PB_2DDrawing_AlphaBlend)
		RoundBox(\Layout\x,\Layout\y,\Layout\w,\Layout\h,\Layout\arcx,\Layout\arcy,\CurrentColorBackground)
		Circle(\Layout\xc,\Layout\yc,\Layout\r,\CurrentColorButton)
		If \Focus
			ModernSwitchGadget_DrawFocus(*ModernSwitchGadget)	
		EndIf
		
		ModernSwitchGadget_Antialiasing(*ModernSwitchGadget)
		
		SetGadgetState(\Number, ImageID(\AAImageID));
		
		If IsImage(\AAImageID) 
			FreeImage(\AAImageID)
			\AAImageID = 0
		EndIf
		
	EndWith
	
EndProcedure

;Send an update event (used with Setters and Getters)
Procedure ModernSwitchGadget_PostUpdate(*ModernSwitchGadget.ModernSwitchGadget) 
	
	If *ModernSwitchGadget\UpdatePosted = #False
		*ModernSwitchGadget\UpdatePosted = #True
		PostEvent(#PB_Event_Gadget, *ModernSwitchGadget\Window, *ModernSwitchGadget\Number, #ModernSwitchGadget_EventType_Updated, -1)
	EndIf
	
EndProcedure

;Keyboard Dummy gadget CallBack (hidden StringGadget onboard) => Tab Key and Spacebar
Procedure ModernSwitchGadget_Keyboard_Callback()
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(EventGadget())
	
	If *ModernSwitchGadget = #Null
		ProcedureReturn
	EndIf
	
	
	With *ModernSwitchGadget
		
		Select EventType()
				
			Case #PB_EventType_Focus           
				ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
				PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Focus, 0)
				
				
			Case #PB_EventType_LostFocus        
				ModernSwitchGadget_SetFocus(*ModernSwitchGadget, #False)
				PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_LostFocus, 0)
				
			Case #PB_EventType_Change          
				\State = \State!1
				ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
				ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
				PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
		EndSelect
		
	EndWith
	
EndProcedure

;Callback
Procedure ModernSwitchGadget_Callback() 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(EventGadget())
	
	If *ModernSwitchGadget = #Null
		ProcedureReturn
	EndIf
	
	If EventType() >= #PB_EventType_FirstCustomValue
		*ModernSwitchGadget\Events = EventData()
		
		Select EventType()
				
			Case #ModernSwitchGadget_EventType_Updated
				If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
					ModernSwitchGadget_Update(*ModernSwitchGadget)
					ModernSwitchGadget_Draw(*ModernSwitchGadget)
					ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
				Else
					*ModernSwitchGadget\UpdatePosted = #False
				EndIf
				
		EndSelect
		
	Else
		
		If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
			ModernSwitchGadget_Examine(*ModernSwitchGadget)
			ModernSwitchGadget_Update(*ModernSwitchGadget)
			ModernSwitchGadget_Draw(*ModernSwitchGadget)
			ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
		EndIf
		
	EndIf
	
EndProcedure


;-  4.2  .:Public Procedures for the Gadget:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;Update and redraw the gadget
Procedure UpdateModernSwitchGadget(Gadget.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
		ModernSwitchGadget_Update(*ModernSwitchGadget)
		ModernSwitchGadget_Draw(*ModernSwitchGadget)
		ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
	EndIf
	
EndProcedure

;Free the gadget
Procedure FreeModernSwitchGadget(Gadget.i)
	
	If Not IsGadget(Gadget)
		ProcedureReturn
	EndIf
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	With *ModernSwitchGadget
		
		SetGadgetData(Gadget, #Null)
		UnbindGadgetEvent(\Number, @ModernSwitchGadget_Callback())
		FreeGadget(Gadget)
		
		SetGadgetData(\NumberDummyGadget, #Null)
		UnbindGadgetEvent(\NumberDummyGadget, @ModernSwitchGadget_Keyboard_Callback())
		FreeGadget(\NumberDummyGadget)
		
		If \ImageID
			FreeImage(\ImageID)
		EndIf
		If \AAImageID
			FreeImage(\AAImageID)
		EndIf
		
		ClearStructure(*ModernSwitchGadget, ModernSwitchGadget)
		FreeMemory(*ModernSwitchGadget)
		
	EndWith
	
EndProcedure

;Disable the gadget and change colors
Procedure DisableModernSwitchGadget(Gadget.i, Value.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	With	*ModernSwitchGadget
		
		Select Value
				
			Case 0
				\Disabled = 0
				
			Case 1
				\Disabled  = 1
				\Focus = #False
				
		EndSelect
		
	EndWith
	
	ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
	
EndProcedure

;Select the color theme
Macro ModernSwitchGadget_UseColorTheme()
	
	Select UCase(ColorTheme$)
			
		Case "", "STANDARD"
			*ModernSwitchGadget\ColorBackground = $FFBC7000
			*ModernSwitchGadget\ColorButtonOn = $FFFFFFFF
			*ModernSwitchGadget\ColorButtonOff = $FFFFFFFF
			*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
			*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
			*ModernSwitchGadget\ColorSelected = $FFBC7000
			
		Case "DARK"
			*ModernSwitchGadget\ColorBackground = $FF000000
			*ModernSwitchGadget\ColorButtonOn = $FFAAAAAA
			*ModernSwitchGadget\ColorButtonOff = $FFAAAAAA
			*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
			*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
			*ModernSwitchGadget\ColorSelected = $FFFFFFFF
			
		Default
			;Like "", "STANDARD"
			*ModernSwitchGadget\ColorBackground = $FFBC7000
			*ModernSwitchGadget\ColorButtonOn = $FFFFFFFF
			*ModernSwitchGadget\ColorButtonOff = $FFFFFFFF
			*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
			*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0
			*ModernSwitchGadget\ColorSelected = $FFBC7000
	EndSelect
	
EndMacro

;Create the gadget
Procedure ModernSwitchGadget(Gadget, x, y, w, h, Attributes, Window, ColorTheme$="STANDARD")
	
	; 	Attributes:
	;   -----------	
	; 	#ModernSwitchGadget_None 
	; 	#ModernSwitchGadget_Border						
	; 	#ModernSwitchGadget_Raised 
	; 	#ModernSwitchGadget_Vertical
	; 	#ModernSwitchGadget_Mirrored 
	; 
	; 	ColorTheme$:
	;   ------------
	; 	"STANDARD"
	; 	"DARK"
	
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = AllocateMemory(SizeOf(ModernSwitchGadget))
	Protected Result.i, OldGadgetList.i, DummyGadget.i
	
	InitializeStructure(*ModernSwitchGadget, ModernSwitchGadget)
	OldGadgetList = UseGadgetList(WindowID(Window))
	
	;Create CheckBox gadget with a size=0: Trick To use keyboard (Tab And Space keys)
	DummyGadget = StringGadget(#PB_Any, X, Y, 0, 0, "")
	
	;Create the gadget with attributes Border/Raised
	If Attributes & #ModernSwitchGadget_Border
		Result = ImageGadget(Gadget, X, Y, W, H, 0, #PB_Image_Border)
	ElseIf Attributes & #ModernSwitchGadget_Raised
		Result = ImageGadget(Gadget, X, Y, W, H, 0, #PB_Image_Raised)
	Else
		Result = ImageGadget(Gadget, X, Y, W, H, 0)
	EndIf
	
	UseGadgetList(OldGadgetList)
	If Gadget = #PB_Any
		Gadget = Result
	EndIf
	SetGadgetData(Gadget, *ModernSwitchGadget)
	SetGadgetData(DummyGadget, *ModernSwitchGadget)
	
	;Fills the structures
	With *ModernSwitchGadget
		
		;Gadget
		\Number = Gadget
		\NumberDummyGadget = DummyGadget
		\X = x
		\Y = y
		\W = w
		\H = h
		\W2 = w*2
		\H2 = h*2
		\Window = Window																						
		\Attributes = Attributes
		\ImageID =	CreateImage(#PB_Any,\W2,\H2,32,#PB_Image_Transparent)
		\MarginButton = DesktopScaledX(6)
		
		;Layout
		\Layout\x = \X
		\Layout\y = \Y
		\Layout\w = \W
		\Layout\h = \H
		
		;Theme
		\ColorThemeName$ = ColorTheme$
		
	EndWith
	
	;Color Theme
	ModernSwitchGadget_UseColorTheme()
	
	;Bind Dummy Gadget CallBack
	BindGadgetEvent(DummyGadget, @ModernSwitchGadget_Keyboard_Callback())
	;Bind Gadget CallBack
	BindGadgetEvent(Gadget, @ModernSwitchGadget_Callback())
	
	UpdateModernSwitchGadget(Gadget)
	
	
	ProcedureReturn Result
	
EndProcedure


;-  4.3  .:Set & Get Procedures:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

;Set active gadget.
Procedure.i SetActiveModernSwitchGadget(Gadget.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
	ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
	
EndProcedure

;Get wether active gadget.
Procedure.i GetActiveModernSwitchGadget(Gadget.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	ProcedureReturn *ModernSwitchGadget\Focus
	
EndProcedure


;Get an attribute value.
Procedure.i GetModernSwitchGadgetAttribute(Gadget.i, Attribute.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select Attribute
		Case 	#ModernSwitchGadget_Vertical,
		     	#ModernSwitchGadget_Border,						
		     	#ModernSwitchGadget_Raised, 
		     	#ModernSwitchGadget_Mirrored,         
		     	#ModernSwitchGadget_Disabled
			
			If *ModernSwitchGadget\Attributes & Attribute
				ProcedureReturn #True
			Else
				ProcedureReturn #False
			EndIf
			
		Default
			ProcedureReturn -1
			
	EndSelect
	
EndProcedure

;Set/Change the data value of the gadget. 
Procedure SetModernSwitchGadgetData(Gadget.i, DataValue.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	Protected *ModernSwitchGadget2.ModernSwitchGadget = GetGadgetData(*ModernSwitchGadget\NumberDummyGadget)
	
	*ModernSwitchGadget\DataValue = DataValue
	*ModernSwitchGadget2\DataValue = DataValue
	
EndProcedure

;Get the data value of the gadget.
Procedure.i GetModernSwitchGadgetData(Gadget.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	ProcedureReturn *ModernSwitchGadget\DataValue
	
EndProcedure

;Change the state of the gadget (ON/OFF).
Procedure ChangeModernSwitchGadgetState(Gadget.i, ChangeFocusState.i = #True) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	With *ModernSwitchGadget
		
		Select \State
				
				;OFF->ON
			Case #ModernSwitchGadgetState_OFF
				\State = #ModernSwitchGadgetState_ON
				If ChangeFocusState
					ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
				EndIf
				
				;ON->OFF
			Case #ModernSwitchGadgetState_ON
				\State = #ModernSwitchGadgetState_OFF	
				If ChangeFocusState
					ModernSwitchGadget_SetFocus(*ModernSwitchGadget, #False)
				EndIf
				
		EndSelect
		
		ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
		PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
		PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Focus, 0)
		
	EndWith
	
EndProcedure

;Set the state of the gadget (ON/OFF).
Procedure SetModernSwitchGadgetState(Gadget.i, State.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	With *ModernSwitchGadget
		
		Select State
				
			Case #ModernSwitchGadgetState_OFF,#ModernSwitchGadgetState_ON
				\State = State	
				ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
				ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
				PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
				PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Focus, 0)				
				
		EndSelect
		
	EndWith
	
EndProcedure

;Get the state of the gadget.
Procedure.i GetModernSwitchGadgetState(Gadget.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	ProcedureReturn *ModernSwitchGadget\State
	
EndProcedure

;Set/Change gadget color by type
Procedure SetModernSwitchGadgetColor(Gadget.i, Type.i, ColorRGBA.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select Type
			
		Case #ModernSwitchGadgetColor_Background
			*ModernSwitchGadget\ColorBackground = ColorRGBA
		Case #ModernSwitchGadgetColor_ButtonOff
			*ModernSwitchGadget\ColorButtonOff = ColorRGBA
		Case #ModernSwitchGadgetColor_ButtonOn
			*ModernSwitchGadget\ColorButtonOn = ColorRGBA	
		Case #ModernSwitchGadgetColor_Selected
			*ModernSwitchGadget\ColorSelected = ColorRGBA
		Case 	#ModernSwitchGadgetColor_BackgroundDisabled
			*ModernSwitchGadget\ColorBackgroundDisabled = ColorRGBA
		Case #ModernSwitchGadgetColor_ButtonDisabled
			*ModernSwitchGadget\ColorButtonDisabled = ColorRGBA
			
	EndSelect
	
	ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
	
EndProcedure

Procedure GetModernSwitchGadgetColor(Gadget.i, Type.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select Type
			
			;Theme colors
		Case #ModernSwitchGadgetColor_Background
			ProcedureReturn *ModernSwitchGadget\ColorBackground
		Case #ModernSwitchGadgetColor_ButtonOff
			ProcedureReturn *ModernSwitchGadget\ColorButtonOff
		Case #ModernSwitchGadgetColor_ButtonOn
			ProcedureReturn *ModernSwitchGadget\ColorButtonOn
		Case #ModernSwitchGadgetColor_Selected	
			ProcedureReturn *ModernSwitchGadget\ColorSelected
		Case 	#ModernSwitchGadgetColor_BackgroundDisabled
			ProcedureReturn *ModernSwitchGadget\ColorBackgroundDisabled
		Case 	#ModernSwitchGadgetColor_ButtonDisabled
			ProcedureReturn *ModernSwitchGadget\ColorButtonDisabled
			
			;Current colors
		Case 	#ModernSwitchGadgetColor_CurrentColorBackground
			ProcedureReturn *ModernSwitchGadget\CurrentColorBackground
		Case  	#ModernSwitchGadgetColor_CurrentColorButtonOn
			ProcedureReturn *ModernSwitchGadget\CurrentColorButtonOn
		Case  	#ModernSwitchGadgetColor_CurrentColorButtonOff
			ProcedureReturn *ModernSwitchGadget\CurrentColorButtonOff
		Case  	#ModernSwitchGadgetColor_CurrentColorSelected
			ProcedureReturn *ModernSwitchGadget\CurrentColorSelected
			
	EndSelect
	
EndProcedure


;Set/Change gadget all colors in once
Procedure.i SetModernSwitchGadgetColors(Gadget.i, ColorBackgroundRGBA.i, ColorButtonOffRGBA.i, ColorButtonOnRGBA.i, ColorSelectedRGBA.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	*ModernSwitchGadget\ColorBackground = ColorBackgroundRGBA
	*ModernSwitchGadget\ColorButtonOff = ColorButtonOffRGBA
	*ModernSwitchGadget\ColorButtonOn = ColorButtonOnRGBA	
	*ModernSwitchGadget\ColorSelected = ColorSelectedRGBA
	
	ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
	
EndProcedure

;Set/Change gadget color theme
Procedure SetModernSwitchGadgetColorTheme(Gadget.i, ColorTheme.s) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	With	*ModernSwitchGadget
		
		;Color Theme
		Select UCase(ColorTheme)	
			Case "", "STANDARD"
				\ColorThemeName$ = ColorTheme
				\ColorBackground = $FFBC7000
				\ColorButtonOn = $FFFFFFFF
				\ColorButtonOff = $FFFFFFFF
				\ColorBackgroundDisabled = $FF808080								;
				\ColorButtonDisabled = $FFC0C0C0
				\ColorSelected = $FFBC7000
				
			Case "DARK"
				\ColorThemeName$ = ColorTheme
				\ColorBackground = $FF000000
				\ColorButtonOn = $FFAAAAAA
				\ColorButtonOff = $FFAAAAAA
				\ColorBackgroundDisabled = $FF808080								;
				\ColorButtonDisabled = $FFC0C0C0
				\ColorSelected = $FFFFFFFF
				
			Default
				DebuggerError("Color Theme Unknown !")
				
		EndSelect
		
	EndWith
	
	ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
	
EndProcedure 

;Get color theme name
Procedure.s GetModernSwitchGadgetColorTheme(Gadget.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	With	*ModernSwitchGadget
		
		;Color Theme
		Select \ColorThemeName$
			Case "", "STANDARD",  "DARK"
				ProcedureReturn \ColorThemeName$
				
			Default
				;DebuggerError("Color Theme Unknown !")
				ProcedureReturn "Color Theme Unknown !"
		EndSelect
		
	EndWith
	
EndProcedure 
;- BOTTOM
;- END
;-


;- Example
CompilerIf #PB_Compiler_IsMainFile
	
	Enumeration 1
		#imgGadget
		#imgGadgetDARK
		#imgGadgetV
		#imgGadgetM
		#imgGadgetMV
		#imgGadgetDisabled
		#btn
	EndEnumeration
	
	Macro CheckerBoard(cb_imgIn,cb_szBlock) ; netmaestro 2023
		cb_chex = CreateImage(#PB_Any,2,2,24,#White)
		StartDrawing(ImageOutput(cb_chex))
		Plot(1,0,$C8C8C8):Plot(0,1,$C8C8C8)
		StopDrawing()
		ResizeImage(cb_chex,cb_szBlock*2,cb_szBlock*2,#PB_Image_Raw)
		StartVectorDrawing(ImageVectorOutput(cb_imgIn))
		VectorSourceImage(ImageID(cb_chex),255,cb_szBlock*2,cb_szBlock*2,#PB_VectorImage_Repeat)
		FillVectorOutput()
		StopVectorDrawing()
		FreeImage(cb_chex)
	EndMacro
	
	
	;Test DPI
	Define W
	ExamineDesktops()
	W=DesktopWidth(0)/2
	
	
	Define.i cb_bkgnd, cb_chex ; Checkerboard background
	
	If OpenWindow(0, 0, 0, W, 400, "ModernSwitchGadget Tests", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
		; 	If OpenWindow(0, 0, 0, DesktopUnscaledX(W), DesktopUnscaledY(400), "ModernSwitchGadget Tests", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
		cb_bkgnd=CreateImage(#PB_Any,w,400)         ; checkerboard background
		checkerboard(cb_bkgnd,10)										;       "          "
		ImageGadget(0,0,0,w,400,ImageID(cb_bkgnd))	;       "          "
		DisableGadget(0,1)
		
		
		ModernSwitchGadget(#imgGadget, 10, 60, 60, 30, #ModernSwitchGadget_None,0);
		ModernSwitchGadget(#imgGadgetDARK,  10, 100, 60, 30, #ModernSwitchGadget_None,0,"DARK")
		ModernSwitchGadget(#imgGadgetV, 100, 60, 30, 60, #ModernSwitchGadget_Vertical,0)
		ModernSwitchGadget(#imgGadgetM, 10, 160, 60, 30, #ModernSwitchGadget_Mirrored,0)
		ModernSwitchGadget(#imgGadgetMV, 100, 160, 30, 60, #ModernSwitchGadget_Vertical|#ModernSwitchGadget_Mirrored,0)
		ModernSwitchGadget(#imgGadgetDisabled, 10, 200, 40, 20, #ModernSwitchGadget_None,0);
		
		ButtonGadget(#btn,10,240,60,30,"ok")
		
		
		GadgetToolTip(#imgGadget, "STANDARD")
		GadgetToolTip(#imgGadgetDARK, "DARK")
		GadgetToolTip(#imgGadgetV, "VERTICAL (and customized)")
		GadgetToolTip(#imgGadgetM, "MIRRORED")
		GadgetToolTip(#imgGadgetMV, "VERTICAL & MIRRORED")
		GadgetToolTip(#imgGadgetDisabled, "Disabled")
		
		SetActiveModernSwitchGadget(#imgGadget)
		
		
;- TEST
; 		
; 		TEST ModernSwitchGadget Procedures
; 		=======================================
; 		UpdateModernSwitchGadget(#imgGadget);ok
; 		FreeModernSwitchGadget(#imgGadgetDARK);ok
		DisableModernSwitchGadget(#imgGadgetDisabled, #True);ok
; 		
; 		DisableModernSwitchGadget(#imgGadgetDisabled, #False);ok    
; 		SetActiveModernSwitchGadget(#imgGadgetDARK)					 ;ok
; 		Debug GetActiveModernSwitchGadget(#imgGadget)				 ;ok
; 		SetModernSwitchGadgetData(#imgGadget, 10)						 ;ok
; 		Debug GetModernSwitchGadgetData(#imgGadget)					 ;ok
; 		ChangeModernSwitchGadgetState(#imgGadget)						 ;ok
; 		ChangeModernSwitchGadgetState(#imgGadget)						 ;ok
; 		SetModernSwitchGadgetState(#imgGadget, #ModernSwitchGadgetState_ON);ok
; 		Debug GetModernSwitchGadgetState(#imgGadget)											 ;ok
; 		SetModernSwitchGadgetState(#imgGadget, #ModernSwitchGadgetState_OFF);ok
; 		Debug GetModernSwitchGadgetState(#imgGadget)												;ok
; 		
; 		TEST attributes
; 		===============
; 		Debug GetModernSwitchGadgetAttribute(#imgGadgetMV, #ModernSwitchGadget_Vertical);ok
; 		Debug GetModernSwitchGadgetAttribute(#imgGadget,   #ModernSwitchGadget_Border)	;ok						
; 		Debug GetModernSwitchGadgetAttribute(#imgGadget,   #ModernSwitchGadget_Raised)	;ok 
; 		Debug GetModernSwitchGadgetAttribute(#imgGadgetMV, #ModernSwitchGadget_Mirrored);ok       
; 		Debug GetModernSwitchGadgetAttribute(#imgGadget,   #ModernSwitchGadget_Disabled);ok
; 		
; 		Tests colors
; 		==============
; 		Theme colors
; 		Define a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_Background);ok
; 		Define a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_ButtonOff)	;ok
; 		Define a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_ButtonOn)	;ok
; 		Define a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_Selected)	;ok
; 		Define a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_BackgroundDisabled);ok
; 		Define a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_ButtonDisabled)		;ok
; 		Current colors
; 		Define a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_CurrentColorBackground);ok
; 		Define a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_CurrentColorButtonOff)	;ok	
; 		Define a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_CurrentColorButtonOn)	;ok
; 		Define a=GetModernSwitchGadgetColor(#imgGadget, #ModernSwitchGadgetColor_CurrentColorSelected)	;ok
; 		Debug Hex(a)																																										;
; 		Debug Red(a)
; 		Debug Green(a)
; 		Debug Blue(a)
; 		Debug Alpha(a)		
; 		\ColorBackground = $FFBC7000
; 		\ColorButtonOn = $FFFFFFFF
; 		\ColorButtonOff = $FFFFFFFF
; 		\ColorBackgroundDisabled = $FF808080								;
; 		\ColorButtonDisabled = $FFC0C0C0
; 		\ColorSelected = $FFBC7000
; 		ShowMemoryViewer(@a,20)
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_Background, $801977F3);ok
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_ButtonOn, $FF3FDC30)	 ;ok
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_ButtonOff, $800D26FF) ;ok
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_Selected, $806E2B5C)
; 		SetModernSwitchGadgetColor(#imgGadgetDisabled, #ModernSwitchGadgetColor_BackgroundDisabled, $400000FF);ok
; 		SetModernSwitchGadgetColor(#imgGadgetDisabled, #ModernSwitchGadgetColor_ButtonDisabled, $4000FFFF)		;ok
; 		SetModernSwitchGadgetColors(#imgGadgetMV, $801977F3, $FF3FDC30, $800D26FF, $806E2B5C)									;ok
; 		SetModernSwitchGadgetColorTheme(#imgGadgetMV, "DARK")																									;ok
; 		Debug GetModernSwitchGadgetColorTheme(#imgGadgetMV)																										;ok
; 		SetModernSwitchGadgetColorTheme(#imgGadgetMV, "ZARK.")																								;Raise an error => ok 
; 		
; 		
; 		
; 		Tests All PB procedures
; 		============================
; 		DisableGadget(#imgGadget, 1);Gadget disabled but colors are not changed => Use DisableModernSwitchGadget(
; 		FreeGadget()								;No => Use FreeModernSwitchGadget()
; 		Debug GadgetHeight(#imgGadget);ok
; 		Debug GadgetID(#imgGadget)		;ok
; 		GadgetToolTip(#imgGadget, "Tooltip");ok
; 		Debug GadgetType(#imgGadget)				;=#PB_GadgetType_Image
; 		Debug #PB_GadgetType_Image
; 		Debug GadgetWidth(#imgGadget,);ok
; 		Debug GadgetX(#imgGadget, #PB_Gadget_ContainerCoordinate );ok
; 		Debug GadgetX(#imgGadget, #PB_Gadget_WindowCoordinate)		;ok
; 		Debug GadgetX(#imgGadget, #PB_Gadget_ScreenCoordinate)		;ok
; 		Debug GadgetY(#imgGadget, #PB_Gadget_ContainerCoordinate );ok
; 		Debug GadgetY(#imgGadget, #PB_Gadget_WindowCoordinate)		;ok
; 		Debug GadgetY(#imgGadget, #PB_Gadget_ScreenCoordinate)		;ok
; 		
; 		Debug GetActiveGadget()									;No => Use GetActiveModernSwitchGadget(#imgGadget)
; 		GetGadgetAttribute(#imgGadget, Attribut);No => Use GetModernSwitchGadgetAttribute()
; 		GetGadgetColor(#imgGadget, TypeCouleur)	;No => Use GetModernSwitchGadgetColor(Gadget.i, Type.i)
; 		GetGadgetData(#imgGadget)								;No => Use GetModernSwitchGadgetData(Gadget.i) 
; 		Debug GetGadgetFont(#imgGadget)					;No effects
; 		Debug GetGadgetState(#imgGadget)				;No effects => Use GetModernSwitchGadgetState(Gadget.i) 
; 		Debug GetGadgetText(#imgGadget)					;No effects
; 		HideGadget(#imgGadget, 1)								;ok
; 		Debug IsGadget(#imgGadget)							;ok
; 		SetActiveGadget(#imgGadget)							;No effects => Use SetActiveModernSwitchGadget(Gadget.i)
; 		SetGadgetAttribute(#imgGadget, Attribut, Valeur);No  
; 		SetGadgetColor(#imgGadget, TypeCouleur, Couleur);No => Use SetModernSwitchGadgetColor(Gadget.i, Type.i, ColorRGBA.i)  
; 		SetGadgetData(#imgGadget, Valeur)								;No => Use SetModernSwitchGadgetData(Gadget.i, DataValue.i)
; 		LoadFont(1, "Arial", 24)
; 		SetGadgetFont(#imgGadget, 1);ok but no effects
; 		SetGadgetState(#imgGadget,1);NOOOO => Use SetModernSwitchGadgetState(Gadget.i, State.i)
; 		SetGadgetText(#imgGadget, "Text");No, strange behaviour, don't use it
; 		
; 		
; 		
; 		Strange DPI...
; 		==================
; 		TEST With the compilator dpi switch on/off
; 			; ModernSwitchGadget(#imgGadget, DesktopUnscaledX(10), 60, DesktopUnscaledX(60), 30, #ModernSwitchGadget_None, 0);
; 			; ModernSwitchGadget(#imgGadgetDARK,  DesktopScaledX(10), 100, DesktopScaledX(60), 30, #ModernSwitchGadget_None, 0, "DARK")
; 			StartDrawing(WindowOutput(0))
; 			LineXY(10, 0, 10, 400, #Red)
; 			LineXY(DesktopUnscaledX(10+60), 0, DesktopUnscaledX(10+60), 400, #Blue)
; 			LineXY(DesktopScaledX(10+60), 0, DesktopScaledX(10+60), 400, #Green)
; 			LineXY(10+60, 0, 10+60, 400, #Red)
; 			LineXY(0, 0, 0, DesktopScaledY(400), #Green)
; 			LineXY(DesktopScaledX(W)-1, 0, DesktopScaledX(W)-1, DesktopScaledY(400), #Green)
; 			DrawText(300, 50, "Normal", #Red, #White)
; 			DrawText(300, 100, "Unscaled", #Blue, #White)
; 			DrawText(300, 150, "Scaled", #Green, #White)
; 			StopDrawing()
			
			
			
			
			Define Event
			
			Repeat
				
				Event = WaitWindowEvent()
				
				Select Event
						
					Case #PB_Event_Gadget
						;- Events
						Select EventGadget()
							Case #imgGadget
								Select EventType()
										;No Test custom event => No public custom events
										
										;Test PB events
									Case #PB_EventType_Change
										Debug "#imgGadget Changed"
										Select GetModernSwitchGadgetState(#imgGadget)
											Case #ModernSwitchGadgetState_ON
												Debug "ON"
												DisableModernSwitchGadget(#imgGadgetDisabled, #False)
											Case #ModernSwitchGadgetState_OFF
												Debug "OFF"
												DisableModernSwitchGadget(#imgGadgetDisabled, #True)
										EndSelect
										
									Case #PB_EventType_LeftClick 
										;Debug "LeftClick";ok
										
									Case #PB_EventType_RightClick
										;Debug "RightClick";ok
										
									Case #PB_EventType_LeftDoubleClick
										;Debug "DoubleClick";ok
										
									Case #PB_EventType_RightDoubleClick
										;Debug "RightDoubleClick";ok
										
									Case #PB_EventType_Focus
										;Debug "Focus #imgGadget";ok
										
									Case #PB_EventType_LostFocus
										;Debug "LostFocus #imgGadget";ok
										
								EndSelect
								
							Case #btn
								Select EventType()
									Case #PB_EventType_LeftClick
										Debug "Button Left Click"		
								EndSelect
								
						EndSelect
				EndSelect
				
			Until Event = #PB_Event_CloseWindow
		EndIf
		
	CompilerEndIf

Mesa.
User avatar
holzhacker
Enthusiast
Enthusiast
Posts: 123
Joined: Mon Mar 08, 2010 9:14 pm
Location: "Mens sana in corpore sano"
Contact:

Re: modern style switchgadget

Post by holzhacker »

Hello good afternoon!
So it needs some tests :oops:
This is the effect that occurred in PB 6.0 running on ubuntu 22.04.

Image
Greetings and thanks!

Romerio Medeiros
romerio@gmail.com
Mesa
Enthusiast
Enthusiast
Posts: 349
Joined: Fri Feb 24, 2012 10:19 am

Re: modern style switchgadget

Post by Mesa »

@holzhacker: Thanks, the problem appears with the first version of the code ( v0.5.5 Beta), the second version (v0.9.0 Beta) or both ?

M.
Mesa
Enthusiast
Enthusiast
Posts: 349
Joined: Fri Feb 24, 2012 10:19 am

Re: modern style switchgadget

Post by Mesa »

Module for the simple ModernSwitchGadget:

Code: Select all

;- TOP

;.-------------------------------------------------------------------------------------------------
;|
;|  Title            : ModernSwitchGadget
;|  Version          : v0.5.6 Beta
;|  Author					 : Mesa
;|  Copyright        : 
;|                     
;|  PureBasic        : 5.70+
;|  
;|  Operating System : Windows (XP to W11+), Linux, MacOS
;|  Processor        : x86, x64
;|
;|  API							 : No api used
;|
;|-------------------------------------------------------------------------------------------------
;|
;|  Description      : Module Switch Gadget with a "modern" style
;|
;|  Forum Topic      : http://www.purebasic.fr/french/viewtopic.php?t=18876
;|                     http://www.purebasic.fr/english/viewtopic.php?t=80957
;|  Website          : 
;|
;|  Documentation    : 
;|
;|	Date 						 : 03/2023
;|
;|  Misc.						 : I confess to being inspired (in a shameless way) in large part by the robust 
;|										 code of Stargate's TabBar gadget. So, if you have analyzed his code then mine 
;|										 will be very easy to understand and improve.
;|
;.-------------------------------------------------------------------------------------------------



;.-------------------------------------------------------------------------------------------------
;|
;|  How to  use 		 : 1) Add UseModule ModernSwitchGadget		 
;|									 : 2) Add ModernSwitchGadget(...)
;|  			           : 3) Nothing else, except using these PB standard event type inside the loop : 
;|  				         : 		#PB_EventType_Change, 
;| 												#PB_EventType_LeftClick, #PB_EventType_RightClick, 
;|												#PB_EventType_LeftDoubleClick, #PB_EventType_RightDoubleClick	
;|																		...
;|                     
;|  Color theme      : To add or modify a color theme
;|									 : -> Modify the Macro ModernSwitchGadget_UseColorTheme()
;|
;|	Shape						 : To modify the gadget shape
;|									 : 1) Add Constants and Modify the Structures if needed
;|									 : 2) Modify the procedure ModernSwitchGadget_Layout() if needed
;|									 : 3) Modify the Procedure ModernSwitchGadget_Update(...) if needed 
;|									 : 4) Modify the Procedure ModernSwitchGadget_Draw(...) 
;|
;.-------------------------------------------------------------------------------------------------



;.-------------------------------------------------------------------------------------------------
;|
;|  Gadget Attributes
;|  ================================================================
;|  		#ModernSwitchGadget_None 
;|  		#ModernSwitchGadget_Border						
;|  		#ModernSwitchGadget_Raised 
;|  		#ModernSwitchGadget_Vertical
;|  		#ModernSwitchGadget_Mirrored         
;|  		#ModernSwitchGadget_Disabled	
;|  	
;|  Gadget States
;|  =================
;|  		#ModernSwitchGadgetState_OFF
;|  		#ModernSwitchGadgetState_ON
;|  	
;|  Gadget Colors
;|  ================================================================
;|  		Theme colors
;|  		#ModernSwitchGadgetColor_Background									;
;|  		#ModernSwitchGadgetColor_ButtonOff
;|  		#ModernSwitchGadgetColor_ButtonOn
;|
;| 	Gadget Events
;|  ================================================================
;|			=> Usefull PureBasic EventTypes
;|  			 #PB_EventType_Change 
;|  			 
;|			-> Useless but working PureBasic EventTypes
;|				 #PB_EventType_LeftClick,  #PB_EventType_LeftDoubleClick 
;|				 #PB_EventType_RightClick, #PB_EventType_RightDoubleClick																																																																...
;|
;|  			 
;|	Procedures
;|  ================================================================
;|  UpdateModernSwitchGadget()
;|  FreeModernSwitchGadget()
;|  DisableModernSwitchGadget()
;|
;|  ModernSwitchGadget()
;|	
;|  GetModernSwitchGadgetAttribute() 
;|	 
;|  SetModernSwitchGadgetData()
;|  GetModernSwitchGadgetData() 
;|	
;|  ChangeModernSwitchGadgetState() 
;|  SetModernSwitchGadgetState() 	
;|  GetModernSwitchGadgetState() 
;|	
;|  SetModernSwitchGadgetColor()  
;|  SetModernSwitchGadgetColors()
;|  SetModernSwitchGadgetColorTheme() 
;|
;.-------------------------------------------------------------------------------------------------



;.-------------------------------------------------------------------------------------------------
;|
;|  License Mesa.
;|  The license Mesa is, do what you like but make the World better, easier and enjoyable.
;|
;|
;|
;| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;| SOFTWARE.
;| 
;.-------------------------------------------------------------------------------------------------




;-  >M<  .:Declare Module:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯



DeclareModule ModernSwitchGadget
	
CompilerIf #PB_Compiler_IsMainFile
	EnableExplicit
CompilerEndIf



;-  1        .:Constantes:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


; Gadget Attributes
EnumerationBinary Attributes
	#ModernSwitchGadget_None 
	#ModernSwitchGadget_Border						
	#ModernSwitchGadget_Raised 
	#ModernSwitchGadget_Vertical
	#ModernSwitchGadget_Mirrored         
	#ModernSwitchGadget_Disabled	
EndEnumeration

; Gadget States
Enumeration States
	#ModernSwitchGadgetState_OFF
	#ModernSwitchGadgetState_ON
EndEnumeration

;Gadget Color Types
Enumeration Color_Types
	#ModernSwitchGadgetColor_Background									;
	#ModernSwitchGadgetColor_ButtonOn
	#ModernSwitchGadgetColor_ButtonOff
	#ModernSwitchGadgetColor_CurrentButton
EndEnumeration

; Gadget Events; No Public EventType
Enumeration Events #PB_EventType_FirstCustomValue
	#ModernSwitchGadget_EventType_Updated      ; The gadget has updated (internal)
EndEnumeration


;-  2        .:Structures:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

Structure ModernSwitchGadget_Layout
	;RoundedBox layout
	x.i			; The position and size of the RoundedBox in the current drawing output. 
	y.i
	w.i
	h.i
	arcx.i	;The radius of the rounded corners in the x and y direction. 
	arcy.i
	
	;Cicle button layout
	xc.i		; The position and size of the circle = button on/off
	yc.i
	r.i
EndStructure

Structure ModernSwitchGadget
	Number.i                          ; Gadget ID, position and size
	X.i
	Y.i
	W.i
	H.i
	W2.i															; W*2 used for antialiasing
	H2.i															; H*2	used for antialiasing
	Window.i													; Window parent ID
	ImageID.i													; Image twice as large as needed for antialiasing
	AAImageID.i											  ; Image will be scaled to the correct size while taking advantage of antialiasing
	DataValue.i												; Used with GadgetData()
	Attributes.i											; Attributes
	State.i														; 0=Left=OFF, 1=Right=ON
	Disabled.i												; 0=Enabled,  1=Disabled
	ColorBackground.i									; Background Color
	ColorButtonOn.i										;	Button color when gadget is ON
	ColorButtonOff.i									; Button color when gadget is OFF
	ColorBackgroundDisabled.i					; Special color when the gadget is disabled
	ColorButtonDisabled.i							; Special color when the gadget is disabled 
	CurrentColorBackground.i					; Current colors
	CurrentColorButtonOn.i
	CurrentColorButtonOff.i
	CurrentColorButton.i
	MarginButton.i										; Button margin on the left/right
	UpdatePosted.i										; 0=Do nothing, 1=Do a gadget update 																	; 	
	Events.i													; EventData() with a custom Event
	Layout.ModernSwitchGadget_Layout	; Layout
EndStructure


;-  3        .:Initializations:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
; NOTHING... because there are NO GLOBAL variables
; Everything is in the GadgetData
; And "initializations" are made inside the Procedure ModernSwitchGadget()


;-  4a      .:Declaration Procedures:. 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;Update and redraw the gadget
Declare.i UpdateModernSwitchGadget(Gadget.i)
	
;Free the gadget
Declare.i FreeModernSwitchGadget(Gadget.i)
		
;Disable the gadget and change colors
Declare.i DisableModernSwitchGadget(Gadget.i, Value.i)
	
;Create the gadget
Declare.i ModernSwitchGadget(Gadget, x, y, w, h, Attributes, Window, ColorTheme$="STANDARD")
	
	; 	Attributes:
	;   -----------	
	; 	#ModernSwitchGadget_None 
	; 	#ModernSwitchGadget_Border						
	; 	#ModernSwitchGadget_Raised 
	; 	#ModernSwitchGadget_Vertical
	; 	#ModernSwitchGadget_Mirrored 
	; 
	; 	ColorTheme$:
	;   ------------
	; 	"STANDARD"
	; 	"DARK"
	
	
	
;Get an attribute value.
Declare.i GetModernSwitchGadgetAttribute(Gadget.i, Attribute.i) 
	
;Set/Change the data value of the gadget. 
Declare SetModernSwitchGadgetData(Gadget.i, DataValue.i)
	
;Get the data value of the gadget.
Declare.i GetModernSwitchGadgetData(Gadget.i) 
	
;Change the state of the gadget (ON/OFF).
Declare.i ChangeModernSwitchGadgetState(Gadget.i) 
	
;Set the state of the gadget (ON/OFF).
Declare SetModernSwitchGadgetState(Gadget.i, State.i) 
	
;Get the state of the gadget.
Declare.i GetModernSwitchGadgetState(Gadget.i) 
	
;Set/Change gadget color by type
Declare SetModernSwitchGadgetColor(Gadget.i, Type.i, ColorRGBA.i) 
	
;Set/Change gadget all colors
Declare.i SetModernSwitchGadgetColors(Gadget.i, ColorBackgroundRGBA.i, ColorButtonOffRGBA.i, ColorButtonOnRGBA.i)
	
;Set/Change gadget color theme
Declare.i SetModernSwitchGadgetColorTheme(Gadget.i, ColorTheme.s) 


EndDeclareModule





;-  >M<  .:Module:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;-  4b      .:Procedures & Macros:. 
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


Module ModernSwitchGadget
;-  4.1     .:Private procedures for internal calculations ! Not for use !:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;StartDrawing
Procedure.i ModernSwitchGadget_StartDrawing(*ModernSwitchGadget.ModernSwitchGadget)
	ProcedureReturn StartDrawing(ImageOutput(*ModernSwitchGadget\ImageID))
EndProcedure

;StopDrawing
Procedure.i ModernSwitchGadget_StopDrawing(*ModernSwitchGadget.ModernSwitchGadget)
	StopDrawing()
EndProcedure

;AntiAliasing
Procedure.i ModernSwitchGadget_Antialiasing(*ModernSwitchGadget.ModernSwitchGadget)
	
	With *ModernSwitchGadget 
		
		;Stop drawing because of the antialiasing which is made in resizing the image
		ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
		
		;Antialiasing by resizing the image
		\AAImageID=CopyImage(\ImageID,#PB_Any)
		ResizeImage(\AAImageID,\W,\H)
		
		ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
		
	EndWith
	
EndProcedure

;Layout
Procedure.i ModernSwitchGadget_Layout(*ModernSwitchGadget.ModernSwitchGadget)
	
	Protected x, y, w, h, arcx, arcy, xc, yc, r
	
	With *ModernSwitchGadget
		
		x=0
		y=0
		w=\w2
		h=\h2
		
		Select \State
			Case 0
				;OFF
				If (\Attributes & #ModernSwitchGadget_Vertical) * (\Attributes & #ModernSwitchGadget_Mirrored)
					arcx=\w:arcy=\w:xc=\w:yc=\h*2-\w:r=\w-\MarginButton					
				ElseIf 	\Attributes & #ModernSwitchGadget_Vertical
					arcx=\w:arcy=\w:xc=\w:yc=\w:r=\w-\MarginButton
				ElseIf \Attributes & #ModernSwitchGadget_Mirrored
					arcx=\h:arcy=\h:xc=\w*2-\h:yc=\h:r=\h-\MarginButton
				Else
					arcx=\h:arcy=\h:xc=\h:yc=\h:r=\h-\MarginButton
				EndIf
				
			Case 1
				;ON
				If \Attributes & #ModernSwitchGadget_Vertical * \Attributes & #ModernSwitchGadget_Mirrored
					arcx=\w:arcy=\w:xc=\w:yc=\w:r=\w-\MarginButton
				ElseIf \Attributes & #ModernSwitchGadget_Vertical
					arcx=\w:arcy=\w:xc=\w:yc=\h*2-\w:r=\w-\MarginButton
				ElseIf \Attributes & #ModernSwitchGadget_Mirrored
					arcx=\h:arcy=\h:xc=\h:yc=\h:r=\h-\MarginButton		
				Else
					arcx=\h:arcy=\h:xc=\w*2-\h:yc=\h:r=\h-\MarginButton
				EndIf
		EndSelect
		
		
		\Layout\x = x
		\Layout\y = y
		\Layout\w = w
		\Layout\h = h
		\Layout\arcx = arcx
		\Layout\arcy = arcy
		\Layout\xc = xc
		\Layout\yc = yc
		\Layout\r = r
		
	EndWith
	
EndProcedure

;Events
Procedure.i ModernSwitchGadget_Examine(*ModernSwitchGadget.ModernSwitchGadget)
	
	With *ModernSwitchGadget
		
		If \Disabled = #False
			Select EventType()
					
				Case #PB_EventType_LeftDoubleClick 
					\State = \State!1
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
					
				Case #PB_EventType_LeftClick 
					\State = \State!1
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
					
			EndSelect
		EndIf	
		
	EndWith
	
EndProcedure

;Internal gadget update
Procedure.i ModernSwitchGadget_Update(*ModernSwitchGadget.ModernSwitchGadget) 
	
	With *ModernSwitchGadget
		
		;Colors
		If \Disabled
			\CurrentColorBackground = \ColorBackgroundDisabled
			\CurrentColorButtonOff = \ColorButtonDisabled
			\CurrentColorButtonOn = \ColorButtonDisabled
			If \State = #ModernSwitchGadgetState_OFF
				\CurrentColorButton = \ColorButtonDisabled
			Else
				\CurrentColorButton = \ColorButtonDisabled
			EndIf
		Else
			\CurrentColorBackground = \ColorBackground
			\CurrentColorButtonOff = \ColorButtonOff
			\CurrentColorButtonOn = \ColorButtonOn
			If \State = #ModernSwitchGadgetState_OFF
				\CurrentColorButton = \CurrentColorButtonOff
			Else
				\CurrentColorButton = \CurrentColorButtonOn
			EndIf
			
		EndIf
		
		;Layout
		ModernSwitchGadget_Layout(*ModernSwitchGadget)
		
		
		*ModernSwitchGadget\UpdatePosted = #False
		
	EndWith
	
EndProcedure

;Draw the gadget
Procedure.i ModernSwitchGadget_Draw(*ModernSwitchGadget.ModernSwitchGadget)
	
	With *ModernSwitchGadget
		
		DrawingMode(#PB_2DDrawing_AllChannels)
		RoundBox(\Layout\x,\Layout\y,\Layout\w,\Layout\h,\Layout\arcx,\Layout\arcy, \CurrentColorBackground)
		DrawingMode(#PB_2DDrawing_AlphaBlend)
		RoundBox(\Layout\x,\Layout\y,\Layout\w,\Layout\h,\Layout\arcx,\Layout\arcy,\CurrentColorBackground)
		Circle(\Layout\xc,\Layout\yc,\Layout\r,\CurrentColorButton)
		
		ModernSwitchGadget_Antialiasing(*ModernSwitchGadget)
		
		SetGadgetState(\Number, ImageID(\AAImageID));
		
		If IsImage(\AAImageID) 
			FreeImage(\AAImageID)
		EndIf
		
	EndWith
	
EndProcedure

;Send an update event to update the gadget (used with Setters and Getters)
Procedure.i ModernSwitchGadget_PostUpdate(*ModernSwitchGadget.ModernSwitchGadget) 
	
	If *ModernSwitchGadget\UpdatePosted = #False
		*ModernSwitchGadget\UpdatePosted = #True
		PostEvent(#PB_Event_Gadget, *ModernSwitchGadget\Window, *ModernSwitchGadget\Number, #ModernSwitchGadget_EventType_Updated, -1)
	EndIf
	
EndProcedure

;Callback
Procedure.i ModernSwitchGadget_Callback() 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(EventGadget())
	
	If *ModernSwitchGadget = #Null
		ProcedureReturn
	EndIf
	
	If EventType() >= #PB_EventType_FirstCustomValue
		*ModernSwitchGadget\Events = EventData()
		
		Select EventType()
				
			Case #ModernSwitchGadget_EventType_Updated
				If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
					ModernSwitchGadget_Update(*ModernSwitchGadget)
					ModernSwitchGadget_Draw(*ModernSwitchGadget)
					ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
				Else
					*ModernSwitchGadget\UpdatePosted = #False
				EndIf
				
		EndSelect
		
	Else
		
		If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
			ModernSwitchGadget_Examine(*ModernSwitchGadget)
			ModernSwitchGadget_Update(*ModernSwitchGadget)
			ModernSwitchGadget_Draw(*ModernSwitchGadget)
			ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
		EndIf
		
	EndIf
	
EndProcedure


;-  4.2     .:Public Procedures for the Gadget:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;Update and redraw the gadget
Procedure.i UpdateModernSwitchGadget(Gadget.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
		ModernSwitchGadget_Update(*ModernSwitchGadget)
		ModernSwitchGadget_Draw(*ModernSwitchGadget)
		ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
	EndIf
	
EndProcedure

;Free the gadget
Procedure.i FreeModernSwitchGadget(Gadget.i)
	
	If Not IsGadget(Gadget)
		ProcedureReturn
	EndIf
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	SetGadgetData(Gadget, #Null)
	UnbindGadgetEvent(*ModernSwitchGadget\Number, @ModernSwitchGadget_Callback())
	FreeGadget(Gadget)
	
	If *ModernSwitchGadget\ImageID
		FreeImage(*ModernSwitchGadget\ImageID)
	EndIf
	If *ModernSwitchGadget\AAImageID
		FreeImage(*ModernSwitchGadget\AAImageID)
	EndIf
	
	ClearStructure(*ModernSwitchGadget, ModernSwitchGadget)
	FreeMemory(*ModernSwitchGadget)
	
EndProcedure

;Disable the gadget and change colors
Procedure.i DisableModernSwitchGadget(Gadget.i, Value.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	With	*ModernSwitchGadget
		
		Select Value
			Case 0
				\Disabled = 0
			Case 1
				\Disabled  = 1	
		EndSelect
		
	EndWith
	
	ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
	
EndProcedure

;Select the color theme
Macro ModernSwitchGadget_UseColorTheme()
	
	Select UCase(ColorTheme$)
			
		Case "", "STANDARD"
			*ModernSwitchGadget\ColorBackground = $FFBC7000
			*ModernSwitchGadget\ColorButtonOn = $FFFFFFFF
			*ModernSwitchGadget\ColorButtonOff = $FFFFFFFF
			*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
			*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
			
		Case "DARK"
			*ModernSwitchGadget\ColorBackground = $FF000000
			*ModernSwitchGadget\ColorButtonOn = $FFAAAAAA
			*ModernSwitchGadget\ColorButtonOff = $FFAAAAAA
			*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
			*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
			
		Default
			;Like "", "STANDARD"
			*ModernSwitchGadget\ColorBackground = $FFBC7000
			*ModernSwitchGadget\ColorButtonOn = $FFFFFFFF
			*ModernSwitchGadget\ColorButtonOff = $FFFFFFFF
			*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
			*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
	EndSelect
	
EndMacro

;Create the gadget
Procedure.i ModernSwitchGadget(Gadget, x, y, w, h, Attributes, Window, ColorTheme$="STANDARD")
	
	; 	Attributes:
	;   -----------	
	; 	#ModernSwitchGadget_None 
	; 	#ModernSwitchGadget_Border						
	; 	#ModernSwitchGadget_Raised 
	; 	#ModernSwitchGadget_Vertical
	; 	#ModernSwitchGadget_Mirrored 
	; 
	; 	ColorTheme$:
	;   ------------
	; 	"STANDARD"
	; 	"DARK"
	
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = AllocateMemory(SizeOf(ModernSwitchGadget))
	Protected Result.i, OldGadgetList.i, DummyGadget.i
	
	InitializeStructure(*ModernSwitchGadget, ModernSwitchGadget)
	OldGadgetList = UseGadgetList(WindowID(Window))
	
	;Create gadget with attributes Border/Raised
	If Attributes & #ModernSwitchGadget_Border
		Result = ImageGadget(Gadget, X, Y, W, H, 0, #PB_Image_Border)
	ElseIf Attributes & #ModernSwitchGadget_Raised
		Result = ImageGadget(Gadget, X, Y, W, H, 0, #PB_Image_Raised)
	Else
		Result = ImageGadget(Gadget, X, Y, W, H, 0)
	EndIf
	
	UseGadgetList(OldGadgetList)
	If Gadget = #PB_Any
		Gadget = Result
	EndIf
	SetGadgetData(Gadget, *ModernSwitchGadget)
	
	;Fills the structures
	With *ModernSwitchGadget
		
		;Gadget
		\Number = Gadget 
		\X = x
		\Y = y
		\W = w
		\H = h
		\W2 = w*2
		\H2 = h*2
		\Window = Window																						
		\Attributes = Attributes
		\ImageID =	CreateImage(#PB_Any,\W2,\H2,32,#PB_Image_Transparent)
		\MarginButton = DesktopScaledX(6)
		
		;Layout
		\Layout\x = \X
		\Layout\y = \Y
		\Layout\w = \W
		\Layout\h = \H
		
	EndWith
	
	;Color Theme
	ModernSwitchGadget_UseColorTheme()
	
	BindGadgetEvent(Gadget, @ModernSwitchGadget_Callback())
	
	UpdateModernSwitchGadget(Gadget)
	
	ProcedureReturn Result
	
EndProcedure


;-  4.3     .:Set & Get Procedures:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


;Get an attribute value.
Procedure.i GetModernSwitchGadgetAttribute(Gadget.i, Attribute.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select Attribute
		Case 	#ModernSwitchGadget_Vertical,
		     	#ModernSwitchGadget_Border,						
		     	#ModernSwitchGadget_Raised, 
		     	#ModernSwitchGadget_Mirrored,         
		     	#ModernSwitchGadget_Disabled
			
			If *ModernSwitchGadget\Attributes & Attribute
				ProcedureReturn #True
			Else
				ProcedureReturn #False
			EndIf
			
		Default
			ProcedureReturn -1
			
	EndSelect
	
EndProcedure

;Set/Change the data value of the gadget. 
Procedure.i SetModernSwitchGadgetData(Gadget.i, DataValue.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	*ModernSwitchGadget\DataValue = DataValue
	
EndProcedure

;Get the data value of the gadget.
Procedure.i GetModernSwitchGadgetData(Gadget.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	ProcedureReturn *ModernSwitchGadget\DataValue
	
EndProcedure

;Change the state of the gadget (ON/OFF).
Procedure.i ChangeModernSwitchGadgetState(Gadget.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select *ModernSwitchGadget\State
		Case #ModernSwitchGadgetState_OFF
			*ModernSwitchGadget\State = #ModernSwitchGadgetState_ON	
		Case #ModernSwitchGadgetState_ON
			*ModernSwitchGadget\State = #ModernSwitchGadgetState_OFF	
	EndSelect
	
	ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
	
EndProcedure

;Set the state of the gadget (ON/OFF).
Procedure.i SetModernSwitchGadgetState(Gadget.i, State.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select State
			
		Case 0,1
			*ModernSwitchGadget\State = State	
			
	EndSelect
	
	ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
	
EndProcedure

;Get the state of the gadget.
Procedure.i GetModernSwitchGadgetState(Gadget.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	ProcedureReturn *ModernSwitchGadget\State
	
EndProcedure

;Set/Change gadget color by type
Procedure.i SetModernSwitchGadgetColor(Gadget.i, Type.i, ColorRGBA.i) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	Select Type
		Case #ModernSwitchGadgetColor_Background
			*ModernSwitchGadget\ColorBackground = ColorRGBA
		Case #ModernSwitchGadgetColor_ButtonOff
			*ModernSwitchGadget\ColorButtonOff = ColorRGBA
		Case #ModernSwitchGadgetColor_ButtonOn
			*ModernSwitchGadget\ColorButtonOn = ColorRGBA		
	EndSelect
	
	ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
	
EndProcedure

;Set/Change gadget all colors
Procedure.i SetModernSwitchGadgetColors(Gadget.i, ColorBackgroundRGBA.i, ColorButtonOffRGBA.i, ColorButtonOnRGBA.i)
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	*ModernSwitchGadget\ColorBackground = ColorBackgroundRGBA
	*ModernSwitchGadget\ColorButtonOff = ColorButtonOffRGBA
	*ModernSwitchGadget\ColorButtonOn = ColorButtonOnRGBA	
	
	ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
	
EndProcedure

;Set/Change gadget color theme
Procedure.i SetModernSwitchGadgetColorTheme(Gadget.i, ColorTheme.s) 
	
	Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
	
	With	*ModernSwitchGadget
		
		;Color Theme
		Select UCase(ColorTheme)	
			Case "", "STANDARD"
				\ColorBackground = $FFBC7000
				\ColorButtonOn = $FFFFFFFF
				\ColorButtonOff = $FFFFFFFF
				\ColorBackgroundDisabled = $FF808080								;
				\ColorButtonDisabled = $FFC0C0C0
				
			Case "DARK"
				\ColorBackground = $FF000000
				\ColorButtonOn = $FFAAAAAA
				\ColorButtonOff = $FFAAAAAA
				\ColorBackgroundDisabled = $FF808080								;
				\ColorButtonDisabled = $FFC0C0C0
				
			Default
				DebuggerError("Color Theme Unknown !")
				
		EndSelect
		
	EndWith
	
	ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
	
EndProcedure 

;- BOTTOM
;- END
;-
EndModule


;- Test
CompilerIf #PB_Compiler_IsMainFile
	
	Enumeration 1
		#imgGadget
		#imgGadgetDARK
		#imgGadgetV
		#imgGadgetM
		#imgGadgetMV
		#imgGadgetDisabled
		#btn
	EndEnumeration
	
	Macro CheckerBoard(cb_imgIn,cb_szBlock) ; netmaestro 2023
		cb_chex = CreateImage(#PB_Any,2,2,24,#White)
		StartDrawing(ImageOutput(cb_chex))
		Plot(1,0,$C8C8C8):Plot(0,1,$C8C8C8)
		StopDrawing()
		ResizeImage(cb_chex,cb_szBlock*2,cb_szBlock*2,#PB_Image_Raw)
		StartVectorDrawing(ImageVectorOutput(cb_imgIn))
		VectorSourceImage(ImageID(cb_chex),255,cb_szBlock*2,cb_szBlock*2,#PB_VectorImage_Repeat)
		FillVectorOutput()
		StopVectorDrawing()
		FreeImage(cb_chex)
	EndMacro
	
	
	;Test DPI
	Define W
	ExamineDesktops()
	W=DesktopWidth(0)/2
	
	
	Define.i cb_bkgnd, cb_chex ; Checkerboard background
	
	If OpenWindow(0, 0, 0, W, 400, "ModernSwitchGadget Tests", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
		
		cb_bkgnd=CreateImage(#PB_Any,w,400)         ; checkerboard background
		checkerboard(cb_bkgnd,10)										;       "          "
		ImageGadget(0,0,0,w,400,ImageID(cb_bkgnd))	;       "          "
		DisableGadget(0,1)
		
		UseModule ModernSwitchGadget
		
		ModernSwitchGadget(#imgGadget, 10, 60, 60, 30, #ModernSwitchGadget_None,0);
		ModernSwitchGadget(#imgGadgetDARK,  10, 100, 60, 30, #ModernSwitchGadget_None,0,"DARK")
		ModernSwitchGadget(#imgGadgetV, 100, 60, 30, 60, #ModernSwitchGadget_Vertical,0)
		ModernSwitchGadget(#imgGadgetM, 10, 160, 60, 30, #ModernSwitchGadget_Mirrored,0)
		ModernSwitchGadget(#imgGadgetMV, 100, 160, 30, 60, #ModernSwitchGadget_Vertical|#ModernSwitchGadget_Mirrored,0)
		ModernSwitchGadget(#imgGadgetDisabled, 10, 200, 40, 20, #ModernSwitchGadget_None,0);
		
		ButtonGadget(#btn,10,240,60,30,"ok")
		
		GadgetToolTip(#imgGadget, "STANDARD")
		GadgetToolTip(#imgGadgetDARK, "DARK")
		GadgetToolTip(#imgGadgetV, "VERTICAL (and customized)")
		GadgetToolTip(#imgGadgetM, "MIRRORED")
		GadgetToolTip(#imgGadgetMV, "VERTICAL & MIRRORED")
		GadgetToolTip(#imgGadgetDisabled, "Disabled")
		
		DisableModernSwitchGadget(#imgGadgetDisabled, #True)
		
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_Background, $801977F3)
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_ButtonOn, $FF3FDC30) 
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_ButtonOff, $800D26FF) 
		
		
		
		
		Define Event
		
		Repeat
			
			Event = WaitWindowEvent()
			
			Select Event
					
				Case #PB_Event_Gadget
					;- Events
					Select EventGadget()
						Case #imgGadget
							Select EventType()
									;No Test custom event => No public custom events
									
									
									;Test PB events
								Case #PB_EventType_Change          
									Debug "Changed"
									If GetModernSwitchGadgetState(#imgGadget) = 1
										Debug "ON"
										DisableModernSwitchGadget(#imgGadgetDisabled, #False)
									Else
										Debug "OFF"
										DisableModernSwitchGadget(#imgGadgetDisabled, #True)
									EndIf
								Case #PB_EventType_LeftClick 
									;Debug "LeftClick";ok
									
								Case #PB_EventType_RightClick
									;Debug "RightClick";ok
									
								Case #PB_EventType_LeftDoubleClick
									;Debug "DoubleClick";ok
									
								Case #PB_EventType_RightDoubleClick
									;Debug "RightDoubleClick";ok
									
							EndSelect
					EndSelect
			EndSelect
			
		Until Event = #PB_Event_CloseWindow
	EndIf
	
CompilerEndIf


M.
Mesa
Enthusiast
Enthusiast
Posts: 349
Joined: Fri Feb 24, 2012 10:19 am

Re: modern style switchgadget

Post by Mesa »

Module for the complex MpdernSwitchGadget

Code: Select all

;- TOP

;.-------------------------------------------------------------------------------------------------
;|
;|  Title            : ModernSwitchGadget
;|  Version          : v0.9.1 Beta
;|  Author					 : Mesa
;|  Copyright        : 
;|                     
;|  PureBasic        : 5.70+
;|  
;|  Operating System : Windows (XP to W11+), Linux, MacOS
;|  Processor        : x86, x64
;|
;|  API							 : No api used
;|
;|-------------------------------------------------------------------------------------------------
;|
;|  Description      : Module Switch Gadget with a "modern" style
;|
;|  Forum Topic      : https://www.purebasic.fr/french/viewtopic.php?t=18876
;|                     https://www.purebasic.fr/english/viewtopic.php?t=80957
;|  Website          : 
;|
;|  Documentation    : 
;|
;|	Date 						 : 03/2023
;|
;|  Misc.						 : I confess to being inspired (in a shameless way) in large part by the robust 
;|										 code of Stargate's TabBar gadget. So, if you have analyzed his code then mine 
;|										 will be very easy to understand and improve.
;|
;.-------------------------------------------------------------------------------------------------


;.-------------------------------------------------------------------------------------------------
;|
;|  How to  use 		 : 1) Add UseModule ModernSwitchGadget		 
;|									 : 2) Add ModernSwitchGadget(...)
;|  			           : 3) Nothing else, except using the PB standard event type inside the loop : 
;|  				         : 		#PB_EventType_Change, #PB_EventType_Focus, #PB_EventType_LostFocus,
;| 												#PB_EventType_LeftClick, #PB_EventType_RightClick, 
;|												#PB_EventType_LeftDoubleClick, #PB_EventType_RightDoubleClick																																																																...
;|                     
;|  Color theme      : To add or modify a color theme
;|									 : -> Modify the Macro ModernSwitchGadget_UseColorTheme()
;|
;|  Selected gadget  : To modify the way the gadget is selected
;|										 -> Modify the Procedure ModernSwitchGadget_DrawFocus()
;|
;|	Shape						 : To modify the gadget shape
;|									 : 1) Add Constants and Modify the Structures if needed
;|									 : 2) Modify the procedure ModernSwitchGadget_Layout() if needed
;|									 : 3) Modify the Procedure ModernSwitchGadget_Update() if needed 
;|									 : 4) Modify the Procedure ModernSwitchGadget_Draw() 
;|
;.-------------------------------------------------------------------------------------------------


;.-------------------------------------------------------------------------------------------------
;|
;|  Gadget Attributes
;|  ================================================================
;|  		#ModernSwitchGadget_None 
;|  		#ModernSwitchGadget_Border						
;|  		#ModernSwitchGadget_Raised 
;|  		#ModernSwitchGadget_Vertical
;|  		#ModernSwitchGadget_Mirrored         
;|  		#ModernSwitchGadget_Disabled	
;|  	
;|  Gadget States
;|  =================
;|  		#ModernSwitchGadgetState_OFF
;|  		#ModernSwitchGadgetState_ON
;|  	
;|  Gadget Colors
;|  ================================================================
;|  		Theme colors
;|  		#ModernSwitchGadgetColor_Background									;
;|  		#ModernSwitchGadgetColor_ButtonOff
;|  		#ModernSwitchGadgetColor_ButtonOn
;|  		#ModernSwitchGadgetColor_Selected
;|  		#ModernSwitchGadgetColor_BackgroundDisabled
;|  		#ModernSwitchGadgetColor_ButtonDisabled
;|  		Current colors
;|  		#ModernSwitchGadgetColor_CurrentColorBackground
;|  		#ModernSwitchGadgetColor_CurrentColorButtonOn
;|  		#ModernSwitchGadgetColor_CurrentColorButtonOff
;|  		#ModernSwitchGadgetColor_CurrentColorSelected
;|
;| 	Gadget Events
;|  ================================================================
;|			=> Usefull PureBasic EventTypes
;|  			 #PB_EventType_Change, 
;|  			 #PB_EventType_Focus, 
;|  			 #PB_EventType_LostFocus
;|  			 
;|			-> Useless but working PureBasic EventTypes
;|				 #PB_EventType_LeftClick,  #PB_EventType_LeftDoubleClick 
;|				 #PB_EventType_RightClick, #PB_EventType_RightDoubleClick																																																																...
;|
;|  			 
;|	Procedures
;|  ================================================================
;|  UpdateModernSwitchGadget()
;|  FreeModernSwitchGadget()
;|  DisableModernSwitchGadget()
;|
;|  ModernSwitchGadget()
;|
;|  SetActiveModernSwitchGadget() 
;|  GetActiveModernSwitchGadget() 
;|	
;|  GetModernSwitchGadgetAttribute() 
;|	 
;|  SetModernSwitchGadgetData()
;|  GetModernSwitchGadgetData() 
;|	
;|  ChangeModernSwitchGadgetState() 
;|  SetModernSwitchGadgetState() 	
;|  GetModernSwitchGadgetState() 
;|	
;|  SetModernSwitchGadgetColor() 
;|  GetModernSwitchGadgetColor() 
;|  SetModernSwitchGadgetColors()
;|  SetModernSwitchGadgetColorTheme() 
;|  GetModernSwitchGadgetColorTheme()
;|
;.-------------------------------------------------------------------------------------------------


;.-------------------------------------------------------------------------------------------------
;|
;|  License Mesa.
;|  The license Mesa is, do what you like but make the World better, easier and enjoyable.
;|
;|
;|
;| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
;| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
;| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
;| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
;| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
;| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
;| SOFTWARE.
;| 
;.-------------------------------------------------------------------------------------------------




;-  >M<  .:Declare Module:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯



DeclareModule ModernSwitchGadget
	
	CompilerIf #PB_Compiler_IsMainFile
		EnableExplicit
	CompilerEndIf
	
	
	
	;-.  1     .:Constantes:.
	;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	
	
	; Gadget Attributes
	EnumerationBinary Attributes
		#ModernSwitchGadget_None 
		#ModernSwitchGadget_Border						
		#ModernSwitchGadget_Raised 
		#ModernSwitchGadget_Vertical
		#ModernSwitchGadget_Mirrored         
		#ModernSwitchGadget_Disabled	
	EndEnumeration
	
	; Gadget States
	Enumeration States
		#ModernSwitchGadgetState_OFF
		#ModernSwitchGadgetState_ON
	EndEnumeration
	
	;Gadget Color Types
	Enumeration Color_Types
		;Theme colors
		#ModernSwitchGadgetColor_Background									;
		#ModernSwitchGadgetColor_ButtonOff
		#ModernSwitchGadgetColor_ButtonOn
		#ModernSwitchGadgetColor_Selected
		#ModernSwitchGadgetColor_BackgroundDisabled
		#ModernSwitchGadgetColor_ButtonDisabled
		;Current colors
		#ModernSwitchGadgetColor_CurrentColorBackground
		#ModernSwitchGadgetColor_CurrentColorButtonOn
		#ModernSwitchGadgetColor_CurrentColorButtonOff
		#ModernSwitchGadgetColor_CurrentColorSelected
	EndEnumeration
	
	; Gadget Events; No Public EventType 
	Enumeration Events #PB_EventType_FirstCustomValue
		#ModernSwitchGadget_EventType_Updated      ; The gadget has updated (internal)																						      
	EndEnumeration
	
	
	;-.  2     .:Structures:.
	;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	
	
	Structure ModernSwitchGadget_Layout
		;RoundedBox layout
		x.i			; The position and size of the RoundedBox in the current drawing output. 
		y.i
		w.i
		h.i
		arcx.i	;The radius of the rounded corners in the x and y direction. 
		arcy.i
		
		;Cicle button layout
		xc.i		; The position and size of the circle = button on/off
		yc.i
		r.i
	EndStructure
	
	Structure ModernSwitchGadget
		Number.i                          ; Gadget ID, position and size
		NumberDummyGadget.i								;	StringGadget with a size=0: Trick to use keyboard (Tab and Space keys)
		X.i
		Y.i
		W.i
		H.i
		W2.i															; W*2 used for antialiasing
		H2.i															; H*2	used for antialiasing
		Window.i													; Window parent ID
		ImageID.i													; Image twice as large as needed for antialiasing
		AAImageID.i												; Image will be scaled to the correct size while taking advantage of antialiasing
		DataValue.i												; Used with GadgetData()
		Attributes.i											; Attributes
		State.i														; 0=Left=OFF, 1=Right=ON
		Disabled.i												; 0=Enabled,  1=Disabled
		Focus.i														;	0=No Focus,	1=Focus
		ColorBackground.i									; Background Color
		ColorButtonOn.i										;	Button color when gadget is ON
		ColorButtonOff.i									; Button color when gadget is OFF
		ColorBackgroundDisabled.i					; Special color when the gadget is disabled
		ColorButtonDisabled.i							; Special color when the gadget is disabled
		ColorSelected.i										; Special color when the gadget is selected
		CurrentColorBackground.i					; Current colors
		CurrentColorButtonOn.i
		CurrentColorButtonOff.i
		CurrentColorButton.i
		CurrentColorSelected.i
		MarginButton.i										; Button margin on the left/right
		UpdatePosted.i										; 0=Do nothing, 1=Do a gadget update 																	; 	
		Events.i													; EventData() with a custom Event
		Layout.ModernSwitchGadget_Layout	; Layout
		ColorThemeName$
	EndStructure
	
	
	;-.  3     .:Initializations:.
	;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	; NOTHING... because there are NO GLOBAL variables
	; Everything is in the GadgetData
	; And "initializations" are made inside the Procedure ModernSwitchGadget()
	
	
	;-.  4a   .:Declaration Procedures:. 
	;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	
	
	;Update and redraw the gadget
	Declare.i UpdateModernSwitchGadget(Gadget.i)
	
	;Free the gadget
	Declare.i FreeModernSwitchGadget(Gadget.i)
	
	;Disable the gadget and change colors
	Declare.i DisableModernSwitchGadget(Gadget.i, Value.i)
	
	;Create the gadget
	Declare.i ModernSwitchGadget(Gadget, x, y, w, h, Attributes, Window, ColorTheme$="STANDARD")
	
	; 	Attributes:
	;   -----------	
	; 	#ModernSwitchGadget_None 
	; 	#ModernSwitchGadget_Border						
	; 	#ModernSwitchGadget_Raised 
	; 	#ModernSwitchGadget_Vertical
	; 	#ModernSwitchGadget_Mirrored 
	; 
	; 	ColorTheme$:
	;   ------------
	; 	"STANDARD"
	; 	"DARK"
	
	
	
	;Set active gadget.
	Declare.i SetActiveModernSwitchGadget(Gadget.i) 
	
	;Get wether active gadget.
	Declare.i GetActiveModernSwitchGadget(Gadget.i) 
	
	;Get an attribute value.
	Declare.i GetModernSwitchGadgetAttribute(Gadget.i, Attribute.i) 
	
	;Set/Change the data value of the gadget. 
	Declare.i SetModernSwitchGadgetData(Gadget.i, DataValue.i)
	
	;Get the data value of the gadget.
	Declare.i GetModernSwitchGadgetData(Gadget.i) 
	
	;Change the state of the gadget (ON/OFF).
	Declare.i ChangeModernSwitchGadgetState(Gadget.i, ChangeFocusState.i = #True) 
	
	;Set the state of the gadget (ON/OFF).
	Declare.i SetModernSwitchGadgetState(Gadget.i, State.i) 	
	
	;Get the state of the gadget.
	Declare.i GetModernSwitchGadgetState(Gadget.i) 
	
	;Set/Change gadget color by type
	Declare.i SetModernSwitchGadgetColor(Gadget.i, Type.i, ColorRGBA.i) 
	
	;Get gadget color by type
	Declare.i GetModernSwitchGadgetColor(Gadget.i, Type.i) 
	
	;Set/Change gadget all colors in once
	Declare.i SetModernSwitchGadgetColors(Gadget.i, ColorBackgroundRGBA.i, ColorButtonOffRGBA.i, ColorButtonOnRGBA.i, ColorSelectedRGBA.i)
	
	;Set/Change gadget color theme
	Declare.i SetModernSwitchGadgetColorTheme(Gadget.i, ColorTheme.s) 
	
	;Get color theme name
	Declare.s GetModernSwitchGadgetColorTheme(Gadget.i) 
	
EndDeclareModule





;-  >M<  .:Module:.
;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯


Module ModernSwitchGadget
	
	
	;-.  4b   .:Procedures & Macros:. 
	;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	
	
	;-.  4.1  .:Private procedures for internal calculations ! Not for use !:.
	;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	
	
	;StartDrawing
	Procedure.i ModernSwitchGadget_StartDrawing(*ModernSwitchGadget.ModernSwitchGadget)
		ProcedureReturn StartDrawing(ImageOutput(*ModernSwitchGadget\ImageID))
	EndProcedure
	
	;StopDrawing
	Procedure.i ModernSwitchGadget_StopDrawing(*ModernSwitchGadget.ModernSwitchGadget)
		StopDrawing()
	EndProcedure
	
	;AntiAliasing
	Procedure.i ModernSwitchGadget_Antialiasing(*ModernSwitchGadget.ModernSwitchGadget)
		
		With *ModernSwitchGadget 
			
			;Stop drawing because of the antialiasing which is made in resizing the image
			ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
			
			;Antialiasing by resizing the image
			\AAImageID=CopyImage(\ImageID,#PB_Any)
			ResizeImage(\AAImageID,\W,\H)
			
			ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
			
		EndWith
		
	EndProcedure
	
	;Layout
	Procedure.i ModernSwitchGadget_Layout(*ModernSwitchGadget.ModernSwitchGadget)
		
		If *ModernSwitchGadget\Disabled = #False
			
			Protected x, y, w, h, arcx, arcy, xc, yc, r
			
			With *ModernSwitchGadget
				
				x=0
				y=0
				w=\w2
				h=\h2
				
				Select \State
					Case #ModernSwitchGadgetState_OFF
						;OFF
						If (\Attributes & #ModernSwitchGadget_Vertical) * (\Attributes & #ModernSwitchGadget_Mirrored)
							arcx=\w:arcy=\w:xc=\w:yc=\h*2-\w:r=\w-\MarginButton					
						ElseIf 	\Attributes & #ModernSwitchGadget_Vertical
							arcx=\w:arcy=\w:xc=\w:yc=\w:r=\w-\MarginButton
						ElseIf \Attributes & #ModernSwitchGadget_Mirrored
							arcx=\h:arcy=\h:xc=\w*2-\h:yc=\h:r=\h-\MarginButton
						Else
							arcx=\h:arcy=\h:xc=\h:yc=\h:r=\h-\MarginButton
						EndIf
						
					Case #ModernSwitchGadgetState_ON
						;ON
						If \Attributes & #ModernSwitchGadget_Vertical * \Attributes & #ModernSwitchGadget_Mirrored
							arcx=\w:arcy=\w:xc=\w:yc=\w:r=\w-\MarginButton
						ElseIf \Attributes & #ModernSwitchGadget_Vertical
							arcx=\w:arcy=\w:xc=\w:yc=\h*2-\w:r=\w-\MarginButton
						ElseIf \Attributes & #ModernSwitchGadget_Mirrored
							arcx=\h:arcy=\h:xc=\h:yc=\h:r=\h-\MarginButton		
						Else
							arcx=\h:arcy=\h:xc=\w*2-\h:yc=\h:r=\h-\MarginButton
						EndIf
				EndSelect
				
				
				\Layout\x = x
				\Layout\y = y
				\Layout\w = w
				\Layout\h = h
				\Layout\arcx = arcx
				\Layout\arcy = arcy
				\Layout\xc = xc
				\Layout\yc = yc
				\Layout\r = r
				
			EndWith
			
		EndIf
		
	EndProcedure
	
	;Set Focus ON/OFF
	Procedure.i 	ModernSwitchGadget_SetFocus(*ModernSwitchGadget.ModernSwitchGadget, Focus.i = #True)
		
		With *ModernSwitchGadget
			
			Select  Focus
					
				Case #True
					\Focus = #True
					SetActiveGadget(\NumberDummyGadget)
					SetGadgetText(\NumberDummyGadget, "")
					
				Case #False
					\Focus = #False
					
			EndSelect
			
		EndWith
		
	EndProcedure
	
	;Events
	Procedure.i ModernSwitchGadget_Examine(*ModernSwitchGadget.ModernSwitchGadget)
		
		With *ModernSwitchGadget
			
			If \Disabled = #False
				Select EventType()
						
					Case #PB_EventType_LeftDoubleClick 
						\State = \State!1
						ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
						PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
						PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Focus, 0)
						
					Case #PB_EventType_LeftClick 
						\State = \State!1
						ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
						PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
						PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Focus, 0)
						
				EndSelect
			EndIf	
			
		EndWith
		
	EndProcedure
	
	;Internal gadget update
	Procedure.i ModernSwitchGadget_Update(*ModernSwitchGadget.ModernSwitchGadget) 
		
		With *ModernSwitchGadget
			
			;Colors
			If \Disabled
				\CurrentColorBackground = \ColorBackgroundDisabled
				\CurrentColorButtonOff = \ColorButtonDisabled
				\CurrentColorButtonOn = \ColorButtonDisabled
				\CurrentColorSelected = \ColorButtonDisabled
				If \State = #ModernSwitchGadgetState_OFF
					\CurrentColorButton = \ColorButtonDisabled
				Else
					\CurrentColorButton = \ColorButtonDisabled
				EndIf
			Else
				\CurrentColorBackground = \ColorBackground
				\CurrentColorButtonOff = \ColorButtonOff
				\CurrentColorButtonOn = \ColorButtonOn
				\CurrentColorSelected = \ColorSelected
				If \State = #ModernSwitchGadgetState_OFF
					\CurrentColorButton = \CurrentColorButtonOff
				Else
					\CurrentColorButton = \CurrentColorButtonOn
				EndIf
				
			EndIf
			
			;Layout
			ModernSwitchGadget_Layout(*ModernSwitchGadget)
			
			
			*ModernSwitchGadget\UpdatePosted = #False
			
		EndWith
		
	EndProcedure
	
	;Draw focus = Just draw a circle as focus
	Procedure.i ModernSwitchGadget_DrawFocus(*ModernSwitchGadget.ModernSwitchGadget)
		
		With *ModernSwitchGadget
			
			Circle(\Layout\xc,\Layout\yc,\Layout\r - DesktopScaledX(6), \CurrentColorSelected)
			
		EndWith
		
	EndProcedure
	
	;Draw the gadget
	Procedure.i ModernSwitchGadget_Draw(*ModernSwitchGadget.ModernSwitchGadget)
		
		With *ModernSwitchGadget
			
			DrawingMode(#PB_2DDrawing_AllChannels)
			RoundBox(\Layout\x,\Layout\y,\Layout\w,\Layout\h,\Layout\arcx,\Layout\arcy, \CurrentColorBackground)
			DrawingMode(#PB_2DDrawing_AlphaBlend)
			RoundBox(\Layout\x,\Layout\y,\Layout\w,\Layout\h,\Layout\arcx,\Layout\arcy,\CurrentColorBackground)
			Circle(\Layout\xc,\Layout\yc,\Layout\r,\CurrentColorButton)
			If \Focus
				ModernSwitchGadget_DrawFocus(*ModernSwitchGadget)	
			EndIf
			
			ModernSwitchGadget_Antialiasing(*ModernSwitchGadget)
			
			SetGadgetState(\Number, ImageID(\AAImageID));
			
			If IsImage(\AAImageID) 
				FreeImage(\AAImageID)
				\AAImageID = 0
			EndIf
			
		EndWith
		
	EndProcedure
	
	;Send an update event (used with Setters and Getters)
	Procedure.i ModernSwitchGadget_PostUpdate(*ModernSwitchGadget.ModernSwitchGadget) 
		
		If *ModernSwitchGadget\UpdatePosted = #False
			*ModernSwitchGadget\UpdatePosted = #True
			PostEvent(#PB_Event_Gadget, *ModernSwitchGadget\Window, *ModernSwitchGadget\Number, #ModernSwitchGadget_EventType_Updated, -1)
		EndIf
		
	EndProcedure
	
	;Keyboard Dummy gadget CallBack (hidden StringGadget onboard) => Tab Key and Spacebar
	Procedure.i ModernSwitchGadget_Keyboard_Callback()
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(EventGadget())
		
		If *ModernSwitchGadget = #Null
			ProcedureReturn
		EndIf
		
		
		With *ModernSwitchGadget
			
			Select EventType()
					
				Case #PB_EventType_Focus           
					ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Focus, 0)
					
					
				Case #PB_EventType_LostFocus        
					ModernSwitchGadget_SetFocus(*ModernSwitchGadget, #False)
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_LostFocus, 0)
					
				Case #PB_EventType_Change          
					\State = \State!1
					ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
					ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
			EndSelect
			
		EndWith
		
	EndProcedure
	
	;Callback
	Procedure.i ModernSwitchGadget_Callback() 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(EventGadget())
		
		If *ModernSwitchGadget = #Null
			ProcedureReturn
		EndIf
		
		If EventType() >= #PB_EventType_FirstCustomValue
			*ModernSwitchGadget\Events = EventData()
			
			Select EventType()
					
				Case #ModernSwitchGadget_EventType_Updated
					If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
						ModernSwitchGadget_Update(*ModernSwitchGadget)
						ModernSwitchGadget_Draw(*ModernSwitchGadget)
						ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
					Else
						*ModernSwitchGadget\UpdatePosted = #False
					EndIf
					
			EndSelect
			
		Else
			
			If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
				ModernSwitchGadget_Examine(*ModernSwitchGadget)
				ModernSwitchGadget_Update(*ModernSwitchGadget)
				ModernSwitchGadget_Draw(*ModernSwitchGadget)
				ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
			EndIf
			
		EndIf
		
	EndProcedure
	
	
	;-.  4.2  .:Public Procedures for the Gadget:.
	;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	
	
	;Update and redraw the gadget
	Procedure.i UpdateModernSwitchGadget(Gadget.i)
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		If ModernSwitchGadget_StartDrawing(*ModernSwitchGadget)
			ModernSwitchGadget_Update(*ModernSwitchGadget)
			ModernSwitchGadget_Draw(*ModernSwitchGadget)
			ModernSwitchGadget_StopDrawing(*ModernSwitchGadget)
		EndIf
		
	EndProcedure
	
	;Free the gadget
	Procedure.i FreeModernSwitchGadget(Gadget.i)
		
		If Not IsGadget(Gadget)
			ProcedureReturn
		EndIf
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		With *ModernSwitchGadget
			
			SetGadgetData(Gadget, #Null)
			UnbindGadgetEvent(\Number, @ModernSwitchGadget_Callback())
			FreeGadget(Gadget)
			
			SetGadgetData(\NumberDummyGadget, #Null)
			UnbindGadgetEvent(\NumberDummyGadget, @ModernSwitchGadget_Keyboard_Callback())
			FreeGadget(\NumberDummyGadget)
			
			If \ImageID
				FreeImage(\ImageID)
			EndIf
			If \AAImageID
				FreeImage(\AAImageID)
			EndIf
			
			ClearStructure(*ModernSwitchGadget, ModernSwitchGadget)
			FreeMemory(*ModernSwitchGadget)
			
		EndWith
		
	EndProcedure
	
	;Disable the gadget and change colors
	Procedure.i DisableModernSwitchGadget(Gadget.i, Value.i)
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		With	*ModernSwitchGadget
			
			Select Value
					
				Case 0
					\Disabled = 0
					
				Case 1
					\Disabled  = 1
					\Focus = #False
					
			EndSelect
			
		EndWith
		
		ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
		
	EndProcedure
	
	;Select the color theme
	Macro ModernSwitchGadget_UseColorTheme()
		
		Select UCase(ColorTheme$)
				
			Case "", "STANDARD"
				*ModernSwitchGadget\ColorBackground = $FFBC7000
				*ModernSwitchGadget\ColorButtonOn = $FFFFFFFF
				*ModernSwitchGadget\ColorButtonOff = $FFFFFFFF
				*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
				*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
				*ModernSwitchGadget\ColorSelected = $FFBC7000
				
			Case "DARK"
				*ModernSwitchGadget\ColorBackground = $FF000000
				*ModernSwitchGadget\ColorButtonOn = $FFAAAAAA
				*ModernSwitchGadget\ColorButtonOff = $FFAAAAAA
				*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
				*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0	
				*ModernSwitchGadget\ColorSelected = $FFFFFFFF
				
			Default
				;Like "", "STANDARD"
				*ModernSwitchGadget\ColorBackground = $FFBC7000
				*ModernSwitchGadget\ColorButtonOn = $FFFFFFFF
				*ModernSwitchGadget\ColorButtonOff = $FFFFFFFF
				*ModernSwitchGadget\ColorBackgroundDisabled = $FF808080								;
				*ModernSwitchGadget\ColorButtonDisabled = $FFC0C0C0
				*ModernSwitchGadget\ColorSelected = $FFBC7000
		EndSelect
		
	EndMacro
	
	;Create the gadget
	Procedure.i ModernSwitchGadget(Gadget, x, y, w, h, Attributes, Window, ColorTheme$="STANDARD")
		
		; 	Attributes:
		;   -----------	
		; 	#ModernSwitchGadget_None 
		; 	#ModernSwitchGadget_Border						
		; 	#ModernSwitchGadget_Raised 
		; 	#ModernSwitchGadget_Vertical
		; 	#ModernSwitchGadget_Mirrored 
		; 
		; 	ColorTheme$:
		;   ------------
		; 	"STANDARD"
		; 	"DARK"
		
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = AllocateMemory(SizeOf(ModernSwitchGadget))
		Protected Result.i, OldGadgetList.i, DummyGadget.i
		
		InitializeStructure(*ModernSwitchGadget, ModernSwitchGadget)
		OldGadgetList = UseGadgetList(WindowID(Window))
		
		;Create CheckBox gadget with a size=0: Trick To use keyboard (Tab And Space keys)
		DummyGadget = StringGadget(#PB_Any, -20, 0, 0, 0, "")
		
		;Create the gadget with attributes Border/Raised
		If Attributes & #ModernSwitchGadget_Border
			Result = ImageGadget(Gadget, X, Y, W, H, 0, #PB_Image_Border)
		ElseIf Attributes & #ModernSwitchGadget_Raised
			Result = ImageGadget(Gadget, X, Y, W, H, 0, #PB_Image_Raised)
		Else
			Result = ImageGadget(Gadget, X, Y, W, H, 0)
		EndIf
		
		UseGadgetList(OldGadgetList)
		If Gadget = #PB_Any
			Gadget = Result
		EndIf
		SetGadgetData(Gadget, *ModernSwitchGadget)
		SetGadgetData(DummyGadget, *ModernSwitchGadget)
		
		;Fills the structures
		With *ModernSwitchGadget
			
			;Gadget
			\Number = Gadget
			\NumberDummyGadget = DummyGadget
			\X = x
			\Y = y
			\W = w
			\H = h
			\W2 = w*2
			\H2 = h*2
			\Window = Window																						
			\Attributes = Attributes
			\ImageID =	CreateImage(#PB_Any,\W2,\H2,32,#PB_Image_Transparent)
			\MarginButton = DesktopScaledX(6)
			
			;Layout
			\Layout\x = \X
			\Layout\y = \Y
			\Layout\w = \W
			\Layout\h = \H
			
			;Theme
			\ColorThemeName$ = ColorTheme$
			
		EndWith
		
		;Color Theme
		ModernSwitchGadget_UseColorTheme()
		
		;Bind Dummy Gadget CallBack
		BindGadgetEvent(DummyGadget, @ModernSwitchGadget_Keyboard_Callback())
		;Bind Gadget CallBack
		BindGadgetEvent(Gadget, @ModernSwitchGadget_Callback())
		
		UpdateModernSwitchGadget(Gadget)
		
		
		ProcedureReturn Result
		
	EndProcedure
	
	
	;-.  4.3  .:Set & Get Procedures:.
	;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	
	;Set active gadget.
	Procedure.i SetActiveModernSwitchGadget(Gadget.i) 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
		ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
		
	EndProcedure
	
	;Get wether active gadget.
	Procedure.i GetActiveModernSwitchGadget(Gadget.i) 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		ProcedureReturn *ModernSwitchGadget\Focus
		
	EndProcedure
	
	
	;Get an attribute value.
	Procedure.i GetModernSwitchGadgetAttribute(Gadget.i, Attribute.i) 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		Select Attribute
			Case 	#ModernSwitchGadget_Vertical,
			     	#ModernSwitchGadget_Border,						
			     	#ModernSwitchGadget_Raised, 
			     	#ModernSwitchGadget_Mirrored,         
			     	#ModernSwitchGadget_Disabled
				
				If *ModernSwitchGadget\Attributes & Attribute
					ProcedureReturn #True
				Else
					ProcedureReturn #False
				EndIf
				
			Default
				ProcedureReturn -1
				
		EndSelect
		
	EndProcedure
	
	;Set/Change the data value of the gadget. 
	Procedure.i SetModernSwitchGadgetData(Gadget.i, DataValue.i)
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		Protected *ModernSwitchGadget2.ModernSwitchGadget = GetGadgetData(*ModernSwitchGadget\NumberDummyGadget)
		
		*ModernSwitchGadget\DataValue = DataValue
		*ModernSwitchGadget2\DataValue = DataValue
		
	EndProcedure
	
	;Get the data value of the gadget.
	Procedure.i GetModernSwitchGadgetData(Gadget.i) 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		ProcedureReturn *ModernSwitchGadget\DataValue
		
	EndProcedure
	
	;Change the state of the gadget (ON/OFF).
	Procedure.i ChangeModernSwitchGadgetState(Gadget.i, ChangeFocusState.i = #True) 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		With *ModernSwitchGadget
			
			Select \State
					
					;OFF->ON
				Case #ModernSwitchGadgetState_OFF
					\State = #ModernSwitchGadgetState_ON
					If ChangeFocusState
						ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
					EndIf
					
					;ON->OFF
				Case #ModernSwitchGadgetState_ON
					\State = #ModernSwitchGadgetState_OFF	
					If ChangeFocusState
						ModernSwitchGadget_SetFocus(*ModernSwitchGadget, #False)
					EndIf
					
			EndSelect
			
			ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
			PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
			PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Focus, 0)
			
		EndWith
		
	EndProcedure
	
	;Set the state of the gadget (ON/OFF).
	Procedure.i SetModernSwitchGadgetState(Gadget.i, State.i) 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		With *ModernSwitchGadget
			
			Select State
					
				Case #ModernSwitchGadgetState_OFF,#ModernSwitchGadgetState_ON
					\State = State	
					ModernSwitchGadget_SetFocus(*ModernSwitchGadget)
					ModernSwitchGadget_PostUpdate(*ModernSwitchGadget)
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Change, 0)
					PostEvent(#PB_Event_Gadget, \Window, \Number, #PB_EventType_Focus, 0)				
					
			EndSelect
			
		EndWith
		
	EndProcedure
	
	;Get the state of the gadget.
	Procedure.i GetModernSwitchGadgetState(Gadget.i) 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		ProcedureReturn *ModernSwitchGadget\State
		
	EndProcedure
	
	;Set/Change gadget color by type
	Procedure.i SetModernSwitchGadgetColor(Gadget.i, Type.i, ColorRGBA.i) 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		Select Type
				
			Case #ModernSwitchGadgetColor_Background
				*ModernSwitchGadget\ColorBackground = ColorRGBA
			Case #ModernSwitchGadgetColor_ButtonOff
				*ModernSwitchGadget\ColorButtonOff = ColorRGBA
			Case #ModernSwitchGadgetColor_ButtonOn
				*ModernSwitchGadget\ColorButtonOn = ColorRGBA	
			Case #ModernSwitchGadgetColor_Selected
				*ModernSwitchGadget\ColorSelected = ColorRGBA
			Case 	#ModernSwitchGadgetColor_BackgroundDisabled
				*ModernSwitchGadget\ColorBackgroundDisabled = ColorRGBA
			Case #ModernSwitchGadgetColor_ButtonDisabled
				*ModernSwitchGadget\ColorButtonDisabled = ColorRGBA
				
		EndSelect
		
		ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
		
	EndProcedure
	
	;Get gadget color by type
	Procedure.i GetModernSwitchGadgetColor(Gadget.i, Type.i) 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		Select Type
				
				;Theme colors
			Case #ModernSwitchGadgetColor_Background
				ProcedureReturn *ModernSwitchGadget\ColorBackground
			Case #ModernSwitchGadgetColor_ButtonOff
				ProcedureReturn *ModernSwitchGadget\ColorButtonOff
			Case #ModernSwitchGadgetColor_ButtonOn
				ProcedureReturn *ModernSwitchGadget\ColorButtonOn
			Case #ModernSwitchGadgetColor_Selected	
				ProcedureReturn *ModernSwitchGadget\ColorSelected
			Case 	#ModernSwitchGadgetColor_BackgroundDisabled
				ProcedureReturn *ModernSwitchGadget\ColorBackgroundDisabled
			Case 	#ModernSwitchGadgetColor_ButtonDisabled
				ProcedureReturn *ModernSwitchGadget\ColorButtonDisabled
				
				;Current colors
			Case 	#ModernSwitchGadgetColor_CurrentColorBackground
				ProcedureReturn *ModernSwitchGadget\CurrentColorBackground
			Case  	#ModernSwitchGadgetColor_CurrentColorButtonOn
				ProcedureReturn *ModernSwitchGadget\CurrentColorButtonOn
			Case  	#ModernSwitchGadgetColor_CurrentColorButtonOff
				ProcedureReturn *ModernSwitchGadget\CurrentColorButtonOff
			Case  	#ModernSwitchGadgetColor_CurrentColorSelected
				ProcedureReturn *ModernSwitchGadget\CurrentColorSelected
				
		EndSelect
		
	EndProcedure
	
	
	;Set/Change gadget all colors in once
	Procedure.i SetModernSwitchGadgetColors(Gadget.i, ColorBackgroundRGBA.i, ColorButtonOffRGBA.i, ColorButtonOnRGBA.i, ColorSelectedRGBA.i)
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		*ModernSwitchGadget\ColorBackground = ColorBackgroundRGBA
		*ModernSwitchGadget\ColorButtonOff = ColorButtonOffRGBA
		*ModernSwitchGadget\ColorButtonOn = ColorButtonOnRGBA	
		*ModernSwitchGadget\ColorSelected = ColorSelectedRGBA
		
		ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
		
	EndProcedure
	
	;Set/Change gadget color theme
	Procedure.i SetModernSwitchGadgetColorTheme(Gadget.i, ColorTheme.s) 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		With	*ModernSwitchGadget
			
			;Color Theme
			Select UCase(ColorTheme)	
				Case "", "STANDARD"
					\ColorThemeName$ = ColorTheme
					\ColorBackground = $FFBC7000
					\ColorButtonOn = $FFFFFFFF
					\ColorButtonOff = $FFFFFFFF
					\ColorBackgroundDisabled = $FF808080								;
					\ColorButtonDisabled = $FFC0C0C0
					\ColorSelected = $FFBC7000
					
				Case "DARK"
					\ColorThemeName$ = ColorTheme
					\ColorBackground = $FF000000
					\ColorButtonOn = $FFAAAAAA
					\ColorButtonOff = $FFAAAAAA
					\ColorBackgroundDisabled = $FF808080								;
					\ColorButtonDisabled = $FFC0C0C0
					\ColorSelected = $FFFFFFFF
					
				Default
					DebuggerError("Color Theme Unknown !")
					
			EndSelect
			
		EndWith
		
		ModernSwitchGadget_PostUpdate(GetGadgetData(Gadget))
		
	EndProcedure 
	
	;Get color theme name
	Procedure.s GetModernSwitchGadgetColorTheme(Gadget.i) 
		
		Protected *ModernSwitchGadget.ModernSwitchGadget = GetGadgetData(Gadget)
		
		With	*ModernSwitchGadget
			
			;Color Theme
			Select \ColorThemeName$
				Case "", "STANDARD",  "DARK"
					ProcedureReturn \ColorThemeName$
					
				Default
					;DebuggerError("Color Theme Unknown !")
					ProcedureReturn "Color Theme Unknown !"
			EndSelect
			
		EndWith
		
	EndProcedure 
	;- BOTTOM
	;- END
EndModule
;-


;- Example
CompilerIf #PB_Compiler_IsMainFile
	
	Enumeration 1
		#imgGadget
		#imgGadgetDARK
		#imgGadgetV
		#imgGadgetM
		#imgGadgetMV
		#imgGadgetDisabled
		#btn
	EndEnumeration
	
	Macro CheckerBoard(cb_imgIn,cb_szBlock) ; netmaestro 2023
		cb_chex = CreateImage(#PB_Any,2,2,24,#White)
		StartDrawing(ImageOutput(cb_chex))
		Plot(1,0,$C8C8C8):Plot(0,1,$C8C8C8)
		StopDrawing()
		ResizeImage(cb_chex,cb_szBlock*2,cb_szBlock*2,#PB_Image_Raw)
		StartVectorDrawing(ImageVectorOutput(cb_imgIn))
		VectorSourceImage(ImageID(cb_chex),255,cb_szBlock*2,cb_szBlock*2,#PB_VectorImage_Repeat)
		FillVectorOutput()
		StopVectorDrawing()
		FreeImage(cb_chex)
	EndMacro
	
	
	;Test DPI
	Define W
	ExamineDesktops()
	W=DesktopWidth(0)/2
	
	
	Define.i cb_bkgnd, cb_chex ; Checkerboard background
	
	If OpenWindow(0, 0, 0, W, 400, "ModernSwitchGadget Tests", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
		; 	If OpenWindow(0, 0, 0, DesktopUnscaledX(W), DesktopUnscaledY(400), "ModernSwitchGadget Tests", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
		cb_bkgnd=CreateImage(#PB_Any,w,400)         ; checkerboard background
		checkerboard(cb_bkgnd,10)										;       "          "
		ImageGadget(0,0,0,w,400,ImageID(cb_bkgnd))	;       "          "
		DisableGadget(0,1)
		
		
		UseModule ModernSwitchGadget
		
		ModernSwitchGadget(#imgGadget, 10, 60, 60, 30, #ModernSwitchGadget_None,0);
		ModernSwitchGadget(#imgGadgetDARK,  10, 100, 60, 30, #ModernSwitchGadget_None,0,"DARK")
		ModernSwitchGadget(#imgGadgetV, 100, 60, 30, 60, #ModernSwitchGadget_Vertical,0)
		ModernSwitchGadget(#imgGadgetM, 10, 160, 60, 30, #ModernSwitchGadget_Mirrored,0)
		ModernSwitchGadget(#imgGadgetMV, 100, 160, 30, 60, #ModernSwitchGadget_Vertical|#ModernSwitchGadget_Mirrored,0)
		ModernSwitchGadget(#imgGadgetDisabled, 10, 200, 40, 20, #ModernSwitchGadget_None,0);
		
		ButtonGadget(#btn,10,240,60,30,"ok")
		
		
		GadgetToolTip(#imgGadget, "STANDARD")
		GadgetToolTip(#imgGadgetDARK, "DARK")
		GadgetToolTip(#imgGadgetV, "VERTICAL (and customized)")
		GadgetToolTip(#imgGadgetM, "MIRRORED")
		GadgetToolTip(#imgGadgetMV, "VERTICAL & MIRRORED")
		GadgetToolTip(#imgGadgetDisabled, "Disabled")
		
		SetActiveModernSwitchGadget(#imgGadget)
		
		DisableModernSwitchGadget(#imgGadgetDisabled, #True);ok
		
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_Background, $801977F3);ok
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_ButtonOn, $FF3FDC30)	 ;ok
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_ButtonOff, $800D26FF) ;ok
		SetModernSwitchGadgetColor(#imgGadgetV, #ModernSwitchGadgetColor_Selected, $806E2B5C)
		
		
		
		Define Event
		
		Repeat
			
			Event = WaitWindowEvent()
			
			Select Event
					
				Case #PB_Event_Gadget
					;- Events
					Select EventGadget()
						Case #imgGadget
							Select EventType()
									;No Test custom event => No public custom events
									
									;Test PB events
								Case #PB_EventType_Change
									Debug "#imgGadget Changed"
									Select GetModernSwitchGadgetState(#imgGadget)
										Case #ModernSwitchGadgetState_ON
											Debug "ON"
											DisableModernSwitchGadget(#imgGadgetDisabled, #False)
										Case #ModernSwitchGadgetState_OFF
											Debug "OFF"
											DisableModernSwitchGadget(#imgGadgetDisabled, #True)
									EndSelect
									
								Case #PB_EventType_LeftClick 
									;Debug "LeftClick";ok
									
								Case #PB_EventType_RightClick
									;Debug "RightClick";ok
									
								Case #PB_EventType_LeftDoubleClick
									;Debug "DoubleClick";ok
									
								Case #PB_EventType_RightDoubleClick
									;Debug "RightDoubleClick";ok
									
								Case #PB_EventType_Focus
									;Debug "Focus #imgGadget";ok
									
								Case #PB_EventType_LostFocus
									;Debug "LostFocus #imgGadget";ok
									
							EndSelect
							
						Case #btn
							Select EventType()
								Case #PB_EventType_LeftClick
									Debug "Button Left Click"		
							EndSelect
							
					EndSelect
			EndSelect
			
		Until Event = #PB_Event_CloseWindow
	EndIf
	
CompilerEndIf

M.
Post Reply