gfx

gfx is our graphics library, built on top of HTML5 Canvas. It is structred as an indirectly built tree of views, each of which has a unique numeric ID. Views are objects:

class gfx.baseProjection(options)

The base view type.

Note that you do not use new with views. Views are just functions that construct objects. They may not necessarily construct a new object; some views are modifiers for other views.

gfx.baseProjection.anchor
gfx.baseProjection.backgroundOpacity
gfx.baseProjection.children(exprId, state)

Get the children of this view, based on the expression ID and current state.

Returns:An iterable of [ childViewId, childExprId ] tuples.
gfx.baseProjection.containsPoint(pos, offset)
gfx.baseProjection.draw(id, exprId, state, stage, offset)

Actually draw this view.

Arguments:
  • id (Number) – The ID of this view.
  • exprId (Number) – The ID of the associated expression, if any.
  • state – The current Redux/Immutable.js state.
  • stage – The containing stage.
  • offset – An object containing a position (x, y) offset to apply, a scale (sx, sy) to apply, and the current cumulative opacity (opacity) value.
gfx.baseProjection.notchOffset(id, exprId, notchId)
gfx.baseProjection.notchPos(id, exprId, notchId)
gfx.baseProjection.offset
gfx.baseProjection.opacity
gfx.baseProjection.pos
gfx.baseProjection.prepare(id, exprId, state, stage)

Perform any layout or update any state for this view. Called before drawing.

Arguments:
  • id (Number) – The ID of this view.
  • exprId (Number) – The ID of the associated expression, if any.
  • state – The current Redux/Immutable.js state.
  • stage – The containing stage.
gfx.baseProjection.scale
gfx.baseProjection.size

Allocating IDs

Use module:BaseStage.allocate(). (You’ll also see allocateInternal, but this should be considered deprecated.) Note that allocating an ID for a view does not mean it will be automatically drawn for you. Also note that this shouldn’t be used for views associated with a particular expression; use module.project() instead.

How the View Hierarchy Works

View IDs may overlap with expression IDs. In that case, the view is the root view representing that expression. However, an expression might have multiple associated views. To distinguish between these, prepare and draw are passed both the expression ID and the view ID.

To give views children views, as with something like gfx.layout.hbox(), views take a function that returns a list of children. This function is passed an expression ID and the current state, and should return a list of either child expression IDs, or pairs of [ childViewId, childExprId ]. (There is a utility function that normalizes these two cases.) This allows the children of a layout to change based on the state (e.g. so a + block can use an hbox to position its children). In case you don’t need this dynamism, there is gfx.constant().

Most of the time, you will be using JSON-defined views, and won’t have to deal with this.

This diagram might help:

Store                           Stage
==============================  =======================

ID     Expression               ID     View
--     -----------------------  --     ----------------
 0 --> { type: "number", ... }   0 --> { ... }
 1 --> { type: "number", ... }   1 --> { ... }
 2 --> { type: "binop",          2 --> { childrenFunc }
         left: 0,
         right: 1 }

childrenFunc:

for (const id of childrenFunc(2, state)) {
    console.log(id);
}
// Prints:
// 0
// 1

JSON-Defined Views

The semantics definition system includes a system for defining how expressions are displayed in JSON (well, “JSON” since we embed functions). The best reference is to look at other expressions and modify them to suit your purposes.

import projector from "./gfx/projector";
gfx.projector.projector(definition)

Given an expression definition, construct a function (stage, nodes, expr) => view that will construct a view for an expression based on the definition, given the stage and the current set of nodes.

This is your interface to the JSON-defined view system; you shouldn’t need to call any of the other projectors listed below directly. (Indeed, you shouldn’t need to use this directly, either.)

gfx.projector.defaultProjector(definition)

The default projector lays out children in a horizontal box with a rounded or hexagonal background.

gfx.projector.textProjector(definition)

The text projector creates a text view.

{
    type: "text",
    text: textDefinition,
}

textDefinition is either a string or a function. If a string, it can have substrings like {fieldName} which will be replaced with expr.get("fieldName"). If a function, it should have the signature (state, exprId) => string.

There are many more projectors, just undocumented. Look at src/gfx/projector.js.

gfx Reference

Utility Functions

gfx.constant(*projections)

Given projection IDs, returns a function that always returns those IDs.

Useful as the childrenFunc argument to a view when your children are static.

Arguments:
  • projections (*) – The view IDs. (This is a variadic function.)
gfx.distance(proj1, proj2)

Return the L2-norm distance between two views or point-like objects (i.e. the object should either have an x and y field, or have a pos field).

gfx.absolutePos(projection)

Return the canvas coordinates of the top left of this view, accounting for anchor (not the coordinates relative to its parent).

gfx.absoluteSize(projection)

Return the canvas size of this view (not the size relative to its parent).

gfx.centerPos(projection)

Return the canvas coordinates of the center of this view (accounting for anchor).

Built-In Views

class gfx.rect()
class gfx.roundedRect()
class gfx.hexaRect()
class gfx.dynamic(mapping, keyFunc, options)

Create a projection that renders based on an expression field or function.

Note that all projections must have compatible fields.

class gfx.dynamicProperty(projection, keyFunc, mappings)

Create a projection that changes values based on an expression field or function.

class gfx.text(txt, options)
class gfx.layout.expand(projection, options)
class gfx.layout.hexpand(projection)
class gfx.layout.sticky(projection, direction, options)
class gfx.layout.hbox(childrenFunc, options, baseProjection)
class gfx.layout.vbox(childrenFunc, options, baseProjection)
class gfx.layout.ratioSizer(projection, ratio, percentage)
class gfx.layout.ratioPlacer(projection, x, y)
class gfx.shapes.circle(options)
class gfx.shapes.rectangle(options)
class gfx.shapes.star(options)
class gfx.shapes.triangle(options)
class gfx.sprite(options)
class gfx.patch3(childFunc, options)
class gfx.exprify(projection)
class gfx.ui.button(stage, label, options)
class gfx.ui.imageButton(images, options)
gfx.viewport.IS_PHONE
gfx.viewport.IS_TABLET
gfx.viewport.IS_MOBILE