Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Unified Diff: sky/specs/style.md

Issue 805083008: Specs: More cleanup around the proposed style model to make things more consistent. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sky/specs/apis.md ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/specs/style.md
diff --git a/sky/specs/style.md b/sky/specs/style.md
index 331582a73d53ad49b3a4e9c7ece52a118b041bef..214750bcc861a016ec8b5d3f334309b2ec44e330 100644
--- a/sky/specs/style.md
+++ b/sky/specs/style.md
@@ -227,43 +227,49 @@ StyleNode
|
+-- NumericStyleValue
| |
- | +-- AnimatableNumericStyleValue
+ | +-- AnimatableNumericStyleValue*
|
+-- LengthStyleValue
| |
- | +-- AnimatableLengthStyleValue
+ | +-- AnimatableLengthStyleValue*
| |
| +-- PixelLengthStyleValue
| |
- | +-- EmLengthStyleValue
+ | +-- EmLengthStyleValue*
| |
- | +-- VHLengthStyleValue
+ | +-- VHLengthStyleValue*
| |
- | +-- CalcLengthStyleValue
+ | +-- CalcLengthStyleValue*
|
+-- ColorStyleValue
| |
| +-- RGBColorStyleValue
| |
- | +-- AnimatableColorStyleValue
+ | +-- AnimatableColorStyleValue*
|
- +-- AbstractStringStyleValue
+ +-- AbstractOpaqueStyleValue
| |
| +-- IdentifierStyleValue
| | |
- | | +-- AnimatableIdentifierStyleValue
+ | | +-- AnimatableIdentifierStyleValue*
| |
- | +-- URLStyleValue
+ | +-- URLStyleValue*
| | |
- | | +-- AnimatableURLStyleValue
+ | | +-- AnimatableURLStyleValue*
| |
- | +-- StringStyleValue
- | |
- | +-- AnimatableStringStyleValue
+ | +-- StringStyleValue*
+ | | |
+ | | +-- AnimatableStringStyleValue*
+ | |
+ | +-- ObjectStyleValue
|
- +-- PrimitiveValuesListStyleValue
+ +-- PrimitiveValuesListStyleValue*
*/
+```
+
+The types marked with * in the list above are not part of sky:core.
+```javascript
abstract class StyleNode {
abstract void markDirty();
}
@@ -284,8 +290,8 @@ class StyleValueResolverSettings {
}
class Property : StyleNode {
- constructor (StyleDeclaration parentNode, PropertyHandle property, AbstractStyleValue? initialValue = null);
- readonly attribute StyleDeclaration parentNode;
+ constructor (AbstractStyleDeclaration parentNode, PropertyHandle property, AbstractStyleValue? initialValue = null);
+ readonly attribute AbstractStyleDeclaration parentNode;
readonly attribute PropertyHandle property;
readonly attribute AbstractStyleValue value;
@@ -315,10 +321,43 @@ abstract class LengthStyleValue : AbstractStyleValue {
}
class PixelLengthStyleValue : LengthStyleValue {
+ constructor(StyleNode parentNode, Float number);
+ readonly attribute Float value;
Float resolve(PropertyHandle property, RenderNode node, StyleValueResolverSettings? settings = null);
}
-// ...
+typedef Color Float; // TODO(ianh): figure out what Color should be
+class ColorStyleValue : LengthStyleValue {
+ constructor(StyleNode parentNode, Float red, Float green, Float blue, Float alpha);
+ // ... color API ...
+ Color resolve(PropertyHandle property, RenderNode node, StyleValueResolverSettings? settings = null);
+}
+
+class AbstractOpaqueStyleValue : AbstractStyleValue {
+ abstract constructor(StyleNode parentNode, any value);
+ readonly attribute any value;
+ any resolve(PropertyHandle property, RenderNode node, StyleValueResolverSettings? settings = null);
+ // returns value
+}
+
+class IdentifierStyleValue : AbstractOpaqueStyleValue {
+ constructor(StyleNode parentNode, String value);
+ // calls superclass constructor
+}
+
+/*
+class AnimatableIdentifierStyleValue : AbstractOpaqueStyleValue {
+ constructor(StyleNode parentNode, String value, String newValue, AnimationFunction player);
+ readonly attribute String newValue;
+ readonly attribute AnimationFunction player;
+ any resolve(PropertyHandle property, RenderNode node, StyleValueResolverSettings? settings = null);
+}
+*/
+
+class ObjectStyleValue : AbstractOpaqueStyleValue {
+ constructor(StyleNode parentNode, any value);
+ // calls superclass constructor
+}
dictionary PropertySettings {
String name;
@@ -335,45 +374,65 @@ typedef PropertyHandle Integer;
PropertyHandle registerProperty(PropertySettings propertySettings);
// sky:core exports a bunch of style grammars so that people can extend them
-attribute StyleGrammar PositiveLengthOrInfinityStyleGrammar; // resolves to Float
-attribute StyleGrammar PositiveLengthOrAutoStyleGrammar; // resolves to Float or null
-attribute StyleGrammar PositiveLengthStyleGrammar; // resolves to Float
-attribute StyleGrammar NumberGrammar; // resolves to Float
-attribute StyleGrammar ColorGrammar; // resolves to object with 'red', 'green', 'blue', and 'alpha' properties each of which is a Float 0..1
-attribute StyleGrammar DisplayStyleGrammar; // resolves to null or LayoutManager constructor
+attribute StyleGrammar PositiveLengthOrInfinityStyleGrammar; // resolves to LengthStyleValue
+attribute StyleGrammar PositiveLengthOrAutoStyleGrammar; // resolves to LengthStyleValue or IdentifierStyleValue (with value 'auto')
+attribute StyleGrammar PositiveLengthStyleGrammar; // resolves to LengthStyleValue
+attribute StyleGrammar NumberGrammar; // resolves to NumericStyleValue
+attribute StyleGrammar ColorGrammar; // resolves to ColorStyleValue
+attribute StyleGrammar DisplayStyleGrammar; // resolves to ObjectStyleValue
```
Inline Styles
-------------
```javascript
-class StyleDeclarationList {
+abstract class AbstractStyleDeclarationList {
+ void addStyles(StyleDeclaration styles, String? pseudoElement = null); // O(1)
+ void removeStyles(StyleDeclaration styles, String? pseudoElement = null); // O(N) in number of declarations
+ Array<StyleDeclaration> getDeclarations(String? pseudoElement = null); // O(N) in number of declarations
+}
+
+class ElementStyleDeclarationList : AbstractStyleDeclarationList {
constructor (Element? element);
- // There are two batches of styles in a StyleDeclarationList.
+ // there are two batches of styles in an ElementStyleDeclarationList.
- // The first batch is the per-frame styles. These get cleared each
- // frame, after which all the matching rules in relevant <style> blocks
- // get added back in, followed by all the animation-derived rules.
- // Scripts can add styles themselves.
+ // the first batch is the per-frame styles; these get (conceptually)
+ // cleared each frame, after which all the matching rules in relevant
+ // <style> blocks get added back in, followed by all the animation-
+ // derived rules; scripts can also add styles themselves, but they are
+ // dropped after the next frame
void addFrameStyles(StyleDeclaration styles, String? pseudoElement = null); // O(1)
void clearFrameStyles();
- // The second batch is the persistent styles.
- // Once added, they remain forever until removed.
- void addPersistentStyles(StyleDeclaration styles, String? pseudoElement = null); // O(1)
- void removePersistentStyles(StyleDeclaration styles, String? pseudoElement = null); // O(N) in number of declarations
+ // the second batch is the persistent styles, which remain until removed;
+ // they are accessed via the AbstractStyleDeclarationList accessors
- // as StyleDeclaration are added and removed here, the StyleDeclarationList calls register(element) and
- // unregister(element) respectively on those StyleDeclaration objects, where element is the element that
- // was passed to the constructor, if not null
- // then, it calls element.renderNode.cascadedValueAdded/cascadedValueRemoved for each property on the object
+ // as StyleDeclarations are added and removed, the ElementStyleDeclarationList
+ // calls register(element) and unregister(element) respectively on those
+ // StyleDeclaration objects, where element is the element that was passed
+ // to the constructor, if not null
+ // then, it calls element.renderNode.cascadedValueAdded/cascadedValueRemoved
+ // for each property on the object
- // This returns all the frame styles followed by all the persistent styles, in insertion order.
- Array<StyleDeclaration> getDeclarations(String? pseudoElement = null); // O(N) in number of declarations
+ // the inherited getDeclarations() method returns all the frame
+ // styles followed by all the persistent styles, in insertion order
+}
+
+class RenderNodeStyleDeclarationList : AbstractStyleDeclarationList {
+ constructor (RenderNode? renderNode);
+
+ // as StyleDeclarations are added and removed, the RenderNodeStyleDeclarationList
+ // calls register(renderNode) and unregister(renderNode) respectively on those
+ // StyleDeclaration objects, where renderNode is the RenderNode that was passed
+ // to the constructor, if not null
+ // then, it calls renderNode.cascadedValueAdded/cascadedValueRemoved
+ // for each property on the object
}
class StyleDeclaration {
+ constructor ();
+
void markDirty(PropertyHandle property);
// this indicates that the cascaded value of the property thinks
// it will now have a different result (as opposed to the cascaded
@@ -381,11 +440,12 @@ class StyleDeclaration {
// invoke element.renderNode.cascadedValueDirty(property, pseudoElement); for each
// currently registered consumer element/pseudoElement pair
- void register(Element element, String? pseudoElement = null); // O(1)
- void unregister(Element element, String? pseudoElement = null); // O(N)
- // registers an element/pseudoElement pair with this StyleDeclaration so that when
- // a property/value on the style declaration is marked dirty, the element
- // is informed and can then clear its property cache
+ void register((Element or RenderNode) consumer, String? pseudoElement = null); // O(1)
+ void unregister((Element or RenderNode) consumer, String? pseudoElement = null); // O(N)
+ // registers an element/pseudoElement or renderNode/pseudoElement pair with
+ // this StyleDeclaration so that a property/value on the style declaration
+ // is marked dirty, the relevant render node is informed and can then update
+ // its property cache accordingly
getter AbstractStyleValue? (PropertyHandle property);
// looks up the Property object for /property/, and returns its value
@@ -420,11 +480,12 @@ class Rule {
}
```
-Each frame, at some defined point relative to requestAnimationFrame():
- - If a rule starts applying to an element, sky:core calls thatElement.style.add(rule.styles, rule.pseudoElement);
- - If a rule stops applying to an element, sky:core calls thatElement.style.remove(rule.styles, rule.pseudoElement);
-
-TODO(ianh): fix the above so that rule order is maintained
+Each frame, at some defined point relative to requestAnimationFrame(),
+if a Rule has started applying, or a Rule stopped applying, to an
+element, sky:core calls thatElement.style.clearFrameStyles() and then,
+for each Rule that now applies, calls
+thatElement.style.addFrameStyles() with the relevant StyleDeclaration
+and pseudoElement from each such Rule.
Cascade
@@ -453,8 +514,10 @@ When an Element or Text node is to be removed from its parent, and it
has a renderNode, and that renderNode has an ownerLayoutManager with
autoreap=false, then before actually removing the node, the node's
renderNode should be marked isGhost=true, and the relevant
-StyleDeclarationList should be flattened and the values stored on the
-RenderNode for use later.
+ElementStyleDeclarationList should be flattened and the values stored on
+the RenderNode's overrideStyles for use later. (Or we can just clone the
+StyleDeclarations directly without flattening. That would probably
+be faster.)
When an Element is to be removed from its parent, regardless of the
above, the node's renderNode attribute should be nulled out.
@@ -474,15 +537,20 @@ class RenderNode { // implemented in C++ with no virtual tables
// looking at the cached data for the given pseudoElement:
// if there's a cached value, return it
// otherwise, figure out which StyleValue we're going to be using, in this order:
- // - if we're isGhost, look out our cached declarations
- // - look at this element's StyleDeclarations for the given pseudo-element (if any)
- // - look at this element's StyleDeclarations with no pseudo-element
- // - if it's an inherited property and there's a parent
- // - call getProperty() on the parent
- // otherwise use the default value
+ // - look out our override declarations (first with the pseudo, if any, then without)
+ // - if there's an element:
+ // - look at this element's StyleDeclarations (first with the pseudo, if any, then without)
+ // - if it's an inherited property and there's a parent:
+ // - call getProperty() on the parent (without the pseudo)
+ // - use the default value
// resolve the StyleValue giving it the property and node in question
// cache the value, along with the StyleValueResolverSettings
+ readonly attribute RenderNodeStyleDeclarationList overrideStyles;
+ // mutable; initially empty
+ // this is used when isGhost is true, and can also be used more generally to
+ // override styles from the layout manager (e.g. to animate a new node into view)
+
private void cascadedValueAdded(PropertyHandle property, String? pseudoElement = null);
private void cascadedValueRemoved(PropertyHandle property, String? pseudoElement = null);
private void cascadedValueChanged(PropertyHandle property, String? pseudoElement = null);
@@ -500,6 +568,8 @@ class RenderNode { // implemented in C++ with no virtual tables
// - if the property is inherited:
// - call this.cascadedValueDirty(property, eachPseudoElement)
// - call eachChildRenderNode.cascadedValueDirty(property, null)
+ // (these four methods all do the same thing; they might get merged into one. For now
+ // they're separate in case we want to make them cleverer later.)
readonly attribute Boolean needsManager;
// means that a property with needsManager:true has changed on this node
@@ -590,13 +660,6 @@ class LayoutManager : EventTarget {
// if called from an adjustProperties() method during the property adjustment phase,
// replaces the value that getProperty() would return on that node with /value/
- virtual void adjustProperties();
- // called before layout; can call setProperty to set new values
- // note that this happens after the cascade so inheritance isn't applied to this new value
- // also note that the value you set is a post-computation value, not an AbstractStyleValue descendant
- // so e.g. you can have an AnimatableColorStyleValue, get its value, and push it into setProperty()
- // but you can't push the AnimatableColorStyleValue directly in, it won't do what you expect
-
void take(RenderNode victim); // sets victim.ownerLayoutManager = this;
// assert: victim hasn't been take()n yet during this layout
// assert: victim.needsLayout == true
@@ -757,8 +820,9 @@ dictionary Dimensions {
Paint
-----
-Sky has a list of RenderNodes that need painting.
-When a RenderNode is created, it's added to this list.
+Sky has a list of RenderNodes that need painting. When a RenderNode is
+created, it's added to this list. (See also needsPaint for another
+time it is added to the list.)
```javascript
callback void Painter (RenderNode node, RenderingSurface canvas);
@@ -798,40 +862,52 @@ StyleDeclaration objects as follows:
* ``script``
* ``content``
* ``title``
- These all add to themselves the same declaration with value:
+ These all add to themselves the same declaration as follows:
```javascript
-{ display: { value: null } }
+let d = new StyleDeclaration();
+d[pDisplay] = new ObjectStyleValue(null);
+this.style.addStyles(d);
```
* ``img``
- This adds to itself the declaration with value:
+ This adds to itself the declaration as follows:
```javascript
-{ display: { value: sky.ImageElementLayoutManager } }
+let d = new StyleDeclaration();
+d[pDisplay] = new ObjectStyleValue(ImageElementLayoutManager);
+this.style.addStyles(d);
```
* ``span``
* ``a``
- These all add to themselves the same declaration with value:
+ These all add to themselves the same declaration as follows:
```javascript
-{ display: { value: sky.InlineLayoutManager } }
+let d = new StyleDeclaration();
+d[pDisplay] = new ObjectStyleValue(InlineLayoutManager);
+this.style.addStyles(d);
```
* ``iframe``
- This adds to itself the declaration with value:
+ This adds to itself the declaration as follows:
```javascript
-{ display: { value: sky.IFrameElementLayoutManager } }
+let d = new StyleDeclaration();
+d[pDisplay] = new ObjectStyleValue(IFrameElementLayoutManager);
+this.style.addStyles(d);
```
* ``t``
- This adds to itself the declaration with value:
+ This adds to itself the declaration as follows:
```javascript
-{ display: { value: sky.ParagraphLayoutManager } }
+let d = new StyleDeclaration();
+d[pDisplay] = new ObjectStyleValue(ParagraphLayoutManager);
+this.style.addStyles(d);
```
* ``error``
- This adds to itself the declaration with value:
+ This adds to itself the declaration as follows:
```javascript
-{ display: { value: sky.ErrorLayoutManager } }
+let d = new StyleDeclaration();
+d[pDisplay] = new ObjectStyleValue(ErrorLayoutManager);
+this.style.addStyles(d);
```
The ``div`` element doesn't have any default styles.
@@ -839,4 +915,6 @@ The ``div`` element doesn't have any default styles.
These declarations are all shared between all the elements (so e.g. if
you reach in and change the declaration that was added to a ``title``
element, you're going to change the styles of all the other
-default-hidden elements).
+default-hidden elements). (In other words, in the code snippets above,
+the ``d`` variable is initialised in shared code, and only the
+addStyles() call is per-element.)
« no previous file with comments | « sky/specs/apis.md ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698