Skip to content

views summary

Damiano Di Vincenzo edited this page Apr 11, 2024 · 8 revisions

Intro

A view, is a set of graphical syntax and semantic behavior applied to an element in the graph.

A view might be applied to multiple graph elements or none.

Every graph element have at least one view assigned. For now we can assume it is exactly one.


Editors

Each view have several user-defined rendering templates, conditions or events.

They are:

1) JSX editor

It defines the html displayed in the graph for a specific element.

A view might be applied to multiple graph elements or none.

2) Usage Declarations

It is a function, that populates an object with variables usable in all other events.

It serves 3 purposes:

  1. Separate logic and presentation, making the jsx editor a purer html template.
  2. Declare which data the visual representation is using, so the visual element will only update if any of the properties "declared" here changed.

Since the rendering phase is computationally heavy, strictly declaring all the dependencies can optimize performance avoiding some pointless re-renders.

By default the elements will update for any change in the model, view or node. Unless the user manually specify a stricter or broader declaration.

If the elements are "not updating" there is probably a missing dependency here.

A likely mistake, is when an element is visualizing data from his containing element ( class -> package ), his subelements ( class -> attribute ) or his pointed value ( reference -> pointed element ), in this case the default declarations do not cover the "external" access, and it must be declared.

This is an example adding the m1 reference -> pointed object name scenario: "targetName = data.value.name".

After adding this declaration, targetName can be used as a variable in the other editors, such as "Pointing to: {targetName}" in jsx editor.

  1. sharing common data structures derived from the model with all other editors, without needing to compute it twice or more.

3) constants

They are usable like declarations in usage declarations, but they are not bound to a specific node/model, they are instead the same declaration set for all elements using this view.

As such "data" and "node" cannot be used in this editor, the values are meant to be constants or values computable without navigating the model.

For example like the first N elements of the fibonacci sequence, or a dictionary mapping a constant set of strings to colors.

The default view of a Value uses this feature to determine the color value according to his type (string -> green, number -> orange...) without polluting the JSX with many if's.

Usage in JSX: <span style={{color: constants[valuesType]}>{values}

Check out the "value" view in default viewpoint for more.

4) Css editor

A simple css editor where all the selectors are restricted to match only elements matched with the current view.

So there is no concern in a div{} selector matching a large portion of the whole website or conflicting with the css from other views.

The editor allows for nested CSS declarations and supports LESS css preprocessor.

This editor is without context, so data, node, view and all the variables from usage declarations and constants are unavailable.

If the "global" checkbox is active, the css can edit the appearance of the whole website and can conflict editing other views style. This is the only way to customize anything outside the graph, but a misplaced declaration like "body{ display: none }" might render the whole application unusable until reloaded.

5) OCL editor

A OCL condition which dictates if the view should be applied to a model element.

The context consists only of the "data" variable which contains a fragment of the model, the ocl should use an invariant expression to determine if the model is eligible for being represented by this view.

The engine is a work of Stephan Köninger with MIT license.

Check his documentation page for all the valid OCL expressions, however only the invariant expressions have been tested to work by the jodel developers.

6) JS condition

Serves the same purpose as the OCL editor, but the expression is in javascript, with "data" and "node" as context.

If the condition is a single line, the output of that expression will determine if the view can be applied to given data and node.

If the condition is multi-lined, the last line will determine it.

The editor can contain multiple non-expression javascript statements such as if, for loops, variable declarations... can also conditionally return values before the end of the script with the "return" statement.

However the last line must be a valid javascript expression that computes into a boolean or numeric value.

7) On data update

An event triggered every time the usage declarations check passes and the element is re-rendered, which is a user-defined subset of all the possible model changes.

The user is free to perform any action here, such as moving the node to a set of coordinates dictated by the model, or even updating the model to implement derived attributes. like if "radius" feature changed, update the "area" feature accordingly.

However be careful of possible infinite loops a misuse of this feature might cause, for example if "radius" is declared in usageDeclarations, and this event increments it, a loop of infinite increments and re-renders will begin.

Such loops are detected and halted after 10 executions performed in less than 0.3 seconds to prevent the editor becoming unresponsive, however the onDataUpdate event will be disabled until modified and it might cause lag.

Slower computers (or huge models) which cannot execute the event more than 10 times in 0.3 seconds might cause the editor to become permanently unresponsive.

8) All other On ... Events

They are free to perform any action editing the model or the node, even restricting his movements or layout to a specific pattern.

  • *-start events are triggered only once when the user begins a drag/resize/rotation interaction, and the element is still in his original layout.
  • *-end events are triggered only once when the user completes a drag/resize/rotation interaction, and the element is in his destination location/size/angle.
  • *-ing events are triggered multiple times when the user begins a drag/resize/rotation interaction.

