Grid widget
-----------

By far the most complex widget is the grid widget which is basically a table to
organize widgets.

Grid widget distributes the space evenly, i.e. all cells in a given row have
the same height as well as all cells in a given column have the same width. The
grid can have border around it and padding between cells. The border and
padding consists of a constant part called padd and resizable part called fill.
The constant padding is accounted for in the grid widget minimal size, while
the resizable fill is accounted for when leftover space is being distributed.

TIP: See link:widget_hbox_vbox.html[Hbox and Vbox] for one dimensional
     variants.

.Grid widget constructor
[source,c]
-------------------------------------------------------------------------------
enum gp_widget_grid_flags {
        /** Draw a frame around the grid */
        GP_WIDGET_GRID_FRAME = 0x01,
        /** Make the cells uniform i.e. same size */
        GP_WIDGET_GRID_UNIFORM = 0x02,
};

gp_widget *gp_widget_grid_new(unsigned int cols, unsigned int rows, int flags);
-------------------------------------------------------------------------------

Creates a new grid widget, both the `cols` and `rows` could be 0 as the grid
can be resized later.

The flags argument can be passed a bitwise or of the `enum
gp_widget_grid_flags`.

Child widget manipulation
~~~~~~~~~~~~~~~~~~~~~~~~~

[source,c]
-------------------------------------------------------------------------------
gp_widget *gp_widget_grid_put(gp_widget *self,
                              unsigned int col, unsigned int row,
                              gp_widget *child);
-------------------------------------------------------------------------------

Inserts a child widget at specified column and row into the grid and returns
previous child occupying the slot. Passing a NULL `child` pointer makes the
call equivalent to the `gp_widget_grid_rem()`.

[source,c]
-------------------------------------------------------------------------------
gp_widget *gp_widget_grid_get(gp_widget *self, unsigned int col, unsigned int row);
-------------------------------------------------------------------------------

Returns a pointer to a child occupying slot at the column and row. If slot is
empty NULL is returned.

[source,c]
-------------------------------------------------------------------------------
gp_widget *gp_widget_grid_rem(gp_widget *self, unsigned int col, unsigned int row);
-------------------------------------------------------------------------------

Removes and returns a pointer to a child widget at the column and row.

[source,c]
-------------------------------------------------------------------------------
void gp_widget_grid_del(gp_widget *self, unsigned int col, unsigned int row);
-------------------------------------------------------------------------------

Removes widget from the slot at the column and row and frees it with
link:widgets_free.html[`gp_widget_free()`].

Row manipulation
~~~~~~~~~~~~~~~~

.Inserting rows
[source,c]
-------------------------------------------------------------------------------
void gp_widget_grid_rows_ins(gp_widget *self, unsigned int row, unsigned int rows);

void gp_widget_grid_row_ins(gp_widget *self, unsigned int row);
-------------------------------------------------------------------------------

These two functions insert empty row(s) at a given offset to the grid.

Row indexes start at 0 and the last valid row index is `self->grid->rows - 1`.

.Appending rows
[source,c]
-------------------------------------------------------------------------------
unsigned int gp_widget_grid_rows_append(gp_widget *self, unsigned int rows);

unsigned int gp_widget_grid_row_append(gp_widget *self);
-------------------------------------------------------------------------------

These two functions append empty row(s) at the bottom of the grid and return
an index to the first appended row.

.Prepending rows
[source,c]
-------------------------------------------------------------------------------
void gp_widget_grid_rows_prepend(gp_widget *self, unsigned int rows);

void gp_widget_grid_row_prepend(gp_widget *self);
-------------------------------------------------------------------------------

These two functions prepend empty row(s) at the top of the grid.

.Removing rows
[source,c]
-------------------------------------------------------------------------------
void gp_widget_grid_rows_del(gp_widget *self, unsigned int row, unsigned int rows);

void gp_widget_grid_row_del(gp_widget *self, unsigned int row);
-------------------------------------------------------------------------------

These two functions delete row(s) at given offset from the grid. All widgets
in the deleted rows are freed recursively with
link:widgets_free.html[`gp_widget_free()`].

Row indexes start at 0 and the last valid row index is `self->grid->rows - 1`.

Column manipulation
~~~~~~~~~~~~~~~~~~~

.Inserting columns
[source,c]
-------------------------------------------------------------------------------
void gp_widget_grid_cols_ins(gp_widget *self, unsigned int col, unsigned int cols);

void gp_widget_grid_col_ins(gp_widget *self, unsigned int col);
-------------------------------------------------------------------------------

These two functions insert empty column(s) at a given offset to the grid.

Column indexes start at 0 and the last valid column index is `self->grid->cols - 1`.

.Appending columns
[source,c]
-------------------------------------------------------------------------------
unsigned int gp_widget_grid_cols_append(gp_widget *self, unsigned int cols);

unsigned int gp_widget_grid_col_append(gp_widget *self);
-------------------------------------------------------------------------------

These two functions append empty column(s) at the right side of the grid and
return an index to the first appended column.

.Prepending columns
[source,c]
-------------------------------------------------------------------------------
void gp_widget_grid_cols_prepend(gp_widget *self, unsigned int cols);

void gp_widget_grid_col_prepend(gp_widget *self);
-------------------------------------------------------------------------------

