mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
layout: Introduce support for legacy presentational attributes to selector
matching, and use it for `<input size>` and `<td width>`. This implements a general framework for legacy presentational attributes to the DOM and style calculation, so that adding more of them later will be straightforward.
This commit is contained in:
parent
8077edc062
commit
5f8d3f72d8
31 changed files with 570 additions and 214 deletions
|
@ -53,6 +53,7 @@ use script_traits::UntrustedNodeAddress;
|
|||
use servo_msg::compositor_msg::ScriptListener;
|
||||
use servo_msg::constellation_msg::ConstellationChan;
|
||||
use servo_util::smallvec::{SmallVec1, SmallVec};
|
||||
use servo_util::str::LengthOrPercentageOrAuto;
|
||||
use layout_interface::{LayoutRPC, LayoutChan};
|
||||
use dom::bindings::utils::WindowProxyHandler;
|
||||
|
||||
|
@ -234,3 +235,6 @@ impl JSTraceable for Box<LayoutRPC+'static> {
|
|||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
untraceable!(LengthOrPercentageOrAuto)
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@ use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
|||
use dom::bindings::codegen::Bindings::ElementBinding;
|
||||
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
|
||||
use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods;
|
||||
use dom::bindings::codegen::InheritTypes::{ElementDerived, NodeCast};
|
||||
use dom::bindings::codegen::InheritTypes::{ElementDerived, HTMLInputElementDerived};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLTableCellElementDerived, NodeCast};
|
||||
use dom::bindings::js::{MutNullableJS, JS, JSRef, Temporary, TemporaryPushable};
|
||||
use dom::bindings::js::{OptionalSettable, OptionalRootable, Root};
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
|
@ -23,16 +24,19 @@ use dom::document::{Document, DocumentHelpers};
|
|||
use dom::domtokenlist::DOMTokenList;
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlcollection::HTMLCollection;
|
||||
use dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers};
|
||||
use dom::htmlserializer::serialize;
|
||||
use dom::htmltablecellelement::{HTMLTableCellElement, HTMLTableCellElementHelpers};
|
||||
use dom::node::{ElementNodeTypeId, Node, NodeHelpers, NodeIterator, document_from_node};
|
||||
use dom::node::{window_from_node, LayoutNodeHelpers};
|
||||
use dom::nodelist::NodeList;
|
||||
use dom::virtualmethods::{VirtualMethods, vtable_for};
|
||||
use devtools_traits::AttrInfo;
|
||||
use style::{IntegerAttribute, LengthAttribute, SizeIntegerAttribute, WidthLengthAttribute};
|
||||
use style::{matches, parse_selector_list_from_str};
|
||||
use style;
|
||||
use servo_util::namespace;
|
||||
use servo_util::str::DOMString;
|
||||
use servo_util::str::{DOMString, LengthOrPercentageOrAuto};
|
||||
|
||||
use std::ascii::StrAsciiExt;
|
||||
use std::cell::{Ref, RefMut, RefCell};
|
||||
|
@ -211,6 +215,10 @@ pub trait RawLayoutElementHelpers {
|
|||
unsafe fn get_attr_atom_for_layout(&self, namespace: &Namespace, name: &Atom) -> Option<Atom>;
|
||||
unsafe fn has_class_for_layout(&self, name: &Atom) -> bool;
|
||||
unsafe fn get_classes_for_layout(&self) -> Option<&'static [Atom]>;
|
||||
unsafe fn get_length_attribute_for_layout(&self, length_attribute: LengthAttribute)
|
||||
-> LengthOrPercentageOrAuto;
|
||||
unsafe fn get_integer_attribute_for_layout(&self, integer_attribute: IntegerAttribute)
|
||||
-> Option<i32>;
|
||||
}
|
||||
|
||||
impl RawLayoutElementHelpers for Element {
|
||||
|
@ -288,6 +296,36 @@ impl RawLayoutElementHelpers for Element {
|
|||
(*attr).value_tokens_forever()
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(unrooted_must_root)]
|
||||
unsafe fn get_length_attribute_for_layout(&self, length_attribute: LengthAttribute)
|
||||
-> LengthOrPercentageOrAuto {
|
||||
match length_attribute {
|
||||
WidthLengthAttribute => {
|
||||
if !self.is_htmltablecellelement() {
|
||||
fail!("I'm not a table cell!")
|
||||
}
|
||||
let this: &HTMLTableCellElement = mem::transmute(self);
|
||||
this.get_width()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(unrooted_must_root)]
|
||||
unsafe fn get_integer_attribute_for_layout(&self, integer_attribute: IntegerAttribute)
|
||||
-> Option<i32> {
|
||||
match integer_attribute {
|
||||
SizeIntegerAttribute => {
|
||||
if !self.is_htmlinputelement() {
|
||||
fail!("I'm not a form input!")
|
||||
}
|
||||
let this: &HTMLInputElement = mem::transmute(self);
|
||||
Some(this.get_size_for_layout() as i32)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait LayoutElementHelpers {
|
||||
|
@ -1133,3 +1171,4 @@ impl<'a> style::TElement<'a> for JSRef<'a, Element> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,14 +88,14 @@ pub trait LayoutHTMLInputElementHelpers {
|
|||
unsafe fn get_size_for_layout(&self) -> u32;
|
||||
}
|
||||
|
||||
impl LayoutHTMLInputElementHelpers for JS<HTMLInputElement> {
|
||||
impl LayoutHTMLInputElementHelpers for HTMLInputElement {
|
||||
#[allow(unrooted_must_root)]
|
||||
unsafe fn get_value_for_layout(&self) -> String {
|
||||
unsafe fn get_raw_value(input: &JS<HTMLInputElement>) -> Option<String> {
|
||||
mem::transmute::<&RefCell<Option<String>>, &Option<String>>(&(*input.unsafe_get()).value).clone()
|
||||
unsafe fn get_raw_value(input: &HTMLInputElement) -> Option<String> {
|
||||
mem::transmute::<&RefCell<Option<String>>, &Option<String>>(&input.value).clone()
|
||||
}
|
||||
|
||||
match (*self.unsafe_get()).input_type.get() {
|
||||
match self.input_type.get() {
|
||||
InputCheckbox | InputRadio => "".to_string(),
|
||||
InputFile | InputImage => "".to_string(),
|
||||
InputButton(ref default) => get_raw_value(self)
|
||||
|
@ -111,7 +111,17 @@ impl LayoutHTMLInputElementHelpers for JS<HTMLInputElement> {
|
|||
|
||||
#[allow(unrooted_must_root)]
|
||||
unsafe fn get_size_for_layout(&self) -> u32 {
|
||||
(*self.unsafe_get()).size.get()
|
||||
self.size.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl LayoutHTMLInputElementHelpers for JS<HTMLInputElement> {
|
||||
unsafe fn get_value_for_layout(&self) -> String {
|
||||
(*self.unsafe_get()).get_value_for_layout()
|
||||
}
|
||||
|
||||
unsafe fn get_size_for_layout(&self) -> u32 {
|
||||
(*self.unsafe_get()).get_size_for_layout()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,11 +197,12 @@ impl<'a> HTMLInputElementMethods for JSRef<'a, HTMLInputElement> {
|
|||
make_setter!(SetFormTarget, "formtarget")
|
||||
}
|
||||
|
||||
trait HTMLInputElementHelpers {
|
||||
pub trait HTMLInputElementHelpers {
|
||||
fn force_relayout(self);
|
||||
fn radio_group_updated(self, group: Option<&str>);
|
||||
fn get_radio_group(self) -> Option<String>;
|
||||
fn update_checked_state(self, checked: bool);
|
||||
fn get_size(&self) -> u32;
|
||||
}
|
||||
|
||||
fn broadcast_radio_checked(broadcaster: JSRef<HTMLInputElement>, group: Option<&str>) {
|
||||
|
@ -248,6 +259,10 @@ impl<'a> HTMLInputElementHelpers for JSRef<'a, HTMLInputElement> {
|
|||
//TODO: dispatch change event
|
||||
self.force_relayout();
|
||||
}
|
||||
|
||||
fn get_size(&self) -> u32 {
|
||||
self.size.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLInputElement> {
|
||||
|
|
|
@ -2,21 +2,28 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use dom::bindings::codegen::InheritTypes::HTMLTableCellElementDerived;
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLTableCellElementDerived};
|
||||
use dom::bindings::js::JSRef;
|
||||
use dom::bindings::utils::{Reflectable, Reflector};
|
||||
use dom::document::Document;
|
||||
use dom::element::{ElementTypeId, HTMLTableDataCellElementTypeId, HTMLTableHeaderCellElementTypeId};
|
||||
use dom::element::{ElementTypeId, HTMLTableDataCellElementTypeId};
|
||||
use dom::element::{HTMLTableHeaderCellElementTypeId};
|
||||
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
|
||||
use dom::htmlelement::HTMLElement;
|
||||
use dom::node::ElementNodeTypeId;
|
||||
use servo_util::str::DOMString;
|
||||
use dom::virtualmethods::VirtualMethods;
|
||||
|
||||
use servo_util::str::{AutoLpa, DOMString, LengthOrPercentageOrAuto};
|
||||
use servo_util::str;
|
||||
use std::cell::Cell;
|
||||
use string_cache::Atom;
|
||||
|
||||
#[jstraceable]
|
||||
#[must_root]
|
||||
#[privatize]
|
||||
pub struct HTMLTableCellElement {
|
||||
htmlelement: HTMLElement,
|
||||
width: Cell<LengthOrPercentageOrAuto>,
|
||||
}
|
||||
|
||||
impl HTMLTableCellElementDerived for EventTarget {
|
||||
|
@ -32,16 +39,58 @@ impl HTMLTableCellElementDerived for EventTarget {
|
|||
impl HTMLTableCellElement {
|
||||
pub fn new_inherited(type_id: ElementTypeId, tag_name: DOMString, prefix: Option<DOMString>, document: JSRef<Document>) -> HTMLTableCellElement {
|
||||
HTMLTableCellElement {
|
||||
htmlelement: HTMLElement::new_inherited(type_id, tag_name, prefix, document)
|
||||
htmlelement: HTMLElement::new_inherited(type_id, tag_name, prefix, document),
|
||||
width: Cell::new(AutoLpa)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn htmlelement<'a>(&'a self) -> &'a HTMLElement {
|
||||
pub fn htmlelement(&self) -> &HTMLElement {
|
||||
&self.htmlelement
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HTMLTableCellElementHelpers {
|
||||
fn get_width(&self) -> LengthOrPercentageOrAuto;
|
||||
}
|
||||
|
||||
impl HTMLTableCellElementHelpers for HTMLTableCellElement {
|
||||
fn get_width(&self) -> LengthOrPercentageOrAuto {
|
||||
self.width.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLTableCellElement> {
|
||||
fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> {
|
||||
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
|
||||
Some(htmlelement as &VirtualMethods)
|
||||
}
|
||||
|
||||
fn after_set_attr(&self, name: &Atom, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.after_set_attr(name, value.clone()),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match name.as_slice() {
|
||||
"width" => self.width.set(str::parse_length(value.as_slice())),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn before_remove_attr(&self, name: &Atom, value: DOMString) {
|
||||
match self.super_type() {
|
||||
Some(ref s) => s.before_remove_attr(name, value),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match name.as_slice() {
|
||||
"width" => self.width.set(AutoLpa),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflectable for HTMLTableCellElement {
|
||||
fn reflector<'a>(&'a self) -> &'a Reflector {
|
||||
self.htmlelement.reflector()
|
||||
|
|
|
@ -19,6 +19,7 @@ use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementCast;
|
|||
use dom::bindings::codegen::InheritTypes::HTMLOptionElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLSelectElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLStyleElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLTableCellElementCast;
|
||||
use dom::bindings::codegen::InheritTypes::HTMLTextAreaElementCast;
|
||||
use dom::bindings::js::JSRef;
|
||||
use dom::element::Element;
|
||||
|
@ -37,6 +38,8 @@ use dom::element::HTMLOptGroupElementTypeId;
|
|||
use dom::element::HTMLOptionElementTypeId;
|
||||
use dom::element::HTMLSelectElementTypeId;
|
||||
use dom::element::HTMLStyleElementTypeId;
|
||||
use dom::element::HTMLTableDataCellElementTypeId;
|
||||
use dom::element::HTMLTableHeaderCellElementTypeId;
|
||||
use dom::element::HTMLTextAreaElementTypeId;
|
||||
use dom::event::Event;
|
||||
use dom::htmlanchorelement::HTMLAnchorElement;
|
||||
|
@ -54,6 +57,7 @@ use dom::htmloptgroupelement::HTMLOptGroupElement;
|
|||
use dom::htmloptionelement::HTMLOptionElement;
|
||||
use dom::htmlselectelement::HTMLSelectElement;
|
||||
use dom::htmlstyleelement::HTMLStyleElement;
|
||||
use dom::htmltablecellelement::HTMLTableCellElement;
|
||||
use dom::htmltextareaelement::HTMLTextAreaElement;
|
||||
use dom::node::{Node, NodeHelpers, ElementNodeTypeId};
|
||||
|
||||
|
@ -193,6 +197,11 @@ pub fn vtable_for<'a>(node: &'a JSRef<'a, Node>) -> &'a VirtualMethods + 'a {
|
|||
let element: &'a JSRef<'a, HTMLStyleElement> = HTMLStyleElementCast::to_borrowed_ref(node).unwrap();
|
||||
element as &'a VirtualMethods + 'a
|
||||
}
|
||||
ElementNodeTypeId(HTMLTableDataCellElementTypeId) |
|
||||
ElementNodeTypeId(HTMLTableHeaderCellElementTypeId) => {
|
||||
let element: &'a JSRef<'a, HTMLTableCellElement> = HTMLTableCellElementCast::to_borrowed_ref(node).unwrap();
|
||||
element as &'a VirtualMethods + 'a
|
||||
}
|
||||
ElementNodeTypeId(HTMLTextAreaElementTypeId) => {
|
||||
let element: &'a JSRef<'a, HTMLTextAreaElement> = HTMLTextAreaElementCast::to_borrowed_ref(node).unwrap();
|
||||
element as &'a VirtualMethods + 'a
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue