SwitchLib — Switch Control Library

Modern on/off toggle controls for Plan9Basic applications. Switches provide a touch-friendly toggle interface ideal for settings and preferences, with animated state transitions. Features include a dedicated OnSwitch event that fires only on actual state changes, programmatic toggle, alignment and margins, drag support, and a comprehensive event system. 91 functions.

CategoryCountDescription
Error Handling4switch_error, errormsg$, strerror$, clearerror
Creation & Destruction3switch# (2 overloads), switch_free
Checked State3ischecked (get/set), toggle#
Position & Size14x, y, width, height (get/set), bounds#, move#, size#
Alignment & Margins12align (get/set), margin#, margins#, marginleft/top/right/bottom (get/set)
Visibility & State10visible, enabled, opacity, hittest, dragmode (get/set)
Focus7isfocused, setfocus#, resetfocus#, canfocus (get/set), taborder (get/set)
Tag & Parent6tag (get/set), parent# (get/set), bringtofront#, sendtoback#
Events3215 event types × set/get + clearcallbacks#

Cross-Platform Support

PlatformStatusNotes
Windows✅ Full SupportWin32/Win64
Linux✅ Full SupportGTK-based
Android✅ Full SupportTouch-optimized toggle

Error Handling

FunctionSignatureDescription
switch_error()switch_error@Last error code (0 = no error)
switch_errormsg$()switch_errormsg$@Last error message as string
switch_strerror$(code)switch_strerror$@nDescription for a given error code
switch_clearerror()switch_clearerror@Clear the error state

Numeric Values Reference

Control Alignment switch_align#

ValueDescription
0None (absolute positioning)
1Top
2Left
3Right
4Bottom
9Client (fill parent)

Drag Mode switch_dragmode#

ValueDescription
0None (default)
1Automatic drag enabled

Creation & Destruction

