@eclipse-glsp/client 1.0.0 → 1.1.0-RC01

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.
Files changed (51) hide show
  1. package/lib/base/types.d.ts +2 -0
  2. package/lib/base/types.d.ts.map +1 -1
  3. package/lib/features/layout/di.config.d.ts.map +1 -1
  4. package/lib/features/layout/di.config.js +2 -0
  5. package/lib/features/layout/di.config.js.map +1 -1
  6. package/lib/features/layout/hbox-layout.d.ts +1 -1
  7. package/lib/features/layout/hbox-layout.d.ts.map +1 -1
  8. package/lib/features/layout/hbox-layout.js +19 -7
  9. package/lib/features/layout/hbox-layout.js.map +1 -1
  10. package/lib/features/layout/layouter.d.ts +37 -0
  11. package/lib/features/layout/layouter.d.ts.map +1 -0
  12. package/lib/features/layout/layouter.js +131 -0
  13. package/lib/features/layout/layouter.js.map +1 -0
  14. package/lib/features/layout/tests/freeform-layout.spec.d.ts +3 -0
  15. package/lib/features/layout/tests/freeform-layout.spec.d.ts.map +1 -0
  16. package/lib/features/layout/tests/freeform-layout.spec.js +201 -0
  17. package/lib/features/layout/tests/freeform-layout.spec.js.map +1 -0
  18. package/lib/features/layout/tests/hbox-layout.spec.d.ts +3 -0
  19. package/lib/features/layout/tests/hbox-layout.spec.d.ts.map +1 -0
  20. package/lib/features/layout/tests/hbox-layout.spec.js +161 -0
  21. package/lib/features/layout/tests/hbox-layout.spec.js.map +1 -0
  22. package/lib/features/layout/tests/layouter-test-util.d.ts +34 -0
  23. package/lib/features/layout/tests/layouter-test-util.d.ts.map +1 -0
  24. package/lib/features/layout/tests/layouter-test-util.js +96 -0
  25. package/lib/features/layout/tests/layouter-test-util.js.map +1 -0
  26. package/lib/features/layout/tests/vbox-layout.spec.d.ts +3 -0
  27. package/lib/features/layout/tests/vbox-layout.spec.d.ts.map +1 -0
  28. package/lib/features/layout/tests/vbox-layout.spec.js +161 -0
  29. package/lib/features/layout/tests/vbox-layout.spec.js.map +1 -0
  30. package/lib/features/layout/vbox-layout.d.ts +1 -1
  31. package/lib/features/layout/vbox-layout.d.ts.map +1 -1
  32. package/lib/features/layout/vbox-layout.js +17 -5
  33. package/lib/features/layout/vbox-layout.js.map +1 -1
  34. package/lib/sprotty-reexport.d.ts +1 -1
  35. package/lib/sprotty-reexport.d.ts.map +1 -1
  36. package/lib/sprotty-reexport.js +6 -4
  37. package/lib/sprotty-reexport.js.map +1 -1
  38. package/lib/views/glsp-projection-view.d.ts.map +1 -1
  39. package/lib/views/glsp-projection-view.js +8 -2
  40. package/lib/views/glsp-projection-view.js.map +1 -1
  41. package/package.json +6 -5
  42. package/src/features/layout/di.config.ts +3 -1
  43. package/src/features/layout/hbox-layout.ts +24 -7
  44. package/src/features/layout/layouter.ts +137 -0
  45. package/src/features/layout/tests/freeform-layout.spec.ts +216 -0
  46. package/src/features/layout/tests/hbox-layout.spec.ts +171 -0
  47. package/src/features/layout/tests/layouter-test-util.ts +122 -0
  48. package/src/features/layout/tests/vbox-layout.spec.ts +171 -0
  49. package/src/features/layout/vbox-layout.ts +22 -5
  50. package/src/sprotty-reexport.ts +6 -1
  51. package/src/views/glsp-projection-view.tsx +10 -3
