Create a css module and divide into values, styles, and resolve things.

This commit is contained in:
Brian J. Burg 2012-09-06 12:32:09 -07:00
parent c326c7880d
commit e1bcdc509a
18 changed files with 81 additions and 78 deletions

View file

@ -14,14 +14,14 @@ import io::{read_whole_file, println};
import dom::base::{Document, Node, NodeScope, Window, define_bindings}; import dom::base::{Document, Node, NodeScope, Window, define_bindings};
import dom::event::{Event, ResizeEvent, ReflowEvent}; import dom::event::{Event, ResizeEvent, ReflowEvent};
import dom::style;
import dom::style::Stylesheet;
import gfx::compositor::Compositor; import gfx::compositor::Compositor;
import parser::html_lexer::spawn_html_lexer_task; import parser::html_lexer::spawn_html_lexer_task;
import parser::html_builder::build_dom; import parser::html_builder::build_dom;
import layout::layout_task; import layout::layout_task;
import layout_task::{LayoutTask, BuildMsg}; import layout_task::{LayoutTask, BuildMsg};
import css::styles::Stylesheet;
import jsrt = js::rust::rt; import jsrt = js::rust::rt;
import js::rust::{cx, methods}; import js::rust::{cx, methods};
import js::global::{global_class, debug_fns}; import js::global::{global_class, debug_fns};

View file

