@operato/scene-table 0.0.17

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 (88) hide show
  1. package/@types/global/index.d.ts +1 -0
  2. package/CHANGELOG.md +16 -0
  3. package/LICENSE +21 -0
  4. package/README.md +33 -0
  5. package/assets/icon-data-list.png +0 -0
  6. package/assets/icon-table.png +0 -0
  7. package/dist/data-list/data-cell.d.ts +22 -0
  8. package/dist/data-list/data-cell.js +56 -0
  9. package/dist/data-list/data-cell.js.map +1 -0
  10. package/dist/data-list/data-list-layout.d.ts +10 -0
  11. package/dist/data-list/data-list-layout.js +95 -0
  12. package/dist/data-list/data-list-layout.js.map +1 -0
  13. package/dist/data-list/data-list.d.ts +56 -0
  14. package/dist/data-list/data-list.js +536 -0
  15. package/dist/data-list/data-list.js.map +1 -0
  16. package/dist/helper-functions.d.ts +37 -0
  17. package/dist/helper-functions.js +135 -0
  18. package/dist/helper-functions.js.map +1 -0
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.js +7 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/table-cell.d.ts +41 -0
  23. package/dist/table-cell.js +104 -0
  24. package/dist/table-cell.js.map +1 -0
  25. package/dist/table.d.ts +54 -0
  26. package/dist/table.js +1270 -0
  27. package/dist/table.js.map +1 -0
  28. package/dist/templates/data-list.d.ts +18 -0
  29. package/dist/templates/data-list.js +20 -0
  30. package/dist/templates/data-list.js.map +1 -0
  31. package/dist/templates/index.d.ts +18 -0
  32. package/dist/templates/index.js +4 -0
  33. package/dist/templates/index.js.map +1 -0
  34. package/dist/templates/table.d.ts +20 -0
  35. package/dist/templates/table.js +26 -0
  36. package/dist/templates/table.js.map +1 -0
  37. package/helps/scene/component/data-cell.ko.md +13 -0
  38. package/helps/scene/component/data-cell.md +13 -0
  39. package/helps/scene/component/data-cell.zh.md +13 -0
  40. package/helps/scene/component/data-list.ko.md +6 -0
  41. package/helps/scene/component/data-list.md +6 -0
  42. package/helps/scene/component/data-list.zh.md +8 -0
  43. package/helps/scene/component/table-cell.ko.md +58 -0
  44. package/helps/scene/component/table-cell.md +58 -0
  45. package/helps/scene/component/table-cell.zh.md +61 -0
  46. package/helps/scene/component/table.ko.md +68 -0
  47. package/helps/scene/component/table.md +68 -0
  48. package/helps/scene/component/table.zh.md +68 -0
  49. package/helps/scene/images/table-01.png +0 -0
  50. package/helps/scene/images/table-02.png +0 -0
  51. package/helps/scene/images/table-03.png +0 -0
  52. package/helps/scene/images/table-04.png +0 -0
  53. package/helps/scene/images/table-05.png +0 -0
  54. package/helps/scene/images/table-06.png +0 -0
  55. package/helps/scene/images/table-07.png +0 -0
  56. package/helps/scene/images/table-08.png +0 -0
  57. package/helps/scene/images/table-09.png +0 -0
  58. package/helps/scene/images/table-10.png +0 -0
  59. package/helps/scene/images/table-11.png +0 -0
  60. package/helps/scene/images/table-12.png +0 -0
  61. package/helps/scene/images/table-13.png +0 -0
  62. package/helps/scene/images/table-14.png +0 -0
  63. package/package.json +62 -0
  64. package/src/data-list/data-cell.ts +66 -0
  65. package/src/data-list/data-list-layout.ts +113 -0
  66. package/src/data-list/data-list.ts +654 -0
  67. package/src/helper-functions.ts +168 -0
  68. package/src/index.ts +6 -0
  69. package/src/table-cell.ts +126 -0
  70. package/src/table.ts +1406 -0
  71. package/src/templates/data-list.ts +20 -0
  72. package/src/templates/index.ts +4 -0
  73. package/src/templates/table.ts +26 -0
  74. package/test/basic-test.html +67 -0
  75. package/test/index.html +22 -0
  76. package/test/unit/a-test-table.js +72 -0
  77. package/test/unit/test-table-find-merged-cell.js +95 -0
  78. package/test/unit/test-table-insert-column.js +81 -0
  79. package/test/unit/test-table-insert-row.js +79 -0
  80. package/test/unit/test-table-rows-columns.js +47 -0
  81. package/test/unit/util.js +21 -0
  82. package/things-scene.config.js +5 -0
  83. package/translations/en.json +3 -0
  84. package/translations/ko.json +3 -0
  85. package/translations/ms.json +3 -0
  86. package/translations/zh.json +3 -0
  87. package/tsconfig.json +22 -0
  88. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,654 @@
