Diff
Modified: trunk/LayoutTests/ChangeLog (207110 => 207111)
--- trunk/LayoutTests/ChangeLog 2016-10-11 12:47:58 UTC (rev 207110)
+++ trunk/LayoutTests/ChangeLog 2016-10-11 12:52:28 UTC (rev 207111)
@@ -1,3 +1,20 @@
+2016-10-11 Antoine Quint <[email protected]>
+
+ [Modern Media Controls] Buttons container
+ https://bugs.webkit.org/show_bug.cgi?id=163238
+ <rdar://problem/28701864>
+
+ Reviewed by Dean Jackson.
+
+ Adding tests for the new ButtonsContainer class.
+
+ * media/modern-media-controls/buttons-container/buttons-container-buttons-property-expected.txt: Added.
+ * media/modern-media-controls/buttons-container/buttons-container-buttons-property.html: Added.
+ * media/modern-media-controls/buttons-container/buttons-container-constructor-expected.txt: Added.
+ * media/modern-media-controls/buttons-container/buttons-container-constructor.html: Added.
+ * media/modern-media-controls/buttons-container/buttons-container-layout-expected.txt: Added.
+ * media/modern-media-controls/buttons-container/buttons-container-layout.html: Added.
+
2016-10-11 Youenn Fablet <[email protected]>
[Fetch API] Support Request cache mode
Added: trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-buttons-property-expected.txt (0 => 207111)
--- trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-buttons-property-expected.txt (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-buttons-property-expected.txt 2016-10-11 12:52:28 UTC (rev 207111)
@@ -0,0 +1,12 @@
+Testing ButtonsContainer buttons property.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS container.buttons.length is 3
+PASS container.children.length is 3
+PASS container.buttons is container.children
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-buttons-property.html (0 => 207111)
--- trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-buttons-property.html (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-buttons-property.html 2016-10-11 12:52:28 UTC (rev 207111)
@@ -0,0 +1,33 @@
+<link rel="stylesheet" href="" type="text/css" media="screen">
+<link rel="stylesheet" href="" type="text/css" media="screen">
+<script src=""
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<body>
+<script type="text/_javascript_">
+
+description("Testing <code>ButtonsContainer</code> buttons property.");
+
+window.jsTestIsAsync = true;
+
+const container = new ButtonsContainer({
+ margin: 10,
+ padding: 20
+});
+
+container.buttons = [new Button, new Button, new Button];
+
+scheduler.frameDidFire = function()
+{
+ shouldBe("container.buttons.length", "3");
+ shouldBe("container.children.length", "3");
+ shouldBe("container.buttons", "container.children");
+ finishJSTest();
+};
+
+</script>
+<script src=""
+</body>
Added: trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-constructor-expected.txt (0 => 207111)
--- trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-constructor-expected.txt (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-constructor-expected.txt 2016-10-11 12:52:28 UTC (rev 207111)
@@ -0,0 +1,20 @@
+Testing the ButtonsContainer constructor.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS defaultContainer.element.localName is "div"
+PASS defaultContainer.element.className.trim() is "buttons-container"
+PASS defaultContainer.margin is 0
+PASS defaultContainer.padding is 0
+PASS defaultContainer.buttons is []
+PASS containerWithParameters.element.localName is "div"
+PASS containerWithParameters.element.classList.contains('buttons-container') is true
+PASS containerWithParameters.element.classList.contains('foo') is true
+PASS containerWithParameters.margin is 10
+PASS containerWithParameters.padding is 20
+PASS containerWithParameters.buttons is buttons
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-constructor.html (0 => 207111)
--- trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-constructor.html (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-constructor.html 2016-10-11 12:52:28 UTC (rev 207111)
@@ -0,0 +1,37 @@
+<link rel="stylesheet" href="" type="text/css" media="screen">
+<link rel="stylesheet" href="" type="text/css" media="screen">
+<script src=""
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<body>
+<script type="text/_javascript_">
+
+description("Testing the <code>ButtonsContainer</code> constructor.");
+
+const defaultContainer = new ButtonsContainer;
+shouldBeEqualToString("defaultContainer.element.localName", "div");
+shouldBeEqualToString("defaultContainer.element.className.trim()", "buttons-container");
+shouldBe("defaultContainer.margin", "0");
+shouldBe("defaultContainer.padding", "0");
+shouldBe("defaultContainer.buttons", "[]");
+
+const buttons = [new Button, new Button];
+const containerWithParameters = new ButtonsContainer({
+ margin: 10,
+ padding: 20,
+ buttons: buttons,
+ cssClassName: "foo"
+});
+shouldBeEqualToString("containerWithParameters.element.localName", "div");
+shouldBeTrue("containerWithParameters.element.classList.contains('buttons-container')");
+shouldBeTrue("containerWithParameters.element.classList.contains('foo')");
+shouldBe("containerWithParameters.margin", "10");
+shouldBe("containerWithParameters.padding", "20");
+shouldBe("containerWithParameters.buttons", "buttons");
+
+</script>
+<script src=""
+</body>
Added: trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-layout-expected.txt (0 => 207111)
--- trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-layout-expected.txt (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-layout-expected.txt 2016-10-11 12:52:28 UTC (rev 207111)
@@ -0,0 +1,17 @@
+Testing ButtonsContainer layout.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS container.children.length is 3
+PASS container.children[0] is tenPtWideButton
+PASS container.children[1] is twentyPtWideButton
+PASS container.children[2] is thirtyPtWideButton
+PASS tenPtWideButton.x is 20
+PASS twentyPtWideButton.x is 40
+PASS thirtyPtWideButton.x is 70
+PASS container.width is 120
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-layout.html (0 => 207111)
--- trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-layout.html (rev 0)
+++ trunk/LayoutTests/media/modern-media-controls/buttons-container/buttons-container-layout.html 2016-10-11 12:52:28 UTC (rev 207111)
@@ -0,0 +1,51 @@
+<link rel="stylesheet" href="" type="text/css" media="screen">
+<link rel="stylesheet" href="" type="text/css" media="screen">
+<script src=""
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<script src="" type="text/_javascript_"></script>
+<body>
+<script type="text/_javascript_">
+
+description("Testing <code>ButtonsContainer</code> layout.");
+
+const tenPtWideButton = new Button;
+tenPtWideButton.width = 10;
+
+const twentyPtWideButton = new Button;
+twentyPtWideButton.width = 20;
+
+const thirtyPtWideButton = new Button;
+thirtyPtWideButton.width = 30;
+
+// Should be disregarded by the container.
+const disabledButton = new Button;
+disabledButton.width = 15;
+disabledButton.enabled = false;
+
+// Should be disregarded by the container.
+const droppedButton = new Button;
+droppedButton.width = 25;
+droppedButton.dropped = true;
+
+const container = new ButtonsContainer({
+ margin: 10,
+ padding: 20,
+ buttons: [tenPtWideButton, disabledButton, twentyPtWideButton, droppedButton, thirtyPtWideButton]
+});
+
+container.layout();
+shouldBe("container.children.length", "3");
+shouldBe("container.children[0]", "tenPtWideButton");
+shouldBe("container.children[1]", "twentyPtWideButton");
+shouldBe("container.children[2]", "thirtyPtWideButton");
+shouldBe("tenPtWideButton.x", "20");
+shouldBe("twentyPtWideButton.x", "40");
+shouldBe("thirtyPtWideButton.x", "70");
+shouldBe("container.width", "120");
+
+</script>
+<script src=""
+</body>
Modified: trunk/Source/WebCore/ChangeLog (207110 => 207111)
--- trunk/Source/WebCore/ChangeLog 2016-10-11 12:47:58 UTC (rev 207110)
+++ trunk/Source/WebCore/ChangeLog 2016-10-11 12:52:28 UTC (rev 207111)
@@ -1,3 +1,48 @@
+2016-10-11 Antoine Quint <[email protected]>
+
+ [Modern Media Controls] Buttons container
+ https://bugs.webkit.org/show_bug.cgi?id=163238
+ <rdar://problem/28701864>
+
+ Reviewed by Dean Jackson.
+
+ We add a new ButtonsContainer class which contains a group of Button objects
+ and positions them based on the provided padding and margin between buttons.
+ Buttons that aren't enabled or marked as dropped are not added to the tree of
+ LayoutNodes, and thus the DOM.
+
+ Additionally, we fix a few issues we found while working on tests for ButtonsContainer
+ where LayoutNodes would schedule layout callbacks even when they would not do any work
+ during the layout callback due to not resetting the `needsLayout` flag to false and
+ removing any scheduled tasks when a layout was completed.
+
+ Finally, we fix a few style issues that had not been caught so far and an unused
+ `size` property on IconButton.
+
+ Tests: media/modern-media-controls/buttons-container/buttons-container-buttons-property.html
+ media/modern-media-controls/buttons-container/buttons-container-constructor.html
+ media/modern-media-controls/buttons-container/buttons-container-layout.html
+
+ * Modules/modern-media-controls/controls/airplay-button.js:
+ (AirplayButton.prototype.set on):
+ (AirplayButton):
+ * Modules/modern-media-controls/controls/buttons-container.css:
+ (.buttons-container):
+ * Modules/modern-media-controls/controls/buttons-container.js:
+ (ButtonsContainer.prototype.get buttons):
+ (ButtonsContainer.prototype.set buttons):
+ (ButtonsContainer.prototype.layout):
+ * Modules/modern-media-controls/controls/icon-button.js:
+ * Modules/modern-media-controls/controls/layout-node.js:
+ (LayoutNode.prototype.set needsLayout):
+ (LayoutNode.prototype.markDirtyProperty):
+ (LayoutNode.prototype._markNodeManipulation):
+ (LayoutNode.prototype._updateDirtyState):
+ (performScheduledLayout):
+ (elementFromString):
+ * Modules/modern-media-controls/controls/scheduler.js:
+ (const.scheduler.new.prototype.unscheduleLayout):
+
2016-10-11 Youenn Fablet <[email protected]>
[Fetch API] Support Request cache mode
Added: trunk/Source/WebCore/Modules/modern-media-controls/controls/buttons-container.css (0 => 207111)
--- trunk/Source/WebCore/Modules/modern-media-controls/controls/buttons-container.css (rev 0)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/buttons-container.css 2016-10-11 12:52:28 UTC (rev 207111)
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.buttons-container {
+ position: absolute;
+ height: 100%;
+}
Added: trunk/Source/WebCore/Modules/modern-media-controls/controls/buttons-container.js (0 => 207111)
--- trunk/Source/WebCore/Modules/modern-media-controls/controls/buttons-container.js (rev 0)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/buttons-container.js 2016-10-11 12:52:28 UTC (rev 207111)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+class ButtonsContainer extends LayoutNode
+{
+
+ constructor({ buttons = [], padding = 0, margin = 0, cssClassName = "" } = {})
+ {
+ super(`<div class="buttons-container ${cssClassName}">`);
+
+ this.margin = margin;
+ this.padding = padding;
+ this.buttons = buttons;
+ }
+
+ // Public
+
+ get buttons()
+ {
+ return this._buttons;
+ }
+
+ set buttons(buttons)
+ {
+ if (!Array.isArray(buttons))
+ return;
+
+ this._buttons = buttons;
+ this.needsLayout = true;
+ }
+
+ layout()
+ {
+ super.layout();
+
+ const children = [];
+ let x = this.padding;
+
+ this._buttons.forEach(button => {
+ if (!button.enabled || button.dropped)
+ return;
+ button.x = x;
+ x += button.width + this.margin;
+ children.push(button);
+ });
+
+ if (children.length)
+ this.width = x - this.margin + this.padding;
+ else
+ this.width = this.padding * 2;
+
+ this.children = children;
+ }
+
+}
Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/icon-button.js (207110 => 207111)
--- trunk/Source/WebCore/Modules/modern-media-controls/controls/icon-button.js 2016-10-11 12:47:58 UTC (rev 207110)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/icon-button.js 2016-10-11 12:52:28 UTC (rev 207111)
@@ -39,8 +39,6 @@
if (!!iconName)
this.iconName = iconName;
-
- this.size = { width: 0, height: 0 };
}
// Public
Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/layout-node.js (207110 => 207111)
--- trunk/Source/WebCore/Modules/modern-media-controls/controls/layout-node.js 2016-10-11 12:47:58 UTC (rev 207110)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/layout-node.js 2016-10-11 12:52:28 UTC (rev 207111)
@@ -95,7 +95,7 @@
if (this.needsLayout === flag)
return;
- this._needsLayout = true;
+ this._needsLayout = flag;
this._updateDirtyState();
}
@@ -167,7 +167,8 @@
return this._parent.removeChild(this);
}
- markDirtyProperty(propertyName) {
+ markDirtyProperty(propertyName)
+ {
const hadProperty = this._dirtyProperties.has(propertyName);
this._dirtyProperties.add(propertyName);
@@ -217,17 +218,22 @@
// Private
- _markNodeManipulation(manipulation) {
+ _markNodeManipulation(manipulation)
+ {
this._pendingDOMManipulation = manipulation;
this._updateDirtyState();
}
- _updateDirtyState() {
+ _updateDirtyState()
+ {
if (this.needsLayout) {
dirtyNodes.add(this);
scheduler.scheduleLayout(performScheduledLayout);
- } else
- dirtyNodes.delete(node);
+ } else {
+ dirtyNodes.delete(this);
+ if (dirtyNodes.size === 0)
+ scheduler.unscheduleLayout(performScheduledLayout);
+ }
}
_updateChildren()
@@ -255,15 +261,21 @@
Addition: 2
};
-function performScheduledLayout() {
- dirtyNodes.forEach(node => node.layout());
+function performScheduledLayout()
+{
+ dirtyNodes.forEach(node => {
+ node.needsLayout = false;
+ node.layout()
+ });
dirtyNodes.clear();
+ scheduler.unscheduleLayout(performScheduledLayout);
nodesRequiringChildrenUpdate.forEach(node => node._updateChildren());
nodesRequiringChildrenUpdate.clear();
}
-function elementFromString(elementString) {
+function elementFromString(elementString)
+{
const element = document.createElement("div");
element.innerHTML = elementString;
return element.firstElementChild;
Modified: trunk/Source/WebCore/Modules/modern-media-controls/controls/scheduler.js (207110 => 207111)
--- trunk/Source/WebCore/Modules/modern-media-controls/controls/scheduler.js 2016-10-11 12:47:58 UTC (rev 207110)
+++ trunk/Source/WebCore/Modules/modern-media-controls/controls/scheduler.js 2016-10-11 12:52:28 UTC (rev 207111)
@@ -19,6 +19,14 @@
this._requestFrameIfNeeded();
}
+ unscheduleLayout(callback)
+ {
+ if (typeof callback !== "function")
+ return;
+
+ this._layoutCallbacks.delete(callback);
+ }
+
// Private
_requestFrameIfNeeded()