CircleLib — Circle Shape Library
Circle shapes for indicators, avatars, buttons, badges, loading dots, traffic lights, and data visualization. Circle is a special case of Ellipse where width equals height. Features fill/stroke styling, opacity, rotation, and a complete mouse event system. 81 functions.
| Category | Count | Description |
|---|---|---|
| Error Handling | 4 | circle_error, errormsg$, strerror$, clearerror |
| Creation & Destruction | 4 | circle# (3 overloads), circle_free |
| Fill | 3 | fill$ (get), fill# (set), fillnone# |
| Stroke | 11 | stroke$ / stroke# / strokenone#, thickness, dash, cap, join (get/set) |
| Position & Size | 14 | x, y, width, height (get/set), bounds#, move#, size# |
| Alignment & Margins | 12 | align (get/set), margin#, margins#, marginleft/top/right/bottom (get/set) |
| Visibility & State | 8 | visible, enabled, opacity, hittest (get/set) |
| Tag, Rotation & Parent | 8 | tag, rotation (get/set), parent# (get/set), bringtofront#, sendtoback#, invalidate# |
| Events | 19 | 9 event types × set/get + clearcallbacks# |
Cross-Platform Support
| Platform | Status | Notes |
|---|---|---|
| Windows | ✅ Full Support | Win32/Win64 |
| Linux | ✅ Full Support | GTK-based |
| Android | ✅ Full Support | Hardware-accelerated |
Error Handling
| Function | Signature | Description |
|---|---|---|
circle_error() | circle_error@ | Last error code (0 = no error) |
circle_errormsg$() | circle_errormsg$@ | Last error message as string |
circle_strerror$(code) | circle_strerror$@n | Description for a given error code |
circle_clearerror() | circle_clearerror@ | Clear the error state |
Numeric Values Reference
Control Alignment circle_align#
| Value | Description |
|---|---|
| 0 | None (absolute positioning) |
| 1 | Top |
| 2 | Left |
| 3 | Right |
| 4 | Bottom |
| 9 | Client (fill parent) |
Stroke Dash Style circle_strokedash#
| Value | Style |
|---|---|
| 0 | Solid |
| 1 | Dash |
| 2 | Dot |
| 3 | DashDot |
| 4 | DashDotDot |
Stroke Cap Style circle_strokecap#
| Value | Style |
|---|---|
| 0 | Flat |
| 1 | Round |
Stroke Join Style circle_strokejoin#
| Value | Style |
|---|---|
| 0 | Miter |
| 1 | Round |
| 2 | Bevel |
Creation & Destruction
| Function | Signature | Description |
|---|---|---|
circle#(parent#) | circle#@# | Create with default size |
circle#(parent#, w, h) | circle#@#nn | Create with specified size |
circle#(parent#, x, y, w, h) | circle#@#nnnn | Create with position and size |
circle_free(c#) | circle_free@# | Destroy circle shape |
' Perfect circle: width = height let c# = circle#(frm#, 50, 50, 80, 80) circle_fill#(c#, "#e74c3c") circle_strokenone#(c#) ' Ring (outline only) let ring# = circle#(frm#, 150, 50, 80, 80) circle_fillnone#(ring#) circle_stroke#(ring#, "#27ae60") circle_strokethickness#(ring#, 4)
⚠ Warning: For a true circle, always use equal width and height. If width ≠ height, the shape will render as an ellipse. Use EllipseLib if you intentionally want non-uniform dimensions.
Fill Properties
| Function | Signature | Description |
|---|---|---|
circle_fill$(c#) | circle_fill$@# | Get fill color as hex string |
circle_fill#(c#, color$) | circle_fill#@#$ | Set fill color ("#RRGGBB" or "#AARRGGBB") |
circle_fillnone#(c#) | circle_fillnone#@# | Remove fill (transparent body) |
| Pattern | Fill | Stroke | Use Case |
|---|---|---|---|
| Solid circle | circle_fill#(c#, color$) | circle_strokenone#(c#) | Status indicators, dots, badges |
| Bordered circle | circle_fill#(c#, color$) | circle_stroke#(c#, color$) | Avatars, buttons, decorations |
| Ring (hollow) | circle_fillnone#(c#) | circle_stroke#(c#, color$) | Rings, progress arcs, outlines |
ⓘ Note: Use
#AARRGGBB format for semi-transparent fills. Alpha ranges from 00 (fully transparent) to FF (fully opaque).Stroke Properties
| Function | Signature | Description |
|---|---|---|
circle_stroke$(c#) | circle_stroke$@# | Get stroke color |
circle_stroke#(c#, color$) | circle_stroke#@#$ | Set stroke color |
circle_strokenone#(c#) | circle_strokenone#@# | Remove stroke (no border) |
circle_strokethickness(c#) | circle_strokethickness@# | Get stroke thickness |
circle_strokethickness#(c#, n) | circle_strokethickness#@#n | Set stroke thickness |
circle_strokedash(c#) | circle_strokedash@# | Get dash style (0–4) |
circle_strokedash#(c#, n) | circle_strokedash#@#n | Set dash style |
circle_strokecap(c#) | circle_strokecap@# | Get cap style (0=Flat, 1=Round) |
circle_strokecap#(c#, n) | circle_strokecap#@#n | Set cap style |
circle_strokejoin(c#) | circle_strokejoin@# | Get join style (0=Miter, 1=Round, 2=Bevel) |
circle_strokejoin#(c#, n) | circle_strokejoin#@#n | Set join style |
Position & Size
| Function | Signature | Description |
|---|---|---|
circle_x(c#) | circle_x@# | Get X position |
circle_x#(c#, x) | circle_x#@#n | Set X position |
circle_y(c#) | circle_y@# | Get Y position |
circle_y#(c#, y) | circle_y#@#n | Set Y position |
circle_width(c#) | circle_width@# | Get width |
circle_width#(c#, w) | circle_width#@#n | Set width |
circle_height(c#) | circle_height@# | Get height |
circle_height#(c#, h) | circle_height#@#n | Set height |
circle_bounds#(c#, x, y, w, h) | circle_bounds#@#nnnn | Set position and size |
circle_move#(c#, x, y) | circle_move#@#nn | Set position only |
circle_size#(c#, w, h) | circle_size#@#nn | Set size only |
ⓘ Note: The X/Y coordinates specify the top-left corner of the bounding box, not the center. A circle at (50, 50) with size (80, 80) has its center at (90, 90).
Alignment & Margins
| Function | Signature | Description |
|---|---|---|
circle_align(c#) | circle_align@# | Get alignment |
circle_align#(c#, n) | circle_align#@#n | Set alignment |
circle_margin#(c#, n) | circle_margin#@#n | Set uniform margin on all four sides |
circle_margins#(c#, l, t, r, b) | circle_margins#@#nnnn | Set individual margins |
circle_marginleft(c#) | circle_marginleft@# | Get left margin |
circle_marginleft#(c#, n) | circle_marginleft#@#n | Set left margin |
circle_margintop(c#) | circle_margintop@# | Get top margin |
circle_margintop#(c#, n) | circle_margintop#@#n | Set top margin |
circle_marginright(c#) | circle_marginright@# | Get right margin |
circle_marginright#(c#, n) | circle_marginright#@#n | Set right margin |
circle_marginbottom(c#) | circle_marginbottom@# | Get bottom margin |
circle_marginbottom#(c#, n) | circle_marginbottom#@#n | Set bottom margin |
Visibility & State
| Function | Signature | Description |
|---|---|---|
circle_visible(c#) | circle_visible@# | Get visibility (0/1) |
circle_visible#(c#, n) | circle_visible#@#n | Set visibility |
circle_enabled(c#) | circle_enabled@# | Get enabled state (0/1) |
circle_enabled#(c#, n) | circle_enabled#@#n | Set enabled state |
circle_opacity(c#) | circle_opacity@# | Get opacity (0.0–1.0) |
circle_opacity#(c#, n) | circle_opacity#@#n | Set opacity |
circle_hittest(c#) | circle_hittest@# | Get hit-test state (0/1) |
circle_hittest#(c#, n) | circle_hittest#@#n | Enable/disable mouse hit testing |
⚠ Warning: Set
circle_hittest#(c#, 1) before assigning mouse event handlers. Without hit testing, the shape will not receive mouse events.Tag, Rotation & Parent
| Function | Signature | Description |
|---|---|---|
circle_tag(c#) | circle_tag@# | Get user-defined integer tag |
circle_tag#(c#, n) | circle_tag#@#n | Set user-defined integer tag |
circle_rotation(c#) | circle_rotation@# | Get rotation angle in degrees |
circle_rotation#(c#, angle) | circle_rotation#@#n | Set rotation angle |
circle_parent#(c#) | circle_parent#@# | Get parent control pointer |
circle_parent#(c#, parent#) | circle_parent#@## | Move to a different parent |
circle_bringtofront#(c#) | circle_bringtofront#@# | Bring to front of Z-order |
circle_sendtoback#(c#) | circle_sendtoback#@# | Send to back of Z-order |
circle_invalidate#(c#) | circle_invalidate#@# | Force the shape to redraw |
ⓘ Note: Rotation has no visible effect on a perfect circle, but it does affect the coordinate system if child controls are present.
Events
Each event has a setter (circle_onXXX#) and a getter (circle_onXXX$). Use circle_clearcallbacks#(c#) to disconnect all callbacks at once.
Mouse Events
| Event Setter | Getter | Callback Signature |
|---|---|---|
circle_onclick#(c#, func$) | circle_onclick$(c#) | function name(sender#) |
circle_ondblclick#(c#, func$) | circle_ondblclick$(c#) | function name(sender#) |
circle_onmousedown#(c#, func$) | circle_onmousedown$(c#) | function name(sender#, button, x, y, shift$) |
circle_onmouseup#(c#, func$) | circle_onmouseup$(c#) | function name(sender#, button, x, y, shift$) |
circle_onmousemove#(c#, func$) | circle_onmousemove$(c#) | function name(sender#, x, y, shift$) |
circle_onmouseenter#(c#, func$) | circle_onmouseenter$(c#) | function name(sender#) |
circle_onmouseleave#(c#, func$) | circle_onmouseleave$(c#) | function name(sender#) |
circle_onmousewheel#(c#, func$) | circle_onmousewheel$(c#) | function name(sender#, delta) |
Other Events
| Event Setter | Getter | Callback Signature |
|---|---|---|
circle_onresize#(c#, func$) | circle_onresize$(c#) | function name(sender#) |
circle_clearcallbacks#(c#) | — | Disconnect all event callbacks |
Circle vs Ellipse vs Arc vs Pie
| Shape | Library | Key Difference | Best For |
|---|---|---|---|
| Circle | CircleLib | Width = Height for true circle | Status indicators, avatars, dots, buttons |
| Ellipse | EllipseLib | Width ≠ Height supported | Ovals, decorative shapes |
| Arc | ArcLib | Partial circle (start/end angles) | Progress rings, gauges, dials |
| Pie | PieLib | Wedge shape (filled sector) | Charts, progress, segmented displays |
Complete Examples
Status Indicators
let frm# = form#("Status", 300, 150) form_position#(frm#, 4) ' Online indicator (green) let indOn# = circle#(frm#, 30, 30, 20, 20) circle_fill#(indOn#, "#27ae60") circle_strokenone#(indOn#) let lblOn# = label#(frm#, "Online") label_move#(lblOn#, 60, 33) ' Away indicator (yellow) let indAway# = circle#(frm#, 30, 60, 20, 20) circle_fill#(indAway#, "#f1c40f") circle_strokenone#(indAway#) let lblAway# = label#(frm#, "Away") label_move#(lblAway#, 60, 63) ' Offline indicator (gray) let indOff# = circle#(frm#, 30, 90, 20, 20) circle_fill#(indOff#, "#95a5a6") circle_strokenone#(indOff#) let lblOff# = label#(frm#, "Offline") label_move#(lblOff#, 60, 93) form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Traffic Light
let frm# = form#("Traffic Light", 150, 350) form_position#(frm#, 4) let state = 1 ' Background let bg# = roundrect#(frm#, 35, 20, 80, 220) roundrect_fill#(bg#, "#2c3e50") roundrect_corners#(bg#, 10) ' Red light (starts active) let red# = circle#(frm#, 45, 30, 60, 60) circle_fill#(red#, "#c0392b") circle_stroke#(red#, "#922b21") circle_strokethickness#(red#, 2) ' Yellow light let yellow# = circle#(frm#, 45, 100, 60, 60) circle_fill#(yellow#, "#7f8c8d") circle_stroke#(yellow#, "#5d6d7e") circle_strokethickness#(yellow#, 2) ' Green light let green# = circle#(frm#, 45, 170, 60, 60) circle_fill#(green#, "#7f8c8d") circle_stroke#(green#, "#5d6d7e") circle_strokethickness#(green#, 2) let btnNext# = button#(frm#, "Next") button_bounds#(btnNext#, 35, 270, 80, 30) button_onclick#(btnNext#, "OnNext") form_show(frm#) function OnNext(sender#) ' Reset all to gray circle_fill#(red#, "#7f8c8d") circle_fill#(yellow#, "#7f8c8d") circle_fill#(green#, "#7f8c8d") state = state + 1 if state > 3 then state = 1 ' Activate current light if state = 1 then circle_fill#(red#, "#c0392b") elseif state = 2 then circle_fill#(yellow#, "#f1c40f") elseif state = 3 then circle_fill#(green#, "#27ae60") endif endfunction while form_visible(frm#) = 1 processmessages() end while
Clickable Color Buttons
let frm# = form#("Circle Buttons", 400, 150) form_position#(frm#, 4) colors# = sdim#(4) colors#$[1] = "#e74c3c" : colors#$[2] = "#3498db" colors#$[3] = "#2ecc71" : colors#$[4] = "#9b59b6" for i = 1 to 4 let c# = circle#(frm#, 30 + i * 80, 30, 60, 60) circle_fill#(c#, colors#$[i]) circle_strokenone#(c#) circle_hittest#(c#, 1) circle_tag#(c#, i) circle_onclick#(c#, "OnCircleClick") circle_onmouseenter#(c#, "OnEnter") circle_onmouseleave#(c#, "OnLeave") next let lblSel# = label#(frm#, "Click a circle") label_move#(lblSel#, 20, 110) form_show(frm#) function OnCircleClick(sender#) label_text#(lblSel#, "Clicked: " + colors#$[circle_tag(sender#)]) endfunction function OnEnter(sender#) circle_opacity#(sender#, 0.7) endfunction function OnLeave(sender#) circle_opacity#(sender#, 1.0) endfunction while form_visible(frm#) = 1 processmessages() end while
Animated Loading Dots
let frm# = form#("Loading", 250, 100) form_position#(frm#, 4) let dot1# = circle#(frm#, 70, 35, 25, 25) circle_fill#(dot1#, "#3498db") circle_strokenone#(dot1#) let dot2# = circle#(frm#, 110, 35, 25, 25) circle_fill#(dot2#, "#3498db") circle_strokenone#(dot2#) circle_opacity#(dot2#, 0.25) let dot3# = circle#(frm#, 150, 35, 25, 25) circle_fill#(dot3#, "#3498db") circle_strokenone#(dot3#) circle_opacity#(dot3#, 0.25) let dotStep = 0 let tmr# = timer#() timer_interval#(tmr#, 300) timer_ontimer#(tmr#, "OnAnimate") timer_start#(tmr#) form_show(frm#) function OnAnimate(sender#) dotStep = dotStep + 1 if dotStep > 2 then dotStep = 0 ' Reset all to dim circle_opacity#(dot1#, 0.25) circle_opacity#(dot2#, 0.25) circle_opacity#(dot3#, 0.25) ' Highlight current dot if dotStep = 0 then circle_opacity#(dot1#, 1.0) elseif dotStep = 1 then circle_opacity#(dot2#, 1.0) elseif dotStep = 2 then circle_opacity#(dot3#, 1.0) endif endfunction while form_visible(frm#) = 1 processmessages() end while
Bouncing Ball
let frm# = form#("Bouncing Ball", 400, 300) form_position#(frm#, 4) let ball# = circle#(frm#, 50, 130, 40, 40) circle_fill#(ball#, "#e74c3c") circle_strokenone#(ball#) let posX = 50 let posY = 130 let dx = 4 let dy = 3 let tmr# = timer#() timer_interval#(tmr#, 16) timer_ontimer#(tmr#, "OnFrame") timer_start#(tmr#) form_show(frm#) function OnFrame(sender#) posX = posX + dx posY = posY + dy if posX >= 360 then dx = -4 if posX <= 0 then dx = 4 if posY >= 260 then dy = -3 if posY <= 0 then dy = 3 circle_move#(ball#, posX, posY) endfunction while form_visible(frm#) = 1 processmessages() end while
Best Practices
| Practice | Why |
|---|---|
| Use equal width and height for true circles | Unequal dimensions render as an ellipse |
Set hittest = 1 for interactive circles | Required for mouse events to fire on shapes |
Use fillnone# for rings | Transparent body with visible stroke creates hollow circles |
Use opacity for hover feedback | Change opacity on mouse enter/leave for subtle interaction |
Use tag to identify circles in shared callbacks | Retrieve with circle_tag(sender#) inside the handler |
Use circle_move# for animation | More efficient than setting x and y separately |
Use strokenone# for clean indicators | Flat color dots without borders look modern |
Quick Reference
| Function | Signature | Description |
|---|---|---|
circle_error / errormsg$ / strerror$ / clearerror | various | Error handling (4) |
circle#(parent#[, w, h] | [, x, y, w, h]) | various | Create (3 overloads) |
circle_free(c#) | circle_free@# | Destroy |
circle_fill$ / fill# / fillnone# | various | Fill (3) |
circle_stroke$ / stroke# / strokenone# / strokethickness / strokedash / strokecap / strokejoin | various | Stroke (11) |
circle_x/y/width/height (get/set) / bounds# / move# / size# | various | Position & size (14) |
circle_align / margin# / margins# / margin[left/top/right/bottom] | various | Alignment & margins (12) |
circle_visible / enabled / opacity / hittest | various | Visibility & state (8) |
circle_tag / rotation / parent# / bringtofront# / sendtoback# / invalidate# | various | Tag, rotation & parent (8) |
circle_onclick/ondblclick/onmousedown/up/move/enter/leave/onmousewheel/onresize | various | Events set+get (18) |
circle_clearcallbacks# | circle_clearcallbacks#@# | Disconnect all events |
81 functions. Part of the Plan9Basic GUI shape library system.