ProgressBarLib — Progress Bar Control Library

Progress bar controls for displaying task completion, download progress, or any value within a defined range. Supports both horizontal and vertical orientations, configurable min/max ranges, timer-driven animation, and a full mouse/drag event system. 79 functions.

CategoryCountDescription
Error Handling4progressbar_error, errormsg$, strerror$, clearerror
Creation & Destruction3progressbar# (2 overloads), progressbar_free
Value Properties6value, min, max (get/set)
Orientation2orientation (get/set)
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)
Tag & Parent6tag (get/set), parent# (get/set), bringtofront#, sendtoback#
Events2210 event types × set/get + clearcallbacks#

Cross-Platform Support

PlatformStatusNotes
Windows✅ Full SupportWin32/Win64 — native progress bar style
Linux✅ Full SupportGTK-based
Android✅ Full SupportMaterial-style progress

Error Handling

FunctionSignatureDescription
progressbar_error()progressbar_error@Last error code (0 = no error)
progressbar_errormsg$()progressbar_errormsg$@Last error message as string
progressbar_strerror$(code)progressbar_strerror$@nDescription for a given error code
progressbar_clearerror()progressbar_clearerror@Clear the error state

Numeric Values Reference

Control Alignment progressbar_align#

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

Orientation progressbar_orientation#

ValueDescriptionTypical Size
0Horizontal (default)Wide × short (e.g., 300 × 25)
1VerticalNarrow × tall (e.g., 30 × 150)

Drag Mode progressbar_dragmode#

ValueDescription
0None (default)
1Automatic drag enabled

Creation & Destruction

