Tabs widget
-----------

Tabs widget is a widget that switches between different layouts based on
active tab on the tab header.

.A tabs widget
image:tabs.png[Tabs widget]

Tabs attributes can be accessed as `widget->tabs`.

Tabs are indexed by an integers, first tab starts at `0` and last valid index
is `tabs_cnt - 1`.

.Tabs widget constructor
[source,c]
-------------------------------------------------------------------------------
gp_widget *gp_widget_tabs_new(unsigned int tabs_cnt, unsigned int active_tab,
                              const char *tab_labels[], int flags);
-------------------------------------------------------------------------------

Creates a tabs widget with `tabs_cnt` tabs `tab_labels[]` for the tab labels.

The `flags` parameter is currently unused and must be 0.

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

[source,c]
-------------------------------------------------------------------------------
gp_widget *gp_widget_tabs_put(gp_widget *self, unsigned int tab,
                              gp_widget *child);
-------------------------------------------------------------------------------

Inserts a `child` widget to the `tab` and returns a child previously occupying
the tab or NULL if it was empty.

Passing a NULL `child` pointer makes the call equivalent to the
`gp_widget_tabs_rem()`.

[source,c]
-------------------------------------------------------------------------------
gp_widget *gp_widget_tabs_child_get(gp_widget *self, unsigned int tab);
-------------------------------------------------------------------------------

Returns a pointer to a child widget occupying the `tab` or NULL if it's
empty.

[source,c]
-------------------------------------------------------------------------------
const char *gp_widget_tabs_label_get(gp_widget *self, unsigned int tab);

const char *gp_widget_tabs_active_label_get(gp_widget *self);
-------------------------------------------------------------------------------

Returns tab and active tab label.

[source,c]
-------------------------------------------------------------------------------
gp_widget *gp_widget_tabs_rem(gp_widget *self, unsigned int tab)
-------------------------------------------------------------------------------

Removes and returns a pointer to a child widget in `tab`. Returns NULL if tab
was empty.

[source,c]
-------------------------------------------------------------------------------
gp_widget *gp_widget_tabs_del(gp_widget *self, unsigned int tab)
-------------------------------------------------------------------------------

Remove and frees, with a link:widgets_free.html[`gp_widget_free()`], child
widget in `tab`. It's no-op if the tab was empty.

Functions to manipulate and query tabs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[source,c]
-------------------------------------------------------------------------------
unsigned int gp_widget_tabs_cnt(gp_widget *self);
-------------------------------------------------------------------------------

Returns number of tabs. The tab indexes are in range `0` and `tabs_cnt - 1`.

[source,c]
-------------------------------------------------------------------------------
unsigned int gp_widget_tabs_active_get(gp_widget *self);

gp_widget *gp_widget_tabs_active_child_get(gp_widget *self);

void gp_widget_tabs_active_set(gp_widget *self, unsigned int tab);
-------------------------------------------------------------------------------

Sets and gets the currently active tab.

[source,c]
-------------------------------------------------------------------------------
int gp_widget_tabs_tab_by_child(gp_widget *self, gp_widget *child);
-------------------------------------------------------------------------------

A lookup function to get tab index by a child widget pointer.

Function to add and remove tabs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[source,c]
-------------------------------------------------------------------------------
void gp_widget_tabs_tab_ins(gp_widget *self, unsigned int tab,
                            const char *label, gp_widget *child);
-------------------------------------------------------------------------------

Inserts a tab at a given position.

Note that indexes of tabs on the right from the given position will increase.
One of the possibilities on how to uniquely identify tabs when inserting in
the middle is by child widgets with `gp_widget_tabs_tab_by_child()`.

[source,c]
-------------------------------------------------------------------------------
unsigned int gp_widget_tabs_tab_append(gp_widget *self,
                                       const char *label, gp_widget *child);
-------------------------------------------------------------------------------

Appends a tab at the end, i.e. to be the most right tab. Returns position of
the newly insterted tab.

[source,c]
-------------------------------------------------------------------------------
unsigned int gp_widget_tabs_tab_prepend(gp_widget *self,
                                        const char *label, gp_widget *child);
-------------------------------------------------------------------------------

Prepends a tab at the begining, i.e. to be the most left tab. The tab is
inserted at position `0`.

Note that all the indexes of already existing tabs increase.

[source,c]
-------------------------------------------------------------------------------
gp_widget *gp_widget_tabs_tab_rem(gp_widget *self, unsigned int tab);

int gp_widget_tabs_tab_rem_by_child(gp_widget *self, gp_widget *child)
-------------------------------------------------------------------------------

Removes a tab at a given position and returns a pointer to the child widget.

The `by_child` variant looks up the tab by the child pointer and returns zero
on success.

[source,c]
-------------------------------------------------------------------------------
gp_widget *gp_widget_tabs_tab_del(gp_widget *self, unsigned int tab);

int gp_widget_tabs_tab_del_by_child(gp_widget *self, gp_widget *child);
-------------------------------------------------------------------------------

The `by_child` variant looks up the tab by the child pointer and returns zero
on success.

These functions remove and free a child widget with link:widgets_free.html[`gp_widget_free()`].

.Tabs JSON attributes
[cols=",,,3",options="header"]
|===================================================
| Attribute     |  Type  | Default | Description
|   +labels+    |  array |         | Array of string labels.
|   +widgets+   |  array |         | Array of child widgets.
|   +active+    |  uint  |    0    | Active tab.
|===================================================

.Tabs widget events
[cols=",3",options="header"]
|=============================================================================
| Widget event value         | Description
| GP_WIDGET_TABS_DEACTIVATED | Currently active tab is going to be deactivated
| GP_WIDGET_TABS_ACTIVATED   | A new active tab was set
|=============================================================================

The deactivation event is send before the action is done, i.e. while the old
active tab is still active and the activation event is send after the action
was done, i.e. after the active tab has changed.