1
+ /*
2
+ * Copyright © HatioLab Inc. All rights reserved.
3
+ */
4
+
5
+ import './data-cell'
6
+ import './data-list-layout'
7
+
8
+ import {
9
+ CLEAR_STYLE,
10
+ WHERE,
11
+ above,
12
+ after,
13
+ array,
14
+ before,
15
+ below,
16
+ buildCopiedCell,
17
+ buildNewCell,
18
+ columnControlHandler,
19
+ isBottomMost,
20
+ isLeftMost,
21
+ isRightMost,
22
+ isTopMost,
23
+ rowControlHandler,
24
+ setCellBorder
25
+ } from '../helper-functions'
26
+ import { Component, ComponentNature, Container, Control, Layout, Model, State, Style } from '@hatiolab/things-scene'
27
+
28
+ import DataCell from './data-cell'
29
+
30
+ const NATURE = {
31
+ mutable: false,
32
+ resizable: true,
33
+ rotatable: true,
34
+ properties: [
35
+ {
36
+ type: 'number',
37
+ label: 'columns',
38
+ name: 'columns',
39
+ property: 'columns'
40
+ }
41
+ ],
42
+ 'value-property': 'data',
43
+ help: 'scene/component/data-list'
44
+ }
45
+
46
+ export default class DataList extends Container {
47
+ postrender(context: CanvasRenderingContext2D) {
48
+ super.postrender(context)
49
+
50
+ // child component들을 다 그린 후에 scrollbar를 표현한다.
51
+ if (this.app.isViewMode) {
52
+ this.renderScrollbar(context)
53
+ }
54
+ }
55
+
56
+ renderScrollbar(context: CanvasRenderingContext2D) {
57
+ var { left, top, width, height } = this.bounds
58
+ var { offset = { x: 0, y: 0 }, data } = this.state
59
+
60
+ var fullHeight = ((data && data.length) || 0) * (this.heights[0] / this.heights_sum) * height
61
+
62
+ if (fullHeight <= height) {
63
+ return
64
+ }
65
+
66
+ var start = (-offset.y / fullHeight) * height
67
+ var end = ((-offset.y + height) / fullHeight) * height
68
+
69
+ context.strokeStyle = 'gray'
70
+ context.lineWidth = 10
71
+ context.globalAlpha = 0.3
72
+
73
+ context.beginPath()
74
+ context.moveTo(left + width - 10, top + start)
75
+ context.lineTo(left + width - 10, top + end)
76
+
77
+ context.stroke()
78
+ }
79
+
80
+ created() {
81
+ this.set('rows', 2)
82
+
83
+ var rows = 1
84
+
85
+ var tobeSize = rows * this.columns
86
+ var gap = this.size() - tobeSize
87
+
88
+ if (this.data) {
89
+ this.setCellsData()
90
+ }
91
+
92
+ if (gap == 0) {
93
+ return
94
+ } else if (gap > 0) {
95
+ let removals = this.components.slice(gap)
96
+ this.remove(removals)
97
+ } else {
98
+ let newbies = []
99
+
100
+ for (let i = 0; i < -gap; i++) newbies.push(buildNewCell('data-cell', this.app))
101
+
102
+ this.add(newbies)
103
+ }
104
+
105
+ var widths = this.get('widths')
106
+ var heights = this.get('heights')
107
+
108
+ if (!widths || widths.length < this.columns) this.set('widths', this.widths)
109
+ if (!heights || heights.length < rows) this.set('heights', this.heights)
110
+ }
111
+
112
+ _onwheel(e: WheelEvent) {
113
+ e.stopPropagation()
114
+
115
+ var { height } = this.bounds
116
+ var { offset = { x: 0, y: 0 } } = this.state
117
+
118
+ var recordHeight = (this.heights[0] / this.heights.reduce((sum: number, height: number) => sum + height)) * height
119
+
120
+ var minX = 0
121
+ var minY = this.data && this.data.length ? Math.min(-recordHeight * this.data.length + height, 0) : 0
122
+
123
+ /* shiftKey + wheel 은 deltaX 값을 변화시킨다. */
124
+ if (e.deltaY == 0 && e.deltaX == 0) return
125
+
126
+ var x = e.deltaX + offset.x
127
+ var y = -e.deltaY + offset.y
128
+
129
+ /* 휠을 밀면.. 화면은 위쪽으로 : scroll down */
130
+ /* 휠을 당기면.. 화면은 아래쪽으로 : scroll up */
131
+
132
+ this.setState({
133
+ offset: {
134
+ x: Math.max(Math.min(0, x), minX),
135
+ y: Math.max(Math.min(0, y), minY)
136
+ }
137
+ })
138
+ }
139
+
140
+ private __START_OFFSET?: { x: number; y: number }
141
+ private __START_Y?: number
142
+
143
+ _ontouchstart(e: DragEvent) {
144
+ this.__START_OFFSET = this.state.offset || {
145
+ x: 0,
146
+ y: 0
147
+ }
148
+ this.__START_Y = e.offsetY
149
+ }
150
+
151
+ _ontouchmove(e: DragEvent) {
152
+ if (!this.__START_OFFSET) {
153
+ return
154
+ }
155
+
156
+ var { height } = this.bounds
157
+
158
+ var recordHeight = (this.heights[0] / this.heights.reduce((sum: number, height: number) => sum + height)) * height
159
+ var minY = this.data && this.data.length ? Math.min(-recordHeight * this.data.length + height, 0) : 0
160
+
161
+ var x = 0
162
+ var y = this.__START_OFFSET.y + (e.offsetY - this.__START_Y!) / this.rootModel.state.scale.y
163
+ y = Math.max(Math.min(0, y), minY)
164
+
165
+ var offset = this.state.offset || { x: 0, y: 0 }
166
+ if (offset.x !== x || offset.y !== y) {
167
+ this.setState('offset', {
168
+ x,
169
+ y
170
+ })
171
+
172
+ e.stopPropagation()
173
+ }
174
+ }
175
+
176
+ _ontouchend(e: DragEvent) {
177
+ delete this.__START_OFFSET
178
+ delete this.__START_Y
179
+ }
180
+
181
+ get layout() {
182
+ return Layout.get('data-list')
183
+ }
184
+
185
+ containable(component: Component) {
186
+ return component.get('type') == 'data-cell'
187
+ }
188
+
189
+ get focusible() {
190
+ /* 이 컨테이너에는 컴포넌트를 임의로 추가 및 삭제할 수 없도록 함 */
191
+ return false
192
+ }
193
+
194
+ get widths_sum(): number {
195
+ var widths = this.widths
196
+ return widths
197
+ ? widths
198
+ .filter((width: number, i: number) => i < this.columns)
199
+ .reduce((sum: number, width: number) => sum + width, 0)
200
+ : this.columns
201
+ }
202
+
203
+ get heights_sum(): number {
204
+ var heights = this.heights
205
+ return heights ? heights.filter((height, i) => i < this.rows).reduce((sum, height) => sum + height, 0) : this.rows
206
+ }
207
+
208
+ get widths(): number[] {
209
+ var widths = this.get('widths')
210
+
211
+ if (!widths) return array(1, this.columns)
212
+
213
+ if (widths.length < this.columns) return widths.concat(array(1, this.columns - widths.length))
214
+ else if (widths.length > this.columns) return widths.slice(0, this.columns)
215
+
216
+ return widths
217
+ }
218
+
219
+ get heights(): number[] {
220
+ var heights = this.get('heights')
221
+ var rows = 2
222
+
223
+ if (!heights) {
224
+ return array(1, rows)
225
+ }
226
+
227
+ if (heights.length < rows) return heights.concat(array(1, rows - heights.length))
228
+ else if (heights.length > rows) return heights.slice(0, rows)
229
+
230
+ return heights
231
+ }
232
+
233
+ get columns() {
234
+ return Number(this.get('columns'))
235
+ }
236
+
237
+ get rows(): number {
238
+ /* 1 for first record fields, 1 for rest record fields */
239
+ return 2
240
+ }
241
+
242
+ get nature(): ComponentNature {
243
+ return NATURE
244
+ }
245
+
246
+ get controls(): Control[] {
247
+ var widths = this.widths
248
+ var heights = this.heights
249
+ var inside = this.textBounds
250
+
251
+ var width_unit = inside.width / this.widths_sum
252
+ var height_unit = inside.height / this.heights_sum
253
+
254
+ var x = inside.left
255
+ var y = inside.top
256
+
257
+ var controls: Control[] = []
258
+
259
+ widths.slice(0, this.columns - 1).forEach(width => {
260
+ x += width * width_unit
261
+ controls.push({
262
+ x: x,
263
+ y: inside.top,
264
+ handler: columnControlHandler
265
+ })
266
+ })
267
+
268
+ heights.slice(0, this.rows - 1).forEach(height => {
269
+ y += height * height_unit
270
+ controls.push({
271
+ x: inside.left,
272
+ y: y,
273
+ handler: rowControlHandler
274
+ })
275
+ })
276
+
277
+ return controls
278
+ }
279
+
280
+ onchange(after: State, before: State) {
281
+ if ('data' in after) {
282
+ this.setCellsData()
283
+ }
284
+
285
+ if ('columns' in after) {
286
+ let { columns } = this
287
+
288
+ this.buildCells(columns, Number(before.columns))
289
+ }
290
+ }
291
+
292
+ get eventMap() {
293
+ return {
294
+ '(self)': {
295
+ '(all)': {
296
+ wheel: this._onwheel,
297
+ touchstart: this._ontouchstart,
298
+ touchmove: this._ontouchmove,
299
+ touchend: this._ontouchend
300
+ }
301
+ }
302
+ }
303
+ }
304
+
305
+ setCellsData() {
306
+ if (!this.app.isViewMode) {
307
+ return
308
+ }
309
+
310
+ var data = this.data || []
311
+ if (!(data instanceof Array)) {
312
+ data = [data]
313
+ }
314
+
315
+ /* 기존의 레코드를 모두 삭제 (템플릿 레코드만 남긴다.) */
316
+ this.remove(this.components.slice(this.columns))
317
+
318
+ /* template 레코드의 데이타를 클리어시킨다 */
319
+ var templates = this.getCellsByRow(0)
320
+ templates.forEach(field => {
321
+ field.data = ''
322
+ })
323
+
324
+ /* 데이타의 크기만큼 새로운 레코드를 만든다 */
325
+ if (data.length > 1) {
326
+ let newbies: Component[] = []
327
+
328
+ for (let i = 1; i < data.length; i++) {
329
+ newbies = newbies.concat(
330
+ templates.map(field => {
331
+ return Model.compile(
332
+ {
333
+ ...field.model,
334
+ id: '',
335
+ data: ''
336
+ },
337
+ this.app
338
+ )
339
+ })
340
+ )
341
+ }
342
+
343
+ this.add(newbies)
344
+ }
345
+
346
+ data.forEach((record: any[], idx: number) => {
347
+ let data = {
348
+ _idx: idx,
349
+ ...record
350
+ }
351
+ let row = this.getCellsByRow(idx)
352
+ row.forEach(field => {
353
+ field.data = data
354
+ })
355
+ })
356
+ }
357
+
358
+ setCellsStyle(cells: Component[], style: Style, where: WHERE) {
359
+ var components = this.components
360
+ var total = components.length
361
+ var columns = this.get('columns')
362
+
363
+ var indices = cells.map(cell => components.indexOf(cell))
364
+ indices.forEach(i => {
365
+ var cell = components[i]
366
+
367
+ switch (where) {
368
+ case 'all':
369
+ setCellBorder(cell, style, where)
370
+
371
+ if (isLeftMost(total, columns, indices, i)) setCellBorder(components[before(columns, i)], style, 'right')
372
+ if (isRightMost(total, columns, indices, i)) setCellBorder(components[after(columns, i)], style, 'left')
373
+ if (isTopMost(total, columns, indices, i)) setCellBorder(components[above(columns, i)], style, 'bottom')
374
+ if (isBottomMost(total, columns, indices, i)) setCellBorder(components[below(columns, i)], style, 'top')
375
+ break
376
+ case 'in':
377
+ if (!isLeftMost(total, columns, indices, i)) {
378
+ setCellBorder(cell, style, 'left')
379
+ }
380
+ if (!isRightMost(total, columns, indices, i)) {
381
+ setCellBorder(cell, style, 'right')
382
+ }
383
+ if (!isTopMost(total, columns, indices, i)) {
384
+ setCellBorder(cell, style, 'top')
385
+ }
386
+ if (!isBottomMost(total, columns, indices, i)) {
387
+ setCellBorder(cell, style, 'bottom')
388
+ }
389
+ break
390
+ case 'out':
391
+ if (isLeftMost(total, columns, indices, i)) {
392
+ setCellBorder(cell, style, 'left')
393
+ setCellBorder(components[before(columns, i)], style, 'right')
394
+ }
395
+ if (isRightMost(total, columns, indices, i)) {
396
+ setCellBorder(cell, style, 'right')
397
+ setCellBorder(components[after(columns, i)], style, 'left')
398
+ }
399
+ if (isTopMost(total, columns, indices, i)) {
400
+ setCellBorder(cell, style, 'top')
401
+ setCellBorder(components[above(columns, i)], style, 'bottom')
402
+ }
403
+ if (isBottomMost(total, columns, indices, i)) {
404
+ setCellBorder(cell, style, 'bottom')
405
+ setCellBorder(components[below(columns, i)], style, 'top')
406
+ }
407
+ break
408
+ case 'left':
409
+ if (isLeftMost(total, columns, indices, i)) {
410
+ setCellBorder(cell, style, 'left')
411
+ setCellBorder(components[before(columns, i)], style, 'right')
412
+ }
413
+ break
414
+ case 'right':
415
+ if (isRightMost(total, columns, indices, i)) {
416
+ setCellBorder(cell, style, 'right')
417
+ setCellBorder(components[after(columns, i)], style, 'left')
418
+ }
419
+ break
420
+ case 'center':
421
+ if (!isLeftMost(total, columns, indices, i)) {
422
+ setCellBorder(cell, style, 'left')
423
+ }
424
+ if (!isRightMost(total, columns, indices, i)) {
425
+ setCellBorder(cell, style, 'right')
426
+ }
427
+ break
428
+ case 'middle':
429
+ if (!isTopMost(total, columns, indices, i)) {
430
+ setCellBorder(cell, style, 'top')
431
+ }
432
+ if (!isBottomMost(total, columns, indices, i)) {
433
+ setCellBorder(cell, style, 'bottom')
434
+ }
435
+ break
436
+ case 'top':
437
+ if (isTopMost(total, columns, indices, i)) {
438
+ setCellBorder(cell, style, 'top')
439
+ setCellBorder(components[above(columns, i)], style, 'bottom')
440
+ }
441
+ break
442
+ case 'bottom':
443
+ if (isBottomMost(total, columns, indices, i)) {
444
+ setCellBorder(cell, style, 'bottom')
445
+ setCellBorder(components[below(columns, i)], style, 'top')
446
+ }
447
+ break
448
+ case 'clear':
449
+ setCellBorder(cell, CLEAR_STYLE, 'all')
450
+
451
+ if (isLeftMost(total, columns, indices, i))
452
+ setCellBorder(components[before(columns, i)], CLEAR_STYLE, 'right')
453
+ if (isRightMost(total, columns, indices, i)) setCellBorder(components[after(columns, i)], CLEAR_STYLE, 'left')
454
+ if (isTopMost(total, columns, indices, i)) setCellBorder(components[above(columns, i)], CLEAR_STYLE, 'bottom')
455
+ if (isBottomMost(total, columns, indices, i)) setCellBorder(components[below(columns, i)], CLEAR_STYLE, 'top')
456
+ }
457
+ })
458
+ }
459
+
460
+ buildCells(newcolumns: number, oldcolumns: number) {
461
+ var minrows = 1
462
+
463
+ if (newcolumns > oldcolumns) {
464
+ for (let r = 0; r < minrows; r++) {
465
+ for (let c = oldcolumns; c < newcolumns; c++) {
466
+ this.insertComponentAt(buildNewCell('data-cell', this.app), r * newcolumns + c)
467
+ }
468
+ }
469
+ } else if (newcolumns < oldcolumns) {
470
+ let removals = []
471
+
472
+ for (let r = 0; r < minrows; r++) {
473
+ for (let c = newcolumns; c < oldcolumns; c++) {
474
+ removals.push(this.components[r * oldcolumns + c])
475
+ }
476
+ }
477
+
478
+ this.remove(removals)
479
+ }
480
+
481
+ this.set({
482
+ widths: this.widths,
483
+ heights: this.heights
484
+ })
485
+
486
+ this.setCellsData()
487
+ }
488
+
489
+ getRowColumn(cell: Component) {
490
+ var idx = this.components.indexOf(cell)
491
+
492
+ return {
493
+ column: idx % this.columns,
494
+ row: Math.floor(idx / this.columns)
495
+ }
496
+ }
497
+
498
+ getCellsByRow(row: number): Component[] {
499
+ return this.components.slice(row * this.columns, (row + 1) * this.columns)
500
+ }
501
+
502
+ getCellsByColumn(column: number): Component[] {
503
+ var cells = []
504
+ for (let i = 0; i < this.rows; i++) cells.push(this.components[this.columns * i + column])
505
+
506
+ return cells
507
+ }
508
+
509
+ mergeCells(cells: Component[]) {}
510
+
511
+ splitCells(cells: Component[]) {}
512
+
513
+ deleteRows(cells: Component[]) {}
514
+
515
+ deleteColumns(cells: Component[]) {
516
+ // 만약 선택한 셀이 병합된 셀이라면 삭제하지 않는다.
517
+ // if (cells[0].merged == true) return false
518
+
519
+ // 먼저 cells 위치의 열을 구한다.
520
+ let columns: number[] = []
521
+ cells.forEach(cell => {
522
+ let column = this.getRowColumn(cell).column
523
+ if (-1 == columns.indexOf(column)) columns.push(column)
524
+ })
525
+ columns.sort((a, b) => {
526
+ return a - b
527
+ })
528
+ columns.reverse()
529
+
530
+ columns.forEach(column => {
531
+ var widths = this.widths.slice()
532
+ this.remove(this.getCellsByColumn(column))
533
+
534
+ widths.splice(column, 1)
535
+ this.model.columns -= 1 // 고의적으로, change 이벤트가 발생하지 않도록 set(..)을 사용하지 않음.
536
+ this.set('widths', widths)
537
+ })
538
+ }
539
+
540
+ insertCellsAbove(cells: Component[]) {}
541
+
542
+ insertCellsBelow(cells: Component[]) {}
543
+
544
+ insertCellsLeft(cells: Component[]) {
545
+ // 먼저 cells 위치의 열을 구한다.
546
+ let columns: number[] = []
547
+ cells.forEach(cell => {
548
+ let column = this.getRowColumn(cell).column
549
+ if (-1 == columns.indexOf(column)) columns.push(column)
550
+ })
551
+ columns.sort((a, b) => {
552
+ return a - b
553
+ })
554
+ columns.reverse()
555
+
556
+ // 열 2개 이상은 추가 안함. 임시로 막아놓음
557
+ if (columns.length >= 2) return false
558
+ let insertionColumnPosition = columns[0]
559
+ let newbieColumnWidths: number[] = []
560
+ let newbieCells: Component[] = []
561
+ columns.forEach(column => {
562
+ for (let i = 0; i < this.rows; i++)
563
+ newbieCells.push(buildCopiedCell(this.components[column + this.columns * i].model, this.app))
564
+ newbieColumnWidths.push(this.widths[column])
565
+
566
+ let increasedColumns = this.columns
567
+ let index = this.rows
568
+ newbieCells.reverse().forEach(cell => {
569
+ if (index == 0) {
570
+ index = this.rows
571
+ increasedColumns++
572
+ }
573
+
574
+ index--
575
+ this.insertComponentAt(cell, insertionColumnPosition + index * increasedColumns)
576
+ })
577
+
578
+ let widths = this.widths.slice()
579
+ this.model.columns += columns.length // 고의적으로, change 이벤트가 발생하지 않도록 set(..)을 사용하지 않음.
580
+
581
+ widths.splice(insertionColumnPosition, 0, ...newbieColumnWidths)
582
+
583
+ this.set('widths', widths)
584
+ })
585
+ }
586
+
587
+ insertCellsRight(cells: Component[]) {
588
+ // 먼저 cells 위치의 열을 구한다.
589
+ let columns: number[] = []
590
+ cells.forEach(cell => {
591
+ let column = this.getRowColumn(cell).column
592
+ if (-1 == columns.indexOf(column)) columns.push(column)
593
+ })
594
+ columns.sort((a, b) => {
595
+ return a - b
596
+ })
597
+ columns.reverse()
598
+ // 열 2개 이상은 추가 안함. 임시로 막아놓음
599
+ if (columns.length >= 2) return false
600
+ let insertionColumnPosition = columns[columns.length - 1] + 1
601
+ let newbieColumnWidths: number[] = []
602
+ let newbieCells: Component[] = []
603
+ columns.forEach(column => {
604
+ for (let i = 0; i < this.rows; i++)
605
+ newbieCells.push(buildCopiedCell(this.components[column + this.columns * i].model, this.app))
606
+ newbieColumnWidths.push(this.widths[column])
607
+
608
+ let increasedColumns = this.columns
609
+ let index = this.rows
610
+ newbieCells.reverse().forEach(cell => {
611
+ if (index == 0) {
612
+ index = this.rows
613
+ increasedColumns++
614
+ }
615
+
616
+ index--
617
+ this.insertComponentAt(cell, insertionColumnPosition + index * increasedColumns)
618
+ })
619
+
620
+ let widths = this.widths.slice()
621
+ this.model.columns += columns.length // 고의적으로, change 이벤트가 발생하지 않도록 set(..)을 사용하지 않음.
622
+
623
+ widths.splice(insertionColumnPosition, 0, ...newbieColumnWidths)
624
+
625
+ this.set('widths', widths)
626
+ })
627
+ }
628
+
629
+ distributeHorizontal(cells: Component[]) {
630
+ var columns: number[] = []
631
+
632
+ cells.forEach(cell => {
633
+ let rowcolumn = this.getRowColumn(cell)
634
+
635
+ if (-1 == columns.indexOf(rowcolumn.column)) columns.push(rowcolumn.column)
636
+ })
637
+
638
+ var sum = columns.reduce((sum, column) => {
639
+ return sum + this.widths[column]
640
+ }, 0)
641
+
642
+ var newval = Math.round((sum / columns.length) * 100) / 100
643
+ var widths = this.widths.slice()
644
+ columns.forEach(column => {
645
+ widths[column] = newval
646
+ })
647
+
648
+ this.set('widths', widths)
649
+ }
650
+
651
+ distributeVertical(cells: Component[]) {}
652
+ }
653
+
654
+ Component.register('data-list', DataList)