@node-projects/web-component-designer-visualization-addons 0.1.18 → 0.1.20

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.
@@ -26,6 +26,10 @@ export declare class EventAssignment extends BaseCustomWebComponentConstructorAp
26
26
  initialize(visualizationHandler: VisualizationHandler, visualizationShell: VisualizationShell, scriptCommandsTypeInfo: any, propertiesTypeInfo: any): void;
27
27
  set instanceServiceContainer(value: InstanceServiceContainer);
28
28
  protected _createControlsForScript(eventItem: IEvent): any;
29
+ protected _getScriptName(eventItem: IEvent): any;
30
+ protected _changeScriptName(e: KeyboardEvent, eventItem: IEvent): Promise<void>;
31
+ protected _getRelativeSignalsPath(eventItem: IEvent): any;
32
+ protected _changeRelativeSignalsPath(e: KeyboardEvent, eventItem: IEvent): Promise<void>;
29
33
  protected _hasParameters(eventItem: IEvent): boolean;
30
34
  protected _getScriptTypeColor(eventItem: IEvent): any;
31
35
  protected _getScriptType(eventItem: IEvent): scriptType;
@@ -45,11 +45,11 @@ export class EventAssignment extends BaseCustomWebComponentConstructorAppend {
45
45
  <div>[[this._createControlsForScript(item)]]</div>
46
46
  </template>
47
47
  <span style="grid-column: 1 / span 3; margin-top: 8px; margin-left: 3px;">add event:</span>
48
- <input id="addEventInput" style="grid-column: 1 / span 3; margin: 5px;" @keypress=[[this._addEvent(event)]] type="text">`;
48
+ <input id="addEventInput" style="grid-column: 1 / span 3; margin: 5px;" @keypress="[[this._addEvent(event)]]" type="text">`;
49
49
  static editRowTemplate = html `
50
50
  <div style="display: flex; justify-content: flex-end;">
51
- <input hidden="[[this._getScriptType(item) !== 'js']]" placeholder="name" title="name" style="min-width: 50px; flex-basis: 30px; flex-grow: 2;" class="mth" type="text">
52
- <input placeholder="relative signals path" title="relative signals path" style="min-width: 50px; flex-basis: 20px; flex-grow: 1;" class="mth" type="text">
51
+ <input value="[[this._getScriptName(item)]]" @keypress="[[this._changeScriptName(event, item)]]" hidden="[[this._getScriptType(item) !== 'js']]" placeholder="name" title="name" style="min-width: 50px; flex-basis: 30px; flex-grow: 2;" class="mth" type="text">
52
+ <input value="[[this._getRelativeSignalsPath(item)]]" @keypress="[[this._changeRelativeSignalsPath(event, item)]]" placeholder="relative signals path" title="relative signals path" style="min-width: 50px; flex-basis: 20px; flex-grow: 1;" class="mth" type="text">
53
53
  <button css:background="[[this._hasParameters(item) ? 'lime' : '']]" style="display: flex; padding: 0; flex-grow: 0;" title="parameter" @click="[[this._editParameter(event, item)]]">p</button>
54
54
  </div>`;
55
55
  static scriptTypeColors = {
@@ -97,6 +97,68 @@ export class EventAssignment extends BaseCustomWebComponentConstructorAppend {
97
97
  const ctl = this.constructor.editRowTemplate.content.cloneNode(true);
98
98
  return ctl;
99
99
  }
100
+ _getScriptName(eventItem) {
101
+ if (this.selectedItems[0].hasAttribute('@' + eventItem.name)) {
102
+ const val = this.selectedItems[0].getAttribute('@' + eventItem.name);
103
+ if (val[0] === '{') {
104
+ if (val.includes('name')) {
105
+ const parsed = JSON.parse(val);
106
+ return parsed.name;
107
+ }
108
+ }
109
+ else {
110
+ return val;
111
+ }
112
+ }
113
+ return null;
114
+ }
115
+ async _changeScriptName(e, eventItem) {
116
+ if (e.key == 'Enter') {
117
+ if (this.selectedItems && this.selectedItems.length) {
118
+ if (this.selectedItems[0].hasAttribute('@' + eventItem.name)) {
119
+ const newValue = e.target.value;
120
+ const val = this.selectedItems[0].getAttribute('@' + eventItem.name);
121
+ if (val.startsWith('{')) {
122
+ const parsed = JSON.parse(val);
123
+ parsed.name = newValue;
124
+ this._selectedItems[0].setAttribute('@' + eventItem.name, JSON.stringify(parsed));
125
+ }
126
+ else {
127
+ this._selectedItems[0].setAttribute('@' + eventItem.name, newValue);
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ _getRelativeSignalsPath(eventItem) {
134
+ if (this.selectedItems[0].hasAttribute('@' + eventItem.name)) {
135
+ const val = this.selectedItems[0].getAttribute('@' + eventItem.name);
136
+ if (val[0] === '{' && val.includes('relativeSignalsPath')) {
137
+ const parsed = JSON.parse(val);
138
+ return parsed.relativeSignalsPath;
139
+ }
140
+ }
141
+ return null;
142
+ }
143
+ async _changeRelativeSignalsPath(e, eventItem) {
144
+ if (e.key == 'Enter') {
145
+ if (this.selectedItems && this.selectedItems.length) {
146
+ if (this.selectedItems[0].hasAttribute('@' + eventItem.name)) {
147
+ const newValue = e.target.value;
148
+ const val = this.selectedItems[0].getAttribute('@' + eventItem.name);
149
+ if (val.startsWith('{')) {
150
+ const parsed = JSON.parse(val);
151
+ parsed.relativeSignalsPath = newValue;
152
+ this._selectedItems[0].setAttribute('@' + eventItem.name, JSON.stringify(parsed));
153
+ }
154
+ else {
155
+ let obj = { name: val, relativeSignalsPath: newValue };
156
+ this._selectedItems[0].setAttribute('@' + eventItem.name, JSON.stringify(obj));
157
+ }
158
+ }
159
+ }
160
+ }
161
+ }
100
162
  _hasParameters(eventItem) {
101
163
  if (this.selectedItems[0].hasAttribute('@' + eventItem.name)) {
102
164
  const val = this.selectedItems[0].getAttribute('@' + eventItem.name);
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1,28 @@
1
+ import { BaseCustomWebComponentConstructorAppend } from "@node-projects/base-custom-webcomponent";
2
+ import { Script } from "../scripting/Script.js";
3
+ import { ServiceContainer } from "@node-projects/web-component-designer";
4
+ import { VisualizationHandler } from "../interfaces/VisualizationHandler";
5
+ import { VisualizationShell } from "../interfaces/VisualizationShell";
6
+ import '@node-projects/splitview.webcomponent';
7
+ export declare class SimpleScriptEditor extends BaseCustomWebComponentConstructorAppend {
8
+ static readonly style: CSSStyleSheet;
9
+ static readonly template: HTMLTemplateElement;
10
+ static readonly is = "node-projects-simple-script-editor";
11
+ serviceContainer: ServiceContainer;
12
+ visualizationHandler: VisualizationHandler;
13
+ visualizationShell: VisualizationShell;
14
+ scriptCommandsTypeInfo: any;
15
+ propertiesTypeInfo: any;
16
+ private _script;
17
+ private _commandListDiv;
18
+ private _commandListFancyTree;
19
+ private _possibleCommands;
20
+ private _propertygrid;
21
+ constructor();
22
+ ready(): Promise<void>;
23
+ private addPossibleCommands;
24
+ loadScript(script: Script): void;
25
+ private createTreeItem;
26
+ addItem(): void;
27
+ getScriptCommands(): any[];
28
+ }
@@ -0,0 +1,254 @@
1
+ import { BaseCustomWebComponentConstructorAppend, css, html } from "@node-projects/base-custom-webcomponent";
2
+ import { ContextMenu } from "@node-projects/web-component-designer";
3
+ import { typeInfoFromJsonSchema } from "@node-projects/propertygrid.webcomponent";
4
+ import { defaultOptions } from "@node-projects/web-component-designer-widgets-wunderbaum";
5
+ import { Wunderbaum } from 'wunderbaum';
6
+ //@ts-ignore
7
+ import wunderbaumStyle from 'wunderbaum/dist/wunderbaum.css' assert { type: 'css' };
8
+ import { VisualizationPropertyGrid } from "./VisualizationPropertyGrid";
9
+ import '@node-projects/splitview.webcomponent';
10
+ export class SimpleScriptEditor extends BaseCustomWebComponentConstructorAppend {
11
+ static style = css `
12
+ :host {
13
+ background: white;
14
+ }
15
+ .list{
16
+ display: grid;
17
+ grid-template-columns: 1fr 40px;
18
+ width: calc(100% - 6px);
19
+ box-sizing: border-box;
20
+ margin: 3px;
21
+ }
22
+
23
+ .list button{
24
+ padding: 5px 10px;
25
+ box-sizing: border-box;
26
+ display: flex;
27
+ justify-content: center;
28
+ margin-right: 5px;
29
+ margin-left: 5px;
30
+ }
31
+
32
+ node-projects-visualization-property-grid {
33
+ width: 100%;
34
+ height: 100%;
35
+ }
36
+ `;
37
+ static template = html `
38
+ <div style="width:100%; height:100%; overflow: hidden;">
39
+ <node-projects-split-view style="height: 100%; width: 100%; position: relative;" orientation="horizontal">
40
+ <div style="width: 40%; position: relative;">
41
+ <div style="width:calc(100% - 4px); height:calc(100% - 4px)">
42
+ <div id="commandList" style="overflow-x: hidden; overflow-y: auto; width:100%; height: calc(100% - 34px);"></div>
43
+ <div class="list">
44
+ <select id="possibleCommands" style="width: 100%"></select>
45
+ <button @click="[[this.addItem()]]">Add</button>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ <div style="width: 60%; position: relative;">
50
+ <node-projects-visualization-property-grid id="propertygrid"></node-projects-visualization-property-grid>
51
+ </div>
52
+ </node-projects-split-view>
53
+ </div>
54
+ `;
55
+ static is = 'node-projects-simple-script-editor';
56
+ serviceContainer;
57
+ visualizationHandler;
58
+ visualizationShell;
59
+ scriptCommandsTypeInfo;
60
+ propertiesTypeInfo;
61
+ _script;
62
+ _commandListDiv;
63
+ _commandListFancyTree;
64
+ _possibleCommands;
65
+ _propertygrid;
66
+ constructor() {
67
+ super();
68
+ this._restoreCachedInititalValues();
69
+ this._commandListDiv = this._getDomElement('commandList');
70
+ this._possibleCommands = this._getDomElement('possibleCommands');
71
+ this._propertygrid = this._getDomElement('propertygrid');
72
+ this.shadowRoot.adoptedStyleSheets = [wunderbaumStyle, SimpleScriptEditor.style];
73
+ }
74
+ async ready() {
75
+ this.addPossibleCommands();
76
+ this._parseAttributesToProperties();
77
+ this._bindingsParse(null, true);
78
+ this._assignEvents();
79
+ let editComplex = async (data) => {
80
+ let pg = new VisualizationPropertyGrid();
81
+ pg.visualizationHandler = this.visualizationHandler;
82
+ pg.visualizationShell = this.visualizationShell;
83
+ pg.serviceContainer = this.serviceContainer;
84
+ pg.getTypeInfo = (obj, type) => typeInfoFromJsonSchema(this.propertiesTypeInfo, obj, type);
85
+ pg.showHead = false;
86
+ pg.typeName = 'IScriptMultiplexValue';
87
+ pg.title = 'Complex for "' + data.propertyPath + '"';
88
+ if (typeof data.value === 'object')
89
+ pg.selectedObject = data.value ?? {};
90
+ else
91
+ pg.selectedObject = {};
92
+ let res = await this.visualizationShell.openConfirmation(pg, { x: 100, y: 100, width: 300, height: 300, parent: this });
93
+ if (res) {
94
+ this._propertygrid.setPropertyValue(data.propertyPath, pg.selectedObject);
95
+ this._propertygrid.refresh();
96
+ }
97
+ };
98
+ this._propertygrid.visualizationHandler = this.visualizationHandler;
99
+ this._propertygrid.visualizationShell = this.visualizationShell;
100
+ this._propertygrid.serviceContainer = this.serviceContainer;
101
+ this._propertygrid.getTypeInfo = (obj, type) => typeInfoFromJsonSchema(this.scriptCommandsTypeInfo, obj, type);
102
+ this._propertygrid.getSpecialEditorForType = async (property, currentValue, propertyPath, wbRender, additionalInfo) => {
103
+ if (typeof currentValue === 'object' && currentValue !== null) {
104
+ let rB = document.createElement('button');
105
+ rB.style.height = 'calc(100% - 6px)';
106
+ rB.style.position = 'relative';
107
+ rB.style.display = 'flex';
108
+ rB.style.justifyContent = 'center';
109
+ rB.style.width = '20px';
110
+ rB.style.boxSizing = 'content-box';
111
+ rB.innerText = 'del';
112
+ rB.onclick = () => {
113
+ this._propertygrid.setPropertyValue(propertyPath, undefined);
114
+ this._propertygrid.refresh();
115
+ };
116
+ wbRender.nodeElem.insertAdjacentElement('afterbegin', rB);
117
+ let d = document.createElement('div');
118
+ d.style.display = 'flex';
119
+ let sp = document.createElement('span');
120
+ sp.innerText = 'complex: ' + JSON.stringify(currentValue);
121
+ sp.style.overflow = 'hidden';
122
+ sp.style.whiteSpace = 'nowrap';
123
+ sp.style.textOverflow = 'ellipsis';
124
+ sp.style.flexGrow = '1';
125
+ sp.title = JSON.stringify(currentValue);
126
+ d.appendChild(sp);
127
+ let b = document.createElement('button');
128
+ b.innerText = '...';
129
+ b.onclick = () => {
130
+ editComplex({ value: currentValue, propertyPath });
131
+ };
132
+ d.appendChild(b);
133
+ wbRender.nodeElem.style.display = 'flex';
134
+ return d;
135
+ }
136
+ else {
137
+ let b = document.createElement('button');
138
+ b.style.height = 'calc(100% - 6px)';
139
+ b.style.position = 'relative';
140
+ b.style.display = 'flex';
141
+ b.style.justifyContent = 'center';
142
+ b.style.width = '20px';
143
+ b.style.boxSizing = 'content-box';
144
+ b.title = 'complex';
145
+ b.style.opacity = '0.2';
146
+ b.innerText = '...';
147
+ b.onclick = () => {
148
+ editComplex({ value: currentValue, propertyPath });
149
+ };
150
+ wbRender.nodeElem.insertAdjacentElement('afterbegin', b);
151
+ wbRender.nodeElem.style.display = 'flex';
152
+ }
153
+ return null;
154
+ };
155
+ this._propertygrid.propertyNodeContextMenu.on((data) => {
156
+ ContextMenu.show([{
157
+ title: 'edit complex value',
158
+ action: async () => {
159
+ editComplex(data);
160
+ }
161
+ },
162
+ {
163
+ title: 'remove complex value',
164
+ action: async () => {
165
+ this._propertygrid.setPropertyValue(data.propertyPath, undefined);
166
+ this._propertygrid.refresh();
167
+ }
168
+ }], data.event);
169
+ });
170
+ }
171
+ //Converter from TypscriptJsonSchema to our Property list...
172
+ async addPossibleCommands() {
173
+ let commands = Object.keys(this.scriptCommandsTypeInfo.definitions);
174
+ for (let c of commands) {
175
+ if (c == 'ScriptCommands')
176
+ continue;
177
+ let option = document.createElement('option');
178
+ option.innerText = c;
179
+ this._possibleCommands.add(option);
180
+ }
181
+ }
182
+ loadScript(script) {
183
+ this._script = script;
184
+ let commandListTreeItems = [];
185
+ for (let c of this._script.commands) {
186
+ commandListTreeItems.push(this.createTreeItem(c));
187
+ }
188
+ ;
189
+ this._commandListFancyTree = new Wunderbaum({
190
+ ...defaultOptions,
191
+ element: this._commandListDiv,
192
+ icon: false,
193
+ source: commandListTreeItems,
194
+ activate: (e) => {
195
+ this._propertygrid.selectedObject = e.node.data.data.item;
196
+ },
197
+ render: (e) => {
198
+ if (e.isNew) {
199
+ let span = e.nodeElem;
200
+ span.oncontextmenu = (ev) => {
201
+ e.node.setActive();
202
+ if (e.node.data.contextMenu) {
203
+ e.node.data.contextMenu(ev, e.node.data, e.node);
204
+ }
205
+ ev.preventDefault();
206
+ return false;
207
+ };
208
+ }
209
+ },
210
+ dnd: {
211
+ guessDropEffect: true,
212
+ preventRecursion: true,
213
+ preventVoidMoves: false,
214
+ serializeClipboardData: false,
215
+ dragStart: (e) => {
216
+ e.event.dataTransfer.effectAllowed = "move";
217
+ e.event.dataTransfer.dropEffect = "move";
218
+ return true;
219
+ },
220
+ dragEnter: (e) => {
221
+ e.event.dataTransfer.dropEffect = 'move';
222
+ return true;
223
+ },
224
+ dragOver: (e) => {
225
+ e.event.dataTransfer.dropEffect = 'move';
226
+ },
227
+ drop: async (e) => {
228
+ e.sourceNode.moveTo(e.node, e.region == 'before' ? 'before' : 'after');
229
+ }
230
+ }
231
+ });
232
+ }
233
+ createTreeItem(currentItem) {
234
+ let cti = {
235
+ title: currentItem.type,
236
+ data: { item: currentItem },
237
+ contextMenu: (e, data, node) => {
238
+ ContextMenu.show([{ title: 'Remove Item', action: (e) => node.remove() }], e);
239
+ }
240
+ };
241
+ return cti;
242
+ }
243
+ addItem() {
244
+ const cmdName = this._possibleCommands.value;
245
+ const command = { type: cmdName };
246
+ const ti = this.createTreeItem(command);
247
+ this._commandListFancyTree.addChildren(ti);
248
+ }
249
+ getScriptCommands() {
250
+ let children = this._commandListFancyTree.root.children;
251
+ return children.map(x => x.data.data.item);
252
+ }
253
+ }
254
+ customElements.define(SimpleScriptEditor.is, SimpleScriptEditor);
@@ -4,53 +4,53 @@ import { typeInfoFromJsonSchema } from "@node-projects/propertygrid.webcomponent
4
4
  import { defaultOptions } from "@node-projects/web-component-designer-widgets-wunderbaum";
5
5
  import { Wunderbaum } from 'wunderbaum';
6
6
  //@ts-ignore
7
- import wunderbaumStyle from 'wunderbaum/dist/wunderbaum.css' assert { type: 'css' };
7
+ import wunderbaumStyle from 'wunderbaum/dist/wunderbaum.css' with { type: 'css' };
8
8
  import { VisualizationPropertyGrid } from "./VisualizationPropertyGrid.js";
9
9
  import '@node-projects/splitview.webcomponent';
10
10
  export class SimpleScriptEditor extends BaseCustomWebComponentConstructorAppend {
11
- static style = css `
12
- :host {
13
- background: white;
14
- }
15
- .list{
16
- display: grid;
17
- grid-template-columns: 1fr 40px;
18
- width: calc(100% - 6px);
19
- box-sizing: border-box;
20
- margin: 3px;
21
- }
22
-
23
- .list button{
24
- padding: 5px 10px;
25
- box-sizing: border-box;
26
- display: flex;
27
- justify-content: center;
28
- margin-right: 5px;
29
- margin-left: 5px;
30
- }
31
-
32
- node-projects-visualization-property-grid {
33
- width: 100%;
34
- height: 100%;
35
- }
11
+ static style = css `
12
+ :host {
13
+ background: white;
14
+ }
15
+ .list{
16
+ display: grid;
17
+ grid-template-columns: 1fr 40px;
18
+ width: calc(100% - 6px);
19
+ box-sizing: border-box;
20
+ margin: 3px;
21
+ }
22
+
23
+ .list button{
24
+ padding: 5px 10px;
25
+ box-sizing: border-box;
26
+ display: flex;
27
+ justify-content: center;
28
+ margin-right: 5px;
29
+ margin-left: 5px;
30
+ }
31
+
32
+ node-projects-visualization-property-grid {
33
+ width: 100%;
34
+ height: 100%;
35
+ }
36
36
  `;
37
- static template = html `
38
- <div style="width:100%; height:100%; overflow: hidden;">
39
- <node-projects-split-view style="height: 100%; width: 100%; position: relative;" orientation="horizontal">
40
- <div style="width: 40%; position: relative;">
41
- <div style="width:calc(100% - 4px); height:calc(100% - 4px)">
42
- <div id="commandList" style="overflow-x: hidden; overflow-y: auto; width:100%; height: calc(100% - 34px);"></div>
43
- <div class="list">
44
- <select id="possibleCommands" style="width: 100%"></select>
45
- <button @click="[[this.addItem()]]">Add</button>
46
- </div>
47
- </div>
48
- </div>
49
- <div style="width: 60%; position: relative;">
50
- <node-projects-visualization-property-grid id="propertygrid"></node-projects-visualization-property-grid>
51
- </div>
52
- </node-projects-split-view>
53
- </div>
37
+ static template = html `
38
+ <div style="width:100%; height:100%; overflow: hidden;">
39
+ <node-projects-split-view style="height: 100%; width: 100%; position: relative;" orientation="horizontal">
40
+ <div style="width: 40%; position: relative;">
41
+ <div style="width:calc(100% - 4px); height:calc(100% - 4px)">
42
+ <div id="commandList" style="overflow-x: hidden; overflow-y: auto; width:100%; height: calc(100% - 34px);"></div>
43
+ <div class="list">
44
+ <select id="possibleCommands" style="width: 100%"></select>
45
+ <button @click="[[this.addItem()]]">Add</button>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ <div style="width: 60%; position: relative;">
50
+ <node-projects-visualization-property-grid id="propertygrid"></node-projects-visualization-property-grid>
51
+ </div>
52
+ </node-projects-split-view>
53
+ </div>
54
54
  `;
55
55
  static is = 'node-projects-visualization-simple-script-editor';
56
56
  serviceContainer;
@@ -100,55 +100,60 @@ export class SimpleScriptEditor extends BaseCustomWebComponentConstructorAppend
100
100
  this._propertygrid.serviceContainer = this.serviceContainer;
101
101
  this._propertygrid.getTypeInfo = (obj, type) => typeInfoFromJsonSchema(this.scriptCommandsTypeInfo, obj, type);
102
102
  this._propertygrid.getSpecialEditorForType = async (property, currentValue, propertyPath, wbRender, additionalInfo) => {
103
- if (typeof currentValue === 'object' && currentValue !== null) {
104
- let rB = document.createElement('button');
105
- rB.style.height = 'calc(100% - 6px)';
106
- rB.style.position = 'relative';
107
- rB.style.display = 'flex';
108
- rB.style.justifyContent = 'center';
109
- rB.style.width = '20px';
110
- rB.style.boxSizing = 'content-box';
111
- rB.innerText = 'del';
112
- rB.onclick = () => {
113
- this._propertygrid.setPropertyValue(propertyPath, undefined);
114
- this._propertygrid.refresh();
115
- };
116
- wbRender.nodeElem.insertAdjacentElement('afterbegin', rB);
117
- let d = document.createElement('div');
118
- d.style.display = 'flex';
119
- let sp = document.createElement('span');
120
- sp.innerText = 'complex: ' + JSON.stringify(currentValue);
121
- sp.style.overflow = 'hidden';
122
- sp.style.whiteSpace = 'nowrap';
123
- sp.style.textOverflow = 'ellipsis';
124
- sp.style.flexGrow = '1';
125
- sp.title = JSON.stringify(currentValue);
126
- d.appendChild(sp);
127
- let b = document.createElement('button');
128
- b.innerText = '...';
129
- b.onclick = () => {
130
- editComplex({ value: currentValue, propertyPath });
131
- };
132
- d.appendChild(b);
133
- wbRender.nodeElem.style.display = 'flex';
134
- return d;
135
- }
136
- else {
137
- let b = document.createElement('button');
138
- b.style.height = 'calc(100% - 6px)';
139
- b.style.position = 'relative';
140
- b.style.display = 'flex';
141
- b.style.justifyContent = 'center';
142
- b.style.width = '20px';
143
- b.style.boxSizing = 'content-box';
144
- b.title = 'complex';
145
- b.style.opacity = '0.2';
146
- b.innerText = '...';
147
- b.onclick = () => {
148
- editComplex({ value: currentValue, propertyPath });
149
- };
150
- wbRender.nodeElem.insertAdjacentElement('afterbegin', b);
151
- wbRender.nodeElem.style.display = 'flex';
103
+ //@ts-ignore
104
+ if (!property.specialAllreadyAdded) {
105
+ //@ts-ignore
106
+ property.specialAllreadyAdded = true;
107
+ if (typeof currentValue === 'object' && currentValue !== null) {
108
+ let rB = document.createElement('button');
109
+ rB.style.height = 'calc(100% - 6px)';
110
+ rB.style.position = 'relative';
111
+ rB.style.display = 'flex';
112
+ rB.style.justifyContent = 'center';
113
+ rB.style.width = '20px';
114
+ rB.style.boxSizing = 'content-box';
115
+ rB.innerText = 'del';
116
+ rB.onclick = () => {
117
+ this._propertygrid.setPropertyValue(propertyPath, undefined);
118
+ this._propertygrid.refresh();
119
+ };
120
+ wbRender.nodeElem.insertAdjacentElement('afterbegin', rB);
121
+ let d = document.createElement('div');
122
+ d.style.display = 'flex';
123
+ let sp = document.createElement('span');
124
+ sp.innerText = 'complex: ' + JSON.stringify(currentValue);
125
+ sp.style.overflow = 'hidden';
126
+ sp.style.whiteSpace = 'nowrap';
127
+ sp.style.textOverflow = 'ellipsis';
128
+ sp.style.flexGrow = '1';
129
+ sp.title = JSON.stringify(currentValue);
130
+ d.appendChild(sp);
131
+ let b = document.createElement('button');
132
+ b.innerText = '...';
133
+ b.onclick = () => {
134
+ editComplex({ value: currentValue, propertyPath });
135
+ };
136
+ d.appendChild(b);
137
+ wbRender.nodeElem.style.display = 'flex';
138
+ return d;
139
+ }
140
+ else {
141
+ let b = document.createElement('button');
142
+ b.style.height = 'calc(100% - 6px)';
143
+ b.style.position = 'relative';
144
+ b.style.display = 'flex';
145
+ b.style.justifyContent = 'center';
146
+ b.style.width = '20px';
147
+ b.style.boxSizing = 'content-box';
148
+ b.title = 'complex property value';
149
+ b.style.opacity = '0.2';
150
+ b.innerText = '...';
151
+ b.onclick = () => {
152
+ editComplex({ value: currentValue, propertyPath });
153
+ };
154
+ wbRender.nodeElem.insertAdjacentElement('afterbegin', b);
155
+ wbRender.nodeElem.style.display = 'flex';
156
+ }
152
157
  }
153
158
  return null;
154
159
  };
@@ -6,6 +6,11 @@ export class VisualizationPropertyGrid extends PropertyGrid {
6
6
  visualizationHandler;
7
7
  visualizationShell;
8
8
  async getEditorForType(property, currentValue, propertyPath, wbRender, additionalInfo) {
9
+ if (this.getSpecialEditorForType) {
10
+ let edt = await this.getSpecialEditorForType(property, currentValue, propertyPath, wbRender, additionalInfo);
11
+ if (edt)
12
+ return edt;
13
+ }
9
14
  switch (property.format) {
10
15
  case 'screen': {
11
16
  let editor = document.createElement('select');
@@ -3,7 +3,7 @@ export declare class IScriptMultiplexValue {
3
3
  * signal - read the value from a Signal
4
4
  * property - read the value from a property of the customControl (not usable in screens)
5
5
  * event - read the value of a property of the event object
6
- * parameter - a paremter you hand over
6
+ * parameter - a parameter you hand over
7
7
  */
8
8
  source: 'signal' | 'property' | 'event' | 'parameter';
9
9
  /**
@@ -3,7 +3,7 @@ export class IScriptMultiplexValue {
3
3
  * signal - read the value from a Signal
4
4
  * property - read the value from a property of the customControl (not usable in screens)
5
5
  * event - read the value of a property of the event object
6
- * parameter - a paremter you hand over
6
+ * parameter - a parameter you hand over
7
7
  */
8
8
  source;
9
9
  /**
@@ -0,0 +1,5 @@
1
+ export interface VisualizationUiHandler {
2
+ switchLanguage(language: string): any;
3
+ closeDialog(element: HTMLElement): any;
4
+ openDialog(): any;
5
+ }
@@ -0,0 +1,2 @@
1
+ //dialog:{screenName: string, title: string, moveable: boolean, closeable: boolean, width: string, height: string, left: string, top: string}
2
+ export {};
@@ -7,6 +7,7 @@ type contextType = {
7
7
  element: Element;
8
8
  root: HTMLElement;
9
9
  parameters?: Record<string, any>;
10
+ relativeSignalsPath?: string;
10
11
  };
11
12
  export declare class ScriptSystem {
12
13
  _visualizationHandler: VisualizationHandler;
@@ -14,6 +15,7 @@ export declare class ScriptSystem {
14
15
  execute(scriptCommands: ScriptCommands[], outerContext: contextType): Promise<void>;
15
16
  runScriptCommand<T extends ScriptCommands>(command: T, context: contextType): Promise<void>;
16
17
  getValue<T>(value: string | number | boolean | IScriptMultiplexValue, outerContext: contextType): Promise<any>;
18
+ getSignaName(name: string, outerContext: contextType): string;
17
19
  static extractPart(obj: any, propertyPath: string): any;
18
20
  assignAllScripts(source: string, javascriptCode: string, shadowRoot: ShadowRoot, instance: HTMLElement, assignExternalScript?: (element: Element, event: string, scriptData: any) => void): Promise<VisualisationElementScript>;
19
21
  }
@@ -31,32 +31,32 @@ export class ScriptSystem {
31
31
  }
32
32
  case 'ToggleSignalValue': {
33
33
  const signal = await this.getValue(command.signal, context);
34
- let state = await this._visualizationHandler.getState(signal);
35
- await this._visualizationHandler.setState(signal, !state?.val);
34
+ let state = await this._visualizationHandler.getState(this.getSignaName(signal, context));
35
+ await this._visualizationHandler.setState(this.getSignaName(signal, context), !state?.val);
36
36
  break;
37
37
  }
38
38
  case 'SetSignalValue': {
39
39
  const signal = await this.getValue(command.signal, context);
40
- await this._visualizationHandler.setState(signal, await this.getValue(command.value, context));
40
+ await this._visualizationHandler.setState(this.getSignaName(signal, context), await this.getValue(command.value, context));
41
41
  break;
42
42
  }
43
43
  case 'IncrementSignalValue': {
44
44
  const signal = await this.getValue(command.signal, context);
45
- let state = await this._visualizationHandler.getState(signal);
46
- await this._visualizationHandler.setState(signal, state.val + await this.getValue(command.value, context));
45
+ let state = await this._visualizationHandler.getState(this.getSignaName(signal, context));
46
+ await this._visualizationHandler.setState(this.getSignaName(signal, context), state.val + await this.getValue(command.value, context));
47
47
  break;
48
48
  }
49
49
  case 'DecrementSignalValue': {
50
50
  const signal = await this.getValue(command.signal, context);
51
- let state = await this._visualizationHandler.getState(signal);
52
- await this._visualizationHandler.setState(signal, state.val - await this.getValue(command.value, context));
51
+ let state = await this._visualizationHandler.getState(this.getSignaName(signal, context));
52
+ await this._visualizationHandler.setState(this.getSignaName(signal, context), state.val - await this.getValue(command.value, context));
53
53
  break;
54
54
  }
55
55
  case 'CalculateSignalValue': {
56
56
  const formula = await this.getValue(command.formula, context);
57
57
  const targetSignal = await this.getValue(command.targetSignal, context);
58
58
  let parsed = parseBindingString(formula);
59
- let results = await Promise.all(parsed.signals.map(x => this._visualizationHandler.getState(x)));
59
+ let results = await Promise.all(parsed.signals.map(x => this._visualizationHandler.getState(this.getSignaName(x, context))));
60
60
  let nm = '';
61
61
  for (let i = 0; i < parsed.parts.length - 1; i++) {
62
62
  let v = results[i].val;
@@ -65,32 +65,32 @@ export class ScriptSystem {
65
65
  nm += v + parsed.parts[i + 1];
66
66
  }
67
67
  let result = eval(nm);
68
- await this._visualizationHandler.setState(targetSignal, result);
68
+ await this._visualizationHandler.setState(this.getSignaName(targetSignal, context), result);
69
69
  break;
70
70
  }
71
71
  case 'SetBitInSignal': {
72
72
  const signal = await this.getValue(command.signal, context);
73
- let state = await this._visualizationHandler.getState(signal);
73
+ let state = await this._visualizationHandler.getState(this.getSignaName(signal, context));
74
74
  let mask = Long.fromNumber(1).shiftLeft(command.bitNumber);
75
75
  const newVal = Long.fromNumber(state.val).or(mask).toNumber();
76
- await this._visualizationHandler.setState(signal, newVal);
76
+ await this._visualizationHandler.setState(this.getSignaName(signal, context), newVal);
77
77
  break;
78
78
  }
79
79
  case 'ClearBitInSignal': {
80
80
  const signal = await this.getValue(command.signal, context);
81
- let state = await this._visualizationHandler.getState(signal);
81
+ let state = await this._visualizationHandler.getState(this.getSignaName(signal, context));
82
82
  let mask = Long.fromNumber(1).shiftLeft(command.bitNumber);
83
83
  mask.negate();
84
84
  const newVal = Long.fromNumber(state.val).and(mask).toNumber();
85
- await this._visualizationHandler.setState(signal, newVal);
85
+ await this._visualizationHandler.setState(this.getSignaName(signal, context), newVal);
86
86
  break;
87
87
  }
88
88
  case 'ToggleBitInSignal': {
89
89
  const signal = await this.getValue(command.signal, context);
90
- let state = await this._visualizationHandler.getState(signal);
90
+ let state = await this._visualizationHandler.getState(this.getSignaName(signal, context));
91
91
  let mask = Long.fromNumber(1).shiftLeft(command.bitNumber);
92
92
  const newVal = Long.fromNumber(state.val).xor(mask).toNumber();
93
- await this._visualizationHandler.setState(signal, newVal);
93
+ await this._visualizationHandler.setState(this.getSignaName(signal, context), newVal);
94
94
  break;
95
95
  }
96
96
  case 'Javascript': {
@@ -138,7 +138,7 @@ export class ScriptSystem {
138
138
  return outerContext.root[value.name];
139
139
  }
140
140
  case 'signal': {
141
- let sng = await this._visualizationHandler.getState(value.name);
141
+ let sng = await this._visualizationHandler.getState(this.getSignaName(value.name, outerContext));
142
142
  return sng.val;
143
143
  }
144
144
  case 'event': {
@@ -154,6 +154,11 @@ export class ScriptSystem {
154
154
  }
155
155
  return value;
156
156
  }
157
+ getSignaName(name, outerContext) {
158
+ if (name[0] === '.')
159
+ return outerContext.relativeSignalsPath + name;
160
+ return name;
161
+ }
157
162
  static extractPart(obj, propertyPath) {
158
163
  let retVal = obj;
159
164
  for (let p of propertyPath.split('.')) {
@@ -185,7 +190,7 @@ export class ScriptSystem {
185
190
  if (script[0] == '{') {
186
191
  let scriptObj = JSON.parse(script);
187
192
  if ('commands' in scriptObj) {
188
- e.addEventListener(evtName, (evt) => this.execute(scriptObj.commands, { event: evt, element: e, root: instance, parameters: scriptObj.parameters }));
193
+ e.addEventListener(evtName, (evt) => this.execute(scriptObj.commands, { event: evt, element: e, root: instance, parameters: scriptObj.parameters, relativeSignalsPath: scriptObj.relativeSignalsPath }));
189
194
  }
190
195
  else if ('blocks' in scriptObj) {
191
196
  let compiledFunc = null;
@@ -0,0 +1,11 @@
1
+ import { BindingTarget, IBinding, IBindingService, IDesignItem } from "@node-projects/web-component-designer";
2
+ import { BindingsHelper } from "../helpers/BindingsHelper.js";
3
+ export declare class BindingsService implements IBindingService {
4
+ constructor(bindingsHelper: BindingsHelper);
5
+ private _bindingsHelper;
6
+ getBindings(designItem: IDesignItem): (IBinding & {
7
+ converter: Record<string, any>;
8
+ })[];
9
+ setBinding(designItem: IDesignItem, binding: IBinding): boolean;
10
+ clearBinding(designItem: IDesignItem, propertyName: string, propertyTarget: BindingTarget): boolean;
11
+ }
@@ -0,0 +1,46 @@
1
+ import { BindingMode, PropertiesHelper } from "@node-projects/web-component-designer";
2
+ export class BindingsService {
3
+ constructor(bindingsHelper) {
4
+ this._bindingsHelper = bindingsHelper;
5
+ }
6
+ _bindingsHelper;
7
+ getBindings(designItem) {
8
+ const iobBindings = Array.from(this._bindingsHelper.getBindings(designItem.element));
9
+ return iobBindings.map(x => ({
10
+ targetName: x[1].target == 'css' ? PropertiesHelper.camelToDashCase(x[0]) : x[0],
11
+ target: x[1].target,
12
+ mode: x[1].twoWay ? BindingMode.twoWay : BindingMode.oneWay,
13
+ invert: x[1].inverted,
14
+ bindableObjectNames: x[1].signal.split(';'),
15
+ expression: x[1].expression,
16
+ expressionTwoWay: x[1].expressionTwoWay,
17
+ converter: x[1].converter,
18
+ type: x[1].type,
19
+ changedEvents: x[1].events,
20
+ historic: x[1].historic
21
+ }));
22
+ }
23
+ setBinding(designItem, binding) {
24
+ let bnd = { signal: binding.bindableObjectNames.join(';'), target: binding.target };
25
+ bnd.inverted = binding.invert;
26
+ bnd.twoWay = binding.mode == BindingMode.twoWay;
27
+ bnd.expression = binding.expression;
28
+ bnd.expressionTwoWay = binding.expressionTwoWay;
29
+ //@ts-ignore
30
+ bnd.historic = binding.historic;
31
+ bnd.type = binding.type;
32
+ bnd.converter = binding.converters;
33
+ bnd.target = binding.target;
34
+ bnd.events = binding.changedEvents;
35
+ let serializedBnd = this._bindingsHelper.serializeBinding(designItem.element, binding.targetName, bnd);
36
+ let group = designItem.openGroup('edit_binding');
37
+ designItem.setAttribute(serializedBnd[0], serializedBnd[1]);
38
+ group.commit();
39
+ return true;
40
+ }
41
+ clearBinding(designItem, propertyName, propertyTarget) {
42
+ const name = this._bindingsHelper.getBindingAttributeName(designItem.element, propertyName, propertyTarget);
43
+ designItem.removeAttribute(name);
44
+ return true;
45
+ }
46
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "description": "web-component-designer addon for visualizations",
3
3
  "name": "@node-projects/web-component-designer-visualization-addons",
4
- "version": "0.1.18",
4
+ "version": "0.1.20",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "author": "jochen.kuehner@gmx.de",