@ -1,14 +1,15 @@
#[doc="Applies the appropriate CSS style to boxes."] #[doc="Applies the appropriate CSS style to boxes."]
import dom::base::{Element, HTMLImageElement, Node}; import dom::base::{Element, HTMLImageElement, Node};
import dom::style::{Percent, Mm, Pt, Px, Auto, PtToPx, MmToPx};
import gfx::geometry::au_to_px; import gfx::geometry::au_to_px;
import base::{Box, BTree, NTree, LayoutData, SpecifiedStyle, ImageHolder, import layout::base::{Box, BTree, NTree, LayoutData, SpecifiedStyle, ImageHolder,
BlockBox, InlineBox, IntrinsicBox, TextBox}; BlockBox, InlineBox, IntrinsicBox, TextBox};
import traverse::{top_down_traversal}; import layout::traverse::{top_down_traversal};
import std::net::url::Url; import std::net::url::Url;
import resource::image_cache_task::ImageCacheTask; import resource::image_cache_task::ImageCacheTask;
import css::values::{Percent, Mm, Pt, Px, Auto, PtToPx, MmToPx};
struct StyleApplicator { struct StyleApplicator {
box: @Box; box: @Box;
doc_url: &Url; doc_url: &Url;

View file

@ -1,12 +1,13 @@
#[doc="Performs CSS selector matching."] #[doc="Performs CSS selector matching."]
import base::{LayoutData}; import dom::base::{LayoutData};
import dom::base; import dom::base;
import base::{ElementData, Node, Text}; import base::{ElementData, Node, Text};
import dom::style::{Selector, StyleDeclaration, FontSize, Display, TextColor, BackgroundColor,
import values::{Selector, StyleDeclaration, FontSize, Display, TextColor, BackgroundColor,
Stylesheet, Element, Child, Descendant, Sibling, Attr, Exact, Exists, Includes, Stylesheet, Element, Child, Descendant, Sibling, Attr, Exact, Exists, Includes,
StartsWith, Width, Height}; StartsWith, Width, Height};
import style::{SpecifiedStyle}; import styles::{SpecifiedStyle};
#[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 {

View file

@ -2,12 +2,13 @@
import std::arc::{ARC, get, clone}; import std::arc::{ARC, get, clone};
import dom::style::{DisplayType, DisBlock, DisInline, DisNone, Stylesheet, Unit, Auto}; import css::values::{DisplayType, DisBlock, DisInline, DisNone, Unit, Auto};
import css::values::Stylesheet;
import dom::base::{HTMLDivElement, HTMLHeadElement, HTMLImageElement, UnknownElement, HTMLScriptElement}; import dom::base::{HTMLDivElement, HTMLHeadElement, HTMLImageElement, UnknownElement, HTMLScriptElement};
import dom::base::{Comment, Doctype, Element, Node, NodeKind, Text}; import dom::base::{Comment, Doctype, Element, Node, NodeKind, Text};
import util::color::{Color, rgb}; import util::color::{Color, rgb};
import util::color::css_colors::{white, black}; import util::color::css_colors::{white, black};
import base::{LayoutData, NTree}; import layout::base::{LayoutData, NTree};
type SpecifiedStyle = {mut background_color : Option<Color>, type SpecifiedStyle = {mut background_color : Option<Color>,
mut display_type : Option<DisplayType>, mut display_type : Option<DisplayType>,

View file

@ -13,7 +13,7 @@ import dvec::DVec;
import ptr::null; import ptr::null;
import bindings; import bindings;
import std::arc::ARC; import std::arc::ARC;
import style::Stylesheet; import css::values::Stylesheet;
import comm::{Port, Chan}; import comm::{Port, Chan};
import content::content_task::{ControlMsg, Timer}; import content::content_task::{ControlMsg, Timer};

View file

@ -1,9 +1,10 @@
#[doc="Fundamental layout structures and algorithms."] #[doc="Fundamental layout structures and algorithms."]
import css::values::Unit;
import css::styles::SpecifiedStyle;
import dom::base::{Element, ElementKind, HTMLDivElement, HTMLImageElement, Node, NodeData}; import dom::base::{Element, ElementKind, HTMLDivElement, HTMLImageElement, Node, NodeData};
import dom::base::{NodeKind}; import dom::base::{NodeKind};
import dom::rcu; import dom::rcu;
import dom::style::Unit;
import gfx::geometry; import gfx::geometry;
import gfx::geometry::{au, zero_size_au}; import gfx::geometry::{au, zero_size_au};
import geom::point::Point2D; import geom::point::Point2D;
@ -14,7 +15,6 @@ import util::tree;
import util::color::Color; import util::color::Color;
import text::TextBox; import text::TextBox;
import traverse::extended_full_traversal; import traverse::extended_full_traversal;
import style::style::{SpecifiedStyle};
import vec::{push, push_all}; import vec::{push, push_all};
import std::net::url::Url; import std::net::url::Url;
import resource::image_cache_task; import resource::image_cache_task;

View file

@ -1,6 +1,6 @@
#[doc="Block layout."] #[doc="Block layout."]
import dom::style::{Px, Mm, Pt, Auto, Percent, Unit}; import css::values::{Px, Mm, Pt, Auto, Percent, Unit};
import geom::point::Point2D; import geom::point::Point2D;
import geom::size::Size2D; import geom::size::Size2D;
import gfx::geometry::{px_to_au, au}; import gfx::geometry::{px_to_au, au};

View file

@ -1,7 +1,7 @@
#[doc="Creates CSS boxes from a DOM."] #[doc="Creates CSS boxes from a DOM."]
import css::values::{DisplayType, DisBlock, DisInline, DisNone};
import dom::base::{ElementData, HTMLDivElement, HTMLImageElement, Element, Text, Node}; import dom::base::{ElementData, HTMLDivElement, HTMLImageElement, Element, Text, Node};
import dom::style::{DisplayType, DisBlock, DisInline, DisNone};
import gfx::geometry::zero_size_au; import gfx::geometry::zero_size_au;
import layout::base::{Appearance, BTree, BlockBox, Box, BoxKind, InlineBox, IntrinsicBox, NTree}; import layout::base::{Appearance, BTree, BlockBox, Box, BoxKind, InlineBox, IntrinsicBox, NTree};
import layout::base::{TextBoxKind}; import layout::base::{TextBoxKind};

View file

@ -1,8 +1,8 @@
#[doc="Inline layout."] #[doc="Inline layout."]
import base::{Box, InlineBox, BTree}; import base::{Box, InlineBox, BTree};
import css::values::{Auto, Px};
import dom::rcu; import dom::rcu;
import dom::style::{Auto, Px};
import geom::point::Point2D; import geom::point::Point2D;
import geom::size::Size2D; import geom::size::Size2D;
import gfx::geometry::{au, px_to_au}; import gfx::geometry::{au, px_to_au};

View file

@ -6,13 +6,13 @@
import std::arc::ARC; import std::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 css::values::Stylesheet;
import gfx::geometry::px_to_au; import gfx::geometry::px_to_au;
import gfx::render_task; import gfx::render_task;
import render_task::RenderTask; import render_task::RenderTask;
import resource::image_cache_task::ImageCacheTask; import resource::image_cache_task::ImageCacheTask;
import std::net::url::Url; import std::net::url::Url;
import style::apply::apply_style; import css::resolve::apply::apply_style;
import dom::event::{Event, ReflowEvent}; import dom::event::{Event, ReflowEvent};
import content::content_task; import content::content_task;

View file

@ -3,13 +3,12 @@
// 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 css::values::{DisInline, DisBlock, DisNone, Display, TextColor, BackgroundColor, FontSize,
import style::{DisInline, DisBlock, DisNone, Display, TextColor, BackgroundColor, FontSize, Height, Width, StyleDeclaration};
Height, Width, StyleDeclaration, Selector}; // Disambiguate parsed Selector, Rule values from tokens
import parser::css_lexer::{Token, StartDescription, EndDescription, import css = css::values;
Descendant, Child, Sibling, import tok = parser::css_lexer;
Comma, Element, Attr, Description, import parser::css_lexer::Token;
Eof};
import comm::recv; import comm::recv;
import option::{map, is_none}; import option::{map, is_none};
import vec::push; import vec::push;
@ -39,18 +38,18 @@ impl TokenReader : TokenReaderMethods {
} }
trait ParserMethods { trait ParserMethods {
fn parse_element() -> Option<~style::Selector>; fn parse_element() -> Option<~css::Selector>;
fn parse_selector() -> Option<~[~Selector]>; fn parse_selector() -> Option<~[~css::Selector]>;
fn parse_description() -> Option<~[StyleDeclaration]>; fn parse_description() -> Option<~[StyleDeclaration]>;
fn parse_rule() -> Option<~style::Rule>; fn parse_rule() -> Option<~css::Rule>;
} }
impl TokenReader : ParserMethods { impl TokenReader : ParserMethods {
fn parse_element() -> Option<~style::Selector> { fn parse_element() -> Option<~css::Selector> {
// Get the current element type // Get the current element type
let elmt_name = match self.get() { let elmt_name = match self.get() {
Element(tag) => { copy tag } tok::Element(tag) => { copy tag }
Eof => { return None; } tok::Eof => { return None; }
_ => { fail ~"Expected an element" } _ => { fail ~"Expected an element" }
}; };
@ -58,23 +57,23 @@ impl TokenReader : ParserMethods {
// Get the attributes associated with that element // Get the attributes associated with that element
loop { loop {
let tok = self.get(); let token = self.get();
match tok { match token {
Attr(attr) => { push(attr_list, copy attr); } tok::Attr(attr) => { push(attr_list, copy attr); }
StartDescription | Descendant | Child | Sibling | Comma => { tok::StartDescription | tok::Descendant | tok::Child | tok::Sibling | tok::Comma => {
self.unget(tok); self.unget(token);
break; break;
} }
Eof => { return None; } tok::Eof => { return None; }
Element(_) => fail ~"Unexpected second element without relation to first element", tok::Element(_) => fail ~"Unexpected second element without relation to first element",
EndDescription => fail ~"Unexpected '}'", tok::EndDescription => fail ~"Unexpected '}'",
Description(_, _) => fail ~"Unexpected description" tok::Description(_, _) => fail ~"Unexpected description"
} }
} }
return Some(~style::Element(elmt_name, attr_list)); return Some(~css::Element(elmt_name, attr_list));
} }
fn parse_selector() -> Option<~[~Selector]> { fn parse_selector() -> Option<~[~css::Selector]> {
let mut sel_list = ~[]; let mut sel_list = ~[];
// Collect all the selectors that this rule applies to // Collect all the selectors that this rule applies to
@ -91,47 +90,47 @@ impl TokenReader : ParserMethods {
let built_sel <- cur_sel; let built_sel <- cur_sel;
match tok { match tok {
Descendant => { tok::Descendant => {
match self.parse_element() { match self.parse_element() {
Some(elmt) => { Some(elmt) => {
let new_sel = copy elmt; let new_sel = copy elmt;
cur_sel <- ~style::Descendant(built_sel, new_sel) cur_sel <- ~css::Descendant(built_sel, new_sel)
} }
None => { return None; } None => { return None; }
} }
} }
Child => { tok::Child => {
match self.parse_element() { match self.parse_element() {
Some(elmt) => { Some(elmt) => {
let new_sel = copy elmt; let new_sel = copy elmt;
cur_sel <- ~style::Child(built_sel, new_sel) cur_sel <- ~css::Child(built_sel, new_sel)
} }
None => { return None; } None => { return None; }
} }
} }
Sibling => { tok::Sibling => {
match self.parse_element() { match self.parse_element() {
Some(elmt) => { Some(elmt) => {
let new_sel = copy elmt; let new_sel = copy elmt;
cur_sel <- ~style::Sibling(built_sel, new_sel) cur_sel <- ~css::Sibling(built_sel, new_sel)
} }
None => { return None; } None => { return None; }
} }
} }
StartDescription => { tok::StartDescription => {
push(sel_list, built_sel); push(sel_list, built_sel);
self.unget(StartDescription); self.unget(tok::StartDescription);
break; break;
} }
Comma => { tok::Comma => {
push(sel_list, built_sel); push(sel_list, built_sel);
self.unget(Comma); self.unget(tok::Comma);
break; break;
} }
Attr(_) | EndDescription | Element(_) | Description(_, _) => { tok::Attr(_) | tok::EndDescription | tok::Element(_) | tok::Description(_, _) => {
fail #fmt["Unexpected token %? in elements", tok]; fail #fmt["Unexpected token %? in elements", tok];
} }
Eof => { return None; } tok::Eof => { return None; }
} }
} }
@ -139,8 +138,8 @@ impl TokenReader : ParserMethods {
// TODO: fix this when rust gets labelled loops // TODO: fix this when rust gets labelled loops
let tok = self.get(); let tok = self.get();
match tok { match tok {
StartDescription => { break; } tok::StartDescription => { break; }
Comma => { } tok::Comma => { }
_ => { self.unget(tok); } _ => { self.unget(tok); }
} }
} }
@ -155,8 +154,8 @@ impl TokenReader : ParserMethods {
loop { loop {
let tok = self.get(); let tok = self.get();
match tok { match tok {
EndDescription => { break; } tok::EndDescription => { break; }
Description(prop, val) => { tok::Description(prop, val) => {
let desc = match prop { let desc = match prop {
// TODO: have color parsing return an option instead of a real value // TODO: have color parsing return an option instead of a real value
~"background-color" => parse_color(val).map(|res| BackgroundColor(res)), ~"background-color" => parse_color(val).map(|res| BackgroundColor(res)),
@ -169,8 +168,9 @@ impl TokenReader : ParserMethods {
}; };
desc.map(|res| push(desc_list, res)); desc.map(|res| push(desc_list, res));
} }
Eof => { return None; } tok::Eof => { return None; }
StartDescription | Descendant | Child | Sibling | Comma | Element(_) | Attr(_) => { tok::StartDescription | tok::Descendant | tok::Child | tok::Sibling
| tok::Comma | tok::Element(_) | tok::Attr(_) => {
fail #fmt["Unexpected token %? in description", tok]; fail #fmt["Unexpected token %? in description", tok];
} }
} }
@ -179,7 +179,7 @@ impl TokenReader : ParserMethods {
return Some(desc_list); return Some(desc_list);
} }
fn parse_rule() -> Option<~style::Rule> { fn parse_rule() -> Option<~css::Rule> {
// TODO: get rid of copies once match move works // TODO: get rid of copies once match move works
let sel_list = match self.parse_selector() { let sel_list = match self.parse_selector() {
Some(list) => { copy list } Some(list) => { copy list }
@ -200,7 +200,7 @@ impl TokenReader : ParserMethods {
} }
} }
fn build_stylesheet(+stream : pipes::Port<Token>) -> ~[~style::Rule] { fn build_stylesheet(+stream : pipes::Port<Token>) -> ~[~css::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

@ -1,6 +1,5 @@
#[doc = "Code to lex and tokenize css files."] #[doc = "Code to lex and tokenize css files."]
import dom::style;
import option::is_none; import option::is_none;
import str::from_bytes; import str::from_bytes;
import vec::push; import vec::push;
@ -32,7 +31,7 @@ enum Token {
Sibling, Sibling,
Comma, Comma,
Element(~str), Element(~str),
Attr(style::Attr), Attr(css::values::Attr),
Description(~str, ~str), Description(~str, ~str),
Eof Eof
} }
@ -120,8 +119,8 @@ impl CssLexer : CssLexerMethods {
} }
match ch { match ch {
'.' as u8 => return Attr(style::Includes(~"class", self.input_state.parse_ident())), '.' as u8 => return Attr(css::values::Includes(~"class", self.input_state.parse_ident())),
'#' as u8 => return Attr(style::Includes(~"id", self.input_state.parse_ident())), '#' as u8 => return Attr(css::values::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();
@ -131,21 +130,21 @@ impl CssLexer : CssLexerMethods {
} }
if ch == ']' as u8 { if ch == ']' as u8 {
return Attr(style::Exists(attr_name)); return Attr(css::values::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);
return Attr(style::Exact(attr_name, attr_val)); return Attr(css::values::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);
return Attr(style::Includes(attr_name, attr_val)); return Attr(css::values::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);
return Attr(style::StartsWith(attr_name, attr_val)); return Attr(css::values::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

@ -8,7 +8,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 css::values::Stylesheet;
import vec::{push, push_all_move, flat_map}; import vec::{push, push_all_move, flat_map};
import std::net::url::Url; import std::net::url::Url;
import resource::resource_task::{ResourceTask, Load, Payload, Done}; import resource::resource_task::{ResourceTask, Load, Payload, Done};

View file

@ -1,5 +1,4 @@
import comm::{Port, Chan}; import comm::{Port, Chan};
import dom::style;
import option::is_none; import option::is_none;
import str::from_bytes; import str::from_bytes;
import vec::push; import vec::push;

View file

@ -1,7 +1,7 @@
use dom::base::{Attr, Comment, Doctype, DoctypeData, Element, ElementData, ElementKind}; use dom::base::{Attr, Comment, Doctype, DoctypeData, Element, ElementData, ElementKind};
use dom::base::{HTMLDivElement, HTMLHeadElement, HTMLImageElement, HTMLScriptElement}; use dom::base::{HTMLDivElement, HTMLHeadElement, HTMLImageElement, HTMLScriptElement};
use dom::base::{Node, NodeScope, Text, UnknownElement}; use dom::base::{Node, NodeScope, Text, UnknownElement};
use dom::style::Stylesheet; use css::values::Stylesheet;
use geom::size::Size2D; use geom::size::Size2D;
use gfx::geometry::px_to_au; use gfx::geometry::px_to_au;
use parser::html_builder::CSSMessage; use parser::html_builder::CSSMessage;

View file

@ -1,6 +1,6 @@
#[doc = "Helper functions to parse values of specific attributes."] #[doc = "Helper functions to parse values of specific attributes."]
import dom::style::*; import css::values::*;
import str::{pop_char, from_chars}; import str::{pop_char, from_chars};
import float::from_str; import float::from_str;
import option::map; import option::map;

View file

@ -24,7 +24,6 @@ mod dom {
mod base; mod base;
mod event; mod event;
mod rcu; mod rcu;
mod style;
mod bindings { mod bindings {
mod document; mod document;
mod element; mod element;
@ -39,13 +38,16 @@ mod content {
mod content_task; mod content_task;
} }
mod layout { mod css {
mod style { mod values;
mod styles;
mod resolve {
mod apply; mod apply;
mod style;
mod matching; mod matching;
} }
}
mod layout {
mod base; mod base;
mod block; mod block;
mod box_builder; mod box_builder;