1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
use velement::VElement; use vlist::VList; use vtext::VText; use std::fmt::Display; use std::fmt::{Formatter, self}; use vcomponent::VComponent; #[cfg(not(target_arch = "wasm32"))] use traits::ServerRender; #[derive(Debug, Eq, PartialEq)] pub enum VNode { Text(VText), Element(VElement), List(VList), Component(VComponent) } impl VNode { pub fn new<T: Into<VNode>>(content: T) -> VNode { content.into() } } impl Display for VNode { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match *self { VNode::Text(ref text) => write!(f, "{}", text), VNode::Element(ref element) => write!(f, "{}", element), VNode::List(ref list) => write!(f, "{}", list), VNode::Component(ref component) => write!(f, "{}", component) } } } macro_rules! impl_conversion_to_vnode { ($variant:ident, $inner:ty) => { impl From<$inner> for VNode { fn from(item: $inner) -> Self { VNode::$variant(item) } } }; } impl_conversion_to_vnode!(Text, VText); impl_conversion_to_vnode!(Element, VElement); impl_conversion_to_vnode!(List, VList); impl_conversion_to_vnode!(Component, VComponent); #[cfg(not(target_arch = "wasm32"))] impl ServerRender for VNode { fn server_render(&mut self) { match *self { VNode::Component(ref mut component) => component.server_render(), VNode::List(ref mut list) => list.server_render(), VNode::Element(ref mut element) => element.server_render(), VNode::Text(_) => {} } } } #[cfg(target_arch = "wasm32")] mod wasm { use vdiff::{DOMPatch, DOMRemove}; use stdweb::web::Element; use super::VNode; use vdiff::DOMReorder; use vdiff::DOMNode; use stdweb::web::Node; use traits::DOMRender; use events::RenderRequestSender; macro_rules! match_for_vnode_patch { ($against:ident, $parent:ident, $next:ident, $old_vnode:ident, $render_req:ident, [$( $variant:ident ),*] ) => { match $against { $( VNode::$variant(node_like) => { if let Some(VNode::$variant(old_node_like)) = $old_vnode { node_like.patch($parent, $next, Some(old_node_like), $render_req).into() } else { $old_vnode.remove($parent); node_like.patch($parent, $next, None, $render_req).into() } } )* } }; } impl DOMPatch<VNode> for VNode { fn patch(self, parent: &Element, next: Option<&Node>, old_vnode: Option<VNode>, render_req: RenderRequestSender) -> Self { match_for_vnode_patch!(self, parent, next, old_vnode, render_req, [Text, Element, List, Component]) } } impl DOMRemove for VNode { fn remove(self, parent: &Element) { match self { VNode::Text(text) => text.remove(parent), VNode::Element(element) => element.remove(parent), VNode::List(list) => list.remove(parent), VNode::Component(component) => component.remove(parent) } } } impl DOMReorder for VNode { fn move_to_last(&self, parent: &Element) { match *self { VNode::Text(ref text) => text.move_to_last(parent), VNode::Element(ref element) => element.move_to_last(parent), VNode::List(ref list) => list.move_to_last(parent), VNode::Component(ref component) => component.move_to_last(parent) } } fn move_before(&self, parent: &Element, next: &Node) { match *self { VNode::Text(ref text) => text.move_before(parent, next), VNode::Element(ref element) => element.move_before(parent, next), VNode::List(ref list) => list.move_before(parent, next), VNode::Component(ref component) => component.move_before(parent, next) } } } impl DOMNode for VNode { fn dom_node(&self) -> Option<Node> { match *self { VNode::Text(ref text) => text.dom_node(), VNode::Element(ref element) => element.dom_node(), VNode::List(ref list) => list.dom_node(), VNode::Component(ref component) => component.dom_node() } } } impl DOMRender for VNode { fn dom_render(&mut self, parent: &Element, next: Option<&Node>, render_req: RenderRequestSender) { match *self { VNode::Component(ref mut component) => component.dom_render(parent, next, render_req), VNode::List(ref mut list) => list.dom_render(parent, next, render_req), VNode::Element(ref mut element) => element.dom_render(parent, next, render_req), VNode::Text(_) => {} } } } }