cpee 2.1.130 → 2.1.131

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -193,13 +193,6 @@ function cockpit() { //{{{
193
193
  },
194
194
  complete: function() {
195
195
  var q = $.parseQuerySimple();
196
- if (q.min || q.min == "") {
197
- uidash_toggle_vis_tab($('#instance'));
198
- uidash_toggle_vis_tab($('#parameters'));
199
- }
200
- if (q.dea || q.dea == "") {
201
- uidash_toggle_vis_tab($('#instance'));
202
- }
203
196
  if (q.theme) { graph_theme = q.theme; }
204
197
  if (q.position) { graph_position = q.position == 'false' ? 'false' : 'true'; }
205
198
  if (q.highlight) {
@@ -256,6 +249,13 @@ function cockpit() { //{{{
256
249
  uidash_activate_tab("#tabexecution");
257
250
  create_instance($("body").attr('current-base'),q.exec,true,true);
258
251
  }
252
+ if (q.min || q.min == "") {
253
+ uidash_toggle_vis_tab($('#instance'));
254
+ uidash_toggle_vis_tab($('#parameters'));
255
+ }
256
+ if (q.dea || q.dea == "") {
257
+ uidash_toggle_vis_tab($('#instance'));
258
+ }
259
259
  }
260
260
  });
261
261
  $.ajax({
@@ -1168,17 +1168,16 @@ function WfDescription(wf_adaptor, wf_illustrator) { // Model {{{
1168
1168
  set_details(ctname,csname,pos,context,true);
1169
1169
  [undefined, endnodes] = draw_position(ctname,parent_pos,pos,prev,block,[],context,{svg: g, pos: origpos});
1170
1170
  }
1171
- prev = JSON.parse(JSON.stringify(endnodes));
1172
1171
  if (illustrator.elements[sname].border == 'structural') {
1173
- // structural border: outgoing arrow starts at the group border instead of leaving from the icon
1174
- // small y offset
1175
- prev = prev.map(function(p) {
1176
- if (!p) return p;
1172
+ // structural border: outgoing arrow starts at the group border instead of from the icon
1173
+ // small y offset.
1174
+ endnodes = endnodes.map(function(p) {
1177
1175
  var np = JSON.parse(JSON.stringify(p));
1178
1176
  np.yoffset = illustrator.height_shift/2 + illustrator.group_extend + 15 - illustrator.structural_tighten;
1179
1177
  return np;
1180
1178
  });
1181
1179
  }
1180
+ prev = JSON.parse(JSON.stringify(endnodes));
1182
1181
  }
1183
1182
  });
1184
1183
 
data/cockpit/llm.html CHANGED
@@ -136,35 +136,35 @@
136
136
  </svg>
137
137
  </template>
138
138
 
139
+ <div class='hidden' id="areanew"> <!--{{{-->
140
+ <table class='x-ui-layout'>
141
+ <tr>
142
+ <td>Resources:</td>
143
+ <td><input name="res-url" type="text" value=""/></td>
144
+ <td></td>
145
+ </tr>
146
+ <tr>
147
+ <td>Engine:</td>
148
+ <td><input name="base-url" type="text" value=""/></td>
149
+ <td><button name="base">create new instance</button></td>
150
+ </tr>
151
+ <tr>
152
+ <td>Instance:</td>
153
+ <td><input name="instance-url" type="text" value=""/></td>
154
+ <td><button name="instance">monitor instance</button></td>
155
+ </tr>
156
+ </table>
157
+ </div> <!--}}}-->
158
+
139
159
  <ui-tabbed id="instance">
140
160
  <ui-tabbar>
141
161
  <ui-tab class="switch" ></ui-tab>
142
- <ui-tab class="" data-tab="new" id="tabnew" >New</ui-tab>
143
162
  <ui-tab class="inactive hidden" data-tab="instance" id="tabinstance" >Instance</ui-tab>
144
163
  <ui-tab class="inactive hidden" data-tab="execution" id="tabexecution">Execution</ui-tab>
145
164
  <ui-behind ><a style='display:none' target='_blank' id='current-instance'></a><a style='display:none' target='_blank' id='current-instance-properties'>P</a><a style='display:none' target='_blank' id='current-instance-subscriptions'>S</a><a style='display:none' target='_blank' id='current-instance-callbacks'>C</a></ui-behind>
146
165
  <ui-last ><a class="logo" href=".."></a></ui-last>
147
166
  </ui-tabbar>
148
167
  <ui-content>
149
- <ui-area data-belongs-to-tab="new" id="areanew"> <!--{{{-->
150
- <table class='x-ui-layout'>
151
- <tr>
152
- <td>Resources:</td>
153
- <td><input name="res-url" type="text" value=""/></td>
154
- <td></td>
155
- </tr>
156
- <tr>
157
- <td>Engine:</td>
158
- <td><input name="base-url" type="text" value=""/></td>
159
- <td><button name="base">create new instance</button></td>
160
- </tr>
161
- <tr>
162
- <td>Instance:</td>
163
- <td><input name="instance-url" type="text" value=""/></td>
164
- <td><button name="instance">monitor instance</button></td>
165
- </tr>
166
- </table>
167
- </ui-area> <!--}}}-->
168
168
  <ui-area data-belongs-to-tab="instance" id="areainstance" class="inactive"> <!--{{{-->
169
169
  <div>
170
170
  <div class='section'>
@@ -264,7 +264,6 @@
264
264
  <ui-tabbar>
265
265
  <ui-before ></ui-before>
266
266
  <ui-tab class="" data-tab="details" id="tabdetails">Graph</ui-tab>
267
- <ui-tab class="inactive" data-tab="dsl" id="tabdsl" >Description</ui-tab>
268
267
  <ui-tab class="inactive" data-tab="log" id="tablog" >Log</ui-tab>
269
268
  <ui-behind ><a style='display:none' target='_blank' id='current-track'>T</a><a style='display:none' target='_blank' id='current-graph'>G</a></ui-behind>
270
269
  </ui-tabbar>
@@ -315,7 +314,6 @@
315
314
  <div id="dat_details" class='x-ui-layout'></div>
316
315
  </ui-part>
317
316
  </ui-area>
318
- <ui-area data-belongs-to-tab="dsl" id="areadsl" class="inactive"></ui-area>
319
317
  <ui-area data-belongs-to-tab="log" id="arealog" class="inactive"> <!--{{{-->
320
318
  <div>Persistent Log: <a style='display:none' target='_blank' id='current-log'></a> [<a style='display:none' target='_blank' id='xml-log'>X</a>,<a style='display:none' target='_blank' id='shifted-log'>S</a>]</div>
321
319
  <table id="dat_log" class="x-ui-layout"></table>
@@ -88,31 +88,31 @@
88
88
  </svg>
89
89
  </template>
90
90
 
91
+ <div class='hidden' id="areanew"> <!--{{{-->
92
+ <table class='x-ui-layout'>
93
+ <tr>
94
+ <td>Resources:</td>
95
+ <td><input name="res-url" type="text" value=""/></td>
96
+ </tr>
97
+ <tr>
98
+ <td>Engine:</td>
99
+ <td><input name="base-url" type="text" value=""/></td>
100
+ </tr>
101
+ <tr>
102
+ <td>Instance:</td>
103
+ <td><input name="instance-url" type="text" value=""/></td>
104
+ </tr>
105
+ </table>
106
+ </div> <!--}}}-->
107
+
91
108
  <ui-tabbed id="instance">
92
109
  <ui-tabbar>
93
110
  <ui-tab class="switch" ></ui-tab>
94
- <ui-tab class="" data-tab="new" id="tabnew" >Config</ui-tab>
95
- <ui-tab class="inactive hidden" data-tab="instance" id="tabinstance" >Instance</ui-tab>
111
+ <ui-tab class="inactive hidden" data-tab="instance" id="tabinstance" >Model</ui-tab>
96
112
  <ui-behind ><a style='display:none' target='_blank' id='current-instance'></a><a style='display:none' target='_blank' id='current-instance-properties'>P</a><a style='display:none' target='_blank' id='current-instance-subscriptions'>S</a><a style='display:none' target='_blank' id='current-instance-callbacks'>C</a></ui-behind>
97
113
  <ui-last ><a class="logo" href=".."></a></ui-last>
98
114
  </ui-tabbar>
99
115
  <ui-content>
100
- <ui-area data-belongs-to-tab="new" id="areanew"> <!--{{{-->
101
- <table class='x-ui-layout'>
102
- <tr>
103
- <td>Resources:</td>
104
- <td><input name="res-url" type="text" value=""/></td>
105
- </tr>
106
- <tr>
107
- <td>Engine:</td>
108
- <td><input name="base-url" type="text" value=""/></td>
109
- </tr>
110
- <tr>
111
- <td>Instance:</td>
112
- <td><input name="instance-url" type="text" value=""/></td>
113
- </tr>
114
- </table>
115
- </ui-area> <!--}}}-->
116
116
  <ui-area data-belongs-to-tab="instance" id="areainstance" class="inactive"> <!--{{{-->
117
117
  <div>
118
118
  <div class='section'>
@@ -0,0 +1,419 @@
1
+ # CPEE Cockpit Themes — Author's Guide
2
+
3
+ This document explains, in detail, how `themes` works and how to build your own theme: your own directory, your own element hierarchy, your own SVG symbols, and your own RelaxNG (`.rng`) schemas.
4
+
5
+ ## Table of contents
6
+
7
+ 1. [The anatomy of a theme directory](#1-the-anatomy-of-a-theme-directory)
8
+ 2. [Creating your own theme, step by step](#2-creating-your-own-theme-step-by-step)
9
+ 3. [The `theme.js` file: class skeleton and instance flags](#3-the-themejs-file-class-skeleton-and-instance-flags)
10
+ 4. [Inside `theme.js` - the element hierarchy](#4-inside-themejs---the-element-hierarchy)
11
+ 1. [Defining an element](#41-defining-an-element)
12
+ 2. [Handling element rendering](#42-handling-element-rendering)
13
+ 3. [Handling interaction with the element](#43-handling-interaction-with-the-element)
14
+ 5. [Defining a UI for elements - RelaxNG schemas (`.rng`)](#5-defining-a-ui-for-elements---relaxng-schemas-rng)
15
+ 6. [Defining Element looks - SVG symbols](#6-defining-element-looks---svg-symbols)
16
+ 7. [Styling Elements - CSS class reference](#7-styling-elements---css-class-reference)
17
+ 8. [Worked example: adding a new element end-to-end](#8-worked-example-adding-a-new-element-end-to-end)
18
+
19
+ ---
20
+
21
+ ## 1. The anatomy of a theme directory
22
+
23
+ ```
24
+ themes/<yourtheme>/
25
+ ├── theme.js # required — defines WFAdaptorManifestation
26
+ ├── rngs/ # real dir OR symlink to another theme's rngs/
27
+ └── symbols/ # real dir OR symlink to another theme's symbols/
28
+ ```
29
+
30
+ Look at the existing themes and a pattern jumps out immediately:
31
+
32
+ ```
33
+ $ ls -la themes/presetid themes/reduced themes/control
34
+ presetid: rngs -> ../preset/rngs/ symbols -> ../preset/symbols/ theme.js
35
+ reduced: rngs -> ../preset/rngs/ symbols -> ../preset/symbols/ theme.js
36
+ control: rngs -> ../preset/rngs/ symbols -> ../preset/symbols/ theme.js
37
+ ```
38
+
39
+ `cockpit/themes/default` is itself nothing but a symlink: `default -> preset/`.
40
+
41
+ Only themes that actually ship **different icons** have a real `symbols/` directory (`preset`, `preset_model`), and only themes that ship **different attribute schemas** have a real `rngs/` directory (`preset`, `preset_model`, `model`, `felix`). Everyone else symlinks the whole directory to `preset`'s, because `theme.js` there only overrides *JS behaviour* (labels, info, event wiring) — it doesn't need new visuals at all.
42
+
43
+ **Rule of thumb:**
44
+
45
+ * Only touching labels/behaviour in `theme.js`? → symlink both `rngs/` and `symbols/` to an existing complete set (usually `preset`).
46
+ * Need to change a handful of icons but nothing else? → make `symbols/` a **real** directory containing a full copy of the base set (see `preset_model/symbols/`, which is a full copy of `preset/symbols/` with only `closed_loop*.svg` and `terminate.svg` actually modified), and keep `rngs/` symlinked.
47
+ * Need custom attributes (new RelaxNG rules) too? → make `rngs/` real as well (see `model/rngs/`, which is a full copy of `preset/rngs/` minus files it never references, e.g. `start.rng`).
48
+
49
+ You cannot symlink individual files *inside* a directory that is itself a symlinked directory (the symlink replaces the whole directory entry) — if you want to override just one icon, you need a real `symbols/` directory containing every file the theme's active elements reference (copy the full set once, then edit the ones you care about).
50
+
51
+ ---
52
+
53
+ ## 2. Creating your own theme, step by step
54
+
55
+ 1. **Pick a name** and create the directory: `themes/mytheme/`.
56
+ 2. **Decide on assets.** If you're not changing any icons or schemas:
57
+ ```
58
+ cd cockpit/themes/mytheme
59
+ ln -s ../preset/symbols/ symbols
60
+ ln -s ../preset/rngs/ rngs
61
+ ```
62
+ If you *are* changing icons, copy instead of symlinking:
63
+ ```
64
+ cp -r ../preset/symbols ./symbols
65
+ ln -s ../preset/rngs/ rngs
66
+ ```
67
+ 3. **Write `theme.js`**. At minimum:
68
+ ```js
69
+ WFAdaptorManifestation = class extends WFAdaptorManifestationBase {
70
+ constructor(adaptor) {
71
+ super(adaptor);
72
+ }
73
+ }
74
+ ```
75
+ This alone gives you a fully working, unmodified copy of the base behaviour.
76
+ 4. **Register the theme** wherever the hosting page lets the user pick a theme name (the theme name is just the directory name, passed as `theme` when constructing `new WfAdaptor(data-theme-base + '/' + theme + '/theme.js', ...)`.
77
+ 5. **Iterate**: override instance flags, per-element behaviour, or whole new elements as needed, reloading the HTML that renders a BPMN with your theme to see the effect.
78
+
79
+ ---
80
+
81
+ ## 3. The `theme.js` file: class skeleton and instance flags
82
+
83
+ ```js
84
+ WFAdaptorManifestation = class extends WFAdaptorManifestationBase {
85
+ constructor(adaptor) {
86
+ super(adaptor);
87
+ var self = this;
88
+
89
+ // instance-level flags (all default false unless noted)
90
+ this.compact = true; // shorter/split multi-line labels
91
+ this.rotated_labels = false; // labels drawn at -30deg
92
+ this.striped = true; // alternating row background stripes
93
+
94
+ // per-element overrides
95
+ this.elements.critical.illustrator.label = function(node) { ... };
96
+ }
97
+ }
98
+ ```
99
+
100
+ `super(adaptor)` must run first; every override below it patches what `base.js` already built, it does not need to redeclare things from scratch.
101
+
102
+ ---
103
+
104
+ ## 4. Inside `theme.js` - the element hierarchy
105
+
106
+ `this.elements.<tagname>` maps 1:1 to an XML tag name in the process description (e.g. `this.elements.critical` describes `<critical>...</critical>` nodes). Two ways to add or extend elements:
107
+
108
+ **A. Override an existing element** (most common): reach into `this.elements.<tag>` after `super(adaptor)` and replace/patch a property. Since `super()` already built the whole object, you can either replace a whole sub-object or just one function:
109
+
110
+ ```js
111
+ this.elements.choose.illustrator.label = null; // suppress a label
112
+ ```
113
+
114
+ **B. Define a brand-new element** with `'parent'`. This is how *sub-variants* of anelement are declared in `base.js` itself (e.g. `parallel_branch_normal` /`parallel_branch_event` are both `'parent': 'parallel_branch'`). The theme loader walks every element once at load time and, for any element with a `parent`, **copies down** whatever the child didn't specify itself.
115
+
116
+ So a `parent`-based element only needs to state what's *different* — typically just its own `svg` (icon) — and inherits every other illustrator key, its `type`, its `description` schema, and its `adaptor` event map from the parent:
117
+
118
+ ```js
119
+ this.elements.critical_finish = {
120
+ 'type': 'primitive',
121
+ 'illustrator': {
122
+ 'endnodes': 'this',
123
+ 'svg': self.adaptor.theme_dir + 'symbols/event_end.svg'
124
+ }
125
+ };
126
+ ```
127
+
128
+ `type` is one of:
129
+
130
+ - `'complex'` — has children, gets recursed into, gets a translucent "tile" background rect.
131
+ - `'primitive'` — a leaf, just an icon (and maybe a label).
132
+ - `'abstract'` — implicit default for elements that exist only to be inherited from via `parent` and are never drawn directly themselves.
133
+
134
+ ---
135
+
136
+ ### 4.1. Defining an element
137
+
138
+ Every key that appears as a **direct** property of `this.elements.<tag>` (not nested inside `illustrator`):
139
+
140
+ | Key | Value | Purpose |
141
+ |---|---|---|
142
+ | `type` | `'complex' or 'primitive' or 'abstract' `| Drives whether `parse()` recurses and whether a tile background is drawn. |
143
+ | `illustrator` | `Object` | Everything about how/where this element is drawn. |
144
+ | `description` | `string (path) `| Path to this element's `.rng` schema, used to render the attribute-editing panel on the right of the graph view. |
145
+ | `parent` | `string (tag name)` | Inherit `illustrator` / `type` /`description` / `adaptor` keys not explicitly set on this element, from the named parent element. |
146
+ | `permissible_children` | `function(node, mode)` | Returns the array of `{label, function_call, menu_icon, type, params}` entries shown in the right-click "Insert into" / "Insert after" menu, depending on `mode` (`'into'` or `'after'`). |
147
+ | `permissible_children_expert` | `function(node, mode)` | Same shape, shown under a separate "…(Experts Only!)" submenu — used for structures that are technically legal but not part of the guided/simple menu (e.g. nesting `parallel` inside `critical`). |
148
+ | `removable_children` | `function(node)` | Returns extra "Remove X" menu entries for optional child structures that aren't ordinary XML children removable by the generic delete action (e.g. removing the `<code>` block under `callmanipulate`). |
149
+ | `adaptor` | `object (event map)` | DOM event handlers bound to displayed element. |
150
+ | `neverdelete` | `'true' or 'false'` | Marks this element's XML node as undeletable by the generic "Remove Element" action; used for e.g. `otherwise`. |
151
+
152
+ ---
153
+
154
+ ### 4.2. Handling element rendering
155
+
156
+ These are the keys read by the layout/rendering engine. All are optional unless
157
+ noted; unset booleans behave as `false`/absent.
158
+
159
+ | Key | Type | Purpose |
160
+ |---|---|---|
161
+ | `svg` | `string (path)` | The icon file. Fetched once via AJAX at theme-load time and replaced in-place with the parsed document, then cloned per drawn instance. |
162
+ | `endnodes` | `'this' \| 'aggregate' \| 'passthrough'` | Controls what "the connection point(s) leaving this element" are, once it and any children/closing symbol have been drawn. `'this'`: only this element itself is an endpoint (used by primitives, and by elements whose own drawn position is the real exit point, e.g. `critical_finish`). Anything else: the element's *children's* endpoints propagate through (used by containers whose exit is wherever their last child ends, e.g. `critical`, `parallel`, `choose`). |
163
+ | `closeblock` | `true \| false` | When `true`, an extra "loop-back" connection is drawn from this element back up to its block's start (used for the closing element of a loop: `loop_finish`, `loop_head_finish`). |
164
+ | `border` | `'visual' \| 'structural'` | Draws a dashed rounded-rect box around the element's block. `'visual'`: just decoration — connections still terminate at/leave from the icon itself (used by `parallel_branch_event`, `group`). `'structural'`: in addition, incoming/outgoing connections stop at the **border edge** instead of the icon (see below) — currently only `critical` uses this. |
165
+ | `closing_symbol` | string (element key) | Name of another element (usually a `parent`-linked sibling-type, e.g. `critical_finish`, `parallel_finish`, `choose_finish`, `loop_finish`) drawn automatically right after this element's children, to visually "close" the block. Also makes the `border`/tile rect grow one extra row to enclose it. |
166
+ | `wide` | `true` | Marks an icon as occupying its own extra grid column instead of reusing the block's first row's column — **"only for the special case of variable parallel, only `event_end` has it, all others should reference the first row"**. Don't set this unless you're doing exactly that. |
167
+ | `noarrow` | `true \| false` | When `true`, suppresses the normal incoming arrow and instead uses the alternate "straight join line, no arrowhead" routing. Used by `parallel_branch_event` (`noarrow: false` there, i.e. explicit default). |
168
+ | `expansion` | `function(node) → 'vertical' \| 'horizontal'` | For `type: 'complex'` elements: do children stack as a sequential column (`'vertical'`, e.g. `critical`, `parallel_branch`, `group`) or lay out side-by-side (`'horizontal'`, e.g. `choose`'s alternatives, `parallel`'s branches when it has non-`parallel_branch` children)? |
169
+ | `col_shift` | `function(node) → boolean` | Whether entering this element's children indents them one grid column to the right (nested visual indentation, matching a drawn border/tile box). `true` for `parallel`, `group`; `false` for `critical` (its structural border is tight against the icon's own column, no extra indent). |
170
+ | `resolve_symbol` | `function(node, shift)` returning an element key, **or** a literal string | Redirects which element's *icon* gets drawn for this XML tag, without changing the tag itself or its RNG schema — e.g. `choose_finish` picks between `choose_inclusive_finish`/`choose_exclusive_finish` based on `node`'s `mode` attribute; `parallel_branch` picks between `parallel_branch_normal`/`parallel_branch_event` based on the `shift` argument (which is that element's own `col_shift(node)` result). |
171
+ | `label` | `function(node) → [{column, value}, ...]` or `null` | Text shown next to the icon (rendered into the `part-middle` group of the. Return an array so multiple stacked lines/columns are possible (e.g. Label + Average). Set to `null` to explicitly suppress a label a parent theme added. Almost always reads an XML attribute, e.g. `$(node).attr('sid')`, `$(node).attr('condition')`. |
172
+ | `style` | `function(node) → {cssProperty: value, ...}` | Per-instance inline style applied to every shape carrying the `.colorstyle` class inside this icon. Typically used to let a user set a custom color per node, e.g. `{'fill': $(node).attr('color')}`. |
173
+ | `info` | `function(node) → {attrName: value, ...}` | Extra HTML attributes stamped onto the drawn element (e.g. `element-endpoint`, `element-alt_id`), consumed later for lookups/menu icon rendering. |
174
+ | `final` | `true` | Marks this element as a true dead-end (used by `terminate`) — downstream connection logic skips drawing anything past a `final` endpoint. |
175
+ | `rotatelabels` | `true \| false` | Per-element opt-out/opt-in for the manifestation-level `rotated_labels` flag. |
176
+ | `noindent` | `true` | Per-element opt-out of the default indent-first-column behavior in horizontal expansions. |
177
+
178
+ `border: 'structural'` is the mechanism built for subprocesses. When an element's `border` is
179
+ `'structural'` an border is painted around all subelements, with arrows connected to the boundary instead of the elements insid
180
+
181
+ ---
182
+
183
+ ### 4.3. Handling interaction with the element
184
+
185
+ ```js
186
+ 'adaptor': {
187
+ 'mousedown': function(node,e) { self.events.mousedown(node,e,true,true); },
188
+ 'touchstart': function(node,e) { self.events.touchstart(node,e,true,true); },
189
+ 'touchend': self.events.touchend,
190
+ 'click': self.events.click,
191
+ 'dblclick': self.events.dblclick,
192
+ 'mouseover': self.events.mouseover,
193
+ 'mouseout': self.events.mouseout,
194
+ }
195
+ ```
196
+
197
+ These events are bound on the rendered elements, dispatching to the function with the DOM element's `element-id`. You
198
+ almost never write new handler bodies — `WFAdaptorManifestationBase` already implements
199
+ the shared interaction vocabulary:
200
+
201
+ | Handler | Purpose |
202
+ |---|---|
203
+ | `mousedown(svgid,e,child,sibling)` | Selection + (with `child`/`sibling` flags) opens the context menu offering "Insert into"/"Insert after" using `permissible_children`. |
204
+ | `touchstart` / `touchend` | Touch equivalents of mousedown/click, with long-press → context menu. |
205
+ | `click` | Populates the details panel (`update_details`) from this node's RNG. |
206
+ | `dblclick` | Usually a shortcut into editing (theme-specific — see `model/theme.js`/`control/theme.js` for concrete uses). |
207
+ | `mouseover` / `mouseout` | Hover highlight (`.hoverstyle`). |
208
+ | `dragstart` | Enables dragging this node elsewhere in the tree (only wired up for a few elements, e.g. `callmanipulate`/`manipulate`'s inner `<code>` block). |
209
+ | `suppress` | No-op stub — used for icons that should not react to interaction (e.g. `end`, `event_end`). |
210
+
211
+ `type: 'complex'` elements typically bind all seven; simple, non-interactive closing icons only bind `mousedown: suppress`. Copy the block from a similar existing element rather than inventing new handler wiring.
212
+
213
+ ---
214
+
215
+ ## 5. Defining a UI for elements - RelaxNG schemas (`.rng`)
216
+
217
+ `<yourtheme>/rngs/<tag>.rng` is a single `<element>` RelaxNG fragment (namespaced
218
+ `rngui` extensions layered on top for the UI form generator, `RelaxNGui`). It defines which
219
+ attributes/child elements are editable in the right-hand details panel when a node is
220
+ selected, and it's what actually gets merged back into the saved XML.
221
+
222
+ Minimal example (`critical.rng`):
223
+
224
+ ```xml
225
+ <element xmlns="http://relaxng.org/ns/structure/1.0" xmlns:rngui="http://rngui.org"
226
+ rngui:version="1.2" name="critical"
227
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
228
+ ns="http://cpee.org/ns/description/1.0">
229
+ <attribute name="eid" rngui:label="ID" rngui:default="javascript:get_free_id('e','eid')">
230
+ <data type="string" rngui:readonly="true"/>
231
+ </attribute>
232
+ <attribute name="sid" rngui:label="SID" rngui:default="section"
233
+ rngui:hint="Identical SID's shared between different 'critical' elements define mutual exclusive areas.">
234
+ <data type="string"/>
235
+ </attribute>
236
+ </element>
237
+ ```
238
+
239
+ A richer example (`choose.rng`) shows a `<choice>` attribute (rendered as a dropdown) and
240
+ nested `rngui:ignore="true"` child elements (structural children that the form generator
241
+ should not itself let the user add/remove, because the graph UI already manages them via
242
+ its own "Insert alternative" menu commands):
243
+
244
+ ```xml
245
+ <attribute name="mode" rngui:label="Mode" rngui:default="exclusive">
246
+ <choice>
247
+ <value>exclusive</value>
248
+ <value>inclusive</value>
249
+ </choice>
250
+ </attribute>
251
+ ```
252
+
253
+ Useful `rngui:*` attributes seen in the base schemas: `label` (form field caption),
254
+ `default` (initial value, or a `javascript:` expression evaluated once on insert —
255
+ `get_free_id(...)` mints a fresh unique id), `hint` (tooltip/help text), `readonly`.
256
+
257
+ If an XML attribute your `illustrator.label`/`illustrator.style`/`illustrator.info`
258
+ function reads (e.g. `sid`, `color`, `a:alt_id`) isn't declared in the `.rng`, the
259
+ attribute-editing UI simply won't expose a way to set it interactively — you'd need to
260
+ add an `<attribute>` for it.
261
+
262
+ ---
263
+
264
+ ## 6. Defining Element looks - SVG symbols
265
+
266
+ Every icon file is a small, **viewBox-less** SVG fragment. There is no `<svg width= height=>`
267
+ sizing — instead every icon is drawn on the same implicit **40×40 unit grid** (`illustrator.width`/`illustrator.height`, both `40`), with a small
268
+ built-in margin (a circle icon uses `r="14"` centered at `(15,15)`, i.e. roughly a
269
+ 1–2 unit margin on every side). Stick to that scale for any new icon so it lines up with
270
+ everything else.
271
+
272
+ ```xml
273
+ <svg class="clickable" xmlns="http://www.w3.org/2000/svg">
274
+ <circle cx="15" cy="15" r="14" class="colorstyle execstyle stand"/>
275
+ ...
276
+ </svg>
277
+ ```
278
+
279
+ Each symbol is cloned per drawn instance, and wrapped in a positioned `<g class="element">`, and:
280
+ - appends a `<title>` (tooltip) and a hover/mark decoration group automatically — you
281
+ don't draw those yourself.
282
+ - appends an exec-state indicator (`▶ active,vote`) automatically unless suppressed.
283
+ - applies any `illustrator.info(node)` result as extra attributes on the `<g>`.
284
+ - applies any `illustrator.style(node)` result as inline CSS to every element inside your
285
+ icon carrying the `.colorstyle` class.
286
+
287
+ ### Multi-state icons: `part-*` groups
288
+
289
+ Any icon that needs a **label next to it**, or that renders differently depending on
290
+ context, is wrapped in named groups instead of being flat markup:
291
+
292
+ ```xml
293
+ <svg class="clickable" xmlns="http://www.w3.org/2000/svg">
294
+ <g class="part-normal">
295
+ <circle cx="15" cy="15" r="14" class="colorstyle execstyle stand"/>
296
+ ...
297
+ </g>
298
+ <g class="part-start">
299
+ <!-- usually identical content to part-normal -->
300
+ ...
301
+ </g>
302
+ <g class="part-middle" transform="translate(32,0)">
303
+ <text transform="translate(0,20)" class="label"></text>
304
+ </g>
305
+ </svg>
306
+ ```
307
+
308
+ | Group class | Meaning |
309
+ |---|---|
310
+ | `part-normal` | Default rendering. |
311
+ | `part-start` | Alternate rendering used when this instance is the first element handling a given "endpoint" chain. Usually identical to `part-normal`; some icons (like `loop.svg`) genuinely differ here (e.g. a diamond icon vs. plain box). |
312
+ | `part-middle` | Positioned *after* the icon and holds the actual `<text class="label">` node that gets its text content set at render time. Only include this group if the element's `illustrator.label` function returns something. |
313
+ | `part-end` | A trailing decoration appended after `part-middle`'s label. |
314
+ | `part-extra` | Extra decoration shown alongside `part-end`. |
315
+
316
+ If your icon has **no label and no state variation**, skip the `part-*` wrapping entirely
317
+ and just put shapes directly under `<svg>` — that's what most simple icons (`start.svg`,
318
+ `stop.svg`, `escape.svg`, the original `critical.svg`) do.
319
+
320
+ ---
321
+
322
+ ## 7. Styling Elements - CSS class reference
323
+
324
+ All symbol styling lives in one shared, global stylesheet — `wfadaptor.css` —
325
+ loaded once regardless of theme. **Themes do not ship their own CSS.** Icon files only
326
+ ever reference classes already defined there (or use inline `style="..."` overrides for
327
+ one-off tweaks, e.g. `style="fill:none;"`).
328
+
329
+ | Class | Purpose |
330
+ |---|---|
331
+ | `.execstyle` / `.execstylethin` | Stroke color/width driven by the *execution state* of the enclosing `<g class="passive\|active\|vote">` (blue/red/green respectively) — put this on the "primary ring" of an icon so it visibly reflects running/failed/voting state. `execstylethin` is the same idea at `stroke-width:2` instead of `4`. |
332
+ | `.hoverstyle` / `.markstyle` | The two decoration shapes `draw_symbol` appends automatically to every icon (a small hover checkmark-in-circle, and the "marked for copy/move" ring) — hidden by default, shown via `g.element.hover` / `.marked` / `.selected` state classes. You never add these yourself; they come for free. |
333
+ | `.colorstyle` | **No CSS rule — a JS hook only.** Marks which shapes inside an icon should receive the element's *per-instance* `illustrator.style(node)` inline style (e.g. a user-chosen color). The engine selects `.colorstyle` elements and applies the style directly as inline CSS. If nothing sets a `style`, elements with this class just render per whatever other classes they also carry. |
334
+ | `.stand` | The default outline style: background-colored fill, dark stroke (`stroke-width:1.6`). Use for the main outline of most shapes. |
335
+ | `.standthin` | Same as `.stand` but forces `stroke-width:1` — for secondary/inner rings (dashed clock rings, etc). |
336
+ | `.standfat` | Same as `.stand` but `stroke-width:3` — for emphasis (e.g. `end.svg`'s thick ring). |
337
+ | `.greyfat` | Like `.standfat` but stroked in the light/muted grey variable — de-emphasized elements. |
338
+ | `.normal` | Solid dark fill, near-zero stroke — flat black glyph fill (e.g. `critical.svg`'s original exclamation mark). |
339
+ | `.white` | Background-colored fill *and* stroke — used to visually "punch a hole"/cover the layer beneath (e.g. `parallel.svg`'s notch). |
340
+ | `.black` | Solid dark fill and stroke, `stroke-width:1.6` — flat black shapes (e.g. the padlock body in `critical.svg`). |
341
+ | `.grey` | Like `.black` but in the light/muted grey variable. |
342
+ | `.unknown` | Fallback style used for the placeholder icon when an element type can't be resolved. |
343
+ | `.gen` | `fill:ButtonFace` themed generic/system look — rarely used directly in icons. |
344
+ | `.standwithout` / `.standtrans` | Background-colored fill only, no stroke rule of its own — thin helper classes for shapes that only need a fill. |
345
+ | `.edge` (on `<line>`/`<path>`) | The connection/arrow line style (`stroke-width:2`, no fill). Applied automatically by `draw_connection`, not something you put in an icon file. |
346
+ | `.block` (on the border `<rect>`) | The dashed outline box drawn by `draw_border` (`border: 'visual' \| 'structural'`). Applied automatically, not authored in an icon. |
347
+ | `.tile` (on the background `<rect>`) | The translucent highlight box drawn by `draw_tile` for every `type: 'complex'` element. Applied automatically. |
348
+ | `.label` (on `<text>`) | The node label text style. Put this on the `<text>` inside `part-middle`; leave its content empty, it's filled in at render time. |
349
+ | `.label.standalone` | Adds a background-colored outline stroke behind the label text (for readability over busy backgrounds) — used e.g. on `loop.svg`'s inline label. |
350
+ | `.label.rotate` | Applied automatically when the manifestation's `rotated_labels`/an element's `rotatelabels` is active. |
351
+ | `.duration` | Stroke color for duration-annotation strokes. |
352
+ | `.super` / `tspan.exec` / `.active` / `.vote` / `.colon` / `.necessary` | The small execution-count indicator (`▶ 0,0`) appended automatically above every icon unless `addition` is suppressed at draw time. |
353
+ | `.stripe.even` / `.stripe.odd` | Alternating row backgrounds, only drawn when the manifestation sets `this.striped = true`. |
354
+
355
+ CSS custom properties (in `:root`, top of `wfadaptor.css`) drive the actual colors:
356
+ `--wfadaptor-exec-passive/active/vote`, `--wfadaptor-base`, `--wfadaptor-base-light`,
357
+ `--wfadaptor-background`, `--wfadaptor-selected*`, `--wfadaptor-hover*`,
358
+ `--wfadaptor-stripe`, `--wfadaptor-border`, `--wfadaptor-mark`, `--wfadaptor-important`,
359
+ `--wfadaptor-label`. Since this stylesheet is shared by every theme, changing these
360
+ variables changes the palette for **all** themes at once — a theme cannot rescope them
361
+ per-instance (there is no per-theme stylesheet), so don't rely on any theme-specific
362
+ palette.
363
+
364
+ ---
365
+
366
+ ## 8. Worked example: adding a new element end-to-end
367
+
368
+ This condenses the actual steps used in this project to add the `critical` "critical
369
+ section" element with its own icon, label, and structural border (a real, tested
370
+ recipe):
371
+
372
+ 1. **Icon** (`symbols/critical.svg`) — a simple circle-backed glyph, with `part-normal`/
373
+ `part-start` (identical) plus `part-middle` holding the label text:
374
+ ```xml
375
+ <svg class="clickable" xmlns="http://www.w3.org/2000/svg">
376
+ <g class="part-normal">
377
+ <circle cx="15" cy="15" r="14" class="colorstyle execstyle stand"/>
378
+ <path d="M 11,14 L 11,10 A 4,4 0 0 1 19,10 L 19,14" class="stand" style="fill:none;"/>
379
+ <rect x="9.5" y="13.5" width="11" height="9" rx="1.5" class="black"/>
380
+ </g>
381
+ <g class="part-start"> <!-- same content --> </g>
382
+ <g class="part-middle" transform="translate(32,0)">
383
+ <text transform="translate(0,20)" class="label"></text>
384
+ </g>
385
+ </svg>
386
+ ```
387
+ 2. **Closing element** (a `parent`-linked variant, reusing an existing icon):
388
+ ```js
389
+ this.elements.critical_finish = {
390
+ 'type': 'primitive',
391
+ 'illustrator': { 'endnodes': 'this', 'svg': self.adaptor.theme_dir + 'symbols/event_end.svg' }
392
+ };
393
+ ```
394
+ 3. **Main element definition**, wiring the closing element and the label:
395
+ ```js
396
+ this.elements.critical = {
397
+ 'type': 'complex',
398
+ 'illustrator': {
399
+ 'label': function(node){ return [ { column: 'Label', value: $(node).attr('sid') } ]; },
400
+ 'endnodes': 'aggregate',
401
+ 'closeblock': false,
402
+ 'border': 'structural',
403
+ 'closing_symbol': 'critical_finish',
404
+ 'expansion': function(node) { return 'vertical'; },
405
+ 'col_shift': function(node) { return false; },
406
+ 'svg': self.adaptor.theme_dir + 'symbols/critical.svg'
407
+ },
408
+ 'description': self.adaptor.theme_dir + 'rngs/critical.rng',
409
+ 'permissible_children': function(node,mode) { /* same shape as choose/parallel above */ },
410
+ 'adaptor': { /* copy the standard 7-handler block from a sibling complex element */ }
411
+ };
412
+ ```
413
+ 4. **Schema** (`rngs/critical.rng`) declaring the `sid` attribute the label function reads.
414
+ 5. Add a menu entry somewhere permissible (e.g. inside `parallel_branch`'s
415
+ `permissible_children`) so the element is actually reachable from the editor UI.
416
+
417
+ That's the whole recipe: one icon file, one schema file, and one (or two, if you need a
418
+ distinct closing icon) entries in `this.elements`.
419
+
@@ -1,5 +1,15 @@
1
1
  <svg class="clickable" xmlns="http://www.w3.org/2000/svg">
2
- <path class="colorstyle execstyle stand" d="m 3.5 27 l 12 -24 l 12 24 z"/>
3
- <path class="normal" style="fill:#000000;" d="m 16.5 11 l 0 8 l -2 0 l 0 -8 z"/>
4
- <path class="normal" style="fill:#000000;" d="m 16.5 21 l 0 2 l -2 0 l 0 -2 z"/>
2
+ <g class="part-normal">
3
+ <circle cx="15" cy="15" r="14" class="colorstyle execstyle stand"/>
4
+ <path d="M 11,14 L 11,10 A 4,4 0 0 1 19,10 L 19,14" class="stand" style="fill:none;"/>
5
+ <rect x="9.5" y="13.5" width="11" height="9" rx="1.5" class="black"/>
6
+ </g>
7
+ <g class="part-start">
8
+ <circle cx="15" cy="15" r="14" class="colorstyle execstyle stand"/>
9
+ <path d="M 11,14 L 11,10 A 4,4 0 0 1 19,10 L 19,14" class="stand" style="fill:none;"/>
10
+ <rect x="9.5" y="13.5" width="11" height="9" rx="1.5" class="black"/>
11
+ </g>
12
+ <g class="part-middle" transform="translate(32,0)">
13
+ <text transform="translate(0,20)" class="label"></text>
14
+ </g>
5
15
  </svg>
data/cpee.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "cpee"
3
- s.version = "2.1.130"
3
+ s.version = "2.1.131"
4
4
  s.platform = Gem::Platform::RUBY
5
5
  s.license = "LGPL-3.0-or-later"
6
6
  s.summary = "The cloud process execution engine (cpee.org). If you just need workflow execution, without a rest service exposing it, then use WEEL."
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpee
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.130
4
+ version: 2.1.131
5
5
  platform: ruby
6
6
  authors:
7
7
  - Juergen eTM Mangler
@@ -354,6 +354,7 @@ files:
354
354
  - cockpit/templates/instantiate/Take_Perf.xml
355
355
  - cockpit/templates/instantiate/Take_Sub.xml
356
356
  - cockpit/templates/instantiate/Take_X.xml
357
+ - cockpit/themes/THEMES.MD
357
358
  - cockpit/themes/base.js
358
359
  - cockpit/themes/control/rngs/alternative.rng
359
360
  - cockpit/themes/control/rngs/call.rng