diff --git a/rust/crates/tidy-tree/src/layout/basic_layout.rs b/rust/crates/tidy-tree/src/layout/basic_layout.rs index 401c515..390704e 100644 --- a/rust/crates/tidy-tree/src/layout/basic_layout.rs +++ b/rust/crates/tidy-tree/src/layout/basic_layout.rs @@ -35,6 +35,13 @@ impl Default for BoundingBox { impl Layout for BasicLayout { fn layout(&mut self, root: &mut Node) { + root.pre_order_traversal_mut(|node| { + node.tidy = None; + node.x = 0.; + node.y = 0.; + node.relative_x = 0.; + node.relative_y = 0.; + }); root.post_order_traversal_mut(|node| { self.update_meta(node); }); diff --git a/rust/crates/tidy-tree/src/layout/tidy_layout.rs b/rust/crates/tidy-tree/src/layout/tidy_layout.rs index 44982aa..b40b4d1 100644 --- a/rust/crates/tidy-tree/src/layout/tidy_layout.rs +++ b/rust/crates/tidy-tree/src/layout/tidy_layout.rs @@ -332,6 +332,10 @@ impl Layout for TidyLayout { modifier_thread_right: 0., test: TEST, })); + node.x = 0.; + node.y = 0.; + node.relative_x = 0.; + node.relative_y = 0.; }); self.set_y(root); self.first_walk(root); diff --git a/rust/crates/tidy-tree/src/lib.rs b/rust/crates/tidy-tree/src/lib.rs index 7dd5098..065f083 100644 --- a/rust/crates/tidy-tree/src/lib.rs +++ b/rust/crates/tidy-tree/src/lib.rs @@ -10,8 +10,15 @@ use layout::BoundingBox; pub use layout::{BasicLayout, Layout, TidyLayout}; pub use node::Node; +#[derive(PartialEq, Eq)] +pub enum LayoutType { + Basic, + Tidy, +} + pub struct TidyTree { root: Node, + layout_type: LayoutType, layout: Box, map: HashMap>, } @@ -19,6 +26,7 @@ pub struct TidyTree { impl TidyTree { pub fn with_basic_layout() -> Self { TidyTree { + layout_type: LayoutType::Basic, root: Default::default(), layout: Box::new(BasicLayout { parent_child_margin: 10., @@ -28,6 +36,41 @@ impl TidyTree { } } + pub fn with_tidy_layout() -> Self { + TidyTree { + layout_type: LayoutType::Tidy, + root: Default::default(), + layout: Box::new(TidyLayout { + parent_child_margin: 10., + peer_margin: 10., + }), + map: HashMap::new(), + } + } + + pub fn change_layout(&mut self, layout_type: LayoutType) { + if layout_type == self.layout_type { + return; + } + + match layout_type { + LayoutType::Basic => { + self.layout = Box::new(BasicLayout { + parent_child_margin: 10., + peer_margin: 10., + }); + } + LayoutType::Tidy => { + self.layout = Box::new(TidyLayout { + parent_child_margin: 10., + peer_margin: 10., + }); + } + } + + self.layout_type = layout_type; + } + pub fn is_empty(&self) -> bool { self.root.id == usize::MAX } diff --git a/rust/crates/wasm/src/lib.rs b/rust/crates/wasm/src/lib.rs index c87f953..e989a0e 100644 --- a/rust/crates/wasm/src/lib.rs +++ b/rust/crates/wasm/src/lib.rs @@ -1,10 +1,16 @@ extern crate wasm_bindgen; -use tidy_tree::{geometry::Coord, TidyTree, NULL_ID}; +use tidy_tree::{geometry::Coord, LayoutType, TidyTree, NULL_ID}; use wasm_bindgen::prelude::*; #[wasm_bindgen] pub struct Tidy(TidyTree); +#[wasm_bindgen] +pub enum WasmLayoutType { + Basic, + Tidy, +} + #[wasm_bindgen] impl Tidy { pub fn null_id() -> usize { @@ -15,6 +21,17 @@ impl Tidy { Tidy(TidyTree::with_basic_layout()) } + pub fn with_tidy_layout() -> Self { + Tidy(TidyTree::with_tidy_layout()) + } + + pub fn change_layout(&mut self, layout_type: WasmLayoutType) { + match layout_type { + WasmLayoutType::Basic => self.0.change_layout(LayoutType::Basic), + WasmLayoutType::Tidy => self.0.change_layout(LayoutType::Tidy), + } + } + pub fn is_empty(&self) -> bool { self.0.is_empty() } diff --git a/src/TidyComponent.tsx b/src/TidyComponent.tsx index dfdd44a..2ec6063 100644 --- a/src/TidyComponent.tsx +++ b/src/TidyComponent.tsx @@ -1,25 +1,35 @@ -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useRef } from 'react'; + import { Renderer } from './renderer'; -import { InnerNode, LayoutType, Node, TidyLayout } from './tidy'; +import { LayoutType, Node, TidyLayout } from './tidy'; + +export enum LayoutTypeStr { + Tidy = 'tidy', + Basic = 'basic', +} interface Props { root: Node; - layoutType?: LayoutType; + layoutType?: LayoutTypeStr; updateTrigger?: number; } +function getLayoutType(type?: LayoutTypeStr) { + return type === LayoutTypeStr.Tidy ? LayoutType.Tidy : LayoutType.Basic; +} + export const TidyComponent = ({ root, layoutType, updateTrigger }: Props) => { const renderRef = useRef(); const containerRef = useRef(null); const layoutRef = useRef(); + const type = getLayoutType(layoutType); useEffect(() => { const func = async () => { renderRef.current = new Renderer(containerRef.current!); - layoutRef.current = await TidyLayout.create(layoutType); + layoutRef.current = await TidyLayout.create(type); const innerRoot = layoutRef.current.set_root(root); layoutRef.current.layout(); renderRef.current.init(innerRoot); - // TODO: Draw }; func(); @@ -32,9 +42,10 @@ export const TidyComponent = ({ root, layoutType, updateTrigger }: Props) => { return; } + layoutRef.current.changeLayoutType(type); layoutRef.current.layout(true); renderRef.current.update(); - }, [updateTrigger]); + }, [updateTrigger, type]); return
; }; diff --git a/src/stories/Tidy.stories.tsx b/src/stories/Tidy.stories.tsx index fe8bbd4..197c171 100644 --- a/src/stories/Tidy.stories.tsx +++ b/src/stories/Tidy.stories.tsx @@ -1,24 +1,28 @@ import React, { useCallback, useState } from 'react'; -import { LayoutType, Node } from '../tidy'; -import { TidyComponent } from '../TidyComponent'; -import { produce } from 'immer'; -import { ComponentStory, ComponentMeta } from '@storybook/react'; +import { Node } from '../tidy'; +import { LayoutTypeStr, TidyComponent } from '../TidyComponent'; import { createNode, createTree, visit } from '../utils'; export default { title: 'Tidy', component: TidyComponent, -} as ComponentMeta; + argTypes: { + layoutType: { + options: [LayoutTypeStr.Tidy, LayoutTypeStr.Basic], + defaultValue: LayoutTypeStr.Basic, + }, + }, +}; interface Props { - layoutType?: LayoutType; - root: Node; + layoutType: LayoutTypeStr; } +const root = createTree(200) as Node; /** * Primary UI component for user interaction */ -export const TidyLayout = ({ root, layoutType, ...props }: Props) => { +export const TidyLayout = ({ layoutType, ...props }: Props) => { const [updateTrigger, setUpdate] = useState(0); const addNode = useCallback(() => { let nodes: [Node, number][] = []; @@ -50,9 +54,3 @@ export const TidyLayout = ({ root, layoutType, ...props }: Props) => {
); }; - -TidyLayout.args = { - root: createTree(200) as Node, -}; - -TidyLayout.play = () => {}; diff --git a/src/tidy.ts b/src/tidy.ts index 7c0250d..98f42e2 100644 --- a/src/tidy.ts +++ b/src/tidy.ts @@ -3,13 +3,12 @@ import _initWasm, { InitOutput, Tidy, Tidy as TidyWasm, + WasmLayoutType as LayoutType, } from '../wasm_dist/wasm'; import { Disposable } from './dispose'; import { visit } from './utils'; -export enum LayoutType { - Basic = 'basic', -} +export { LayoutType }; let promise: Promise | undefined; @@ -65,6 +64,8 @@ export class TidyLayout extends Disposable { super(); if (type === LayoutType.Basic) { this.tidy = TidyWasm.with_basic_layout(); + } else if (type === LayoutType.Tidy) { + this.tidy = TidyWasm.with_tidy_layout(); } else { throw new Error('not implemented'); } @@ -75,6 +76,10 @@ export class TidyLayout extends Disposable { }); } + changeLayoutType(type: LayoutType) { + this.tidy.change_layout(type); + } + layout(updated = false) { if (updated) { visit(this.root!, (node) => {