@refinitiv-ui/efx-grid 6.0.13 → 6.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/lib/core/dist/core.js +1209 -160
  2. package/lib/core/dist/core.min.js +1 -1
  3. package/lib/core/es6/data/DataCache.js +1 -1
  4. package/lib/core/es6/data/DataTable.d.ts +18 -3
  5. package/lib/core/es6/data/DataTable.js +203 -17
  6. package/lib/core/es6/data/DataView.d.ts +8 -1
  7. package/lib/core/es6/data/DataView.js +30 -2
  8. package/lib/core/es6/data/Segment.d.ts +36 -11
  9. package/lib/core/es6/data/Segment.js +575 -59
  10. package/lib/core/es6/data/SegmentCollection.d.ts +15 -1
  11. package/lib/core/es6/data/SegmentCollection.js +236 -80
  12. package/lib/core/es6/grid/Core.js +1 -1
  13. package/lib/grid/index.js +1 -1
  14. package/lib/row-segmenting/es6/RowSegmenting.d.ts +2 -0
  15. package/lib/row-segmenting/es6/RowSegmenting.js +26 -3
  16. package/lib/rt-grid/dist/rt-grid.js +1115 -158
  17. package/lib/rt-grid/dist/rt-grid.min.js +1 -1
  18. package/lib/rt-grid/es6/Grid.d.ts +2 -0
  19. package/lib/rt-grid/es6/Grid.js +53 -0
  20. package/lib/rt-grid/es6/RowDefinition.js +22 -2
  21. package/lib/tr-grid-column-grouping/es6/ColumnGrouping.d.ts +1 -0
  22. package/lib/tr-grid-column-grouping/es6/ColumnGrouping.js +194 -366
  23. package/lib/tr-grid-column-stack/es6/ColumnStack.d.ts +10 -3
  24. package/lib/tr-grid-column-stack/es6/ColumnStack.js +93 -36
  25. package/lib/tr-grid-util/es6/RowPainter.d.ts +2 -1
  26. package/lib/tr-grid-util/es6/RowPainter.js +7 -1
  27. package/lib/tr-grid-util/es6/jet/mockDataAPI.d.ts +1 -0
  28. package/lib/tr-grid-util/es6/jet/mockDataAPI.js +191 -52
  29. package/lib/types/es6/ColumnGrouping.d.ts +1 -0
  30. package/lib/types/es6/ColumnStack.d.ts +10 -3
  31. package/lib/types/es6/Core/data/DataTable.d.ts +18 -3
  32. package/lib/types/es6/Core/data/DataView.d.ts +8 -1
  33. package/lib/types/es6/Core/data/Segment.d.ts +36 -11
  34. package/lib/types/es6/Core/data/SegmentCollection.d.ts +15 -1
  35. package/lib/types/es6/RealtimeGrid/ColumnDefinition.d.ts +6 -1
  36. package/lib/types/es6/RealtimeGrid/Grid.d.ts +2 -0
  37. package/lib/types/es6/RowSegmenting.d.ts +2 -0
  38. package/lib/versions.json +4 -4
  39. package/package.json +1 -1
@@ -1,11 +1,53 @@
1
+ import Ext from "../../../tr-grid-util/es6/Ext.js";
2
+ import EventDispatcher from "../../../tr-grid-util/es6/EventDispatcher.js";
3
+
1
4
  /** @constructor
2
5
  * @param {string} rid
6
+ * @param {!Object} sharedObj
3
7
  */
