dock-spawn-ts 3.19.0 → 3.21.0
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.
- package/lib/js/DockManager.js +0 -2
- package/lib/js/DockManager.js.map +1 -1
- package/lib/js/SplitterPanel.d.ts +6 -0
- package/lib/js/SplitterPanel.js +90 -23
- package/lib/js/SplitterPanel.js.map +1 -1
- package/lib/js/index-min.js +3 -3
- package/lib/js/index-webcomponent-min.js +4 -4
- package/package.json +1 -1
- package/src/DockManager.ts +4 -6
- package/src/ResizableContainer.ts +14 -14
- package/src/SplitterPanel.ts +169 -92
package/src/SplitterPanel.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { SplitterBar } from "./SplitterBar.js";
|
|
2
|
-
import { Utils } from "./Utils.js";
|
|
3
|
-
import {
|
|
1
|
+
import { SplitterBar } from "./SplitterBar.js";
|
|
2
|
+
import { Utils } from "./Utils.js";
|
|
3
|
+
import { ContainerType } from "./ContainerType.js";
|
|
4
|
+
import { IDockContainer } from "./interfaces/IDockContainer.js";
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* A splitter panel manages the child containers inside it with splitter bars.
|
|
@@ -8,9 +9,11 @@ import { IDockContainer } from "./interfaces/IDockContainer.js";
|
|
|
8
9
|
*/
|
|
9
10
|
export class SplitterPanel {
|
|
10
11
|
panelElement: HTMLDivElement;
|
|
11
|
-
spiltterBars: SplitterBar[];
|
|
12
|
-
stackedVertical: boolean;
|
|
13
|
-
childContainers: IDockContainer[];
|
|
12
|
+
spiltterBars: SplitterBar[];
|
|
13
|
+
stackedVertical: boolean;
|
|
14
|
+
childContainers: IDockContainer[];
|
|
15
|
+
private preferredChildSizes = new WeakMap<IDockContainer, number>();
|
|
16
|
+
private preserveNonElasticSizes = false;
|
|
14
17
|
|
|
15
18
|
constructor(childContainers: IDockContainer[], stackedVertical: boolean) {
|
|
16
19
|
this.childContainers = childContainers;
|
|
@@ -45,10 +48,15 @@ export class SplitterPanel {
|
|
|
45
48
|
|
|
46
49
|
performLayout(children: IDockContainer[], relayoutEvenIfEqual: boolean) {
|
|
47
50
|
let containersEqual = Utils.arrayEqual(this.childContainers, children);
|
|
48
|
-
if (!containersEqual || relayoutEvenIfEqual) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
51
|
+
if (!containersEqual || relayoutEvenIfEqual) {
|
|
52
|
+
if (!relayoutEvenIfEqual) {
|
|
53
|
+
this.preferredChildSizes = new WeakMap<IDockContainer, number>();
|
|
54
|
+
this.preserveNonElasticSizes = false;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.childContainers.forEach((container) => {
|
|
58
|
+
if (!children.some((item) => item == container)) {
|
|
59
|
+
if (container.containerElement) {
|
|
52
60
|
container.containerElement.classList.remove('splitter-container-vertical');
|
|
53
61
|
container.containerElement.classList.remove('splitter-container-horizontal');
|
|
54
62
|
Utils.removeNode(container.containerElement);
|
|
@@ -123,12 +131,14 @@ export class SplitterPanel {
|
|
|
123
131
|
else
|
|
124
132
|
size = newContainerSize;
|
|
125
133
|
|
|
126
|
-
if (this.stackedVertical)
|
|
127
|
-
child.resize(child.width, Math.floor(size));
|
|
128
|
-
else
|
|
129
|
-
child.resize(Math.floor(size), child.height);
|
|
130
|
-
|
|
131
|
-
|
|
134
|
+
if (this.stackedVertical)
|
|
135
|
+
child.resize(child.width, Math.floor(size));
|
|
136
|
+
else
|
|
137
|
+
child.resize(Math.floor(size), child.height);
|
|
138
|
+
this.preferredChildSizes.set(child, Math.floor(size));
|
|
139
|
+
}
|
|
140
|
+
this.preserveNonElasticSizes = this.hasElasticChild();
|
|
141
|
+
}
|
|
132
142
|
|
|
133
143
|
getRatios(): number[] {
|
|
134
144
|
let barSize = this.stackedVertical ? this.spiltterBars[0].barElement.clientHeight : this.spiltterBars[0].barElement.clientWidth;
|
|
@@ -153,80 +163,147 @@ export class SplitterPanel {
|
|
|
153
163
|
// Fix rounding error on last child so panels fill the available space exactly
|
|
154
164
|
if (i === this.childContainers.length - 1)
|
|
155
165
|
size += splitPanelSize - updatedTotalSize;
|
|
156
|
-
if (this.stackedVertical)
|
|
157
|
-
child.resize(child.width, size);
|
|
158
|
-
else
|
|
159
|
-
child.resize(size, child.height);
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (this.childContainers.length <= 1)
|
|
165
|
-
return;
|
|
166
|
-
|
|
167
|
-
this.panelElement.style.width = width + 'px';
|
|
168
|
-
this.panelElement.style.height = height + 'px';
|
|
169
|
-
|
|
170
|
-
let i;
|
|
171
|
-
|
|
172
|
-
// Adjust the fixed dimension that is common to all (i.e. width, if stacked vertical; height, if stacked horizontally)
|
|
173
|
-
for (i = 0; i < this.childContainers.length; i++) {
|
|
174
|
-
let childContainer = this.childContainers[i];
|
|
175
|
-
if (this.stackedVertical)
|
|
176
|
-
childContainer.resize(width, !childContainer.height ? height : childContainer.height);
|
|
177
|
-
else
|
|
178
|
-
childContainer.resize(!childContainer.width ? width : childContainer.width, height);
|
|
179
|
-
|
|
180
|
-
if (i < this.spiltterBars.length) {
|
|
181
|
-
let splitBar = this.spiltterBars[i];
|
|
182
|
-
if (this.stackedVertical)
|
|
183
|
-
splitBar.barElement.style.width = width + 'px';
|
|
184
|
-
else
|
|
185
|
-
splitBar.barElement.style.height = height + 'px';
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Adjust the varying dimension
|
|
190
|
-
let totalChildPanelSize = 0;
|
|
191
|
-
// Find out how much space existing child containers take up (excluding the splitter bars)
|
|
192
|
-
this.childContainers.forEach((container) => {
|
|
193
|
-
let size = this.stackedVertical ?
|
|
194
|
-
container.height :
|
|
195
|
-
container.width;
|
|
196
|
-
totalChildPanelSize += size;
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
// Get the thickness of the bar
|
|
200
|
-
let barSize = this.stackedVertical ? this.spiltterBars[0].barElement.clientHeight : this.spiltterBars[0].barElement.clientWidth;
|
|
201
|
-
|
|
202
|
-
// Find out how much space existing child containers will take after being resized (excluding the splitter bars)
|
|
203
|
-
let targetTotalChildPanelSize = this.stackedVertical ? height : width;
|
|
204
|
-
targetTotalChildPanelSize -= barSize * this.spiltterBars.length;
|
|
205
|
-
|
|
206
|
-
// Get the scale multiplier
|
|
207
|
-
totalChildPanelSize = Math.max(totalChildPanelSize, 1);
|
|
208
|
-
let scaleMultiplier = targetTotalChildPanelSize / totalChildPanelSize;
|
|
166
|
+
if (this.stackedVertical)
|
|
167
|
+
child.resize(child.width, size);
|
|
168
|
+
else
|
|
169
|
+
child.resize(size, child.height);
|
|
170
|
+
this.preferredChildSizes.set(child, size);
|
|
171
|
+
}
|
|
172
|
+
this.preserveNonElasticSizes = this.hasElasticChild();
|
|
173
|
+
}
|
|
209
174
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
175
|
+
resize(width: number, height: number) {
|
|
176
|
+
if (this.childContainers.length <= 1)
|
|
177
|
+
return;
|
|
178
|
+
|
|
179
|
+
this.panelElement.style.width = width + 'px';
|
|
180
|
+
this.panelElement.style.height = height + 'px';
|
|
181
|
+
|
|
182
|
+
for (let i = 0; i < this.childContainers.length; i++) {
|
|
183
|
+
if (i < this.spiltterBars.length) {
|
|
184
|
+
let splitBar = this.spiltterBars[i];
|
|
185
|
+
if (this.stackedVertical)
|
|
186
|
+
splitBar.barElement.style.width = width + 'px';
|
|
187
|
+
else
|
|
188
|
+
splitBar.barElement.style.height = height + 'px';
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
let barSize = this.stackedVertical ? this.spiltterBars[0].barElement.clientHeight : this.spiltterBars[0].barElement.clientWidth;
|
|
193
|
+
let targetTotalChildPanelSize = this.stackedVertical ? height : width;
|
|
194
|
+
targetTotalChildPanelSize -= barSize * this.spiltterBars.length;
|
|
195
|
+
|
|
196
|
+
if (!this.preserveNonElasticSizes || !this.hasElasticChild()) {
|
|
197
|
+
this.resizeProportionally(width, height, targetTotalChildPanelSize);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
let resizeIndex = this.getElasticChildIndex();
|
|
202
|
+
let childSizes = this.childContainers.map((container, index) => {
|
|
203
|
+
let currentSize = this.getChildSize(container);
|
|
204
|
+
if (index === resizeIndex)
|
|
205
|
+
return currentSize;
|
|
206
|
+
let preferredSize = this.preferredChildSizes.get(container);
|
|
207
|
+
if (preferredSize === undefined || currentSize > preferredSize)
|
|
208
|
+
preferredSize = currentSize;
|
|
209
|
+
this.preferredChildSizes.set(container, preferredSize);
|
|
210
|
+
return preferredSize;
|
|
211
|
+
});
|
|
212
|
+
let totalChildPanelSize = childSizes.reduce((sum, size) => sum + size, 0);
|
|
213
|
+
if (totalChildPanelSize <= 0) {
|
|
214
|
+
let size = targetTotalChildPanelSize / this.childContainers.length;
|
|
215
|
+
childSizes = this.childContainers.map(() => size);
|
|
216
|
+
totalChildPanelSize = targetTotalChildPanelSize;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
let sizeDelta = targetTotalChildPanelSize - totalChildPanelSize;
|
|
220
|
+
childSizes[resizeIndex] += sizeDelta;
|
|
221
|
+
if (childSizes[resizeIndex] < 0) {
|
|
222
|
+
let deficit = -childSizes[resizeIndex];
|
|
223
|
+
childSizes[resizeIndex] = 0;
|
|
224
|
+
for (let i = this.childContainers.length - 1; i >= 0 && deficit > 0; i--) {
|
|
225
|
+
if (i === resizeIndex)
|
|
226
|
+
continue;
|
|
227
|
+
let reduction = Math.min(childSizes[i], deficit);
|
|
228
|
+
childSizes[i] -= reduction;
|
|
229
|
+
deficit -= reduction;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
childSizes = childSizes.map((size) => Math.floor(size));
|
|
234
|
+
childSizes[resizeIndex] += targetTotalChildPanelSize - childSizes.reduce((sum, size) => sum + size, 0);
|
|
235
|
+
|
|
236
|
+
for (let i = 0; i < this.childContainers.length; i++) {
|
|
237
|
+
let child = this.childContainers[i];
|
|
238
|
+
if (child.containerElement.style.display == 'none')
|
|
239
|
+
child.containerElement.style.display = 'block';
|
|
240
|
+
let newSize = childSizes[i];
|
|
241
|
+
|
|
242
|
+
if (this.stackedVertical)
|
|
243
|
+
child.resize(width, newSize);
|
|
244
|
+
else
|
|
245
|
+
child.resize(newSize, height);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private resizeProportionally(width: number, height: number, targetTotalChildPanelSize: number) {
|
|
250
|
+
for (let i = 0; i < this.childContainers.length; i++) {
|
|
251
|
+
let childContainer = this.childContainers[i];
|
|
252
|
+
if (this.stackedVertical)
|
|
253
|
+
childContainer.resize(width, !childContainer.height ? height : childContainer.height);
|
|
254
|
+
else
|
|
255
|
+
childContainer.resize(!childContainer.width ? width : childContainer.width, height);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
let totalChildPanelSize = 0;
|
|
259
|
+
this.childContainers.forEach((container) => {
|
|
260
|
+
let size = this.stackedVertical ? container.height : container.width;
|
|
261
|
+
totalChildPanelSize += size;
|
|
262
|
+
});
|
|
263
|
+
totalChildPanelSize = Math.max(totalChildPanelSize, 1);
|
|
264
|
+
let scaleMultiplier = targetTotalChildPanelSize / totalChildPanelSize;
|
|
265
|
+
|
|
266
|
+
let updatedTotalChildPanelSize = 0;
|
|
267
|
+
for (let i = 0; i < this.childContainers.length; i++) {
|
|
268
|
+
let child = this.childContainers[i];
|
|
269
|
+
if (child.containerElement.style.display == 'none')
|
|
270
|
+
child.containerElement.style.display = 'block';
|
|
271
|
+
let original = this.stackedVertical ? child.containerElement.clientHeight : child.containerElement.clientWidth;
|
|
272
|
+
let newSize = Math.floor(original * scaleMultiplier);
|
|
273
|
+
updatedTotalChildPanelSize += newSize;
|
|
274
|
+
|
|
275
|
+
if (i === this.childContainers.length - 1)
|
|
276
|
+
newSize += targetTotalChildPanelSize - updatedTotalChildPanelSize;
|
|
277
|
+
|
|
278
|
+
if (this.stackedVertical)
|
|
279
|
+
child.resize(child.width, newSize);
|
|
280
|
+
else
|
|
281
|
+
child.resize(newSize, child.height);
|
|
282
|
+
this.preferredChildSizes.set(child, newSize);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private hasElasticChild(): boolean {
|
|
287
|
+
return this.childContainers.some((container) =>
|
|
288
|
+
container.containerType === ContainerType.fill ||
|
|
289
|
+
container.containerType === ContainerType.horizontal ||
|
|
290
|
+
container.containerType === ContainerType.vertical);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private getElasticChildIndex(): number {
|
|
294
|
+
let fillIndex = this.childContainers.findIndex((container) => container.containerType === ContainerType.fill);
|
|
295
|
+
if (fillIndex >= 0)
|
|
296
|
+
return fillIndex;
|
|
297
|
+
|
|
298
|
+
let compositeIndex = this.childContainers.findIndex((container) =>
|
|
299
|
+
container.containerType === ContainerType.horizontal || container.containerType === ContainerType.vertical);
|
|
300
|
+
if (compositeIndex >= 0)
|
|
301
|
+
return compositeIndex;
|
|
302
|
+
|
|
303
|
+
return this.childContainers.length - 1;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private getChildSize(container: IDockContainer): number {
|
|
307
|
+
return this.stackedVertical ? container.height : container.width;
|
|
308
|
+
}
|
|
309
|
+
}
|