aboutsummaryrefslogtreecommitdiff
path: root/src/components/TileTree.vue
blob: 5c3d08e9d9b194b2e121dec365f8a600e5eefc89 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<script>
import Tile from './Tile.vue';

import tol from '/src/tol.json';
function preprocessTol(tree){
	if (!tree.children){
		tree.children = [];
	} else {
		tree.children.forEach(preprocessTol);
	}
}
preprocessTol(tol);

import {staticSqrLayout, staticRectLayout, sweepToSideLayout} from '/src/layout.js';
let LAYOUT_SYS = sweepToSideLayout;

export default {
	data(){
		return {
			tree: this.initTree(tol, 1),
			width: document.documentElement.clientWidth,
			height: document.documentElement.clientHeight,
		}
	},
	methods: {
		initTree(tol, lvl){
			let tree = {
				tolNode:tol, children:[],
				x:0, y:0, w:0, h:0, headerSz:0,
			};
			function initTreeRec(tree, lvl){
				if (lvl > 0)
					tree.children = tree.tolNode.children.map(tNode => initTreeRec({
						tolNode: tNode, children: [],
						x:0, y:0, w:0, h:0, headerSz:0,
					}, lvl-1));
				return tree;
			}
			initTreeRec(tree, lvl);
			LAYOUT_SYS.initLayoutInfo(tree)
			return tree;
		},
		onResize(){
			this.width = document.documentElement.clientWidth;
			this.height = document.documentElement.clientHeight;
			this.tryLayout(); //use best-effort collapsing-layout?
		},
		onInnerTileClicked(nodeList){
			//nodeList holds an array of tree-objects, from the clicked-on-tile's tree-object upward
			let numNewTiles = nodeList[0].tolNode.children.length;
			if (numNewTiles == 0){
				console.log('Tile-to-expand has no children');
				return;
			}
			//add children
			nodeList[0].children = nodeList[0].tolNode.children.map(tNode => ({
				tolNode: tNode, children: [],
				x:0, y:0, w:0, h:0, headerSz:0,
			}));
			LAYOUT_SYS.updateLayoutInfoOnExpand(nodeList);
			//try to layout tree
			if (!this.tryLayout())
				nodeList[0].children = [];
		},
		onInnerHeaderClicked(nodeList){ //nodeList is array of tree-objects, from clicked-on-tile's tree-object upward
			nodeList[0].children = [];
			LAYOUT_SYS.updateLayoutInfoOnCollapse(nodeList);
			this.tryLayout();
		},
		tryLayout(){
			let layout = LAYOUT_SYS.genLayout(this.tree, 0, 0, this.width, this.height, true);
			if (layout == null){
				console.log('Unable to layout tree');
				return false;
			} else {
				this.applyLayout(layout, this.tree);
				return true;
			}
		},
		applyLayout(layout, tree){
			//layout format: {x, y, w, h, headerSz, children:[layout1, ...], contentW, contentH, empSpc}
			tree.x = layout.x;
			tree.y = layout.y;
			tree.w = layout.w;
			tree.h = layout.h;
			tree.headerSz = layout.headerSz;
			layout.children.forEach((n,i) => this.applyLayout(n, tree.children[i]));
		}
	},
	created(){
		window.addEventListener('resize', this.onResize);
		this.tryLayout();
	},
	unmounted(){
		window.removeEventListener('resize', this.onResize);
	},
	components: {
		Tile
	}
}
</script>

<template>
<div class="h-[100vh]">
	<tile :tree="tree" @tile-clicked="onInnerTileClicked" @header-clicked="onInnerHeaderClicked"></tile>
</div>
</template>