4
- var Segment = function(rid) {
8
+ var Segment = function(rid, sharedObj) {
5
9
  this._rid = rid;
6
10
  this._children = {};
11
+ this._shared = sharedObj;
7
12
  };
13
+ Ext.inherits(Segment, EventDispatcher);
14
+
15
+ /** @private
16
+ * @function
17
+ * @param {string} a
18
+ * @param {string} b
19
+ * @return {number}
20
+ */
21
+ Segment._subSegSortLogic = function(a, b) {
22
+ if(a === "Uncategorized") {
23
+ return 1;
24
+ }
25
+ if(b === "Uncategorized") {
26
+ return -1;
27
+ }
8
28
 
29
+ if(a < b) {
30
+ return -1;
31
+ }
32
+ if(b < a) {
33
+ return 1;
34
+ }
35
+
36
+ return 0;
37
+ };
38
+ /** @private
39
+ * @function
40
+ * @param {Segment} segment
41
+ * @param {number} idx
42
+ */
43
+ Segment._assignSubSegmentOrder = function(segment, idx) {
44
+ segment.setOrder(idx + 1);
45
+ };
46
+
47
+ /** @type {Object}
48
+ * @private
49
+ */
50
+ Segment.prototype._shared = null;
9
51
 
10
52
  /** @type {string}
11
53
  * @private
@@ -26,13 +68,67 @@ Segment.prototype._collapsed = false;
26
68
  /** @type {number}
27
69
  * @private
28
70
  */
29
- Segment.prototype._value = 0;
71
+ Segment.prototype._order = 0;
72
+ /** @type {boolean}
73
+ * @private
74
+ */
75
+ Segment.prototype._disposed = false;
76
+
77
+ /** @type {Object}
78
+ * @private
79
+ */
80
+ Segment.prototype._subSegDef = null;
30
81
  /** @type {number}
31
82
  * @private
32
83
  */
33
- Segment.prototype._order = 0;
84
+ Segment.prototype._subSegLevel = 0;
85
+ /** @type {Object.<string, Segment>}
86
+ * @private
87
+ */
88
+ Segment.prototype._subSegMap = null; // For immediate sub-segment children
89
+ /** @type {Array.<string>}
90
+ * @private
91
+ */
92
+ Segment.prototype._subSegNames = null; // For immediate sub-segment child names
93
+ /** @type {string}
94
+ * @private
95
+ */
96
+ Segment.prototype._subSegName = "";
97
+ /** @type {*}
98
+ * @private
99
+ */
100
+ Segment.prototype._subSegVal;
101
+ /** @type {Segment}
102
+ * @private
103
+ */
104
+ Segment.prototype._subSegParent = null;
105
+
106
+
107
+ /** @public
108
+ */
109
+ Segment.prototype.dispose = function() {
110
+ if(this._disposed) {
111
+ return;
112
+ }
113
+ this._disposed = true;
34
114
 
115
+ this.removeAllEventListeners();
116
+ var segmentNames = this._subSegNames;
117
+ if(segmentNames) {
118
+ var segmentCount = segmentNames.length;
119
+ var segmentMap = this._subSegMap;
120
+ for(var i = 0; i < segmentCount; ++i) {
121
+ segmentMap[segmentNames[i]].dispose();
122
+ }
123
+ this._subSegMap = this._subSegNames = null;
124
+ }
125
+ if(this._collapsed) {
126
+ this._shared.dirtyCollapsingState = true;
127
+ }
35
128
 
129
+ this._shared = null;
130
+ this._subSegParent = this._subSegDef = this._subSegVal = null;
131
+ };
36
132
  /** @public
37
133
  * @return {string}
38
134
  */
@@ -40,32 +136,66 @@ Segment.prototype.getId = function() {
40
136
  return this._rid;
41
137
  };
42
138
  /** @public
139
+ * @return {string}
140
+ */
141
+ Segment.prototype.getParentId = function() {
142
+ if(this._subSegParent) {
143
+ return this._subSegParent.getId();
144
+ }
145
+ return "";
146
+ };
147
+ /** @public
148
+ * @param {Array.<string>=} out_ary
149
+ * @return {Array.<string>}
150
+ */
151
+ Segment.prototype.getSubSegmentIds = function(out_ary) {
152
+ var segmentNames = this._subSegNames;
153
+ if(segmentNames) {
154
+ if(!out_ary) {
155
+ out_ary = [];
156
+ }
157
+ var segmentCount = segmentNames.length;
158
+ var segmentMap = this._subSegMap;
159
+ for(var i = 0; i < segmentCount; ++i) {
160
+ var segmentName = segmentNames[i];
161
+ var segment = segmentMap[segmentName];
162
+ out_ary.push(segment.getId());
163
+ segment.getSubSegmentIds(out_ary);
164
+ }
165
+
166
+ return out_ary;
167
+ }
168
+ return null;
169
+ };
170
+ /** @public
43
171
  * @param {string} rid
44
- * @param {Object=} objMap
172
+ * @param {string=} dataId Row id for retrieving data
45
173
  * @return {boolean}
46
174
  */
47
- Segment.prototype.addChild = function(rid, objMap) {
48
- if(rid && !this._children[rid]) {
49
- if(objMap) {
50
- objMap[rid] = this._rid;
175
+ Segment.prototype.addChild = function(rid, dataId) {
176
+ if(rid) {
177
+ this._shared.childToSegment[rid] = this._rid;
178
+ if(this._collapsed) {
179
+ this._shared.dirtyCollapsingState = true; // TODO: Check if we need to update this only when new child is added
180
+ }
181
+ if(!this._children[rid]) {
182
+ this._children[rid] = dataId || rid;
183
+ ++this._childCount;
184
+ return true;
51
185
  }
52
- this._children[rid] = 1;
53
- ++this._childCount;
54
- return true;
55
186
  }
56
187
  return false;
57
188
  };
58
189
  /** @public
59
190
  * @param {Array.<string>} rids
60
- * @param {Object=} objMap
61
191
  * @return {boolean}
62
192
  */
63
- Segment.prototype.addChildren = function(rids, objMap) {
193
+ Segment.prototype.addChildren = function(rids) {
64
194
  var rowIds = Array.isArray(rids) ? rids : [rids];
65
195
  var rowCount = rowIds.length;
66
196
  var dirty = 0;
67
197
  for(var i = 0; i < rowCount; ++i) {
68
- dirty |= this.addChild(rowIds[i], objMap);
198
+ dirty |= this.addChild(rowIds[i]);
69
199
  }
70
200
  return dirty ? true : false;
71
201
  };
@@ -78,26 +208,37 @@ Segment.prototype.containsChild = function(rid) {
78
208
  };
79
209
  /** @public
80
210
  * @param {string} rid
81
- * @param {Object=} objMap
82
211
  * @return {boolean}
83
212
  */
84
- Segment.prototype.removeChild = function(rid, objMap) {
85
- if(this._childCount && this._children[rid]) {
86
- if(objMap) {
87
- delete objMap[rid];
88
- }
89
- delete this._children[rid]; // Slow
90
- --this._childCount;
91
- return true;
213
+ Segment.prototype.removeChild = function(rid) {
214
+ if(this._subSegLevel) {
215
+ return false; // Sub segments are not allowed to remove its children
92
216
  }
93
- return false;
217
+ if(!this._childCount) {
218
+ return false;
219
+ }
220
+ if(!this._children[rid]) {
221
+ return false; // The specified rid is not a child of this segment
222
+ }
223
+
224
+ var objMap = this._shared.childToSegment;
225
+ delete objMap[rid];
226
+ delete this._children[rid]; // Slow
227
+ --this._childCount;
228
+
229
+ if(this._collapsed) {
230
+ this._shared.dirtyCollapsingState = true;
231
+ }
232
+ return true;
94
233
  };
95
234
  /** @public
96
235
  * @param {Array.<string>} rids
97
- * @param {Object=} objMap
98
236
  * @return {boolean}
99
237
  */
100
- Segment.prototype.removeChildren = function(rids, objMap) {
238
+ Segment.prototype.removeChildren = function(rids) {
239
+ if(this._subSegLevel) {
240
+ return false; // Sub segments are not allowed to remove its children
241
+ }
101
242
  if(!this._childCount) {
102
243
  return false;
103
244
  }
@@ -105,7 +246,7 @@ Segment.prototype.removeChildren = function(rids, objMap) {
105
246
  var rowCount = rowIds.length;
106
247
  var dirty = 0;
107
248
  for(var i = 0; i < rowCount; ++i) {
108
- dirty |= this.removeChild(rowIds[i], objMap);
249
+ dirty |= this.removeChild(rowIds[i]);
109
250
  }
110
251
  return dirty ? true : false;
111
252
  };
@@ -113,21 +254,27 @@ Segment.prototype.removeChildren = function(rids, objMap) {
113
254
  * @param {Object=} objMap
114
255
  * @return {boolean}
115
256
  */
116
- Segment.prototype.removeAllChildren = function(objMap) {
117
- if(this._childCount) {
118
- if(objMap) {
119
- var chdr = this._children;
120
- for(var rid in chdr) {
121
- if(objMap[rid]) {
122
- delete objMap[rid];
123
- }
124
- }
257
+ Segment.prototype.removeAllChildren = function() {
258
+ if(this._subSegLevel) {
259
+ return false; // Sub segments are not allowed to remove its children
260
+ }
261
+ if(!this._childCount) {
262
+ return false;
263
+ }
264
+ var objMap = this._shared.childToSegment;
265
+ var chdr = this._children;
266
+ for(var rid in chdr) {
267
+ if(objMap[rid]) {
268
+ delete objMap[rid]; // TODO: Check if we need to do this
125
269
  }
126
- this._children = {};
127
- this._childCount = 0;
128
- return true;
129
270
  }
130
- return false;
271
+ this._children = {};
272
+ this._childCount = 0;
273
+
274
+ if(this._collapsed) {
275
+ this._shared.dirtyCollapsingState = true;
276
+ }
277
+ return true;
131
278
  };
132
279
  /** @public
133
280
  * @return {!Array.<string>}
@@ -143,6 +290,309 @@ Segment.prototype.getChildCount = function() {
143
290
  };
144
291
 
145
292
 
293
+ /** @public
294
+ * @return {Array.<string>} fields
295
+ */
296
+ Segment.prototype.getClassification = function() {
297
+ if(this._subSegDef) {
298
+ return this._subSegDef.classifiers || null;
299
+ }
300
+ return null;
301
+ };
302
+ /** @public
303
+ * @param {string|Array.<string>} fields
304
+ * @return {boolean}
305
+ */
306
+ Segment.prototype.setClassification = function(fields) {
307
+ if(this._subSegLevel) {
308
+ return false; // non-root segment cannot be classified
309
+ }
310
+ var classifiers = null;
311
+ if(this._subSegDef) {
312
+ classifiers = this._subSegDef.classifiers;
313
+ }
314
+
315
+ var newClassifiers = null;
316
+ if(fields) {
317
+ if(typeof fields === "string") {
318
+ newClassifiers = [fields];
319
+ } else if(Array.isArray(fields)) {
320
+ newClassifiers = fields;
321
+ }
322
+ }
323
+ var i;
324
+ var fieldCount = newClassifiers ? newClassifiers.length : 0;
325
+
326
+ if(fieldCount) {
327
+ var curCount = classifiers ? classifiers.length : 0;
328
+ if(curCount === fieldCount) { // Check duplication
329
+ for(i = 0; i < fieldCount; ++i) {
330
+ if(newClassifiers[i] !== classifiers[i]) {
331
+ break;
332
+ }
333
+ }
334
+ if(i >= fieldCount) {
335
+ return false; // nothing has change
336
+ }
337
+ }
338
+
339
+ if(!this._subSegDef) {
340
+ this._subSegDef = {
341
+ root: this,
342
+ subSegments: null
343
+ };
344
+ }
345
+
346
+ this._subSegDef.classifiers = newClassifiers;
347
+ // this._subSegDef.classifierChanged = true;
348
+ return true;
349
+ } else if(classifiers) { // Remove existing ones
350
+ this._subSegDef.classifiers = null;
351
+ this._subSegDef.subSegments = null;
352
+ // this._subSegDef.classifierChanged = true;
353
+ this._subSegDef = null; // WARNING: All sub segments remain existing
354
+ return true;
355
+ }
356
+ return false;
357
+ };
358
+ /** @public
359
+ * @param {Object.<string, Object>=} rows Object maps between row id and its record
360
+ * @return {boolean}
361
+ */
362
+ Segment.prototype.classify = function(rows) {
363
+ var classifiers = this._subSegDef ? this._subSegDef.classifiers : null;
364
+ var classifierCount = classifiers ? classifiers.length : 0;
365
+
366
+ var segmentNames = this._subSegNames;
367
+ var segmentCount = segmentNames ? segmentNames.length : 0;
368
+
369
+ if(!segmentCount) {
370
+ if(this._subSegLevel >= classifierCount) {
371
+ return false; // Current segment level is beyond existing classification level and this segment should already be removed
372
+ }
373
+ }
374
+
375
+ // Prepare existing sub segments for checking change in its members
376
+ var i;
377
+ var segmentName = "";
378
+ var nonExistenceGroups = {};
379
+ var removalCount = 0;
380
+ var segmentMap = this._subSegMap;
381
+ var segment = null;
382
+ if(segmentCount) {
383
+ removalCount = segmentCount;
384
+ for(i = 0; i < removalCount; ++i) {
385
+ segmentName = segmentNames[i];
386
+ nonExistenceGroups[segmentName] = 1;
387
+
388
+ segment = segmentMap[segmentName];
389
+ if(segment._childCount) { // Quick cleaning up
390
+ segment._children = {};
391
+ segment._childCount = 0;
392
+ }
393
+ }
394
+ }
395
+
396
+ // Loop through row children and assign them to their corresponding sub segment
397
+ var isRootSegment = !this._subSegLevel;
398
+ var rid;
399
+ var children = this._children;
400
+ if(this._subSegLevel < classifierCount && rows) {
401
+ if(!segmentMap) {
402
+ segmentMap = this._subSegMap = {};
403
+ segmentNames = this._subSegNames = [];
404
+ }
405
+
406
+ var classifier = classifiers[this._subSegLevel];
407
+
408
+ for(rid in children) {
409
+ var dataId = children[rid];
410
+ var record = rows[dataId];
411
+ var val = record ? record[classifier] : null; // WARNING: row could already be removed
412
+
413
+ this._shared.childToSegment[rid] = this._rid; // Relocate child in case of it has been moved to a non existence group
414
+
415
+ segmentName = "Uncategorized";
416
+ if(val || val === 0 || val === false) { // Check for null, undefined, "", and NaN value
417
+ segmentName = val + "";
418
+ }
419
+ if(nonExistenceGroups[segmentName]) {
420
+ nonExistenceGroups[segmentName] = 0;
421
+ --removalCount;
422
+ }
423
+
424
+ segment = segmentMap[segmentName];
425
+ if(!segment) { // New group is detected
426
+ segment = new Segment(this._rid + "/" + segmentName, this._shared);
427
+ segment._subSegDef = this._subSegDef;
428
+ segment._subSegLevel = this._subSegLevel + 1;
429
+ segment._subSegName = segmentName;
430
+ segment._subSegVal = val;
431
+ segment._subSegParent = this;
432
+
433
+ segmentMap[segmentName] = segment;
434
+ segmentNames.push(segmentName);
435
+
436
+ this._dispatch("subSegmentAdded", {
437
+ "rid": segment.getId(),
438
+ "segment": segment
439
+ });
440
+ }
441
+
442
+ segment.addChild(rid, dataId);
443
+ }
444
+ } else if(isRootSegment) { // In case of no classification
445
+ for(rid in children) {
446
+ this._shared.childToSegment[rid] = this._rid; // Relocate child in case of it has been moved to a non existence group
447
+ }
448
+ }
449
+
450
+ // Remove all sub segments with no members
451
+ if(removalCount > 0) {
452
+ if(removalCount >= segmentNames.length) {
453
+ segmentNames.length = 0;
454
+ }
455
+ for(segmentName in nonExistenceGroups) {
456
+ if(nonExistenceGroups[segmentName]) {
457
+ segment = segmentMap[segmentName];
458
+ delete segmentMap[segmentName];
459
+ // TODO: Slow
460
+ var at = segmentNames.indexOf(segmentName);
461
+ if(at >= 0) {
462
+ segmentNames.splice(at, 1);
463
+ }
464
+
465
+ this._dispatch("subSegmentRemoved", {
466
+ "rid": segment.getId(),
467
+ "segment": segment
468
+ });
469
+
470
+ // segment.dispose(); Already done by segment collection
471
+ }
472
+ }
473
+ if(!segmentNames.length) {
474
+ segmentNames = this._subSegMap = this._subSegNames = null;
475
+ }
476
+ }
477
+
478
+ // Sort and classify existing sub segments
479
+ segmentCount = segmentNames ? segmentNames.length : 0;
480
+ if(segmentCount) {
481
+ segmentNames.sort(Segment._subSegSortLogic);
482
+ for(i = 0; i < segmentCount; ++i) {
483
+ segment = segmentMap[segmentNames[i]];
484
+ segment.classify(rows);
485
+ }
486
+ }
487
+
488
+ // Collecting all sub segments including all descendants and reassigning segment order.
489
+ if(isRootSegment) { // If this is a root segment
490
+ if(this._subSegDef) {
491
+ if(segmentCount) {
492
+ var subSegments = this._subSegDef.subSegments = [];
493
+ this.getAllSubSegments(subSegments);
494
+ subSegments.forEach(Segment._assignSubSegmentOrder);
495
+ } else {
496
+ this._subSegDef.subSegments = null;
497
+ }
498
+ // this._subSegDef.classifierChanged = false;
499
+ }
500
+ }
501
+ return true;
502
+ };
503
+ /** @public
504
+ * @return {boolean}
505
+ */
506
+ Segment.prototype.hasSubSegments = function() {
507
+ if(this._subSegNames) {
508
+ return this._subSegNames.length ? true : false;
509
+ }
510
+ return false;
511
+ };
512
+ /** @public
513
+ * @return {boolean}
514
+ */
515
+ Segment.prototype.isSubSegment = function() {
516
+ return this._subSegLevel ? true : false;
517
+ };
518
+ /** @public
519
+ * @return {Segment}
520
+ */
521
+ Segment.prototype.getFirstAncestor = function() {
522
+ if(this._subSegLevel && this._subSegDef) {
523
+ var ancestor = this._subSegDef.root;
524
+ return /** @type{Segment} */(ancestor) || null;
525
+ }
526
+ return null;
527
+ };
528
+ /** @public
529
+ * @param {Array.<Segment>=} out_ary
530
+ * @return {Array.<Segment>}
531
+ */
532
+ Segment.prototype.getAllSubSegments = function(out_ary) {
533
+ var segmentNames = this._subSegNames;
534
+ if(segmentNames) {
535
+ if(!out_ary) {
536
+ out_ary = [];
537
+ }
538
+ var segmentMap = this._subSegMap;
539
+ var segmentCount = segmentNames.length;
540
+ for(var i = 0; i < segmentCount; ++i) {
541
+ var segment = segmentMap[segmentNames[i]];
542
+ out_ary.push(segment);
543
+ segment.getAllSubSegments(out_ary);
544
+ }
545
+ }
546
+ return out_ary;
547
+ };
548
+ /** @public
549
+ * @return {number}
550
+ */
551
+ Segment.prototype.getSegmentLevel = function() {
552
+ return this._subSegLevel;
553
+ };
554
+ /** This method will be called on sub segments only
555
+ * @public
556
+ * @param {Object=} rows
557
+ * @param {Object=} clsSource
558
+ */
559
+ Segment.prototype.setRowData = function(rows, clsSource) {
560
+ if(!rows) {
561
+ return;
562
+ }
563
+ var row = rows[this._rid];
564
+ if(!row) {
565
+ row = rows[this._rid] = {};
566
+ }
567
+
568
+ if(!clsSource) {
569
+ clsSource = rows;
570
+ }
571
+ row = clsSource[this._rid];
572
+ if(!row) {
573
+ row = clsSource[this._rid] = {};
574
+ }
575
+
576
+ var segment = this;
577
+ while(segment && segment.isSubSegment()) {
578
+ segment.getSubSegmentName(row);
579
+ segment = segment._subSegParent;
580
+ }
581
+ };
582
+ /** @public
583
+ * @param {Object=} row
584
+ * @return {string}
585
+ */
586
+ Segment.prototype.getSubSegmentName = function(row) {
587
+ if(row && this._subSegLevel) {
588
+ var classifiers = this.getClassification();
589
+ var field = classifiers[this._subSegLevel - 1];
590
+ if(field) {
591
+ row[field] = this._subSegName;
592
+ }
593
+ }
594
+ return this._subSegName;
595
+ };
146
596
 
147
597
  /** @public
148
598
  * @param {boolean=} bool
@@ -152,6 +602,7 @@ Segment.prototype.collapse = function(bool) {
152
602
  bool = (bool !== false);
153
603
  if(this._collapsed !== bool) {
154
604
  this._collapsed = bool;
605
+ this._shared.dirtyCollapsingState = true;
155
606
  return true;
156
607
  }
157
608
  return false;
@@ -171,44 +622,109 @@ Segment.prototype.isCollapsed = function() {
171
622
  };
172
623
  /** @public
173
624
  * @param {Object=} objMap
174
- * @return {!Object}
625
+ * @param {boolean=} parentState=false Collapsing state from parent segment
626
+ * @return {number}
175
627
  */
176
- Segment.prototype.getCollapsingStates = function(objMap) {
628
+ Segment.prototype.getCollapsingStates = function(objMap, parentState) {
629
+ var segmentNames = this._subSegNames;
630
+ if(!this._subSegLevel) { // Only root segment
631
+ if(!segmentNames) { // No sub segment
632
+ if(!this._collapsed) {
633
+ return false;
634
+ }
635
+ }
636
+ }
637
+
177
638
  if(!objMap) {
178
639
  objMap = {};
179
640
  }
641
+ var dirty = false;
642
+ if(this._subSegLevel) { // Sub segments are also subjected to collapsing
643
+ if(parentState) {
644
+ objMap[this._rid] = true;
645
+ dirty = true;
646
+ }
647
+ }
180
648
  if(this._childCount) {
181
- var chdr = this._children;
182
- var collapsed = this._collapsed;
183
- for(var rid in chdr) {
184
- objMap[rid] = collapsed;
649
+ var collapsed = parentState || this._collapsed;
650
+ if(segmentNames) {
651
+ var segmentMap = this._subSegMap;
652
+ var segmentCount = segmentNames.length;
653
+ for(var i = 0; i < segmentCount; ++i) {
654
+ var segment = segmentMap[segmentNames[i]];
655
+ objMap[segment.getId()] = !!parentState;
656
+ if(segment.getCollapsingStates(objMap, collapsed)) {
657
+ dirty = true;
658
+ }
659
+ }
660
+ } else if(collapsed) {
661
+ var chdr = this._children;
662
+ for(var rid in chdr) {
663
+ objMap[rid] = collapsed;
664
+ }
665
+ dirty = true;
185
666
  }
186
667
  }
187
- return objMap;
668
+ return dirty;
188
669
  };
670
+
189
671
  /** @public
190
672
  * @return {number}
191
673
  */
192
- Segment.prototype.getValue = function() {
193
- return this._value;
674
+ Segment.prototype.getOrder = function() {
675
+ if(this._subSegLevel) {
676
+ var ancestor = this.getFirstAncestor();
677
+ if(ancestor) {
678
+ // WARNING: this._order cannot be greater than 9999
679
+ return ancestor.getOrder() + this._order;
680
+ }
681
+ }
682
+ return this._order * 10000;
194
683
  };
195
684
  /** @public
196
685
  * @param {number} val
197
686
  */
198
- Segment.prototype.setValue = function(val) {
199
- this._value = val;
687
+ Segment.prototype.setOrder = function(val) {
688
+ this._order = val;
200
689
  };
201
- /** @public
202
- * @return {number}
690
+
691
+ /** @private
692
+ * @type {Array.<string>}
203
693
  */
204
- Segment.prototype.getOrder = function() {
205
- return this._order;
206
- };
694
+ Segment._tabs = null;
207
695
  /** @public
208
- * @param {number} val
696
+ * @param {Array.<string>} lines
697
+ * @return {Array.<string>} lines
209
698
  */
210
- Segment.prototype.setOrder = function(val) {
211
- this._order = val;
699
+ Segment.prototype.log = function(lines) {
700
+ var i;
701
+ var tabs = Segment._tabs;
702
+ if(!tabs) {
703
+ tabs = Segment._tabs = [];
704
+ var tabCh = "";
705
+ for(i = 0; i < 11; ++i) {
706
+ tabs[i] = tabCh;
707
+ tabCh += " ";
708
+ }
709
+ }
710
+ var collapsedCh = this._collapsed ? "+ " : "- ";
711
+ lines.push(tabs[this._subSegLevel] + collapsedCh + this._rid);
712
+
713
+ var segmentNames = this._subSegNames;
714
+ if(segmentNames) {
715
+ var segmentCount = segmentNames.length;
716
+ var segmentMap = this._subSegMap;
717
+ for(i = 0; i < segmentCount; ++i) {
718
+ segmentMap[segmentNames[i]].log(lines);
719
+ }
720
+ } else if(this._childCount) {
721
+ var indent = tabs[this._subSegLevel + 1];
722
+ for(var rid in this._children) {
723
+ lines.push(indent + "- " + rid);
724
+ }
725
+ }
726
+
727
+ return lines;
212
728
  };
213
729
 
214
730