@@ -0,0 +1,216 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2022 STMicroelectronics and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+ import { expect } from 'chai';
17
+ import 'mocha';
18
+ import 'reflect-metadata';
19
+ import { BoundsData, ConsoleLogger, SModelElement } from 'sprotty';
20
+ import { gModel, layout, sComp, setupLayoutRegistry, sLabel, sNode } from './layouter-test-util';
21
+
22
+ describe('FreeFormLayouter', () => {
23
+ const layoutRegistry = setupLayoutRegistry();
24
+ const log = new ConsoleLogger();
25
+ const map = new Map<SModelElement, BoundsData>();
26
+
27
+ describe('issue-610', () => {
28
+ it('recursive hGrab/vGrab', () => {
29
+ /**
30
+ * _________________________
31
+ * | Category 1 |
32
+ * | _______________________ |
33
+ * || ||
34
+ * || ||
35
+ * || ||
36
+ * || ||
37
+ * ||_______________________||
38
+ * | _______________________ |
39
+ * ||_left____________right_||
40
+ * |_________________________|
41
+ *
42
+ * This test case checks recursive hGrab/vGrab functionality of nested compartments
43
+ * See also issue 610 for details and an example model https://github.com/eclipse-glsp/glsp/issues/610.
44
+ */
45
+ const model = gModel();
46
+ const category = sNode('category', 'vbox', { width: 410.0, height: 215.0 }, undefined, {
47
+ vGrab: false,
48
+ hGrab: false,
49
+ hAlign: 'center',
50
+ prefWidth: 410.0,
51
+ prefHeight: 215.0
52
+ });
53
+ const headerComp = sComp('comp:header', 'hbox');
54
+ headerComp.children = [sLabel('Category 1')];
55
+ const childContainer = sComp('struct', 'freeform', { hGrab: true, vGrab: true });
56
+ const labelContainer = sComp('struct', 'hbox', { hGrab: true });
57
+ labelContainer.children = [sLabel('left text', { hGrab: true }), sLabel('right text')];
58
+ category.children = [headerComp, childContainer, labelContainer];
59
+
60
+ model.add(category);
61
+ layout(layoutRegistry, log, map, model);
62
+ // check category
63
+ expect(map.get(category)!.bounds).to.deep.equal({ x: 0, y: 0, width: 410.0, height: 215.0 });
64
+ // check header compartment
65
+ expect(map.get(category.children[0])!.bounds).to.deep.equal({ x: 0, y: 0, width: -1, height: -1 });
66
+ // check child freeform compartment
67
+ expect(map.get(category.children[1])!.bounds).to.deep.equal({ x: 5, y: 5, width: 400.0, height: 205.0 });
68
+ // check label compartment
69
+ expect(map.get(category.children[2])!.bounds).to.deep.equal({ x: 0, y: 0, width: -1, height: -1 });
70
+ });
71
+ });
72
+
73
+ describe('issue-694', () => {
74
+ it('Structure compartment (hGrab=true, vGrab=true), Left-aligned label (hGrab=true), right-aligned label (hGrab=false)', () => {
75
+ /**
76
+ * _________________________
77
+ * | Category 2 |
78
+ * | _______________________ |
79
+ * || ||
80
+ * || ||
81
+ * || Task node ||
82
+ * || ||
83
+ * ||_______________________||
84
+ * | _______________________ |
85
+ * ||_left____________right_||
86
+ * |_________________________|
87
+ */
88
+ const model = gModel();
89
+ const category = sNode('category', 'vbox', { width: 500.0, height: 375.0 }, undefined, {
90
+ vGrab: false,
91
+ hGrab: false,
92
+ hAlign: 'center',
93
+ prefWidth: 500.0,
94
+ prefHeight: 375.0
95
+ });
96
+ const headerComp = sComp('comp:header', 'hbox');
97
+ headerComp.children = [sLabel('Category 2')];
98
+ const childContainer = sComp('struct', 'freeform', { hGrab: true, vGrab: true });
99
+ const childNode = sNode('task', 'hbox', undefined, { x: 170, y: 190 });
100
+ childNode.children = [sLabel('Task node', undefined, { x: 5.0, y: 5.0 }, { width: 25.0, height: 20.0 })];
101
+ childContainer.children = [childNode];
102
+ const labelContainer = sComp('struct', 'hbox', { hGrab: true });
103
+ labelContainer.children = [sLabel('left text', { hGrab: true }), sLabel('right text')];
104
+ category.children = [headerComp, childContainer, labelContainer];
105
+
106
+ model.add(category);
107
+
108
+ // layout graph
109
+ layout(layoutRegistry, log, map, model);
110
+ // check category
111
+ expect(map.get(category)!.bounds).to.deep.equal({ x: 0, y: 0, width: 500.0, height: 375.0 });
112
+ // check header compartment
113
+ expect(map.get(category.children[0])!.bounds).to.deep.equal({ x: 0, y: 0, width: -1, height: -1 });
114
+ // check child freeform compartment
115
+ expect(map.get(category.children[1])!.bounds).to.deep.equal({ x: 5.0, y: 5.0, width: 490.0, height: 365.0 });
116
+ // check child task node
117
+ expect(map.get(category.children[1].children[0])!.bounds).to.deep.equal({ x: 170.0, y: 190.0, width: 35.0, height: 30.0 });
118
+ // check label compartment
119
+ expect(map.get(category.children[2])!.bounds).to.deep.equal({ x: 0, y: 0, width: -1, height: -1 });
120
+ });
121
+
122
+ it('Structure compartment (hGrab=true, vGrab=true)', () => {
123
+ /**
124
+ * _________________________
125
+ * | Category 2 |
126
+ * | _______________________ |
127
+ * || ||
128
+ * || Task node ||
129
+ * || ||
130
+ * || ||
131
+ * ||_______________________||
132
+ * |_________________________|
133
+ */
134
+ const model = gModel();
135
+ const category = sNode('category', 'vbox', { width: 500.0, height: 375.0 }, undefined, {
136
+ vGrab: false,
137
+ hGrab: false,
138
+ hAlign: 'center',
139
+ prefWidth: 500.0,
140
+ prefHeight: 375.0
141
+ });
142
+ const headerComp = sComp('comp:header', 'hbox');
143
+ headerComp.children = [sLabel('Category 2')];
144
+ const childContainer = sComp('struct', 'freeform', { hGrab: true, vGrab: true });
145
+ const childNode = sNode('task', 'hbox', undefined, { x: 55, y: 15 });
146
+ childNode.children = [sLabel('Task node', undefined, undefined, { width: 50.0, height: 35.0 })];
147
+ childContainer.children = [childNode];
148
+ category.children = [headerComp, childContainer];
149
+
150
+ model.add(category);
151
+
152
+ // layout graph
153
+ layout(layoutRegistry, log, map, model);
154
+ // check category
155
+ expect(map.get(category)!.bounds).to.deep.equal({ x: 0, y: 0, width: 500.0, height: 375.0 });
156
+ // check header compartment
157
+ expect(map.get(category.children[0])!.bounds).to.deep.equal({ x: 0, y: 0, width: -1, height: -1 });
158
+ // check child freeform compartment
159
+ expect(map.get(category.children[1])!.bounds).to.deep.equal({ x: 5.0, y: 5.0, width: 490.0, height: 365.0 });
160
+ // check child task node
161
+ expect(map.get(category.children[1].children[0])!.bounds).to.deep.equal({ x: 55.0, y: 15.0, width: 60.0, height: 45.0 });
162
+ });
163
+
164
+ it('Structure compartment (hGrab=true, vGrab=true, padding*=10)', () => {
165
+ /**
166
+ * _________________________
167
+ * | Category 2 |
168
+ * | _______________________ |
169
+ * || ||
170
+ * || Task node ||
171
+ * || ||
172
+ * || ||
173
+ * ||_______________________||
174
+ * |_________________________|
175
+ */
176
+ const model = gModel();
177
+ const category = sNode('category', 'vbox', { width: 500.0, height: 375.0 }, undefined, {
178
+ vGrab: false,
179
+ hGrab: false,
180
+ hAlign: 'center',
181
+ prefWidth: 500.0,
182
+ prefHeight: 375.0,
183
+ paddingLeft: 10,
184
+ paddingRight: 10,
185
+ paddingTop: 10,
186
+ paddingBottom: 10
187
+ });
188
+ const headerComp = sComp('comp:header', 'hbox');
189
+ headerComp.children = [sLabel('Category 2')];
190
+ const childContainer = sComp('struct', 'freeform', { hGrab: true, vGrab: true });
191
+ const childNode = sNode(
192
+ 'task',
193
+ 'hbox',
194
+ undefined,
195
+ { x: 55, y: 15 },
196
+ { paddingLeft: 10, paddingRight: 10, paddingTop: 10, paddingBottom: 10 }
197
+ );
198
+ childNode.children = [sLabel('Task node', undefined, undefined, { width: 50.0, height: 35.0 })];
199
+ childContainer.children = [childNode];
200
+ category.children = [headerComp, childContainer];
201
+
202
+ model.add(category);
203
+
204
+ // layout graph
205
+ layout(layoutRegistry, log, map, model);
206
+ // check category
207
+ expect(map.get(category)!.bounds).to.deep.equal({ x: 0, y: 0, width: 500.0, height: 375.0 });
208
+ // check header compartment
209
+ expect(map.get(category.children[0])!.bounds).to.deep.equal({ x: 0, y: 0, width: -1, height: -1 });
210
+ // check child freeform compartment
211
+ expect(map.get(category.children[1])!.bounds).to.deep.equal({ x: 10.0, y: 10.0, width: 480.0, height: 355.0 });
212
+ // check child task node
213
+ expect(map.get(category.children[1].children[0])!.bounds).to.deep.equal({ x: 55.0, y: 15.0, width: 70.0, height: 55.0 });
214
+ });
215
+ });
216
+ });
@@ -0,0 +1,171 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2022 TypeFox, STMicroelectronics and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+ /* eslint-disable deprecation/deprecation */
17
+ import { Dimension } from '@eclipse-glsp/protocol';
18
+ import { expect } from 'chai';
19
+ import 'mocha';
20
+ import 'reflect-metadata';
21
+ import { BoundsData, ConsoleLogger, SModelElement, SNode } from 'sprotty';
22
+ import { layout, setupLayoutRegistry, sLabel, sNode } from './layouter-test-util';
23
+
24
+ describe('HBoxLayouter', () => {
25
+ const layoutRegistry = setupLayoutRegistry();
26
+ const log = new ConsoleLogger();
27
+ const map = new Map<SModelElement, BoundsData>();
28
+
29
+ function createModel(): SNode {
30
+ const model = sNode('node', undefined, Dimension.EMPTY);
31
+ model.children = [
32
+ sLabel('label1', undefined, undefined, { width: 1, height: 2 }),
33
+ sLabel('label2', undefined, undefined, { width: 2, height: 1 }),
34
+ sLabel('label3', undefined, undefined, { width: 3, height: 3 })
35
+ ];
36
+ model.layout = 'hbox';
37
+ return model;
38
+ }
39
+
40
+ it('defaultParams', () => {
41
+ const model = createModel();
42
+ layout(layoutRegistry, log, map, model);
43
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 18, height: 13 });
44
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 5, y: 5.5, width: 1, height: 2 });
45
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 7, y: 6, width: 2, height: 1 });
46
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 10, y: 5, width: 3, height: 3 });
47
+ });
48
+
49
+ it('alignTop', () => {
50
+ const model = createModel();
51
+ model.layoutOptions = {
52
+ vAlign: 'top'
53
+ };
54
+ layout(layoutRegistry, log, map, model);
55
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 18, height: 13 });
56
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 5, y: 5, width: 1, height: 2 });
57
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 7, y: 5, width: 2, height: 1 });
58
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 10, y: 5, width: 3, height: 3 });
59
+ });
60
+
61
+ it('alignCenter', () => {
62
+ const model = createModel();
63
+ model.layoutOptions = {
64
+ vAlign: 'center'
65
+ };
66
+ layout(layoutRegistry, log, map, model);
67
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 18, height: 13 });
68
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 5, y: 5.5, width: 1, height: 2 });
69
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 7, y: 6, width: 2, height: 1 });
70
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 10, y: 5, width: 3, height: 3 });
71
+ });
72
+
73
+ it('alignBottom', () => {
74
+ const model = createModel();
75
+ model.layoutOptions = {
76
+ vAlign: 'bottom'
77
+ };
78
+ layout(layoutRegistry, log, map, model);
79
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 18, height: 13 });
80
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 5, y: 6, width: 1, height: 2 });
81
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 7, y: 7, width: 2, height: 1 });
82
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 10, y: 5, width: 3, height: 3 });
83
+ });
84
+
85
+ it('padding', () => {
86
+ const model = createModel();
87
+ model.layoutOptions = {
88
+ paddingTop: 7,
89
+ paddingBottom: 8,
90
+ paddingLeft: 9,
91
+ paddingRight: 10
92
+ };
93
+ layout(layoutRegistry, log, map, model);
94
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 27, height: 18 });
95
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 9, y: 7.5, width: 1, height: 2 });
96
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 11, y: 8, width: 2, height: 1 });
97
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 14, y: 7, width: 3, height: 3 });
98
+ });
99
+
100
+ it('hGap', () => {
101
+ const model = createModel();
102
+ model.layoutOptions = {
103
+ hGap: 4
104
+ };
105
+ layout(layoutRegistry, log, map, model);
106
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 24, height: 13 });
107
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 5, y: 5.5, width: 1, height: 2 });
108
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 10, y: 6, width: 2, height: 1 });
109
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 16, y: 5, width: 3, height: 3 });
110
+ });
111
+
112
+ it('paddingFactor', () => {
113
+ const model = createModel();
114
+ model.layoutOptions = {
115
+ paddingFactor: 2
116
+ };
117
+ layout(layoutRegistry, log, map, model);
118
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 18, height: 13 });
119
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 9, y: 8.5, width: 1, height: 2 });
120
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 11, y: 9, width: 2, height: 1 });
121
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 14, y: 8, width: 3, height: 3 });
122
+ });
123
+
124
+ it('minWidth', () => {
125
+ const model = createModel();
126
+ model.layoutOptions = {
127
+ minWidth: 25
128
+ };
129
+ layout(layoutRegistry, log, map, model);
130
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 25, height: 13 });
131
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 5, y: 5.5, width: 1, height: 2 });
132
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 7, y: 6, width: 2, height: 1 });
133
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 10, y: 5, width: 3, height: 3 });
134
+ });
135
+
136
+ it('minHeight', () => {
137
+ const model = createModel();
138
+ model.layoutOptions = {
139
+ minHeight: 25
140
+ };
141
+ layout(layoutRegistry, log, map, model);
142
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 18, height: 25 });
143
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 5, y: 11.5, width: 1, height: 2 });
144
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 7, y: 12, width: 2, height: 1 });
145
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 10, y: 11, width: 3, height: 3 });
146
+ });
147
+
148
+ it('prefWidth', () => {
149
+ const model = createModel();
150
+ model.layoutOptions = {
151
+ prefWidth: 20
152
+ };
153
+ layout(layoutRegistry, log, map, model);
154
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 20, height: 13 });
155
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 5, y: 5.5, width: 1, height: 2 });
156
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 7, y: 6, width: 2, height: 1 });
157
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 10, y: 5, width: 3, height: 3 });
158
+ });
159
+
160
+ it('prefHeight', () => {
161
+ const model = createModel();
162
+ model.layoutOptions = {
163
+ prefHeight: 20
164
+ };
165
+ layout(layoutRegistry, log, map, model);
166
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 18, height: 20 });
167
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 5, y: 9, width: 1, height: 2 });
168
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 7, y: 9.5, width: 2, height: 1 });
169
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 10, y: 8.5, width: 3, height: 3 });
170
+ });
171
+ });
@@ -0,0 +1,122 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2022 STMicroelectronics and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+
17
+ import { Dimension, Point } from '@eclipse-glsp/protocol';
18
+ import 'mocha';
19
+ import 'reflect-metadata';
20
+ import {
21
+ BoundsData,
22
+ ConsoleLogger,
23
+ createFeatureSet,
24
+ layoutableChildFeature,
25
+ LayoutRegistry,
26
+ SCompartment,
27
+ SLabel,
28
+ SModelElement,
29
+ SNode,
30
+ SParentElement,
31
+ TYPES
32
+ } from 'sprotty';
33
+ import { createClientContainer } from '../../../base/container-modules';
34
+ import { GLSPGraph } from '../../../lib/model';
35
+ import { StatefulLayouterExt } from '../layouter';
36
+
37
+ export function gModel(): GLSPGraph {
38
+ return new GLSPGraph();
39
+ }
40
+
41
+ export function sNode(
42
+ type: string,
43
+ nodeLayout?: string,
44
+ size?: Dimension,
45
+ position?: Point,
46
+ layoutOptions?: { [key: string]: string | number | boolean }
47
+ ): SNode {
48
+ const node = new SNode();
49
+ node.features = createFeatureSet(SNode.DEFAULT_FEATURES, { enable: [layoutableChildFeature] });
50
+ node.position = position || {
51
+ x: 0,
52
+ y: 0
53
+ };
54
+ if (size) {
55
+ node.size = size;
56
+ }
57
+ node.type = type;
58
+ if (nodeLayout) {
59
+ node.layout = nodeLayout;
60
+ }
61
+ node.layoutOptions = layoutOptions;
62
+ return node;
63
+ }
64
+
65
+ export function sComp(type: string, compLayout: string, layoutOptions?: { [key: string]: string | number | boolean }): SCompartment {
66
+ const comp = new SCompartment();
67
+ comp.features = createFeatureSet(SCompartment.DEFAULT_FEATURES);
68
+ comp.type = type;
69
+ comp.layout = compLayout;
70
+ comp.layoutOptions = layoutOptions;
71
+ return comp;
72
+ }
73
+
74
+ export function sLabel(
75
+ labelText: string,
76
+ layoutOptions?: { [key: string]: string | number | boolean },
77
+ position?: Point,
78
+ size?: Dimension
79
+ ): SLabel {
80
+ const label = new SLabel();
81
+ label.features = createFeatureSet(SLabel.DEFAULT_FEATURES);
82
+ if (position) {
83
+ label.position = position;
84
+ }
85
+ if (size) {
86
+ label.size = size;
87
+ }
88
+ label.layoutOptions = layoutOptions;
89
+ label.text = labelText;
90
+ label.type = 'label';
91
+ return label;
92
+ }
93
+
94
+ export function addToMap(map: Map<SModelElement, BoundsData>, element: SModelElement): void {
95
+ map.set(element, {
96
+ bounds: (element as any).bounds,
97
+ boundsChanged: true,
98
+ alignmentChanged: true
99
+ });
100
+ if (element instanceof SParentElement) {
101
+ element.children.forEach(c => addToMap(map, c));
102
+ }
103
+ }
104
+
105
+ export function layout(
106
+ layoutRegistry: LayoutRegistry,
107
+ log: ConsoleLogger,
108
+ map: Map<SModelElement, BoundsData>,
109
+ model: SNode | GLSPGraph
110
+ ): void {
111
+ map.clear();
112
+ addToMap(map, model);
113
+ const layouter = new StatefulLayouterExt(map, layoutRegistry, log);
114
+ layouter.layout();
115
+ }
116
+
117
+ export function setupLayoutRegistry(): LayoutRegistry {
118
+ // Generic Test setup
119
+ // create client container that registers all default modules including the layoutModule
120
+ const layoutContainer = createClientContainer();
121
+ return layoutContainer.get<LayoutRegistry>(TYPES.LayoutRegistry);
122
+ }
@@ -0,0 +1,171 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2022 TypeFox, STMicroelectronics and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the Eclipse Public License v. 2.0 which is available at
6
+ * http://www.eclipse.org/legal/epl-2.0.
7
+ *
8
+ * This Source Code may also be made available under the following Secondary
9
+ * Licenses when the conditions for such availability set forth in the Eclipse
10
+ * Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ * with the GNU Classpath Exception which is available at
12
+ * https://www.gnu.org/software/classpath/license.html.
13
+ *
14
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ ********************************************************************************/
16
+ /* eslint-disable deprecation/deprecation */
17
+ import { Dimension } from '@eclipse-glsp/protocol';
18
+ import { expect } from 'chai';
19
+ import 'mocha';
20
+ import 'reflect-metadata';
21
+ import { BoundsData, ConsoleLogger, SModelElement, SNode } from 'sprotty';
22
+ import { layout, setupLayoutRegistry, sLabel, sNode } from './layouter-test-util';
23
+
24
+ describe('VBoxLayouter', () => {
25
+ const layoutRegistry = setupLayoutRegistry();
26
+ const log = new ConsoleLogger();
27
+ const map = new Map<SModelElement, BoundsData>();
28
+
29
+ function createModel(): SNode {
30
+ const model = sNode('node', undefined, Dimension.EMPTY);
31
+ model.children = [
32
+ sLabel('label1', undefined, undefined, { width: 1, height: 2 }),
33
+ sLabel('label2', undefined, undefined, { width: 2, height: 1 }),
34
+ sLabel('label3', undefined, undefined, { width: 3, height: 3 })
35
+ ];
36
+ model.layout = 'vbox';
37
+ return model;
38
+ }
39
+
40
+ it('defaultParams', () => {
41
+ const model = createModel();
42
+ layout(layoutRegistry, log, map, model);
43
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 13, height: 18 });
44
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 6, y: 5, width: 1, height: 2 });
45
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 5.5, y: 8, width: 2, height: 1 });
46
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 5, y: 10, width: 3, height: 3 });
47
+ });
48
+
49
+ it('alignLeft', () => {
50
+ const model = createModel();
51
+ model.layoutOptions = {
52
+ hAlign: 'left'
53
+ };
54
+ layout(layoutRegistry, log, map, model);
55
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 13, height: 18 });
56
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 5, y: 5, width: 1, height: 2 });
57
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 5, y: 8, width: 2, height: 1 });
58
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 5, y: 10, width: 3, height: 3 });
59
+ });
60
+
61
+ it('alignCenter', () => {
62
+ const model = createModel();
63
+ model.layoutOptions = {
64
+ hAlign: 'center'
65
+ };
66
+ layout(layoutRegistry, log, map, model);
67
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 13, height: 18 });
68
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 6, y: 5, width: 1, height: 2 });
69
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 5.5, y: 8, width: 2, height: 1 });
70
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 5, y: 10, width: 3, height: 3 });
71
+ });
72
+
73
+ it('alignRight', () => {
74
+ const model = createModel();
75
+ model.layoutOptions = {
76
+ hAlign: 'right'
77
+ };
78
+ layout(layoutRegistry, log, map, model);
79
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 13, height: 18 });
80
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 7, y: 5, width: 1, height: 2 });
81
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 6, y: 8, width: 2, height: 1 });
82
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 5, y: 10, width: 3, height: 3 });
83
+ });
84
+
85
+ it('padding', () => {
86
+ const model = createModel();
87
+ model.layoutOptions = {
88
+ paddingTop: 7,
89
+ paddingBottom: 8,
90
+ paddingLeft: 9,
91
+ paddingRight: 10
92
+ };
93
+ layout(layoutRegistry, log, map, model);
94
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 22, height: 23 });
95
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 10, y: 7, width: 1, height: 2 });
96
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 9.5, y: 10, width: 2, height: 1 });
97
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 9, y: 12, width: 3, height: 3 });
98
+ });
99
+
100
+ it('vGap', () => {
101
+ const model = createModel();
102
+ model.layoutOptions = {
103
+ vGap: 4
104
+ };
105
+ layout(layoutRegistry, log, map, model);
106
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 13, height: 24 });
107
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 6, y: 5, width: 1, height: 2 });
108
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 5.5, y: 11, width: 2, height: 1 });
109
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 5, y: 16, width: 3, height: 3 });
110
+ });
111
+
112
+ it('paddingFactor', () => {
113
+ const model = createModel();
114
+ model.layoutOptions = {
115
+ paddingFactor: 2
116
+ };
117
+ layout(layoutRegistry, log, map, model);
118
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 13, height: 18 });
119
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 9, y: 9, width: 1, height: 2 });
120
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 8.5, y: 12, width: 2, height: 1 });
121
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 8, y: 14, width: 3, height: 3 });
122
+ });
123
+
124
+ it('minWidth', () => {
125
+ const model = createModel();
126
+ model.layoutOptions = {
127
+ minWidth: 25
128
+ };
129
+ layout(layoutRegistry, log, map, model);
130
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 25, height: 18 });
131
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 12, y: 5, width: 1, height: 2 });
132
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 11.5, y: 8, width: 2, height: 1 });
133
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 11, y: 10, width: 3, height: 3 });
134
+ });
135
+
136
+ it('minHeight', () => {
137
+ const model = createModel();
138
+ model.layoutOptions = {
139
+ minHeight: 25
140
+ };
141
+ layout(layoutRegistry, log, map, model);
142
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 13, height: 25 });
143
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 6, y: 5, width: 1, height: 2 });
144
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 5.5, y: 8, width: 2, height: 1 });
145
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 5, y: 10, width: 3, height: 3 });
146
+ });
147
+
148
+ it('prefWidth', () => {
149
+ const model = createModel();
150
+ model.layoutOptions = {
151
+ prefWidth: 20
152
+ };
153
+ layout(layoutRegistry, log, map, model);
154
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 20, height: 18 });
155
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 9.5, y: 5, width: 1, height: 2 });
156
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 9, y: 8, width: 2, height: 1 });
157
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 8.5, y: 10, width: 3, height: 3 });
158
+ });
159
+
160
+ it('prefHeight', () => {
161
+ const model = createModel();
162
+ model.layoutOptions = {
163
+ prefHeight: 20
164
+ };
165
+ layout(layoutRegistry, log, map, model);
166
+ expect(map.get(model)!.bounds).to.deep.equal({ x: 0, y: 0, width: 13, height: 20 });
167
+ expect(map.get(model.children[0])!.bounds).to.deep.equal({ x: 6, y: 5, width: 1, height: 2 });
168
+ expect(map.get(model.children[1])!.bounds).to.deep.equal({ x: 5.5, y: 8, width: 2, height: 1 });
169
+ expect(map.get(model.children[2])!.bounds).to.deep.equal({ x: 5, y: 10, width: 3, height: 3 });
170
+ });
171
+ });