diff options
| author | Pietro Gagliardi <[email protected]> | 2014-08-30 23:02:02 -0400 |
|---|---|---|
| committer | Pietro Gagliardi <[email protected]> | 2014-08-30 23:02:02 -0400 |
| commit | 77bf566ebbcb62acd4d08d905d9542d6ff9b6b80 (patch) | |
| tree | eeb8e72bc3bf57f5be7f0c0af4319189ac6de838 /table.go | |
| parent | 155899c65ed32245e2ccad4197a10c77017d835b (diff) | |
...in with the new.
Diffstat (limited to 'table.go')
| -rw-r--r-- | table.go | 92 |
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 +} |
