rust-dominator/src/traits.rs

181 lines
5.6 KiB
Rust
Raw Normal View History

2018-03-08 17:07:17 -05:00
use stdweb::{Reference, JsSerialize};
2018-02-25 06:58:20 -05:00
use stdweb::web::TextNode;
use stdweb::traits::{IElement, IHtmlElement, INode};
use stdweb::unstable::TryInto;
use dom::{Dom, IStyle, Dynamic};
use callbacks::Callbacks;
use futures_signals::signal::Signal;
use futures_signals::signal_vec::SignalVec;
2018-02-25 06:58:20 -05:00
use operations;
pub trait IntoDynamic where Self: Sized {
fn dynamic(self) -> Dynamic<Self>;
}
impl<A> IntoDynamic for A {
#[inline]
fn dynamic(self) -> Dynamic<Self> {
Dynamic(self)
}
}
2018-03-15 06:54:18 -04:00
pub use animation::AnimatedSignalVec;
2018-03-12 20:09:44 -04:00
// TODO if I change these traits to inherit from Signal, and I implement Signal for &str / bool, then I might be able to avoid using Dynamic
2018-02-25 06:58:20 -05:00
pub trait Text {
fn into_dom(self) -> Dom;
}
pub trait Property {
fn set_property<A: AsRef<Reference> + Clone + 'static>(self, element: &A, callbacks: &mut Callbacks, name: &str);
}
pub trait Attribute {
fn set_attribute<A: IElement + Clone + 'static>(self, element: &A, callbacks: &mut Callbacks, name: &str, namespace: Option<&str>);
}
pub trait Style {
fn set_style<A: IStyle + Clone + 'static>(self, element: &A, callbacks: &mut Callbacks, name: &str, important: bool);
}
pub trait Class {
fn toggle_class<A: IElement + Clone + 'static>(self, element: &A, callbacks: &mut Callbacks, name: &str);
}
pub trait Focused {
fn toggle_focused<A: IHtmlElement + Clone + 'static>(self, element: &A, callbacks: &mut Callbacks);
}
pub trait Children {
fn insert_children<A: INode + Clone + 'static>(self, element: &A, callbacks: &mut Callbacks);
}
impl<'a> Text for &'a str {
#[inline]
fn into_dom(self) -> Dom {
Dom::new(js!( return document.createTextNode(@{self}); ).try_into().unwrap())
}
}
impl<'a> Text for String {
#[inline]
fn into_dom(self) -> Dom {
self.as_str().into_dom()
}
}
2018-03-08 17:07:17 -05:00
impl<'a, A: JsSerialize> Property for A {
2018-02-25 06:58:20 -05:00
#[inline]
2018-03-08 17:07:17 -05:00
fn set_property<B: AsRef<Reference>>(self, element: &B, _callbacks: &mut Callbacks, name: &str) {
operations::set_property_str(element, name, &self)
2018-02-25 06:58:20 -05:00
}
}
impl<'a> Attribute for &'a str {
#[inline]
fn set_attribute<A: IElement>(self, element: &A, _callbacks: &mut Callbacks, name: &str, namespace: Option<&str>) {
operations::set_attribute_str(element, name, self, namespace)
}
}
impl<'a> Style for &'a str {
#[inline]
fn set_style<A: IStyle>(self, element: &A, _callbacks: &mut Callbacks, name: &str, important: bool) {
operations::set_style_str(element, name, self, important)
}
}
impl Class for bool {
#[inline]
fn toggle_class<A: IElement>(self, element: &A, _callbacks: &mut Callbacks, name: &str) {
operations::toggle_class_bool(element, name, self)
}
}
impl Focused for bool {
#[inline]
fn toggle_focused<A: IHtmlElement + Clone + 'static>(self, element: &A, callbacks: &mut Callbacks) {
operations::set_focused_bool(element, callbacks, self)
}
}
// TODO figure out how to make this owned rather than &mut
2018-02-26 03:01:04 -05:00
impl<'a, A: IntoIterator<Item = &'a mut Dom>> Children for A {
2018-02-25 06:58:20 -05:00
#[inline]
2018-02-26 03:01:04 -05:00
fn insert_children<B: INode>(self, element: &B, callbacks: &mut Callbacks) {
operations::insert_children_iter(element, callbacks, self)
2018-02-25 06:58:20 -05:00
}
}
impl<A: Signal<Item = String> + 'static> Text for Dynamic<A> {
// TODO should this inline ?
fn into_dom(self) -> Dom {
let element: TextNode = js!( return document.createTextNode(""); ).try_into().unwrap();
let mut callbacks = Callbacks::new();
operations::set_text_signal(&element, &mut callbacks, self.0);
Dom {
element: element.into(),
callbacks: callbacks,
}
}
}
2018-03-08 17:07:17 -05:00
impl<A: Signal<Item = B> + 'static, B: JsSerialize> Property for Dynamic<A> {
2018-02-25 06:58:20 -05:00
#[inline]
2018-03-08 17:07:17 -05:00
fn set_property<C: AsRef<Reference> + Clone + 'static>(self, element: &C, callbacks: &mut Callbacks, name: &str) {
2018-02-25 06:58:20 -05:00
operations::set_property_signal(element, callbacks, name, self.0)
}
}
impl<A: Signal<Item = Option<String>> + 'static> Attribute for Dynamic<A> {
#[inline]
fn set_attribute<B: IElement + Clone + 'static>(self, element: &B, callbacks: &mut Callbacks, name: &str, namespace: Option<&str>) {
operations::set_attribute_signal(element, callbacks, name, self.0, namespace)
}
}
impl<A: Signal<Item = Option<String>> + 'static> Style for Dynamic<A> {
#[inline]
fn set_style<B: IStyle + Clone + 'static>(self, element: &B, callbacks: &mut Callbacks, name: &str, important: bool) {
operations::set_style_signal(element, callbacks, name, self.0, important)
}
}
impl<A: Signal<Item = bool> + 'static> Class for Dynamic<A> {
#[inline]
fn toggle_class<B: IElement + Clone + 'static>(self, element: &B, callbacks: &mut Callbacks, name: &str) {
operations::toggle_class_signal(element, callbacks, name, self.0)
}
}
impl<A: Signal<Item = bool> + 'static> Focused for Dynamic<A> {
#[inline]
fn toggle_focused<B: IHtmlElement + Clone + 'static>(self, element: &B, callbacks: &mut Callbacks) {
operations::set_focused_signal(element, callbacks, self.0)
}
}
/*impl<A, B> Children for Dynamic<B>
2018-02-25 06:58:20 -05:00
where A: IntoIterator<Item = Dom>,
B: Signal<Item = A> + 'static {
#[inline]
fn insert_children<C: INode + Clone + 'static>(self, element: &C, callbacks: &mut Callbacks) {
operations::insert_children_signal(element, callbacks, self.0)
}
}*/
impl<A> Children for Dynamic<A> where A: SignalVec<Item = Dom> + 'static {
#[inline]
fn insert_children<C: INode + Clone + 'static>(self, element: &C, callbacks: &mut Callbacks) {
operations::insert_children_signal_vec(element, callbacks, self.0)
}
2018-02-25 06:58:20 -05:00
}