These two functions prepend empty column(s) at the left side of the grid.

.Removing columns
[source,c]
-------------------------------------------------------------------------------
void gp_widget_grid_cols_del(gp_widget *self, unsigned int col, unsigned int cols);

void gp_widget_grid_col_del(gp_widget *self, unsigned int col);
-------------------------------------------------------------------------------

These two functions delete column(s) at given offset from the grid. All widgets
in the deleted columns are freed recursively with
link:widgets_free.html[`gp_widget_free()`].

Column indexes start at 0 and the last valid column index is `self->grid->cols - 1`.

Border padding and fill
~~~~~~~~~~~~~~~~~~~~~~~

[source,c]
-------------------------------------------------------------------------------
enum gp_widget_border {
	GP_WIDGET_BORDER_NONE = 0x00,

        GP_WIDGET_BORDER_LEFT = 0x01,
        GP_WIDGET_BORDER_RIGHT = 0x2,
        GP_WIDGET_BORDER_TOP = 0x10,
        GP_WIDGET_BORDER_BOTTOM = 0x20,

        GP_WIDGET_BORDER_HORIZ = GP_WIDGET_BORDER_TOP | GP_WIDGET_BORDER_BOTTOM,
        GP_WIDGET_BORDER_VERT = GP_WIDGET_BORDER_LEFT | GP_WIDGET_BORDER_RIGHT,

        GP_WIDGET_BORDER_ALL = GP_WIDGET_BORDER_HORIZ | GP_WIDGET_BORDER_VERT,

        /* clears all borders missing from the bitflags */
        GP_WIDGET_BORDER_CLEAR = 0x80
};

void gp_widget_grid_border_set(gp_widget *self, enum gp_widget_border border,
                               int padd, int fill);

void gp_widget_grid_no_border(gp_widget *self);
-------------------------------------------------------------------------------

Sets a grid border padding and fill coeficients, most common usage is to make
the grid borderless with passing 0 for both `padd` and `fill`.

The call `gp_widget_grid_no_boder(self)` is shortcut for
`gp_widget_grid_border_set(self, GP_WIDGET_BORDER_ALL, 0, 0)`.

If `padd` is -1 no changes to border padding are done.

If `fill` is -1 no changes to border fills are done.

See the detailed description below on padding and fill.

Cell row and column fill
~~~~~~~~~~~~~~~~~~~~~~~~

[source,c]
-------------------------------------------------------------------------------
void gp_widget_grid_col_fill_set(gp_widget *self,
                                 unsigned int col, uint8_t fill);

void gp_widget_grid_row_fill_set(gp_widget *self,
                                 unsigned int row, uint8_t fill);
-------------------------------------------------------------------------------

Sets cell column and row fill coeficient. When fill is set to 0 the respective
column or row is set to its minimal horizontal or vertical size. When non-zero
the coeficient describes how aggresively is leftover space allocated, the
higher coeficient the more space is allocated. When grid is created all
columnt and row fill coeficients are set to 1.

Grid JSON Example
~~~~~~~~~~~~~~~~~

image:grid.png[Grid widget]

[source,json]
------------------------------------------------------------------
include::../demos/widgets/test_layouts/test_align.json[]
------------------------------------------------------------------

TIP: Pass '-d layout' on application commandline to highlight grid columns and
     rows.

.Grid JSON attributes
[cols=",,,3",options="header"]
|==============================================================================
| Attribute |  Type  | Default  | Description
|  +cols+   |  uint  |   +1+    | Number of columns
|  +rows+   |  uint  |   +1+    | Number of rows
|  +border+ | string | +all 1+  | See below
|  +cpad+   | string | all +1+  | Horizontal border and padding size multiples.
|  +rpad+   | string | all +1+  | Vertical border and padding size multiples.
|  +cpadf+  | string | all +0+  | Horizontal border and padding fill coeficients.
|  +rpadf+  | string | all +0+  | Vertical border and padding fill coeficients.
|  +cfill+  | string | all +1+  | Horizontal cell fill coeficients.
|  +rfill+  | string | all +1+  | Vertical cell fill coeficients.
|   +pad+   |  uint  |   +1+    | Horizontal and vertical padding size multiples.
| +frame+   |  bool  |  false   | Draws frame around grid.
| +uniform+ |  bool  |  false   | The minimal sizes are distributed uniformly.
| +widgets+ |  json  |          | +cols+ * +rows+ widgets.
|==============================================================================

The +pad+ attribute is set before the +cpad+ and +rpad+.

Border
~~~~~~

The boder can be one of 'none', 'all', 'horiz', 'vert', 'top', 'bottom',
'left', 'right' and can be combined with 'border=int'.

.Examples
|==============================================================================
| "border": "none" | Sets all border padds to 0
| "border": 4      | Sets all border padds to 4
| "border": "vert" | Sets vertical border to 1 and clears horizontal border
| "border": top, "border": 4 | Sets top border to 4 clears rest of the borders
|==============================================================================

Padding and fill string
~~~~~~~~~~~~~~~~~~~~~~~

* Numbers are divided with comma (,)
* Repetition can be done with number and asterisk (*)

For example "1, 1, 1" is the same as "3 * 1"
