2929 </PopoverButton >
3030 </LayoutRow >
3131 <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))" >
3434 <div class =" visibility" >
3535 <IconButton
3636 :action =" (e) => (toggleLayerVisibility(layer.path), e && e.stopPropagation())"
@@ -307,12 +307,12 @@ export default defineComponent({
307307 opacityNumberInputDisabled: true ,
308308 // TODO: replace with BigUint64Array as index
309309 layerCache: new Map () as Map <string , LayerPanelEntry >,
310- layers: [] as LayerPanelEntry [],
310+ layers: [] as { folderIndex : number ; entry : LayerPanelEntry } [],
311311 layerDepths: [] as number [],
312312 selectionRangeStartLayer: undefined as undefined | LayerPanelEntry ,
313313 selectionRangeEndLayer: undefined as undefined | LayerPanelEntry ,
314314 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 },
316316 };
317317 },
318318 methods: {
@@ -343,63 +343,64 @@ export default defineComponent({
343343 },
344344 async clearSelection() {
345345 this .layers .forEach ((layer ) => {
346- layer .layer_metadata .selected = false ;
346+ layer .entry . layer_metadata .selected = false ;
347347 });
348348 },
349- closest(tree : HTMLElement , clientY : number ): [ BigUint64Array , boolean , Node ] {
349+ closest(tree : HTMLElement , clientY : number ): { insertFolder : BigUint64Array ; insertIndex : number ; insertAboveNode : Node } {
350350 const treeChildren = tree .children ;
351351
352352 // Closest distance to the middle of the row along the Y axis
353353 let closest = Infinity ;
354354
355355 // The nearest row parent (element of the tree)
356- let nearestElement = tree .lastChild as Node ;
356+ let insertAboveNode = tree .lastChild as Node ;
357357
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 ();
360360
361- // Item goes above or below the mouse
362- let above = false ;
361+ // Insert index
362+ let insertIndex = - 1 ;
363363
364364 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 ] ;
368368
369369 const indexAttribute = child .getAttribute (" data-index" );
370370 if (! indexAttribute ) return ;
371- const layer = this .layers [parseInt (indexAttribute , 10 )];
371+ const { folderIndex, entry : layer } = this .layers [parseInt (indexAttribute , 10 )];
372372
373373 const rect = child .getBoundingClientRect ();
374374 const position = rect .top + rect .height / 2 ;
375375 const distance = position - clientY ;
376376
377377 // Inserting above current row
378378 if (distance > 0 && distance < closest ) {
379+ insertAboveNode = treeChild ;
380+ insertFolder = layer .path .slice (0 , layer .path .length - 1 );
381+ insertIndex = folderIndex ;
379382 closest = distance ;
380- nearestPath = layer .path ;
381- above = true ;
382- if (child .parentNode ) {
383- nearestElement = child .parentNode ;
384- }
385383 }
386384 // 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 ) {
390386 if (child .parentNode && child .parentNode .nextSibling ) {
391- nearestElement = child .parentNode .nextSibling ;
387+ insertAboveNode = child .parentNode .nextSibling ;
392388 }
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 ;
393392 }
394393 // 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 ;
397396 }
398397 });
399398
400- return [ nearestPath , above , nearestElement ] ;
399+ return { insertFolder , insertIndex , insertAboveNode } ;
401400 },
402401 async dragStart(event : DragEvent , layer : LayerPanelEntry ) {
402+ if (! layer .layer_metadata .selected ) this .selectLayer (layer , event .ctrlKey , event .shiftKey );
403+
403404 // Set style of cursor for drag
404405 if (event .dataTransfer ) {
405406 event .dataTransfer .dropEffect = " move" ;
@@ -413,31 +414,30 @@ export default defineComponent({
413414 insertLine .classList .add (" insert-mark" );
414415 tree .appendChild (insertLine );
415416
416- const [nearestPath, above, nearestElement] = this .closest (tree , event .clientY );
417+ const { insertFolder, insertIndex, insertAboveNode } = this .closest (tree , event .clientY );
417418
418419 // 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 );
422423 }
423424
424- this .draggingData = { path: layer . path , above , nearestPath , insertLine };
425+ this .draggingData = { insertFolder , insertIndex , insertLine };
425426 },
426427 updateInsertLine(event : DragEvent ) {
427428 // Stop the drag from being shown as cancelled
428429 event .preventDefault ();
429430
430431 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 );
433433
434434 if (this .draggingData ) {
435- this .draggingData .nearestPath = nearestPath ;
436- this .draggingData .above = above ;
435+ this .draggingData .insertFolder = insertFolder ;
436+ this .draggingData .insertIndex = insertIndex ;
437437
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 );
441441 }
442442 }
443443 },
@@ -448,12 +448,15 @@ export default defineComponent({
448448 },
449449 async drop() {
450450 this .removeLine ();
451+
451452 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 );
453456 }
454457 },
455458 setBlendModeForSelectedLayers() {
456- const selected = this .layers .filter ((layer ) => layer .layer_metadata .selected );
459+ const selected = this .layers .filter ((layer ) => layer .entry . layer_metadata .selected );
457460
458461 if (selected .length < 1 ) {
459462 this .blendModeSelectedIndex = 0 ;
@@ -462,8 +465,8 @@ export default defineComponent({
462465 }
463466 this .blendModeDropdownDisabled = false ;
464467
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 );
467470
468471 if (allBlendModesAlike ) {
469472 this .blendModeSelectedIndex = this .blendModeEntries .flat ().findIndex ((entry ) => entry .value === firstEncounteredBlendMode );
@@ -474,7 +477,7 @@ export default defineComponent({
474477 },
475478 setOpacityForSelectedLayers() {
476479 // 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 );
478481
479482 if (selected .length < 1 ) {
480483 this .opacity = 100 ;
@@ -483,8 +486,8 @@ export default defineComponent({
483486 }
484487 this .opacityNumberInputDisabled = false ;
485488
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 );
488491
489492 if (allOpacitiesAlike ) {
490493 this .opacity = firstEncounteredOpacity ;
@@ -497,14 +500,14 @@ export default defineComponent({
497500 mounted() {
498501 this .editor .dispatcher .subscribeJsMessage (DisplayFolderTreeStructure , (displayFolderTreeStructure ) => {
499502 const path = [] as bigint [];
500- this .layers = [] as LayerPanelEntry [];
503+ this .layers = [] as { folderIndex : number ; entry : LayerPanelEntry } [];
501504
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 ) => {
504507 // TODO: fix toString
505508 path .push (BigInt (item .layerId .toString ()));
506509 const mapping = cache .get (path .toString ());
507- if (mapping ) layers .push (mapping );
510+ if (mapping ) layers .push ({ folderIndex: index , entry: mapping } );
508511 if (item .children .length >= 1 ) recurse (item , layers , cache );
509512 path .pop ();
510513 });
0 commit comments