summaryrefslogtreecommitdiff
path: root/table.go
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-08-30 23:02:02 -0400
committerPietro Gagliardi <[email protected]>2014-08-30 23:02:02 -0400
commit77bf566ebbcb62acd4d08d905d9542d6ff9b6b80 (patch)
treeeeb8e72bc3bf57f5be7f0c0af4319189ac6de838 /table.go
parent155899c65ed32245e2ccad4197a10c77017d835b (diff)
...in with the new.
Diffstat (limited to 'table.go')
-rw-r--r--table.go92
1 files changed, 92 insertions, 0 deletions
diff --git a/table.go b/table.go
new file mode 100644
index 0000000..846378d
--- /dev/null
+++ b/table.go
@@ -0,0 +1,92 @@
+// 28 july 2014
+
+package ui
+
+import (
+ "fmt"
+ "reflect"
+ "sync"
+)
+
+// Table is a Control that displays a list of like-structured data in a grid where each row represents an item and each column represents a bit of data.
+// Tables store and render a slice of struct values.
+// Each field of the struct of type ImageIndex is rendered as an icon from the Table's ImageList.
+// Each field whose type is bool or equivalent to bool is rendered as a checkbox.
+// All other fields are rendered as strings formatted with package fmt's %v format specifier.
+//
+// Tables are read-only by default, except for checkboxes, which are user-settable.
+//
+// Tables have headers on top of all columns.
+// Currently the name of the header is the same as the name of the field.
+//
+// Tables maintain their own storage behind a sync.RWMutex-compatible sync.Locker; use Table.Lock()/Table.Unlock() to make changes and Table.RLock()/Table.RUnlock() to merely read values.
+type Table interface {
+ Control
+
+ // Lock and Unlock lock and unlock Data for reading or writing.
+ // RLock and RUnlock lock and unlock Data for reading only.
+ // These methods have identical semantics to the analogous methods of sync.RWMutex.
+ // In addition, Unlock() will request an update of the Table to account for whatever was changed.
+ Lock()
+ Unlock()
+ RLock()
+ RUnlock()
+
+ // Data returns the internal data.
+ // The returned value will contain an object of type pointer to slice of some structure; use a type assertion to get the properly typed object out.
+ // Do not call this outside a Lock()..Unlock() or RLock()..RUnlock() pair.
+ Data() interface{}
+
+ // LoadImageList loads the given ImageList into the Table.
+ // This function copies; changes to the ImageList made later will not be reflected by the Table.
+ LoadImageList(imagelist ImageList)
+
+ // Selected and Select get and set the currently selected item in the Table.
+ // Selected returns -1 if no item is selected.
+ // Pass -1 to Select to deselect all items.
+ Selected() int
+ Select(index int)
+
+ // OnSelected is an event that gets triggered after the selection in the Table changes in whatever way (item selected or item deselected).
+ OnSelected(func())
+}
+
+type tablebase struct {
+ lock sync.RWMutex
+ data interface{}
+}
+
+// NewTable creates a new Table.
+// Currently, the argument must be a reflect.Type representing the structure that each item in the Table will hold, and the Table will be initially empty.
+// This will change in the future.
+func NewTable(ty reflect.Type) Table {
+ if ty.Kind() != reflect.Struct {
+ panic(fmt.Errorf("unknown or unsupported type %v given to NewTable()", ty))
+ }
+ b := new(tablebase)
+ // we want a pointer to a slice
+ b.data = reflect.New(reflect.SliceOf(ty)).Interface()
+ return finishNewTable(b, ty)
+}
+
+func (b *tablebase) Lock() {
+ b.lock.Lock()
+}
+
+// Unlock() is defined on each backend implementation of Table
+// they should all call this, however
+func (b *tablebase) unlock() {
+ b.lock.Unlock()
+}
+
+func (b *tablebase) RLock() {
+ b.lock.RLock()
+}
+
+func (b *tablebase) RUnlock() {
+ b.lock.RUnlock()
+}
+
+func (b *tablebase) Data() interface{} {
+ return b.data
+}