diff --git a/extensions/widgets/switchbutton/notes/feature-theming.md b/extensions/widgets/switchbutton/notes/feature-theming.md
new file mode 100644
index 00000000000..d4f8e39a323
--- /dev/null
+++ b/extensions/widgets/switchbutton/notes/feature-theming.md
@@ -0,0 +1,35 @@
+# Theming and appearance
+
+* The switch button is now drawn the same size for both its "iOS" and
+ "android" themes. It is no longer possible to resize the bounding box of
+ the switch button so that some of it is "cut off" at the edges.
+
+* The switch button now uses the **theme** property to control its appearance.
+ Currently, the **theme** property is _not_ saved, and is reset to "native"
+ whenever the widget is loaded.
+
+* The switch button colors are now controlled by the standard LiveCode
+ **hiliteColor**, **borderColor** and **backgroundColor** properties. They
+ can be edited in the property inspector.
+
+* The switch button now obeys the standard LiveCode **showBorder** property,
+ which can be edited in the property inspector.
+
+# Properties
+
+* The **widgetTheme** property has been removed. Use the **theme** property
+ instead.
+
+* The **colorScheme** property has been removed. Set the **hiliteColor**,
+ **borderColor** and **backgroundColor** properties instead.
+
+* The **switchIsOn** property has been removed. Use the **hilited** property
+ instead.
+
+# Signals
+
+* The **switchChanged** signal has been renamed to **hiliteChanged**.
+
+# Default script
+
+* The switch button now has a default script.
diff --git a/extensions/widgets/switchbutton/support/defaultscript.livecodescript b/extensions/widgets/switchbutton/support/defaultscript.livecodescript
new file mode 100644
index 00000000000..78fdcd9ffe1
--- /dev/null
+++ b/extensions/widgets/switchbutton/support/defaultscript.livecodescript
@@ -0,0 +1,4 @@
+script "com.livecode.widget.switchbutton.__DefaultScript"
+on hiliteChanged pHilited
+
+end hiliteChanged
diff --git a/extensions/widgets/switchbutton/switchbutton.lcb b/extensions/widgets/switchbutton/switchbutton.lcb
index d9e12794b6c..4961343ff52 100644
--- a/extensions/widgets/switchbutton/switchbutton.lcb
+++ b/extensions/widgets/switchbutton/switchbutton.lcb
@@ -1,5 +1,5 @@
/*
-Copyright (C) 2015 LiveCode Ltd.
+Copyright (C) 2015-2016 LiveCode Ltd.
This file is part of LiveCode.
@@ -15,24 +15,24 @@ for more details.
You should have received a copy of the GNU General Public License
along with LiveCode. If not see . */
-/*
+/**
This widget is a switch button, consisting of two mutually exclusive choices or states.
-Name: switchChanged
+Name: hiliteChanged
Type: message
-Syntax: on switchChanged
+Syntax: on hiliteChanged
Summary: Sent when the switch is changed to either the on or off position
Parameters:
-pSwitchIsOn (boolean): True if the switch is in the on position and false if the switch is in the off position
+pHilited (boolean): `true` if the switch is in the on position; `false` otherwise
Example:
-on switchChanged pSwitchIsOn
- set the visible of group 1 to pSwitchIsOn
+on hiliteChanged pHilited
+ set the visible of group 1 to pHilited
end switchChanged
Description:
-Handle the switchChanged message in the widget's object script to respond to the user switching the button on or off.
+Handle the hiliteChanged message in the widget's object script to respond to the user switching the button on or off.
*/
-- declaring extension as widget, followed by identifier
@@ -44,479 +44,414 @@ use com.livecode.canvas
use com.livecode.widget
use com.livecode.engine
use com.livecode.library.iconSVG
+use com.livecode.library.widgetutils
--
-- adding metadata to ensure the extension displays correctly in livecode
metadata title is "Switch Button"
metadata author is "LiveCode"
-metadata version is "1.0.3"
+metadata version is "2.0.0"
metadata preferredSize is "64,48"
metadata svgicon is "M47.3,0H18.5C8.3,0,0,8.3,0,18.5v0C0,28.7,8.3,37,18.5,37h28.8c10.2,0,18.5-8.3,18.5-18.5v0C65.8,8.3,57.5,0,47.3,0zM19.8,33.5c-8.3,0-15-6.7-15-15c0-8.3,6.7-15,15-15s15,6.7,15,15C34.8,26.8,28,33.5,19.8,33.5z"
--
-/*
-Syntax: set the widgetTheme of to
-Syntax: get the widgetTheme of
+/**
+Name: theme
-Summary: The theme of the widget
+Syntax: set the theme of to
+Syntax: get the theme of
-Parameters:
-pWidgetTheme(enum): The theme of the widget
--"iOS"
--"Android(Dark)"
--"Android(Light)"
+Summary: Specifies the theme to use when drawing the switch button.
+
+Value (string):
+The of the switch button is a name identifying the
+style to use when drawing it.
Description:
-Use the property to set the theme of the widget.
+Use the property to control the general appearance of the switch
+button. The currently-supported values are "native", "iOS" and "Android".
+
+**Note**: The value of the property is not saved by the switch button.
+Set the property to preview the way the switch button will appear when
+used on an Android or iOS device.
*/
-property widgetTheme get mWidgetTheme set setWidgetTheme
-metadata widgetTheme.editor is "com.livecode.pi.enum"
-metadata widgetTheme.options is "iOS,Android(Dark),Android(Light)"
-metadata widgetTheme.default is "iOS"
-metadata widgetTheme.label is "Widget Theme"
+property Theme get mTheme set setWidgetTheme
+metadata Theme.editor is "com.livecode.pi.enum"
+metadata Theme.options is "native,iOS,Android"
+metadata Theme.default is "native"
+metadata Theme.label is "Theme"
-/*
-Syntax: set the colorScheme of to
-Syntax: get the colorScheme of
+/**
+Name: highlight
-Summary: The color scheme of the widget (Android only)
+Syntax: set the highlight of to {true | false}
+Syntax: get the highlight of
-Parameters:
-pColorScheme(enum): The color scheme of the widget
--"Red"
--"Pink"
--"Purple"
--"Deep Purple"
--"Indigo"
--"Blue"
--"Light Blue"
--"Cyan"
--"Teal"
--"Green"
--"Light Green"
--"Lime"
--"Yellow"
--"Amber"
--"Orange"
--"Deep Orange"
--"Brown"
--"Grey"
--"Blue Grey"
+Summary: Whether the switch is on or off
+
+Value (boolean): `true` if the switch is in the on position; `false` otherwise.
Description:
-Use the property to set the color scheme of the widget.
-This property can be set for Android only, the color scheme for the iOS switch button is fixed.
+Use this property to determine whether the switch button displays as on.
*/
-property colorScheme get mColorScheme set setColorScheme
-metadata colorScheme.editor is "com.livecode.pi.enum"
-metadata colorScheme.options is "Red,Pink,Purple,Deep Purple,Indigo,Blue,Light Blue,Cyan,Teal,Green,Light Green,Lime,Yellow,Amber,Orange,Deep Orange,Brown,Grey,Blue Grey"
-metadata colorScheme.default is "Teal"
-metadata colorScheme.label is "Color Scheme"
+property Highlight get mSwitchIsOn set setSwitch
+metadata Highlight.default is "false"
+metadata Highlight.label is "Hilited"
-/*
-Syntax: set the switchIsOn of to {true | false}
-Syntax: get the switchIsOn of
+/**
+Syntax: set the showBorder of to {true|false}
+Syntax: get the showBorder of
-Summary: Whether the switch is on or off
+Summary: Whether the widget has a border or not.
+
+Description:
+Use the property to control whether the switch button has a border
+around it or not
+*/
+property showBorder get mShowFrameBorder set setShowFrameBorder
+metadata showBorder.default is "true"
+
+/**
+Syntax: set the backColor of to
+Syntax: get the backColor of
+
+Summary: Controls the background color of the switch button
+
+Description:
+Use the property to control the off-position fill color of the
+switch button.
+*/
+metadata backgroundColor.editor is "com.livecode.pi.color"
+metadata backgroundColor.default is "empty"
+metadata backgroundcolor.section is "Colors"
+metadata backgroundColor.label is "Background Color"
+
+/**
+Syntax: set the hiliteColor of to
+Syntax: get the hiliteColor of
+
+Summary: Controls the color of the switch button when it is in the on position
Description:
-Use this property to determine whether the switch button displays as on (true) or off (false).
+Use the property to control the on-position fill color of the
+switch button.
*/
-property switchIsOn get mSwitchIsOn set setSwitch
-metadata switchIsOn.default is "false"
-metadata switchIsOn.label is "Switch On"
+metadata hiliteColor.editor is "com.livecode.pi.color"
+metadata hiliteColor.default is "empty"
+metadata hilitecolor.section is "Colors"
+metadata hiliteColor.label is "Highlight Color"
+
+/**
+Syntax: set the borderColor of to
+Syntax: get the borderColor of
+
+Summary: Controls the color of the switch button when it is in the on position
+
+Description:
+Use the property to control the on-position fill color of the
+switch button.
+*/
+metadata borderColor.editor is "com.livecode.pi.color"
+metadata borderColor.default is "empty"
+metadata bordercolor.section is "Colors"
+metadata borderColor.label is "Border Color"
+
-- private instance variables
+private variable mTheme as String
private variable mWidgetTheme as String
-private variable mColorScheme as String
private variable mSwitchIsOn as Boolean
+private variable mShowFrameBorder as Boolean
private variable mIsPressed as Boolean
private variable mXClick as Real
private variable mMouseHasMoved as Boolean
private variable mSwitchIsInOnPosition as Boolean
-private variable mAndroidLightOnColors as Array
-private variable mAndroidDarkOnColors as Array
-
-private variable mAndroidLightThumbOff as Color
-private variable mAndroidLightThumbDisabled as Color
-private variable mAndroidLightTrackOff as Color
-private variable mAndroidLightTrackDisabled as Color
+private variable mClickableRect as Rectangle
+
+constant kGeometry is { \
+ "margin-px": { "iOS": 4, "android": 4 }, \
+ "length": { "iOS": 1.75, "android": 2 }, \
+ "trackwidth": { "iOS": 1, "android": 0.66 }, \
+ "thumbstretch": { "iOS": 0.5, "android": 0 } \
+}
+
+constant kPaints is { \
+ "track": { \
+ "off": { \
+ "fill": { \
+ "iOS": [["background", 1]], "android": [["background", 1], ["border", 0.5]] \
+ }, \
+ "stroke": { \
+ "iOS": [["border", 1]], "android": [["border", 1]] \
+ } \
+ }, \
+ "on": { \
+ "fill": { \
+ "iOS": [["highlight", 1]], "android": [["background", 1], ["highlight", 0.5]] \
+ }, \
+ "stroke": { \
+ "iOS": [["border", 1]], "android": [["border", 1]] \
+ } \
+ } \
+ }, \
+ "thumb": { \
+ "off": { \
+ "fill": { \
+ "iOS": [["background", 1]], "android": [["background", 1]] \
+ }, \
+ "stroke": { \
+ "iOS": [["border", 1]], "android": [["border", 1]] \
+ } \
+ }, \
+ "on": { \
+ "fill": { \
+ "iOS": [["background", 1]], "android": [["highlight", 1]] \
+ }, \
+ "stroke": { \
+ "iOS": [["border", 1]], "android": [["border", 1]] \
+ } \
+ } \
+ } \
+}
+
+constant kStrokeWidth is 1
+
+constant kDisabledOpacity is 0.5
-private variable mAndroidDarkThumbOff as Color
-private variable mAndroidDarkThumbDisabled as Color
-private variable mAndroidDarkTrackOff as Color
-private variable mAndroidDarkTrackDisabled as Color
-
-private variable mWidth as Real
-private variable mHeight as Real
-private variable mRadius as Real
--
public handler OnSave(out rProperties as Array)
put the empty array into rProperties
- put mWidgetTheme into rProperties["widgetTheme"]
- put mColorScheme into rProperties["colorScheme"]
- put mSwitchIsOn into rProperties["checked"]
-
+ put mSwitchIsOn into rProperties["highlight"]
+ put mShowFrameBorder into rProperties["showBorder"]
end handler
public handler OnLoad(in pProperties as Array)
- put pProperties["widgetTheme"] into mWidgetTheme
- put pProperties["colorScheme"] into mColorScheme
- put pProperties["checked"] into mSwitchIsOn
+ put pProperties["highlight"] into mSwitchIsOn
+ put pProperties["showBorder"] into mShowFrameBorder
end handler
public handler OnCreate() returns nothing
- put "iOS" into mWidgetTheme
- put the empty string into mColorScheme
+ put "native" into mTheme
+ put getNativeThemeName() into mWidgetTheme
put false into mSwitchIsOn
+ put true into mShowFrameBorder
put false into mIsPressed
put 0 into mXClick
put false into mMouseHasMoved
put false into mSwitchIsInOnPosition
- fetchAndroidColors()
updateVariables()
end handler
public handler OnPaint() returns nothing
-
updateVariables()
- if mWidgetTheme is "iOS" then
- drawIos()
- else if mWidgetTheme contains "Android" then
- drawAndroid()
+ variable tTransform as optional Transform
+ variable tScale as optional Number
+ if not paintGetTransform(tTransform, tScale) then
+ return
end if
+ transform this canvas by tTransform
+ set the stroke width of this canvas to 1/tScale
+
+ paintDrawComponent("track")
+ paintDrawComponent("thumb")
end handler
-private handler drawIos() returns nothing
+private handler paintGetTransform(out rTransform as optional Transform, \
+ out rScale as optional Number) returns Boolean
- -- draw the track when animating and not animating
- set the paint of this canvas to fetchPaint("track")
- fill fetchPath("track") on this canvas
- set the stroke width of this canvas to 1.5
- set the paint of this canvas to fetchPaint("border")
- stroke fetchPath("track") on this canvas
+ -- Sanity check
+ if my width is 0 or my height is 0 then
+ return false
+ end if
- -- draw thumb or extended thumb based on whether the mouse is down or not, with shadow
- variable tShadow as Effect
- put drawDropShadow() into tShadow
+ -- Create a canvas transformation that places the centre of the control at
+ -- (0, 0), and ensures that the whole control is visible when the radius of
+ -- the control's "thumb" is 1.
- set the paint of this canvas to fetchPaint("border")
- set the stroke width of this canvas to 1
- if mIsPressed then
- -- draw the extended thumb
- stroke fetchPath("thumbExtensionRect") on this canvas
- stroke fetchPath("thumbExtensionCircle") on this canvas
- stroke fetchPath("thumb") on this canvas
-
- begin layer with tShadow on this canvas
- set the paint of this canvas to solid paint with color [1,1,1]
- fill fetchPath("thumbExtensionRect") on this canvas
- fill fetchPath("thumbExtensionCircle") on this canvas
- fill fetchPath("thumb") on this canvas
- end layer on this canvas
+ variable tX
+ variable tY
+ put (the left of mClickableRect + the right of mClickableRect) / 2 into tX
+ put (the top of mClickableRect + the bottom of mClickableRect) / 2 into tY
- else
- -- draw the thumb
- stroke fetchPath("thumb") on this canvas
+ variable tScale
+ put (the height of mClickableRect / 2) into tScale
+
+ variable tTransform
+ put transform with translation [tX, tY] into tTransform
- begin layer with tShadow on this canvas
- set the paint of this canvas to fetchPaint("thumb")
- fill fetchPath("thumb") on this canvas
- end layer on this canvas
+ scale tTransform by [tScale]
+
+ -- Flip horizontally for "on" position
+ if mSwitchIsInOnPosition then
+ scale tTransform by [-1, 1]
end if
+ put tScale into rScale
+ put tTransform into rTransform
+ return true
end handler
-private handler drawAndroid() returns nothing
+private handler paintGetPath(in pComponent as String) returns Path
- -- draw the pressed circle
- if mIsPressed then
- set the paint of this canvas to fetchPaint("pressedHilite")
- fill fetchPath("pressedHilite") on this canvas
- end if
+ -- X position of centre of thumb
+ variable tCentreX as Number
+ put 1 - kGeometry["length"][mWidgetTheme] into tCentreX
- -- draw the track
- set the paint of this canvas to fetchPaint("track")
- fill fetchPath("track") on this canvas
+ variable tTrack as Number
+ variable tStretch as Number
- -- draw the thumb with drop shadow for Android(Light) theme
- if mWidgetTheme is "Android(Light)" then
- variable tShadow as Effect
- put drawDropShadow() into tShadow
+ if pComponent is "track" then
+ put kGeometry["trackwidth"][mWidgetTheme] into tTrack
+ return rounded rectangle path of rectangle \
+ [tCentreX - tTrack, -tTrack, tTrack - tCentreX, tTrack] \
+ with radius tTrack
- begin layer with tShadow on this canvas
- set the paint of this canvas to fetchPaint("thumb")
- fill fetchPath("thumb") on this canvas
- end layer on this canvas
+ else if pComponent is "thumb" then
+ if mIsPressed then
+ put kGeometry["thumbstretch"][mWidgetTheme] into tStretch
+ return rounded rectangle path of rectangle \
+ [tCentreX - 1, -1, tCentreX + 1 + tStretch, 1] with radius 1
+ else
+ return circle path centered at point [tCentreX, 0] with radius 1
+ end if
+ end if
+end handler
- else if mWidgetTheme is "Android(Dark)" then
- set the paint of this canvas to fetchPaint("thumb")
- fill fetchPath("thumb") on this canvas
+private handler paintGetPaint(in pComponent as String, in pType as String) \
+ returns List
+
+ if pType is "stroke" and not mShowFrameBorder then
+ return []
end if
- -- draw the thumb border
- if mWidgetTheme is "Android(Light)" then
- if my enabled is false or mSwitchIsInOnPosition is false then
- set the paint of this canvas to fetchPaint("thumbBorder")
- set the stroke width of this canvas to 0.5
- stroke fetchPath("thumb") on this canvas
- end if
+ variable tState as String
+ if mSwitchIsInOnPosition then
+ put "on" into tState
+ else
+ put "off" into tState
end if
+ variable tRaw as List
+ put kPaints[pComponent][tState][pType][mWidgetTheme] into tRaw
+
+ variable tPaints as List
+ put [] into tPaints
+
+ variable tPaintInfo as List
+ repeat for each element tPaintInfo in tRaw
+ if tPaintInfo[1] is "background" then
+ put my background paint into tPaintInfo[1]
+ else if tPaintInfo[1] is "border" then
+ put my border paint into tPaintInfo[1]
+ else if tPaintInfo[1] is "highlight" then
+ put my highlight paint into tPaintInfo[1]
+ end if
+
+ push tPaintInfo onto back of tPaints
+ end repeat
+
+ return tPaints
end handler
-private handler drawDropShadow() returns Effect
- variable tProps as Array
- put the empty array into tProps
-
- -- iOS drop shadow effect
- if mWidgetTheme is "iOS" then
- put color [168/255, 168/255, 168/255, 0.75] into tProps["color"]
- put "source over" into tProps["blend mode"]
- put 0.9 into tProps["spread"]
- put 1 into tProps["size"]
- put 2 into tProps["distance"]
- put 135 into tProps["angle"]
-
- -- Android drop shadow effect
-else if mWidgetTheme is "Android(Light)" then
- put color [164/255, 164/255, 164/255, 0.5] into tProps["color"]
- put "source over" into tProps["blend mode"]
- put 0 into tProps["spread"]
- put 1 into tProps["size"]
- put 4 into tProps["distance"]
- put 45 into tProps["angle"]
+private handler paintDrawComponent(in pComponent as String)
+ variable tPath as Path
+ put paintGetPath(pComponent) into tPath
+
+ variable tBaseOpacity as Number
+
+ variable tStrokePaints as List
+ variable tFillPaints as List
+
+ put paintGetPaint(pComponent, "stroke") into tStrokePaints
+ put paintGetPaint(pComponent, "fill") into tFillPaints
+
+ if tStrokePaints is empty and tFillPaints is empty then
+ return
end if
- variable tEffect as Effect
- put outer shadow effect with properties tProps into tEffect
- return tEffect
-end handler
+ save state of this canvas
-private handler fetchPaint(in pObject as String) returns Paint
- variable tColorString as String
- variable tColor as Color
- variable tTheme as String
-
- -- iOS colors
- if mWidgetTheme is "iOS" then
- if pObject is "border" then
- if mSwitchIsInOnPosition is false then
- put color [228/255, 228/255, 228/255] into tColor
- else
- put color [66/255, 212/255, 81/255] into tColor
- end if
- else if pObject is "track" then
- if mSwitchIsInOnPosition then
- put color [66/255, 212/255, 81/255] into tColor
- else
- if mIsPressed then
- put color [224/255, 224/255, 224/255] into tColor
- else
- put color [1,1,1] into tColor
- end if
- end if
- else if pObject is "thumb" then
- put color [1,1,1] into tColor
+ -- When the control is disabled, first paint everything in the background
+ -- paint, then paint the control over the top with reduced opacity
+ -- FIXME This is ugly!
+ if my disabled then
+ set the paint of this canvas to my background paint
+ if tFillPaints is not empty then
+ fill tPath on this canvas
end if
-
- -- Android(Light) colors
- else if mWidgetTheme is "Android(Light)" then
- if my enabled is true then
- if mSwitchIsInOnPosition then
- if pObject is "thumb" then
- put mAndroidLightOnColors[mColorScheme] into tColorString
- else if pObject is "track" then
- put mAndroidLightOnColors[mColorScheme] into tColorString
- put ",128" after tColorString
- else if pObject is "pressedHilite" then
- put mAndroidLightOnColors[mColorScheme] into tColorString
- put ",20" after tColorString
- end if
- put stringToColor(tColorString) into tColor
- else
- if pObject is "thumb" then
- put mAndroidLightThumbOff into tColor
- else if pObject is "track" then
- put mAndroidLightTrackOff into tColor
- else if pObject is "thumbBorder" then
- put color [167/255, 167/255, 167/255] into tColor
- else if pObject is "pressedHilite" then
- put color [0,0,0,0.06] into tColor
- end if
- end if
- else
- if pObject is "thumb" then
- put mAndroidLightThumbDisabled into tColor
- else if pObject is "track" then
- put mAndroidLightTrackDisabled into tColor
- else if pObject is "thumbBorder" then
- put color [168/255, 168/255, 168/255] into tColor
- else if pObject is "pressedHilite" then
- put color [0,0,0,0.06] into tColor
- end if
+ if tStrokePaints is not empty then
+ stroke tPath on this canvas
end if
- -- Android(Dark) colors
- else if mWidgetTheme is "Android(Dark)" then
- if my enabled is true then
- if mSwitchIsInOnPosition then
- if pObject is "thumb" then
- put mAndroidDarkOnColors[mColorScheme] into tColorString
- else if pObject is "track" then
- put mAndroidDarkOnColors[mColorScheme] into tColorString
- put ",128" after tColorString
- else if pObject is "pressedHilite" then
- put mAndroidLightOnColors[mColorScheme] into tColorString
- put ",30" after tColorString
- end if
- put stringToColor(tColorString) into tColor
- else
- if pObject is "thumb" then
- put mAndroidDarkThumbOff into tColor
- else if pObject is "track" then
- put mAndroidDarkTrackOff into tColor
- else if pObject is "pressedHilite" then
- put color [1,1,1,0.15] into tColor
- end if
- end if
- else
- if pObject is "thumb" then
- put mAndroidDarkThumbDisabled into tColor
- else if pObject is "track" then
- put mAndroidDarkTrackDisabled into tColor
- else if pObject is "pressedHilite" then
- put color [1,1,1,0.15] into tColor
- end if
- end if
+ put kDisabledOpacity into tBaseOpacity
+ else
+ put 1 into tBaseOpacity
end if
- return solid paint with tColor
+ -- Loop over the fills, applying them in turn
+ variable tPaintInfo as List
+ repeat for each element tPaintInfo in tFillPaints
+ set the paint of this canvas to tPaintInfo[1]
+ set the opacity of this canvas to tPaintInfo[2] * tBaseOpacity
+ fill tPath on this canvas
+ end repeat
+
+ -- Loop over the strokes, applying them in turn
+ repeat for each element tPaintInfo in tStrokePaints
+ set the paint of this canvas to tPaintInfo[1]
+ set the opacity of this canvas to tPaintInfo[2] * tBaseOpacity
+ stroke tPath on this canvas
+ end repeat
+
+ restore state of this canvas
end handler
-private handler fetchPath(in pObject as String) returns Path
-
- -- iOS paths
- if mWidgetTheme is "iOS" then
- if pObject is "track" then
- return rounded rectangle path of rectangle [mWidth/2 - 3*mHeight/8, mHeight/4, mWidth/2 + 3*mHeight/8, 3*mHeight/4] with radius (mHeight/4)
- else if pObject is "thumb" then
- if mSwitchIsInOnPosition then
- return circle path centered at point [mWidth/2 + 3*mHeight/16, mHeight/2] with radius (mHeight/4)
- else
- return circle path centered at point [mWidth/2 - 3*mHeight/16, mHeight/2] with radius (mHeight/4)
- end if
- else if pObject is "thumbExtensionCircle" then
- if mSwitchIsInOnPosition then
- return circle path centered at point [mWidth/2 + mHeight/16, mHeight/2] with radius (mHeight/4)
- else
- return circle path centered at point [mWidth/2 - mHeight/16, mHeight/2] with radius (mHeight/4)
- end if
- else if pObject is "thumbExtensionRect" then
- if mSwitchIsInOnPosition then
- return rectangle path of rectangle [mWidth/2 + mHeight/16, mHeight/4, mWidth/2 + 3*mHeight/16, 3*mHeight/4]
- else
- return rectangle path of rectangle [mWidth/2 - 3*mHeight/16, mHeight/4, mWidth/2 - mHeight/16, 3*mHeight/4]
- end if
- end if
+----------------------------------------------------------------
+-- Other stuff
+----------------------------------------------------------------
- -- Android paths
- else if mWidgetTheme contains "Android" then
- if pObject is "thumb" then
- if mSwitchIsInOnPosition then
- return circle path centered at point [5*mRadius, mHeight/2] with radius mRadius
- else
- return circle path centered at point [3*mRadius, mHeight/2] with radius mRadius
- end if
- else if pObject is "track" then
- return rounded rectangle path of rectangle [2.5*mRadius, mHeight/2 - 2*mRadius/3, 5.5*mRadius, mHeight/2 + 2*mRadius/3] with radius (2*mRadius/3)
- else if pObject is "pressedHilite" then
- if mSwitchIsInOnPosition then
- return circle path centered at point [5*mRadius, mHeight/2] with radius (2.5*mRadius)
- else
- return circle path centered at point [3*mRadius, mHeight/2] with radius (2.5*mRadius)
- end if
- end if
+private handler updateVariables() returns nothing
+ -- Compute the rectangle for which the widget should respond to clicks.
+
+ if my width is 0 or my height is 0 then
+ put my bounds into mClickableRect
+ return
end if
-end handler
-private handler fetchAndroidColors() returns nothing
-
- put the empty array into mAndroidLightOnColors
- put "238,43,41" into mAndroidLightOnColors["Red"]
- put "224,0,81" into mAndroidLightOnColors["Pink"]
- put "137,0,161" into mAndroidLightOnColors["Purple"]
- put "83,33,168" into mAndroidLightOnColors["Deep Purple"]
- put "48,58,165" into mAndroidLightOnColors["Indigo"]
- put "30,128,240" into mAndroidLightOnColors["Blue"]
- put "20,150,241" into mAndroidLightOnColors["Light Blue"]
- put "22,175,202" into mAndroidLightOnColors["Cyan"]
- put "17,133,117" into mAndroidLightOnColors["Teal"]
- put "63,164,63" into mAndroidLightOnColors["Green"]
- put "122,186,58" into mAndroidLightOnColors["Light Green"]
- put "194,215,45" into mAndroidLightOnColors["Lime"]
- put "254,233,46" into mAndroidLightOnColors["Yellow"]
- put "253,182,13" into mAndroidLightOnColors["Amber"]
- put "253,133,9" into mAndroidLightOnColors["Orange"]
- put "251,63,28" into mAndroidLightOnColors["Deep Orange"]
- put "101,67,56" into mAndroidLightOnColors["Brown"]
- put "140,140,140" into mAndroidLightOnColors["Grey"]
- put "78,106,120" into mAndroidLightOnColors["Blue Grey"]
-
- put the empty array into mAndroidDarkOnColors
- put "233,133,136" into mAndroidDarkOnColors["Red"]
- put "239,119,162" into mAndroidDarkOnColors["Pink"]
- put "193,124,206" into mAndroidDarkOnColors["Purple"]
- put "163,135,210" into mAndroidDarkOnColors["Deep Purple"]
- put "141,149,209" into mAndroidDarkOnColors["Indigo"]
- put "127,190,247" into mAndroidDarkOnColors["Blue"]
- put "112,201,248" into mAndroidDarkOnColors["Light Blue"]
- put "113,215,229" into mAndroidDarkOnColors["Cyan"]
- put "112,194,184" into mAndroidDarkOnColors["Teal"]
- put "150,207,151" into mAndroidDarkOnColors["Green"]
- put "186,220,148" into mAndroidDarkOnColors["Light Green"]
- put "224,237,138" into mAndroidDarkOnColors["Lime"]
- put "255,245,140" into mAndroidDarkOnColors["Yellow"]
- put "254,219,111" into mAndroidDarkOnColors["Amber"]
- put "254,193,109" into mAndroidDarkOnColors["Orange"]
- put "253,153,127" into mAndroidDarkOnColors["Deep Orange"]
- put "174,154,147" into mAndroidDarkOnColors["Brown"]
- put "234,234,234" into mAndroidDarkOnColors["Grey"]
- put "160,176,185" into mAndroidDarkOnColors["Blue Grey"]
-
- put color [249/255,249/255,249/255] into mAndroidLightThumbOff
- put color [175/255,175/255,175/255] into mAndroidLightThumbDisabled
- put color [0,0,0,0.26] into mAndroidLightTrackOff
- put color [0,0,0,0.12] into mAndroidLightTrackDisabled
-
- put color [175/255,175/255,175/255] into mAndroidDarkThumbOff
- put color [51/255,51/255,51/255] into mAndroidDarkThumbDisabled
- put color [1,1,1,0.3] into mAndroidDarkTrackOff
- put color [1,1,1,0.1] into mAndroidDarkTrackDisabled
+ variable tMargin as Number
+ variable tAspectRatio as Number
+ put kGeometry["margin-px"][mWidgetTheme] into tMargin
+ put kGeometry["length"][mWidgetTheme] into tAspectRatio
-end handler
+ variable tMidWidth as Number
+ variable tMidHeight as Number
+ put my width / 2 into tMidWidth
+ put my height / 2 into tMidHeight
-private handler updateVariables() returns nothing
- put my width into mWidth
- put my height into mHeight
- put mWidth/9 into mRadius
-end handler
+ variable tHalfWidth as Number
+ variable tHalfHeight as Number
+ put tMidWidth - tMargin into tHalfWidth
+ put tMidHeight - tMargin into tHalfHeight
-private handler clickableRect() returns Rectangle
- if mWidgetTheme is "iOS" then
- return rectangle [mWidth/2 - mHeight/2, mHeight/4, mWidth/2 + mHeight/2, 3*mHeight/4]
- else if mWidgetTheme contains "Android" then
- return rectangle [1.5*mRadius, mHeight/2 - mRadius, 6*mRadius, mHeight/2 + mRadius]
+ if tHalfHeight * tAspectRatio < tHalfWidth then
+ -- height controlled
+ put tHalfHeight * tAspectRatio into tHalfWidth
+ else
+ -- width controlled
+ put tHalfWidth / tAspectRatio into tHalfHeight
end if
+
+ put rectangle [tMidWidth - tHalfWidth, tMidHeight - tHalfHeight, \
+ tMidWidth + tHalfWidth, tMidHeight + tHalfHeight] into mClickableRect
end handler
public handler OnMouseMove() returns nothing
@@ -550,7 +485,7 @@ public handler OnMouseDown() returns nothing
return
end if
- if the click position is within clickableRect() then
+ if the click position is within mClickableRect then
put the x of the click position into mXClick
put true into mIsPressed
redraw all
@@ -566,12 +501,12 @@ public handler OnMouseUp() returns nothing
setSwitch(mSwitchIsInOnPosition)
put false into mMouseHasMoved
else
- if the click position is within clickableRect() then
+ if the click position is within mClickableRect then
setSwitch(not(mSwitchIsOn))
end if
end if
- post "switchChanged" with [mSwitchIsOn]
+ post "hiliteChanged" with [mSwitchIsOn]
put false into mIsPressed
end handler
@@ -583,7 +518,7 @@ public handler OnMouseRelease() returns nothing
if mMouseHasMoved then
setSwitch(mSwitchIsInOnPosition)
put false into mMouseHasMoved
- post "switchChanged" with [mSwitchIsOn]
+ post "hiliteChanged" with [mSwitchIsOn]
put false into mIsPressed
end if
end handler
@@ -594,150 +529,38 @@ end handler
--
--------------------------------------------------------------------------------
-constant kWidgetThemeIos is "iOS"
-constant kWidgetThemeAndroidDark is "Android(Dark)"
-constant kWidgetThemeAndroidLight is "Android(Light)"
+constant kKnownThemes is ["iOS", "Android"]
-private handler setWidgetTheme(in pWidgetTheme as String) returns nothing
+private handler setWidgetTheme(in pTheme as String) returns nothing
- if pWidgetTheme is mWidgetTheme then
+ if pTheme is mTheme then
return
end if
- variable tThemeList as List
- put [kWidgetThemeIos, kWidgetThemeAndroidDark, kWidgetThemeAndroidLight] into tThemeList
-
- if not(pWidgetTheme is in tThemeList) then
- throw "invalid widget theme"
- end if
+ put pTheme into mTheme
- put pWidgetTheme into mWidgetTheme
- if mWidgetTheme contains "Android" then
- put "Teal" into mColorScheme
+ if mTheme is "native" then
+ put getNativeThemeName() into mWidgetTheme
else
- put the empty string into mColorScheme
+ put mTheme into mWidgetTheme
end if
- redraw all
-end handler
-
-constant kAndroidColorSchemeRed is "Red"
-constant kAndroidColorSchemePink is "Pink"
-constant kAndroidColorSchemePurple is "Purple"
-constant kAndroidColorSchemeDeepPurple is "Deep Purple"
-constant kAndroidColorSchemeIndigo is "Indigo"
-constant kAndroidColorSchemeBlue is "Blue"
-constant kAndroidColorSchemeLightBlue is "Light Blue"
-constant kAndroidColorSchemeCyan is "Cyan"
-constant kAndroidColorSchemeTeal is "Teal"
-constant kAndroidColorSchemeGreen is "Green"
-constant kAndroidColorSchemeLightGreen is "Light Green"
-constant kAndroidColorSchemeLime is "Lime"
-constant kAndroidColorSchemeYellow is "Yellow"
-constant kAndroidColorSchemeAmber is "Amber"
-constant kAndroidColorSchemeOrange is "Orange"
-constant kAndroidColorSchemeDeepOrange is "Deep Orange"
-constant kAndroidColorSchemeBrown is "Brown"
-constant kAndroidColorSchemeGrey is "Grey"
-constant kAndroidColorSchemeBlueGrey is "Blue Grey"
-
-private handler setColorScheme(in pColorScheme as String) returns nothing
-
- if pColorScheme is mColorScheme then
- return
- end if
-
- variable tColorSchemeList as List
- put [kAndroidColorSchemeRed, kAndroidColorSchemePink, kAndroidColorSchemePurple, kAndroidColorSchemeDeepPurple, kAndroidColorSchemeIndigo, kAndroidColorSchemeBlue, kAndroidColorSchemeLightBlue, kAndroidColorSchemeCyan, kAndroidColorSchemeTeal, kAndroidColorSchemeGreen, kAndroidColorSchemeLightGreen, kAndroidColorSchemeLime, kAndroidColorSchemeYellow, kAndroidColorSchemeAmber, kAndroidColorSchemeOrange, kAndroidColorSchemeDeepOrange, kAndroidColorSchemeBrown, kAndroidColorSchemeGrey, kAndroidColorSchemeBlueGrey] into tColorSchemeList
- if not(pColorScheme is in tColorSchemeList) then
- throw "invalid color scheme"
+ if not (mWidgetTheme is in kKnownThemes) then
+ throw "invalid theme name '" & mWidgetTheme & "'"
end if
- if mWidgetTheme contains "Android" then
- put pColorScheme into mColorScheme
- else
- put the empty string into mColorScheme
- end if
redraw all
-
end handler
private handler setSwitch(in pIsOn as Boolean) returns nothing
- if my enabled is false then
- return
- end if
-
put pIsOn into mSwitchIsOn
put mSwitchIsOn into mSwitchIsInOnPosition
redraw all
end handler
---------------------------------------------------------------------------------
---
--- Converting Data Types
---
---------------------------------------------------------------------------------
-
--- this handler converts a string of numbers to an RGBA color
-private handler stringToColor(in pString as String) returns Color
- variable tRed as Real
- variable tGreen as Real
- variable tBlue as Real
- variable tAlpha as Real
-
- variable tComponentList as List
- split pString by "," into tComponentList
-
- variable tComponentCount
- put the number of elements in tComponentList into tComponentCount
- if tComponentCount is not 3 and tComponentCount is not 4 then
- -- Invalid number of components detected
- throw "Invalid color"
- end if
-
- put (element 1 of tComponentList) parsed as number into tRed
- put (element 2 of tComponentList) parsed as number into tGreen
- put (element 3 of tComponentList) parsed as number into tBlue
-
- if tComponentCount is 4 then
- put (element 4 of tComponentList) parsed as number into tAlpha
- else
- put 255 into tAlpha
- end if
-
- return color [ tRed/255, tGreen/255, tBlue/255, tAlpha/255 ]
-end handler
-
--- this handler converts an RGBA color to a string of numbers
-private handler colorToString(in pColor as Color) returns String
-
- variable tRed as String
- variable tGreen as String
- variable tBlue as String
- variable tAlpha as String
-
- put stripZeros((the rounded of ((the red of pColor) * 255)) formatted as string) into tRed
- put stripZeros((the rounded of ((the green of pColor) * 255)) formatted as string) into tGreen
- put stripZeros((the rounded of ((the blue of pColor) * 255)) formatted as string) into tBlue
- put stripZeros((the rounded of ((the alpha of pColor) * 255)) formatted as string) into tAlpha
-
- return tRed & "," & tGreen & "," & tBlue & "," & tAlpha
-end handler
-
--- this handler strips the zeros when a integer is formatted as a string
-private handler stripZeros(in tString as String) returns String
- if tString contains "." then
- variable tCount as Integer
- repeat while ((the last char of tString) is in ".0")
- if the last char of tString is "." then
- delete the last char of tString
- exit repeat
- else
- delete the last char of tString
- end if
- end repeat
- end if
- return tString
+private handler setShowFrameBorder(in pShowBorder as Boolean) returns nothing
+ put pShowBorder into mShowFrameBorder
+ redraw all
end handler
end widget