Inherit CSS styles

This commit is contained in:
Brian Anderson 2012-11-06 15:11:50 -08:00
parent cd9e0c020b
commit 25ad384974
8 changed files with 55 additions and 162 deletions

@ -1 +1 @@
Subproject commit fa72e6b29671d70bd866052e55c930249cd2a3f9 Subproject commit 1b5d29808c55b375252668a90ab5255598f0e06d

@ -1 +1 @@
Subproject commit d13bc5f0bcd00c70d83f5902f4dd3e52ba54be7d Subproject commit d5734c425ae0dacb37f116ec3b0b8243d600987a

@ -1 +1 @@
Subproject commit 7d3776335dbd66688d25a7dbe0da5638e9e6702e Subproject commit 6d5b25957f5f6493b3acc6ed326354ad81c91cd1

View file

@ -4,6 +4,7 @@
use std::arc::{ARC, get, clone}; use std::arc::{ARC, get, clone};
use dom::node::{Node, NodeTree}; use dom::node::{Node, NodeTree};
use newcss::select::{SelectCtx, SelectResults}; use newcss::select::{SelectCtx, SelectResults};
use newcss::complete::CompleteSelectResults;
use layout::context::LayoutContext; use layout::context::LayoutContext;
use select_handler::NodeSelectHandler; use select_handler::NodeSelectHandler;
@ -20,20 +21,48 @@ impl Node : MatchMethods {
* computed style. * computed style.
*/ */
fn restyle_subtree(select_ctx: &SelectCtx) { fn restyle_subtree(select_ctx: &SelectCtx) {
let mut i = 0u;
for NodeTree.each_child(&self) |kid| {
i = i + 1u;
kid.restyle_subtree(select_ctx);
}
// Only elements have styles // Only elements have styles
if self.is_element() { if self.is_element() {
let select_handler = NodeSelectHandler { let select_handler = NodeSelectHandler {
node: self node: self
}; };
let style = select_ctx.select_style(&self, &select_handler); let incomplete_results = select_ctx.select_style(&self, &select_handler);
self.set_css_select_results(move style); // Combine this node's results with its parent's to resolve all inherited values
let complete_results = compose_results(&self, move incomplete_results);
self.set_css_select_results(move complete_results);
}
let mut i = 0u;
for NodeTree.each_child(&self) |kid| {
i = i + 1u;
kid.restyle_subtree(select_ctx);
} }
} }
} }
fn compose_results(node: &Node, results: SelectResults) -> CompleteSelectResults {
match find_parent_element_node(node) {
None => CompleteSelectResults::new_root(move results),
Some(parent_node) => {
let parent_results = parent_node.get_css_select_results();
CompleteSelectResults::new_from_parent(parent_results, move results)
}
}
}
fn find_parent_element_node(node: &Node) -> Option<Node> {
use util::tree::parent;
match parent(&NodeTree, node) {
Some(ref parent) => {
if parent.is_element() {
Some(*parent)
} else {
find_parent_element_node(parent)
}
}
None => None
}
}

View file

