Skip to content

Commit

Permalink
feat: draw mind map
Browse files Browse the repository at this point in the history
  • Loading branch information
zxch3n committed Jun 3, 2022
1 parent 21ac21c commit e455a18
Show file tree
Hide file tree
Showing 15 changed files with 388 additions and 102 deletions.
31 changes: 30 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
},
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react-dom": "^17.0.2",
"zrender": "^5.3.1"
}
}
1 change: 1 addition & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 10 additions & 4 deletions rust/crates/tidy-tree/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,16 @@ impl TidyTree {
self.layout.layout(&mut self.root);
}

pub fn get_pos(&self, id: usize) -> Option<(Coord, Coord)> {
let node = self.map.get(&id)?;
let node = unsafe { node.as_ref() };
Some((node.x, node.y))
pub fn get_pos(&self) -> Vec<Coord> {
let mut ans = vec![];
for (id, node) in self.map.iter() {
let node = unsafe { node.as_ref() };
ans.push((*id) as Coord);
ans.push(node.x);
ans.push(node.y);
}

ans
}
}

Expand Down
1 change: 1 addition & 0 deletions rust/crates/wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2.74"
tidy-tree = { path = "../tidy-tree" }
44 changes: 26 additions & 18 deletions rust/crates/wasm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,37 @@
mod linked_list;
extern crate wasm_bindgen;
use tidy_tree::{geometry::Coord, TidyTree, NULL_ID};
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
extern "C" {
pub fn alert(s: &str);
}
pub struct Tidy(TidyTree);

#[wasm_bindgen]
pub fn greet(name: &str) {
unsafe {
alert(&format!("Hello, {}!", name));
impl Tidy {
pub fn null_id() -> usize {
NULL_ID
}
}

#[wasm_bindgen]
pub fn sum_of_squares(input: &[i32]) -> i32 {
input.iter().map(|x| x * x).sum()
}
pub fn with_basic_layout() -> Self {
Tidy(TidyTree::with_basic_layout())
}

pub fn is_empty(&self) -> bool {
self.0.is_empty()
}

pub fn add_node(&mut self, id: usize, width: Coord, height: Coord, parent_id: usize) {
self.0.add_node(id, width, height, parent_id);
}

pub fn data(&mut self, id: &[usize], width: &[Coord], height: &[Coord], parent_id: &[usize]) {
self.0.data(id, width, height, parent_id);
}

pub fn layout(&mut self) {
self.0.layout();
}

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
let result = 2 + 2;
assert_eq!(result, 4);
pub fn get_pos(&self) -> Vec<Coord> {
self.0.get_pos()
}
}
69 changes: 0 additions & 69 deletions rust/crates/wasm/src/linked_list.rs

This file was deleted.

5 changes: 2 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { useEffect, useState } from 'react';
import { sumOfSquares, init } from './wasmEntry';
import { TidyLayout } from './tidy';

function App() {
const [count, setCount] = useState(0);
useEffect(() => {
(async () => {
await init();
console.log(sumOfSquares(1, 2));
console.log();
})();
}, []);

Expand Down
32 changes: 32 additions & 0 deletions src/TidyComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useEffect, useRef, useState } from 'react';
import { Renderer } from './renderer';
import { InnerNode, LayoutType, Node, TidyLayout } from './tidy';

interface Props {
root: Node;
layoutType?: LayoutType;
}

export const TidyComponent = ({ root, layoutType }: Props) => {
const renderRef = useRef<Renderer>();
const containerRef = useRef<HTMLDivElement>(null);
const layoutRef = useRef<TidyLayout>();
useEffect(() => {
const func = async () => {
renderRef.current = new Renderer(containerRef.current!);
layoutRef.current = await TidyLayout.create(layoutType);
const innerRoot = layoutRef.current.set_root(root);
layoutRef.current.layout();
renderRef.current.init(innerRoot);
// TODO: Draw
};

func();
return () => {
renderRef.current?.dispose();
};
}, []);
useEffect(() => {}, [root]);

return <div ref={containerRef} style={{ width: '100%', minHeight: 500 }} />;
};
44 changes: 44 additions & 0 deletions src/dispose.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

export interface IDisposable {
dispose(): void;
}

export function disposeAll(disposables: IDisposable[]) {
while (disposables.length) {
const item = disposables.pop();
if (item) {
item.dispose();
}
}
}

export abstract class Disposable {
private _isDisposed = false;

protected _disposables: IDisposable[] = [];

public dispose(): any {
if (this._isDisposed) {
return;
}
this._isDisposed = true;
disposeAll(this._disposables);
}

protected _register<T extends IDisposable>(value: T): T {
if (this._isDisposed) {
value.dispose();
} else {
this._disposables.push(value);
}
return value;
}

protected get isDisposed() {
return this._isDisposed;
}
}
68 changes: 68 additions & 0 deletions src/renderer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Rect, ZRenderType, dispose, init, BezierCurve, Group } from 'zrender';
import { Disposable } from './dispose';
import { InnerNode } from './tidy';
import { visit } from './utils';

export class Renderer extends Disposable {
private render: ZRenderType;
private root: InnerNode | undefined;
private rectMap: Map<number, Rect> = new Map();
private lineFromMap: Map<number, BezierCurve> = new Map();
private lineToMap: Map<number, BezierCurve> = new Map();
constructor(container: HTMLElement) {
super();
this.render = init(container);
this._register({
dispose: () => {
dispose(this.render);
},
});
}

init(root: InnerNode) {
this.root = root;
const g = new Group();
this.render.add(g);
g.setPosition([this.render.getWidth() / 2, 12]);
g.setScale([1.2, 1.2]);
visit(root, (node) => {
const rect = new Rect({
shape: {
x: node.x - node.width / 2,
y: node.y,
width: node.width,
height: node.height,
r: 4,
},
style: {
stroke: '#2b5de9',
fill: '#a8bbf0',
},
});
this.rectMap.set(node.id, rect);
g.add(rect);

for (const child of node.children) {
const line = new BezierCurve({
shape: {
x1: node.x,
y1: node.y + node.height,
x2: child.x,
y2: child.y,
cpx1: node.x,
cpy1: (child.y + node.y + node.height) / 2,
cpx2: child.x,
cpy2: (child.y + node.y + node.height) / 2,
},
style: {
stroke: '#2b5de9',
},
});

g.add(line);
this.lineFromMap.set(node.id, line);
this.lineToMap.set(child.id, line);
}
});
}
}
Loading

0 comments on commit e455a18

Please sign in to comment.