-
Notifications
You must be signed in to change notification settings - Fork 5
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
6 changed files
with
260 additions
and
7 deletions.
There are no files selected for viewing
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
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
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 +1,157 @@ | ||
use concoct::{Handle, Object, Signal, Slot}; | ||
use web_sys::wasm_bindgen::JsCast; | ||
|
||
pub trait View { | ||
fn node(&self) -> &web_sys::Node; | ||
|
||
fn set_parent(&mut self, parent: web_sys::Element); | ||
} | ||
|
||
pub trait IntoView { | ||
type View: View; | ||
|
||
fn into_view(self) -> Handle<Self::View>; | ||
} | ||
|
||
impl<V> IntoView for V | ||
where | ||
V: View + Object + 'static, | ||
{ | ||
type View = V; | ||
|
||
fn into_view(self) -> Handle<Self::View> { | ||
self.spawn() | ||
} | ||
} | ||
|
||
impl<V: View> IntoView for Handle<V> { | ||
type View = V; | ||
|
||
fn into_view(self) -> Handle<Self::View> { | ||
self | ||
} | ||
} | ||
|
||
|
||
pub trait ViewGroup { | ||
type Handles; | ||
|
||
fn view_group(self) -> Self::Handles; | ||
} | ||
|
||
impl<V: IntoView> ViewGroup for V { | ||
type Handles = Handle<V::View>; | ||
|
||
fn view_group(self) -> Self::Handles { | ||
self.into_view() | ||
} | ||
} | ||
|
||
impl<A: IntoView, B: IntoView, C: IntoView> ViewGroup for (A, B, C) { | ||
type Handles = (Handle<A::View>, Handle<B::View> ,Handle<C::View>); | ||
|
||
fn view_group(self) -> Self::Handles { | ||
(self.0.into_view(), self.1.into_view(), self.2.into_view()) | ||
} | ||
} | ||
|
||
pub struct MouseEvent; | ||
|
||
pub struct ElementBuilder { | ||
|
||
} | ||
|
||
impl ElementBuilder { | ||
pub fn on_click(&mut self, f: Handle<impl Slot<MouseEvent>>) -> &mut Self { | ||
self | ||
} | ||
|
||
pub fn child(&mut self, view: impl ViewGroup) -> &mut Self { | ||
self | ||
} | ||
|
||
pub fn build(&mut self) -> Element { | ||
todo!() | ||
} | ||
} | ||
|
||
pub struct Element { | ||
pub element: web_sys::Element, | ||
parent: Option<web_sys::Element>, | ||
} | ||
|
||
impl Element { | ||
pub fn new(tag: &str) -> Self { | ||
Self { | ||
element: web_sys::window() | ||
.unwrap() | ||
.document() | ||
.unwrap() | ||
.create_element(tag) | ||
.unwrap(), | ||
parent: None, | ||
} | ||
} | ||
|
||
pub fn builder() -> ElementBuilder { | ||
ElementBuilder { } | ||
} | ||
} | ||
|
||
impl Object for Element {} | ||
|
||
impl View for Element { | ||
fn node(&self) -> &web_sys::Node { | ||
self.element.unchecked_ref() | ||
} | ||
|
||
fn set_parent(&mut self, parent: web_sys::Element) { | ||
self.parent = Some(parent.clone()); | ||
parent.append_child(&self.element).unwrap(); | ||
} | ||
} | ||
|
||
pub struct AppendChild<V>(pub Handle<V>); | ||
|
||
impl<V: View + 'static> Slot<AppendChild<V>> for Element { | ||
fn handle(&mut self, handle: concoct::Context<Self>, msg: AppendChild<V>) { | ||
self.element.append_child(msg.0.borrow().node()).unwrap(); | ||
} | ||
} | ||
|
||
pub struct Text { | ||
pub node: web_sys::Text, | ||
parent: Option<web_sys::Element>, | ||
} | ||
|
||
impl Text { | ||
pub fn new(content: &str) -> Self { | ||
Self { | ||
node: web_sys::window() | ||
.unwrap() | ||
.document() | ||
.unwrap() | ||
.create_text_node(content), | ||
parent: None, | ||
} | ||
} | ||
} | ||
|
||
impl View for Text { | ||
fn node(&self) -> &web_sys::Node { | ||
&self.node | ||
} | ||
|
||
fn set_parent(&mut self, parent: web_sys::Element) { | ||
self.parent = Some(parent.clone()); | ||
parent.append_child(&self.node).unwrap(); | ||
} | ||
} | ||
|
||
impl Object for Text {} | ||
|
||
impl Slot<String> for Text { | ||
fn handle(&mut self, handle: concoct::Context<Self>, msg: String) { | ||
|
||
} | ||
} |
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,10 @@ | ||
[package] | ||
name = "web-examples" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
viewbuilder = { path = "../", features = ["full"] } | ||
concoct = { git = "https://github.com/concoct-rs/concoct" } |
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,75 @@ | ||
use concoct::{Handle, Object, Slot}; | ||
use viewbuilder::web::{self, Element, Text}; | ||
|
||
#[derive(Clone, Copy)] | ||
enum Message { | ||
Increment, | ||
Decrement, | ||
} | ||
|
||
struct Counter { | ||
value: i32, | ||
text: Handle<Text>, | ||
} | ||
|
||
impl Object for Counter {} | ||
|
||
impl Slot<Message> for Counter { | ||
fn handle(&mut self, _cx: concoct::Context<Self>, msg: Message) { | ||
match msg { | ||
Message::Increment => self.value += 1, | ||
Message::Decrement => self.value -= 1, | ||
}; | ||
self.text.send(self.value.to_string()); | ||
} | ||
} | ||
|
||
struct CounterButton { | ||
msg: Message, | ||
counter: Handle<Counter>, | ||
} | ||
|
||
impl Object for CounterButton {} | ||
|
||
impl Slot<web::MouseEvent> for CounterButton { | ||
fn handle(&mut self, _cx: concoct::Context<Self>, _msg: web::MouseEvent) { | ||
self.counter.send(self.msg); | ||
} | ||
} | ||
|
||
#[viewbuilder::main] | ||
fn main() { | ||
let text = Text::new("0").spawn(); | ||
|
||
let counter = Counter { | ||
value: 0, | ||
text: text.clone(), | ||
} | ||
.spawn(); | ||
|
||
let increment_button = CounterButton { | ||
msg: Message::Increment, | ||
counter: counter.clone(), | ||
} | ||
.spawn(); | ||
let decrement_button = CounterButton { | ||
msg: Message::Decrement, | ||
counter, | ||
} | ||
.spawn(); | ||
|
||
Element::builder() | ||
.child(( | ||
text, | ||
Element::builder() | ||
.on_click(increment_button) | ||
.child(Text::new("Up High!")) | ||
.build(), | ||
Element::builder() | ||
.on_click(decrement_button) | ||
.child(Text::new("Down Low!")) | ||
.build(), | ||
)) | ||
.build() | ||
.spawn(); | ||
} |