@operato/scene-storage 10.0.0-beta.33 → 10.0.0-beta.34
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/CHANGELOG.md +14 -0
- package/dist/crane-3d.d.ts +14 -0
- package/dist/crane-3d.js +238 -0
- package/dist/crane-3d.js.map +1 -0
- package/dist/crane.d.ts +157 -0
- package/dist/crane.js +440 -0
- package/dist/crane.js.map +1 -0
- package/dist/index.d.ts +13 -6
- package/dist/index.js +9 -4
- package/dist/index.js.map +1 -1
- package/dist/mobile-storage-rack.d.ts +17 -0
- package/dist/mobile-storage-rack.js +55 -0
- package/dist/mobile-storage-rack.js.map +1 -0
- package/dist/rack-column.d.ts +35 -0
- package/dist/rack-column.js +258 -0
- package/dist/rack-column.js.map +1 -0
- package/dist/rack-grid-3d.d.ts +13 -0
- package/dist/rack-grid-3d.js +94 -0
- package/dist/rack-grid-3d.js.map +1 -0
- package/dist/rack-grid-cell.d.ts +341 -0
- package/dist/rack-grid-cell.js +321 -0
- package/dist/rack-grid-cell.js.map +1 -0
- package/dist/rack-grid-helpers.d.ts +28 -0
- package/dist/rack-grid-helpers.js +71 -0
- package/dist/rack-grid-helpers.js.map +1 -0
- package/dist/rack-grid-location.d.ts +37 -0
- package/dist/rack-grid-location.js +227 -0
- package/dist/rack-grid-location.js.map +1 -0
- package/dist/rack-grid.d.ts +80 -0
- package/dist/rack-grid.js +829 -0
- package/dist/rack-grid.js.map +1 -0
- package/dist/stock.d.ts +78 -0
- package/dist/stock.js +333 -0
- package/dist/stock.js.map +1 -0
- package/dist/{rack-cell-3d.d.ts → storage-cell-3d.d.ts} +1 -1
- package/dist/{rack-cell-3d.js → storage-cell-3d.js} +3 -3
- package/dist/storage-cell-3d.js.map +1 -0
- package/dist/{rack-cell.d.ts → storage-cell.d.ts} +12 -6
- package/dist/{rack-cell.js → storage-cell.js} +9 -9
- package/dist/storage-cell.js.map +1 -0
- package/dist/{asrs-rack-3d.d.ts → storage-rack-3d.d.ts} +1 -1
- package/dist/{asrs-rack-3d.js → storage-rack-3d.js} +4 -4
- package/dist/storage-rack-3d.js.map +1 -0
- package/dist/{asrs-rack.d.ts → storage-rack.d.ts} +22 -16
- package/dist/{asrs-rack.js → storage-rack.js} +32 -26
- package/dist/storage-rack.js.map +1 -0
- package/dist/templates/index.d.ts +60 -0
- package/dist/templates/index.js +59 -17
- package/dist/templates/index.js.map +1 -1
- package/package.json +2 -2
- package/src/crane-3d.ts +273 -0
- package/src/crane.ts +538 -0
- package/src/index.ts +13 -6
- package/src/mobile-storage-rack.ts +56 -0
- package/src/rack-column.ts +340 -0
- package/src/rack-grid-3d.ts +128 -0
- package/src/rack-grid-cell.ts +404 -0
- package/src/rack-grid-helpers.ts +77 -0
- package/src/rack-grid-location.ts +286 -0
- package/src/rack-grid.ts +994 -0
- package/src/stock.ts +426 -0
- package/src/{rack-cell-3d.ts → storage-cell-3d.ts} +2 -2
- package/src/{rack-cell.ts → storage-cell.ts} +19 -13
- package/src/{asrs-rack-3d.ts → storage-rack-3d.ts} +3 -3
- package/src/{asrs-rack.ts → storage-rack.ts} +31 -25
- package/src/templates/index.ts +59 -17
- package/test/test-rack-grid-crane.ts +212 -0
- package/test/test-rack-grid.ts +77 -0
- package/test/{test-asrs-crane.ts → test-storage-rack-crane.ts} +8 -8
- package/translations/en.json +55 -7
- package/translations/ja.json +52 -4
- package/translations/ko.json +52 -4
- package/translations/ms.json +55 -7
- package/translations/zh.json +52 -4
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/asrs-crane-3d.d.ts +0 -17
- package/dist/asrs-crane-3d.js +0 -181
- package/dist/asrs-crane-3d.js.map +0 -1
- package/dist/asrs-crane.d.ts +0 -98
- package/dist/asrs-crane.js +0 -216
- package/dist/asrs-crane.js.map +0 -1
- package/dist/asrs-rack-3d.js.map +0 -1
- package/dist/asrs-rack.js.map +0 -1
- package/dist/rack-cell-3d.js.map +0 -1
- package/dist/rack-cell.js.map +0 -1
- package/src/asrs-crane-3d.ts +0 -211
- package/src/asrs-crane.ts +0 -275
- /package/icons/{asrs-crane.png → crane.png} +0 -0
- /package/icons/{asrs-rack.png → storage-rack.png} +0 -0
package/src/rack-grid.ts
ADDED
|
@@ -0,0 +1,994 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © HatioLab Inc. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
ApplicationContext,
|
|
7
|
+
Component,
|
|
8
|
+
ComponentNature,
|
|
9
|
+
ContainerAbstract,
|
|
10
|
+
Control,
|
|
11
|
+
Layout,
|
|
12
|
+
Model,
|
|
13
|
+
POINT,
|
|
14
|
+
Properties,
|
|
15
|
+
sceneComponent,
|
|
16
|
+
RealObject
|
|
17
|
+
} from '@hatiolab/things-scene'
|
|
18
|
+
import type { State } from '@hatiolab/things-scene'
|
|
19
|
+
import * as THREE from 'three'
|
|
20
|
+
|
|
21
|
+
/** RackGrid 컴포넌트 state */
|
|
22
|
+
export interface RackGridState extends State {
|
|
23
|
+
rows?: number
|
|
24
|
+
columns?: number
|
|
25
|
+
zone?: string
|
|
26
|
+
shelves?: number
|
|
27
|
+
locPattern?: string
|
|
28
|
+
sectionDigits?: number
|
|
29
|
+
unitDigits?: number
|
|
30
|
+
shelfLocations?: string
|
|
31
|
+
stockScale?: number
|
|
32
|
+
hideRackFrame?: boolean
|
|
33
|
+
legendTarget?: string
|
|
34
|
+
hideEmptyStock?: boolean
|
|
35
|
+
widths?: number[]
|
|
36
|
+
heights?: number[]
|
|
37
|
+
}
|
|
38
|
+
import { RackGridCell } from './rack-grid-cell.js'
|
|
39
|
+
import { RackGrid3D } from './rack-grid-3d.js'
|
|
40
|
+
import { increaseLocation } from './rack-grid-location.js'
|
|
41
|
+
import type { StockMaterialProvider } from './stock.js'
|
|
42
|
+
|
|
43
|
+
const NATURE: ComponentNature = {
|
|
44
|
+
mutable: false,
|
|
45
|
+
resizable: true,
|
|
46
|
+
rotatable: true,
|
|
47
|
+
properties: [
|
|
48
|
+
{
|
|
49
|
+
type: 'number',
|
|
50
|
+
label: 'rows',
|
|
51
|
+
name: 'rows',
|
|
52
|
+
property: 'rows'
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: 'number',
|
|
56
|
+
label: 'columns',
|
|
57
|
+
name: 'columns',
|
|
58
|
+
property: 'columns'
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
type: 'string',
|
|
62
|
+
label: 'zone',
|
|
63
|
+
name: 'zone',
|
|
64
|
+
property: 'zone'
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: 'number',
|
|
68
|
+
label: 'shelves',
|
|
69
|
+
name: 'shelves',
|
|
70
|
+
property: 'shelves'
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
type: 'number',
|
|
74
|
+
label: 'depth',
|
|
75
|
+
name: 'depth',
|
|
76
|
+
property: 'depth'
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
type: 'string',
|
|
80
|
+
label: 'location-pattern',
|
|
81
|
+
name: 'locPattern',
|
|
82
|
+
placeholder: '{z}{s}-{u}-{sh}'
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
type: 'number',
|
|
86
|
+
label: 'section-digits',
|
|
87
|
+
name: 'sectionDigits',
|
|
88
|
+
placeholder: '1, 2, 3, ...'
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
type: 'number',
|
|
92
|
+
label: 'unit-digits',
|
|
93
|
+
name: 'unitDigits',
|
|
94
|
+
placeholder: '1, 2, 3, ...'
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: 'string',
|
|
98
|
+
label: 'shelf-locations',
|
|
99
|
+
name: 'shelfLocations',
|
|
100
|
+
placeholder: '1,2,3,... / ,,,04'
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
type: 'number',
|
|
104
|
+
label: 'stock-scale',
|
|
105
|
+
name: 'stockScale',
|
|
106
|
+
property: {
|
|
107
|
+
step: 0.01,
|
|
108
|
+
min: 0,
|
|
109
|
+
max: 1
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
type: 'checkbox',
|
|
114
|
+
label: 'hide-rack-frame',
|
|
115
|
+
name: 'hideRackFrame'
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
type: 'id-input',
|
|
119
|
+
label: 'legend-target',
|
|
120
|
+
name: 'legendTarget',
|
|
121
|
+
property: {
|
|
122
|
+
component: 'legend'
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
type: 'checkbox',
|
|
127
|
+
label: 'hide-empty-stock',
|
|
128
|
+
name: 'hideEmptyStock'
|
|
129
|
+
}
|
|
130
|
+
],
|
|
131
|
+
help: 'scene/component/rack-grid'
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
type SIDE_KEY = 'all' | 'out' | 'left' | 'right' | 'top' | 'bottom' | 'leftright' | 'topbottom'
|
|
135
|
+
|
|
136
|
+
const SIDES = {
|
|
137
|
+
all: ['top', 'left', 'bottom', 'right'],
|
|
138
|
+
out: ['top', 'left', 'bottom', 'right'],
|
|
139
|
+
left: ['left'],
|
|
140
|
+
right: ['right'],
|
|
141
|
+
top: ['top'],
|
|
142
|
+
bottom: ['bottom'],
|
|
143
|
+
leftright: ['left', 'right'],
|
|
144
|
+
topbottom: ['top', 'bottom']
|
|
145
|
+
} as { [key: string]: SIDE_KEY[] }
|
|
146
|
+
|
|
147
|
+
const CLEAR_STYLE = {
|
|
148
|
+
strokeStyle: '',
|
|
149
|
+
lineDash: 'solid',
|
|
150
|
+
lineWidth: 0
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const DEFAULT_STYLE = {
|
|
154
|
+
strokeStyle: '#999',
|
|
155
|
+
lineDash: 'solid',
|
|
156
|
+
lineWidth: 1
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const TABLE_LAYOUT = Layout.get('table')
|
|
160
|
+
|
|
161
|
+
function buildNewCell(app: ApplicationContext) {
|
|
162
|
+
return Model.compile(
|
|
163
|
+
{
|
|
164
|
+
type: 'rack-grid-cell',
|
|
165
|
+
strokeStyle: 'black',
|
|
166
|
+
fillStyle: 'transparent',
|
|
167
|
+
left: 0,
|
|
168
|
+
top: 0,
|
|
169
|
+
width: 1,
|
|
170
|
+
height: 1,
|
|
171
|
+
textWrap: true,
|
|
172
|
+
isEmpty: false,
|
|
173
|
+
border: buildBorderStyle(DEFAULT_STYLE, 'all')
|
|
174
|
+
},
|
|
175
|
+
app
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function buildCopiedCell(copy: any, app: ApplicationContext) {
|
|
180
|
+
const obj = JSON.parse(JSON.stringify(copy))
|
|
181
|
+
delete obj.text
|
|
182
|
+
|
|
183
|
+
return Model.compile(obj, app)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function buildBorderStyle(style: any, where: SIDE_KEY): { [key: string]: any } {
|
|
187
|
+
return (SIDES[where] || []).reduce((border: { [key: string]: any }, side: string) => {
|
|
188
|
+
border[side] = style
|
|
189
|
+
return border
|
|
190
|
+
}, {} as { [key: string]: any })
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function setCellBorder(cell: RackGridCell, style: any, where: SIDE_KEY) {
|
|
194
|
+
if (!cell) {
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
cell.set('border', Object.assign({}, cell.getState('border') || {}, buildBorderStyle(style, where)))
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function isLeftMost(total: number, columns: number, indices: number[], i: number) {
|
|
202
|
+
return i == 0 || !(i % columns) || indices.indexOf(i - 1) == -1
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function isRightMost(total: number, columns: number, indices: number[], i: number) {
|
|
206
|
+
return i == total - 1 || i % columns == columns - 1 || indices.indexOf(i + 1) == -1
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function isTopMost(total: number, columns: number, indices: number[], i: number) {
|
|
210
|
+
return i < columns || indices.indexOf(i - columns) == -1
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function isBottomMost(total: number, columns: number, indices: number[], i: number) {
|
|
214
|
+
return i > total - columns - 1 || indices.indexOf(i + columns) == -1
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function above(columns: number, i: number) {
|
|
218
|
+
return i - columns
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function below(columns: number, i: number) {
|
|
222
|
+
return i + columns
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function before(columns: number, i: number) {
|
|
226
|
+
return !(i % columns) ? -1 : i - 1
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function after(columns: number, i: number) {
|
|
230
|
+
return !((i + 1) % columns) ? -1 : i + 1
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function array(value: any, size: number) {
|
|
234
|
+
const arr = []
|
|
235
|
+
for (let i = 0; i < size; i++) arr.push(1)
|
|
236
|
+
return arr
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const columnControlHandler = {
|
|
240
|
+
ondragmove: function (point: POINT, index: number, component: RackGrid) {
|
|
241
|
+
const { left, top, width, height } = component.textBounds
|
|
242
|
+
const widths_sum = component.widths_sum
|
|
243
|
+
|
|
244
|
+
const widths = component.widths.slice()
|
|
245
|
+
|
|
246
|
+
/* 컨트롤의 원래 위치를 구한다. */
|
|
247
|
+
const origin_pos_unit = widths.slice(0, index + 1).reduce((sum: number, width: number) => sum + width, 0)
|
|
248
|
+
const origin_offset = left + (origin_pos_unit / widths_sum) * width
|
|
249
|
+
|
|
250
|
+
/*
|
|
251
|
+
* point의 좌표는 부모 레이어 기준의 x, y 값이다.
|
|
252
|
+
* 따라서, 도형의 회전을 감안한 좌표로의 변환이 필요하다.
|
|
253
|
+
* Transcoord시에는 point좌표가 부모까지 transcoord되어있는 상태이므로,
|
|
254
|
+
* 컴포넌트자신에 대한 transcoord만 필요하다.(마지막 파라미터를 false로).
|
|
255
|
+
*/
|
|
256
|
+
const transcoorded = component.transcoordP2S(point.x, point.y)
|
|
257
|
+
const diff = transcoorded.x - origin_offset
|
|
258
|
+
|
|
259
|
+
let diff_unit = (diff / width) * widths_sum
|
|
260
|
+
|
|
261
|
+
const min_width_unit = (widths_sum / width) * 5 // 5픽셀정도를 최소로
|
|
262
|
+
|
|
263
|
+
if (diff_unit < 0) diff_unit = -Math.min(widths[index] - min_width_unit, -diff_unit)
|
|
264
|
+
else diff_unit = Math.min(widths[index + 1] - min_width_unit, diff_unit)
|
|
265
|
+
|
|
266
|
+
widths[index] = Math.round((widths[index] + diff_unit) * 100) / 100
|
|
267
|
+
widths[index + 1] = Math.round((widths[index + 1] - diff_unit) * 100) / 100
|
|
268
|
+
|
|
269
|
+
component.set('widths', widths)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const rowControlHandler = {
|
|
274
|
+
ondragmove: function (point: POINT, index: number, component: RackGrid) {
|
|
275
|
+
const { left, top, width, height } = component.textBounds
|
|
276
|
+
const heights_sum = component.heights_sum
|
|
277
|
+
|
|
278
|
+
const heights = component.heights.slice()
|
|
279
|
+
|
|
280
|
+
/* 컨트롤의 원래 위치를 구한다. */
|
|
281
|
+
index -= component.columns - 1
|
|
282
|
+
const origin_pos_unit = heights.slice(0, index + 1).reduce((sum: number, height: number) => sum + height, 0)
|
|
283
|
+
const origin_offset = top + (origin_pos_unit / heights_sum) * height
|
|
284
|
+
|
|
285
|
+
/*
|
|
286
|
+
* point의 좌표는 부모 레이어 기준의 x, y 값이다.
|
|
287
|
+
* 따라서, 도형의 회전을 감안한 좌표로의 변환이 필요하다.
|
|
288
|
+
* Transcoord시에는 point좌표가 부모까지 transcoord되어있는 상태이므로,
|
|
289
|
+
* 컴포넌트자신에 대한 transcoord만 필요하다.(마지막 파라미터를 false로).
|
|
290
|
+
*/
|
|
291
|
+
const transcoorded = component.transcoordP2S(point.x, point.y)
|
|
292
|
+
const diff = transcoorded.y - origin_offset
|
|
293
|
+
|
|
294
|
+
let diff_unit = (diff / height) * heights_sum
|
|
295
|
+
|
|
296
|
+
const min_height_unit = (heights_sum / height) * 5 // 5픽셀정도를 최소로
|
|
297
|
+
|
|
298
|
+
if (diff_unit < 0) diff_unit = -Math.min(heights[index] - min_height_unit, -diff_unit)
|
|
299
|
+
else diff_unit = Math.min(heights[index + 1] - min_height_unit, diff_unit)
|
|
300
|
+
|
|
301
|
+
heights[index] = Math.round((heights[index] + diff_unit) * 100) / 100
|
|
302
|
+
heights[index + 1] = Math.round((heights[index + 1] - diff_unit) * 100) / 100
|
|
303
|
+
|
|
304
|
+
component.set('heights', heights)
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
@sceneComponent('rack-grid')
|
|
309
|
+
export default class RackGrid extends ContainerAbstract implements StockMaterialProvider {
|
|
310
|
+
override get state(): RackGridState {
|
|
311
|
+
return super.state as RackGridState
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
_focused_cell?: RackGridCell
|
|
315
|
+
|
|
316
|
+
// StockMaterialProvider 구현
|
|
317
|
+
_stock_materials: THREE.Material[] = []
|
|
318
|
+
_default_material?: THREE.Material
|
|
319
|
+
_empty_material?: THREE.Material
|
|
320
|
+
private _legendTarget?: Component
|
|
321
|
+
|
|
322
|
+
get legendTarget(): Component | undefined {
|
|
323
|
+
const { legendTarget } = this.state
|
|
324
|
+
|
|
325
|
+
if (!this._legendTarget && legendTarget) {
|
|
326
|
+
this._legendTarget = this.root.findById?.(legendTarget)
|
|
327
|
+
this._legendTarget?.on('change', this._onLegendChanged, this)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// 하위호환: 자체 legendTarget이 없으면 부모(Visualizer)의 legendTarget 폴백
|
|
331
|
+
if (!this._legendTarget) {
|
|
332
|
+
let ancestor = this.parent as any
|
|
333
|
+
while (ancestor) {
|
|
334
|
+
if (ancestor.legendTarget) return ancestor.legendTarget
|
|
335
|
+
ancestor = ancestor.parent
|
|
336
|
+
}
|
|
337
|
+
// 서비스 레지스트리 폴백: stock-hub의 legendTarget
|
|
338
|
+
const stockHub = (this.root as any)?.getService?.('stock')
|
|
339
|
+
if (stockHub?.legendTarget) return stockHub.legendTarget
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return this._legendTarget
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
get hideEmptyStock(): boolean {
|
|
346
|
+
return !!this.getState('hideEmptyStock')
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
private _onLegendChanged() {
|
|
350
|
+
this._resetMaterials()
|
|
351
|
+
this.invalidate()
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
private _resetMaterials() {
|
|
355
|
+
this._stock_materials.forEach(m => m.dispose?.())
|
|
356
|
+
this._stock_materials = []
|
|
357
|
+
delete this._default_material
|
|
358
|
+
delete this._empty_material
|
|
359
|
+
}
|
|
360
|
+
buildRealObject(): RealObject | undefined {
|
|
361
|
+
return new RackGrid3D(this)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
dispose() {
|
|
365
|
+
this._legendTarget?.off('change', this._onLegendChanged, this)
|
|
366
|
+
delete this._legendTarget
|
|
367
|
+
this._resetMaterials()
|
|
368
|
+
|
|
369
|
+
super.dispose()
|
|
370
|
+
|
|
371
|
+
delete this._focused_cell
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
created() {
|
|
375
|
+
const tobeSize = this.rows * this.columns
|
|
376
|
+
const gap = this.size() - tobeSize
|
|
377
|
+
|
|
378
|
+
if (gap == 0) {
|
|
379
|
+
return
|
|
380
|
+
} else if (gap > 0) {
|
|
381
|
+
let removals = this.components.slice(gap)
|
|
382
|
+
this.remove(removals)
|
|
383
|
+
} else {
|
|
384
|
+
let newbies = []
|
|
385
|
+
|
|
386
|
+
for (let i = 0; i < -gap; i++) newbies.push(buildNewCell(this.app))
|
|
387
|
+
|
|
388
|
+
this.add(newbies)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const widths = this.getState('widths')
|
|
392
|
+
const heights = this.getState('heights')
|
|
393
|
+
|
|
394
|
+
if (!widths || widths.length < this.columns) this.set('widths', this.widths)
|
|
395
|
+
if (!heights || heights.length < this.rows) this.set('heights', this.heights)
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// 컴포넌트를 임의로 추가 및 삭제할 수 있는 지를 지정하는 속성임.
|
|
399
|
+
get focusible() {
|
|
400
|
+
return false
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
get widths(): number[] {
|
|
404
|
+
const widths = this.getState('widths')
|
|
405
|
+
|
|
406
|
+
if (!widths) return array(1, this.columns)
|
|
407
|
+
|
|
408
|
+
if (widths.length < this.columns) return widths.concat(array(1, this.columns - widths.length))
|
|
409
|
+
else if (widths.length > this.columns) return widths.slice(0, this.columns)
|
|
410
|
+
|
|
411
|
+
return widths
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
get heights(): number[] {
|
|
415
|
+
const heights = this.getState('heights')
|
|
416
|
+
|
|
417
|
+
if (!heights) return array(1, this.rows)
|
|
418
|
+
|
|
419
|
+
if (heights.length < this.rows) return heights.concat(array(1, this.rows - heights.length))
|
|
420
|
+
else if (heights.length > this.rows) return heights.slice(0, this.rows)
|
|
421
|
+
|
|
422
|
+
return heights
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
buildCells(newrows: number, newcolumns: number, oldrows: number, oldcolumns: number) {
|
|
426
|
+
if (newrows < oldrows) {
|
|
427
|
+
let removals = this.components.slice(oldcolumns * newrows)
|
|
428
|
+
this.remove(removals)
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const minrows = Math.min(newrows, oldrows)
|
|
432
|
+
|
|
433
|
+
if (newcolumns > oldcolumns) {
|
|
434
|
+
for (let r = 0; r < minrows; r++) {
|
|
435
|
+
for (let c = oldcolumns; c < newcolumns; c++) {
|
|
436
|
+
this.insertComponentAt(buildNewCell(this.app), r * newcolumns + c)
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
} else if (newcolumns < oldcolumns) {
|
|
440
|
+
let removals = []
|
|
441
|
+
|
|
442
|
+
for (let r = 0; r < minrows; r++) {
|
|
443
|
+
for (let c = newcolumns; c < oldcolumns; c++) {
|
|
444
|
+
removals.push(this.components[r * oldcolumns + c])
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
this.remove(removals)
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
if (newrows > oldrows) {
|
|
451
|
+
let newbies = []
|
|
452
|
+
|
|
453
|
+
for (let r = oldrows; r < newrows; r++) {
|
|
454
|
+
for (let i = 0; i < newcolumns; i++) {
|
|
455
|
+
newbies.push(buildNewCell(this.app))
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
this.add(newbies)
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
this.set({
|
|
462
|
+
widths: this.widths,
|
|
463
|
+
heights: this.heights
|
|
464
|
+
})
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
get layout(): any {
|
|
468
|
+
return TABLE_LAYOUT
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
get rows() {
|
|
472
|
+
return this.getState('rows')
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
setCellsStyle(cells: RackGridCell[], style: any, where: string) {
|
|
476
|
+
const components = this.components
|
|
477
|
+
const total = components.length
|
|
478
|
+
const columns = this.getState('columns')
|
|
479
|
+
|
|
480
|
+
// 병합된 셀도 포함시킨다.
|
|
481
|
+
const _cells = [] as RackGridCell[]
|
|
482
|
+
cells.forEach(c => {
|
|
483
|
+
_cells.push(c)
|
|
484
|
+
if (c.colspan || c.rowspan) {
|
|
485
|
+
let col = this.getRowColumn(c).column
|
|
486
|
+
let row = this.getRowColumn(c).row
|
|
487
|
+
for (let i = row; i < row + c.rowspan; i++)
|
|
488
|
+
for (let j = col; j < col + c.colspan; j++)
|
|
489
|
+
if (i != row || j != col) _cells.push(this.components[i * this.columns + j] as RackGridCell)
|
|
490
|
+
}
|
|
491
|
+
})
|
|
492
|
+
|
|
493
|
+
const indices = _cells.map(cell => components.indexOf(cell))
|
|
494
|
+
indices.forEach(i => {
|
|
495
|
+
const cell = components[i] as RackGridCell
|
|
496
|
+
|
|
497
|
+
switch (where) {
|
|
498
|
+
case 'all':
|
|
499
|
+
setCellBorder(cell, style, where)
|
|
500
|
+
|
|
501
|
+
if (isLeftMost(total, columns, indices, i))
|
|
502
|
+
setCellBorder(components[before(columns, i)] as RackGridCell, style, 'right')
|
|
503
|
+
if (isRightMost(total, columns, indices, i))
|
|
504
|
+
setCellBorder(components[after(columns, i)] as RackGridCell, style, 'left')
|
|
505
|
+
if (isTopMost(total, columns, indices, i))
|
|
506
|
+
setCellBorder(components[above(columns, i)] as RackGridCell, style, 'bottom')
|
|
507
|
+
if (isBottomMost(total, columns, indices, i))
|
|
508
|
+
setCellBorder(components[below(columns, i)] as RackGridCell, style, 'top')
|
|
509
|
+
break
|
|
510
|
+
case 'in':
|
|
511
|
+
if (!isLeftMost(total, columns, indices, i)) {
|
|
512
|
+
setCellBorder(cell, style, 'left')
|
|
513
|
+
}
|
|
514
|
+
if (!isRightMost(total, columns, indices, i)) {
|
|
515
|
+
setCellBorder(cell, style, 'right')
|
|
516
|
+
}
|
|
517
|
+
if (!isTopMost(total, columns, indices, i)) {
|
|
518
|
+
setCellBorder(cell, style, 'top')
|
|
519
|
+
}
|
|
520
|
+
if (!isBottomMost(total, columns, indices, i)) {
|
|
521
|
+
setCellBorder(cell, style, 'bottom')
|
|
522
|
+
}
|
|
523
|
+
break
|
|
524
|
+
case 'out':
|
|
525
|
+
if (isLeftMost(total, columns, indices, i)) {
|
|
526
|
+
setCellBorder(cell, style, 'left')
|
|
527
|
+
setCellBorder(components[before(columns, i)] as RackGridCell, style, 'right')
|
|
528
|
+
}
|
|
529
|
+
if (isRightMost(total, columns, indices, i)) {
|
|
530
|
+
setCellBorder(cell, style, 'right')
|
|
531
|
+
setCellBorder(components[after(columns, i)] as RackGridCell, style, 'left')
|
|
532
|
+
}
|
|
533
|
+
if (isTopMost(total, columns, indices, i)) {
|
|
534
|
+
setCellBorder(cell, style, 'top')
|
|
535
|
+
setCellBorder(components[above(columns, i)] as RackGridCell, style, 'bottom')
|
|
536
|
+
}
|
|
537
|
+
if (isBottomMost(total, columns, indices, i)) {
|
|
538
|
+
setCellBorder(cell, style, 'bottom')
|
|
539
|
+
setCellBorder(components[below(columns, i)] as RackGridCell, style, 'top')
|
|
540
|
+
}
|
|
541
|
+
break
|
|
542
|
+
case 'left':
|
|
543
|
+
if (isLeftMost(total, columns, indices, i)) {
|
|
544
|
+
setCellBorder(cell, style, 'left')
|
|
545
|
+
setCellBorder(components[before(columns, i)] as RackGridCell, style, 'right')
|
|
546
|
+
}
|
|
547
|
+
break
|
|
548
|
+
case 'right':
|
|
549
|
+
if (isRightMost(total, columns, indices, i)) {
|
|
550
|
+
setCellBorder(cell, style, 'right')
|
|
551
|
+
setCellBorder(components[after(columns, i)] as RackGridCell, style, 'left')
|
|
552
|
+
}
|
|
553
|
+
break
|
|
554
|
+
case 'center':
|
|
555
|
+
if (!isLeftMost(total, columns, indices, i)) {
|
|
556
|
+
setCellBorder(cell, style, 'left')
|
|
557
|
+
}
|
|
558
|
+
if (!isRightMost(total, columns, indices, i)) {
|
|
559
|
+
setCellBorder(cell, style, 'right')
|
|
560
|
+
}
|
|
561
|
+
break
|
|
562
|
+
case 'middle':
|
|
563
|
+
if (!isTopMost(total, columns, indices, i)) {
|
|
564
|
+
setCellBorder(cell, style, 'top')
|
|
565
|
+
}
|
|
566
|
+
if (!isBottomMost(total, columns, indices, i)) {
|
|
567
|
+
setCellBorder(cell, style, 'bottom')
|
|
568
|
+
}
|
|
569
|
+
break
|
|
570
|
+
case 'top':
|
|
571
|
+
if (isTopMost(total, columns, indices, i)) {
|
|
572
|
+
setCellBorder(cell, style, 'top')
|
|
573
|
+
setCellBorder(components[above(columns, i)] as RackGridCell, style, 'bottom')
|
|
574
|
+
}
|
|
575
|
+
break
|
|
576
|
+
case 'bottom':
|
|
577
|
+
if (isBottomMost(total, columns, indices, i)) {
|
|
578
|
+
setCellBorder(cell, style, 'bottom')
|
|
579
|
+
setCellBorder(components[below(columns, i)] as RackGridCell, style, 'top')
|
|
580
|
+
}
|
|
581
|
+
break
|
|
582
|
+
case 'clear':
|
|
583
|
+
setCellBorder(cell, CLEAR_STYLE, 'all')
|
|
584
|
+
|
|
585
|
+
if (isLeftMost(total, columns, indices, i))
|
|
586
|
+
setCellBorder(components[before(columns, i)] as RackGridCell, CLEAR_STYLE, 'right')
|
|
587
|
+
if (isRightMost(total, columns, indices, i))
|
|
588
|
+
setCellBorder(components[after(columns, i)] as RackGridCell, CLEAR_STYLE, 'left')
|
|
589
|
+
if (isTopMost(total, columns, indices, i))
|
|
590
|
+
setCellBorder(components[above(columns, i)] as RackGridCell, CLEAR_STYLE, 'bottom')
|
|
591
|
+
if (isBottomMost(total, columns, indices, i))
|
|
592
|
+
setCellBorder(components[below(columns, i)] as RackGridCell, CLEAR_STYLE, 'top')
|
|
593
|
+
}
|
|
594
|
+
})
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
getRowColumn(cell: RackGridCell) {
|
|
598
|
+
const idx = this.components.indexOf(cell)
|
|
599
|
+
|
|
600
|
+
return {
|
|
601
|
+
column: idx % this.columns,
|
|
602
|
+
row: Math.floor(idx / this.columns)
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
getCellsByRow(row: number) {
|
|
607
|
+
return this.components.slice(row * this.columns, (row + 1) * this.columns)
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
getCellsByColumn(column: number) {
|
|
611
|
+
const cells = []
|
|
612
|
+
for (let i = 0; i < this.rows; i++) cells.push(this.components[this.columns * i + column])
|
|
613
|
+
|
|
614
|
+
return cells
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
deleteRows(cells: RackGridCell[]) {
|
|
618
|
+
// 먼저 cells 위치의 행을 구한다.
|
|
619
|
+
let rows = [] as number[]
|
|
620
|
+
|
|
621
|
+
cells.forEach(cell => {
|
|
622
|
+
let row = this.getRowColumn(cell).row
|
|
623
|
+
if (-1 == rows.indexOf(row)) {
|
|
624
|
+
rows.push(row)
|
|
625
|
+
}
|
|
626
|
+
})
|
|
627
|
+
|
|
628
|
+
rows.sort((a, b) => {
|
|
629
|
+
return a - b
|
|
630
|
+
})
|
|
631
|
+
|
|
632
|
+
rows.reverse()
|
|
633
|
+
|
|
634
|
+
const heights = this.heights.slice()
|
|
635
|
+
rows.forEach(row => {
|
|
636
|
+
this.remove(this.getCellsByRow(row))
|
|
637
|
+
})
|
|
638
|
+
|
|
639
|
+
rows.forEach(row => heights.splice(row, 1))
|
|
640
|
+
|
|
641
|
+
this.model.rows -= rows.length // 고의적으로, change 이벤트가 발생하지 않도록 set(..)을 사용하지 않음.
|
|
642
|
+
this.set('heights', heights)
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
deleteColumns(cells: RackGridCell[]) {
|
|
646
|
+
// 먼저 cells 위치의 열을 구한다.
|
|
647
|
+
let columns = [] as number[]
|
|
648
|
+
cells.forEach(cell => {
|
|
649
|
+
let column = this.getRowColumn(cell).column
|
|
650
|
+
if (-1 == columns.indexOf(column)) columns.push(column)
|
|
651
|
+
})
|
|
652
|
+
columns.sort((a, b) => {
|
|
653
|
+
return a - b
|
|
654
|
+
})
|
|
655
|
+
columns.reverse()
|
|
656
|
+
|
|
657
|
+
columns.forEach(column => {
|
|
658
|
+
const widths = this.widths.slice()
|
|
659
|
+
this.remove(this.getCellsByColumn(column))
|
|
660
|
+
widths.splice(column, 1)
|
|
661
|
+
this.model.columns -= 1 // 고의적으로, change 이벤트가 발생하지 않도록 set(..)을 사용하지 않음.
|
|
662
|
+
this.set('widths', widths)
|
|
663
|
+
})
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
insertCellsAbove(cells: RackGridCell[]) {
|
|
667
|
+
// 먼저 cells 위치의 행을 구한다.
|
|
668
|
+
let rows = [] as number[]
|
|
669
|
+
cells.forEach(cell => {
|
|
670
|
+
let row = this.getRowColumn(cell).row
|
|
671
|
+
if (-1 == rows.indexOf(row)) rows.push(row)
|
|
672
|
+
})
|
|
673
|
+
rows.sort((a, b) => {
|
|
674
|
+
return a - b
|
|
675
|
+
})
|
|
676
|
+
rows.reverse()
|
|
677
|
+
// 행 2개 이상은 추가 안함. 임시로 막아놓음
|
|
678
|
+
if (rows.length >= 2) return false
|
|
679
|
+
let insertionRowPosition = rows[0]
|
|
680
|
+
let newbieRowHeights = [] as number[]
|
|
681
|
+
let newbieCells = [] as RackGridCell[]
|
|
682
|
+
rows.forEach(row => {
|
|
683
|
+
for (let i = 0; i < this.columns; i++)
|
|
684
|
+
newbieCells.push(buildCopiedCell(this.components[row * this.columns + i].model, this.app) as RackGridCell)
|
|
685
|
+
|
|
686
|
+
newbieRowHeights.push(this.heights[row])
|
|
687
|
+
|
|
688
|
+
newbieCells.reverse().forEach(cell => {
|
|
689
|
+
this.insertComponentAt(cell, insertionRowPosition * this.columns)
|
|
690
|
+
})
|
|
691
|
+
|
|
692
|
+
let heights = this.heights.slice()
|
|
693
|
+
heights.splice(insertionRowPosition, 0, ...newbieRowHeights)
|
|
694
|
+
this.set('heights', heights)
|
|
695
|
+
|
|
696
|
+
this.model.rows += rows.length
|
|
697
|
+
|
|
698
|
+
this.clearCache()
|
|
699
|
+
})
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
insertCellsBelow(cells: RackGridCell[]) {
|
|
703
|
+
// 먼저 cells 위치의 행을 구한다.
|
|
704
|
+
let rows = [] as number[]
|
|
705
|
+
cells.forEach(cell => {
|
|
706
|
+
let row = this.getRowColumn(cell).row
|
|
707
|
+
if (-1 == rows.indexOf(row)) rows.push(row)
|
|
708
|
+
})
|
|
709
|
+
rows.sort((a, b) => {
|
|
710
|
+
return a - b
|
|
711
|
+
})
|
|
712
|
+
rows.reverse()
|
|
713
|
+
// 행 2개 이상은 추가 안함. 임시로 막아놓음
|
|
714
|
+
if (rows.length >= 2) return false
|
|
715
|
+
let insertionRowPosition = rows[rows.length - 1] + 1
|
|
716
|
+
let newbieRowHeights = [] as number[]
|
|
717
|
+
let newbieCells = [] as RackGridCell[]
|
|
718
|
+
rows.forEach(row => {
|
|
719
|
+
for (let i = 0; i < this.columns; i++)
|
|
720
|
+
newbieCells.push(buildCopiedCell(this.components[row * this.columns + i].model, this.app) as RackGridCell)
|
|
721
|
+
newbieRowHeights.push(this.heights[row])
|
|
722
|
+
|
|
723
|
+
newbieCells.reverse().forEach(cell => {
|
|
724
|
+
this.insertComponentAt(cell, insertionRowPosition * this.columns)
|
|
725
|
+
})
|
|
726
|
+
|
|
727
|
+
let heights = this.heights.slice()
|
|
728
|
+
heights.splice(insertionRowPosition, 0, ...newbieRowHeights)
|
|
729
|
+
this.set('heights', heights)
|
|
730
|
+
|
|
731
|
+
this.model.rows += 1
|
|
732
|
+
|
|
733
|
+
this.clearCache()
|
|
734
|
+
})
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
insertCellsLeft(cells: RackGridCell[]) {
|
|
738
|
+
// 먼저 cells 위치의 열을 구한다.
|
|
739
|
+
let columns = [] as number[]
|
|
740
|
+
cells.forEach(cell => {
|
|
741
|
+
let column = this.getRowColumn(cell).column
|
|
742
|
+
if (-1 == columns.indexOf(column)) columns.push(column)
|
|
743
|
+
})
|
|
744
|
+
columns.sort((a, b) => {
|
|
745
|
+
return a - b
|
|
746
|
+
})
|
|
747
|
+
columns.reverse()
|
|
748
|
+
// 열 2개 이상은 추가 안함. 임시로 막아놓음
|
|
749
|
+
if (columns.length >= 2) return false
|
|
750
|
+
let insertionColumnPosition = columns[0]
|
|
751
|
+
let newbieColumnWidths = [] as number[]
|
|
752
|
+
let newbieCells = [] as RackGridCell[]
|
|
753
|
+
columns.forEach(column => {
|
|
754
|
+
for (let i = 0; i < this.rows; i++)
|
|
755
|
+
newbieCells.push(buildCopiedCell(this.components[column + this.columns * i].model, this.app) as RackGridCell)
|
|
756
|
+
newbieColumnWidths.push(this.widths[column])
|
|
757
|
+
|
|
758
|
+
let increasedColumns = this.columns
|
|
759
|
+
let index = this.rows
|
|
760
|
+
newbieCells.reverse().forEach(cell => {
|
|
761
|
+
if (index == 0) {
|
|
762
|
+
index = this.rows
|
|
763
|
+
increasedColumns++
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
index--
|
|
767
|
+
this.insertComponentAt(cell, insertionColumnPosition + index * increasedColumns)
|
|
768
|
+
})
|
|
769
|
+
|
|
770
|
+
let widths = this.widths.slice()
|
|
771
|
+
this.model.columns += columns.length // 고의적으로, change 이벤트가 발생하지 않도록 set(..)을 사용하지 않음.
|
|
772
|
+
|
|
773
|
+
widths.splice(insertionColumnPosition, 0, ...newbieColumnWidths)
|
|
774
|
+
|
|
775
|
+
this.set('widths', widths)
|
|
776
|
+
})
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
insertCellsRight(cells: RackGridCell[]) {
|
|
780
|
+
// 먼저 cells 위치의 열을 구한다.
|
|
781
|
+
let columns = [] as number[]
|
|
782
|
+
cells.forEach(cell => {
|
|
783
|
+
let column = this.getRowColumn(cell).column
|
|
784
|
+
if (-1 == columns.indexOf(column)) columns.push(column)
|
|
785
|
+
})
|
|
786
|
+
columns.sort((a, b) => {
|
|
787
|
+
return a - b
|
|
788
|
+
})
|
|
789
|
+
columns.reverse()
|
|
790
|
+
// 열 2개 이상은 추가 안함. 임시로 막아놓음
|
|
791
|
+
if (columns.length >= 2) return false
|
|
792
|
+
let insertionColumnPosition = columns[columns.length - 1] + 1
|
|
793
|
+
let newbieColumnWidths = [] as number[]
|
|
794
|
+
let newbieCells = [] as RackGridCell[]
|
|
795
|
+
columns.forEach(column => {
|
|
796
|
+
for (let i = 0; i < this.rows; i++)
|
|
797
|
+
newbieCells.push(buildCopiedCell(this.components[column + this.columns * i].model, this.app) as RackGridCell)
|
|
798
|
+
newbieColumnWidths.push(this.widths[column])
|
|
799
|
+
|
|
800
|
+
let increasedColumns = this.columns
|
|
801
|
+
let index = this.rows
|
|
802
|
+
newbieCells.reverse().forEach(cell => {
|
|
803
|
+
if (index == 0) {
|
|
804
|
+
index = this.rows
|
|
805
|
+
increasedColumns++
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
index--
|
|
809
|
+
this.insertComponentAt(cell, insertionColumnPosition + index * increasedColumns)
|
|
810
|
+
})
|
|
811
|
+
|
|
812
|
+
let widths = this.widths.slice()
|
|
813
|
+
this.model.columns += columns.length // 고의적으로, change 이벤트가 발생하지 않도록 set(..)을 사용하지 않음.
|
|
814
|
+
|
|
815
|
+
widths.splice(insertionColumnPosition, 0, ...newbieColumnWidths)
|
|
816
|
+
|
|
817
|
+
this.set('widths', widths)
|
|
818
|
+
})
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
distributeHorizontal(cells: RackGridCell[]) {
|
|
822
|
+
const columns = [] as number[]
|
|
823
|
+
|
|
824
|
+
cells.forEach(cell => {
|
|
825
|
+
let rowcolumn = this.getRowColumn(cell)
|
|
826
|
+
|
|
827
|
+
if (-1 == columns.indexOf(rowcolumn.column)) columns.push(rowcolumn.column)
|
|
828
|
+
})
|
|
829
|
+
|
|
830
|
+
const sum = columns.reduce((sum, column) => {
|
|
831
|
+
return sum + this.widths[column]
|
|
832
|
+
}, 0)
|
|
833
|
+
|
|
834
|
+
const newval = Math.round((sum / columns.length) * 100) / 100
|
|
835
|
+
const widths = this.widths.slice()
|
|
836
|
+
columns.forEach(column => {
|
|
837
|
+
widths[column] = newval
|
|
838
|
+
})
|
|
839
|
+
|
|
840
|
+
this.set('widths', widths)
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
distributeVertical(cells: RackGridCell[]) {
|
|
844
|
+
const rows = [] as number[]
|
|
845
|
+
|
|
846
|
+
cells.forEach(cell => {
|
|
847
|
+
let rowcolumn = this.getRowColumn(cell)
|
|
848
|
+
|
|
849
|
+
if (-1 == rows.indexOf(rowcolumn.row)) rows.push(rowcolumn.row)
|
|
850
|
+
})
|
|
851
|
+
|
|
852
|
+
const sum = rows.reduce((sum, row) => {
|
|
853
|
+
return sum + this.heights[row]
|
|
854
|
+
}, 0)
|
|
855
|
+
|
|
856
|
+
const newval = Math.round((sum / rows.length) * 100) / 100
|
|
857
|
+
const heights = this.heights.slice()
|
|
858
|
+
rows.forEach(row => {
|
|
859
|
+
heights[row] = newval
|
|
860
|
+
})
|
|
861
|
+
|
|
862
|
+
this.set('heights', heights)
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
increaseLocation(type: string, skipNumbering: boolean, startSection: number, startUnit: number) {
|
|
866
|
+
const { sectionDigits = 2, unitDigits = 2 } = this.state
|
|
867
|
+
const selectedCells = this.root.selected as RackGridCell[]
|
|
868
|
+
|
|
869
|
+
increaseLocation(selectedCells, type, skipNumbering, startSection, startUnit, sectionDigits, unitDigits)
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
get columns() {
|
|
873
|
+
return this.getState('columns')
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
get lefts() {
|
|
877
|
+
return this.components.filter((c: any, i: any) => {
|
|
878
|
+
return !(i % this.columns)
|
|
879
|
+
})
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
get centers() {
|
|
883
|
+
return this.components.filter((c: any, i: any) => {
|
|
884
|
+
return i % this.columns && (i + 1) % this.columns
|
|
885
|
+
})
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
get rights() {
|
|
889
|
+
return this.components.filter((c: any, i: any) => {
|
|
890
|
+
return !((i + 1) % this.columns)
|
|
891
|
+
})
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
get tops() {
|
|
895
|
+
return this.components.slice(0, this.columns)
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
get middles() {
|
|
899
|
+
return this.components.slice(this.columns, this.columns * (this.rows - 1))
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
get bottoms() {
|
|
903
|
+
return this.components.slice(this.columns * (this.rows - 1))
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
get all() {
|
|
907
|
+
return this.components
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
get widths_sum() {
|
|
911
|
+
const widths = this.widths
|
|
912
|
+
return widths ? widths.filter((width, i) => i < this.columns).reduce((sum, width) => sum + width, 0) : this.columns
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
get heights_sum() {
|
|
916
|
+
const heights = this.heights
|
|
917
|
+
return heights ? heights.filter((height, i) => i < this.rows).reduce((sum, height) => sum + height, 0) : this.rows
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
get nature() {
|
|
921
|
+
return NATURE
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
get controls(): Array<Control> | undefined {
|
|
925
|
+
const widths = this.widths
|
|
926
|
+
const heights = this.heights
|
|
927
|
+
const inside = this.textBounds
|
|
928
|
+
|
|
929
|
+
const width_unit = inside.width / this.widths_sum
|
|
930
|
+
const height_unit = inside.height / this.heights_sum
|
|
931
|
+
|
|
932
|
+
let x = inside.left
|
|
933
|
+
let y = inside.top
|
|
934
|
+
|
|
935
|
+
const controls: Array<Control> = []
|
|
936
|
+
|
|
937
|
+
widths.slice(0, this.columns - 1).forEach((width: number) => {
|
|
938
|
+
x += width * width_unit
|
|
939
|
+
controls.push({
|
|
940
|
+
x: x,
|
|
941
|
+
y: inside.top,
|
|
942
|
+
handler: columnControlHandler
|
|
943
|
+
})
|
|
944
|
+
})
|
|
945
|
+
|
|
946
|
+
heights.slice(0, this.rows - 1).forEach((height: number) => {
|
|
947
|
+
y += height * height_unit
|
|
948
|
+
controls.push({
|
|
949
|
+
x: inside.left,
|
|
950
|
+
y: y,
|
|
951
|
+
handler: rowControlHandler
|
|
952
|
+
})
|
|
953
|
+
})
|
|
954
|
+
|
|
955
|
+
return controls
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
onchange(after: Properties, before: Properties) {
|
|
959
|
+
if ('legendTarget' in after || 'legendTarget' in before) {
|
|
960
|
+
this._legendTarget?.off('change', this._onLegendChanged, this)
|
|
961
|
+
delete this._legendTarget
|
|
962
|
+
this._resetMaterials()
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
if ('rows' in after || 'columns' in after) {
|
|
966
|
+
this.buildCells(
|
|
967
|
+
this.getState('rows'),
|
|
968
|
+
this.getState('columns'),
|
|
969
|
+
before.hasOwnProperty('rows') ? before.rows : this.getState('rows'),
|
|
970
|
+
before.hasOwnProperty('columns') ? before.columns : this.getState('columns')
|
|
971
|
+
)
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
this.invalidate()
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
get eventMap() {
|
|
978
|
+
return {
|
|
979
|
+
'(self)': {
|
|
980
|
+
'(descendant)': {
|
|
981
|
+
change: this.oncellchanged
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
oncellchanged(after: Properties, before: Properties) {
|
|
988
|
+
this.invalidate()
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
;['rows', 'columns', 'widths', 'heights', 'widths_sum', 'heights_sum', 'controls'].forEach(getter =>
|
|
993
|
+
Component.memoize(RackGrid.prototype, getter, false)
|
|
994
|
+
)
|