-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
347 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
{ | ||
"rust-analyzer.linkedProjects": ["./examples/demo/Cargo.toml"] | ||
"rust-analyzer.linkedProjects": [ | ||
"./examples/demo/Cargo.toml", | ||
"./hframe-core/Cargo.toml" | ||
] | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[package] | ||
name = "hframe-core" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
use crate::{geo::*, id::*}; | ||
|
||
#[derive(Debug, Clone)] | ||
pub(crate) struct ComposedHtml { | ||
pub(crate) content: String, | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
pub(crate) enum ComposedAreaKind { | ||
Canvas, | ||
Html(ComposedHtml), | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
pub(crate) struct ComposedArea { | ||
pub(crate) id: Id, | ||
pub(crate) size: Size, | ||
pub(crate) abs_pos: Pos, | ||
pub(crate) kind: ComposedAreaKind, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
use crate::{ | ||
composed_area::ComposedArea, platform::Platform, test_platform::TestPlatform, tree::Node, | ||
}; | ||
|
||
struct Context<P: Platform> { | ||
tree: Node<ComposedArea>, | ||
platform: P, | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::{ | ||
composed_area::{ComposedAreaKind, ComposedHtml}, | ||
geo::{Pos, Size}, | ||
id::Id, | ||
}; | ||
|
||
use super::*; | ||
|
||
#[test] | ||
fn it_works() { | ||
let ctx = Context { | ||
tree: Node::new(ComposedArea { | ||
id: Id::from("root"), | ||
size: Size::new(100.0, 100.0), | ||
abs_pos: Pos::new(0.0, 0.0), | ||
kind: ComposedAreaKind::Canvas, | ||
}) | ||
.nest( | ||
Node::new(ComposedArea { | ||
id: Id::from("child"), | ||
size: Size::new(50.0, 50.0), | ||
abs_pos: Pos::new(10.0, 10.0), | ||
kind: ComposedAreaKind::Canvas, | ||
}) | ||
.nest(Node::new(ComposedArea { | ||
id: Id::from("grandchild"), | ||
size: Size::new(25.0, 25.0), | ||
abs_pos: Pos::new(5.0, 5.0), | ||
kind: ComposedAreaKind::Html(ComposedHtml { | ||
content: "<div>hello</div>".into(), | ||
}), | ||
})), | ||
), | ||
platform: TestPlatform { | ||
mouse_pos: Pos::new(0.0, 0.0), | ||
}, | ||
}; | ||
|
||
ctx.tree | ||
.find(|node| node.read(|data| data.value.id == Id::from("grandchild"))) | ||
.unwrap(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
#[derive(Debug, Clone, Copy, PartialEq, Default)] | ||
pub(crate) struct Pos { | ||
pub(crate) x: f64, | ||
pub(crate) y: f64, | ||
} | ||
|
||
impl Pos { | ||
pub(crate) fn new(x: f64, y: f64) -> Self { | ||
Pos { x, y } | ||
} | ||
} | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Default)] | ||
pub(crate) struct Size { | ||
pub(crate) width: f64, | ||
pub(crate) height: f64, | ||
} | ||
|
||
impl Size { | ||
pub(crate) fn new(width: f64, height: f64) -> Self { | ||
Size { width, height } | ||
} | ||
} | ||
|
||
/* | ||
#[derive(Debug, Clone, Copy, PartialEq, Default)] | ||
struct Rect { | ||
pos: Pos, | ||
size: Size, | ||
} | ||
impl Rect { | ||
fn new(pos: Pos, size: Size) -> Self { | ||
Rect { pos, size } | ||
} | ||
} | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
use std::hash::{DefaultHasher, Hash, Hasher}; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
pub(crate) struct Id(u64); | ||
|
||
impl From<u64> for Id { | ||
fn from(id: u64) -> Self { | ||
Id(id) | ||
} | ||
} | ||
|
||
impl From<&str> for Id { | ||
fn from(id: &str) -> Self { | ||
let mut hasher = DefaultHasher::new(); | ||
id.hash(&mut hasher); | ||
Id(hasher.finish()) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn it_works() { | ||
let id = Id::from("hello"); | ||
assert_eq!(id, Id::from("hello")); | ||
assert_ne!(id, Id::from("world")); | ||
|
||
let id = Id::from(42); | ||
assert_eq!(id, Id::from(42)); | ||
assert_ne!(id, Id::from(43)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
mod composed_area; | ||
mod context; | ||
mod geo; | ||
mod id; | ||
mod platform; | ||
mod test_platform; | ||
mod tree; | ||
mod web_platform; | ||
|
||
pub fn add(left: usize, right: usize) -> usize { | ||
left + right | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn it_works() { | ||
let result = add(2, 2); | ||
assert_eq!(result, 4); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
use crate::geo::Pos; | ||
|
||
pub(crate) trait Platform { | ||
fn mouse_pos(&self) -> Pos; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
use crate::{geo::Pos, platform::Platform}; | ||
|
||
pub(crate) struct TestPlatform { | ||
pub(crate) mouse_pos: Pos, | ||
} | ||
|
||
impl Platform for TestPlatform { | ||
fn mouse_pos(&self) -> Pos { | ||
self.mouse_pos | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
use std::{cell::RefCell, fmt::Debug, rc::Rc}; | ||
|
||
struct Handle<T>(Rc<RefCell<T>>); | ||
|
||
impl<T> Clone for Handle<T> { | ||
fn clone(&self) -> Self { | ||
Handle(Rc::clone(&self.0)) | ||
} | ||
} | ||
|
||
impl<T> Handle<T> { | ||
fn new(value: T) -> Self { | ||
Handle(Rc::new(RefCell::new(value))) | ||
} | ||
|
||
fn read<R>(&self, f: impl FnOnce(&T) -> R) -> R { | ||
match self.0.try_borrow() { | ||
Ok(value) => f(&value), | ||
Err(_) => panic!("The handle can't be read because it's being written somewhere else. Hint: Search where a `read_mut` closure is being used."), | ||
} | ||
} | ||
|
||
fn read_mut<R>(&self, f: impl FnOnce(&mut T) -> R) -> R { | ||
match self.0.try_borrow_mut() { | ||
Ok(mut value) => f(&mut value), | ||
Err(_) => panic!("The handle can't be written because it's being read somewhere else. Hint: Search where a `read` closure is being used."), | ||
} | ||
} | ||
} | ||
|
||
pub(crate) struct NodeData<T: Debug> { | ||
pub(crate) value: T, | ||
pub(crate) children: Vec<Node<T>>, | ||
} | ||
|
||
pub(crate) struct Node<T: Debug>(Handle<NodeData<T>>); | ||
|
||
impl<T: Debug> Clone for Node<T> { | ||
fn clone(&self) -> Self { | ||
Node(self.0.clone()) | ||
} | ||
} | ||
|
||
#[derive(Clone, Copy, Debug, PartialEq)] | ||
pub(crate) enum Walk { | ||
Continue, | ||
Stop, | ||
} | ||
|
||
impl<T: Debug> Node<T> { | ||
pub(crate) fn new(value: T) -> Self { | ||
Node(Handle::new(NodeData { | ||
value, | ||
children: Vec::new(), | ||
})) | ||
} | ||
|
||
pub(crate) fn nest(&self, node: Node<T>) -> Node<T> { | ||
self.read_mut(|data| data.children.push(node)); | ||
self.clone() | ||
} | ||
|
||
fn walk_impl(&self, f: &mut impl FnMut(Node<T>, usize) -> Walk, depth: usize) -> Walk { | ||
if f(self.clone(), depth) == Walk::Stop { | ||
return Walk::Stop; | ||
} | ||
|
||
self.read(|data| { | ||
for child in data.children.iter() { | ||
if child.walk_impl(f, depth + 1) == Walk::Stop { | ||
return Walk::Stop; | ||
} | ||
} | ||
|
||
Walk::Continue | ||
}) | ||
} | ||
|
||
pub(crate) fn walk(&self, mut f: impl FnMut(Node<T>, usize) -> Walk) { | ||
self.walk_impl(&mut f, 0); | ||
} | ||
|
||
// kepp this private to fully hide the handle | ||
fn data(&self) -> Handle<NodeData<T>> { | ||
self.0.clone() | ||
} | ||
|
||
pub(crate) fn find(&self, predicate: impl Fn(Node<T>) -> bool) -> Option<Node<T>> { | ||
let mut found = None; | ||
|
||
self.walk(|node, _| { | ||
if predicate(node.clone()) { | ||
found = Some(node.clone()); | ||
Walk::Stop | ||
} else { | ||
Walk::Continue | ||
} | ||
}); | ||
|
||
found | ||
} | ||
|
||
pub(crate) fn read<R>(&self, f: impl FnOnce(&NodeData<T>) -> R) -> R { | ||
self.data().read(|data| f(&data)) | ||
} | ||
|
||
pub(crate) fn read_mut<R>(&self, f: impl FnOnce(&mut NodeData<T>) -> R) -> R { | ||
self.data().read_mut(|data| f(data)) | ||
} | ||
} | ||
|
||
impl Debug for Node<String> { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
if f.alternate() { | ||
self.walk(|node, depth| { | ||
node.read(|data| { | ||
writeln!(f, "{:indent$}{:?}", "", data.value, indent = depth * 2).unwrap(); | ||
Walk::Continue | ||
}) | ||
}); | ||
} else { | ||
self.read(|data| { | ||
write!(f, "{:?}", data.value).unwrap(); | ||
|
||
if !data.children.is_empty() { | ||
write!(f, " {{").unwrap(); | ||
for child in data.children.iter() { | ||
write!(f, " {:?}", child).unwrap(); | ||
} | ||
write!(f, " }}").unwrap(); | ||
} | ||
}); | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
use crate::platform::Platform; | ||
|
||
pub struct WebPlatform; | ||
|
||
impl Platform for WebPlatform { | ||
fn mouse_pos(&self) -> crate::geo::Pos { | ||
crate::geo::Pos::new(0.0, 0.0) | ||
} | ||
} |