29
29
</PopoverButton >
30
30
</LayoutRow >
31
31
<LayoutRow :class =" 'layer-tree scrollable-y'" >
32
- <LayoutCol :class =" 'list'" ref =" layerTreeList" @click =" () => deselectAllLayers()" @dragover =" updateInsertLine($event)" @dragend =" drop()" >
33
- <div class =" layer-row" v-for =" (layer, index) in layers" :key =" String(layer.path.slice(-1))" >
32
+ <LayoutCol :class =" 'list'" ref =" layerTreeList" @click =" () => deselectAllLayers()" @dragover =" updateInsertLine($event)" @dragend =" drop($event )" >
33
+ <div class =" layer-row" v-for =" ({ entry: layer } , index) in layers" :key =" String(layer.path.slice(-1))" >
34
34
<div class =" visibility" >
35
35
<IconButton
36
36
:action =" (e) => (toggleLayerVisibility(layer.path), e && e.stopPropagation())"
@@ -307,12 +307,12 @@ export default defineComponent({
307
307
opacityNumberInputDisabled: true ,
308
308
// TODO: replace with BigUint64Array as index
309
309
layerCache: new Map () as Map <string , LayerPanelEntry >,
310
- layers: [] as LayerPanelEntry [],
310
+ layers: [] as { folderIndex : number ; entry : LayerPanelEntry } [],
311
311
layerDepths: [] as number [],
312
312
selectionRangeStartLayer: undefined as undefined | LayerPanelEntry ,
313
313
selectionRangeEndLayer: undefined as undefined | LayerPanelEntry ,
314
314
opacity: 100 ,
315
- draggingData: undefined as undefined | { path : BigUint64Array ; above : boolean ; nearestPath : BigUint64Array ; insertLine: HTMLDivElement },
315
+ draggingData: undefined as undefined | { insertFolder : BigUint64Array ; insertIndex : number ; insertLine: HTMLDivElement },
316
316
};
317
317
},
318
318
methods: {
@@ -343,63 +343,64 @@ export default defineComponent({
343
343
},
344
344
async clearSelection() {
345
345
this .layers .forEach ((layer ) => {
346
- layer .layer_metadata .selected = false ;
346
+ layer .entry . layer_metadata .selected = false ;
347
347
});
348
348
},
349
- closest(tree : HTMLElement , clientY : number ): [ BigUint64Array , boolean , Node ] {
349
+ closest(tree : HTMLElement , clientY : number ): { insertFolder : BigUint64Array ; insertIndex : number ; insertAboveNode : Node } {
350
350
const treeChildren = tree .children ;
351
351
352
352
// Closest distance to the middle of the row along the Y axis
353
353
let closest = Infinity ;
354
354
355
355
// The nearest row parent (element of the tree)
356
- let nearestElement = tree .lastChild as Node ;
356
+ let insertAboveNode = tree .lastChild as Node ;
357
357
358
- // The nearest element in the path to the mouse
359
- let nearestPath = new BigUint64Array ();
358
+ // Folder to insert into
359
+ let insertFolder = new BigUint64Array ();
360
360
361
- // Item goes above or below the mouse
362
- let above = false ;
361
+ // Insert index
362
+ let insertIndex = - 1 ;
363
363
364
364
Array .from (treeChildren ).forEach ((treeChild ) => {
365
- if ( treeChild . childElementCount <= 2 ) return ;
366
-
367
- const child = treeChild . children [ 2 ] as HTMLElement ;
365
+ const layerComponents = treeChild . getElementsByClassName ( " layer " ) ;
366
+ if ( layerComponents . length !== 1 ) return ;
367
+ const child = layerComponents [ 0 ] ;
368
368
369
369
const indexAttribute = child .getAttribute (" data-index" );
370
370
if (! indexAttribute ) return ;
371
- const layer = this .layers [parseInt (indexAttribute , 10 )];
371
+ const { folderIndex, entry : layer } = this .layers [parseInt (indexAttribute , 10 )];
372
372
373
373
const rect = child .getBoundingClientRect ();
374
374
const position = rect .top + rect .height / 2 ;
375
375
const distance = position - clientY ;
376
376
377
377
// Inserting above current row
378
378
if (distance > 0 && distance < closest ) {
379
+ insertAboveNode = treeChild ;
380
+ insertFolder = layer .path .slice (0 , layer .path .length - 1 );
381
+ insertIndex = folderIndex ;
379
382
closest = distance ;
380
- nearestPath = layer .path ;
381
- above = true ;
382
- if (child .parentNode ) {
383
- nearestElement = child .parentNode ;
384
- }
385
383
}
386
384
// Inserting below current row
387
- else if (distance > - closest && distance > - RANGE_TO_INSERT_WITHIN_BOTTOM_FOLDER_NOT_ROOT && distance < 0 && layer .layer_type !== " Folder" ) {
388
- closest = - distance ;
389
- nearestPath = layer .path ;
385
+ else if (distance > - closest && distance > - RANGE_TO_INSERT_WITHIN_BOTTOM_FOLDER_NOT_ROOT && distance < 0 ) {
390
386
if (child .parentNode && child .parentNode .nextSibling ) {
391
- nearestElement = child .parentNode .nextSibling ;
387
+ insertAboveNode = child .parentNode .nextSibling ;
392
388
}
389
+ insertFolder = layer .layer_type === " Folder" ? layer .path : layer .path .slice (0 , layer .path .length - 1 );
390
+ insertIndex = layer .layer_type === " Folder" ? 0 : folderIndex + 1 ;
391
+ closest = - distance ;
393
392
}
394
393
// Inserting with no nesting at the end of the panel
395
- else if (closest === Infinity ) {
396
- nearestPath = layer . path . slice ( 0 , 1 ) ;
394
+ else if (closest === Infinity && layer . path . length === 1 ) {
395
+ insertIndex = folderIndex + 1 ;
397
396
}
398
397
});
399
398
400
- return [ nearestPath , above , nearestElement ] ;
399
+ return { insertFolder , insertIndex , insertAboveNode } ;
401
400
},
402
401
async dragStart(event : DragEvent , layer : LayerPanelEntry ) {
402
+ if (! layer .layer_metadata .selected ) this .selectLayer (layer , event .ctrlKey , event .shiftKey );
403
+
403
404
// Set style of cursor for drag
404
405
if (event .dataTransfer ) {
405
406
event .dataTransfer .dropEffect = " move" ;
@@ -413,31 +414,30 @@ export default defineComponent({
413
414
insertLine .classList .add (" insert-mark" );
414
415
tree .appendChild (insertLine );
415
416
416
- const [nearestPath, above, nearestElement] = this .closest (tree , event .clientY );
417
+ const { insertFolder, insertIndex, insertAboveNode } = this .closest (tree , event .clientY );
417
418
418
419
// Set the initial state of the insert line
419
- if (nearestElement .parentNode ) {
420
- insertLine .style .marginLeft = ` ${LAYER_LEFT_MARGIN_OFFSET + LAYER_LEFT_INDENT_OFFSET * nearestPath .length }px ` ; // TODO: use layerIndent function to calculate this
421
- tree .insertBefore (insertLine , nearestElement );
420
+ if (insertAboveNode .parentNode ) {
421
+ insertLine .style .marginLeft = ` ${LAYER_LEFT_MARGIN_OFFSET + LAYER_LEFT_INDENT_OFFSET * ( insertFolder .length + 1 ) }px ` ; // TODO: use layerIndent function to calculate this
422
+ tree .insertBefore (insertLine , insertAboveNode );
422
423
}
423
424
424
- this .draggingData = { path: layer . path , above , nearestPath , insertLine };
425
+ this .draggingData = { insertFolder , insertIndex , insertLine };
425
426
},
426
427
updateInsertLine(event : DragEvent ) {
427
428
// Stop the drag from being shown as cancelled
428
429
event .preventDefault ();
429
430
430
431
const tree = (this .$refs .layerTreeList as typeof LayoutCol ).$el as HTMLElement ;
431
-
432
- const [nearestPath, above, nearestElement] = this .closest (tree , event .clientY );
432
+ const { insertFolder, insertIndex, insertAboveNode } = this .closest (tree , event .clientY );
433
433
434
434
if (this .draggingData ) {
435
- this .draggingData .nearestPath = nearestPath ;
436
- this .draggingData .above = above ;
435
+ this .draggingData .insertFolder = insertFolder ;
436
+ this .draggingData .insertIndex = insertIndex ;
437
437
438
- if (nearestElement .parentNode ) {
439
- this .draggingData .insertLine .style .marginLeft = ` ${LAYER_LEFT_MARGIN_OFFSET + LAYER_LEFT_INDENT_OFFSET * nearestPath .length }px ` ;
440
- tree .insertBefore (this .draggingData .insertLine , nearestElement );
438
+ if (insertAboveNode .parentNode ) {
439
+ this .draggingData .insertLine .style .marginLeft = ` ${LAYER_LEFT_MARGIN_OFFSET + LAYER_LEFT_INDENT_OFFSET * ( insertFolder .length + 1 ) }px ` ;
440
+ tree .insertBefore (this .draggingData .insertLine , insertAboveNode );
441
441
}
442
442
}
443
443
},
@@ -448,12 +448,15 @@ export default defineComponent({
448
448
},
449
449
async drop() {
450
450
this .removeLine ();
451
+
451
452
if (this .draggingData ) {
452
- this .editor .instance .move_layer_in_tree (this .draggingData .path , this .draggingData .above , this .draggingData .nearestPath );
453
+ const { insertFolder, insertIndex } = this .draggingData ;
454
+
455
+ this .editor .instance .move_layer_in_tree (insertFolder , insertIndex );
453
456
}
454
457
},
455
458
setBlendModeForSelectedLayers() {
456
- const selected = this .layers .filter ((layer ) => layer .layer_metadata .selected );
459
+ const selected = this .layers .filter ((layer ) => layer .entry . layer_metadata .selected );
457
460
458
461
if (selected .length < 1 ) {
459
462
this .blendModeSelectedIndex = 0 ;
@@ -462,8 +465,8 @@ export default defineComponent({
462
465
}
463
466
this .blendModeDropdownDisabled = false ;
464
467
465
- const firstEncounteredBlendMode = selected [0 ].blend_mode ;
466
- const allBlendModesAlike = ! selected .find ((layer ) => layer .blend_mode !== firstEncounteredBlendMode );
468
+ const firstEncounteredBlendMode = selected [0 ].entry . blend_mode ;
469
+ const allBlendModesAlike = ! selected .find ((layer ) => layer .entry . blend_mode !== firstEncounteredBlendMode );
467
470
468
471
if (allBlendModesAlike ) {
469
472
this .blendModeSelectedIndex = this .blendModeEntries .flat ().findIndex ((entry ) => entry .value === firstEncounteredBlendMode );
@@ -474,7 +477,7 @@ export default defineComponent({
474
477
},
475
478
setOpacityForSelectedLayers() {
476
479
// todo figure out why this is here
477
- const selected = this .layers .filter ((layer ) => layer .layer_metadata .selected );
480
+ const selected = this .layers .filter ((layer ) => layer .entry . layer_metadata .selected );
478
481
479
482
if (selected .length < 1 ) {
480
483
this .opacity = 100 ;
@@ -483,8 +486,8 @@ export default defineComponent({
483
486
}
484
487
this .opacityNumberInputDisabled = false ;
485
488
486
- const firstEncounteredOpacity = selected [0 ].opacity ;
487
- const allOpacitiesAlike = ! selected .find ((layer ) => layer .opacity !== firstEncounteredOpacity );
489
+ const firstEncounteredOpacity = selected [0 ].entry . opacity ;
490
+ const allOpacitiesAlike = ! selected .find ((layer ) => layer .entry . opacity !== firstEncounteredOpacity );
488
491
489
492
if (allOpacitiesAlike ) {
490
493
this .opacity = firstEncounteredOpacity ;
@@ -497,14 +500,14 @@ export default defineComponent({
497
500
mounted() {
498
501
this .editor .dispatcher .subscribeJsMessage (DisplayFolderTreeStructure , (displayFolderTreeStructure ) => {
499
502
const path = [] as bigint [];
500
- this .layers = [] as LayerPanelEntry [];
503
+ this .layers = [] as { folderIndex : number ; entry : LayerPanelEntry } [];
501
504
502
- const recurse = (folder : DisplayFolderTreeStructure , layers : LayerPanelEntry [], cache : Map <string , LayerPanelEntry >): void => {
503
- folder .children .forEach ((item ) => {
505
+ const recurse = (folder : DisplayFolderTreeStructure , layers : { folderIndex : number ; entry : LayerPanelEntry } [], cache : Map <string , LayerPanelEntry >): void => {
506
+ folder .children .forEach ((item , index ) => {
504
507
// TODO: fix toString
505
508
path .push (BigInt (item .layerId .toString ()));
506
509
const mapping = cache .get (path .toString ());
507
- if (mapping ) layers .push (mapping );
510
+ if (mapping ) layers .push ({ folderIndex: index , entry: mapping } );
508
511
if (item .children .length >= 1 ) recurse (item , layers , cache );
509
512
path .pop ();
510
513
});
0 commit comments