The rate of activation depends on the operative system and speed of the computer, you can count it "as fast your computer can", which is every N pixels of movement, with a minumum of 1. Slower computers might trigger this event every 100 pixels or so.

Warning 1: If the view.ladyUpdate mode is set, this event will not trigger at all.

Warning 2: Since this event is triggered multiple times, use it only if it is unavoidable such as to disallow dragging an element inside an area.

A similar result can be obtained with a "*-end" event, which will not dictate the movement while the element is dragging, but can bring it back to the closest valid position outside the "no-drag area" when the drag is finished. Similar constraints can be done for Resize/Rotate events.

Editors available context

context jodel usageDeclarations, constants, and props are accessible in destructured form too. Meaning they are accessible both through "constants.constant_name" and simply as "constant_name". If there is a naming conflict between destructured contexts, the following priority is used:

  1. usage declarations
  2. constants
  3. props

Advanced features

Sub Views

A view can list N other views as "sub views", which can get a customizable score boost, which will recommend a view to be used for his subelements if eligible. For example if there is are a set of "red themed" views, and a set of "blue themed" views, it makes sense to have the red themed class view as a subview of the red themed package view, and the blue-classes as subviews of blue-packages. So the classes contained in a red themed package will be red themed as well, and the classes contained in a blue-themed package will be blue, even if both class views ocl/jsCondition are matching the class and both could be eligible.

Decorative Views

Those views behaves like normal views for everything except the JSX template.

A graph element can be assigned with exactly 1 main view, and 0...N decorative Views.

Those views are meant to either add functionalities / events to an element displayed by another view (decorative view with empty jsx) like additional drag events and css declarations.

Or to insert decorative / functional visual elements (with some JSX). In this case, the JSX will not replace the main element representation, which is made by his main view but will add some additional interface, like a frame with some additional buttons/menus in addition to possible extra events/css.

Some usage example could be:

  • Adding a button or :hover css query which will display a model-to-text fragment for the interacted element, for easier m2t debugging/visualization.
  • Adding a condition set in OCL/jsCondition which matches a validation constraint, if the decorator view matches, the element is invalid in some way. And the view can add CSS/HTML to display some red underline, circling or displaying a error message next or around the matched element.

Constants and usage declaration variables are not shared between main view and secondary view, each view is independent and adds his own independent set of features.

Scores

When a graph element matches multiple views, each view is given a score.

The views will then be sorted according to their score, to pick the single main view with highest score, discarding all other matching _main view_s, and to determine the order of concatenation of _decorative view_s

The view score is obtained by combining 4 subscores:

  1. viewpoint bonus: Only views from non-exclusive viewpoints or the active one can be matched. Views from the active viewpoint get a multiplicative bonus of 2, views from non-esclusive viewpoints have no bonus.

  2. pre-requisite_bonus: The view can dictate which model type elements can be applied to (classes, objects, packages...) if the model element is not of the current type, it will declare a mismatch without evaluating other scores.

If this condition is satisfied, there are 2 possible bonus multipliers: * (1) for implicit matches with the "any" condition. * (3) for exact match, eg: requesting DAttribute model type and being applied to an attribute. * (2) for inheritance match, eg: requesting DStructuralFeature, which can match attributes, references and operations and matching one of those. Or DNamedElement or any other Ecore type which can have subclasses.

  1. subView bonus: if the element containing this one is recommending the current view through his subview collection, a user-defined bonus will apply.
  2. view Priority: if OCL or jsCondition are present but failed the match, the view will mismatch without proceeding. Otherwise there are 3 subcases, the first valid applies.
    1. If the jsCondition returns a number instead of a boolean, that number is the view_priority.
    2. Can be manually defined by the user.
    3. If neither, it is the sum of the ocl and jsCondition length as raw strings (an euristic to give more weight to more "complex" queries).

The final score is computed as: prerequisite_bonus * subView_bonus * view_priority

Overriding the score

In JSX editor, when defining the , or other tags that will generate a graph element, it is possible to add a props named "view" which can contain a View, a Pointer or a view name.

If multiple views share the same name, it is also possible to specify a "path" through subviews. If there is a "package_view" with a subview "class_view" "package_view.class_view" will retrieve "class_view", the path can contain spaces if a view name have them.

If given, the target view will become the main view regardless of his score.

The "views" props can be used to forcefully assign a set of decorative views.

ViewStack

when a graph element matches multiple views, they form a stack, where


Other options

store size in view

If this option is active, a node using this view will not share his position with other views, so if this view is disabled (viewpoint change), the node will revert to the position he had before being matched with this view. and if this view is re-enabled the node will be back to his former position.

This allows for different viewpoints to have different layouts.

...

and more options yet to list

Clone this wiki locally