
Edit: Aug 14, 2015
Bug with use of #PB_Any fixed thanks to dige
Edit: Dec 11, 2014
Added some window loading code to demo to reduce loading flicker as suggested by Electrochrisso
Commented out GetGadgetFont() line as it was not working on Macs. Thanks, Shardik.
Edit: Code for trackbar not included. Still working on it.

Code: Select all
; Project : Slick GUI Elements
; This Element: Switch/toggle
; Author : missile69 - http://www.purebasic.fr/english/memberlist.php?mode=viewprofile&u=7421
; OS : Cross-platform, I think :)
; PB version : 5.31
; License : http://www.gnu.org/licenses/gpl.html
;XIncludeFile "SlickSlider.pbi"
EnableExplicit
Structure _slk_switch
cnvColor.i
fontNumber.i
gadNumber.i
height.i
hover.b
ONcolor.i
style.i
state.i
text.s
textColor.i
width.i
EndStructure
; Check to see if the values shared among my custom gadgets already exist
CompilerIf Not Defined(imgSlickBG, #PB_Constant)
Enumeration _Slk
;Drawn Images
#imgSlickBG
#imgSlickLayer1
EndEnumeration
;Drawing Style constants
#SlickMetal = 4 ; Brushed aluminum look
#SlickClean = 8 ; Clean white look
;- Color Constants
#clrSlickText = $FF000000 ; Default text color
#clrSlickBlue = $FFFFB300 ; Default color for ON position
#clrSlickWhite = $FFFFFFFF ;
#clrSlickExLtGrey = $FFEBEBEB ; Main knob color 1
#clrSlickLtGrey = $FFE2E2E2 ; Default OFF color
#clrSlickDkGrey = $FF575757 ; Main knob color 2. Also for bevel.
#clrSlickMdGrey = $FFAEAEAE ; Used for bevel edge
CompilerEndIf
;- Size Constants
#switchMinWidth = 32
#switchMinHeight = 20
NewList slk_Switches._slk_switch()
Procedure.i _slk_Select_Switch(gadNum.i)
Shared slk_Switches()
ForEach slk_Switches()
If slk_Switches()\gadNumber = gadNum
ProcedureReturn @slk_Switches()
EndIf
Next
ProcedureReturn 0
EndProcedure
Procedure _slk_UpdateSwitchDrawing()
;Main drawing procedure. Called for any visible changes like drawing On/off state
;and when the text changes.
;State : Zero/#false is OFF state. Non-zero is ON state
Shared slk_Switches()
If CreateImage(#imgSlickBG, 370, 230, 32, slk_Switches()\cnvColor) And CreateImage(#imgSlickLayer1, 230, 230, 32)
With slk_Switches()
;-===================== Draw knob ==========================
;Common parts
StartDrawing(ImageOutput(#imgSlickLayer1))
;Make circle's BG transparent
DrawingMode(#PB_2DDrawing_AlphaChannel)
Box(0, 0, 230, 230, $00000000)
;Circle Shadow
DrawingMode(#PB_2DDrawing_AlphaBlend)
Circle(115, 121, 106, #clrSlickDkGrey)
;Bevel
DrawingMode(#PB_2DDrawing_Gradient|#PB_2DDrawing_AlphaBlend)
BackColor (#clrSlickMdGrey)
FrontColor(#clrSlickMdGrey)
GradientColor(0.5, #clrSlickDkGrey)
LinearGradient(115, 5, 115, 230)
Circle(115, 115, 106)
If \style = #SlickMetal
;Main circle
ResetGradientColors()
BackColor (#clrSlickDkGrey)
FrontColor(#clrSlickDkGrey)
GradientColor (3/6, #clrSlickDkGrey )
If \hover
GradientColor(1/6, #clrSlickWhite )
GradientColor(4/6, #clrSlickWhite )
Else
GradientColor(1/6, #clrSlickExLtGrey)
GradientColor(4/6, #clrSlickExLtGrey)
EndIf
ConicalGradient(115, 115, 30)
Circle(115, 115, 100)
StopDrawing()
ElseIf \style = #SlickClean
;Main circle
If \hover
ResetGradientColors()
BackColor (#clrSlickExLtGrey)
FrontColor(#clrSlickWhite)
Circle(115, 115, 100)
Else
DrawingMode(#PB_2DDrawing_Default)
Circle(115, 115, 100, #clrSlickWhite)
EndIf
StopDrawing()
EndIf
;-=============== Draw the pill-shaped BG ==================
;Box is common to both ON and OFF states
StartDrawing(ImageOutput(#imgSlickBG))
DrawingMode(#PB_2DDrawing_AlphaBlend)
Box(115, 12, 170, 200, #clrSlickDkGrey)
Box(115, 18, 170, 200, #clrSlickWhite )
If \state = #False ;0 Gadget OFF - Draw grey pill
Circle(265, 112, 100, #clrSlickDkGrey)
Circle(265, 118, 100, #clrSlickWhite )
Circle(265, 115, 100, #clrSlickLtGrey)
Box(115, 15, 170, 200, #clrSlickLtGrey)
;place the knob
DrawingMode(#PB_2DDrawing_AlphaBlend)
DrawAlphaImage(ImageID(#imgSlickLayer1), 2, 0)
StopDrawing()
ResizeImage(#imgSlickBG, 32, 20)
Else ;non-zero is ON - Draw colored pill
Circle(115, 112, 100, #clrSlickDkGrey)
Circle(115, 118, 100, #clrSlickWhite )
Circle(115, 115, 100, \ONcolor)
Box (115, 15, 170, 200, \ONcolor)
;place the knob
DrawingMode(#PB_2DDrawing_AlphaBlend)
DrawAlphaImage(ImageID(#imgSlickLayer1), 138, 0)
StopDrawing()
ResizeImage(#imgSlickBG, 32, 20)
EndIf
;assign image to canvas gadget and set BG color
StartDrawing(CanvasOutput(\gadNumber))
Box(0, 0, \width, \height, \cnvColor)
DrawImage(ImageID(#imgSlickBG), 0, (\height-ImageHeight(#imgSlickBG))/2)
;-====================== Draw Text =========================
If IsFont(\fontNumber)
DrawingFont(FontID(\fontNumber))
Else
CompilerIf #PB_Compiler_OS = #PB_OS_Windows Or #PB_Compiler_OS = #PB_OS_Linux
DrawingFont(GetGadgetFont(#PB_Default))
CompilerElse
;Not working on Macs
;DrawingFont(GetGadgetFont(#PB_Default))
CompilerEndIf
EndIf
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(38, (\height-TextHeight(\text))/2, \text, \textColor)
StopDrawing()
EndWith
EndIf
EndProcedure
Procedure.i GetSlickSwitchState(GadNum.i)
;Returns 0 if in OFF state and non-zero if ON
Shared slk_Switches()
If _slk_Select_Switch(GadNum)
ProcedureReturn slk_Switches()\state
EndIf
ProcedureReturn 0
EndProcedure
Procedure SetSlickSwitchState(GadNum.i, State.i)
;Set the switch's state. Zero = Off, Non-zero = ON
Shared slk_Switches()
If _slk_Select_Switch(GadNum)
slk_Switches()\state = State
_slk_UpdateSwitchDrawing()
EndIf
EndProcedure
Procedure SetSlickSwitchColor(GadNum.i, Color.i)
;Change the track/bar color
Shared slk_Switches()
If _slk_Select_Switch(GadNum)
slk_Switches()\ONcolor = Color
_slk_UpdateSwitchDrawing()
EndIf
EndProcedure
Procedure.s GetSlickSwitchText(GadNum.i)
;Retrieve gadget's text
Shared slk_Switches()
If _slk_Select_Switch(GadNum)
ProcedureReturn slk_Switches()\text
EndIf
ProcedureReturn #NULL$
EndProcedure
Procedure SetSlickSwitchText(GadNum.i, Text.s)
;Set gadget text
Shared slk_Switches()
If _slk_Select_Switch(GadNum)
slk_Switches()\text = Text
_slk_UpdateSwitchDrawing()
EndIf
EndProcedure
Procedure.i IsSlickSwitch(GadNum.i)
;Checks to see if given gadget number is a SlickSwitch
;Returns non-zero if it is and 0 if it's not.
ProcedureReturn _slk_Select_Switch(GadNum)
EndProcedure
Procedure FreeSlickSwitch(GadNum.i)
;Free/remove given switch gadget
Shared slk_Switches()
If _slk_Select_Switch(GadNum)
DeleteElement(slk_Switches())
FreeGadget(GadNum)
EndIf
EndProcedure
Procedure _slk_Switch_Events()
;Callback for all the switch gadgets.
Shared slk_Switches()
Protected GadNum.i = EventGadget()
_slk_Select_Switch(GadNum)
With slk_Switches()
Select EventType()
Case #PB_EventType_LeftClick
If \state = #False
\state = #True
_slk_UpdateSwitchDrawing()
Else
\state = #False
_slk_UpdateSwitchDrawing()
EndIf
;Send Change event to gadget's window
PostEvent(#PB_Event_Gadget, EventWindow(), GadNum, #PB_EventType_Change)
Case #PB_EventType_RightClick
Debug "Right Click"
Case #PB_EventType_MouseEnter, #PB_EventType_Focus
\hover = #True
_slk_UpdateSwitchDrawing()
Case #PB_EventType_MouseLeave, #PB_EventType_LostFocus
\hover = #False
_slk_UpdateSwitchDrawing()
Case #PB_EventType_KeyUp
;Enable turning on/off via space key like with checkbox
If GetGadgetAttribute(\gadNumber, #PB_Canvas_Key) = #PB_Shortcut_Space
If \state
\state = #False
Else
\state = #True
EndIf
_slk_UpdateSwitchDrawing()
PostEvent(#PB_Event_Gadget, EventWindow(), GadNum, #PB_EventType_Change)
EndIf
Case #PB_EventType_MouseWheel
If GetGadgetAttribute(\gadNumber, #PB_Canvas_WheelDelta) < 0 ;Mouse wheel down
If \state = #False
\state = #True
_slk_UpdateSwitchDrawing()
PostEvent(#PB_Event_Gadget, EventWindow(), GadNum, #PB_EventType_Change)
EndIf
Else ;Mouse wheel up
If \state
\state = #False
_slk_UpdateSwitchDrawing()
PostEvent(#PB_Event_Gadget, EventWindow(), GadNum, #PB_EventType_Change)
EndIf
EndIf
;Comment the above IF statement and uncomment the one below to change which
;mouse wheel directions turns the gadget on or off.
; If GetGadgetAttribute(\gadNumber, #PB_Canvas_WheelDelta) < 0 ;Mouse wheel down
; If \state
; \state = #False
; _slk_UpdateSwitchDrawing()
; EndIf
; Else ;Mouse wheel up
; If \state = #False
; \state = #True
; _slk_UpdateSwitchDrawing()
; EndIf
; EndIf
EndSelect
EndWith
EndProcedure
Procedure.i SlickSwitchGadget(GadNum.i, x.i, y.i,
w.i = 0,
h.i = 0,
Text.s = "",
Style.i = #SlickMetal,
ONColor.i = #clrSlickBlue,
CnvColor.i = #PB_Default,
TextColor.i = #clrSlickText,
FontNum.i = #PB_Default)
Shared slk_Switches()
Protected r.i
;Set minimums and defaults
If w < #switchMinWidth: w = #switchMinWidth: EndIf
If h < #switchMinHeight: h = #switchMinHeight: EndIf
If CnvColor = #PB_Default
CompilerIf #PB_Compiler_OS = #PB_OS_Windows
CnvColor = GetSysColor_(#COLOR_BTNFACE)
CompilerElse
CnvColor = $D0D0D0
CompilerEndIf
EndIf
If IsGadget(GadNum) = #False
If AddElement(slk_Switches())
With slk_Switches()
\cnvColor = CnvColor
\fontNumber = FontNum
;\gadNumber = CanvasGadget(GadNum, x, y, w, h, #PB_Canvas_Keyboard|#PB_Canvas_DrawFocus)
\gadNumber = CanvasGadget(GadNum, x, y, w, h, #PB_Canvas_Keyboard)
If gadNum <> #PB_Any: \gadNumber = gadNum: EndIf
\height = h
\ONcolor = ONColor
\state = #False
\style = Style
\text = Text
\textColor = TextColor
\width = w
_slk_UpdateSwitchDrawing() ;Initial drawing
BindGadgetEvent(\gadNumber, @_slk_Switch_Events())
r = \gadNumber
EndWith
EndIf
EndIf
ProcedureReturn r
EndProcedure
DisableExplicit
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
If OpenWindow(0, 0, 0, 275, 175, "Slick Switch Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu|#PB_Window_Invisible)
Define e.i, Switch1.i, Slider1.i, winColor.i = $FFFFFF
SetWindowColor(0, winColor)
Switch1 = SlickSwitchGadget(#PB_Any, 10, 10, 125, 0, "With sample text", #SlickClean, #clrSlickBlue, winColor)
SlickSwitchGadget(#PB_Any, 10, 40, 0, 0, "", #SlickClean, $FFc900ff, winColor)
SlickSwitchGadget(#PB_Any, 10, 70, 0, 0, "", #SlickClean, #clrSlickDkGrey, winColor)
;CheckBoxGadget(#PB_Any, 10, 100, 125, 20, "Normal checkbox")
SlickSwitchGadget(#PB_Any, 140, 10, 125, 0, "With sample text", #SlickMetal, #clrSlickBlue, winColor)
SlickSwitchGadget(#PB_Any, 140, 40, 0, 0, "", #SlickMetal, $FFc900ff, winColor)
SlickSwitchGadget(#PB_Any, 140, 70, 0, 0, "", #SlickMetal, #clrSlickDkGrey, winColor)
;Slider1 = SlickSliderGadget(#PB_Any, 10, 140, 255, 0, 0, 500, #clrSlickBlue, #SliderStateOnHover|#SlickClean, winColor)
;SetSlickSliderState(Slider1, 250)
HideWindow(0, #False)
Repeat
e = WaitWindowEvent()
If e = #PB_Event_Gadget
Select EventGadget()
Case Switch1
If EventType() = #PB_EventType_Change
Debug "Switch 1 changed"
EndIf
EndSelect
EndIf
Until e = #PB_Event_CloseWindow
EndIf
CompilerEndIf