1 | /*
|
2 | * Copyright (C) 1998-2021 by Northwoods Software Corporation. All Rights Reserved.
|
3 | */
|
4 | var __extends = (this && this.__extends) || (function () {
|
5 | var extendStatics = function (d, b) {
|
6 | extendStatics = Object.setPrototypeOf ||
|
7 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
8 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
9 | return extendStatics(d, b);
|
10 | };
|
11 | return function (d, b) {
|
12 | extendStatics(d, b);
|
13 | function __() { this.constructor = d; }
|
14 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
15 | };
|
16 | })();
|
17 | (function (factory) {
|
18 | if (typeof module === "object" && typeof module.exports === "object") {
|
19 | var v = factory(require, exports);
|
20 | if (v !== undefined) module.exports = v;
|
21 | }
|
22 | else if (typeof define === "function" && define.amd) {
|
23 | define(["require", "exports", "../release/go.js"], factory);
|
24 | }
|
25 | })(function (require, exports) {
|
26 | ;
|
27 | Object.defineProperty(exports, "__esModule", { value: true });
|
28 | exports.TableLayout = void 0;
|
29 | /*
|
30 | * This is an extension and not part of the main GoJS library.
|
31 | * Note that the API for this class may change with any version, even point releases.
|
32 | * If you intend to use an extension in production, you should copy the code to your own source directory.
|
33 | * Extensions can be found in the GoJS kit under the extensions or extensionsTS folders.
|
34 | * See the Extensions intro page (https://gojs.net/latest/intro/extensions.html) for more information.
|
35 | */
|
36 | var go = require("../release/go.js");
|
37 | /**
|
38 | * This {@link Layout} positions non-Link Parts into a table according to the values of
|
39 | * {@link GraphObject#row}, {@link GraphObject#column}, {@link GraphObject#rowSpan}, {@link GraphObject#columnSpan},
|
40 | * {@link GraphObject#alignment}, {@link GraphObject#stretch}.
|
41 | * If the value of GraphObject.stretch is not {@link GraphObject.None}, the Part will be sized
|
42 | * according to the available space in the cell(s).
|
43 | *
|
44 | * You can specify constraints for whole rows or columns by calling
|
45 | * {@link #getRowDefinition} or {@link #getColumnDefinition} and setting one of the following properties:
|
46 | * {@link RowColumnDefinition#alignment}, {@link RowColumnDefinition#height}, {@link RowColumnDefinition#width},
|
47 | * {@link RowColumnDefinition#maximum}, {@link RowColumnDefinition#minimum}, {@link RowColumnDefinition#stretch}.
|
48 | *
|
49 | * The {@link #defaultAlignment} and {@link #defaultStretch} properties apply to all parts if not specified
|
50 | * on the individual Part or in the corresponding row or column definition.
|
51 | *
|
52 | * At the current time, there is no support for separator lines
|
53 | * ({@link RowColumnDefinition#separatorStroke}, {@link RowColumnDefinition#separatorStrokeWidth},
|
54 | * and {@link RowColumnDefinition#separatorDashArray} properties)
|
55 | * nor background ({@link RowColumnDefinition#background} and {@link RowColumnDefinition#coversSeparators} properties).
|
56 | * There is no support for {@link RowColumnDefinition#sizing}, either.
|
57 | *
|
58 | * If you want to experiment with this extension, try the <a href="../../extensionsJSM/Table.html">Table Layout</a> sample.
|
59 | * @category Layout Extension
|
60 | */
|
61 | var TableLayout = /** @class */ (function (_super) {
|
62 | __extends(TableLayout, _super);
|
63 | function TableLayout() {
|
64 | var _this = _super !== null && _super.apply(this, arguments) || this;
|
65 | _this._defaultAlignment = go.Spot.Default;
|
66 | _this._defaultStretch = go.GraphObject.Default;
|
67 | _this._rowDefs = [];
|
68 | _this._colDefs = [];
|
69 | return _this;
|
70 | }
|
71 | Object.defineProperty(TableLayout.prototype, "defaultAlignment", {
|
72 | /**
|
73 | * Gets or sets the alignment to use by default for Parts in rows (vertically) and in columns (horizontally).
|
74 | *
|
75 | * The default value is {@link Spot.Default}.
|
76 | * Setting this property does not raise any events.
|
77 | */
|
78 | get: function () { return this._defaultAlignment; },
|
79 | set: function (val) { this._defaultAlignment = val; },
|
80 | enumerable: false,
|
81 | configurable: true
|
82 | });
|
83 | Object.defineProperty(TableLayout.prototype, "defaultStretch", {
|
84 | /**
|
85 | * Gets or sets whether Parts should be stretched in rows (vertically) and in columns (horizontally).
|
86 | *
|
87 | * The default value is {@link GraphObject.Default}.
|
88 | * Setting this property does not raise any events.
|
89 | */
|
90 | get: function () { return this._defaultStretch; },
|
91 | set: function (val) { this._defaultStretch = val; },
|
92 | enumerable: false,
|
93 | configurable: true
|
94 | });
|
95 | Object.defineProperty(TableLayout.prototype, "rowCount", {
|
96 | /**
|
97 | * This read-only property returns the number of rows in this TableLayout.
|
98 | * This value is only valid after the layout has been performed.
|
99 | */
|
100 | get: function () { return this._rowDefs.length; },
|
101 | enumerable: false,
|
102 | configurable: true
|
103 | });
|
104 | Object.defineProperty(TableLayout.prototype, "columnCount", {
|
105 | /**
|
106 | * This read-only property returns the number of columns in this TableLayout.
|
107 | * This value is only valid after the layout has been performed.
|
108 | */
|
109 | get: function () { return this._colDefs.length; },
|
110 | enumerable: false,
|
111 | configurable: true
|
112 | });
|
113 | /**
|
114 | * Copies properties to a cloned Layout.
|
115 | */
|
116 | TableLayout.prototype.cloneProtected = function (copy) {
|
117 | _super.prototype.cloneProtected.call(this, copy);
|
118 | copy._defaultAlignment = this._defaultAlignment;
|
119 | copy._defaultStretch = this._defaultStretch;
|
120 | for (var i = 0; i < this._rowDefs.length; i++) {
|
121 | var def = this._rowDefs[i];
|
122 | copy._rowDefs.push(def !== undefined ? def.copy() : def);
|
123 | }
|
124 | for (var i = 0; i < this._colDefs.length; i++) {
|
125 | var def = this._colDefs[i];
|
126 | copy._colDefs.push(def !== undefined ? def.copy() : def);
|
127 | }
|
128 | };
|
129 | /**
|
130 | * Gets the {@link RowColumnDefinition} for a particular row in this TableLayout.
|
131 | * If you ask for the definition of a row at or beyond the {@link #rowCount},
|
132 | * it will automatically create one and return it.
|
133 | * @param {number} idx the non-negative zero-based integer row index.
|
134 | * @return {RowColumnDefinition}
|
135 | */
|
136 | TableLayout.prototype.getRowDefinition = function (idx) {
|
137 | if (idx < 0)
|
138 | throw new Error('Row index must be non-negative, not: ' + idx);
|
139 | idx = Math.round(idx);
|
140 | var defs = this._rowDefs;
|
141 | var d = defs[idx];
|
142 | if (d === undefined) {
|
143 | d = new go.RowColumnDefinition();
|
144 | // .panel remains null
|
145 | d.isRow = true;
|
146 | d.index = idx;
|
147 | defs[idx] = d;
|
148 | }
|
149 | return d;
|
150 | };
|
151 | /**
|
152 | * Returns the row at a given y-coordinate in document coordinates.
|
153 | * This information is only valid when this layout has been performed and {@link Layout#isValidLayout} is true.
|
154 | *
|
155 | * If the point is above row 0, this method returns -1.
|
156 | * If the point below the last row, this returns the last row + 1.
|
157 | * @param {number} y
|
158 | * @return {number} a zero-based integer
|
159 | * @see {@link #findColumnForDocumentX}
|
160 | */
|
161 | TableLayout.prototype.findRowForDocumentY = function (y) {
|
162 | y -= this.arrangementOrigin.y;
|
163 | if (y < 0)
|
164 | return -1;
|
165 | var total = 0.0;
|
166 | var it = this._rowDefs;
|
167 | var l = it.length;
|
168 | for (var i = 0; i < l; i++) {
|
169 | var def = it[i];
|
170 | if (def === undefined)
|
171 | continue;
|
172 | total += def.total;
|
173 | if (y < total) {
|
174 | return i;
|
175 | }
|
176 | }
|
177 | return l;
|
178 | };
|
179 | /**
|
180 | * Gets the {@link RowColumnDefinition} for a particular column in this TableLayout.
|
181 | * If you ask for the definition of a column at or beyond the {@link #columnCount},
|
182 | * it will automatically create one and return it.
|
183 | * @param {number} idx the non-negative zero-based integer column index.
|
184 | * @return {RowColumnDefinition}
|
185 | */
|
186 | TableLayout.prototype.getColumnDefinition = function (idx) {
|
187 | if (idx < 0)
|
188 | throw new Error('Column index must be non-negative, not: ' + idx);
|
189 | idx = Math.round(idx);
|
190 | var defs = this._colDefs;
|
191 | var d = defs[idx];
|
192 | if (d === undefined) {
|
193 | d = new go.RowColumnDefinition();
|
194 | // .panel remains null
|
195 | d.isRow = false;
|
196 | d.index = idx;
|
197 | defs[idx] = d;
|
198 | }
|
199 | return d;
|
200 | };
|
201 | /**
|
202 | * Returns the cell at a given x-coordinate in document coordinates.
|
203 | * This information is only valid when this layout has been performed and {@link Layout#isValidLayout} is true.
|
204 | *
|
205 | * If the point is to left of the column 0, this method returns -1.
|
206 | * If the point to to the right of the last column, this returns the last column + 1.
|
207 | * @param {number} x
|
208 | * @return {number} a zero-based integer
|
209 | * @see {@link #findRowForDocumentY}
|
210 | */
|
211 | TableLayout.prototype.findColumnForDocumentX = function (x) {
|
212 | x -= this.arrangementOrigin.x;
|
213 | if (x < 0)
|
214 | return -1;
|
215 | var total = 0.0;
|
216 | var it = this._colDefs;
|
217 | var l = it.length;
|
218 | for (var i = 0; i < l; i++) {
|
219 | var def = it[i];
|
220 | if (def === undefined)
|
221 | continue;
|
222 | total += def.total;
|
223 | if (x < total) {
|
224 | return i;
|
225 | }
|
226 | }
|
227 | return l;
|
228 | };
|
229 | /**
|
230 | * @hidden @internal
|
231 | * Only ever called from TableLayout's measure and arrange
|
232 | */
|
233 | TableLayout.prototype.getEffectiveTableStretch = function (child, row, col) {
|
234 | var effectivestretch = child.stretch;
|
235 | if (effectivestretch !== go.GraphObject.Default)
|
236 | return effectivestretch;
|
237 | // which directions are we stretching?
|
238 | // undefined = default
|
239 | var horizontal;
|
240 | var vertical;
|
241 | switch (row.stretch) {
|
242 | case go.GraphObject.Default:
|
243 | case go.GraphObject.Horizontal: break;
|
244 | case go.GraphObject.Vertical:
|
245 | vertical = true;
|
246 | break;
|
247 | case go.GraphObject.Fill:
|
248 | vertical = true;
|
249 | break;
|
250 | }
|
251 | switch (col.stretch) {
|
252 | case go.GraphObject.Default:
|
253 | case go.GraphObject.Vertical: break;
|
254 | case go.GraphObject.Horizontal:
|
255 | horizontal = true;
|
256 | break;
|
257 | case go.GraphObject.Fill:
|
258 | horizontal = true;
|
259 | break;
|
260 | }
|
261 | var str = this.defaultStretch;
|
262 | if (horizontal === undefined && (str === go.GraphObject.Horizontal || str === go.GraphObject.Fill)) {
|
263 | horizontal = true;
|
264 | }
|
265 | else {
|
266 | horizontal = false;
|
267 | }
|
268 | if (vertical === undefined && (str === go.GraphObject.Vertical || str === go.GraphObject.Fill)) {
|
269 | vertical = true;
|
270 | }
|
271 | else {
|
272 | vertical = false;
|
273 | }
|
274 | if (horizontal === true && vertical === true)
|
275 | return go.GraphObject.Fill;
|
276 | if (horizontal === true)
|
277 | return go.GraphObject.Horizontal;
|
278 | if (vertical === true)
|
279 | return go.GraphObject.Vertical;
|
280 | return go.GraphObject.None; // Everything else is none by default
|
281 | };
|
282 | /**
|
283 | * This method performs the measuring and arranging of the table, assiging positions to each part.
|
284 | * @param {Iterable.<Part>} coll A collection of {@link Part}s.
|
285 | */
|
286 | TableLayout.prototype.doLayout = function (coll) {
|
287 | this.arrangementOrigin = this.initialOrigin(this.arrangementOrigin);
|
288 | // put all eligible Parts that are not Links into an Array
|
289 | var parts = new go.List();
|
290 | this.collectParts(coll).each(function (p) {
|
291 | if (!(p instanceof go.Link)) {
|
292 | parts.add(p);
|
293 | }
|
294 | });
|
295 | if (this.diagram !== null) {
|
296 | this.diagram.startTransaction('TableLayout');
|
297 | var union = new go.Size();
|
298 | // this calls .beforeMeasure(parts, rowcol)
|
299 | var rowcol = this.measureTable(Infinity, Infinity, parts, union, 0, 0);
|
300 | this.arrangeTable(parts, union, rowcol);
|
301 | this.afterArrange(parts, rowcol);
|
302 | this.diagram.commitTransaction('TableLayout');
|
303 | }
|
304 | };
|
305 | /**
|
306 | * Override this method in order to perform some operations before measuring.
|
307 | * By default this method does nothing.
|
308 | * @expose
|
309 | */
|
310 | TableLayout.prototype.beforeMeasure = function (parts, rowcol) { };
|
311 | /**
|
312 | * Override this method in order to perform some operations after arranging.
|
313 | * By default this method does nothing.
|
314 | * @expose
|
315 | */
|
316 | TableLayout.prototype.afterArrange = function (parts, rowcol) { };
|
317 | /**
|
318 | * @hidden @internal
|
319 | */
|
320 | TableLayout.prototype.measureTable = function (width, height, children, union, minw, minh) {
|
321 | var l = children.length;
|
322 | // Make the array that holds [rows][cols] of the table
|
323 | var rowcol = []; // saved (so no temp array) starts as an array of rows, will end up [row][col][cell]
|
324 | for (var i = 0; i < l; i++) {
|
325 | var child = children.elt(i);
|
326 | if (!rowcol[child.row]) {
|
327 | rowcol[child.row] = []; // make new column for this row
|
328 | }
|
329 | if (!rowcol[child.row][child.column]) {
|
330 | rowcol[child.row][child.column] = []; // new list for this cell
|
331 | }
|
332 | rowcol[child.row][child.column].push(child); // push child into right cell
|
333 | }
|
334 | this.beforeMeasure(children, rowcol);
|
335 | // Reset the row/col definitions because the ones from last measure are irrelevant
|
336 | var resetCols = []; // keep track of which columns we've already reset
|
337 | // Objects that span multiple columns and
|
338 | var spanners = [];
|
339 | var nosize = [];
|
340 | // These hashes are used to tally the number of rows and columns that do not have a size
|
341 | var nosizeCols = { count: 0 };
|
342 | var nosizeRows = { count: 0 };
|
343 | var colleft = width;
|
344 | var rowleft = height;
|
345 | var defs = this._rowDefs;
|
346 | l = defs.length;
|
347 | for (var i = 0; i < l; i++) {
|
348 | var def = defs[i];
|
349 | if (def !== undefined)
|
350 | def.actual = 0;
|
351 | }
|
352 | defs = this._colDefs;
|
353 | l = defs.length;
|
354 | for (var i = 0; i < l; i++) {
|
355 | var def = defs[i];
|
356 | if (def !== undefined)
|
357 | def.actual = 0;
|
358 | }
|
359 | var lrow = rowcol.length; // number of rows
|
360 | var lcol = 0;
|
361 | for (var i = 0; i < lrow; i++) {
|
362 | if (!rowcol[i])
|
363 | continue;
|
364 | lcol = Math.max(lcol, rowcol[i].length); // column length in this row
|
365 | }
|
366 | // Go through each cell (first pass)
|
367 | var amt = 0.0;
|
368 | lrow = rowcol.length; // number of rows
|
369 | for (var i = 0; i < lrow; i++) {
|
370 | if (!rowcol[i])
|
371 | continue;
|
372 | lcol = rowcol[i].length; // column length in this row
|
373 | var rowHerald = this.getRowDefinition(i);
|
374 | rowHerald.measured = 0; // Reset rows (only on first pass)
|
375 | for (var j = 0; j < lcol; j++) {
|
376 | // foreach column j in row i...
|
377 | if (!rowcol[i][j])
|
378 | continue;
|
379 | var colHerald = this.getColumnDefinition(j);
|
380 | if (resetCols[j] === undefined) { // make sure we only reset these once
|
381 | colHerald.measured = 0;
|
382 | resetCols[j] = true;
|
383 | }
|
384 | var cell = rowcol[i][j];
|
385 | var len = cell.length;
|
386 | for (var k = 0; k < len; k++) {
|
387 | // foreach element in cell, measure
|
388 | var child = cell[k];
|
389 | // Skip children that span more than one row or column or do not have a set size
|
390 | var spanner = (child.rowSpan > 1 || child.columnSpan > 1);
|
391 | if (spanner) {
|
392 | spanners.push(child);
|
393 | // We used to not measure spanners twice, but now we do
|
394 | // The reason is that there may be a row whose size
|
395 | // is dictated by an object with columnSpan 2+ and vice versa
|
396 | // continue;
|
397 | }
|
398 | var marg = child.margin;
|
399 | var margw = marg.right + marg.left;
|
400 | var margh = marg.top + marg.bottom;
|
401 | var stretch = this.getEffectiveTableStretch(child, rowHerald, colHerald);
|
402 | var dsize = child.resizeObject.desiredSize;
|
403 | var realwidth = !(isNaN(dsize.width));
|
404 | var realheight = !(isNaN(dsize.height));
|
405 | var realsize = realwidth && realheight;
|
406 | if (!spanner && stretch !== go.GraphObject.None && !realsize) {
|
407 | if (nosizeCols[j] === undefined && (stretch === go.GraphObject.Fill || stretch === go.GraphObject.Horizontal)) {
|
408 | nosizeCols[j] = -1;
|
409 | nosizeCols.count++;
|
410 | }
|
411 | if (nosizeRows[i] === undefined && (stretch === go.GraphObject.Fill || stretch === go.GraphObject.Vertical)) {
|
412 | nosizeRows[i] = -1;
|
413 | nosizeRows.count++;
|
414 | }
|
415 | nosize.push(child);
|
416 | }
|
417 | if (stretch !== go.GraphObject.None) {
|
418 | var unrestrictedSize = new go.Size(NaN, NaN);
|
419 | // if (stretch !== go.GraphObject.Horizontal) unrestrictedSize.height = rowHerald.minimum;
|
420 | // if (stretch !== go.GraphObject.Vertical) unrestrictedSize.width = colHerald.minimum;
|
421 | // ??? allow resizing during measure phase
|
422 | child.resizeObject.desiredSize = unrestrictedSize;
|
423 | child.ensureBounds();
|
424 | }
|
425 | var m = this.getLayoutBounds(child);
|
426 | var mwidth = Math.max(m.width + margw, 0);
|
427 | var mheight = Math.max(m.height + margh, 0);
|
428 | // Make sure the heralds have the right layout size
|
429 | // the row/column should use the largest measured size of any
|
430 | // GraphObject contained, constrained by mins and maxes
|
431 | if (child.rowSpan === 1 && (realheight || stretch === go.GraphObject.None || stretch === go.GraphObject.Horizontal)) {
|
432 | var def = this.getRowDefinition(i);
|
433 | amt = Math.max(mheight - def.actual, 0);
|
434 | if (amt > rowleft)
|
435 | amt = rowleft;
|
436 | def.measured = def.measured + amt;
|
437 | def.actual = def.actual + amt;
|
438 | rowleft = Math.max(rowleft - amt, 0);
|
439 | }
|
440 | if (child.columnSpan === 1 && (realwidth || stretch === go.GraphObject.None || stretch === go.GraphObject.Vertical)) {
|
441 | var def = this.getColumnDefinition(j);
|
442 | amt = Math.max(mwidth - def.actual, 0);
|
443 | if (amt > colleft)
|
444 | amt = colleft;
|
445 | def.measured = def.measured + amt;
|
446 | def.actual = def.actual + amt;
|
447 | colleft = Math.max(colleft - amt, 0);
|
448 | }
|
449 | } // end cell
|
450 | } // end col
|
451 | } // end row
|
452 | // For objects of no desired size we allocate what is left as we go,
|
453 | // or else what is already in the column
|
454 | var totalColWidth = 0.0;
|
455 | var totalRowHeight = 0.0;
|
456 | l = this.columnCount;
|
457 | for (var i = 0; i < l; i++) {
|
458 | if (this._colDefs[i] === undefined)
|
459 | continue;
|
460 | totalColWidth += this.getColumnDefinition(i).measured;
|
461 | }
|
462 | l = this.rowCount;
|
463 | for (var i = 0; i < l; i++) {
|
464 | if (this._rowDefs[i] === undefined)
|
465 | continue;
|
466 | totalRowHeight += this.getRowDefinition(i).measured;
|
467 | }
|
468 | colleft = Math.max(width - totalColWidth, 0);
|
469 | rowleft = Math.max(height - totalRowHeight, 0);
|
470 | var originalrowleft = rowleft;
|
471 | var originalcolleft = colleft;
|
472 | // Determine column sizes for the yet-to-be-sized columns
|
473 | l = nosize.length;
|
474 | for (var i = 0; i < l; i++) {
|
475 | var child = nosize[i];
|
476 | var rowHerald = this.getRowDefinition(child.row);
|
477 | var colHerald = this.getColumnDefinition(child.column);
|
478 | // We want to gather the largest difference between desired and expected col/row sizes
|
479 | var mb = this.getLayoutBounds(child);
|
480 | var marg = child.margin;
|
481 | var margw = marg.right + marg.left;
|
482 | var margh = marg.top + marg.bottom;
|
483 | if (colHerald.measured === 0 && nosizeCols[child.column] !== undefined) {
|
484 | nosizeCols[child.column] = Math.max(mb.width + margw, nosizeCols[child.column]);
|
485 | }
|
486 | else {
|
487 | nosizeCols[child.column] = null; // obey the column herald
|
488 | }
|
489 | if (rowHerald.measured === 0 && nosizeRows[child.row] !== undefined) {
|
490 | nosizeRows[child.row] = Math.max(mb.height + margh, nosizeRows[child.row]);
|
491 | }
|
492 | else {
|
493 | nosizeRows[child.row] = null; // obey the row herald
|
494 | }
|
495 | }
|
496 | // we now have the size that all these columns prefer to be
|
497 | // we also have the amount left over
|
498 | var desiredRowTotal = 0.0;
|
499 | var desiredColTotal = 0.0;
|
500 | for (var i in nosizeRows) {
|
501 | if (i !== 'count')
|
502 | desiredRowTotal += nosizeRows[i];
|
503 | }
|
504 | for (var i in nosizeCols) {
|
505 | if (i !== 'count')
|
506 | desiredColTotal += nosizeCols[i];
|
507 | }
|
508 | var allowedSize = new go.Size(); // used in stretch and span loops
|
509 | // Deal with objects that have a stretch
|
510 | for (var i = 0; i < l; i++) {
|
511 | var child = nosize[i];
|
512 | var rowHerald = this.getRowDefinition(child.row);
|
513 | var colHerald = this.getColumnDefinition(child.column);
|
514 | var w = 0.0;
|
515 | if (isFinite(colHerald.width)) {
|
516 | w = colHerald.width;
|
517 | }
|
518 | else {
|
519 | if (isFinite(colleft) && nosizeCols[child.column] !== null) {
|
520 | if (desiredColTotal === 0)
|
521 | w = colHerald.actual + colleft;
|
522 | else
|
523 | w = /*colHerald.actual +*/ ((nosizeCols[child.column] / desiredColTotal) * originalcolleft);
|
524 | }
|
525 | else {
|
526 | // Only use colHerald.actual if it was nonzero before this loop
|
527 | if (nosizeCols[child.column] !== null)
|
528 | w = colleft;
|
529 | else
|
530 | w = colHerald.actual || colleft;
|
531 | // w = nosizeCols[child.column] || colleft; // Older, less correct way
|
532 | }
|
533 | w = Math.max(0, w - colHerald.computeEffectiveSpacing());
|
534 | }
|
535 | var h = 0.0;
|
536 | if (isFinite(rowHerald.height)) {
|
537 | h = rowHerald.height;
|
538 | }
|
539 | else {
|
540 | if (isFinite(rowleft) && nosizeRows[child.row] !== null) {
|
541 | if (desiredRowTotal === 0)
|
542 | h = rowHerald.actual + rowleft;
|
543 | else
|
544 | h = /*rowHerald.actual +*/ ((nosizeRows[child.row] / desiredRowTotal) * originalrowleft);
|
545 | }
|
546 | else {
|
547 | // Only use rowHerald.actual if it was nonzero before this loop
|
548 | if (nosizeRows[child.row] !== null)
|
549 | h = rowleft;
|
550 | else
|
551 | h = rowHerald.actual || rowleft;
|
552 | // h = nosizeRows[child.row] || rowleft; // Older, less correct way
|
553 | }
|
554 | h = Math.max(0, h - rowHerald.computeEffectiveSpacing());
|
555 | }
|
556 | allowedSize.setTo(Math.max(colHerald.minimum, Math.min(w, colHerald.maximum)), Math.max(rowHerald.minimum, Math.min(h, rowHerald.maximum)));
|
557 | // Which way do we care about fill:
|
558 | var stretch = this.getEffectiveTableStretch(child, rowHerald, colHerald);
|
559 | // This used to set allowedSize height/width to Infinity,
|
560 | // but we can only set it to the current row/column space, plus rowleft/colleft values, at most.
|
561 | switch (stretch) {
|
562 | case go.GraphObject.Horizontal: // H stretch means it can be as large as its wants vertically
|
563 | allowedSize.height = Math.max(allowedSize.height, rowHerald.actual + rowleft);
|
564 | break;
|
565 | case go.GraphObject.Vertical: // vice versa
|
566 | allowedSize.width = Math.max(allowedSize.width, colHerald.actual + colleft);
|
567 | break;
|
568 | }
|
569 | var marg = child.margin;
|
570 | var margw = marg.right + marg.left;
|
571 | var margh = marg.top + marg.bottom;
|
572 | var m = this.getLayoutBounds(child);
|
573 | var mwidth = Math.max(m.width + margw, 0);
|
574 | var mheight = Math.max(m.height + margh, 0);
|
575 | if (isFinite(colleft))
|
576 | mwidth = Math.min(mwidth, allowedSize.width);
|
577 | if (isFinite(rowleft))
|
578 | mheight = Math.min(mheight, allowedSize.height);
|
579 | var oldAmount = 0.0;
|
580 | oldAmount = rowHerald.actual;
|
581 | rowHerald.actual = Math.max(rowHerald.actual, mheight);
|
582 | rowHerald.measured = Math.max(rowHerald.measured, mheight);
|
583 | amt = rowHerald.actual - oldAmount;
|
584 | rowleft = Math.max(rowleft - amt, 0);
|
585 | oldAmount = colHerald.actual;
|
586 | colHerald.actual = Math.max(colHerald.actual, mwidth);
|
587 | colHerald.measured = Math.max(colHerald.measured, mwidth);
|
588 | amt = colHerald.actual - oldAmount;
|
589 | colleft = Math.max(colleft - amt, 0);
|
590 | } // end no fixed size objects
|
591 | // Go through each object that spans multiple rows or columns
|
592 | var additionalSpan = new go.Size();
|
593 | var actualSizeRows = [];
|
594 | var actualSizeColumns = [];
|
595 | l = spanners.length;
|
596 | if (l !== 0) {
|
597 | // record the actual sizes of every row/column before measuring spanners
|
598 | // because they will change during the loop and we want to use their 'before' values
|
599 | for (var i = 0; i < lrow; i++) {
|
600 | if (!rowcol[i])
|
601 | continue;
|
602 | lcol = rowcol[i].length; // column length in this row
|
603 | var rowHerald = this.getRowDefinition(i);
|
604 | actualSizeRows[i] = rowHerald.actual;
|
605 | for (var j = 0; j < lcol; j++) {
|
606 | // foreach column j in row i...
|
607 | if (!rowcol[i][j])
|
608 | continue;
|
609 | var colHerald = this.getColumnDefinition(j);
|
610 | actualSizeColumns[j] = colHerald.actual;
|
611 | }
|
612 | }
|
613 | }
|
614 | for (var i = 0; i < l; i++) {
|
615 | var child = spanners[i];
|
616 | var rowHerald = this.getRowDefinition(child.row);
|
617 | var colHerald = this.getColumnDefinition(child.column);
|
618 | // If there's a set column width/height we don't care about the given width/height
|
619 | allowedSize.setTo(Math.max(colHerald.minimum, Math.min(width, colHerald.maximum)), Math.max(rowHerald.minimum, Math.min(height, rowHerald.maximum)));
|
620 | // If it is a spanner and has a fill:
|
621 | var stretch = this.getEffectiveTableStretch(child, rowHerald, colHerald);
|
622 | switch (stretch) {
|
623 | case go.GraphObject.Fill:
|
624 | if (actualSizeColumns[colHerald.index] !== 0)
|
625 | allowedSize.width = Math.min(allowedSize.width, actualSizeColumns[colHerald.index]);
|
626 | if (actualSizeRows[rowHerald.index] !== 0)
|
627 | allowedSize.height = Math.min(allowedSize.height, actualSizeRows[rowHerald.index]);
|
628 | break;
|
629 | case go.GraphObject.Horizontal:
|
630 | if (actualSizeColumns[colHerald.index] !== 0)
|
631 | allowedSize.width = Math.min(allowedSize.width, actualSizeColumns[colHerald.index]);
|
632 | break;
|
633 | case go.GraphObject.Vertical:
|
634 | if (actualSizeRows[rowHerald.index] !== 0)
|
635 | allowedSize.height = Math.min(allowedSize.height, actualSizeRows[rowHerald.index]);
|
636 | break;
|
637 | }
|
638 | // If there's a set column width/height we don't care about any of the above:
|
639 | if (isFinite(colHerald.width))
|
640 | allowedSize.width = colHerald.width;
|
641 | if (isFinite(rowHerald.height))
|
642 | allowedSize.height = rowHerald.height;
|
643 | // take into account rowSpan and columnSpan
|
644 | var def = this.getRowDefinition(child.row);
|
645 | additionalSpan.setTo(0, 0);
|
646 | for (var n = 1; n < child.rowSpan; n++) {
|
647 | if (child.row + n >= this.rowCount)
|
648 | break; // if the row exists at all
|
649 | def = this.getRowDefinition(child.row + n);
|
650 | amt = 0;
|
651 | if (stretch === go.GraphObject.Fill || stretch === go.GraphObject.Vertical) {
|
652 | amt = Math.max(def.minimum, (actualSizeRows[child.row + n] === 0) ? def.maximum : Math.min(actualSizeRows[child.row + n], def.maximum));
|
653 | }
|
654 | else {
|
655 | amt = Math.max(def.minimum, isNaN(def.height) ? def.maximum : Math.min(def.height, def.maximum));
|
656 | }
|
657 | additionalSpan.height += amt;
|
658 | }
|
659 | for (var n = 1; n < child.columnSpan; n++) {
|
660 | if (child.column + n >= this.columnCount)
|
661 | break; // if the col exists at all
|
662 | def = this.getColumnDefinition(child.column + n);
|
663 | amt = 0;
|
664 | if (stretch === go.GraphObject.Fill || stretch === go.GraphObject.Horizontal) {
|
665 | amt = Math.max(def.minimum, (actualSizeColumns[child.column + n] === 0) ? def.maximum : Math.min(actualSizeColumns[child.column + n], def.maximum));
|
666 | }
|
667 | else {
|
668 | amt = Math.max(def.minimum, isNaN(def.width) ? def.maximum : Math.min(def.width, def.maximum));
|
669 | }
|
670 | additionalSpan.width += amt;
|
671 | }
|
672 | allowedSize.width += additionalSpan.width;
|
673 | allowedSize.height += additionalSpan.height;
|
674 | var marg = child.margin;
|
675 | var margw = marg.right + marg.left;
|
676 | var margh = marg.top + marg.bottom;
|
677 | var m = this.getLayoutBounds(child);
|
678 | var mwidth = Math.max(m.width + margw, 0);
|
679 | var mheight = Math.max(m.height + margh, 0);
|
680 | var totalRow = 0.0;
|
681 | for (var n = 0; n < child.rowSpan; n++) {
|
682 | if (child.row + n >= this.rowCount)
|
683 | break; // if the row exists at all
|
684 | def = this.getRowDefinition(child.row + n);
|
685 | totalRow += def.total || 0;
|
686 | }
|
687 | // def is the last row definition
|
688 | if (totalRow < mheight) {
|
689 | var roomLeft = mheight - totalRow;
|
690 | while (roomLeft > 0) { // Add the extra to the first row that allows us to
|
691 | var act = def.actual || 0;
|
692 | if (isNaN(def.height) && def.maximum > act) {
|
693 | def.actual = Math.min(def.maximum, act + roomLeft);
|
694 | if (def.actual !== act)
|
695 | roomLeft -= def.actual - act;
|
696 | }
|
697 | if (def.index - 1 === -1)
|
698 | break;
|
699 | def = this.getRowDefinition(def.index - 1);
|
700 | }
|
701 | }
|
702 | var totalCol = 0.0;
|
703 | for (var n = 0; n < child.columnSpan; n++) {
|
704 | if (child.column + n >= this.columnCount)
|
705 | break; // if the col exists at all
|
706 | def = this.getColumnDefinition(child.column + n);
|
707 | totalCol += def.total || 0;
|
708 | }
|
709 | // def is the last col definition
|
710 | if (totalCol < mwidth) {
|
711 | var roomLeft = mwidth - totalCol;
|
712 | while (roomLeft > 0) { // Add the extra to the first row that allows us to
|
713 | var act = def.actual || 0;
|
714 | if (isNaN(def.width) && def.maximum > act) {
|
715 | def.actual = Math.min(def.maximum, act + roomLeft);
|
716 | if (def.actual !== act)
|
717 | roomLeft -= def.actual - act;
|
718 | }
|
719 | if (def.index - 1 === -1)
|
720 | break;
|
721 | def = this.getColumnDefinition(def.index - 1);
|
722 | }
|
723 | }
|
724 | } // end spanning objects
|
725 | l = this.columnCount;
|
726 | for (var i = 0; i < l; i++) {
|
727 | if (this._colDefs[i] === undefined)
|
728 | continue;
|
729 | var def = this.getColumnDefinition(i);
|
730 | def.position = union.width;
|
731 | if (def.actual !== 0) {
|
732 | union.width += def.actual;
|
733 | union.width += def.computeEffectiveSpacing();
|
734 | }
|
735 | }
|
736 | l = this.rowCount;
|
737 | for (var i = 0; i < l; i++) {
|
738 | if (this._rowDefs[i] === undefined)
|
739 | continue;
|
740 | var def = this.getRowDefinition(i);
|
741 | def.position = union.height;
|
742 | if (def.actual !== 0) {
|
743 | union.height += def.actual;
|
744 | union.height += def.computeEffectiveSpacing();
|
745 | }
|
746 | }
|
747 | // save these for arrange (destroy them or not? Possibly needed for drawing spacers)
|
748 | return rowcol;
|
749 | }; // end measureTable
|
750 | /**
|
751 | * @hidden @internal
|
752 | */
|
753 | TableLayout.prototype.arrangeTable = function (children, union, rowcol) {
|
754 | var l = children.length;
|
755 | var originx = this.arrangementOrigin.x;
|
756 | var originy = this.arrangementOrigin.y;
|
757 | var x = 0.0;
|
758 | var y = 0.0;
|
759 | var lrow = rowcol.length; // number of rows
|
760 | var lcol = 0;
|
761 | for (var i = 0; i < lrow; i++) {
|
762 | if (!rowcol[i])
|
763 | continue;
|
764 | lcol = Math.max(lcol, rowcol[i].length); // column length in this row
|
765 | }
|
766 | var additionalSpan = new go.Size();
|
767 | // Find cell space and arrange objects:
|
768 | for (var i = 0; i < lrow; i++) {
|
769 | if (!rowcol[i])
|
770 | continue;
|
771 | lcol = rowcol[i].length; // column length in this row
|
772 | var rowHerald = this.getRowDefinition(i);
|
773 | y = originy + rowHerald.position + rowHerald.computeEffectiveSpacingTop();
|
774 | for (var j = 0; j < lcol; j++) {
|
775 | // foreach column j in row i...
|
776 | if (!rowcol[i][j])
|
777 | continue;
|
778 | var colHerald = this.getColumnDefinition(j);
|
779 | x = originx + colHerald.position + colHerald.computeEffectiveSpacingTop();
|
780 | var cell = rowcol[i][j];
|
781 | var len = cell.length;
|
782 | for (var k = 0; k < len; k++) {
|
783 | // foreach element in cell
|
784 | var child = cell[k];
|
785 | // add to layoutWidth/Height any additional span
|
786 | additionalSpan.setTo(0, 0);
|
787 | for (var n = 1; n < child.rowSpan; n++) {
|
788 | // if the row exists at all
|
789 | if (i + n >= this.rowCount)
|
790 | break;
|
791 | var rh = this.getRowDefinition(i + n);
|
792 | additionalSpan.height += rh.total;
|
793 | }
|
794 | for (var n = 1; n < child.columnSpan; n++) {
|
795 | // if the col exists at all
|
796 | if (j + n >= this.columnCount)
|
797 | break;
|
798 | var ch = this.getColumnDefinition(j + n);
|
799 | additionalSpan.width += ch.total;
|
800 | }
|
801 | // Construct containing rect (cell):
|
802 | // total width and height of the cell that an object could possibly be created in
|
803 | var colwidth = colHerald.actual + additionalSpan.width;
|
804 | var rowheight = rowHerald.actual + additionalSpan.height;
|
805 | // construct a rect that represents the total cell size allowed for this object
|
806 | var ar = new go.Rect();
|
807 | ar.x = x;
|
808 | ar.y = y;
|
809 | ar.width = colwidth;
|
810 | ar.height = rowheight;
|
811 | // Also keep them for clip values
|
812 | var cellx = x;
|
813 | var celly = y;
|
814 | var cellw = colwidth;
|
815 | var cellh = rowheight;
|
816 | // Ending rows/col might have actual spaces that are larger than the remaining space
|
817 | // Modify them for clipping regions
|
818 | if (x + colwidth > union.width)
|
819 | cellw = Math.max(union.width - x, 0);
|
820 | if (y + rowheight > union.height)
|
821 | cellh = Math.max(union.height - y, 0);
|
822 | // Construct alignment:
|
823 | var align = child.alignment;
|
824 | var alignx = 0.0;
|
825 | var aligny = 0.0;
|
826 | var alignoffsetX = 0.0;
|
827 | var alignoffsetY = 0.0;
|
828 | if (align.isDefault()) {
|
829 | align = this.defaultAlignment;
|
830 | if (!align.isSpot())
|
831 | align = go.Spot.Center;
|
832 | alignx = align.x;
|
833 | aligny = align.y;
|
834 | alignoffsetX = align.offsetX;
|
835 | alignoffsetY = align.offsetY;
|
836 | var ca = colHerald.alignment;
|
837 | var ra = rowHerald.alignment;
|
838 | if (ca.isSpot()) {
|
839 | alignx = ca.x;
|
840 | alignoffsetX = ca.offsetX;
|
841 | }
|
842 | if (ra.isSpot()) {
|
843 | aligny = ra.y;
|
844 | alignoffsetY = ra.offsetY;
|
845 | }
|
846 | }
|
847 | else {
|
848 | alignx = align.x;
|
849 | aligny = align.y;
|
850 | alignoffsetX = align.offsetX;
|
851 | alignoffsetY = align.offsetY;
|
852 | }
|
853 | // same as if (!align.isSpot()) align = go.Spot.Center;
|
854 | if (isNaN(alignx) || isNaN(aligny)) {
|
855 | alignx = 0.5;
|
856 | aligny = 0.5;
|
857 | alignoffsetX = 0;
|
858 | alignoffsetY = 0;
|
859 | }
|
860 | var width = 0.0;
|
861 | var height = 0.0;
|
862 | var marg = child.margin;
|
863 | var margw = marg.left + marg.right;
|
864 | var margh = marg.top + marg.bottom;
|
865 | var stretch = this.getEffectiveTableStretch(child, rowHerald, colHerald);
|
866 | if ( /* isNaN(child.resizeObject.desiredSize.width) && */(stretch === go.GraphObject.Fill || stretch === go.GraphObject.Horizontal)) {
|
867 | width = Math.max(colwidth - margw, 0);
|
868 | }
|
869 | else {
|
870 | width = this.getLayoutBounds(child).width;
|
871 | }
|
872 | if ( /* isNaN(child.resizeObject.desiredSize.height) && */(stretch === go.GraphObject.Fill || stretch === go.GraphObject.Vertical)) {
|
873 | height = Math.max(rowheight - margh, 0);
|
874 | }
|
875 | else {
|
876 | height = this.getLayoutBounds(child).height;
|
877 | }
|
878 | // min and max override any stretch values
|
879 | var max = child.maxSize;
|
880 | var min = child.minSize;
|
881 | width = Math.min(max.width, width);
|
882 | height = Math.min(max.height, height);
|
883 | width = Math.max(min.width, width);
|
884 | height = Math.max(min.height, height);
|
885 | var widthmarg = width + margw;
|
886 | var heightmarg = height + margh;
|
887 | ar.x += (ar.width * alignx) - (widthmarg * alignx) + alignoffsetX + marg.left;
|
888 | ar.y += (ar.height * aligny) - (heightmarg * aligny) + alignoffsetY + marg.top;
|
889 | child.moveTo(ar.x, ar.y);
|
890 | if (stretch !== go.GraphObject.None) {
|
891 | child.resizeObject.desiredSize = new go.Size(width, height);
|
892 | }
|
893 | } // end cell
|
894 | } // end col
|
895 | } // end row
|
896 | }; // end arrangeTable
|
897 | return TableLayout;
|
898 | }(go.Layout)); // end TableLayout class
|
899 | exports.TableLayout = TableLayout;
|
900 | });
|