StringGridLib — Data Grid Control Library
Comprehensive functionality for creating and managing tabular data grids in Plan9Basic. StringGrid displays rows and columns of data with support for 9 column types (text, checkbox, currency, date, glyph, image, popup/dropdown, progress bar, time), in-cell editing, column sorting, clipboard operations, CSV import/export, popup column items, and a rich event system. 112 functions.
| Category | Count | Description |
|---|---|---|
| Error Handling | 4 | stringgrid_error, errormsg$, strerror$, clearerror |
| Creation & Destruction | 3 | stringgrid# (2 overloads), stringgrid_free |
| Row & Column Count | 3 | rowcount (get/set), colcount |
| Column Management | 4 | addcolumn#, deletecolumn, clearcolumns, column# |
| Column Properties | 11 | header, width, visible, readonly, type, align (get/set) |
| Cell Access | 8 | cell text (get/set), cellcheck (get/set), cellnum (get/set), cellprogress (get/set) |
| Row Operations | 9 | rowheight (get/set), insertrow, deleterow, moverow, swaprows, clearrow, copyrow, clearrows |
| Sorting | 2 | sort (text), sortnum (numeric) |
| Clipboard | 5 | copy, copysel, paste, copycell, pastecell |
| CSV Import/Export | 4 | exportcsv, importcsv, tocsv$, fromcsv |
| Selection | 5 | col (get/set), row (get/set), selectcell# |
| Grid Options | 10 | showhdr, editing, altcolors, colresize, rowselect (get/set) |
| Popup Columns | 3 | popupadd, popupclear, popupcount |
| Position & Size | 12 | x, y, width, height (get/set), bounds#, + align (get/set) |
| Visibility & State | 8 | visible, enabled, opacity (get/set) + focus, isfocused |
| Scrolling | 1 | scrolltorow |
| Tag & Parent | 4 | tag (get/set), parent# (get/set) |
| Events | 17 | 8 event types × set/get + clearcallbacks# |
Cross-Platform Support
| Platform | Status | Notes |
|---|---|---|
| Windows | ✅ Full Support | Win32/Win64 |
| Linux | ✅ Full Support | GTK-based |
| Android | ✅ Full Support | Mobile-optimized touch scrolling |
Error Handling
| Function | Signature | Description |
|---|---|---|
stringgrid_error() | stringgrid_error@ | Last error code (0 = no error) |
stringgrid_errormsg$() | stringgrid_errormsg$@ | Last error message as string |
stringgrid_strerror$(code) | stringgrid_strerror$@n | Description for a given error code |
stringgrid_clearerror() | stringgrid_clearerror@ | Clear the error state |
Numeric Values Reference
Column Types stringgrid_addcolumn#
| Value | Constant | Description | Cell Accessors |
|---|---|---|---|
| 0 | COL_STRING | Standard text column | cell$ / cell# |
| 1 | COL_CHECK | Checkbox column | cellcheck / cellcheck# |
| 2 | COL_CURRENCY | Currency formatted | cell$ / cell# |
| 3 | COL_DATE | Date column | cell$ / cell# |
| 4 | COL_GLYPH | Glyph/icon column | cellnum / cellnum# |
| 5 | COL_IMAGE | Image column | cell$ / cell# |
| 6 | COL_POPUP | Dropdown/popup column | cell$ / cell# + popup functions |
| 7 | COL_PROGRESS | Progress bar column | cellprogress / cellprogress# |
| 8 | COL_TIME | Time column | cell$ / cell# |
let COL_STRING = 0, let COL_CHECK = 1, etc.Control Alignment stringgrid_align#
| Value | Description |
|---|---|
| 0 | None (absolute positioning) |
| 1 | Top |
| 2 | Left |
| 3 | Right |
| 4 | Bottom |
| 9 | Client (fill parent) |
Column Text Alignment stringgrid_columnalign#
| Value | Description | Use Case |
|---|---|---|
| 0 | Center | Headers, status columns |
| 1 | Leading (Left) | Text, names, descriptions (default) |
| 2 | Trailing (Right) | Numbers, prices, quantities |
Creation & Destruction
| Function | Signature | Description |
|---|---|---|
stringgrid#(parent#) | stringgrid#@# | Create grid with default size |
stringgrid#(parent#, x, y, w, h) | stringgrid#@#nnnn | Create with position and size |
stringgrid_free(grid#) | stringgrid_free@# | Destroy grid and release resources |
let grid# = stringgrid#(frm#, 10, 10, 580, 350) ' Cleanup stringgrid_free(grid#)
Row & Column Count
| Function | Signature | Description |
|---|---|---|
stringgrid_rowcount(grid#) | stringgrid_rowcount@# | Get the number of data rows |
stringgrid_rowcount#(grid#, n) | stringgrid_rowcount#@#n | Set the number of data rows |
stringgrid_colcount(grid#) | stringgrid_colcount@# | Get the number of columns |
' Add columns first, then set row count stringgrid_addcolumn#(grid#, "Name", 0, 150) stringgrid_addcolumn#(grid#, "Age", 0, 60) ' Create 10 empty rows stringgrid_rowcount#(grid#, 10) println "Rows: " + str$(stringgrid_rowcount(grid#)) println "Cols: " + str$(stringgrid_colcount(grid#))
Column Management
| Function | Signature | Description |
|---|---|---|
stringgrid_addcolumn#(grid#, header$, type, width) | stringgrid_addcolumn#@#$nn | Add a column; returns column pointer |
stringgrid_deletecolumn(grid#, col) | stringgrid_deletecolumn@#n | Delete column at index |
stringgrid_clearcolumns(grid#) | stringgrid_clearcolumns@# | Remove all columns |
stringgrid_column#(grid#, col) | stringgrid_column#@#n | Get column object pointer |
' Define column types let COL_STRING = 0 let COL_CHECK = 1 let COL_PROGRESS = 7 ' Add columns: header$, type, width stringgrid_addcolumn#(grid#, "Done", COL_CHECK, 50) stringgrid_addcolumn#(grid#, "Task", COL_STRING, 200) stringgrid_addcolumn#(grid#, "Progress", COL_PROGRESS, 120) ' Delete last column stringgrid_deletecolumn(grid#, 2) ' Clear and rebuild stringgrid_clearcolumns(grid#)
Column Properties
| Function | Signature | Description |
|---|---|---|
stringgrid_columnheader$(grid#, col) | stringgrid_columnheader$@#n | Get column header text |
stringgrid_columnheader#(grid#, col, text$) | stringgrid_columnheader#@#n$ | Set column header text |
stringgrid_columnwidth(grid#, col) | stringgrid_columnwidth@#n | Get column width in pixels |
stringgrid_columnwidth#(grid#, col, w) | stringgrid_columnwidth#@#nn | Set column width |
stringgrid_columnvisible(grid#, col) | stringgrid_columnvisible@#n | Get column visibility (0/1) |
stringgrid_columnvisible#(grid#, col, n) | stringgrid_columnvisible#@#nn | Show/hide a column |
stringgrid_columnreadonly(grid#, col) | stringgrid_columnreadonly@#n | Get column read-only state (0/1) |
stringgrid_columnreadonly#(grid#, col, n) | stringgrid_columnreadonly#@#nn | Set column read-only |
stringgrid_columntype(grid#, col) | stringgrid_columntype@#n | Get column type (0–8) |
stringgrid_columnalign(grid#, col) | stringgrid_columnalign@#n | Get column text alignment (0=center, 1=left, 2=right) |
stringgrid_columnalign#(grid#, col, align) | stringgrid_columnalign#@#nn | Set column text alignment |
' Right-align numeric columns stringgrid_columnalign#(grid#, 1, 2) ' Age stringgrid_columnalign#(grid#, 2, 2) ' Price ' Make ID column read-only stringgrid_columnreadonly#(grid#, 0, 1) ' Hide a column without deleting it stringgrid_columnvisible#(grid#, 3, 0) ' Rename a header stringgrid_columnheader#(grid#, 0, "Full Name")
Cell Access
Different column types use different cell accessors. Text columns use cell$/cell#, checkbox columns use cellcheck, numeric columns use cellnum, and progress columns use cellprogress.
| Function | Signature | Description |
|---|---|---|
stringgrid_cell$(grid#, col, row) | stringgrid_cell$@#nn | Get cell text value |
stringgrid_cell#(grid#, col, row, text$) | stringgrid_cell#@#nn$ | Set cell text value |
stringgrid_cellcheck(grid#, col, row) | stringgrid_cellcheck@#nn | Get checkbox state (0=unchecked, 1=checked) |
stringgrid_cellcheck#(grid#, col, row, n) | stringgrid_cellcheck#@#nnn | Set checkbox state |
stringgrid_cellnum(grid#, col, row) | stringgrid_cellnum@#nn | Get cell numeric value |
stringgrid_cellnum#(grid#, col, row, value) | stringgrid_cellnum#@#nnn | Set cell numeric value |
stringgrid_cellprogress(grid#, col, row) | stringgrid_cellprogress@#nn | Get progress value (0–100) |
stringgrid_cellprogress#(grid#, col, row, value) | stringgrid_cellprogress#@#nnn | Set progress value (0–100) |
' Text cells (COL_STRING) stringgrid_cell#(grid#, 0, 0, "Alice") let name$ = stringgrid_cell$(grid#, 0, 0) ' Checkbox cells (COL_CHECK) stringgrid_cellcheck#(grid#, 1, 0, 1) ' Check it let checked = stringgrid_cellcheck(grid#, 1, 0) ' Numeric cells (COL_GLYPH or generic) stringgrid_cellnum#(grid#, 2, 0, 42) let val = stringgrid_cellnum(grid#, 2, 0) ' Progress cells (COL_PROGRESS) stringgrid_cellprogress#(grid#, 3, 0, 75) ' 75% let pct = stringgrid_cellprogress(grid#, 3, 0)
Row Operations
| Function | Signature | Description |
|---|---|---|
stringgrid_rowheight(grid#) | stringgrid_rowheight@# | Get row height in pixels |
stringgrid_rowheight#(grid#, h) | stringgrid_rowheight#@#n | Set row height for all rows |
stringgrid_insertrow(grid#, row) | stringgrid_insertrow@#n | Insert a new empty row at the given index |
stringgrid_deleterow(grid#, row) | stringgrid_deleterow@#n | Delete the row at the given index |
stringgrid_moverow(grid#, from, to) | stringgrid_moverow@#nn | Move a row from one index to another |
stringgrid_swaprows(grid#, row1, row2) | stringgrid_swaprows@#nn | Swap two rows |
stringgrid_clearrow(grid#, row) | stringgrid_clearrow@#n | Clear all cell values in a row |
stringgrid_copyrow(grid#, src, dest) | stringgrid_copyrow@#nn | Copy cell values from one row to another |
stringgrid_clearrows(grid#) | stringgrid_clearrows@# | Clear all rows (remove all data) |
' Insert row at the top stringgrid_insertrow(grid#, 0) ' Delete selected row let r = stringgrid_row(grid#) if r >= 0 then stringgrid_deleterow(grid#, r) ' Move row 3 to position 0 stringgrid_moverow(grid#, 3, 0) ' Swap rows 1 and 2 stringgrid_swaprows(grid#, 1, 2) ' Duplicate a row stringgrid_rowcount#(grid#, stringgrid_rowcount(grid#) + 1) stringgrid_copyrow(grid#, 0, stringgrid_rowcount(grid#) - 1)
Sorting
| Function | Signature | Description |
|---|---|---|
stringgrid_sort(grid#, col, asc) | stringgrid_sort@#nn | Sort by column using text (alphabetical) comparison |
stringgrid_sortnum(grid#, col, asc) | stringgrid_sortnum@#nn | Sort by column using numeric comparison |
' Sort by name alphabetically (ascending) stringgrid_sort(grid#, 0, 1) ' Sort by score numerically (descending) stringgrid_sortnum(grid#, 2, 0)
stringgrid_sort for text columns (names, cities) and stringgrid_sortnum for numeric columns (ages, prices, scores). Using the wrong one produces incorrect ordering — e.g., text sort orders “9” after “10”.asc parameter: 1 = ascending (A→Z, 0→9), 0 = descending (Z→A, 9→0).Clipboard
| Function | Signature | Description |
|---|---|---|
stringgrid_copy(grid#) | stringgrid_copy@# | Copy entire grid to clipboard (tab-delimited) |
stringgrid_copysel(grid#) | stringgrid_copysel@# | Copy current selection to clipboard |
stringgrid_paste(grid#) | stringgrid_paste@# | Paste from clipboard into the grid |
stringgrid_copycell(grid#, col, row) | stringgrid_copycell@#nn | Copy a specific cell to clipboard |
stringgrid_pastecell(grid#, col, row) | stringgrid_pastecell@#nn | Paste clipboard content into a specific cell |
' Copy entire grid stringgrid_copy(grid#) ' Copy just the selected cell let c = stringgrid_col(grid#) let r = stringgrid_row(grid#) stringgrid_copycell(grid#, c, r) ' Paste into specific cell stringgrid_pastecell(grid#, 0, 0)
CSV Import / Export
| Function | Signature | Description |
|---|---|---|
stringgrid_exportcsv(grid#, file$, delim$, hdr) | stringgrid_exportcsv@#$$n | Export grid to a CSV file |
stringgrid_importcsv(grid#, file$, delim$, hdr) | stringgrid_importcsv@#$$n | Import CSV file into the grid |
stringgrid_tocsv$(grid#, delim$, hdr) | stringgrid_tocsv$@#$n | Get grid data as a CSV string |
stringgrid_fromcsv(grid#, data$, delim$, hdr) | stringgrid_fromcsv@#$$n | Load grid from a CSV string |
' Export to file with comma delimiter, including headers stringgrid_exportcsv(grid#, "data.csv", ",", 1) ' Import from file stringgrid_importcsv(grid#, "data.csv", ",", 1) ' Export to string (for println, HTTP, etc.) let csv$ = stringgrid_tocsv$(grid#, ",", 1) println csv$ ' Load from string (e.g., from HTTP response) stringgrid_fromcsv(grid#, csv$, ",", 1) ' Use semicolon delimiter stringgrid_exportcsv(grid#, "data.csv", ";", 1)
hdr parameter: 1 = include/expect column headers as the first row, 0 = data only. The delim$ parameter accepts any single character (“,”, “;”, tab, etc.).Selection
| Function | Signature | Description |
|---|---|---|
stringgrid_col(grid#) | stringgrid_col@# | Get the currently selected column index |
stringgrid_col#(grid#, col) | stringgrid_col#@#n | Set the selected column |
stringgrid_row(grid#) | stringgrid_row@# | Get the currently selected row index |
stringgrid_row#(grid#, row) | stringgrid_row#@#n | Set the selected row |
stringgrid_selectcell#(grid#, col, row) | stringgrid_selectcell#@#nn | Select a specific cell (sets both col and row) |
' Read current selection let c = stringgrid_col(grid#) let r = stringgrid_row(grid#) println "Selected: col=" + str$(c) + " row=" + str$(r) ' Select a specific cell stringgrid_selectcell#(grid#, 2, 5)
Grid Options
| Function | Signature | Description |
|---|---|---|
stringgrid_showhdr(grid#) | stringgrid_showhdr@# | Get show column headers (0/1) |
stringgrid_showhdr#(grid#, n) | stringgrid_showhdr#@#n | Show/hide column headers |
stringgrid_editing(grid#) | stringgrid_editing@# | Get editing enabled (0/1) |
stringgrid_editing#(grid#, n) | stringgrid_editing#@#n | Enable/disable cell editing |
stringgrid_altcolors(grid#) | stringgrid_altcolors@# | Get alternating row colors (0/1) |
stringgrid_altcolors#(grid#, n) | stringgrid_altcolors#@#n | Enable/disable alternating row colors (zebra stripes) |
stringgrid_colresize(grid#) | stringgrid_colresize@# | Get column resize enabled (0/1) |
stringgrid_colresize#(grid#, n) | stringgrid_colresize#@#n | Allow/prevent user column resizing |
stringgrid_rowselect(grid#) | stringgrid_rowselect@# | Get row selection mode (0/1) |
stringgrid_rowselect#(grid#, n) | stringgrid_rowselect#@#n | Enable/disable full row selection mode |
' Typical grid setup stringgrid_editing#(grid#, 1) ' Allow cell editing stringgrid_altcolors#(grid#, 1) ' Zebra stripes stringgrid_colresize#(grid#, 1) ' User can resize columns stringgrid_rowselect#(grid#, 0) ' Cell selection (not full row) ' Read-only display grid stringgrid_editing#(grid#, 0) stringgrid_rowselect#(grid#, 1) ' Full row highlighting
Popup Column Items
Columns of type COL_POPUP (6) display a dropdown list. Use these functions to manage the dropdown choices:
| Function | Signature | Description |
|---|---|---|
stringgrid_popupadd(grid#, col, item$) | stringgrid_popupadd@#n$ | Add an item to the popup dropdown for a column |
stringgrid_popupclear(grid#, col) | stringgrid_popupclear@#n | Clear all popup items for a column |
stringgrid_popupcount(grid#, col) | stringgrid_popupcount@#n | Get the number of popup items |
let COL_POPUP = 6 ' Add a popup column stringgrid_addcolumn#(grid#, "Status", COL_POPUP, 100) ' Populate the dropdown choices stringgrid_popupadd(grid#, 0, "Active") stringgrid_popupadd(grid#, 0, "Inactive") stringgrid_popupadd(grid#, 0, "Pending") ' Set a cell value stringgrid_cell#(grid#, 0, 0, "Active") println "Choices: " + str$(stringgrid_popupcount(grid#, 0))
stringgrid_popupadd. The selected value is stored as text and can be read with stringgrid_cell$.Position & Size
| Function | Signature | Description |
|---|---|---|
stringgrid_x(grid#) | stringgrid_x@# | Get X position |
stringgrid_x#(grid#, x) | stringgrid_x#@#n | Set X position |
stringgrid_y(grid#) | stringgrid_y@# | Get Y position |
stringgrid_y#(grid#, y) | stringgrid_y#@#n | Set Y position |
stringgrid_width(grid#) | stringgrid_width@# | Get width |
stringgrid_width#(grid#, w) | stringgrid_width#@#n | Set width |
stringgrid_height(grid#) | stringgrid_height@# | Get height |
stringgrid_height#(grid#, h) | stringgrid_height#@#n | Set height |
stringgrid_bounds#(grid#, x, y, w, h) | stringgrid_bounds#@#nnnn | Set position and size in one call |
stringgrid_align(grid#) | stringgrid_align@# | Get control alignment |
stringgrid_align#(grid#, n) | stringgrid_align#@#n | Set control alignment (0=none, 1=top, 2=left, 3=right, 4=bottom, 9=client) |
' Fill the client area of a form stringgrid_align#(grid#, 9)
Visibility & State
| Function | Signature | Description |
|---|---|---|
stringgrid_visible(grid#) | stringgrid_visible@# | Get visibility (0/1) |
stringgrid_visible#(grid#, n) | stringgrid_visible#@#n | Set visibility |
stringgrid_enabled(grid#) | stringgrid_enabled@# | Get enabled state (0/1) |
stringgrid_enabled#(grid#, n) | stringgrid_enabled#@#n | Set enabled state |
stringgrid_opacity(grid#) | stringgrid_opacity@# | Get opacity (0.0–1.0) |
stringgrid_opacity#(grid#, value) | stringgrid_opacity#@#n | Set opacity |
Focus & Scrolling
| Function | Signature | Description |
|---|---|---|
stringgrid_focus(grid#) | stringgrid_focus@# | Set focus to the grid |
stringgrid_isfocused(grid#) | stringgrid_isfocused@# | Is the grid focused? (0/1) |
stringgrid_scrolltorow(grid#, row) | stringgrid_scrolltorow@#n | Scroll the grid to make a specific row visible |
' Select and scroll to row 50 stringgrid_row#(grid#, 50) stringgrid_scrolltorow(grid#, 50)
Tag & Parent
| Function | Signature | Description |
|---|---|---|
stringgrid_tag(grid#) | stringgrid_tag@# | Get user-defined integer tag |
stringgrid_tag#(grid#, n) | stringgrid_tag#@#n | Set user-defined integer tag |
stringgrid_parent#(grid#) | stringgrid_parent#@# | Get parent control pointer |
stringgrid_parent#(grid#, parent#) | stringgrid_parent#@## | Move grid to a different parent |
Events
Each event has a setter (stringgrid_onXXX#(grid#, func$)) and a getter (stringgrid_onXXX$(grid#)). Use stringgrid_clearcallbacks#(grid#) to disconnect all callbacks at once.
Cell & Selection Events
| Event Setter | Getter | Callback Signature | When It Fires |
|---|---|---|---|
stringgrid_oncellclick#(grid#, func$) | stringgrid_oncellclick$(grid#) | function name(sender#, col, row) | A cell is clicked |
stringgrid_oncelldblclick#(grid#, func$) | stringgrid_oncelldblclick$(grid#) | function name(sender#, col, row) | A cell is double-clicked |
stringgrid_onselectcell#(grid#, func$) | stringgrid_onselectcell$(grid#) | function name(sender#, col, row) | A new cell is about to be selected |
stringgrid_onselchanged#(grid#, func$) | stringgrid_onselchanged$(grid#) | function name(sender#) | The selection has changed |
stringgrid_oneditingdone#(grid#, func$) | stringgrid_oneditingdone$(grid#) | function name(sender#, col, row) | User finishes editing a cell |
Header & General Events
| Event Setter | Getter | Callback Signature | When It Fires |
|---|---|---|---|
stringgrid_onheaderclick#(grid#, func$) | stringgrid_onheaderclick$(grid#) | function name(sender#, col) | A column header is clicked (ideal for sorting) |
stringgrid_onclick#(grid#, func$) | stringgrid_onclick$(grid#) | function name(sender#) | The grid control is clicked |
stringgrid_onresize#(grid#, func$) | stringgrid_onresize$(grid#) | function name(sender#) | The grid is resized |
stringgrid_clearcallbacks#(grid#) | — | — | Disconnect all event callbacks |
Complete Examples
Data Entry Grid
let COL_STRING = 0 let COL_CHECK = 1 function OnAddRow(sender#) local cnt cnt = stringgrid_rowcount(grid#) stringgrid_rowcount#(grid#, cnt + 1) endfunction function OnDelRow(sender#) local row row = stringgrid_row(grid#) if row >= 0 then stringgrid_deleterow(grid#, row) endfunction function OnEdit(sender#, col, row) println "Edited [" + str$(col) + "," + str$(row) + "]: " + stringgrid_cell$(sender#, col, row) endfunction let frm# = form#("Data Entry", 600, 400) form_position#(frm#, 4) let grid# = stringgrid#(frm#, 10, 10, 580, 300) stringgrid_editing#(grid#, 1) stringgrid_altcolors#(grid#, 1) stringgrid_addcolumn#(grid#, "Product", COL_STRING, 150) stringgrid_addcolumn#(grid#, "Quantity", COL_STRING, 80) stringgrid_addcolumn#(grid#, "Price", COL_STRING, 80) stringgrid_addcolumn#(grid#, "In Stock", COL_CHECK, 70) stringgrid_columnalign#(grid#, 1, 2) stringgrid_columnalign#(grid#, 2, 2) stringgrid_rowcount#(grid#, 5) let btnAdd# = button#(frm#, "Add Row", 10, 320, 100, 30) let btnDel# = button#(frm#, "Delete Row", 120, 320, 100, 30) button_onclick#(btnAdd#, "OnAddRow") button_onclick#(btnDel#, "OnDelRow") stringgrid_oneditingdone#(grid#, "OnEdit") form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Sortable Table
let sortCol = 0 let sortAsc = 1 function OnHeaderClick(sender#, col) local isNumeric if col = sortCol then sortAsc = 1 - sortAsc else sortCol = col sortAsc = 1 endif isNumeric = 0 if col = 1 then isNumeric = 1 if col = 2 then isNumeric = 1 if isNumeric = 1 then stringgrid_sortnum(sender#, col, sortAsc) else stringgrid_sort(sender#, col, sortAsc) endif endfunction let frm# = form#("Sortable Table", 500, 350) form_position#(frm#, 4) let grid# = stringgrid#(frm#, 10, 10, 480, 300) stringgrid_addcolumn#(grid#, "Name", 0, 150) stringgrid_addcolumn#(grid#, "Age", 0, 60) stringgrid_addcolumn#(grid#, "Score", 0, 80) stringgrid_columnalign#(grid#, 1, 2) stringgrid_columnalign#(grid#, 2, 2) stringgrid_rowcount#(grid#, 5) stringgrid_cell#(grid#, 0, 0, "Alice") : stringgrid_cell#(grid#, 1, 0, "30") : stringgrid_cell#(grid#, 2, 0, "95") stringgrid_cell#(grid#, 0, 1, "Bob") : stringgrid_cell#(grid#, 1, 1, "25") : stringgrid_cell#(grid#, 2, 1, "87") stringgrid_cell#(grid#, 0, 2, "Carol") : stringgrid_cell#(grid#, 1, 2, "35") : stringgrid_cell#(grid#, 2, 2, "92") stringgrid_cell#(grid#, 0, 3, "David") : stringgrid_cell#(grid#, 1, 3, "28") : stringgrid_cell#(grid#, 2, 3, "78") stringgrid_cell#(grid#, 0, 4, "Eve") : stringgrid_cell#(grid#, 1, 4, "32") : stringgrid_cell#(grid#, 2, 4, "99") stringgrid_onheaderclick#(grid#, "OnHeaderClick") form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
CSV Import/Export
function OnExport(sender#) stringgrid_exportcsv(grid#, "contacts.csv", ",", 1) println "Exported to contacts.csv" endfunction function OnImport(sender#) stringgrid_importcsv(grid#, "contacts.csv", ",", 1) println "Imported from contacts.csv" endfunction function OnToString(sender#) local csv$ csv$ = stringgrid_tocsv$(grid#, ",", 1) println csv$ endfunction let frm# = form#("CSV Demo", 600, 400) form_position#(frm#, 4) let grid# = stringgrid#(frm#, 10, 50, 580, 300) stringgrid_editing#(grid#, 1) stringgrid_addcolumn#(grid#, "Name", 0, 150) stringgrid_addcolumn#(grid#, "Email", 0, 200) stringgrid_addcolumn#(grid#, "Phone", 0, 150) let btnExport# = button#(frm#, "Export CSV", 10, 10, 100, 30) let btnImport# = button#(frm#, "Import CSV", 120, 10, 100, 30) let btnToStr# = button#(frm#, "To String", 230, 10, 100, 30) button_onclick#(btnExport#, "OnExport") button_onclick#(btnImport#, "OnImport") button_onclick#(btnToStr#, "OnToString") form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Task List (Checkbox + Progress)
let COL_CHECK = 1 let COL_STRING = 0 let COL_PROGRESS = 7 function OnCellClick(sender#, col, row) local checked if col = 0 then checked = stringgrid_cellcheck(sender#, col, row) stringgrid_cellcheck#(sender#, col, row, 1 - checked) if checked = 0 then stringgrid_cellprogress#(sender#, 2, row, 100) endif endif endfunction let frm# = form#("Task List", 500, 350) form_position#(frm#, 4) let grid# = stringgrid#(frm#, 10, 10, 480, 300) stringgrid_addcolumn#(grid#, "Done", COL_CHECK, 50) stringgrid_addcolumn#(grid#, "Task", COL_STRING, 200) stringgrid_addcolumn#(grid#, "Progress", COL_PROGRESS, 120) stringgrid_rowcount#(grid#, 4) stringgrid_cell#(grid#, 1, 0, "Design UI") stringgrid_cellprogress#(grid#, 2, 0, 100) stringgrid_cellcheck#(grid#, 0, 0, 1) stringgrid_cell#(grid#, 1, 1, "Implement backend") stringgrid_cellprogress#(grid#, 2, 1, 75) stringgrid_cell#(grid#, 1, 2, "Write tests") stringgrid_cellprogress#(grid#, 2, 2, 30) stringgrid_cell#(grid#, 1, 3, "Deploy") stringgrid_cellprogress#(grid#, 2, 3, 0) stringgrid_oncellclick#(grid#, "OnCellClick") form_show(frm#) while form_visible(frm#) = 1 processmessages() end while
Best Practices
| Practice | Why |
|---|---|
| Define column type constants | let COL_STRING = 0 is far more readable than bare numbers |
| Add columns before rows | Set up the column structure, then call rowcount# |
| Right-align numeric columns | stringgrid_columnalign#(grid#, col, 2) for numbers, prices, scores |
Use stringgrid_sortnum for numbers | Text sort orders “9” after “10”; numeric sort does not |
Handle OnEditingDone | Validate data and update dependent cells after the user finishes editing |
Use OnHeaderClick for sorting | Standard UX pattern: click header to sort ascending, click again to toggle |
Enable altcolors for readability | Zebra stripes help users track rows visually in large grids |
Use scrolltorow after programmatic selection | Ensures the selected row is visible after setting row# |
| Use CSV functions for data exchange | tocsv$ for in-memory processing, exportcsv for file output |
Quick Reference
| Function | Signature | Description |
|---|---|---|
stringgrid_error / errormsg$ / strerror$ / clearerror | various | Error handling (4) |
stringgrid#(parent#[, x, y, w, h]) | various | Create (2 overloads) |
stringgrid_free(grid#) | stringgrid_free@# | Destroy |
stringgrid_rowcount / colcount | various | Row & column count (3) |
stringgrid_addcolumn# / deletecolumn / clearcolumns / column# | various | Column management (4) |
stringgrid_columnheader / width / visible / readonly / type / align | various | Column properties (11) |
stringgrid_cell / cellcheck / cellnum / cellprogress | various | Cell access (8) |
stringgrid_rowheight / insertrow / deleterow / moverow / swaprows / clearrow / copyrow / clearrows | various | Row operations (9) |
stringgrid_sort / sortnum | various | Sorting (2) |
stringgrid_copy / copysel / paste / copycell / pastecell | various | Clipboard (5) |
stringgrid_exportcsv / importcsv / tocsv$ / fromcsv | various | CSV import/export (4) |
stringgrid_col / row / selectcell# | various | Selection (5) |
stringgrid_showhdr / editing / altcolors / colresize / rowselect | various | Grid options (10) |
stringgrid_popupadd / popupclear / popupcount | various | Popup columns (3) |
stringgrid_x/y/width/height / bounds# / align | various | Position & size (12) |
stringgrid_visible / enabled / opacity / focus / isfocused / scrolltorow | various | Visibility, focus & scrolling (9) |
stringgrid_tag / parent# | various | Tag & parent (4) |
stringgrid_oncellclick/oncelldblclick/onselectcell/onselchanged/oneditingdone/onheaderclick/onclick/onresize | various | Events set+get (17) |
stringgrid_clearcallbacks# | stringgrid_clearcallbacks#@# | Disconnect all events |
112 functions. Part of the Plan9Basic GUI library system.