FunctionSignatureDescription
progressbar#(parent#)progressbar#@#Create progress bar with default size
progressbar#(parent#, x, y, w, h)progressbar#@#nnnnCreate with position and size
progressbar_free(pb#)progressbar_free@#Destroy progress bar and release resources
╯ plan9basic
let pb# = progressbar#(frm#, 20, 50, 360, 25)
progressbar_min#(pb#, 0)
progressbar_max#(pb#, 100)
progressbar_value#(pb#, 0)

Value Properties

FunctionSignatureDescription
progressbar_value(pb#)progressbar_value@#Get current value
progressbar_value#(pb#, n)progressbar_value#@#nSet current value
progressbar_min(pb#)progressbar_min@#Get minimum value
progressbar_min#(pb#, n)progressbar_min#@#nSet minimum value
progressbar_max(pb#)progressbar_max@#Get maximum value
progressbar_max#(pb#, n)progressbar_max#@#nSet maximum value
╯ plan9basic
' Standard 0-100 percentage range
progressbar_min#(pb#, 0)
progressbar_max#(pb#, 100)
progressbar_value#(pb#, 50)   ' 50%

' Custom range (e.g., steps in a process)
progressbar_min#(pb#, 0)
progressbar_max#(pb#, 4)      ' 4 steps
progressbar_value#(pb#, 2)    ' Step 2 of 4

' Read current progress
let pct = progressbar_value(pb#)
println str$(pct) + "%"
⚠ Warning: Always set min and max before setting value. Setting a value outside the min/max range may produce unexpected results.
ⓘ Note: The progress bar displays a filled portion proportional to (value − min) / (max − min). For percentage-based progress, use min=0 and max=100.

Orientation

FunctionSignatureDescription
progressbar_orientation(pb#)progressbar_orientation@#Get orientation (0=horizontal, 1=vertical)
progressbar_orientation#(pb#, n)progressbar_orientation#@#nSet orientation
╯ plan9basic
' Horizontal (default) - wide and short
let pbH# = progressbar#(frm#, 20, 30, 300, 25)
progressbar_orientation#(pbH#, 0)

' Vertical - narrow and tall
let pbV# = progressbar#(frm#, 20, 30, 30, 150)
progressbar_orientation#(pbV#, 1)
ⓘ Note: When switching to vertical orientation, consider swapping the width and height values. A horizontal bar of 300×25 becomes a vertical bar of 30×150.

Position & Size

FunctionSignatureDescription
progressbar_x(pb#)progressbar_x@#Get X position
progressbar_x#(pb#, x)progressbar_x#@#nSet X position
progressbar_y(pb#)progressbar_y@#Get Y position
progressbar_y#(pb#, y)progressbar_y#@#nSet Y position
progressbar_width(pb#)progressbar_width@#Get width
progressbar_width#(pb#, w)progressbar_width#@#nSet width
progressbar_height(pb#)progressbar_height@#Get height
progressbar_height#(pb#, h)progressbar_height#@#nSet height
progressbar_bounds#(pb#, x, y, w, h)progressbar_bounds#@#nnnnSet position and size in one call
progressbar_move#(pb#, x, y)progressbar_move#@#nnSet position only
progressbar_size#(pb#, w, h)progressbar_size#@#nnSet size only

Alignment & Margins

FunctionSignatureDescription
progressbar_align(pb#)progressbar_align@#Get control alignment
progressbar_align#(pb#, n)progressbar_align#@#nSet alignment
progressbar_margin#(pb#, n)progressbar_margin#@#nSet uniform margin on all four sides
progressbar_margins#(pb#, l, t, r, b)progressbar_margins#@#nnnnSet individual margins
progressbar_marginleft(pb#)progressbar_marginleft@#Get left margin
progressbar_marginleft#(pb#, n)progressbar_marginleft#@#nSet left margin
progressbar_margintop(pb#)progressbar_margintop@#Get top margin
progressbar_margintop#(pb#, n)progressbar_margintop#@#nSet top margin
progressbar_marginright(pb#)progressbar_marginright@#Get right margin
progressbar_marginright#(pb#, n)progressbar_marginright#@#nSet right margin
progressbar_marginbottom(pb#)progressbar_marginbottom@#Get bottom margin
progressbar_marginbottom#(pb#, n)progressbar_marginbottom#@#nSet bottom margin
╯ plan9basic
' Full-width progress bar docked to bottom
let pb# = progressbar#(frm#)
progressbar_align#(pb#, 4)       ' Bottom
progressbar_height#(pb#, 8)      ' Thin bar
progressbar_margin#(pb#, 5)      ' 5px gap all sides

Visibility & State

FunctionSignatureDescription
progressbar_visible(pb#)progressbar_visible@#Get visibility (0/1)
progressbar_visible#(pb#, n)progressbar_visible#@#nSet visibility
progressbar_enabled(pb#)progressbar_enabled@#Get enabled state (0/1)
progressbar_enabled#(pb#, n)progressbar_enabled#@#nSet enabled state
progressbar_opacity(pb#)progressbar_opacity@#Get opacity (0.0–1.0)
progressbar_opacity#(pb#, value)progressbar_opacity#@#nSet opacity
progressbar_hittest(pb#)progressbar_hittest@#Get hit-test state (0/1)
progressbar_hittest#(pb#, n)progressbar_hittest#@#nEnable/disable mouse hit testing
progressbar_dragmode(pb#)progressbar_dragmode@#Get drag mode (0=none, 1=auto)
progressbar_dragmode#(pb#, n)progressbar_dragmode#@#nSet drag mode
╯ plan9basic
' Show progress bar only during operation
progressbar_visible#(pb#, 0)   ' Hidden initially

' When task starts
progressbar_visible#(pb#, 1)   ' Show
progressbar_value#(pb#, 0)

' When task ends
progressbar_visible#(pb#, 0)   ' Hide again

Tag & Parent

FunctionSignatureDescription
progressbar_tag(pb#)progressbar_tag@#Get user-defined integer tag
progressbar_tag#(pb#, n)progressbar_tag#@#nSet user-defined integer tag
progressbar_parent#(pb#)progressbar_parent#@#Get parent control pointer
progressbar_parent#(pb#, parent#)progressbar_parent#@##Move progress bar to a different parent
progressbar_bringtofront#(pb#)progressbar_bringtofront#@#Bring to front of Z-order
progressbar_sendtoback#(pb#)progressbar_sendtoback#@#Send to back of Z-order

Events

Each event has a setter (progressbar_onXXX#(pb#, func$)) and a getter (progressbar_onXXX$(pb#)). Use progressbar_clearcallbacks#(pb#) to disconnect all callbacks at once.

Mouse Events

Event SetterGetterCallback Signature
progressbar_onclick#(pb#, func$)progressbar_onclick$(pb#)function name(sender#)
progressbar_ondblclick#(pb#, func$)progressbar_ondblclick$(pb#)function name(sender#)
progressbar_onmousedown#(pb#, func$)progressbar_onmousedown$(pb#)function name(sender#, button, x, y, shift$)
progressbar_onmouseup#(pb#, func$)progressbar_onmouseup$(pb#)function name(sender#, button, x, y, shift$)
progressbar_onmousemove#(pb#, func$)progressbar_onmousemove$(pb#)function name(sender#, x, y, shift$)
progressbar_onmouseenter#(pb#, func$)progressbar_onmouseenter$(pb#)function name(sender#)
progressbar_onmouseleave#(pb#, func$)progressbar_onmouseleave$(pb#)function name(sender#)
progressbar_onresize#(pb#, func$)progressbar_onresize$(pb#)function name(sender#)

Drag Events

Event SetterGetterCallback Signature
progressbar_ondragenter#(pb#, func$)progressbar_ondragenter$(pb#)function name(sender#)
progressbar_ondragover#(pb#, func$)progressbar_ondragover$(pb#)function name(sender#)
progressbar_ondragdrop#(pb#, func$)progressbar_ondragdrop$(pb#)function name(sender#)
progressbar_ondragleave#(pb#, func$)progressbar_ondragleave$(pb#)function name(sender#)
progressbar_clearcallbacks#(pb#)Disconnect all event callbacks

Timer-Driven Animation Pattern

Progress bars are almost always updated using a Timer. Blocking the UI thread with a loop prevents the progress bar from repainting. The standard pattern is:

StepActionCode
1Create timer with intervaltimer_interval#(tmr#, 50)
2Start timer when task beginstimer_start#(tmr#)
3Increment value in OnTimerprogressbar_value#(pb#, val + 1)
4Stop timer when completetimer_stop#(tmr#)
╯ timer_pattern.bas
' Standard timer-driven progress pattern
let tmr# = timer#()
timer_interval#(tmr#, 50)
timer_ontimer#(tmr#, "OnTick")

function OnStart(sender#)
    progressbar_value#(pb#, 0)
    button_enabled#(btnStart#, 0)
    timer_start#(tmr#)
endfunction

function OnTick(sender#) local val
    val = progressbar_value(pb#) + 1
    progressbar_value#(pb#, val)
    label_text#(lblPct#, str$(val) + "%")
    if val >= progressbar_max(pb#) then
        timer_stop#(tmr#)
        button_enabled#(btnStart#, 1)
    endif
endfunction
⚠ Warning: Never use a blocking loop (for i = 0 to 100 ... next) to animate a progress bar. The UI will freeze and the bar won't update visually. Always use a Timer for smooth animation.
ⓘ Note: Timer intervals between 30–100 ms provide smooth animation. Faster intervals (30 ms) give smoother visuals; slower intervals (100 ms) use less CPU.

Complete Examples

File Download Simulation

╯ download.bas
function OnDownload(sender#)
    progressbar_value#(pb#, 0)
    button_enabled#(btnDownload#, 0)
    timer_start#(tmr#)
endfunction

function OnProgress(sender#) local val, pct$
    val = progressbar_value(pb#) + rnd(5) + 1
    if val > 100 then val = 100
    progressbar_value#(pb#, val)
    pct$ = str$(int(val)) + "%"
    label_text#(lblPercent#, pct$)
    if val >= 100 then
        timer_stop#(tmr#)
        label_text#(lblFile#, "Download complete!")
        button_enabled#(btnDownload#, 1)
    endif
endfunction

let frm# = form#("Download Progress", 450, 180)
form_position#(frm#, 4)

let lblFile# = label#(frm#, "Downloading: large_file.zip")
label_move#(lblFile#, 20, 20)

let pb# = progressbar#(frm#, 20, 50, 410, 25)
progressbar_max#(pb#, 100)

let lblPercent# = label#(frm#, "0%")
label_move#(lblPercent#, 200, 85)

let btnDownload# = button#(frm#, "Start Download", 160, 120, 130, 35)
button_onclick#(btnDownload#, "OnDownload")

let tmr# = timer#()
timer_interval#(tmr#, 100)
timer_ontimer#(tmr#, "OnProgress")

form_show(frm#)

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

Multi-Step Installation

╯ install.bas
function OnInstall(sender#)
    button_enabled#(btnInstall#, 0)

    label_text#(lblStep#, "Step 1: Copying files...")
    progressbar_value#(pb#, 1)
    pause(1)

    label_text#(lblStep#, "Step 2: Configuring...")
    progressbar_value#(pb#, 2)
    pause(1)

    label_text#(lblStep#, "Step 3: Installing components...")
    progressbar_value#(pb#, 3)
    pause(1)

    label_text#(lblStep#, "Step 4: Finalizing...")
    progressbar_value#(pb#, 4)
    pause(1)

    label_text#(lblStep#, "Installation complete!")
    button_text#(btnInstall#, "Close")
    button_enabled#(btnInstall#, 1)
endfunction

let frm# = form#("Installation", 400, 200)
form_position#(frm#, 4)

let lblStep# = label#(frm#, "Ready to install")
label_move#(lblStep#, 20, 20)

let pb# = progressbar#(frm#, 20, 55, 360, 20)
progressbar_max#(pb#, 4)

let btnInstall# = button#(frm#, "Install", 150, 100, 100, 35)
button_onclick#(btnInstall#, "OnInstall")

form_show(frm#)

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

Vertical Level Meters

╯ levels.bas
let frm# = form#("Levels", 300, 250)
form_position#(frm#, 4)

' CPU meter
let pb1# = progressbar#(frm#, 50, 30, 30, 150)
progressbar_orientation#(pb1#, 1)
progressbar_max#(pb1#, 100)
progressbar_value#(pb1#, 75)

' Memory meter
let pb2# = progressbar#(frm#, 120, 30, 30, 150)
progressbar_orientation#(pb2#, 1)
progressbar_max#(pb2#, 100)
progressbar_value#(pb2#, 50)

' Disk meter
let pb3# = progressbar#(frm#, 190, 30, 30, 150)
progressbar_orientation#(pb3#, 1)
progressbar_max#(pb3#, 100)
progressbar_value#(pb3#, 25)

label#(frm#, "CPU", 50, 190)
label#(frm#, "MEM", 117, 190)
label#(frm#, "DISK", 183, 190)

form_show(frm#)

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

Progress with Percentage Label

╯ percentage.bas
function OnRun(sender#)
    progressbar_value#(pb#, 0)
    timer_start#(tmr#)
endfunction

function OnTick(sender#) local val
    val = progressbar_value(pb#) + 1
    progressbar_value#(pb#, val)
    label_text#(lblPct#, str$(val) + "%")
    if val >= 100 then timer_stop#(tmr#)
endfunction

let frm# = form#("Task Progress", 400, 150)
form_position#(frm#, 4)

let pb# = progressbar#(frm#, 20, 30, 360, 25)
progressbar_max#(pb#, 100)

let lblPct# = label#(frm#, "0%")
label_bounds#(lblPct#, 180, 65, 40, 20)
label_textalign#(lblPct#, 0)

let btnRun# = button#(frm#, "Run Task", 150, 95, 100, 35)
button_onclick#(btnRun#, "OnRun")

let tmr# = timer#()
timer_interval#(tmr#, 30)
timer_ontimer#(tmr#, "OnTick")

form_show(frm#)

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

Best Practices

PracticeWhy
Set min and max before valueEnsures the value falls within the valid range
Use Timers for animationBlocking loops freeze the UI; timers allow smooth repainting
Use vertical orientation for level metersprogressbar_orientation#(pb#, 1) for CPU, memory, audio level displays
Pair with a Label for percentageProgress bars have no built-in text; use label_text# to show “X%”
Disable buttons during processingPrevents multiple clicks while a task runs
Timer interval 30–100 ms30 ms for smooth animation, 100 ms for less CPU usage
Hide when idleUse progressbar_visible#(pb#, 0) when no task is running
Use custom ranges for stepsmax = 4 for a 4-step installer is cleaner than calculating percentages

Quick Reference

FunctionSignatureDescription
progressbar_error / errormsg$ / strerror$ / clearerrorvariousError handling (4)
progressbar#(parent#[, x, y, w, h])variousCreate (2 overloads)
progressbar_free(pb#)progressbar_free@#Destroy
progressbar_value / min / max (get/set)variousValue properties (6)
progressbar_orientation (get/set)variousOrientation (2)
progressbar_x/y/width/height (get/set) / bounds# / move# / size#variousPosition & size (14)
progressbar_align / margin# / margins# / margin[left/top/right/bottom]variousAlignment & margins (12)
progressbar_visible / enabled / opacity / hittest / dragmodevariousVisibility & state (10)
progressbar_tag / parent# / bringtofront# / sendtoback#variousTag & parent (6)
progressbar_onclick/ondblclick/onmousedown/up/move/enter/leave/onresize/ondragenter/over/drop/leavevariousEvents set+get (21)
progressbar_clearcallbacks#progressbar_clearcallbacks#@#Disconnect all events

79 functions. Part of the Plan9Basic GUI library system.