Skip to content

GUI design choices

Jean-David Moisan edited this page Oct 22, 2019 · 5 revisions

GUI design choices

Component

A component is the smallest unit of an interface. A button is a component. A label is a component. A panel is also a component.

A component holds it's:

  • position
  • width, height
  • preferred width and height. Those might or might not be honored by your layout manager.
  • parent (e.g: the panel that contains this component)
    • The parent is in charge of establishing the hierarchy with it's children.
  • bounding rectangle (position.X, position.Y, width, height)
  • clipping rectangle (This is used to define which part of the component is visible on screen.)
  • hovered state (How this is defined is up to you, but usually if the mouse is over a component's visible area, it is hovered.)
  • is focusable (A component is aware of whether or not it can be focusable, along with whether or not it is currently focused. Normally, a component that doesn't offer any interaction should not be focusable. (e.g: a label))
    • focus state (Normally, there is only a single component that can be in focus at a time in a component hierarchy.)
  1. It has ways to travel to it's neighbors.
  2. It has ways to sink down the chain. e.g: In a hierarchy where a component (1) contains another component (2), we can travel from (1) to (2).
  3. A component also has a way to grab the focus in a component hierarchy. (GrabFocus)

Those first two points are primarily used to facilitate GamePad handling.

A component holds it's logic code. There are 3 update phases:

  1. UpdateSetup(): This is the step where layout managers can update the component's positions and sizes.
  2. UpdateInput(): called to process mouse, keyboard, gamepad inputs. Separating this step gives the freedom of freezing inputs on the UI while keeping the UI responsive during animations. To be more precise, if you want to have both an in-game UI and a menu that could be drawn on top, it's nice to be able to disable inputs on the in-game UI and allow interaction on the menu.
  3. Update(): The final step in the updating process. This is where everything that doesn't rely on inputs gets updated.

A component is also in charge of drawing itself. The component is given a spritebatch. The component must never draw outside it's clipping rectangle.

Components are scriptable. It is possible to add conditions associated with actions. When a condition evaluates to true, the action is executed. You can add any amount of [conditions / actions] to components.

To explain this last point better. It is possible to create a button component. Add a first condition that triggers on a left mouse click. Then add a second condition that triggers on a right mouse click. Then add a third condition that triggers on a middle mouse click. You now have a single button that can be interacted with in 3 separate ways, and all of them can have a separate action. This makes it possible to create complex UIs with very simple components.

Panel

A panel is a container that can hold multiple components.

A panel holds it's:

  • children
  • layout manager
  • offset
  • size

The offset and size are used to define a panel canvas. The panel's canvas is meant to stretch in order to fully contain all the children in the panel. In practice, a panel that is smaller than it's canvas should be scrollable.

A panel is in charge of updating all of it's children, along with drawing them. During the UpdateSetup() phase, the panel is in charge of calling the layout manager to give each children their size and position.

Layout

A layout has for purpose to give a position and a size to the children inside a panel. The Layout also needs to give each children their clipping rectangle.

A layout holds only the panel on which it is operating on.

Clone this wiki locally