FunctionSignatureDescription
switch#(parent#)switch#@#Create switch with default size
switch#(parent#, x, y, w, h)switch#@#nnnnCreate with position and size
switch_free(sw#)switch_free@#Destroy switch and release resources
╯ plan9basic
let sw# = switch#(frm#, 180, 45, 50, 25)

' Cleanup
switch_free(sw#)
ⓘ Note: Switch controls have no built-in label text. Pair them with a Label for descriptive text. Consider using larger dimensions (e.g., 60×30 or 80×40) on touch interfaces like Android and iOS.

Checked State

FunctionSignatureDescription
switch_ischecked(sw#)switch_ischecked@#Get checked state (0=off, 1=on)
switch_ischecked#(sw#, n)switch_ischecked#@#nSet checked state
switch_toggle#(sw#)switch_toggle#@#Toggle current state (on→off or off→on)
╯ plan9basic
' Set switch on
switch_ischecked#(sw#, 1)

' Read state
if switch_ischecked(sw#) = 1 then
    println "ON"
else
    println "OFF"
endif

' Toggle (simpler than reading + setting)
switch_toggle#(sw#)
ⓘ Note: switch_toggle# is a convenience function — it reads the current state and flips it. Equivalent to switch_ischecked#(sw#, 1 - switch_ischecked(sw#)) but cleaner.

Position & Size

FunctionSignatureDescription
switch_x(sw#)switch_x@#Get X position
switch_x#(sw#, x)switch_x#@#nSet X position
switch_y(sw#)switch_y@#Get Y position
switch_y#(sw#, y)switch_y#@#nSet Y position
switch_width(sw#)switch_width@#Get width
switch_width#(sw#, w)switch_width#@#nSet width
switch_height(sw#)switch_height@#Get height
switch_height#(sw#, h)switch_height#@#nSet height
switch_bounds#(sw#, x, y, w, h)switch_bounds#@#nnnnSet position and size in one call
switch_move#(sw#, x, y)switch_move#@#nnSet position only
switch_size#(sw#, w, h)switch_size#@#nnSet size only

Alignment & Margins

FunctionSignatureDescription
switch_align(sw#)switch_align@#Get control alignment
switch_align#(sw#, n)switch_align#@#nSet alignment (0=none, 1=top, 2=left, 3=right, 4=bottom, 9=client)
switch_margin#(sw#, n)switch_margin#@#nSet uniform margin on all four sides
switch_margins#(sw#, l, t, r, b)switch_margins#@#nnnnSet individual margins
switch_marginleft(sw#)switch_marginleft@#Get left margin
switch_marginleft#(sw#, n)switch_marginleft#@#nSet left margin
switch_margintop(sw#)switch_margintop@#Get top margin
switch_margintop#(sw#, n)switch_margintop#@#nSet top margin
switch_marginright(sw#)switch_marginright@#Get right margin
switch_marginright#(sw#, n)switch_marginright#@#nSet right margin
switch_marginbottom(sw#)switch_marginbottom@#Get bottom margin
switch_marginbottom#(sw#, n)switch_marginbottom#@#nSet bottom margin

Visibility & State

FunctionSignatureDescription
switch_visible(sw#)switch_visible@#Get visibility (0/1)
switch_visible#(sw#, n)switch_visible#@#nSet visibility
switch_enabled(sw#)switch_enabled@#Get enabled state (0/1)
switch_enabled#(sw#, n)switch_enabled#@#nSet enabled state
switch_opacity(sw#)switch_opacity@#Get opacity (0.0–1.0)
switch_opacity#(sw#, value)switch_opacity#@#nSet opacity
switch_hittest(sw#)switch_hittest@#Get hit-test state (0/1)
switch_hittest#(sw#, n)switch_hittest#@#nEnable/disable mouse hit testing
switch_dragmode(sw#)switch_dragmode@#Get drag mode (0=none, 1=auto)
switch_dragmode#(sw#, n)switch_dragmode#@#nSet drag mode
╯ plan9basic
' Disable a switch (grayed out, not interactive)
switch_enabled#(sw#, 0)

' Semi-transparent
switch_opacity#(sw#, 0.5)

Focus

FunctionSignatureDescription
switch_isfocused(sw#)switch_isfocused@#Is this switch focused? (0/1)
switch_setfocus#(sw#)switch_setfocus#@#Set focus to the switch
switch_resetfocus#(sw#)switch_resetfocus#@#Remove focus from the switch
switch_canfocus(sw#)switch_canfocus@#Get whether switch can receive focus (0/1)
switch_canfocus#(sw#, n)switch_canfocus#@#nSet whether switch can receive focus
switch_taborder(sw#)switch_taborder@#Get tab order index
switch_taborder#(sw#, n)switch_taborder#@#nSet tab order index

Tag & Parent

FunctionSignatureDescription
switch_tag(sw#)switch_tag@#Get user-defined integer tag
switch_tag#(sw#, n)switch_tag#@#nSet user-defined integer tag
switch_parent#(sw#)switch_parent#@#Get parent control pointer
switch_parent#(sw#, parent#)switch_parent#@##Move switch to a different parent
switch_bringtofront#(sw#)switch_bringtofront#@#Bring to front of Z-order
switch_sendtoback#(sw#)switch_sendtoback#@#Send to back of Z-order

Events

Each event has a setter (switch_onXXX#(sw#, func$)) and a getter (switch_onXXX$(sw#)). Use switch_clearcallbacks#(sw#) to disconnect all callbacks at once.

State & Focus Events

Event SetterGetterCallback SignatureWhen It Fires
switch_onswitch#(sw#, func$)switch_onswitch$(sw#)function name(sender#)When the switch state actually changes (on→off or off→on)
switch_onclick#(sw#, func$)switch_onclick$(sw#)function name(sender#)On any click, regardless of state change
switch_ondblclick#(sw#, func$)switch_ondblclick$(sw#)function name(sender#)When double-clicked
switch_onenter#(sw#, func$)switch_onenter$(sw#)function name(sender#)When the control receives focus
switch_onexit#(sw#, func$)switch_onexit$(sw#)function name(sender#)When the control loses focus
switch_onresize#(sw#, func$)switch_onresize$(sw#)function name(sender#)When the switch is resized
⚠ Warning: OnSwitch vs OnClick: Use OnSwitch to respond to state changes — it only fires when the switch actually toggles. OnClick fires on every click even if the state doesn't change. For settings and preferences, OnSwitch is almost always the correct choice.

Keyboard Events

Event SetterGetterCallback Signature
switch_onkeydown#(sw#, func$)switch_onkeydown$(sw#)function name(sender#, key, keychar$, shift$)
switch_onkeyup#(sw#, func$)switch_onkeyup$(sw#)function name(sender#, key, keychar$, shift$)

Mouse Events

Event SetterGetterCallback Signature
switch_onmousedown#(sw#, func$)switch_onmousedown$(sw#)function name(sender#, button, x, y, shift$)
switch_onmouseup#(sw#, func$)switch_onmouseup$(sw#)function name(sender#, button, x, y, shift$)
switch_onmousemove#(sw#, func$)switch_onmousemove$(sw#)function name(sender#, x, y, shift$)
switch_onmouseenter#(sw#, func$)switch_onmouseenter$(sw#)function name(sender#)
switch_onmouseleave#(sw#, func$)switch_onmouseleave$(sw#)function name(sender#)

Drag Events

Event SetterGetterCallback Signature
switch_ondragenter#(sw#, func$)switch_ondragenter$(sw#)function name(sender#, x, y)
switch_ondragover#(sw#, func$)switch_ondragover$(sw#)function name(sender#, x, y)
switch_ondragdrop#(sw#, func$)switch_ondragdrop$(sw#)function name(sender#, x, y)
switch_ondragleave#(sw#, func$)switch_ondragleave$(sw#)function name(sender#)
switch_clearcallbacks#(sw#)Disconnect all event callbacks

Switch vs CheckBox

FeatureSwitchCheckBox
Visual StyleModern sliding toggleTraditional checkbox with tick mark
Built-in LabelNo (pair with Label)Yes (checkbox_text#)
AnimationAnimated slide transitionInstant check/uncheck
Touch InterfaceExcellent (large hit area)Smaller target
Primary EventOnSwitch (state change only)OnChange
Use CaseSettings, preferences, on/off togglesForms, checklists, multi-select options

Use Switch for settings and preferences with clear on/off semantics. Use CheckBox for forms, checklists, and when you need a built-in label.

Complete Examples

Settings Panel

╯ settings.bas
function OnApply(sender#) local settings$
    settings$ = "Settings:" + chr$(10)
    if switch_ischecked(swNotif#) = 1 then
        settings$ = settings$ + "Notifications: ON" + chr$(10)
    else
        settings$ = settings$ + "Notifications: OFF" + chr$(10)
    endif
    if switch_ischecked(swSound#) = 1 then
        settings$ = settings$ + "Sound: ON" + chr$(10)
    else
        settings$ = settings$ + "Sound: OFF" + chr$(10)
    endif
    if switch_ischecked(swDark#) = 1 then
        settings$ = settings$ + "Dark Mode: ON" + chr$(10)
    else
        settings$ = settings$ + "Dark Mode: OFF" + chr$(10)
    endif
    if switch_ischecked(swSave#) = 1 then
        settings$ = settings$ + "Auto-Save: ON"
    else
        settings$ = settings$ + "Auto-Save: OFF"
    endif
    println settings$
endfunction

let frm# = form#("Settings", 400, 350)
form_position#(frm#, 4)

label#(frm#, "Application Settings", 20, 15)
label_fontsize#(lbl#, 16)
label_bold#(lbl#, 1)

label#(frm#, "Enable Notifications", 20, 60)
let swNotif# = switch#(frm#, 300, 55, 50, 25)

label#(frm#, "Sound Effects", 20, 100)
let swSound# = switch#(frm#, 300, 95, 50, 25)

label#(frm#, "Dark Mode", 20, 140)
let swDark# = switch#(frm#, 300, 135, 50, 25)

label#(frm#, "Auto-Save", 20, 180)
let swSave# = switch#(frm#, 300, 175, 50, 25)
switch_ischecked#(swSave#, 1)

let btnApply# = button#(frm#, "Apply Settings", 140, 240, 120, 35)
button_onclick#(btnApply#, "OnApply")

form_show(frm#)

while form_visible(frm#) = 1
    processmessages()
end while

Interactive Toggle with Visual Feedback

╯ toggle.bas
function OnSwitchChange(sender#)
    if switch_ischecked(sender#) = 1 then
        label_text#(lblState#, "ON")
        label_fontcolor#(lblState#, "#00AA00")
    else
        label_text#(lblState#, "OFF")
        label_fontcolor#(lblState#, "#FF0000")
    endif
endfunction

function OnToggle(sender#)
    switch_toggle#(sw#)
endfunction

let frm# = form#("Toggle Demo", 350, 250)
form_position#(frm#, 4)

let sw# = switch#(frm#, 125, 50, 100, 40)

let lblState# = label#(frm#, "OFF")
label_move#(lblState#, 150, 110)
label_fontsize#(lblState#, 24)
label_bold#(lblState#, 1)
label_fontcolor#(lblState#, "#FF0000")

let btnToggle# = button#(frm#, "Toggle", 125, 170, 100, 35)

switch_onswitch#(sw#, "OnSwitchChange")
button_onclick#(btnToggle#, "OnToggle")

form_show(frm#)

while form_visible(frm#) = 1
    processmessages()
end while

Feature Toggles with Dependencies

╯ features.bas
function OnMasterSwitch(sender#) local enabled
    enabled = switch_ischecked(sender#)
    switch_enabled#(swA#, enabled)
    switch_enabled#(swB#, enabled)
    switch_enabled#(swC#, enabled)
    if enabled = 0 then
        switch_ischecked#(swA#, 0)
        switch_ischecked#(swB#, 0)
        switch_ischecked#(swC#, 0)
    endif
endfunction

let frm# = form#("Feature Toggles", 400, 300)
form_position#(frm#, 4)

label#(frm#, "Enable All Features", 20, 30)
label_bold#(lbl#, 1)
let swMaster# = switch#(frm#, 300, 25, 50, 25)

label#(frm#, "  Feature A", 20, 70)
let swA# = switch#(frm#, 300, 65, 50, 25)
switch_enabled#(swA#, 0)

label#(frm#, "  Feature B", 20, 110)
let swB# = switch#(frm#, 300, 105, 50, 25)
switch_enabled#(swB#, 0)

label#(frm#, "  Feature C", 20, 150)
let swC# = switch#(frm#, 300, 145, 50, 25)
switch_enabled#(swC#, 0)

switch_onswitch#(swMaster#, "OnMasterSwitch")

form_show(frm#)

while form_visible(frm#) = 1
    processmessages()
end while

Real-Time Preview

╯ preview.bas
function UpdatePreview(sender#)
    label_bold#(lblPreview#, switch_ischecked(swBold#))
    label_italic#(lblPreview#, switch_ischecked(swItalic#))
    if switch_ischecked(swLarge#) = 1 then
        label_fontsize#(lblPreview#, 20)
    else
        label_fontsize#(lblPreview#, 14)
    endif
endfunction

let frm# = form#("Preview Demo", 400, 300)
form_position#(frm#, 4)

let rectPreview# = rectangle#(frm#, 150, 20, 230, 150)
rectangle_fill#(rectPreview#, "#FFFFFF")

let lblPreview# = label#(frm#, "Preview Text")
label_bounds#(lblPreview#, 160, 80, 210, 30)
label_textalign#(lblPreview#, 0)

label#(frm#, "Bold", 20, 30)
let swBold# = switch#(frm#, 80, 25, 50, 25)

label#(frm#, "Italic", 20, 70)
let swItalic# = switch#(frm#, 80, 65, 50, 25)

label#(frm#, "Large", 20, 110)
let swLarge# = switch#(frm#, 80, 105, 50, 25)

switch_onswitch#(swBold#, "UpdatePreview")
switch_onswitch#(swItalic#, "UpdatePreview")
switch_onswitch#(swLarge#, "UpdatePreview")

form_show(frm#)

while form_visible(frm#) = 1
    processmessages()
end while

Best Practices

PracticeWhy
Use OnSwitch for state changesOnly fires when the state actually changes (not on every click)
Pair switches with labelsSwitch controls have no built-in text; use a Label next to each switch
Use switch_toggle# for programmatic toggleCleaner than reading and setting the state manually
Increase size for touch interfacesDefault size is small; use larger dimensions (60×30+) on mobile
Disable dependent controlsUse switch_enabled# to gray out sub-options when a master switch is off
Visual feedback is automaticThe switch animates between on/off states; no manual animation needed
Use Switch for on/off settingsUse CheckBox for forms and checklists instead

Quick Reference

FunctionSignatureDescription
switch_error / errormsg$ / strerror$ / clearerrorvariousError handling (4)
switch#(parent#[, x, y, w, h])variousCreate (2 overloads)
switch_free(sw#)switch_free@#Destroy
switch_ischecked (get/set) / toggle#variousChecked state (3)
switch_x/y/width/height (get/set) / bounds# / move# / size#variousPosition & size (14)
switch_align / margin# / margins# / margin[left/top/right/bottom]variousAlignment & margins (12)
switch_visible / enabled / opacity / hittest / dragmodevariousVisibility & state (10)
switch_isfocused / setfocus# / resetfocus# / canfocus / tabordervariousFocus (7)
switch_tag / parent# / bringtofront# / sendtoback#variousTag & parent (6)
switch_onswitch/onclick/ondblclick/onenter/onexit/onresize/onkeydown/onkeyup/onmousedown/up/move/enter/leave/ondragenter/over/drop/leavevariousEvents set+get (31)
switch_clearcallbacks#switch_clearcallbacks#@#Disconnect all events

91 functions. Part of the Plan9Basic GUI library system.