Capitalized css style types, removed redundant pretty-printing.

This commit is contained in:
Margaret Meyerhofer 2012-06-29 17:21:58 -07:00
parent e4edb86df9
commit 55d8fc332a
9 changed files with 122 additions and 235 deletions

View file

@ -13,8 +13,6 @@ import result::{ok, err};
import dom::base::NodeScope; import dom::base::NodeScope;
import dom::rcu::WriterMethods; import dom::rcu::WriterMethods;
import dom::style; import dom::style;
import style::print_sheet;
import parser::css_lexer::spawn_css_lexer_task;
import parser::html_lexer::spawn_html_lexer_task; import parser::html_lexer::spawn_html_lexer_task;
import parser::css_builder::build_stylesheet; import parser::css_builder::build_stylesheet;
import parser::html_builder::build_dom; import parser::html_builder::build_dom;
@ -72,7 +70,7 @@ fn Content(layout: Layout) -> Content {
let css_rules = style_port.recv(); let css_rules = style_port.recv();
// Apply the css rules to the dom tree: // Apply the css rules to the dom tree:
#debug["%s", print_sheet(css_rules)]; #debug["%?", css_rules];
// Now, join the layout so that they will see the latest // Now, join the layout so that they will see the latest
// changes we have made. // changes we have made.

View file

@ -1,143 +1,32 @@
import util::color::{Color, methods}; import util::color::Color;
import util::color::css_colors::black;
enum display_type{ enum DisplayType{
di_block, DisBlock,
di_inline, DisInline,
di_none DisNone
} }
enum style_decl{ enum StyleDeclaration{
font_size(uint), // Currently assumes format '# pt' FontSize(uint), // Currently assumes format '# pt'
display(display_type), Display(DisplayType),
text_color(Color), TextColor(Color),
background_color(Color) BackgroundColor(Color)
} }
enum attr{ enum Attr{
exists(str), Exists(str),
exact(str, str), Exact(str, str),
includes(str, str), Includes(str, str),
starts_with(str, str) StartsWith(str, str)
} }
enum selector{ enum Selector{
element(str, [attr]), Element(str, [Attr]),
child(~selector, ~selector), Child(~Selector, ~Selector),
descendant(~selector, ~selector), Descendant(~Selector, ~Selector),
sibling(~selector, ~selector) Sibling(~Selector, ~Selector)
} }
type rule = ([~selector], [style_decl]); type Rule = ([~Selector], [StyleDeclaration]);
type stylesheet = [~rule]; type Stylesheet = [~Rule];
fn print_list<T>(list : [T], print : fn(T) -> str) -> str {
let l = vec::len(list);
if l == 0u { ret "" }
let mut res = print(list[0]);
let mut i = 1u;
while i < l {
res += ", ";
res += print(list[i]);
i += 1u;
}
ret res;
}
fn print_list_vert<T>(list : [T], print : fn(T) -> str) -> str {
let l = vec::len(list);
if l == 0u { ret "" }
let mut res = "-";
res += print(list[0]);
let mut i = 1u;
while i < l {
res += "\n-";
res += print(list[i]);
i += 1u;
}
ret res;
}
fn print_display(dis_ty : display_type) -> str {
alt dis_ty {
di_block { "block" }
di_inline { "inline" }
di_none { "none" }
}
}
fn print_style(decl : style_decl) -> str{
alt decl {
font_size(s) { #fmt["Font size = %u pt", s] }
display(dis_ty) { #fmt["Display style = %s", print_display(dis_ty)] }
text_color(c) { #fmt["Text color = %s", c.print()] }
background_color(c) { #fmt["Background color = %s", c.print()] }
}
}
fn print_attr(attribute : attr) -> str {
alt attribute {
exists(att) { #fmt["[%s]", att] }
exact(att, val) { #fmt["[%s = %s]", att, val] }
includes(att, val) { #fmt["[%s ~= %s]", att, val] }
starts_with(att, val) { #fmt["[%s |= %s]", att, val] }
}
}
fn print_selector(&&select : ~selector) -> str {
alt *select {
element(s, attrs) { #fmt["Element %s with attributes: %s", s,
print_list(attrs, print_attr)] }
child(sel1, sel2) { #fmt["(%s) > (%s)", print_selector(sel1),
print_selector(sel2)] }
descendant(sel1, sel2) { #fmt["(%s) (%s)", print_selector(sel1),
print_selector(sel2)] }
sibling(sel1, sel2) { #fmt["(%s) + (%s)", print_selector(sel1),
print_selector(sel2)] }
}
}
fn print_rule(&&rule : ~rule) -> str {
alt *rule {
(sels, styles) {
let sel_str = print_list(sels, print_selector);
let sty_str = print_list(styles, print_style);
#fmt["Selectors: %s; Style: {%s}", sel_str, sty_str]
}
}
}
fn print_sheet(sheet : stylesheet) -> str {
#fmt["CSS Rules:\n%s", print_list_vert(sheet, print_rule)]
}
#[test]
fn test_pretty_print() {
let test1 = [~([~element("p", [])], [font_size(32u)])];
let actual1 = print_sheet(test1);
let expected1 = "CSS Rules:\n-Selectors: Element p with attributes: ;" +
" Style: {Font size = 32 pt}";
assert(actual1 == expected1);
let elmt1 = ~element("*", []);
let elmt2 = ~element("body", [exact("class", "2")]);
let test2 = [~([~descendant(elmt1, elmt2)],
[display(di_block), text_color(black())])];
let actual2 = print_sheet(test2);
let expected2 = "CSS Rules:\n-Selectors: (Element * with attributes: ) "
+ "(Element body with attributes: [class = 2]); " +
"Style: {Display style = block, Text color = rgba(0,0,0,1)}";
assert(actual2 == expected2);
}

View file

@ -1,7 +1,7 @@
#[doc="Creates CSS boxes from a DOM."] #[doc="Creates CSS boxes from a DOM."]
import dom::base::{ElementData, HTMLDivElement, HTMLImageElement, Element, Text, Node}; import dom::base::{ElementData, HTMLDivElement, HTMLImageElement, Element, Text, Node};
import dom::style::{display_type, di_block, di_inline, di_none}; import dom::style::{DisplayType, DisBlock, DisInline, DisNone};
import dom::rcu::ReaderMethods; import dom::rcu::ReaderMethods;
import gfx::geometry; import gfx::geometry;
import layout::base::{BlockBox, Box, BoxKind, BoxTreeReadMethods, BoxTreeWriteMethods, InlineBox}; import layout::base::{BlockBox, Box, BoxKind, BoxTreeReadMethods, BoxTreeWriteMethods, InlineBox};
@ -51,16 +51,16 @@ impl methods for ctxt {
// Determine the child's display. // Determine the child's display.
let disp = kid.get_computed_style().display; let disp = kid.get_computed_style().display;
if disp != di_inline { if disp != DisInline {
self.finish_anonymous_box_if_necessary(); self.finish_anonymous_box_if_necessary();
} }
// Add the child's box to the current enclosing box or the current anonymous box. // Add the child's box to the current enclosing box or the current anonymous box.
alt kid.get_computed_style().display { alt kid.get_computed_style().display {
di_block { DisBlock {
BTree.add_child(self.parent_box, kid_box); BTree.add_child(self.parent_box, kid_box);
} }
di_inline { DisInline {
let anon_box = alt self.anon_box { let anon_box = alt self.anon_box {
none { none {
// //
@ -79,7 +79,7 @@ impl methods for ctxt {
}; };
BTree.add_child(anon_box, kid_box); BTree.add_child(anon_box, kid_box);
} }
di_none { DisNone {
// Nothing to do. // Nothing to do.
} }
} }
@ -99,23 +99,23 @@ impl methods for ctxt {
// Determine the child's display. // Determine the child's display.
let disp = kid.get_computed_style().display; let disp = kid.get_computed_style().display;
if disp != di_inline { if disp != DisInline {
// TODO // TODO
} }
// Add the child's box to the current enclosing box. // Add the child's box to the current enclosing box.
alt kid.get_computed_style().display { alt kid.get_computed_style().display {
di_block { DisBlock {
// TODO // TODO
#warn("TODO: non-inline display found inside inline box"); #warn("TODO: non-inline display found inside inline box");
BTree.add_child(self.parent_box, kid_box); BTree.add_child(self.parent_box, kid_box);
} }
di_inline { DisInline {
BTree.add_child(self.parent_box, kid_box); BTree.add_child(self.parent_box, kid_box);
} }
di_none { DisNone {
// Nothing to do. // Nothing to do.
} }
} }
} }
} }
@ -126,9 +126,9 @@ impl methods for ctxt {
self.parent_node.dump(); self.parent_node.dump();
alt self.parent_node.get_computed_style().display { alt self.parent_node.get_computed_style().display {
di_block { self.construct_boxes_for_block_children(); } DisBlock { self.construct_boxes_for_block_children(); }
di_inline { self.construct_boxes_for_inline_children(); } DisInline { self.construct_boxes_for_inline_children(); }
di_none { /* Nothing to do. */ } DisNone { /* Nothing to do. */ }
} }
self.finish_anonymous_box_if_necessary(); self.finish_anonymous_box_if_necessary();

View file

@ -7,7 +7,7 @@ import arc::arc;
import display_list_builder::build_display_list; import display_list_builder::build_display_list;
import dom::base::{Node}; import dom::base::{Node};
import dom::style::stylesheet; import dom::style::Stylesheet;
import gfx::geometry::px_to_au; import gfx::geometry::px_to_au;
import gfx::renderer::Renderer; import gfx::renderer::Renderer;
import base::{NodeMethods, layout_methods}; import base::{NodeMethods, layout_methods};
@ -21,7 +21,7 @@ import comm::*;
type Layout = chan<Msg>; type Layout = chan<Msg>;
enum Msg { enum Msg {
BuildMsg(Node, stylesheet), BuildMsg(Node, Stylesheet),
PingMsg(chan<content::PingMsg>), PingMsg(chan<content::PingMsg>),
ExitMsg ExitMsg
} }

View file

@ -1,31 +1,32 @@
#[doc="Performs CSS selector matching."] #[doc="Performs CSS selector matching."]
import base::{LayoutData}; import base::{LayoutData};
import dom::base::{Element, ElementData, Node, Text}; import dom::base;
import dom::style::{selector, style_decl, font_size, display, text_color, background_color, import base::{ElementData, Node, Text};
stylesheet, element, child, descendant, sibling, attr, exact, exists, includes, import dom::style::{Selector, StyleDeclaration, FontSize, Display, TextColor, BackgroundColor,
starts_with}; Stylesheet, Element, Child, Descendant, Sibling, Attr, Exact, Exists, Includes,
StartsWith};
import dom::rcu::ReaderMethods; import dom::rcu::ReaderMethods;
import style::{computed_style, default_style_for_node_kind}; import style::{computed_style, default_style_for_node_kind};
export matching_methods; export matching_methods;
#[doc="Check if a CSS attribute matches the attribute of an HTML element."] #[doc="Check if a CSS attribute matches the attribute of an HTML element."]
fn attrs_match(attr: attr, elmt: ElementData) -> bool { fn attrs_match(attr: Attr, elmt: ElementData) -> bool {
alt attr { alt attr {
exists(name) { Exists(name) {
alt elmt.get_attr(name) { alt elmt.get_attr(name) {
some(_) { ret true; } some(_) { ret true; }
none { ret false; } none { ret false; }
} }
} }
exact(name, val) { Exact(name, val) {
alt elmt.get_attr(name) { alt elmt.get_attr(name) {
some(value) { ret value == val; } some(value) { ret value == val; }
none { ret false; } none { ret false; }
} }
} }
includes(name, val) { Includes(name, val) {
// Comply with css spec, if the specified attribute is empty // Comply with css spec, if the specified attribute is empty
// it cannot match. // it cannot match.
if val == "" { ret false; } if val == "" { ret false; }
@ -35,7 +36,7 @@ fn attrs_match(attr: attr, elmt: ElementData) -> bool {
none { ret false; } none { ret false; }
} }
} }
starts_with(name, val) { StartsWith(name, val) {
alt elmt.get_attr(name) { alt elmt.get_attr(name) {
some(value) { some(value) {
//check that there is only one attribute value and it //check that there is only one attribute value and it
@ -59,12 +60,12 @@ impl priv_matching_methods for Node {
Checks if the given CSS selector, which must describe a single element with no relational Checks if the given CSS selector, which must describe a single element with no relational
information, describes the given HTML element. information, describes the given HTML element.
"] "]
fn matches_element(sel: ~selector) -> bool { fn matches_element(sel: ~Selector) -> bool {
alt *sel { alt *sel {
child(_, _) | descendant(_, _) | sibling(_, _) { ret false; } Child(_, _) | Descendant(_, _) | Sibling(_, _) { ret false; }
element(tag, attrs) { Element(tag, attrs) {
alt self.read { |n| copy *n.kind } { alt self.read { |n| copy *n.kind } {
Element(elmt) { base::Element(elmt) {
if !(tag == "*" || tag == elmt.tag_name) { if !(tag == "*" || tag == elmt.tag_name) {
ret false; ret false;
} }
@ -87,10 +88,10 @@ impl priv_matching_methods for Node {
} }
#[doc = "Checks if a generic CSS selector matches a given HTML element"] #[doc = "Checks if a generic CSS selector matches a given HTML element"]
fn matches_selector(sel : ~selector) -> bool { fn matches_selector(sel : ~Selector) -> bool {
alt *sel { alt *sel {
element(str, atts) { ret self.matches_element(sel); } Element(str, atts) { ret self.matches_element(sel); }
child(sel1, sel2) { Child(sel1, sel2) {
alt self.read { |n| n.tree.parent } { alt self.read { |n| n.tree.parent } {
some(parent) { some(parent) {
ret self.matches_element(sel2) && ret self.matches_element(sel2) &&
@ -99,7 +100,7 @@ impl priv_matching_methods for Node {
none { ret false; } none { ret false; }
} }
} }
descendant(sel1, sel2) { Descendant(sel1, sel2) {
if !self.matches_element(sel2) { if !self.matches_element(sel2) {
ret false; ret false;
} }
@ -120,7 +121,7 @@ impl priv_matching_methods for Node {
}; };
} }
} }
sibling(sel1, sel2) { Sibling(sel1, sel2) {
if !self.matches_element(sel2) { ret false; } if !self.matches_element(sel2) { ret false; }
// Loop over this node's previous siblings to see if they match. // Loop over this node's previous siblings to see if they match.
@ -163,12 +164,12 @@ impl priv_matching_methods for Node {
impl priv_style_methods for Node { impl priv_style_methods for Node {
#[doc="Update the computed style of an HTML element with a style specified by CSS."] #[doc="Update the computed style of an HTML element with a style specified by CSS."]
fn update_style(decl : style_decl) { fn update_style(decl : StyleDeclaration) {
self.aux() { |layout| self.aux() { |layout|
alt decl { alt decl {
display(dis) { layout.computed_style.display = dis; } Display(dis) { layout.computed_style.display = dis; }
background_color(col) { layout.computed_style.back_color = col; } BackgroundColor(col) { layout.computed_style.back_color = col; }
text_color(*) | font_size(*) { /* not supported yet */ } TextColor(*) | FontSize(*) { /* not supported yet */ }
} }
} }
} }
@ -177,7 +178,7 @@ impl priv_style_methods for Node {
impl matching_methods for Node { impl matching_methods for Node {
#[doc="Compare an html element to a list of css rules and update its #[doc="Compare an html element to a list of css rules and update its
style according to the rules matching it."] style according to the rules matching it."]
fn match_css_style(styles : stylesheet) { fn match_css_style(styles : Stylesheet) {
// Loop over each rule, see if our node matches what is described in the rule. If it // Loop over each rule, see if our node matches what is described in the rule. If it
// matches, update its style. As we don't currently have priorities of style information, // matches, update its style. As we don't currently have priorities of style information,
// the latest rule takes precedence over the others. So we just overwrite style // the latest rule takes precedence over the others. So we just overwrite style
@ -200,7 +201,7 @@ impl matching_methods for Node {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
import dom::base::{Attr, Element, HTMLDivElement, HTMLHeadElement, HTMLImageElement}; import dom::base::{Attr, HTMLDivElement, HTMLHeadElement, HTMLImageElement};
import dom::base::{NodeScope, TreeReadMethods, TreeWriteMethods, UnknownElement}; import dom::base::{NodeScope, TreeReadMethods, TreeWriteMethods, UnknownElement};
import dvec::{dvec, extensions}; import dvec::{dvec, extensions};
import io::println; import io::println;
@ -210,7 +211,7 @@ mod test {
let elmt = ElementData("div", ~HTMLDivElement); let elmt = ElementData("div", ~HTMLDivElement);
let attr = ~Attr(name, val); let attr = ~Attr(name, val);
elmt.attrs.push(attr); elmt.attrs.push(attr);
ret scope.new_node(Element(elmt)); ret scope.new_node(base::Element(elmt));
} }
#[test] #[test]
@ -218,7 +219,7 @@ mod test {
let scope = NodeScope(); let scope = NodeScope();
let node = new_node_from_attr(scope, "lang", "en-us"); let node = new_node_from_attr(scope, "lang", "en-us");
let sel = element("*", [starts_with("lang", "en")]); let sel = Element("*", [StartsWith("lang", "en")]);
assert node.matches_selector(~sel); assert node.matches_selector(~sel);
} }
@ -228,7 +229,7 @@ mod test {
let scope = NodeScope(); let scope = NodeScope();
let node = new_node_from_attr(scope, "lang", "en"); let node = new_node_from_attr(scope, "lang", "en");
let sel = element("*", [starts_with("lang", "en")]); let sel = Element("*", [StartsWith("lang", "en")]);
assert node.matches_selector(~sel); assert node.matches_selector(~sel);
} }
@ -238,7 +239,7 @@ mod test {
let scope = NodeScope(); let scope = NodeScope();
let node = new_node_from_attr(scope, "lang", "english"); let node = new_node_from_attr(scope, "lang", "english");
let sel = element("*", [starts_with("lang", "en")]); let sel = Element("*", [StartsWith("lang", "en")]);
assert !node.matches_selector(~sel); assert !node.matches_selector(~sel);
} }
@ -248,7 +249,7 @@ mod test {
let scope = NodeScope(); let scope = NodeScope();
let node = new_node_from_attr(scope, "mad", "hatter cobler cooper"); let node = new_node_from_attr(scope, "mad", "hatter cobler cooper");
let sel = element("div", [includes("mad", "hatter")]); let sel = Element("div", [Includes("mad", "hatter")]);
assert node.matches_selector(~sel); assert node.matches_selector(~sel);
} }
@ -258,8 +259,8 @@ mod test {
let scope = NodeScope(); let scope = NodeScope();
let node = new_node_from_attr(scope, "mad", "hatter cobler cooper"); let node = new_node_from_attr(scope, "mad", "hatter cobler cooper");
let sel1 = element("div", [exists("mad")]); let sel1 = Element("div", [Exists("mad")]);
let sel2 = element("div", [exists("hatter")]); let sel2 = Element("div", [Exists("hatter")]);
assert node.matches_selector(~sel1); assert node.matches_selector(~sel1);
assert !node.matches_selector(~sel2); assert !node.matches_selector(~sel2);
@ -271,7 +272,7 @@ mod test {
let node1 = new_node_from_attr(scope, "mad", "hatter cobler cooper"); let node1 = new_node_from_attr(scope, "mad", "hatter cobler cooper");
let node2 = new_node_from_attr(scope, "mad", "hatter"); let node2 = new_node_from_attr(scope, "mad", "hatter");
let sel = element("div", [exact("mad", "hatter")]); let sel = Element("div", [Exact("mad", "hatter")]);
assert !node1.matches_selector(~copy sel); assert !node1.matches_selector(~copy sel);
assert node2.matches_selector(~sel); assert node2.matches_selector(~sel);
@ -294,8 +295,8 @@ mod test {
scope.add_child(gchild, ggchild); scope.add_child(gchild, ggchild);
scope.add_child(ggchild, gggchild); scope.add_child(ggchild, gggchild);
let sel1 = descendant(~element("*", [exact("class", "blue")]), let sel1 = Descendant(~Element("*", [Exact("class", "blue")]),
~element("*", [])); ~Element("*", []));
assert !root.matches_selector(~copy sel1); assert !root.matches_selector(~copy sel1);
assert child1.matches_selector(~copy sel1); assert child1.matches_selector(~copy sel1);
@ -304,9 +305,9 @@ mod test {
assert ggchild.matches_selector(~copy sel1); assert ggchild.matches_selector(~copy sel1);
assert gggchild.matches_selector(~sel1); assert gggchild.matches_selector(~sel1);
let sel2 = descendant(~child(~element("*", [exact("class", "blue")]), let sel2 = Descendant(~Child(~Element("*", [Exact("class", "blue")]),
~element("*", [])), ~Element("*", [])),
~element("div", [exists("flag")])); ~Element("div", [Exists("flag")]));
assert !root.matches_selector(~copy sel2); assert !root.matches_selector(~copy sel2);
assert !child1.matches_selector(~copy sel2); assert !child1.matches_selector(~copy sel2);
@ -315,7 +316,7 @@ mod test {
assert ggchild.matches_selector(~copy sel2); assert ggchild.matches_selector(~copy sel2);
assert gggchild.matches_selector(~sel2); assert gggchild.matches_selector(~sel2);
let sel3 = sibling(~element("*", []), ~element("*", [])); let sel3 = Sibling(~Element("*", []), ~Element("*", []));
assert !root.matches_selector(~copy sel3); assert !root.matches_selector(~copy sel3);
assert child1.matches_selector(~copy sel3); assert child1.matches_selector(~copy sel3);
@ -324,9 +325,9 @@ mod test {
assert !ggchild.matches_selector(~copy sel3); assert !ggchild.matches_selector(~copy sel3);
assert !gggchild.matches_selector(~sel3); assert !gggchild.matches_selector(~sel3);
let sel4 = descendant(~child(~element("*", [exists("class")]), let sel4 = Descendant(~Child(~Element("*", [Exists("class")]),
~element("*", [])), ~Element("*", [])),
~element("*", [])); ~Element("*", []));
assert !root.matches_selector(~copy sel4); assert !root.matches_selector(~copy sel4);
assert !child1.matches_selector(~copy sel4); assert !child1.matches_selector(~copy sel4);

View file

@ -2,7 +2,7 @@
import arc::{arc, get, clone}; import arc::{arc, get, clone};
import dom::style::{display_type, di_block, di_inline, di_none, stylesheet}; import dom::style::{DisplayType, DisBlock, DisInline, DisNone, Stylesheet};
import dom::base::{Element, HTMLDivElement, HTMLHeadElement, HTMLImageElement, Node, NodeKind}; import dom::base::{Element, HTMLDivElement, HTMLHeadElement, HTMLImageElement, Node, NodeKind};
import dom::base::{Text}; import dom::base::{Text};
import dom::rcu::ReaderMethods; import dom::rcu::ReaderMethods;
@ -11,23 +11,23 @@ import matching::matching_methods;
import util::color::{Color, rgb}; import util::color::{Color, rgb};
import util::color::css_colors::{white, black}; import util::color::css_colors::{white, black};
type computed_style = {mut display : display_type, mut back_color : Color}; type computed_style = {mut display : DisplayType, mut back_color : Color};
#[doc="Returns the default style for the given node kind."] #[doc="Returns the default style for the given node kind."]
fn default_style_for_node_kind(kind: NodeKind) -> computed_style { fn default_style_for_node_kind(kind: NodeKind) -> computed_style {
alt kind { alt kind {
Text(*) { Text(*) {
{mut display: di_inline, mut back_color: white()} {mut display: DisInline, mut back_color: white()}
} }
Element(element) { Element(element) {
let r = rand::rng(); let r = rand::rng();
let rand_color = rgb(r.next() as u8, r.next() as u8, r.next() as u8); let rand_color = rgb(r.next() as u8, r.next() as u8, r.next() as u8);
alt *element.kind { alt *element.kind {
HTMLDivElement { {mut display: di_block, mut back_color: rand_color} } HTMLDivElement { {mut display: DisBlock, mut back_color: rand_color} }
HTMLHeadElement { {mut display: di_none, mut back_color: rand_color} } HTMLHeadElement { {mut display: DisNone, mut back_color: rand_color} }
HTMLImageElement(*) { {mut display: di_inline, mut back_color: rand_color} } HTMLImageElement(*) { {mut display: DisInline, mut back_color: rand_color} }
UnknownElement { {mut display: di_inline, mut back_color: rand_color} } UnknownElement { {mut display: DisInline, mut back_color: rand_color} }
} }
} }
} }
@ -79,7 +79,7 @@ impl style_methods for Node {
This is, importantly, the function that updates the layout data for the node (the reader- This is, importantly, the function that updates the layout data for the node (the reader-
auxiliary box in the RCU model) with the computed style. auxiliary box in the RCU model) with the computed style.
"] "]
fn recompute_style_for_subtree(styles : arc<stylesheet>) { fn recompute_style_for_subtree(styles : arc<Stylesheet>) {
listen { |ack_chan| listen { |ack_chan|
let mut i = 0u; let mut i = 0u;

View file

@ -3,7 +3,8 @@
// TODO: fail according to the css spec instead of failing when things // TODO: fail according to the css spec instead of failing when things
// are not as expected // are not as expected
import dom::style::*; import dom::style;
import style::{DisInline, DisBlock, DisNone, Display, TextColor, BackgroundColor, FontSize};
import parser::css_lexer::{Token, StartDescription, EndDescription, import parser::css_lexer::{Token, StartDescription, EndDescription,
Descendant, Child, Sibling, Descendant, Child, Sibling,
Comma, Element, Attr, Description, Comma, Element, Attr, Description,
@ -28,12 +29,12 @@ impl methods for TokenReader {
} }
} }
fn parse_element(reader : TokenReader) -> option<~selector> { fn parse_element(reader : TokenReader) -> option<~style::Selector> {
// Get the current element type // Get the current element type
let elmt_name = alt reader.get() { let elmt_name = alt reader.get() {
Element(tag) { copy tag } Element(tag) { copy tag }
Eof { ret none; } Eof { ret none; }
_ { fail "Expected an element" } _ { fail "Expected an element" }
}; };
let mut attr_list = []; let mut attr_list = [];
@ -55,10 +56,10 @@ fn parse_element(reader : TokenReader) -> option<~selector> {
} }
} }
ret some(~element(elmt_name, attr_list)); ret some(~style::Element(elmt_name, attr_list));
} }
fn parse_rule(reader : TokenReader) -> option<~rule> { fn parse_rule(reader : TokenReader) -> option<~style::Rule> {
let mut sel_list = []; let mut sel_list = [];
let mut desc_list = []; let mut desc_list = [];
@ -79,7 +80,7 @@ fn parse_rule(reader : TokenReader) -> option<~rule> {
some(elmt) { some(elmt) {
let built_sel <- cur_sel; let built_sel <- cur_sel;
let new_sel = copy elmt; let new_sel = copy elmt;
cur_sel <- ~descendant(built_sel, new_sel) cur_sel <- ~style::Descendant(built_sel, new_sel)
} }
none { ret none; } none { ret none; }
} }
@ -89,7 +90,7 @@ fn parse_rule(reader : TokenReader) -> option<~rule> {
some(elmt) { some(elmt) {
let built_sel <- cur_sel; let built_sel <- cur_sel;
let new_sel = copy elmt; let new_sel = copy elmt;
cur_sel <- ~child(built_sel, new_sel) cur_sel <- ~style::Child(built_sel, new_sel)
} }
none { ret none; } none { ret none; }
} }
@ -99,7 +100,7 @@ fn parse_rule(reader : TokenReader) -> option<~rule> {
some(elmt) { some(elmt) {
let built_sel <- cur_sel; let built_sel <- cur_sel;
let new_sel = copy elmt; let new_sel = copy elmt;
cur_sel <- ~sibling(built_sel, new_sel) cur_sel <- ~style::Sibling(built_sel, new_sel)
} }
none { ret none; } none { ret none; }
} }
@ -145,24 +146,24 @@ fn parse_rule(reader : TokenReader) -> option<~rule> {
let num = val.substr(0u, val.len() - 2u); let num = val.substr(0u, val.len() - 2u);
alt uint::from_str(num) { alt uint::from_str(num) {
some(n) { desc_list += [font_size(n)]; } some(n) { desc_list += [FontSize(n)]; }
none { fail "Nonnumber provided as font size"; } none { fail "Nonnumber provided as font size"; }
} }
} }
"display" { "display" {
alt val { alt val {
"inline" { desc_list += [display(di_inline)]; } "inline" { desc_list += [Display(DisInline)]; }
"block" { desc_list += [display(di_block)]; } "block" { desc_list += [Display(DisBlock)]; }
"none" { desc_list += [display(di_none)]; } "none" { desc_list += [Display(DisNone)]; }
_ { #debug["Recieved unknown display value '%s'", _ { #debug["Recieved unknown display value '%s'",
val]; } val]; }
} }
} }
"color" { "color" {
desc_list += [text_color(parse_color(val))]; desc_list += [TextColor(parse_color(val))];
} }
"background-color" { "background-color" {
desc_list += [background_color(parse_color(val))]; desc_list += [BackgroundColor(parse_color(val))];
} }
_ { #debug["Recieved unknown style property '%s'", _ { #debug["Recieved unknown style property '%s'",
val]; } val]; }
@ -179,7 +180,7 @@ fn parse_rule(reader : TokenReader) -> option<~rule> {
ret some(~(sel_list, desc_list)); ret some(~(sel_list, desc_list));
} }
fn build_stylesheet(stream : port<Token>) -> [~rule] { fn build_stylesheet(stream : port<Token>) -> [~style::Rule] {
let mut rule_list = []; let mut rule_list = [];
let reader = {stream : stream, mut lookahead : none}; let reader = {stream : stream, mut lookahead : none};

View file

@ -25,7 +25,7 @@ enum Token {
Sibling, Sibling,
Comma, Comma,
Element(str), Element(str),
Attr(style::attr), Attr(style::Attr),
Description(str, str), Description(str, str),
Eof Eof
} }
@ -105,10 +105,8 @@ impl css_methods for CssLexer {
} }
alt ch { alt ch {
'.' as u8 { ret Attr( '.' as u8 { ret Attr(style::Includes("class", self.input_state.parse_ident())); }
style::includes("class", self.input_state.parse_ident())); } '#' as u8 { ret Attr(style::Includes("id", self.input_state.parse_ident())); }
'#' as u8 { ret Attr(
style::includes("id", self.input_state.parse_ident())); }
'[' as u8 { '[' as u8 {
let attr_name = self.input_state.parse_ident(); let attr_name = self.input_state.parse_ident();
@ -118,21 +116,21 @@ impl css_methods for CssLexer {
} }
if ch == ']' as u8 { if ch == ']' as u8 {
ret Attr(style::exists(attr_name)); ret Attr(style::Exists(attr_name));
} else if ch == '=' as u8 { } else if ch == '=' as u8 {
let attr_val = self.input_state.parse_ident(); let attr_val = self.input_state.parse_ident();
self.input_state.expect(']' as u8); self.input_state.expect(']' as u8);
ret Attr(style::exact(attr_name, attr_val)); ret Attr(style::Exact(attr_name, attr_val));
} else if ch == '~' as u8 { } else if ch == '~' as u8 {
self.input_state.expect('=' as u8); self.input_state.expect('=' as u8);
let attr_val = self.input_state.parse_ident(); let attr_val = self.input_state.parse_ident();
self.input_state.expect(']' as u8); self.input_state.expect(']' as u8);
ret Attr(style::includes(attr_name, attr_val)); ret Attr(style::Includes(attr_name, attr_val));
} else if ch == '|' as u8 { } else if ch == '|' as u8 {
self.input_state.expect('=' as u8); self.input_state.expect('=' as u8);
let attr_val = self.input_state.parse_ident(); let attr_val = self.input_state.parse_ident();
self.input_state.expect(']' as u8); self.input_state.expect(']' as u8);
ret Attr(style::starts_with(attr_name, attr_val)); ret Attr(style::StartsWith(attr_name, attr_val));
} }
fail #fmt("Unexpected symbol %c in attribute", ch as char); fail #fmt("Unexpected symbol %c in attribute", ch as char);

View file

@ -9,7 +9,7 @@ import gfx::geometry;
import gfx::geometry::au; import gfx::geometry::au;
import parser = parser::html_lexer; import parser = parser::html_lexer;
import parser::Token; import parser::Token;
import dom::style::stylesheet; import dom::style::Stylesheet;
import dvec::extensions; import dvec::extensions;
@ -86,7 +86,7 @@ spawned, collates them, and sends them to the given result channel.
* `from_parent` - A port on which to receive new links. * `from_parent` - A port on which to receive new links.
"] "]
fn css_link_listener(to_parent : chan<stylesheet>, from_parent : port<css_message>) { fn css_link_listener(to_parent : chan<Stylesheet>, from_parent : port<css_message>) {
let mut result_vec = []; let mut result_vec = [];
loop { loop {
@ -121,7 +121,7 @@ fn css_link_listener(to_parent : chan<stylesheet>, from_parent : port<css_messag
} }
#[warn(no_non_implicitly_copyable_typarams)] #[warn(no_non_implicitly_copyable_typarams)]
fn build_dom(scope: NodeScope, stream: port<Token>) -> (Node, port<stylesheet>) { fn build_dom(scope: NodeScope, stream: port<Token>) -> (Node, port<Stylesheet>) {
// The current reference node. // The current reference node.
let mut cur_node = scope.new_node(Element(ElementData("html", ~HTMLDivElement))); let mut cur_node = scope.new_node(Element(ElementData("html", ~HTMLDivElement)));
// We will spawn a separate task to parse any css that is // We will spawn a separate task to parse any css that is