Button matrix (lv_btnmatrix)
============================

Overview
********

The Button Matrix object is a lightweight way to display multiple
buttons in rows and columns. Lightweight because the buttons are not
actually created but just virtually drawn on the fly. This way, one
button use only eight extra bytes of memory instead of the ~100-150
bytes a normal `Button </widgets/btn>`__ object plus the 100 or so bytes
for the `Label </widgets/label>`__ object.

The Button matrix is added to the default group (if one is set). Besides
the Button matrix is an editable object to allow selecting and clicking
the buttons with encoder navigation too.

Parts and Styles
****************

-  :cpp:enumerator:`LV_PART_MAIN` The background of the button matrix, uses the
   typical background style properties. ``pad_row`` and ``pad_column``
   sets the space between the buttons.
-  :cpp:enumerator:`LV_PART_ITEMS` The buttons all use the text and typical background
   style properties except translations and transformations.

Usage
*****

Button's text
-------------

There is a text on each button. To specify them a descriptor string
array, called *map*, needs to be used. The map can be set with
:cpp:expr:`lv_btnmatrix_set_map(btnm, my_map)`. The declaration of a map should
look like ``const char * map[] = {"btn1", "btn2", "btn3", NULL}``. Note
that the last element has to be either ``NULL`` or an empty string
(``""``)!

Use ``"\n"`` in the map to insert a **line break**. E.g.
``{"btn1", "btn2", "\n", "btn3", ""}``. Each line's buttons have their
width calculated automatically. So in the example the first row will
have 2 buttons each with 50% width and a second row with 1 button having
100% width.

Control buttons
---------------

The buttons' width can be set relative to the other button in the same
row with :cpp:expr:`lv_btnmatrix_set_btn_width(btnm, btn_id, width)` E.g. in a
line with two buttons: *btnA, width = 1* and *btnB, width = 2*, *btnA*
will have 33 % width and *btnB* will have 66 % width. It's similar to
how the
```flex-grow`` <https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow>`__
property works in CSS. The width must be in the [1..15] range and the
default width is 1.

In addition to the width, each button can be customized with the
following parameters:

- :cpp:enumerator:`LV_BTNMATRIX_CTRL_HIDDEN`: Makes a button hidden (hidden buttons still take up space in the layout, they are just not visible or clickable)
- :cpp:enumerator:`LV_BTNMATRIX_CTRL_NO_REPEAT`: Disable repeating when the button is long pressed
- :cpp:enumerator:`LV_BTNMATRIX_CTRL_DISABLED`: Makes a button disabled Like :cpp:enumerator:`LV_STATE_DISABLED` on normal objects
- :cpp:enumerator:`LV_BTNMATRIX_CTRL_CHECKABLE`: Enable toggling of a button. I.e. :cpp:enumerator:`LV_STATE_CHECHED` will be added/removed as the button is clicked
- :cpp:enumerator:`LV_BTNMATRIX_CTRL_CHECKED`: Make the button checked. It will use the :cpp:enumerator:`LV_STATE_CHECHKED` styles.
- :cpp:enumerator:`LV_BTNMATRIX_CTRL_CLICK_TRIG`: Enabled: send LV_EVENT_VALUE_CHANGE on CLICK, Disabled: send :cpp:enumerator:`LV_EVENT_VALUE_CHANGE` on PRESS
- :cpp:enumerator:`LV_BTNMATRIX_CTRL_POPOVER`: Show the button label in a popover when pressing this key
- :cpp:enumerator:`LV_BTNMATRIX_CTRL_RECOLOR`: Enable recoloring of button texts with ``#``. E.g. ``"It's #ff0000 red#"``
- :cpp:enumerator:`LV_BTNMATRIX_CTRL_CUSTOM_1`: Custom free to use flag
- :cpp:enumerator:`LV_BTNMATRIX_CTRL_CUSTOM_2`: Custom free to use flag

By default, all flags are disabled.

To set or clear a button's control attribute, use
``lv_btnmatrix_set_btn_ctrl(btnm, btn_id, LV_BTNM_CTRL_...)`` and
``lv_btnmatrix_clear_btn_ctrl(btnm, btn_id, LV_BTNMATRIX_CTRL_...)``
respectively. More ``LV_BTNM_CTRL_...`` values can be OR-ed

To set/clear the same control attribute for all buttons of a button
matrix, use ``lv_btnmatrix_set_btn_ctrl_all(btnm, LV_BTNM_CTRL_...)``
and ``lv_btnmatrix_clear_btn_ctrl_all(btnm, LV_BTNMATRIX_CTRL_...)``.

The set a control map for a button matrix (similarly to the map for the
text), use ``lv_btnmatrix_set_ctrl_map(btnm, ctrl_map)``. An element of
``ctrl_map`` should look like
``ctrl_map[0] = width | LV_BTNM_CTRL_NO_REPEAT |  LV_BTNM_CTRL_CHECHKABLE``.
The number of elements should be equal to the number of buttons
(excluding newlines characters).

One check
---------

The "One check" feature can be enabled with
:cpp:expr:`lv_btnmatrix_set_one_checked(btnm, true)` to allow only one button to
be checked at a time.

Events
******

-  :cpp:enumerator:`LV_EVENT_VALUE_CHANGED`: Sent when a button is pressed/released or
   repeated after long press. The event parameter is set to the ID of
   the pressed/released button.
-  :cpp:enumerator:`LV_EVENT_DRAW_PART_BEGIN` and :cpp:enumerator:`LV_EVENT_DRAW_PART_END` are sent
   for the following types:

   -  :cpp:enumerator:`LV_BTNMATRIX_DRAW_PART_BTN` The individual buttons.

      -  ``part``: :cpp:enumerator:`LV_PART_ITEMS`
      -  ``id``:index of the button being drawn
      -  ``draw_area``: the area of the button
      -  ``rect_dsc``

See the events of the `Base object </widgets/obj>`__ too.

:cpp:expr:`lv_btnmatrix_get_selected_btn(btnm)` returns the index of the most
recently released or focused button or :cpp:enumerator:`LV_BTNMATRIX_BTN_NONE` if no
such button.

:cpp:expr:`lv_btnmatrix_get_btn_text(btnm, btn_id)` returns a pointer to the
text of ``btn_id``\ th button.

Learn more about :ref:`events`.

Keys
****

-  ``LV_KEY_RIGHT/UP/LEFT/RIGHT`` To navigate among the buttons to
   select one
-  :cpp:enumerator:`LV_KEY_ENTER` To press/release the selected button

Note that long pressing the button matrix with an encoder can mean to
enter/leave edit mode and simply long pressing a button to make it
repeat as well. To avoid this contradiction it's suggested to add
:cpp:expr:`lv_btnmatrix_set_btn_ctrl_all(btnm, LV_BTNMATRIX_CTRL_CLICK_TRIG | LV_BTNMATRIX_CTRL_NO_REPEAT)`
to the button matrix if used with encoder. This way, the pressed button
repeat feature is disabled and on leaving edit mode the selected button
won't be activated.

Learn more about :ref:`indev_keys`.

Example
*******

.. include:: ../examples/widgets/btnmatrix/index.rst

API
***