@ -1,152 +1,15 @@
/*!
Calculates computed Node styles, based on CSS SelectResults.
These methods mostly defer to the Node's ComputedStyle object.
The only exception is that this is where inheritance is resolved.
*/
use dom::node::Node; use dom::node::Node;
use newcss::color::{Color, rgba}; use newcss::complete::CompleteStyle;
use newcss::units::{Length, Px};
use newcss::values::{CSSValue, Specified, Inherit};
use newcss::values::{CSSMargin, CSSMarginLength};
use newcss::values::{CSSBorderWidth, CSSBorderWidthLength};
use newcss::values::{CSSDisplay, CSSDisplayBlock};
use newcss::values::{CSSPosition, CSSPositionRelative};
use newcss::values::{CSSFloat, CSSFloatNone};
use newcss::values::{CSSWidth, CSSWidthLength};
use newcss::values::{CSSHeight, CSSHeightLength};
use newcss::computed::ComputedStyle;
/// Node mixin providing `style` method that returns a `NodeStyle` /// Node mixin providing `style` method that returns a `NodeStyle`
trait StyledNode { trait StyledNode {
fn style(&self) -> NodeStyle/&self; fn style(&self) -> CompleteStyle/&self;
} }
impl Node: StyledNode { impl Node: StyledNode {
fn style(&self) -> NodeStyle/&self { fn style(&self) -> CompleteStyle/&self {
assert self.is_element(); // Only elements can have styles assert self.is_element(); // Only elements can have styles
NodeStyle::new(self) let results = self.get_css_select_results();
} results.computed_style()
}
/// Provides getters for calculated node styles
pub struct NodeStyle {
priv node: &Node
}
impl NodeStyle {
static fn new(node: &r/Node) -> NodeStyle/&r {
NodeStyle {
node: node
}
}
// CSS 2.1, Section 8 - Box model
fn margin_top(&self) -> CSSMargin {
resolve(self, CSSMarginLength(Px(0.0)), |cs| cs.margin_top() )
}
fn margin_right(&self) -> CSSMargin {
resolve(self, CSSMarginLength(Px(0.0)), |cs| cs.margin_right() )
}
fn margin_bottom(&self) -> CSSMargin {
resolve(self, CSSMarginLength(Px(0.0)), |cs| cs.margin_bottom() )
}
fn margin_left(&self) -> CSSMargin {
resolve(self, CSSMarginLength(Px(0.0)), |cs| cs.margin_left() )
}
fn border_top_width(&self) -> CSSBorderWidth {
resolve(self, CSSBorderWidthLength(Px(0.0)), |cs| cs.border_top_width() )
}
fn border_right_width(&self) -> CSSBorderWidth {
resolve(self, CSSBorderWidthLength(Px(0.0)), |cs| cs.border_right_width() )
}
fn border_bottom_width(&self) -> CSSBorderWidth {
resolve(self, CSSBorderWidthLength(Px(0.0)), |cs| cs.border_bottom_width() )
}
fn border_left_width(&self) -> CSSBorderWidth {
resolve(self, CSSBorderWidthLength(Px(0.0)), |cs| cs.border_left_width() )
}
fn border_top_color(&self) -> Color {
resolve(self, rgba(255, 255, 255, 0.0), |cs| cs.border_top_color() )
}
fn border_right_color(&self) -> Color {
resolve(self, rgba(255, 255, 255, 0.0), |cs| cs.border_right_color() )
}
fn border_bottom_color(&self) -> Color {
resolve(self, rgba(255, 255, 255, 0.0), |cs| cs.border_bottom_color() )
}
fn border_left_color(&self) -> Color {
resolve(self, rgba(255, 255, 255, 0.0), |cs| cs.border_left_color() )
}
// CSS 2.1, Section 9 - Visual formatting model
fn display(&self) -> CSSDisplay {
// FIXME: Shouldn't be passing false here
resolve(self, CSSDisplayBlock, |cs| cs.display(false) )
}
fn position(&self) -> CSSPosition {
resolve(self, CSSPositionRelative, |cs| cs.position() )
}
fn float(&self) -> CSSFloat {
resolve(self, CSSFloatNone, |cs| cs.float() )
}
// CSS 2.1, Section 10 - Visual formatting model details
fn width(&self) -> CSSWidth {
resolve(self, CSSWidthLength(Px(0.0)), |cs| cs.width() )
}
fn height(&self) -> CSSHeight {
resolve(self, CSSHeightLength(Px(0.0)), |cs| cs.height() )
}
// CSS 2.1, Section 11 - Visual effects
// CSS 2.1, Section 12 - Generated content, automatic numbering, and lists
// CSS 2.1, Section 13 - Paged media
// CSS 2.1, Section 14 - Colors and Backgrounds
fn background_color(&self) -> Color {
resolve(self, rgba(0, 0, 0, 0.0), |cs| cs.background_color() )
}
// CSS 2.1, Section 15 - Fonts
// CSS 2.1, Section 16 - Text
// CSS 2.1, Section 17 - Tables
// CSS 2.1, Section 18 - User interface
}
fn resolve<T>(node_style: &NodeStyle, default: T, get: &fn(cs: ComputedStyle) -> CSSValue<T>) -> T {
let node = node_style.node;
let select_res = node.get_css_select_results();
let computed = select_res.computed_style();
let value = get(computed);
match move value {
Inherit => /* FIXME: need inheritance */ move default,
Specified(move value) => move value,
} }
} }

