@hpcc-js/layout 3.5.10 → 3.5.11

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/src/Border.ts CHANGED
@@ -1,636 +1,636 @@
1
- import { d3Event, HTMLWidget, Platform, select as d3Select, selectAll as d3SelectAll, Utility } from "@hpcc-js/common";
2
- import { drag as d3Drag } from "d3-drag";
3
- import { Cell } from "./Cell.ts";
4
-
5
- import "../src/Border.css";
6
-
7
- export class Border extends HTMLWidget {
8
- _colCount: number;
9
- _rowCount: number;
10
- _colSize: number;
11
- _rowSize: number;
12
- _shrinkWrapBoxes;
13
- _watch;
14
- _offsetX;
15
- _offsetY;
16
- _dragCell;
17
- _dragCellSize;
18
- _dragCellStartSize;
19
- _handleTop;
20
- _handleLeft;
21
- _dragPrevX;
22
- _dragPrevY;
23
- _cellSizes;
24
- contentDiv;
25
- _scrollBarWidth;
26
- _borderHandles;
27
- _sectionTypeArr;
28
-
29
- constructor() {
30
- super();
31
-
32
- this._tag = "div";
33
-
34
- this._colCount = 0;
35
- this._rowCount = 0;
36
- this._colSize = 0;
37
- this._rowSize = 0;
38
-
39
- this._shrinkWrapBoxes = {};
40
-
41
- this.content([]);
42
- this.sectionTypes([]);
43
- }
44
-
45
- watchWidget(widget) {
46
- if (this._watch === undefined) {
47
- this._watch = {};
48
- }
49
- if (this._watch[widget.id()]) {
50
- this._watch[widget.id()].remove();
51
- delete this._watch[widget.id()];
52
- }
53
- if (widget) {
54
- const context = this;
55
- this._watch[widget.id()] = widget.monitor(function (paramId, newVal, oldVal) {
56
- if (oldVal !== newVal) {
57
- context.lazyPostUpdate();
58
- }
59
- });
60
- }
61
- }
62
-
63
- lazyPostUpdate = Utility.debounce(function () {
64
- this.postUpdate();
65
- }, 100);
66
-
67
- applyLayoutType() {
68
- const layoutObj = this.borderLayoutObject();
69
- this.content().forEach(function (cell, i) {
70
- cell._fixedLeft = layoutObj[this.sectionTypes()[i]].left;
71
- cell._fixedTop = layoutObj[this.sectionTypes()[i]].top;
72
- cell._fixedWidth = layoutObj[this.sectionTypes()[i]].width;
73
- cell._fixedHeight = layoutObj[this.sectionTypes()[i]].height;
74
- cell._dragHandles = this.cellSpecificDragHandles(this.sectionTypes()[i]);
75
- }, this);
76
- }
77
- cellSpecificDragHandles(sectionType) {
78
- switch (sectionType) {
79
- case "top": return ["s"];
80
- case "right": return ["w"];
81
- case "bottom": return ["n"];
82
- case "left": return ["e"];
83
- case "center": return [];
84
- }
85
- }
86
-
87
- borderLayoutObject(layoutType?) {
88
- const retObj = {};
89
- const context = this;
90
- let topSize;
91
- let topPerc;
92
- let bottomSize;
93
- let bottomPerc;
94
- let leftSize;
95
- let leftPerc;
96
- let rightSize;
97
- let rightPerc;
98
-
99
- const bcRect = this.target().getBoundingClientRect();
100
- const gridRect: any = {};
101
- gridRect.top = bcRect.top;
102
- gridRect.left = bcRect.left;
103
- gridRect.bottom = bcRect.bottom;
104
- gridRect.right = bcRect.right;
105
- if (this.target() instanceof SVGElement) {
106
- gridRect.width = parseFloat(this.target().getAttribute("width"));
107
- gridRect.height = parseFloat(this.target().getAttribute("height"));
108
- } else {
109
- gridRect.width = bcRect.width;
110
- gridRect.height = bcRect.height;
111
- }
112
- if (this.sectionTypes().indexOf("top") !== -1) {
113
- topSize = this.topSize();
114
- topPerc = this.topPercentage();
115
- if (typeof (this._shrinkWrapBoxes["top"]) !== "undefined") {
116
- topSize = this._shrinkWrapBoxes["top"].height + this.gutter();
117
- topPerc = 0;
118
- }
119
- }
120
- if (this.sectionTypes().indexOf("bottom") !== -1) {
121
- bottomSize = this.bottomSize();
122
- bottomPerc = this.bottomPercentage();
123
- if (typeof (this._shrinkWrapBoxes["bottom"]) !== "undefined") {
124
- bottomSize = this._shrinkWrapBoxes["bottom"].height + this.gutter();
125
- bottomPerc = 0;
126
- }
127
- }
128
- if (this.sectionTypes().indexOf("left") !== -1) {
129
- leftSize = this.leftSize();
130
- leftPerc = this.leftPercentage();
131
- if (typeof (this._shrinkWrapBoxes["left"]) !== "undefined") {
132
- leftSize = this._shrinkWrapBoxes["left"].width + this.gutter();
133
- leftPerc = 0;
134
- }
135
- }
136
- if (this.sectionTypes().indexOf("right") !== -1) {
137
- rightSize = this.rightSize();
138
- rightPerc = this.rightPercentage();
139
- if (typeof (this._shrinkWrapBoxes["right"]) !== "undefined") {
140
- rightSize = this._shrinkWrapBoxes["right"].width + this.gutter();
141
- rightPerc = 0;
142
- }
143
- }
144
-
145
- const t = _sectionPlacementObject({
146
- width: { "px": 0, "%": 100 },
147
- height: { "px": topSize, "%": topPerc },
148
- top: { "px": 0, "%": 0 },
149
- left: { "px": 0, "%": 0 }
150
- });
151
- const b = _sectionPlacementObject({
152
- width: { "px": 0, "%": 100 },
153
- height: { "px": bottomSize, "%": bottomPerc },
154
- top: { "px": 0, "%": 100 },
155
- left: { "px": 0, "%": 0 }
156
- });
157
- b.top -= b.height;
158
- const l = _sectionPlacementObject({
159
- width: { "px": leftSize, "%": leftPerc },
160
- height: { "px": -t.height - b.height, "%": 100 },
161
- top: { "px": t.height, "%": 0 },
162
- left: { "px": 0, "%": 0 }
163
- });
164
- const r = _sectionPlacementObject({
165
- width: { "px": rightSize, "%": rightPerc },
166
- height: { "px": -t.height - b.height, "%": 100 },
167
- top: { "px": t.height, "%": 0 },
168
- left: { "px": 0, "%": 100 }
169
- });
170
- r.left -= r.width;
171
- const c = _sectionPlacementObject({
172
- width: { "px": -r.width - l.width, "%": 100 },
173
- height: { "px": -t.height - b.height, "%": 100 },
174
- top: { "px": t.height, "%": 0 },
175
- left: { "px": l.width, "%": 0 }
176
- });
177
- retObj["top"] = t;
178
- retObj["bottom"] = b;
179
- retObj["right"] = r;
180
- retObj["left"] = l;
181
- retObj["center"] = c;
182
- return retObj;
183
-
184
- function _sectionPlacementObject(obj) {
185
- obj.width["px"] = typeof (obj.width["px"]) !== "undefined" ? obj.width["px"] : 0;
186
- obj.width["%"] = typeof (obj.width["%"]) !== "undefined" ? obj.width["%"] : 0;
187
- obj.height["px"] = typeof (obj.height["px"]) !== "undefined" ? obj.height["px"] : 0;
188
- obj.height["%"] = typeof (obj.height["%"]) !== "undefined" ? obj.height["%"] : 0;
189
- const ret = {
190
- width: obj.width["px"] + (obj.width["%"] / 100 * context.width()),
191
- height: obj.height["px"] + (obj.height["%"] / 100 * context.height()),
192
- top: obj.top["px"] + (obj.top["%"] / 100 * context.height()) + context.gutter() / 2,
193
- left: obj.left["px"] + (obj.left["%"] / 100 * context.width()) + context.gutter() / 2
194
- };
195
- return ret;
196
- }
197
- }
198
-
199
- clearContent(sectionType) {
200
- if (!sectionType) {
201
- this.content().forEach(function (contentWidget) {
202
- contentWidget.target(null);
203
- return false;
204
- });
205
- d3Select("#" + this.id() + " > div.borderHandle")
206
- .classed("borderHandleDisabled", true)
207
- ;
208
- delete this._watch;
209
- this.content([]);
210
- this.sectionTypes([]);
211
- } else {
212
- const idx = this.sectionTypes().indexOf(sectionType);
213
- if (idx >= 0) {
214
- if (this._watch && this.content()[idx]) {
215
- delete this._watch[this.content()[idx].id()];
216
- }
217
- this.content()[idx].target(null);
218
- d3Select("#" + this.id() + " > div.borderHandle_" + sectionType)
219
- .classed("borderHandleDisabled", true)
220
- ;
221
- this.content().splice(idx, 1);
222
- this.sectionTypes().splice(idx, 1);
223
- }
224
- }
225
- }
226
-
227
- hasContent(sectionType, widget, title) {
228
- return this.sectionTypes().indexOf(sectionType) >= 0;
229
- }
230
-
231
- setContent(sectionType, widget, title?) {
232
- this.clearContent(sectionType);
233
- title = typeof (title) !== "undefined" ? title : "";
234
- if (widget) {
235
- const cell = new Cell()
236
- .surfaceBorderWidth(0)
237
- .widget(widget)
238
- .title(title)
239
- ;
240
- this.watchWidget(widget);
241
- this.content().push(cell);
242
- this.sectionTypes().push(sectionType);
243
- }
244
- return this;
245
- }
246
-
247
- getCell(id) {
248
- const idx = this.sectionTypes().indexOf(id);
249
- if (idx >= 0) {
250
- return this.content()[idx];
251
- }
252
- return null;
253
- }
254
-
255
- getContent(id) {
256
- const idx = this.sectionTypes().indexOf(id);
257
- if (idx >= 0) {
258
- return this.content()[idx].widget();
259
- }
260
- return null;
261
- }
262
-
263
- setLayoutOffsets() {
264
- this._offsetX = this._element.node().getBoundingClientRect().left + (this.gutter() / 2);
265
- this._offsetY = this._element.node().getBoundingClientRect().top + (this.gutter() / 2);
266
- }
267
-
268
- dragStart(handle) {
269
- const event = d3Event();
270
- event.sourceEvent.stopPropagation();
271
- const context = this;
272
-
273
- this._dragCell = handle;
274
- this._dragCellStartSize = this[handle + "Size"]();
275
-
276
- if (this[handle + "ShrinkWrap"]()) {
277
- this[handle + "Percentage"](0);
278
- this[handle + "ShrinkWrap"](false);
279
- }
280
-
281
- const handleElm = d3Select("#" + context.id() + " > div.borderHandle_" + handle);
282
- context._handleTop = parseFloat(handleElm.style("top").split("px")[0]);
283
- context._handleLeft = parseFloat(handleElm.style("left").split("px")[0]);
284
-
285
- this._dragPrevX = event.sourceEvent.clientX;
286
- this._dragPrevY = event.sourceEvent.clientY;
287
- }
288
- dragTick(handle) {
289
- const context = this;
290
-
291
- const event = d3Event();
292
- const xDelta = this._dragPrevX - event.sourceEvent.clientX;
293
- const yDelta = this._dragPrevY - event.sourceEvent.clientY;
294
-
295
- switch (handle) {
296
- case "top":
297
- case "bottom":
298
- _moveHandles(handle, yDelta);
299
- break;
300
- case "right":
301
- case "left":
302
- _moveHandles(handle, xDelta);
303
- break;
304
- }
305
-
306
- function _moveHandles(handle2, delta) {
307
- if (delta === 0) return;
308
- const handles = d3SelectAll("#" + context.id() + " > div.borderHandle");
309
- const grabbedHandle = d3Select("#" + context.id() + " > div.borderHandle_" + handle2);
310
-
311
- if (grabbedHandle.classed("borderHandle_top")) {
312
- grabbedHandle.style("top", (context._handleTop - delta) + "px");
313
- context._cellSizes.topHeight = context._handleTop - delta;
314
- context._cellSizes.leftHeight = context._cellSizes.height;
315
- context._cellSizes.leftHeight -= context._cellSizes.topHeight;
316
- context._cellSizes.leftHeight -= context._cellSizes.bottomHeight;
317
- context._cellSizes.rightHeight = context._cellSizes.leftHeight;
318
- } else if (grabbedHandle.classed("borderHandle_right")) {
319
- grabbedHandle.style("left", (context._handleLeft - delta) + "px");
320
- context._cellSizes.rightWidth = context._cellSizes.width - context._handleLeft + delta;
321
- } else if (grabbedHandle.classed("borderHandle_bottom")) {
322
- grabbedHandle.style("top", (context._handleTop - delta) + "px");
323
- context._cellSizes.bottomHeight = context._cellSizes.height - context._handleTop + delta;
324
- context._cellSizes.leftHeight = context._cellSizes.height;
325
- context._cellSizes.leftHeight -= context._cellSizes.bottomHeight;
326
- context._cellSizes.leftHeight -= context._cellSizes.topHeight;
327
- context._cellSizes.rightHeight = context._cellSizes.leftHeight;
328
- } else if (grabbedHandle.classed("borderHandle_left")) {
329
- grabbedHandle.style("left", (context._handleLeft - delta) + "px");
330
- context._cellSizes.leftWidth = context._handleLeft - delta;
331
- }
332
-
333
- handles.each(function () {
334
- const handle3 = d3Select(this);
335
- if (handle3.classed("borderHandle_top")) {
336
- handle3.style("width", context._cellSizes.width + "px");
337
- handle3.style("top", (context._cellSizes.topHeight - 3) + "px");
338
- } else if (handle3.classed("borderHandle_right")) {
339
- handle3.style("left", (context._cellSizes.width - context._cellSizes.rightWidth) + "px");
340
- handle3.style("top", (context._cellSizes.topHeight + 3) + "px");
341
- handle3.style("height", context._cellSizes.rightHeight + "px");
342
- } else if (handle3.classed("borderHandle_bottom")) {
343
- handle3.style("width", context._cellSizes.width + "px");
344
- handle3.style("top", (context._cellSizes.height - context._cellSizes.bottomHeight - 3) + "px");
345
- } else if (handle3.classed("borderHandle_left")) {
346
- handle3.style("left", context._cellSizes.leftWidth + "px");
347
- handle3.style("height", context._cellSizes.leftHeight + "px");
348
- handle3.style("top", (context._cellSizes.topHeight + 3) + "px");
349
- }
350
- });
351
- }
352
- }
353
- dragEnd(handle) {
354
- if (handle) {
355
- const event = d3Event();
356
- const xDelta = this._dragPrevX - event.sourceEvent.clientX;
357
- const yDelta = this._dragPrevY - event.sourceEvent.clientY;
358
-
359
- switch (handle) {
360
- case "top":
361
- if (yDelta !== 0) {
362
- this.topPercentage(0);
363
- this.topSize(this.topSize() === 0 ? this.getContent("top").getBBox().height - yDelta : this.topSize() - yDelta);
364
- }
365
- break;
366
- case "right":
367
- if (xDelta !== 0) {
368
- this.rightPercentage(0);
369
- this.rightSize(this.rightSize() === 0 ? this.getContent("right").getBBox().width + xDelta : this.rightSize() + xDelta);
370
- }
371
- break;
372
- case "bottom":
373
- if (yDelta !== 0) {
374
- this.bottomPercentage(0);
375
- this.bottomSize(this.bottomSize() === 0 ? this.getContent("bottom").getBBox().height + yDelta : this.bottomSize() + yDelta);
376
- }
377
- break;
378
- case "left":
379
- if (xDelta !== 0) {
380
- this.leftPercentage(0);
381
- this.leftSize(this.leftSize() === 0 ? this.getContent("left").getBBox().width - xDelta : this.leftSize() - xDelta);
382
- }
383
- break;
384
- }
385
-
386
- this._dragPrevX = event.sourceEvent.clientX;
387
- this._dragPrevY = event.sourceEvent.clientY;
388
- }
389
- this.render();
390
- }
391
-
392
- size(_?) {
393
- const retVal = HTMLWidget.prototype.size.apply(this, arguments);
394
- if (arguments.length && this.contentDiv) {
395
- this.contentDiv
396
- .style("width", this._size.width + "px")
397
- .style("height", this._size.height + "px")
398
- ;
399
- }
400
- return retVal;
401
- }
402
-
403
- enter(domNode, element) {
404
- super.enter(domNode, element);
405
- const context = this;
406
- element.style("position", "relative");
407
- this.contentDiv = element.append("div").classed("border-content", true);
408
- this._scrollBarWidth = Platform.getScrollbarWidth();
409
- this._borderHandles = ["top", "left", "right", "bottom"];
410
-
411
- const handles = element.selectAll("div.borderHandle").data(this._borderHandles);
412
- handles.enter().append("div")
413
- .classed("borderHandle", true)
414
- .each(function (handle) {
415
- const h = d3Select(this);
416
- h.classed("borderHandle_" + handle, true)
417
- .classed("borderHandleDisabled", context.getContent(handle) === null)
418
- ;
419
- });
420
- }
421
-
422
- update(domNode, element) {
423
- super.update(domNode, element);
424
- this._sectionTypeArr = this.sectionTypes();
425
- const context = this;
426
-
427
- element.classed("design-mode", this.designMode());
428
-
429
- this.setLayoutOffsets();
430
-
431
- const rows = this.contentDiv.selectAll(".cell_" + this._id).data(this.content(), function (d) { return d._id; });
432
- const rowsUpdate = rows.enter().append("div")
433
- .classed("cell_" + this._id, true)
434
- .style("position", "absolute")
435
- .each(function (d, i) {
436
- d3Select(this).classed("border-cell border-cell-" + context._sectionTypeArr[i], true);
437
- d.target(this);
438
- d3Select("#" + context.id() + " > div.borderHandle_" + context._sectionTypeArr[i])
439
- .classed("borderHandleDisabled", false);
440
- }).merge(rows);
441
- rowsUpdate
442
- .each(function (d, idx) {
443
- const sectionType = context.sectionTypes()[idx];
444
- if (typeof (context[sectionType + "ShrinkWrap"]) !== "undefined" && context[sectionType + "ShrinkWrap"]()) {
445
- d.render();
446
- context._shrinkWrapBoxes[sectionType] = d.widget().getBBox(true);
447
- } else {
448
- delete context._shrinkWrapBoxes[sectionType];
449
- }
450
- });
451
-
452
- const drag = d3Drag()
453
- .on("start", function (d, i) { context.dragStart.call(context, d, i); })
454
- .on("drag", function (d, i) { context.dragTick.call(context, d, i); })
455
- .on("end", function (d, i) { context.dragEnd.call(context, d, i); })
456
- ;
457
- if (this.designMode()) {
458
- element.selectAll("#" + this.id() + " > div.borderHandle").call(drag);
459
- } else {
460
- element.selectAll("#" + this.id() + " > div.borderHandle").on(".drag", null);
461
- }
462
-
463
- const layoutObj = this.borderLayoutObject();
464
- this.content().forEach(function (cell, i) {
465
- cell._fixedLeft = layoutObj[this.sectionTypes()[i]].left;
466
- cell._fixedTop = layoutObj[this.sectionTypes()[i]].top;
467
- cell._fixedWidth = layoutObj[this.sectionTypes()[i]].width;
468
- cell._fixedHeight = layoutObj[this.sectionTypes()[i]].height;
469
- cell._dragHandles = [];
470
- }, this);
471
-
472
- rowsUpdate
473
- .style("left", function (d) { return d._fixedLeft + "px"; })
474
- .style("top", function (d) { return d._fixedTop + "px"; })
475
- .style("width", function (d) { return d._fixedWidth - context.gutter() + "px"; })
476
- .style("height", function (d) { return d._fixedHeight - context.gutter() + "px"; })
477
- .each(function (d) {
478
- d._placeholderElement
479
- .attr("draggable", context.designMode())
480
- .selectAll(".dragHandle")
481
- .attr("draggable", context.designMode())
482
- ;
483
- d
484
- .surfacePadding(context.surfacePadding())
485
- .resize()
486
- ;
487
- });
488
- rows.exit().each(function (d) {
489
- d.target(null);
490
- }).remove();
491
-
492
- this.getCellSizes();
493
-
494
- element
495
- .selectAll("#" + this.id() + " > div.borderHandle")
496
- .each(function () {
497
- const handle = d3Select(this);
498
- if (handle.classed("borderHandle_top")) {
499
- handle.style("width", context._cellSizes.width + "px");
500
- handle.style("top", (context._cellSizes.topHeight - 3) + "px");
501
- } else if (handle.classed("borderHandle_right")) {
502
- handle.style("left", (context._cellSizes.width - context._cellSizes.rightWidth) + "px");
503
- handle.style("top", (context._cellSizes.topHeight + 3) + "px");
504
- handle.style("height", context._cellSizes.rightHeight + "px");
505
- } else if (handle.classed("borderHandle_bottom")) {
506
- handle.style("width", context._cellSizes.width + "px");
507
- handle.style("top", (context._cellSizes.height - context._cellSizes.bottomHeight - 3) + "px");
508
- } else if (handle.classed("borderHandle_left")) {
509
- handle.style("left", context._cellSizes.leftWidth + "px");
510
- handle.style("height", context._cellSizes.leftHeight + "px");
511
- handle.style("top", (context._cellSizes.topHeight + 3) + "px");
512
- }
513
-
514
- })
515
- ;
516
- }
517
-
518
- getCellSizes() {
519
- const context = this;
520
- context._cellSizes = {};
521
- const contentRect = this.element().node().getBoundingClientRect();
522
- context._cellSizes.width = contentRect.width;
523
- context._cellSizes.height = contentRect.height;
524
- this.element()
525
- .selectAll("#" + this.id() + " > div > div.border-cell")
526
- .each(function () {
527
- const cell = d3Select(this);
528
- if (typeof cell.node === "function") {
529
- const rect = cell.node().getBoundingClientRect();
530
- if (cell.classed("border-cell-top")) {
531
- context._cellSizes.topHeight = rect.height;
532
- } else if (cell.classed("border-cell-left")) {
533
- context._cellSizes.leftWidth = rect.width;
534
- context._cellSizes.leftHeight = rect.height;
535
- } else if (cell.classed("border-cell-right")) {
536
- context._cellSizes.rightWidth = rect.width;
537
- context._cellSizes.rightHeight = rect.height;
538
- } else if (cell.classed("border-cell-bottom")) {
539
- context._cellSizes.bottomHeight = rect.height;
540
- }
541
- }
542
- });
543
- const sizes = ["height", "width", "topHeight", "bottomHeight", "leftHeight", "rightHeight", "leftWidth", "rightWidth"];
544
- sizes.forEach(function (size) {
545
- context._cellSizes[size] = context._cellSizes[size] === undefined ? 0 : context._cellSizes[size];
546
- });
547
- }
548
-
549
- postUpdate(domNode, element) {
550
- const context = this;
551
- this.content().forEach(function (n) {
552
- if (n._element.node() !== null && n.widget()) {
553
- const prevBox = n.widget().getBBox(false, true);
554
- const currBox = n.widget().getBBox(true, true);
555
- if (prevBox.width !== currBox.width || prevBox.height !== currBox.height) {
556
- context.lazyRender();
557
- }
558
- }
559
- });
560
- }
561
-
562
- exit(domNode, element) {
563
- this.content().forEach(w => w.target(null));
564
- super.exit(domNode, element);
565
- }
566
- }
567
- Border.prototype._class += " layout_Border";
568
-
569
- export interface Border {
570
- designMode(): boolean;
571
- designMode(_: boolean): this;
572
-
573
- content(): any[];
574
- content(_: any[]): this;
575
-
576
- gutter(): number;
577
- gutter(_: number): this;
578
-
579
- topShrinkWrap(): boolean;
580
- topShrinkWrap(_: boolean): this;
581
- leftShrinkWrap(): boolean;
582
- leftShrinkWrap(_: boolean): this;
583
- rightShrinkWrap(): boolean;
584
- rightShrinkWrap(_: boolean): this;
585
- bottomShrinkWrap(): boolean;
586
- bottomShrinkWrap(_: boolean): this;
587
-
588
- topSize(): number;
589
- topSize(_: number): this;
590
- leftSize(): number;
591
- leftSize(_: number): this;
592
- rightSize(): number;
593
- rightSize(_: number): this;
594
- bottomSize(): number;
595
- bottomSize(_: number): this;
596
-
597
- topPercentage(): number;
598
- topPercentage(_: number): this;
599
- leftPercentage(): number;
600
- leftPercentage(_: number): this;
601
- rightPercentage(): number;
602
- rightPercentage(_: number): this;
603
- bottomPercentage(): number;
604
- bottomPercentage(_: number): this;
605
-
606
- surfacePadding(): number;
607
- surfacePadding(_: number): this;
608
-
609
- sectionTypes(): any[];
610
- sectionTypes(_: any[]): this;
611
- }
612
-
613
- Border.prototype.publish("designMode", false, "boolean", "Design Mode", null, { tags: ["Basic"] });
614
-
615
- Border.prototype.publish("content", [], "widgetArray", "widgets", null, { tags: ["Intermediate"] });
616
-
617
- Border.prototype.publish("gutter", 0, "number", "Gap Between Widgets", null, { tags: ["Basic"] });
618
-
619
- Border.prototype.publish("topShrinkWrap", false, "boolean", "'Top' Cell shrinks to fit content", null, { tags: ["Intermediate"] });
620
- Border.prototype.publish("leftShrinkWrap", false, "boolean", "'Left' Cell shrinks to fit content", null, { tags: ["Intermediate"] });
621
- Border.prototype.publish("rightShrinkWrap", false, "boolean", "'Right' Cell shrinks to fit content", null, { tags: ["Intermediate"] });
622
- Border.prototype.publish("bottomShrinkWrap", false, "boolean", "'Bottom' Cell shrinks to fit content", null, { tags: ["Intermediate"] });
623
-
624
- Border.prototype.publish("topSize", 0, "number", "Height of the 'Top' Cell (px)", null, { tags: ["Private"] });
625
- Border.prototype.publish("leftSize", 0, "number", "Width of the 'Left' Cell (px)", null, { tags: ["Private"] });
626
- Border.prototype.publish("rightSize", 0, "number", "Width of the 'Right' Cell (px)", null, { tags: ["Private"] });
627
- Border.prototype.publish("bottomSize", 0, "number", "Height of the 'Bottom' Cell (px)", null, { tags: ["Private"] });
628
-
629
- Border.prototype.publish("topPercentage", 20, "number", "Percentage (of parent) Height of the 'Top' Cell", null, { tags: ["Private"] });
630
- Border.prototype.publish("leftPercentage", 20, "number", "Percentage (of parent) Width of the 'Left' Cell", null, { tags: ["Private"] });
631
- Border.prototype.publish("rightPercentage", 20, "number", "Percentage (of parent) Width of the 'Right' Cell", null, { tags: ["Private"] });
632
- Border.prototype.publish("bottomPercentage", 20, "number", "Percentage (of parent) Height of the 'Bottom' Cell", null, { tags: ["Private"] });
633
-
634
- Border.prototype.publish("surfacePadding", 0, "number", "Cell Padding (px)", null, { tags: ["Intermediate"] });
635
-
636
- Border.prototype.publish("sectionTypes", [], "array", "Section Types sharing an index with 'content' - Used to determine position/size.", null, { tags: ["Private"] });
1
+ import { d3Event, HTMLWidget, Platform, select as d3Select, selectAll as d3SelectAll, Utility } from "@hpcc-js/common";
2
+ import { drag as d3Drag } from "d3-drag";
3
+ import { Cell } from "./Cell.ts";
4
+
5
+ import "../src/Border.css";
6
+
7
+ export class Border extends HTMLWidget {
8
+ _colCount: number;
9
+ _rowCount: number;
10
+ _colSize: number;
11
+ _rowSize: number;
12
+ _shrinkWrapBoxes;
13
+ _watch;
14
+ _offsetX;
15
+ _offsetY;
16
+ _dragCell;
17
+ _dragCellSize;
18
+ _dragCellStartSize;
19
+ _handleTop;
20
+ _handleLeft;
21
+ _dragPrevX;
22
+ _dragPrevY;
23
+ _cellSizes;
24
+ contentDiv;
25
+ _scrollBarWidth;
26
+ _borderHandles;
27
+ _sectionTypeArr;
28
+
29
+ constructor() {
30
+ super();
31
+
32
+ this._tag = "div";
33
+
34
+ this._colCount = 0;
35
+ this._rowCount = 0;
36
+ this._colSize = 0;
37
+ this._rowSize = 0;
38
+
39
+ this._shrinkWrapBoxes = {};
40
+
41
+ this.content([]);
42
+ this.sectionTypes([]);
43
+ }
44
+
45
+ watchWidget(widget) {
46
+ if (this._watch === undefined) {
47
+ this._watch = {};
48
+ }
49
+ if (this._watch[widget.id()]) {
50
+ this._watch[widget.id()].remove();
51
+ delete this._watch[widget.id()];
52
+ }
53
+ if (widget) {
54
+ const context = this;
55
+ this._watch[widget.id()] = widget.monitor(function (paramId, newVal, oldVal) {
56
+ if (oldVal !== newVal) {
57
+ context.lazyPostUpdate();
58
+ }
59
+ });
60
+ }
61
+ }
62
+
63
+ lazyPostUpdate = Utility.debounce(function () {
64
+ this.postUpdate();
65
+ }, 100);
66
+
67
+ applyLayoutType() {
68
+ const layoutObj = this.borderLayoutObject();
69
+ this.content().forEach(function (cell, i) {
70
+ cell._fixedLeft = layoutObj[this.sectionTypes()[i]].left;
71
+ cell._fixedTop = layoutObj[this.sectionTypes()[i]].top;
72
+ cell._fixedWidth = layoutObj[this.sectionTypes()[i]].width;
73
+ cell._fixedHeight = layoutObj[this.sectionTypes()[i]].height;
74
+ cell._dragHandles = this.cellSpecificDragHandles(this.sectionTypes()[i]);
75
+ }, this);
76
+ }
77
+ cellSpecificDragHandles(sectionType) {
78
+ switch (sectionType) {
79
+ case "top": return ["s"];
80
+ case "right": return ["w"];
81
+ case "bottom": return ["n"];
82
+ case "left": return ["e"];
83
+ case "center": return [];
84
+ }
85
+ }
86
+
87
+ borderLayoutObject(layoutType?) {
88
+ const retObj = {};
89
+ const context = this;
90
+ let topSize;
91
+ let topPerc;
92
+ let bottomSize;
93
+ let bottomPerc;
94
+ let leftSize;
95
+ let leftPerc;
96
+ let rightSize;
97
+ let rightPerc;
98
+
99
+ const bcRect = this.target().getBoundingClientRect();
100
+ const gridRect: any = {};
101
+ gridRect.top = bcRect.top;
102
+ gridRect.left = bcRect.left;
103
+ gridRect.bottom = bcRect.bottom;
104
+ gridRect.right = bcRect.right;
105
+ if (this.target() instanceof SVGElement) {
106
+ gridRect.width = parseFloat(this.target().getAttribute("width"));
107
+ gridRect.height = parseFloat(this.target().getAttribute("height"));
108
+ } else {
109
+ gridRect.width = bcRect.width;
110
+ gridRect.height = bcRect.height;
111
+ }
112
+ if (this.sectionTypes().indexOf("top") !== -1) {
113
+ topSize = this.topSize();
114
+ topPerc = this.topPercentage();
115
+ if (typeof (this._shrinkWrapBoxes["top"]) !== "undefined") {
116
+ topSize = this._shrinkWrapBoxes["top"].height + this.gutter();
117
+ topPerc = 0;
118
+ }
119
+ }
120
+ if (this.sectionTypes().indexOf("bottom") !== -1) {
121
+ bottomSize = this.bottomSize();
122
+ bottomPerc = this.bottomPercentage();
123
+ if (typeof (this._shrinkWrapBoxes["bottom"]) !== "undefined") {
124
+ bottomSize = this._shrinkWrapBoxes["bottom"].height + this.gutter();
125
+ bottomPerc = 0;
126
+ }
127
+ }
128
+ if (this.sectionTypes().indexOf("left") !== -1) {
129
+ leftSize = this.leftSize();
130
+ leftPerc = this.leftPercentage();
131
+ if (typeof (this._shrinkWrapBoxes["left"]) !== "undefined") {
132
+ leftSize = this._shrinkWrapBoxes["left"].width + this.gutter();
133
+ leftPerc = 0;
134
+ }
135
+ }
136
+ if (this.sectionTypes().indexOf("right") !== -1) {
137
+ rightSize = this.rightSize();
138
+ rightPerc = this.rightPercentage();
139
+ if (typeof (this._shrinkWrapBoxes["right"]) !== "undefined") {
140
+ rightSize = this._shrinkWrapBoxes["right"].width + this.gutter();
141
+ rightPerc = 0;
142
+ }
143
+ }
144
+
145
+ const t = _sectionPlacementObject({
146
+ width: { "px": 0, "%": 100 },
147
+ height: { "px": topSize, "%": topPerc },
148
+ top: { "px": 0, "%": 0 },
149
+ left: { "px": 0, "%": 0 }
150
+ });
151
+ const b = _sectionPlacementObject({
152
+ width: { "px": 0, "%": 100 },
153
+ height: { "px": bottomSize, "%": bottomPerc },
154
+ top: { "px": 0, "%": 100 },
155
+ left: { "px": 0, "%": 0 }
156
+ });
157
+ b.top -= b.height;
158
+ const l = _sectionPlacementObject({
159
+ width: { "px": leftSize, "%": leftPerc },
160
+ height: { "px": -t.height - b.height, "%": 100 },
161
+ top: { "px": t.height, "%": 0 },
162
+ left: { "px": 0, "%": 0 }
163
+ });
164
+ const r = _sectionPlacementObject({
165
+ width: { "px": rightSize, "%": rightPerc },
166
+ height: { "px": -t.height - b.height, "%": 100 },
167
+ top: { "px": t.height, "%": 0 },
168
+ left: { "px": 0, "%": 100 }
169
+ });
170
+ r.left -= r.width;
171
+ const c = _sectionPlacementObject({
172
+ width: { "px": -r.width - l.width, "%": 100 },
173
+ height: { "px": -t.height - b.height, "%": 100 },
174
+ top: { "px": t.height, "%": 0 },
175
+ left: { "px": l.width, "%": 0 }
176
+ });
177
+ retObj["top"] = t;
178
+ retObj["bottom"] = b;
179
+ retObj["right"] = r;
180
+ retObj["left"] = l;
181
+ retObj["center"] = c;
182
+ return retObj;
183
+
184
+ function _sectionPlacementObject(obj) {
185
+ obj.width["px"] = typeof (obj.width["px"]) !== "undefined" ? obj.width["px"] : 0;
186
+ obj.width["%"] = typeof (obj.width["%"]) !== "undefined" ? obj.width["%"] : 0;
187
+ obj.height["px"] = typeof (obj.height["px"]) !== "undefined" ? obj.height["px"] : 0;
188
+ obj.height["%"] = typeof (obj.height["%"]) !== "undefined" ? obj.height["%"] : 0;
189
+ const ret = {
190
+ width: obj.width["px"] + (obj.width["%"] / 100 * context.width()),
191
+ height: obj.height["px"] + (obj.height["%"] / 100 * context.height()),
192
+ top: obj.top["px"] + (obj.top["%"] / 100 * context.height()) + context.gutter() / 2,
193
+ left: obj.left["px"] + (obj.left["%"] / 100 * context.width()) + context.gutter() / 2
194
+ };
195
+ return ret;
196
+ }
197
+ }
198
+
199
+ clearContent(sectionType) {
200
+ if (!sectionType) {
201
+ this.content().forEach(function (contentWidget) {
202
+ contentWidget.target(null);
203
+ return false;
204
+ });
205
+ d3Select("#" + this.id() + " > div.borderHandle")
206
+ .classed("borderHandleDisabled", true)
207
+ ;
208
+ delete this._watch;
209
+ this.content([]);
210
+ this.sectionTypes([]);
211
+ } else {
212
+ const idx = this.sectionTypes().indexOf(sectionType);
213
+ if (idx >= 0) {
214
+ if (this._watch && this.content()[idx]) {
215
+ delete this._watch[this.content()[idx].id()];
216
+ }
217
+ this.content()[idx].target(null);
218
+ d3Select("#" + this.id() + " > div.borderHandle_" + sectionType)
219
+ .classed("borderHandleDisabled", true)
220
+ ;
221
+ this.content().splice(idx, 1);
222
+ this.sectionTypes().splice(idx, 1);
223
+ }
224
+ }
225
+ }
226
+
227
+ hasContent(sectionType, widget, title) {
228
+ return this.sectionTypes().indexOf(sectionType) >= 0;
229
+ }
230
+
231
+ setContent(sectionType, widget, title?) {
232
+ this.clearContent(sectionType);
233
+ title = typeof (title) !== "undefined" ? title : "";
234
+ if (widget) {
235
+ const cell = new Cell()
236
+ .surfaceBorderWidth(0)
237
+ .widget(widget)
238
+ .title(title)
239
+ ;
240
+ this.watchWidget(widget);
241
+ this.content().push(cell);
242
+ this.sectionTypes().push(sectionType);
243
+ }
244
+ return this;
245
+ }
246
+
247
+ getCell(id) {
248
+ const idx = this.sectionTypes().indexOf(id);
249
+ if (idx >= 0) {
250
+ return this.content()[idx];
251
+ }
252
+ return null;
253
+ }
254
+
255
+ getContent(id) {
256
+ const idx = this.sectionTypes().indexOf(id);
257
+ if (idx >= 0) {
258
+ return this.content()[idx].widget();
259
+ }
260
+ return null;
261
+ }
262
+
263
+ setLayoutOffsets() {
264
+ this._offsetX = this._element.node().getBoundingClientRect().left + (this.gutter() / 2);
265
+ this._offsetY = this._element.node().getBoundingClientRect().top + (this.gutter() / 2);
266
+ }
267
+
268
+ dragStart(handle) {
269
+ const event = d3Event();
270
+ event.sourceEvent.stopPropagation();
271
+ const context = this;
272
+
273
+ this._dragCell = handle;
274
+ this._dragCellStartSize = this[handle + "Size"]();
275
+
276
+ if (this[handle + "ShrinkWrap"]()) {
277
+ this[handle + "Percentage"](0);
278
+ this[handle + "ShrinkWrap"](false);
279
+ }
280
+
281
+ const handleElm = d3Select("#" + context.id() + " > div.borderHandle_" + handle);
282
+ context._handleTop = parseFloat(handleElm.style("top").split("px")[0]);
283
+ context._handleLeft = parseFloat(handleElm.style("left").split("px")[0]);
284
+
285
+ this._dragPrevX = event.sourceEvent.clientX;
286
+ this._dragPrevY = event.sourceEvent.clientY;
287
+ }
288
+ dragTick(handle) {
289
+ const context = this;
290
+
291
+ const event = d3Event();
292
+ const xDelta = this._dragPrevX - event.sourceEvent.clientX;
293
+ const yDelta = this._dragPrevY - event.sourceEvent.clientY;
294
+
295
+ switch (handle) {
296
+ case "top":
297
+ case "bottom":
298
+ _moveHandles(handle, yDelta);
299
+ break;
300
+ case "right":
301
+ case "left":
302
+ _moveHandles(handle, xDelta);
303
+ break;
304
+ }
305
+
306
+ function _moveHandles(handle2, delta) {
307
+ if (delta === 0) return;
308
+ const handles = d3SelectAll("#" + context.id() + " > div.borderHandle");
309
+ const grabbedHandle = d3Select("#" + context.id() + " > div.borderHandle_" + handle2);
310
+
311
+ if (grabbedHandle.classed("borderHandle_top")) {
312
+ grabbedHandle.style("top", (context._handleTop - delta) + "px");
313
+ context._cellSizes.topHeight = context._handleTop - delta;
314
+ context._cellSizes.leftHeight = context._cellSizes.height;
315
+ context._cellSizes.leftHeight -= context._cellSizes.topHeight;
316
+ context._cellSizes.leftHeight -= context._cellSizes.bottomHeight;
317
+ context._cellSizes.rightHeight = context._cellSizes.leftHeight;
318
+ } else if (grabbedHandle.classed("borderHandle_right")) {
319
+ grabbedHandle.style("left", (context._handleLeft - delta) + "px");
320
+ context._cellSizes.rightWidth = context._cellSizes.width - context._handleLeft + delta;
321
+ } else if (grabbedHandle.classed("borderHandle_bottom")) {
322
+ grabbedHandle.style("top", (context._handleTop - delta) + "px");
323
+ context._cellSizes.bottomHeight = context._cellSizes.height - context._handleTop + delta;
324
+ context._cellSizes.leftHeight = context._cellSizes.height;
325
+ context._cellSizes.leftHeight -= context._cellSizes.bottomHeight;
326
+ context._cellSizes.leftHeight -= context._cellSizes.topHeight;
327
+ context._cellSizes.rightHeight = context._cellSizes.leftHeight;
328
+ } else if (grabbedHandle.classed("borderHandle_left")) {
329
+ grabbedHandle.style("left", (context._handleLeft - delta) + "px");
330
+ context._cellSizes.leftWidth = context._handleLeft - delta;
331
+ }
332
+
333
+ handles.each(function () {
334
+ const handle3 = d3Select(this);
335
+ if (handle3.classed("borderHandle_top")) {
336
+ handle3.style("width", context._cellSizes.width + "px");
337
+ handle3.style("top", (context._cellSizes.topHeight - 3) + "px");
338
+ } else if (handle3.classed("borderHandle_right")) {
339
+ handle3.style("left", (context._cellSizes.width - context._cellSizes.rightWidth) + "px");
340
+ handle3.style("top", (context._cellSizes.topHeight + 3) + "px");
341
+ handle3.style("height", context._cellSizes.rightHeight + "px");
342
+ } else if (handle3.classed("borderHandle_bottom")) {
343
+ handle3.style("width", context._cellSizes.width + "px");
344
+ handle3.style("top", (context._cellSizes.height - context._cellSizes.bottomHeight - 3) + "px");
345
+ } else if (handle3.classed("borderHandle_left")) {
346
+ handle3.style("left", context._cellSizes.leftWidth + "px");
347
+ handle3.style("height", context._cellSizes.leftHeight + "px");
348
+ handle3.style("top", (context._cellSizes.topHeight + 3) + "px");
349
+ }
350
+ });
351
+ }
352
+ }
353
+ dragEnd(handle) {
354
+ if (handle) {
355
+ const event = d3Event();
356
+ const xDelta = this._dragPrevX - event.sourceEvent.clientX;
357
+ const yDelta = this._dragPrevY - event.sourceEvent.clientY;
358
+
359
+ switch (handle) {
360
+ case "top":
361
+ if (yDelta !== 0) {
362
+ this.topPercentage(0);
363
+ this.topSize(this.topSize() === 0 ? this.getContent("top").getBBox().height - yDelta : this.topSize() - yDelta);
364
+ }
365
+ break;
366
+ case "right":
367
+ if (xDelta !== 0) {
368
+ this.rightPercentage(0);
369
+ this.rightSize(this.rightSize() === 0 ? this.getContent("right").getBBox().width + xDelta : this.rightSize() + xDelta);
370
+ }
371
+ break;
372
+ case "bottom":
373
+ if (yDelta !== 0) {
374
+ this.bottomPercentage(0);
375
+ this.bottomSize(this.bottomSize() === 0 ? this.getContent("bottom").getBBox().height + yDelta : this.bottomSize() + yDelta);
376
+ }
377
+ break;
378
+ case "left":
379
+ if (xDelta !== 0) {
380
+ this.leftPercentage(0);
381
+ this.leftSize(this.leftSize() === 0 ? this.getContent("left").getBBox().width - xDelta : this.leftSize() - xDelta);
382
+ }
383
+ break;
384
+ }
385
+
386
+ this._dragPrevX = event.sourceEvent.clientX;
387
+ this._dragPrevY = event.sourceEvent.clientY;
388
+ }
389
+ this.render();
390
+ }
391
+
392
+ size(_?) {
393
+ const retVal = HTMLWidget.prototype.size.apply(this, arguments);
394
+ if (arguments.length && this.contentDiv) {
395
+ this.contentDiv
396
+ .style("width", this._size.width + "px")
397
+ .style("height", this._size.height + "px")
398
+ ;
399
+ }
400
+ return retVal;
401
+ }
402
+
403
+ enter(domNode, element) {
404
+ super.enter(domNode, element);
405
+ const context = this;
406
+ element.style("position", "relative");
407
+ this.contentDiv = element.append("div").classed("border-content", true);
408
+ this._scrollBarWidth = Platform.getScrollbarWidth();
409
+ this._borderHandles = ["top", "left", "right", "bottom"];
410
+
411
+ const handles = element.selectAll("div.borderHandle").data(this._borderHandles);
412
+ handles.enter().append("div")
413
+ .classed("borderHandle", true)
414
+ .each(function (handle) {
415
+ const h = d3Select(this);
416
+ h.classed("borderHandle_" + handle, true)
417
+ .classed("borderHandleDisabled", context.getContent(handle) === null)
418
+ ;
419
+ });
420
+ }
421
+
422
+ update(domNode, element) {
423
+ super.update(domNode, element);
424
+ this._sectionTypeArr = this.sectionTypes();
425
+ const context = this;
426
+
427
+ element.classed("design-mode", this.designMode());
428
+
429
+ this.setLayoutOffsets();
430
+
431
+ const rows = this.contentDiv.selectAll(".cell_" + this._id).data(this.content(), function (d) { return d._id; });
432
+ const rowsUpdate = rows.enter().append("div")
433
+ .classed("cell_" + this._id, true)
434
+ .style("position", "absolute")
435
+ .each(function (d, i) {
436
+ d3Select(this).classed("border-cell border-cell-" + context._sectionTypeArr[i], true);
437
+ d.target(this);
438
+ d3Select("#" + context.id() + " > div.borderHandle_" + context._sectionTypeArr[i])
439
+ .classed("borderHandleDisabled", false);
440
+ }).merge(rows);
441
+ rowsUpdate
442
+ .each(function (d, idx) {
443
+ const sectionType = context.sectionTypes()[idx];
444
+ if (typeof (context[sectionType + "ShrinkWrap"]) !== "undefined" && context[sectionType + "ShrinkWrap"]()) {
445
+ d.render();
446
+ context._shrinkWrapBoxes[sectionType] = d.widget().getBBox(true);
447
+ } else {
448
+ delete context._shrinkWrapBoxes[sectionType];
449
+ }
450
+ });
451
+
452
+ const drag = d3Drag()
453
+ .on("start", function (d, i) { context.dragStart.call(context, d, i); })
454
+ .on("drag", function (d, i) { context.dragTick.call(context, d, i); })
455
+ .on("end", function (d, i) { context.dragEnd.call(context, d, i); })
456
+ ;
457
+ if (this.designMode()) {
458
+ element.selectAll("#" + this.id() + " > div.borderHandle").call(drag);
459
+ } else {
460
+ element.selectAll("#" + this.id() + " > div.borderHandle").on(".drag", null);
461
+ }
462
+
463
+ const layoutObj = this.borderLayoutObject();
464
+ this.content().forEach(function (cell, i) {
465
+ cell._fixedLeft = layoutObj[this.sectionTypes()[i]].left;
466
+ cell._fixedTop = layoutObj[this.sectionTypes()[i]].top;
467
+ cell._fixedWidth = layoutObj[this.sectionTypes()[i]].width;
468
+ cell._fixedHeight = layoutObj[this.sectionTypes()[i]].height;
469
+ cell._dragHandles = [];
470
+ }, this);
471
+
472
+ rowsUpdate
473
+ .style("left", function (d) { return d._fixedLeft + "px"; })
474
+ .style("top", function (d) { return d._fixedTop + "px"; })
475
+ .style("width", function (d) { return d._fixedWidth - context.gutter() + "px"; })
476
+ .style("height", function (d) { return d._fixedHeight - context.gutter() + "px"; })
477
+ .each(function (d) {
478
+ d._placeholderElement
479
+ .attr("draggable", context.designMode())
480
+ .selectAll(".dragHandle")
481
+ .attr("draggable", context.designMode())
482
+ ;
483
+ d
484
+ .surfacePadding(context.surfacePadding())
485
+ .resize()
486
+ ;
487
+ });
488
+ rows.exit().each(function (d) {
489
+ d.target(null);
490
+ }).remove();
491
+
492
+ this.getCellSizes();
493
+
494
+ element
495
+ .selectAll("#" + this.id() + " > div.borderHandle")
496
+ .each(function () {
497
+ const handle = d3Select(this);
498
+ if (handle.classed("borderHandle_top")) {
499
+ handle.style("width", context._cellSizes.width + "px");
500
+ handle.style("top", (context._cellSizes.topHeight - 3) + "px");
501
+ } else if (handle.classed("borderHandle_right")) {
502
+ handle.style("left", (context._cellSizes.width - context._cellSizes.rightWidth) + "px");
503
+ handle.style("top", (context._cellSizes.topHeight + 3) + "px");
504
+ handle.style("height", context._cellSizes.rightHeight + "px");
505
+ } else if (handle.classed("borderHandle_bottom")) {
506
+ handle.style("width", context._cellSizes.width + "px");
507
+ handle.style("top", (context._cellSizes.height - context._cellSizes.bottomHeight - 3) + "px");
508
+ } else if (handle.classed("borderHandle_left")) {
509
+ handle.style("left", context._cellSizes.leftWidth + "px");
510
+ handle.style("height", context._cellSizes.leftHeight + "px");
511
+ handle.style("top", (context._cellSizes.topHeight + 3) + "px");
512
+ }
513
+
514
+ })
515
+ ;
516
+ }
517
+
518
+ getCellSizes() {
519
+ const context = this;
520
+ context._cellSizes = {};
521
+ const contentRect = this.element().node().getBoundingClientRect();
522
+ context._cellSizes.width = contentRect.width;
523
+ context._cellSizes.height = contentRect.height;
524
+ this.element()
525
+ .selectAll("#" + this.id() + " > div > div.border-cell")
526
+ .each(function () {
527
+ const cell = d3Select(this);
528
+ if (typeof cell.node === "function") {
529
+ const rect = cell.node().getBoundingClientRect();
530
+ if (cell.classed("border-cell-top")) {
531
+ context._cellSizes.topHeight = rect.height;
532
+ } else if (cell.classed("border-cell-left")) {
533
+ context._cellSizes.leftWidth = rect.width;
534
+ context._cellSizes.leftHeight = rect.height;
535
+ } else if (cell.classed("border-cell-right")) {
536
+ context._cellSizes.rightWidth = rect.width;
537
+ context._cellSizes.rightHeight = rect.height;
538
+ } else if (cell.classed("border-cell-bottom")) {
539
+ context._cellSizes.bottomHeight = rect.height;
540
+ }
541
+ }
542
+ });
543
+ const sizes = ["height", "width", "topHeight", "bottomHeight", "leftHeight", "rightHeight", "leftWidth", "rightWidth"];
544
+ sizes.forEach(function (size) {
545
+ context._cellSizes[size] = context._cellSizes[size] === undefined ? 0 : context._cellSizes[size];
546
+ });
547
+ }
548
+
549
+ postUpdate(domNode, element) {
550
+ const context = this;
551
+ this.content().forEach(function (n) {
552
+ if (n._element.node() !== null && n.widget()) {
553
+ const prevBox = n.widget().getBBox(false, true);
554
+ const currBox = n.widget().getBBox(true, true);
555
+ if (prevBox.width !== currBox.width || prevBox.height !== currBox.height) {
556
+ context.lazyRender();
557
+ }
558
+ }
559
+ });
560
+ }
561
+
562
+ exit(domNode, element) {
563
+ this.content().forEach(w => w.target(null));
564
+ super.exit(domNode, element);
565
+ }
566
+ }
567
+ Border.prototype._class += " layout_Border";
568
+
569
+ export interface Border {
570
+ designMode(): boolean;
571
+ designMode(_: boolean): this;
572
+
573
+ content(): any[];
574
+ content(_: any[]): this;
575
+
576
+ gutter(): number;
577
+ gutter(_: number): this;
578
+
579
+ topShrinkWrap(): boolean;
580
+ topShrinkWrap(_: boolean): this;
581
+ leftShrinkWrap(): boolean;
582
+ leftShrinkWrap(_: boolean): this;
583
+ rightShrinkWrap(): boolean;
584
+ rightShrinkWrap(_: boolean): this;
585
+ bottomShrinkWrap(): boolean;
586
+ bottomShrinkWrap(_: boolean): this;
587
+
588
+ topSize(): number;
589
+ topSize(_: number): this;
590
+ leftSize(): number;
591
+ leftSize(_: number): this;
592
+ rightSize(): number;
593
+ rightSize(_: number): this;
594
+ bottomSize(): number;
595
+ bottomSize(_: number): this;
596
+
597
+ topPercentage(): number;
598
+ topPercentage(_: number): this;
599
+ leftPercentage(): number;
600
+ leftPercentage(_: number): this;
601
+ rightPercentage(): number;
602
+ rightPercentage(_: number): this;
603
+ bottomPercentage(): number;
604
+ bottomPercentage(_: number): this;
605
+
606
+ surfacePadding(): number;
607
+ surfacePadding(_: number): this;
608
+
609
+ sectionTypes(): any[];
610
+ sectionTypes(_: any[]): this;
611
+ }
612
+
613
+ Border.prototype.publish("designMode", false, "boolean", "Design Mode", null, { tags: ["Basic"] });
614
+
615
+ Border.prototype.publish("content", [], "widgetArray", "widgets", null, { tags: ["Intermediate"] });
616
+
617
+ Border.prototype.publish("gutter", 0, "number", "Gap Between Widgets", null, { tags: ["Basic"] });
618
+
619
+ Border.prototype.publish("topShrinkWrap", false, "boolean", "'Top' Cell shrinks to fit content", null, { tags: ["Intermediate"] });
620
+ Border.prototype.publish("leftShrinkWrap", false, "boolean", "'Left' Cell shrinks to fit content", null, { tags: ["Intermediate"] });
621
+ Border.prototype.publish("rightShrinkWrap", false, "boolean", "'Right' Cell shrinks to fit content", null, { tags: ["Intermediate"] });
622
+ Border.prototype.publish("bottomShrinkWrap", false, "boolean", "'Bottom' Cell shrinks to fit content", null, { tags: ["Intermediate"] });
623
+
624
+ Border.prototype.publish("topSize", 0, "number", "Height of the 'Top' Cell (px)", null, { tags: ["Private"] });
625
+ Border.prototype.publish("leftSize", 0, "number", "Width of the 'Left' Cell (px)", null, { tags: ["Private"] });
626
+ Border.prototype.publish("rightSize", 0, "number", "Width of the 'Right' Cell (px)", null, { tags: ["Private"] });
627
+ Border.prototype.publish("bottomSize", 0, "number", "Height of the 'Bottom' Cell (px)", null, { tags: ["Private"] });
628
+
629
+ Border.prototype.publish("topPercentage", 20, "number", "Percentage (of parent) Height of the 'Top' Cell", null, { tags: ["Private"] });
630
+ Border.prototype.publish("leftPercentage", 20, "number", "Percentage (of parent) Width of the 'Left' Cell", null, { tags: ["Private"] });
631
+ Border.prototype.publish("rightPercentage", 20, "number", "Percentage (of parent) Width of the 'Right' Cell", null, { tags: ["Private"] });
632
+ Border.prototype.publish("bottomPercentage", 20, "number", "Percentage (of parent) Height of the 'Bottom' Cell", null, { tags: ["Private"] });
633
+
634
+ Border.prototype.publish("surfacePadding", 0, "number", "Cell Padding (px)", null, { tags: ["Intermediate"] });
635
+
636
+ Border.prototype.publish("sectionTypes", [], "array", "Section Types sharing an index with 'content' - Used to determine position/size.", null, { tags: ["Private"] });