Table view concepts

A table view in the Syside VS Code Extension shows one model element per row. Each column shows one aspect of that element, such as its name, a value or a piece of documentation. Which elements become rows is decided the same way in every grid view (see Select view elements). The attributes a table view accepts are listed in Table view structure.

Rows, columns and cells

A column answers two questions for every row: which element the cell is about, and what to show about that element. The first is the column’s navigation chain, the second its representation, and the two are independent. Owner(baseViewElement), where baseViewElement is the row element, with ColRep::declaredName shows the name of each row’s owner. The same chain with ColRep::documentation shows the owner’s documentation instead. A column without a chain is about the row element itself. Table navigation chains explains chains in depth, and Cell representations lists every representation.

Because the two halves are separate, each can come up empty in its own way, and the cell shows which:

  • A value. The chain reached an element and the representation found something to show on it.

  • Applicable, but no value. The chain reached an element, but it holds nothing for the representation, such as an attribute declared without a value. The cell shows the column’s defaultValue. In a column that can be edited, the cell stays editable, since there is a place to write a value.

  • Not applicable. The chain never reached an element, such as Subject on a part. The cell shows the column’s notApplicableValue and cannot be edited, since there is nothing to write to.

  • Truncated. A First step found more than one element. The cell shows the first with a warning and cannot be edited, since an edit could land on the wrong one.

The difference between the middle two is what lets a table tell “this requirement has no priority yet” apart from “this row is not a requirement”.

Rows that fan out

Most columns show one cell per row. A column can instead fan a row out into one row for each element its chain finds, such as one per port of each part, while the other columns keep one cell per row, merged across these fanned-out rows. This is a fan-out, written with a Fan step.

A fan-out changes the shape of the whole table rather than one column, so it is declared once at view level, as a named navigation called an anchor. Columns that reference the same anchor share its fanned-out rows, so each describes one port across all of them. Fanning a row out covers the rules for anchors and the shapes a table rejects, and Work with fanned-out rows how sorting, filtering and export treat fanned-out rows.

Hierarchical tables

A hierarchical table shows the same kind of rows as a flat table, arranged as the tree they sit in. Its one expose decides where the tree starts: X::** makes X the top row, and X::*::** starts one tree per member of X, with no X row. Beneath each row sit its child rows, one for each feature it declares or inherits, so the tree follows the model’s own structure.

Because a usage’s children include those of the definition typing it, a tree can be assembled from definitions that each declare only their immediate children. Each such definition can live in its own file or package, owned by the team responsible for it, and its structure appears wherever it is used. Children nested in one usage’s body, as in part powertrain : Powertrain { part engine; }, appear under that usage only.

A tree raises two issues that a flat table never has:

  • The filter prunes. In a flat table, a row that fails the filter disappears and the rows for its features stay. In a tree, a row that fails takes everything beneath it, since its children would have nowhere to hang. A filter therefore has to admit every kind of row on the path, the top row included.

  • One element can sit in several places. A feature that a definition declares appears under every usage of that definition: the cylinder of Engine sits under both e1 : Engine and e2 : Engine. It is one element, so an edit or a new requirement there would change it under both, and the table locks those rows. To change it, edit Engine, or open a separate view that exposes Engine::**. A flat table lists such an element once.

To show trees from different packages in one table, declare a definition that holds them all, as Show several trees in one table shows.

What an edit writes

An edit changes the element the cell is about: the row element for a column without a chain, and the chain’s target otherwise. A value in an Owner column is written to the owner. A cell merged across several fanned-out rows of a fan-out edits the one element behind it, once.

What the edit writes depends on where the value is declared. Take a table with a row for engine and three featureValue columns, Mass, Torque and Priority, each looking its attribute up by name:

:>> columnFeature = NamedUsage(
    baseViewElement, "…", NameType::name, UsageKind::attributeUsage
);

The model declares two of the three attributes:

part def Engine {
    attribute mass default 150;
    attribute torque = 300;
}

part def Car {
    part engine : Engine;
}

Setting Mass to 180 and Priority to 2 writes this into engine:

part engine : Engine {
    attribute :>> Engine::mass = 180;
    attribute priority = 2;
}
  • An inherited value is redefined. engine inherits mass, so the edit redefines it in engine, and Engine and its other usages keep 150. That works because Engine binds mass with default. torque is bound with =, which SysML does not let a usage override, so the Torque cell is read-only.

  • A missing attribute is created. engine has no priority, so the Priority cell starts empty but editable, and saving a value adds the attribute. In a longer chain, the attribute is added to the element the earlier steps reached. If they did not reach exactly one element, or crossed an inheritance boundary on the way, the cell is read-only.

  • A value the element declares itself is changed in place. Editing Mass again changes the 180.

  • Inherited documentation and textual bodies are never redefined. Editing them would change the base element for everything that inherits from it, so such a cell is read-only. A chain that navigates to the base on purpose, such as HeritageFirst or DefinitionsFirst, edits the base element itself, and the change shows everywhere it is inherited.

Some edits are refused whatever the cell. Elements from libraries, from files that a syside.toml include brings in, and from Sysand dependencies are read-only. A model with errors makes every view read-only (see A view shows a “Model errors” banner and cannot be edited), and a syntax error stops views opening at all. A model with only warnings stays editable.