diff options
Diffstat (limited to 'BBB_GOFILES/tablemodel.go')
| -rw-r--r-- | BBB_GOFILES/tablemodel.go | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/BBB_GOFILES/tablemodel.go b/BBB_GOFILES/tablemodel.go new file mode 100644 index 0000000..b4ca7a4 --- /dev/null +++ b/BBB_GOFILES/tablemodel.go @@ -0,0 +1,243 @@ +// 24 august 2018 + +package ui + +// #include "ui.h" +// extern int doTableModelNumColumns(uiTableModelHandler *, uiTableModel *); +// extern uiTableValueType doTableModelColumnType(uiTableModelHandler *, uiTableModel *, int); +// extern int doTableModelNumRows(uiTableModelHandler *, uiTableModel *); +// extern uiTableValue *doTableModelCellValue(uiTableModelHandler *mh, uiTableModel *m, int row, int column); +// extern void doTableModelSetCellValue(uiTableModelHandler *, uiTableModel *, int, int, uiTableValue *); +// // deal with cgo being dumb +// static inline void realDoTableModelSetCellValue(uiTableModelHandler *mh, uiTableModel *m, int row, int column, const uiTableValue *value) +// { +// doTableModelSetCellValue(mh, m, row, column, (uiTableValue *) value); +// } +// // TODO why can't this be static? +// const uiTableModelHandler pkguiTableModelHandler = { +// .NumColumns = doTableModelNumColumns, +// .ColumnType = doTableModelColumnType, +// .NumRows = doTableModelNumRows, +// .CellValue = doTableModelCellValue, +// .SetCellValue = realDoTableModelSetCellValue, +// }; +import "C" + +// TableValue is a type that represents a piece of data that can come +// out of a TableModel. +type TableValue interface { + toLibui() *C.uiTableValue +} + +// TableString is a TableValue that stores a string. TableString is +// used for displaying text in a Table. +type TableString string + +func (s TableString) toLibui() *C.uiTableValue { + cs := C.CString(string(s)) + defer freestr(cs) + return C.uiNewTableValueString(cs) +} + +// TableImage is a TableValue that represents an Image. Ownership +// of the Image is not copied; you must keep it alive alongside the +// TableImage. +type TableImage struct { + I *Image +} + +func (i TableImage) toLibui() *C.uiTableValue { + return C.uiNewTableValueImage(i.I.i) +} + +// TableInt is a TableValue that stores integers. These are used for +// progressbars. Due to current limitations of libui, they also +// represent checkbox states, via TableFalse and TableTrue. +type TableInt int + +// TableFalse and TableTrue are the Boolean constants for TableInt. +const ( + TableFalse TableInt = 0 + TableTrue TableInt = 1 +) + +func (i TableInt) toLibui() *C.uiTableValue { + return C.uiNewTableValueInt(C.int(i)) +} + +// TableColor is a TableValue that represents a color. +type TableColor struct { + R float64 + G float64 + B float64 + A float64 +} + +func (c TableColor) toLibui() *C.uiTableValue { + return C.uiNewTableValueColor(C.double(c.R), C.double(c.G), C.double(c.B), C.double(c.A)) +} + +func tableValueFromLibui(value *C.uiTableValue) TableValue { + if value == nil { + return nil + } + switch C.uiTableValueGetType(value) { + case C.uiTableValueTypeString: + cs := C.uiTableValueString(value) + return TableString(C.GoString(cs)) + case C.uiTableValueTypeImage: + panic("TODO") + case C.uiTableValueTypeInt: + return TableInt(C.uiTableValueInt(value)) + case C.uiTableValueTypeColor: + panic("TODO") + } + panic("unreachable") +} + +// no need to lock these; only the GUI thread can access them +var modelhandlers = make(map[*C.uiTableModel]TableModelHandler) +var models = make(map[*C.uiTableModel]*TableModel) + +// TableModel is an object that provides the data for a Table. +// This data is returned via methods you provide in the +// TableModelHandler interface. +// +// TableModel represents data using a table, but this table does +// not map directly to Table itself. Instead, you can have data +// columns which provide instructions for how to render a given +// Table's column — for instance, one model column can be used +// to give certain rows of a Table a different background color. +// Row numbers DO match with uiTable row numbers. +// +// Once created, the number and data types of columns of a +// TableModel cannot change. +// +// Row and column numbers start at 0. A TableModel can be +// associated with more than one Table at a time. +type TableModel struct { + m *C.uiTableModel +} + +// TableModelHandler defines the methods that TableModel +// calls when it needs data. +type TableModelHandler interface { + // ColumnTypes returns a slice of value types of the data + // stored in the model columns of the TableModel. + // Each entry in the slice should ideally be a zero value for + // the TableValue type of the column in question; the number + // of elements in the slice determines the number of model + // columns in the TableModel. The returned slice must remain + // constant through the lifetime of the TableModel. This + // method is not guaranteed to be called depending on the + // system. + ColumnTypes(m *TableModel) []TableValue + + // NumRows returns the number or rows in the TableModel. + // This value must be non-negative. + NumRows(m *TableModel) int + + // CellValue returns a TableValue corresponding to the model + // cell at (row, column). The type of the returned TableValue + // must match column's value type. Under some circumstances, + // nil may be returned; refer to the various methods that add + // columns to Table for details. + CellValue(m *TableModel, row, column int) TableValue + + // SetCellValue changes the model cell value at (row, column) + // in the TableModel. Within this function, either do nothing + // to keep the current cell value or save the new cell value as + // appropriate. After SetCellValue is called, the Table will + // itself reload the table cell. Under certain conditions, the + // TableValue passed in can be nil; refer to the various + // methods that add columns to Table for details. + SetCellValue(m *TableModel, row, column int, value TableValue) +} + +//export doTableModelNumColumns +func doTableModelNumColumns(umh *C.uiTableModelHandler, um *C.uiTableModel) C.int { + mh := modelhandlers[um] + return C.int(len(mh.ColumnTypes(models[um]))) +} + +//export doTableModelColumnType +func doTableModelColumnType(umh *C.uiTableModelHandler, um *C.uiTableModel, n C.int) C.uiTableValueType { + mh := modelhandlers[um] + c := mh.ColumnTypes(models[um]) + switch c[n].(type) { + case TableString: + return C.uiTableValueTypeString + case TableImage: + return C.uiTableValueTypeImage + case TableInt: + return C.uiTableValueTypeInt + case TableColor: + return C.uiTableValueTypeColor + } + panic("unreachable") +} + +//export doTableModelNumRows +func doTableModelNumRows(umh *C.uiTableModelHandler, um *C.uiTableModel) C.int { + mh := modelhandlers[um] + return C.int(mh.NumRows(models[um])) +} + +//export doTableModelCellValue +func doTableModelCellValue(umh *C.uiTableModelHandler, um *C.uiTableModel, row, column C.int) *C.uiTableValue { + mh := modelhandlers[um] + v := mh.CellValue(models[um], int(row), int(column)) + if v == nil { + return nil + } + return v.toLibui() +} + +//export doTableModelSetCellValue +func doTableModelSetCellValue(umh *C.uiTableModelHandler, um *C.uiTableModel, row, column C.int, value *C.uiTableValue) { + mh := modelhandlers[um] + v := tableValueFromLibui(value) + mh.SetCellValue(models[um], int(row), int(column), v) +} + +// NewTableModel creates a new TableModel. +func NewTableModel(handler TableModelHandler) *TableModel { + m := &TableModel{ + m: C.uiNewTableModel(&C.pkguiTableModelHandler), + } + modelhandlers[m.m] = handler + models[m.m] = m + return m +} + +// Free frees m. It is an error to Free any models associated with a +// Table. +func (m *TableModel) Free() { + delete(models, m.m) + delete(modelhandlers, m.m) + C.uiFreeTableModel(m.m) +} + +// RowInserted tells any Tables associated with m that a new row +// has been added to m at index index. You call this method when +// the number of rows in your model has changed; after calling it, +// NumRows should returm the new row count. +func (m *TableModel) RowInserted(index int) { + C.uiTableModelRowInserted(m.m, C.int(index)) +} + +// RowChanged tells any Tables associated with m that the data in +// the row at index has changed. You do not need to call this in +// your SetCellValue handlers, but you do need to call this if your +// data changes at some other point. +func (m *TableModel) RowChanged(index int) { + C.uiTableModelRowChanged(m.m, C.int(index)) +} + +// RowDeleted tells any Tables associated with m that the row at +// index index has been deleted. You call this function when the +// number of rows in your model has changed; after calling it, +// NumRows should returm the new row count. +func (m *TableModel) RowDeleted(index int) { + C.uiTableModelRowDeleted(m.m, C.int(index)) +} |
