iced_rizzen 0.14.0

Extra widgets for official releases of iced GUI library.
Documentation
= `CellGrid` widget
Rizzen Yazston
:iced-git: https://github.com/iced-rs/iced
:iced: pass:q[*iced*]
:iced_core: pass:q[*iced_core*]
:iced_runtime: pass:q[*iced_runtime*]
:iced_widget: pass:q[*iced_widget*]

== Description

The `CellGrid` widget is a scrollable grid layout container widget consisting of a grid of columns and rows of specified sizes containing any widget (that is converted to `Element`). Each column has a label cell that is located at the top of the column, and always remains visible while the content cells are scrolled. These column labels row have a height range, which auto adjusts the row height, though height is resticted to the provided range. Similar rows also has row label cell.

The columns' and rows' size are resizable, by dragging the one edge of a label cell. Each column and row has a specified size range, which the widget will enforce. The resizing of a column or row can be done either live (continuously redraws the widget), or with a resizing preview guide line, which can be either solid or stippled. The color of the guide line can be specified to be contrast to the majority of the content.

The widget does supports hidden columns and rows by specifying the hidden attribute in the column and row properties.

All the cells (including the labels and corner cell) can be set as active or not. Inactive cells prevents any interaction with the cell's contents (the widget within the cell). This can be used as a form of cell protection from change.

The widget also supports optional grid lines for content widgets that do not have their own borders. These grid lines can be colored to be contrast to the majority of the content. The grid lines can be content only, or entire widget.

The content grid is scrollable in both directions, where the scrollbars can be always displayed (default) or be smart scrollables (only appearing when content is larger than the widget's viewport). The scrollbars can be non-overlaying (default) or overlaying the content. The scrollbar's length can be either the widget width (horizontal, height for vertical) or excludes the labels. The scrollbars has a few options, see `Scrollbar` for more details. In addition the scrollbar's rail and scroller can have various styles, independent of the theme default style. Initial scroll offset can be provided for both directions.

The widget supports the concept of frozen columns (left side) and rows (top side), as is found in spreadsheet like applications.

Page break indicator lines is another feature of the `CellGrid`, an useful feature when the application supports printing the content to printer or PDF. This supports hidden columns and rows, ignoring these as they would not be printed.

The final feature is that the widget does not require the entire content to be available to the widget at once. The widget supports partial loaded content, that is one to four portions of content is placed into the widget (depending if columns and rows are frozen), however the entire column and row properties must be loaded into the application state as the scrolling feature requires to know the total size, visible size, and scrolling size of the content. If partial content is used for the widget, ensure the `on_scroll()` is used, so that the application can determine when to load or swap out content, and update the widget with the new portions.

== Directory structure

* `cell.rs`: Contains the optional container `Cell` widget. This widget is to provide the typical styling that is done on spreadsheet cells: background fill, border colouring, and border styles.

* `cellgrid.rs`: The `CellGrid` widget.

* `content.rs`: Contains the content structs that are required by `CellGrid` widget, and optional content builder structs (these are the recommended way to build the content structs).

* `extra.rs`: Has the optional extras.

* `style.rs`: Contains the styling for `CellGrid`.

* `types.rs`: Various structs and enums.

== Components

There are a number of structs, enums, etc that are used together to produce the `CellGrid` widget.

=== Minimal components

These components are required for a functional `CellGrid` widget:

* `CellGrid`: The final step in the application's `view()` for creating the `CellGrid` widget instance.

* `ContentLayout`: This struct is placed in the application's state struct, and contains the layout information for `CellGrid` to build the layout of the widget.

* `Content`: Is created in the application's `view()`, and contains the reference to `ContentLayout` instance, the `Element`s, and cells' active indicator.

* `Vec<PropertyMinimal>`: In the application's state two vectors are required, one for the columns and another for the rows, containing the minimum properties for all the columns or the rows.

* `Vec<f32>`: In the application's state two vectors are required, for the page breaks indicator lines for horizontal and vertical directions.

=== Optional yet preferred

* `ContentLayoutBuilder`: Used in the application's state "new" function to create the `ContentLayout` struct.

* `ContentBuilder`: Used in the application's `view()` to create the `Content` struct.

=== Optional extra

* `Cell`: Basic container widget, that provides background fill color, border width, and border color.

* `TextInputCatalog`: Extends the `Catalog` of the `TextInput` widget, with a no border style.

* `TextEditorCatalog`: Extends the `Catalog` of the `TextEditor` widget, with a no border style.

* Various page breaks determination functions, using different algorithms.

== Usage

As there is no usage example provided in the widget's documentation, the process to use the `CellGrid` widget is described here.

. In the application's "new" function:

. . Create the two vectors `Vec<PropertyMinimal>` for the column and row properties respectively, and stores in the application's state struct.

. . Create two vectors `Vec<f32>` for the vertical and horizontal page breaks, and stores in the application's state struct. These can be created using any of the four page breaks determination functions are provided in the `extra.rs` file, or using your own functions, else simply create empty vectors with zero capacity when page breaks are not required.

. . Create the `ContentLayoutBuilder` struct, and optionally configure using the struct's functions.

. . Finally call struct's function `build()` with references to the four vectors in the application's state struct, to create the `ContentLayout` struct and store it in the application's state struct.

. In the application's `view()` function (creation of the widgets):

. . Create the `ContentBuilder` struct with reference to the `ContentLayout` struct in the application's state struct.

. . Optional provide a widget for the corner cell between the column labels row and the row labels column, to change it from the default empty space.

. . Use the four functions: `push_left_column(label)` (frozen portion), `push_right_column(label)` (scrolling portion), `push_up_row(label)` (frozen portion), and `push_up_row(label)` (scrolling portion) to add the label widgets. All labels cells are considered active, thus events may pass through to the cell's widget.

. . Use the four functions: `push_up_left_data(element, active)` (no scrolling), `push_up_right_data(element, active)` (horizontal scrolling), `push_down_left_data(element, active)` (vertical scrolling), and `push_down_right_data(element, active)` (scrolling) to add the content widgets and their active state.

. . Finally call struct's function `into()` to create the `Content` struct.

. . Create the `CellGrid` widget struct with the `Content` struct.

. . Optionally configure using the struct's functions.

. . Finally call struct's function `into()` to create the `Element` struct.

=== Events

* If wanting resizing to take place, ensure to use `CellGrid::on_resized()` to specify a message in order to get the final size.

* If wanting to have live resizing, additionally ensure to use `CellGrid::on_resizing()` to specify a message in order to get the current size.

* When using partial loaded content for the widget, ensure to use `CellGrid::on_scroll()` to specify a message in order to get the current scrolling offsets, and in application's `update()` check if the offsets are within the visible bounds of the portion, and if not the load require content and rebuild the `CellGrid` widget.

== Future developments

* Change the logic of the stippled resize guide line to use `Canvas` widget. Reason being, that the computed canvas state can be saved, and reused as needed.

* Improve the styling options of the scrollbar rail and scroller by using `Canvas` widget.

* Increase the border styles of `Cell` widget by using `Canvas` widget, such as stippled lines, and double lines.

* Have option to not to display cells partially when scrolling, similar to spreadsheet applications.