Skip to content
Alexandre Bury edited this page Dec 7, 2017 · 3 revisions

The basic building block for UI layouts in Cursive is the View.

  • Some views are simple leave nodes in the tree and directly handle their representation and behaviours.
  • Some views are wrapper around another view: this is a common solution to add new behaviour to a view. While technically view groups, they often forward most control in a straightforward way.
  • Some views are meant to contain multiple children and manage them as a group: those are the Group Views we'll be talking about here.

The official group views in Cursive are currently:

  • StackView
  • LinearLayout
  • ListView

All three manage their multiple children in slightly different ways. We'll look into how they deal with the main points of managing children:

  • Event passing: when the view group receives an event, how does it select which child should receive it?
  • Layout and drawing: given some constraints for the entire group, what constraints should be passed on to the children? How should the view be located and drawn?
  • Identifying: when the group receives an identification request, it should dispatch it to its children depending on the request.
    • Find by ID: this request should be forwarded to all children until a match is found.
    • Find by path: this request should use a view-dependent path identifier to point to a specific child.

StackView

The first view most cursive users deal with, albeit often unknowingly, this views stacks its children on top of each other. This is what the cursive root uses when calling Cursive::add_layer.

  • Event passing: This view always send events to the top view. No focus selection.
  • Layout and drawing: Tach child is given as much space as the StackView itself. Children are drawn above one another.
  • Path Identifier: children are a simple list, so their ID is enough.

LinearLayout

This is currently the main way to build complex layouts. The linear layout contains a list of views and aligns them in a linear way. This view can be either vertical or horizontal.

  • Event passing: One of the views is in focus and receive events. When this view ignores a key event (Up/Down for vertical views, Left/Right for horizontal, Tab/Shift+Tab for either), the focus is moved in the given direction to the next focusable view.
  • Layout and drawing: This is a bit more complicated, and may deserve its own article. The linear layout uses a magic formula to compute sizes for each of its children, then draw them next to each other in order.
  • Path Identifier: children are a simple list, so their ID is enough.

ListView

Born of the need for a scrolling form, this view is mostly a temporary fix until a more generic view is implemented. For now, it displays a vertical list of child views, each 1-row high.

  • Event passing: Like a LinearLayout, one of the view is in focus, and ignored events from the child view are used to move the focus up/down.
  • Layout and drawing: Each view is only given a single row, and the entire width of the ListView. If the ListView height is less then the number of views, a scrollbar is added, and the ListView scrolls when focus is changed to keep the selected child visible.
  • Identifying: Find by ID should just be dispatched to all children. The path index here would be the ID of the child.

Future works

GridView

A more generic replacement for both LinearLayout and ListView is planned. It would allow better bidirectional focus move, allow to scroll any kind of children view, and save baby seals across the planet.