View file

@ -1,10 +1,10 @@
use dom::node::Node; use dom::node::Node;
use newcss::select::SelectResults; use newcss::complete::CompleteSelectResults;
use std::cell::Cell; use std::cell::Cell;
trait NodeUtil { trait NodeUtil {
fn get_css_select_results() -> &self/SelectResults; fn get_css_select_results() -> &self/CompleteSelectResults;
fn set_css_select_results(decl : SelectResults); fn set_css_select_results(decl : CompleteSelectResults);
} }
impl Node: NodeUtil { impl Node: NodeUtil {
@ -15,7 +15,7 @@ impl Node: NodeUtil {
* FIXME: This isn't completely memory safe since the style is * FIXME: This isn't completely memory safe since the style is
* stored in a box that can be overwritten * stored in a box that can be overwritten
*/ */
fn get_css_select_results() -> &self/SelectResults { fn get_css_select_results() -> &self/CompleteSelectResults {
if !self.has_aux() { if !self.has_aux() {
fail ~"style() called on a node without aux data!"; fail ~"style() called on a node without aux data!";
} }
@ -30,7 +30,7 @@ impl Node: NodeUtil {
/** /**
Update the computed style of an HTML element with a style specified by CSS. Update the computed style of an HTML element with a style specified by CSS.
*/ */
fn set_css_select_results(decl : SelectResults) { fn set_css_select_results(decl : CompleteSelectResults) {
let decl = Cell(move decl); let decl = Cell(move decl);
do self.aux |data| { do self.aux |data| {
data.style = Some(decl.take()) data.style = Some(decl.take())

View file

@ -1,5 +1,5 @@
/* The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. */ /* The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. */
use newcss::select::SelectResults; use newcss::complete::CompleteSelectResults;
use dom::bindings; use dom::bindings;
use dom::document::Document; use dom::document::Document;
use dom::element::{Attr, ElementData}; use dom::element::{Attr, ElementData};
@ -118,7 +118,7 @@ fn define_bindings(compartment: &bare_compartment, doc: @Document,
Note that there may be multiple boxes per DOM node. */ Note that there may be multiple boxes per DOM node. */
enum LayoutData = { enum LayoutData = {
mut style: Option<SelectResults>, mut style: Option<CompleteSelectResults>,
mut flow: Option<@FlowContext> mut flow: Option<@FlowContext>
}; };

View file

@ -8,7 +8,8 @@ use au::Au;
use core::dvec::DVec; use core::dvec::DVec;
use core::to_str::ToStr; use core::to_str::ToStr;
use core::rand; use core::rand;
use css::node_style::{NodeStyle, StyledNode}; use css::node_style::StyledNode;
use newcss::complete::CompleteStyle;
use newcss::units::{BoxSizing, Length, Px}; use newcss::units::{BoxSizing, Length, Px};
use newcss::values::{CSSDisplay, Specified, CSSBackgroundColorColor, CSSBackgroundColorTransparent}; use newcss::values::{CSSDisplay, Specified, CSSBackgroundColorColor, CSSBackgroundColorTransparent};
use newcss::values::{CSSBorderColor, CSSPositionAbsolute}; use newcss::values::{CSSBorderColor, CSSPositionAbsolute};
@ -364,7 +365,7 @@ impl RenderBox : RenderBoxMethods {
self.content_box() self.content_box()
} }
fn style(&self) -> NodeStyle/&self { fn style(&self) -> CompleteStyle/&self {
let d: &self/RenderBoxData = self.d(); let d: &self/RenderBoxData = self.d();
d.node.style() d.node.style()
} }