Table widget
------------

Table widget is a widget that shows a table.

The table content is not stored in the widget, instead there are callbacks
that are called to get the cells content when table is being rendered.

See link:example_widgets_table.html[table widget example code].

.Table widget callbacks
[source,c]
-------------------------------------------------------------------------------
enum gp_widget_table_row_op {
        GP_TABLE_ROW_RESET,
        GP_TABLE_ROW_ADVANCE,
        GP_TABLE_ROW_TELL,
};

typedef struct gp_widget_table_col_dsc {
	/** Column human readable ID */
	const char *id;
	/** An index to map the human readable ID to */
	unsigned long idx;
	/** If sort is not set this describes if column is sortable */
	int sortable:1;
} gp_widget_table_col_dsc;

typedef struct gp_widget_table_col_ops {
	int (*seek_row)(gp_widget *self, int op, unsigned int pos);
	int (*get_cell)(gp_widget *self, gp_widget_table_cell *cell, unsigned int col_idx);
	void (*sort)(gp_widget *self, int desc, unsigned int col_idx);

	/** Optional on_event handler */
	int (*on_event)(gp_widget_event *ev);
	void *on_event_priv;

	/** NULL id terminated column map array */
	gp_widget_table_col_dsc col_map[];
} gp_widget_table_col_ops;
-------------------------------------------------------------------------------

The 'gp_widget_table_col_dsc' structure describes a column and the
'gp_widget_table_col_ops' describes all possible columns along with callbacks
to get table cells and possibly sort table by a column.

If the optional 'on_event()' handle is not NULL the widget handler is
initialized with the values from the structure when the widget is created.

What user sees on the screen is described by an array of
'gp_widget_table_header' structures which is usually loaded from a JSON
description.

.seek_row() callback ops
[options="header"]
|==============================================================================
| enum gp_widget_table_row_op | Description
| GP_TABLE_ROW_RESET
| Sets the current row to 0 i.e. the first row in the table.
| GP_TABLE_ROW_ADVANCE
| Moves the current row by the op parameter elements forward. Returns
  non-zero if resulting row is valid and zero if not.
| GP_TABLE_ROW_MAX
| Returns the number of rows in a table i.e. max_index + 1, or -1 if unknown
  at the time of the call.
|==============================================================================

Sorting
~~~~~~~

If any of the table columns is sortable the 'sortable' flag has to be set in
the corresponding column description and the 'col_ops->sort()' callback must
be implemented for the particular column.

.Table JSON attributes
[cols=",,,3",options="header"]
|==================================================================
| Attribute     |  Type  | Default | Description
|  +col_ops+    | string |         | An column ops id.
|  +header+     | array  |         | Array of table header objects.
|  +min_rows+   |  int   |         | Minimal number of table rows.
|==================================================================

.Table Header JSON attributes
[cols=",,,3",options="header"]
|=================================================================================
|  Attribute    |  Type  | Default | Description
|    +fill+     |   int  |    0    | Column fill coeficient.
|     +id+      | string |         | Column id to match in gp_widget_table_col_dsc
|    +label+    | string |         | If set it's the the column heading label.
|   +min_size+  |   int  |         | Minimal column width.
|    +order+    | string |         | If column is sortable, it can be asc or desc.
|    +tattr+    | tattr  |  bold   | Column heading label text attribute.
|=================================================================================

.Table widget events
[cols=",3",options="header"]
|===================================================
|   Widget event value    | Description
| GP_WIDGET_TABLE_TRIGGER | Emitted on pressing enter or double click.
| GP_WIDGET_TABLE_SELECT  | Emitted when table entry is selected.
|===================================================
