Move Event States to |Element|.

Conceptually they belong there, rather than on |Node|.

Fixes #7934.
This commit is contained in:
Bobby Holley 2015-10-07 20:02:00 -07:00
parent 628c2a0432
commit 75ec093334
14 changed files with 251 additions and 262 deletions

View file

@ -47,7 +47,7 @@ use dom::htmltableelement::HTMLTableElement;
use dom::htmltextareaelement::RawLayoutHTMLTextAreaElementHelpers;
use dom::namednodemap::NamedNodeMap;
use dom::node::{CLICK_IN_PROGRESS, LayoutNodeHelpers, Node};
use dom::node::{NodeDamage, NodeFlags, SEQUENTIALLY_FOCUSABLE};
use dom::node::{NodeDamage, SEQUENTIALLY_FOCUSABLE};
use dom::node::{document_from_node, window_from_node};
use dom::nodelist::NodeList;
use dom::virtualmethods::{VirtualMethods, vtable_for};
@ -62,7 +62,7 @@ use selectors::parser::{AttrSelector, NamespaceConstraint};
use smallvec::VecLike;
use std::ascii::AsciiExt;
use std::borrow::{Cow, ToOwned};
use std::cell::Ref;
use std::cell::{Cell, Ref};
use std::default::Default;
use std::mem;
use std::sync::Arc;
@ -76,6 +76,25 @@ use style::values::specified::{self, CSSColor, CSSRGBA};
use url::UrlParser;
use util::str::{DOMString, LengthOrPercentageOrAuto};
bitflags! {
#[doc = "Element Event States."]
#[derive(JSTraceable, HeapSizeOf)]
flags EventState: u8 {
#[doc = "The mouse is down on this element. \
(https://html.spec.whatwg.org/multipage/#selector-active). \
FIXME(#7333): set/unset this when appropriate"]
const IN_ACTIVE_STATE = 0x01,
#[doc = "This element has focus."]
const IN_FOCUS_STATE = 0x02,
#[doc = "The mouse is hovering over this element."]
const IN_HOVER_STATE = 0x04,
#[doc = "Content is enabled (and can be disabled)."]
const IN_ENABLED_STATE = 0x08,
#[doc = "Content is disabled."]
const IN_DISABLED_STATE = 0x10,
}
}
#[dom_struct]
pub struct Element {
node: Node,
@ -87,6 +106,7 @@ pub struct Element {
style_attribute: DOMRefCell<Option<PropertyDeclarationBlock>>,
attr_list: MutNullableHeap<JS<NamedNodeMap>>,
class_list: MutNullableHeap<JS<DOMTokenList>>,
event_state: Cell<EventState>,
}
impl PartialEq for Element {
@ -115,16 +135,16 @@ impl Element {
pub fn new_inherited(local_name: DOMString,
namespace: Namespace, prefix: Option<DOMString>,
document: &Document) -> Element {
Element::new_inherited_with_flags(NodeFlags::new(), local_name,
Element::new_inherited_with_state(EventState::empty(), local_name,
namespace, prefix, document)
}
pub fn new_inherited_with_flags(flags: NodeFlags, local_name: DOMString,
pub fn new_inherited_with_state(state: EventState, local_name: DOMString,
namespace: Namespace, prefix: Option<DOMString>,
document: &Document)
-> Element {
Element {
node: Node::new_inherited_with_flags(flags, document),
node: Node::new_inherited(document),
local_name: Atom::from_slice(&local_name),
namespace: namespace,
prefix: prefix,
@ -133,6 +153,7 @@ impl Element {
class_list: Default::default(),
id_attribute: DOMRefCell::new(None),
style_attribute: DOMRefCell::new(None),
event_state: Cell::new(state),
}
}
@ -224,6 +245,8 @@ pub trait LayoutElementHelpers {
fn namespace(&self) -> &Namespace;
fn get_checked_state_for_layout(&self) -> bool;
fn get_indeterminate_state_for_layout(&self) -> bool;
fn get_event_state_for_layout(&self) -> EventState;
}
impl LayoutElementHelpers for LayoutJS<Element> {
@ -574,6 +597,14 @@ impl LayoutElementHelpers for LayoutJS<Element> {
None => false,
}
}
#[inline]
#[allow(unsafe_code)]
fn get_event_state_for_layout(&self) -> EventState {
unsafe {
(*self.unsafe_get()).event_state.get()
}
}
}
#[derive(PartialEq, Eq, Copy, Clone, HeapSizeOf)]
@ -827,7 +858,7 @@ impl Element {
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement)) |
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) |
NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement)) => {
node.get_disabled_state()
self.get_disabled_state()
}
// TODO:
// an optgroup element that has a disabled attribute
@ -1624,31 +1655,30 @@ impl<'a> ::selectors::Element for Root<Element> {
fn get_namespace<'b>(&'b self) -> &'b Namespace {
self.namespace()
}
fn get_hover_state(&self) -> bool {
let node = NodeCast::from_ref(&**self);
node.get_hover_state()
Element::get_hover_state(self)
}
fn get_active_state(&self) -> bool {
let node = NodeCast::from_ref(&**self);
node.get_active_state()
Element::get_active_state(self)
}
fn get_focus_state(&self) -> bool {
// TODO: Also check whether the top-level browsing context has the system focus,
// and whether this element is a browsing context container.
// https://html.spec.whatwg.org/multipage/#selector-focus
let node = NodeCast::from_ref(&**self);
node.get_focus_state()
Element::get_focus_state(self)
}
fn get_id(&self) -> Option<Atom> {
self.id_attribute.borrow().clone()
}
fn get_disabled_state(&self) -> bool {
let node = NodeCast::from_ref(&**self);
node.get_disabled_state()
Element::get_disabled_state(self)
}
fn get_enabled_state(&self) -> bool {
let node = NodeCast::from_ref(&**self);
node.get_enabled_state()
Element::get_enabled_state(self)
}
fn get_checked_state(&self) -> bool {
let input_element: Option<&HTMLInputElement> = HTMLInputElementCast::to_ref(&**self);
@ -1816,6 +1846,58 @@ impl Element {
// Step 7
self.set_click_in_progress(false);
}
fn set_state(&self, which: EventState, value: bool) {
let mut state = self.event_state.get();
match value {
true => state.insert(which),
false => state.remove(which),
};
self.event_state.set(state);
let node = NodeCast::from_ref(self);
node.dirty(NodeDamage::NodeStyleDamaged);
}
pub fn get_active_state(&self) -> bool {
self.event_state.get().contains(IN_ACTIVE_STATE)
}
pub fn set_active_state(&self, value: bool) {
self.set_state(IN_ACTIVE_STATE, value)
}
pub fn get_focus_state(&self) -> bool {
self.event_state.get().contains(IN_FOCUS_STATE)
}
pub fn set_focus_state(&self, value: bool) {
self.set_state(IN_FOCUS_STATE, value)
}
pub fn get_hover_state(&self) -> bool {
self.event_state.get().contains(IN_HOVER_STATE)
}
pub fn set_hover_state(&self, value: bool) {
self.set_state(IN_HOVER_STATE, value)
}
pub fn get_enabled_state(&self) -> bool {
self.event_state.get().contains(IN_ENABLED_STATE)
}
pub fn set_enabled_state(&self, value: bool) {
self.set_state(IN_ENABLED_STATE, value)
}
pub fn get_disabled_state(&self) -> bool {
self.event_state.get().contains(IN_DISABLED_STATE)
}
pub fn set_disabled_state(&self, value: bool) {
self.set_state(IN_DISABLED_STATE, value)
}
}
#[derive(Clone, Copy, PartialEq)]