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 dom::node::{Node, NodeTree};
use newcss::select::{SelectCtx, SelectResults};
use newcss::complete::CompleteSelectResults;
use layout::context::LayoutContext;
use select_handler::NodeSelectHandler;
@ -20,20 +21,48 @@ impl Node : MatchMethods {
* computed style.
*/
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
if self.is_element() {
let select_handler = NodeSelectHandler {
node: self
};
let style = select_ctx.select_style(&self, &select_handler);
self.set_css_select_results(move style);
let incomplete_results = select_ctx.select_style(&self, &select_handler);
// 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 newcss::color::{Color, rgba};
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;
use newcss::complete::CompleteStyle;
/// Node mixin providing `style` method that returns a `NodeStyle`
trait StyledNode {
fn style(&self) -> NodeStyle/&self;
fn style(&self) -> CompleteStyle/&self;
}
impl Node: StyledNode {
fn style(&self) -> NodeStyle/&self {
fn style(&self) -> CompleteStyle/&self {
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 newcss::select::SelectResults;
use newcss::complete::CompleteSelectResults;
use std::cell::Cell;
trait NodeUtil {
fn get_css_select_results() -> &self/SelectResults;
fn set_css_select_results(decl : SelectResults);
fn get_css_select_results() -> &self/CompleteSelectResults;
fn set_css_select_results(decl : CompleteSelectResults);
}
impl Node: NodeUtil {
@ -15,7 +15,7 @@ impl Node: NodeUtil {
* FIXME: This isn't completely memory safe since the style is
* 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() {
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.
*/
fn set_css_select_results(decl : SelectResults) {
fn set_css_select_results(decl : CompleteSelectResults) {
let decl = Cell(move decl);
do self.aux |data| {
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. */
use newcss::select::SelectResults;
use newcss::complete::CompleteSelectResults;
use dom::bindings;
use dom::document::Document;
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. */
enum LayoutData = {
mut style: Option<SelectResults>,
mut style: Option<CompleteSelectResults>,
mut flow: Option<@FlowContext>
};

View file

@ -8,7 +8,8 @@ use au::Au;
use core::dvec::DVec;
use core::to_str::ToStr;
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::values::{CSSDisplay, Specified, CSSBackgroundColorColor, CSSBackgroundColorTransparent};
use newcss::values::{CSSBorderColor, CSSPositionAbsolute};
@ -364,7 +365,7 @@ impl RenderBox : RenderBoxMethods {
self.content_box()
}
fn style(&self) -> NodeStyle/&self {
fn style(&self) -> CompleteStyle/&self {
let d: &self/RenderBoxData = self.d();
d.node.style()
}