Skip to main content

CID and Views

CID (Column Item Display) is the layout primitive that drives most non-grid views in Race Platform. A CID layout is a tree of Section → Block → Line → Cell that the renderer walks once to produce a screen.

Why CID exists

A motorsport setup sheet, a tyre measurement form, a pit-window calculator — they all want the same thing: a dense, labelled grid of small numeric fields, grouped into logical sections, with each field driven either by a parameter value or by a math expression.

CID is the JSON description of that layout. Once you have CID, adding a new screen is editing JSON, not writing Flutter.

The tree

CID
└─ Section (e.g. "Front Suspension")
└─ Block (e.g. "Front Left Corner")
└─ Line (a horizontal row inside the block)
└─ Cell (one labelled value)

Each level can carry style overrides: title weight, background tint, column count, label position, etc. Cells can:

  • Bind directly to a parameter (Lap.parameters.BrakeTemp)
  • Compute via a math expression
  • Display a static label
  • Use a custom format string (see Format Strings)

Where CID renders

PlaceWhat CID drives
Run Sheet Setup tabWhen a Setup Definition exists, the renderer is CID (toggleable with the hand-coded form via the segmented control)
Custom Views of type cidThe whole view is a CID tree mounted at a custom path
Pit Window CalculatorSeeded as a cid custom view with 7 cells

Custom Views — four view types

A Custom View has one of four viewType values:

viewTypeWhat it rendersUse case
cidA CID tree (Section / Block / Line / Cell)Calculators, setup sheets, dense numeric dashboards
cgdA free-form layout-item tree (Border / Grid / Stack / Tab / Scroll / Expander / ItemsControl / ListView)Free-form forms or screens where CID's strict tabular shape is too rigid
single-tableA single-source table with column list, filter, sort, row-accent expression"All laps for this session by sector 1 time"
multi-session-tableA table that spans multiple sessions"All laps across the event"

The custom view also stores:

  • path — where it mounts in the router (/custom/...)
  • icon — a Material icon name; mapped to IconData by the shell
  • section — ribbon section the entry belongs to (championship / event / analysis / admin)
  • enabled — whether the shell synthesises a feature spec for it

CGD — free-form layout

CGD (Custom Generic Designer) is the free-form sibling of CID. Where CID enforces a strict Section / Block / Line / Cell shape, CGD lets you compose any of nine layout items — border, grid, stack, tab, tab-item, scroll, expander, items-control, list-view — interleaved with the same cellSpec cell leaves CID uses.

The runtime spec is a recursive CGDNode tree where each node is either:

  • { type: "layout", layoutType: "...", properties, children: [...] }
  • { type: "cell", cellSpec: { ... } }

CGD is intended for forms and dashboards that don't fit the flat-grid mental model. See the dedicated CGD Editor page for the property catalogue.

Live registration

When you save a Custom View, the shell's buildRouter watches the provider and re-runs. Within seconds, your new view shows up in the ribbon's sub-toolbar and the sidebar — no restart, no rebuild.

What you can do today

  • Author CID layouts in Admin → Custom Views (/admin/custom-views). The CID editor supports full Section → Block → Line → Cell editing with add / remove / reorder.
  • Author CGD layouts in the same screen — the editor surfaces a recursive layout-item / cell tree.
  • Author single-table custom views with column lists, filter expressions, row-accent expressions.
  • Toggle Run Sheet's Setup tab between CID and hand-coded form via the segmented control.
  • See the seeded Pit Window Calculator (/custom/pit-window- calculator) for a working CID with 3 math parameters and a few literal cells.
  • See the seeded All Laps view (/custom/all-laps) for a multi-session-table example.

What's coming

  • CGD ItemsControl / ListView data binding — the shapes render today; binding their itemsSourcePath against live scope is partially wired.
  • Cell-level expression binding to related entities — the filter expression already runs in a permissive scope but doesn't yet see joined related rows (e.g. Lap.Session.BestLapTimeMs). Joined scope is in the queue.
  • CID print / export — the renderer is screen-only today.