aboutsummaryrefslogtreecommitdiff
path: root/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'src/components')
-rw-r--r--src/components/Tile.vue33
-rw-r--r--src/components/TileTree.vue110
2 files changed, 55 insertions, 88 deletions
diff --git a/src/components/Tile.vue b/src/components/Tile.vue
index 09d6128..3ca02ce 100644
--- a/src/components/Tile.vue
+++ b/src/components/Tile.vue
@@ -1,43 +1,44 @@
<script lang="ts">
import {defineComponent, PropType} from 'vue';
-import {LayoutNode} from '../types';
+import {LayoutNode} from '../layout';
-const TRANSITION_DURATION = 300;
export default defineComponent({
name: 'tile',
data(){
return {
zIdx: 0,
- transitionDuration: TRANSITION_DURATION,
overFlow: 'visible',
}
},
props: {
layoutNode: {type: Object as PropType<LayoutNode>, required: true},
+ transitionDuration: {type: Number, required: true},
+ headerSz: {type: Number, required: true},
+ tileSpacing: {type: Number, required: true},
},
computed: {
name(){return this.layoutNode.tolNode.name.replaceAll('\'', '\\\'')}
},
methods: {
onImgClick(){
- this.$emit('tile-clicked', [this.layoutNode]);
+ this.$emit('tile-clicked', this.layoutNode);
//increase z-index and hide overflow during transition
this.zIdx = 1;
this.overFlow = 'hidden';
setTimeout(() => {this.zIdx = 0; this.overFlow = 'visible'}, this.transitionDuration);
},
- onInnerTileClicked(nodeList: LayoutNode[]){
- this.$emit('tile-clicked', [...nodeList, this.layoutNode]);
+ onInnerTileClicked(node: LayoutNode){
+ this.$emit('tile-clicked', node);
},
onHeaderClick(){
- this.$emit('header-clicked', [this.layoutNode]);
+ this.$emit('header-clicked', this.layoutNode);
//increase z-index and hide overflow during transition
this.zIdx = 1;
this.overFlow = 'hidden';
setTimeout(() => {this.zIdx = 0; this.overFlow = 'visible'}, this.transitionDuration);
},
- onInnerHeaderClicked(nodeList: LayoutNode[]){
- this.$emit('header-clicked', [...nodeList, this.layoutNode]);
+ onInnerHeaderClicked(node: LayoutNode){
+ this.$emit('header-clicked', node);
}
}
})
@@ -57,32 +58,30 @@ export default defineComponent({
/>
<div v-else>
<div
- v-if="(layoutNode.headerSz && !layoutNode.sepSweptArea) ||
+ v-if="(layoutNode.showHeader && !layoutNode.sepSweptArea) ||
(layoutNode.sepSweptArea && layoutNode.sepSweptArea.sweptLeft)"
- :style="{height: layoutNode.headerSz+'px'}"
+ :style="{height: headerSz+'px'}"
class="text-center hover:cursor-pointer bg-stone-300" @click="onHeaderClick">
{{layoutNode.tolNode.name}}
</div>
<div v-if="layoutNode.sepSweptArea"
:style="{position: 'absolute',
left: layoutNode.sepSweptArea.pos[0]+'px', top: layoutNode.sepSweptArea.pos[1]+'px',
- width: (layoutNode.sepSweptArea.dims[0] +
- (layoutNode.sepSweptArea.sweptLeft ? layoutNode.sepSweptArea.tileSpacing+1 : 0))+'px',
- height: (layoutNode.sepSweptArea.dims[1] +
- (layoutNode.sepSweptArea.sweptLeft ? 0 : layoutNode.sepSweptArea.tileSpacing+1))+'px',
+ width: (layoutNode.sepSweptArea.dims[0]+(layoutNode.sepSweptArea.sweptLeft ? tileSpacing+1 : 0))+'px',
+ height: (layoutNode.sepSweptArea.dims[1]+(layoutNode.sepSweptArea.sweptLeft ? 0 : tileSpacing+1))+'px',
borderRightColor: (layoutNode.sepSweptArea.sweptLeft ? 'white' : 'currentColor'),
borderBottomColor: (layoutNode.sepSweptArea.sweptLeft ? 'currentColor' : 'white'),
transitionDuration: transitionDuration+'ms'}"
class="transition-[left,top,width,height] ease-out border border-stone-900 bg-white">
- <div v-if="!layoutNode.sepSweptArea.sweptLeft" :style="{height: layoutNode.headerSz+'px'}"
+ <div v-if="!layoutNode.sepSweptArea.sweptLeft" :style="{height: headerSz+'px'}"
class="text-center hover:cursor-pointer bg-stone-300" @click="onHeaderClick">
{{layoutNode.tolNode.name}}
</div>
</div>
<tile v-for="child in layoutNode.children" :key="child.tolNode.name" :layoutNode="child"
+ :headerSz="headerSz" :tileSpacing="tileSpacing" :transitionDuration="transitionDuration"
@tile-clicked="onInnerTileClicked" @header-clicked="onInnerHeaderClicked"
></tile>
</div>
</div>
</template>
-
diff --git a/src/components/TileTree.vue b/src/components/TileTree.vue
index d662f50..0e5b793 100644
--- a/src/components/TileTree.vue
+++ b/src/components/TileTree.vue
@@ -2,12 +2,7 @@
import {defineComponent} from 'vue';
import Tile from './Tile.vue';
-import {TolNode, LayoutNode} from '../types';
-import {genLayout, layoutInfoHooks} from '../layout';
-//regarding importing a file f1.ts:
- //using 'import f1.ts' makes vue-tsc complain, and 'import f1.js' makes vite complain
- //using 'import f1' might cause problems with build systems other than vite
-
+import {TolNode} from '../types';
import tol from '../tol.json';
function preprocessTol(tree: any): void {
if (!tree.children){
@@ -18,96 +13,67 @@ function preprocessTol(tree: any): void {
}
preprocessTol(tol);
+import {LayoutTree, LayoutNode} from '../layout';
+import type {LayoutOptions} from '../layout';
+//regarding importing a file f1.ts:
+ //using 'import f1.ts' makes vue-tsc complain, and 'import f1.js' makes vite complain
+ //using 'import f1' might cause problems with build systems other than vite
+
+let defaultLayoutOptions: LayoutOptions = {
+ tileSpacing: 5,
+ headerSz: 20,
+ minTileSz: 50,
+ maxTileSz: 200,
+ layoutType: 'sweep', //'sqr' | 'rect' | 'sweep'
+ rectMode: 'auto', //'horz' | 'vert' | 'linear' | 'auto'
+ rectSpaceShifting: true,
+ sweepMode: 'left', //'left' | 'top' | 'shorter' | 'auto'
+ sweepingToParent: true,
+};
+let defaultOtherOptions = {
+ transitionDuration: 300,
+};
+
export default defineComponent({
data(){
return {
- layoutTree: this.initLayoutTree(tol as TolNode, 1),
+ layoutOptions: defaultLayoutOptions,
+ otherOptions: defaultOtherOptions,
+ layoutTree: new LayoutTree(tol as TolNode, 1, defaultLayoutOptions),
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
resizeThrottled: false,
}
},
methods: {
- initLayoutTree(tol: TolNode, lvl: number): LayoutNode {
- let node = new LayoutNode(tol, []);
- function initRec(node: LayoutNode, lvl: number){
- if (lvl > 0)
- node.children = node.tolNode.children.map(
- (n: TolNode) => initRec(new LayoutNode(n, []), lvl-1));
- return node;
- }
- initRec(node, lvl);
- layoutInfoHooks.initLayoutInfo(node)
- return node;
- },
onResize(){
if (!this.resizeThrottled){
this.width = document.documentElement.clientWidth;
this.height = document.documentElement.clientHeight;
- this.tryLayout();
+ if (!this.layoutTree.tryLayout([0,0], [this.width,this.height]))
+ console.log('Unable to layout tree');
//prevent re-triggering until after a delay
this.resizeThrottled = true;
setTimeout(() => {this.resizeThrottled = false;}, 100);
}
},
- onInnerTileClicked(nodeList: LayoutNode[]){
- //nodeList is an array of layout-nodes, from the clicked-on-tile's node upward
- let numNewTiles = nodeList[0].tolNode.children.length;
- if (numNewTiles == 0){
+ onInnerTileClicked(node: LayoutNode){
+ if (node.tolNode.children.length == 0){
console.log('Tile-to-expand has no children');
return;
}
- //add children
- nodeList[0].children = nodeList[0].tolNode.children.map((n: TolNode) => new LayoutNode(n, []));
- layoutInfoHooks.updateLayoutInfoOnExpand(nodeList);
- //try to re-layout
- if (!this.tryLayout()){
- nodeList[0].children = [];
- layoutInfoHooks.updateLayoutInfoOnCollapse(nodeList);
- }
- },
- onInnerHeaderClicked(nodeList: LayoutNode[]){
- //nodeList is an array of layout-nodes, from the clicked-on-tile's node upward
- let children = nodeList[0].children;
- nodeList[0].children = [];
- layoutInfoHooks.updateLayoutInfoOnCollapse(nodeList);
- if (!this.tryLayout()){
- nodeList[0].children = children;
- layoutInfoHooks.updateLayoutInfoOnExpand(nodeList);
- }
+ if (!this.layoutTree.tryLayoutOnExpand([0,0], [this.width,this.height], node))
+ console.log('Unable to layout tree');
},
- tryLayout(){
- let newLayout = genLayout(this.layoutTree, [0,0], [this.width,this.height], true);
- if (newLayout == null){
+ onInnerHeaderClicked(node: LayoutNode){
+ if (!this.layoutTree.tryLayoutOnCollapse([0,0], [this.width,this.height], node))
console.log('Unable to layout tree');
- return false;
- } else {
- this.applyLayout(newLayout, this.layoutTree);
- return true;
- }
},
- applyLayout(newLayout: LayoutNode, layoutTree: LayoutNode){
- layoutTree.pos = newLayout.pos;
- layoutTree.dims = newLayout.dims;
- layoutTree.headerSz = newLayout.headerSz;
- newLayout.children.forEach((n,i) => this.applyLayout(n, layoutTree.children[i]));
- //handle case where leaf nodes placed in leftover space from parent-sweep
- if (newLayout.sepSweptArea != null){
- //add parent area coords
- layoutTree.sepSweptArea = newLayout.sepSweptArea;
- //move leaf node children to parent area
- layoutTree.children.filter(n => n.children.length == 0).map(n => {
- n.pos[0] += newLayout.sepSweptArea!.pos[0],
- n.pos[1] += newLayout.sepSweptArea!.pos[1]
- });
- } else {
- layoutTree.sepSweptArea = null;
- }
- }
},
created(){
window.addEventListener('resize', this.onResize);
- this.tryLayout();
+ if (!this.layoutTree.tryLayout([0,0], [this.width,this.height]))
+ console.log('Unable to layout tree');
},
unmounted(){
window.removeEventListener('resize', this.onResize);
@@ -120,7 +86,9 @@ export default defineComponent({
<template>
<div class="h-[100vh]">
- <tile :layoutNode="layoutTree" @tile-clicked="onInnerTileClicked" @header-clicked="onInnerHeaderClicked"></tile>
+ <tile :layoutNode="layoutTree.root"
+ :headerSz="layoutOptions.headerSz" :tileSpacing="layoutOptions.tileSpacing"
+ :transitionDuration="otherOptions.transitionDuration"
+ @tile-clicked="onInnerTileClicked" @header-clicked="onInnerHeaderClicked"></tile>
</div>
</template>
-