2014-07-28 16:59:50 -05:00
// 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.
2014-08-17 18:49:57 -05:00
// 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.
//
2014-07-28 16:59:50 -05:00
// 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 {
2014-07-28 19:52:32 -05:00
Control
2014-07-28 16:59:50 -05:00
// 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.
2014-07-28 17:03:59 -05:00
// In addition, Unlock() will request an update of the Table to account for whatever was changed.
2014-07-28 16:59:50 -05:00
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 { }
2014-08-16 16:37:21 -05:00
// LoadImageList loads the given ImageList into the Table.
// This function copies; changes to the ImageList made later will not be reflected by the Table.
2014-08-18 01:22:27 -05:00
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 )
2014-08-20 20:21:45 -05:00
// OnSelected is an event that gets triggered after the selection in the Table changes in whatever way (item selected or item deselected).
OnSelected ( func ( ) )
2014-07-28 16:59:50 -05:00
}
type tablebase struct {
2014-10-02 09:05:53 -05:00
lock sync . RWMutex
data interface { }
2014-07-28 16:59:50 -05:00
}
// 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 )
2014-07-28 19:52:32 -05:00
// we want a pointer to a slice
b . data = reflect . New ( reflect . SliceOf ( ty ) ) . Interface ( )
return finishNewTable ( b , ty )
2014-07-28 16:59:50 -05:00
}
func ( b * tablebase ) Lock ( ) {
b . lock . Lock ( )
}
2014-07-28 19:52:32 -05:00
// Unlock() is defined on each backend implementation of Table
// they should all call this, however
func ( b * tablebase ) unlock ( ) {
2014-07-28 16:59:50 -05:00
b . lock . Unlock ( )
}
func ( b * tablebase ) RLock ( ) {
b . lock . RLock ( )
}
func ( b * tablebase ) RUnlock ( ) {
b . lock . RUnlock ( )
}
2014-07-28 19:52:32 -05:00
func ( b * tablebase ) Data ( ) interface { } {
2014-07-28 16:59:50 -05:00
return b . data
}