forked from yewstack/yew
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
211: Hide Scope behind App r=DenisKolodin a=DenisKolodin This PR adds a `Pool` which helps to collect `Callback`s and emit events from a single entity. That is useful for a context implementation. Co-authored-by: Denis Kolodin <[email protected]>
- Loading branch information
Showing
20 changed files
with
206 additions
and
131 deletions.
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
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
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
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
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,71 @@ | ||
//! This module contains `App` sctruct which used to bootstrap | ||
//! a component in an isolated scope. | ||
use std::rc::Rc; | ||
use std::cell::RefCell; | ||
use stdweb::web::{document, Element, INode, IParentNode}; | ||
use html::{Scope, ScopeBuilder, ScopeEnv, Component, Renderable, SharedContext}; | ||
|
||
/// An application instance. | ||
pub struct App<CTX, COMP: Component<CTX>> { | ||
/// `Scope` holder | ||
scope: Option<Scope<CTX, COMP>>, | ||
/// Environment of the created scope | ||
env: ScopeEnv<CTX, COMP>, | ||
} | ||
|
||
impl<CTX, COMP> App<CTX, COMP> | ||
where | ||
CTX: 'static, | ||
COMP: Component<CTX> + Renderable<CTX, COMP>, | ||
{ | ||
/// Creates a new `App` with a component in a context. | ||
pub fn new(context: CTX) -> Self { | ||
let context = Rc::new(RefCell::new(context)); | ||
App::reuse(context) | ||
} | ||
|
||
/// Creates isolated `App` instance, but reuse the context. | ||
pub fn reuse(context: SharedContext<CTX>) -> Self { | ||
let builder = ScopeBuilder::new(); | ||
let scope = builder.build(context); | ||
let env = scope.get_env(); | ||
App { | ||
scope: Some(scope), | ||
env, | ||
} | ||
} | ||
|
||
/// Alias to `mount("body", ...)`. | ||
pub fn mount_to_body(self) { | ||
let element = document() | ||
.query_selector("body") | ||
.expect("can't get body node for rendering") | ||
.expect("can't unwrap body node"); | ||
self.mount(element) | ||
} | ||
|
||
/// The main entrypoint of a yew program. It works similar as `program` | ||
/// function in Elm. You should provide an initial model, `update` function | ||
/// which will update the state of the model and a `view` function which | ||
/// will render the model to a virtual DOM tree. | ||
pub fn mount(mut self, element: Element) { | ||
clear_element(&element); | ||
self.scope.take() | ||
.expect("can't mount the same app twice") | ||
.mount_in_place(element, None, None, None) | ||
} | ||
|
||
/// Returns an environment. | ||
pub fn get_env(&self) -> ScopeEnv<CTX, COMP> { | ||
self.env.clone() | ||
} | ||
} | ||
|
||
/// Removes anything from the given element. | ||
fn clear_element(element: &Element) { | ||
while let Some(child) = element.last_child() { | ||
element.remove_child(&child).expect("can't remove a child"); | ||
} | ||
} | ||
|
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,53 @@ | ||
//! This module contains structs to interact with `Scope`s. | ||
use std::rc::Rc; | ||
|
||
/// Universal callback wrapper. | ||
/// <aside class="warning"> | ||
/// Use callbacks carefully, because it you call it from `update` loop | ||
/// of `Components` (even from JS) it will delay a message until next. | ||
/// Callbacks should be used from JS callbacks or `setTimeout` calls. | ||
/// </aside> | ||
/// `Rc` wrapper used to make it clonable. | ||
#[must_use] | ||
pub struct Callback<IN>(Rc<Fn(IN)>); | ||
|
||
impl<IN, F: Fn(IN) + 'static> From<F> for Callback<IN> { | ||
fn from(func: F) -> Self { | ||
Callback(Rc::new(func)) | ||
} | ||
} | ||
|
||
impl<IN> Clone for Callback<IN> { | ||
fn clone(&self) -> Self { | ||
Callback(self.0.clone()) | ||
} | ||
} | ||
|
||
impl<IN> PartialEq for Callback<IN> { | ||
fn eq(&self, other: &Callback<IN>) -> bool { | ||
Rc::ptr_eq(&self.0, &other.0) | ||
} | ||
} | ||
|
||
impl<IN> Callback<IN> { | ||
/// This method calls the actual callback. | ||
pub fn emit(&self, value: IN) { | ||
(self.0)(value); | ||
} | ||
} | ||
|
||
impl<IN: 'static> Callback<IN> { | ||
/// Changes input type of the callback to another. | ||
/// Works like common `map` method but in an opposite direction. | ||
pub fn reform<F, T>(self, func: F) -> Callback<T> | ||
where | ||
F: Fn(T) -> IN + 'static, | ||
{ | ||
let func = move |input| { | ||
let output = func(input); | ||
self.clone().emit(output); | ||
}; | ||
Callback::from(func) | ||
} | ||
} |
Oops, something went wrong.