dock-spawn-ts 3.20.0 → 3.22.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.
@@ -9,9 +9,11 @@ import { IDockContainer } from "./interfaces/IDockContainer.js";
9
9
  */
10
10
  export class SplitterPanel {
11
11
  panelElement: HTMLDivElement;
12
- spiltterBars: SplitterBar[];
13
- stackedVertical: boolean;
14
- childContainers: IDockContainer[];
12
+ spiltterBars: SplitterBar[];
13
+ stackedVertical: boolean;
14
+ childContainers: IDockContainer[];
15
+ private preferredChildSizes = new WeakMap<IDockContainer, number>();
16
+ private preserveNonElasticSizes = false;
15
17
 
16
18
  constructor(childContainers: IDockContainer[], stackedVertical: boolean) {
17
19
  this.childContainers = childContainers;
@@ -46,10 +48,15 @@ export class SplitterPanel {
46
48
 
47
49
  performLayout(children: IDockContainer[], relayoutEvenIfEqual: boolean) {
48
50
  let containersEqual = Utils.arrayEqual(this.childContainers, children);
49
- if (!containersEqual || relayoutEvenIfEqual) {
50
- this.childContainers.forEach((container) => {
51
- if (!children.some((item) => item == container)) {
52
- if (container.containerElement) {
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) {
53
60
  container.containerElement.classList.remove('splitter-container-vertical');
54
61
  container.containerElement.classList.remove('splitter-container-horizontal');
55
62
  Utils.removeNode(container.containerElement);
@@ -124,12 +131,14 @@ export class SplitterPanel {
124
131
  else
125
132
  size = newContainerSize;
126
133
 
127
- if (this.stackedVertical)
128
- child.resize(child.width, Math.floor(size));
129
- else
130
- child.resize(Math.floor(size), child.height);
131
- }
132
- }
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
+ }
133
142
 
134
143
  getRatios(): number[] {
135
144
  let barSize = this.stackedVertical ? this.spiltterBars[0].barElement.clientHeight : this.spiltterBars[0].barElement.clientWidth;
@@ -154,12 +163,14 @@ export class SplitterPanel {
154
163
  // Fix rounding error on last child so panels fill the available space exactly
155
164
  if (i === this.childContainers.length - 1)
156
165
  size += splitPanelSize - updatedTotalSize;
157
- if (this.stackedVertical)
158
- child.resize(child.width, size);
159
- else
160
- child.resize(size, child.height);
161
- }
162
- }
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
+ }
163
174
 
164
175
  resize(width: number, height: number) {
165
176
  if (this.childContainers.length <= 1)
@@ -182,7 +193,22 @@ export class SplitterPanel {
182
193
  let targetTotalChildPanelSize = this.stackedVertical ? height : width;
183
194
  targetTotalChildPanelSize -= barSize * this.spiltterBars.length;
184
195
 
185
- let childSizes = this.childContainers.map((container) => this.stackedVertical ? container.height : container.width);
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
+ });
186
212
  let totalChildPanelSize = childSizes.reduce((sum, size) => sum + size, 0);
187
213
  if (totalChildPanelSize <= 0) {
188
214
  let size = targetTotalChildPanelSize / this.childContainers.length;
@@ -190,7 +216,6 @@ export class SplitterPanel {
190
216
  totalChildPanelSize = targetTotalChildPanelSize;
191
217
  }
192
218
 
193
- let resizeIndex = this.getElasticChildIndex();
194
219
  let sizeDelta = targetTotalChildPanelSize - totalChildPanelSize;
195
220
  childSizes[resizeIndex] += sizeDelta;
196
221
  if (childSizes[resizeIndex] < 0) {
@@ -221,6 +246,50 @@ export class SplitterPanel {
221
246
  }
222
247
  }
223
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
+
224
293
  private getElasticChildIndex(): number {
225
294
  let fillIndex = this.childContainers.findIndex((container) => container.containerType === ContainerType.fill);
226
295
  if (fillIndex >= 0)
@@ -233,4 +302,8 @@ export class SplitterPanel {
233
302
 
234
303
  return this.childContainers.length - 1;
235
304
  }
305
+
306
+ private getChildSize(container: IDockContainer): number {
307
+ return this.stackedVertical ? container.height : container.width;
308
+ }
236
309
  }