summaryrefslogtreecommitdiff
path: root/Source/WebInspectorUI/UserInterface/Views/InlineSwatch.js
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Views/InlineSwatch.js')
-rw-r--r--Source/WebInspectorUI/UserInterface/Views/InlineSwatch.js340
1 files changed, 340 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Views/InlineSwatch.js b/Source/WebInspectorUI/UserInterface/Views/InlineSwatch.js
new file mode 100644
index 000000000..85a09d59d
--- /dev/null
+++ b/Source/WebInspectorUI/UserInterface/Views/InlineSwatch.js
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2016 Devin Rousso <dcrousso+webkit@gmail.com>. 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+WebInspector.InlineSwatch = class InlineSwatch extends WebInspector.Object
+{
+ constructor(type, value, readOnly)
+ {
+ super();
+
+ this._type = type;
+
+ this._swatchElement = document.createElement("span");
+ this._swatchElement.classList.add("inline-swatch", this._type.split("-").lastValue);
+
+ switch (this._type) {
+ case WebInspector.InlineSwatch.Type.Color:
+ this._swatchElement.title = WebInspector.UIString("Click to select a color. Shift-click to switch color formats.");
+ break;
+ case WebInspector.InlineSwatch.Type.Gradient:
+ this._swatchElement.title = WebInspector.UIString("Edit custom gradient");
+ break;
+ case WebInspector.InlineSwatch.Type.Bezier:
+ this._swatchElement.title = WebInspector.UIString("Edit “cubic-bezier“ function");
+ break;
+ case WebInspector.InlineSwatch.Type.Spring:
+ this._swatchElement.title = WebInspector.UIString("Edit “spring“ function");
+ break;
+ case WebInspector.InlineSwatch.Type.Variable:
+ this._swatchElement.title = WebInspector.UIString("View variable value");
+ break;
+ default:
+ WebInspector.reportInternalError(`Unknown InlineSwatch type "${type}"`);
+ break;
+ }
+
+ this._boundSwatchElementClicked = null;
+ if (!readOnly) {
+ this._boundSwatchElementClicked = this._swatchElementClicked.bind(this);
+ this._swatchElement.addEventListener("click", this._boundSwatchElementClicked);
+ if (this._type === WebInspector.InlineSwatch.Type.Color)
+ this._swatchElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this));
+ }
+
+ this._swatchInnerElement = this._swatchElement.createChild("span");
+
+ this._value = value || this._fallbackValue();
+ this._valueEditor = null;
+
+ this._updateSwatch();
+ }
+
+ // Public
+
+ get element()
+ {
+ return this._swatchElement;
+ }
+
+ get value()
+ {
+ return this._value;
+ }
+
+ set value(value)
+ {
+ this._value = value;
+ this._updateSwatch(true);
+ }
+
+ // Popover delegate
+
+ didDismissPopover(popover)
+ {
+ if (!this._valueEditor)
+ return;
+
+ if (typeof this._valueEditor.removeListeners === "function")
+ this._valueEditor.removeListeners();
+
+ if (this._boundSwatchElementClicked)
+ this._swatchElement.addEventListener("click", this._boundSwatchElementClicked);
+
+ this.dispatchEventToListeners(WebInspector.InlineSwatch.Event.Deactivated);
+ }
+
+ // Private
+
+ _fallbackValue()
+ {
+ switch (this._type) {
+ case WebInspector.InlineSwatch.Type.Bezier:
+ return WebInspector.CubicBezier.fromString("linear");
+ case WebInspector.InlineSwatch.Type.Gradient:
+ return WebInspector.Gradient.fromString("linear-gradient(transparent, transparent)");
+ case WebInspector.InlineSwatch.Type.Spring:
+ return WebInspector.Spring.fromString("1 100 10 0");
+ case WebInspector.InlineSwatch.Type.Color:
+ return WebInspector.Color.fromString("white");
+ default:
+ return null;
+ }
+ }
+
+ _updateSwatch(dontFireEvents)
+ {
+ if (this._type === WebInspector.InlineSwatch.Type.Color || this._type === WebInspector.InlineSwatch.Type.Gradient)
+ this._swatchInnerElement.style.background = this._value ? this._value.toString() : null;
+
+ if (!dontFireEvents)
+ this.dispatchEventToListeners(WebInspector.InlineSwatch.Event.ValueChanged, {value: this._value});
+ }
+
+ _swatchElementClicked(event)
+ {
+ this.dispatchEventToListeners(WebInspector.InlineSwatch.Event.BeforeClicked);
+
+ if (this._type === WebInspector.InlineSwatch.Type.Color && event.shiftKey && this._value) {
+ let nextFormat = this._value.nextFormat();
+ console.assert(nextFormat);
+ if (!nextFormat)
+ return;
+
+ this._value.format = nextFormat;
+ this._updateSwatch();
+ return;
+ }
+
+ let bounds = WebInspector.Rect.rectFromClientRect(this._swatchElement.getBoundingClientRect());
+ let popover = new WebInspector.Popover(this);
+
+ popover.windowResizeHandler = () => {
+ let bounds = WebInspector.Rect.rectFromClientRect(this._swatchElement.getBoundingClientRect());
+ popover.present(bounds.pad(2), [WebInspector.RectEdge.MIN_X]);
+ };
+
+ this._valueEditor = null;
+ if (this._type === WebInspector.InlineSwatch.Type.Color) {
+ this._valueEditor = new WebInspector.ColorPicker;
+ this._valueEditor.addEventListener(WebInspector.ColorPicker.Event.ColorChanged, this._valueEditorValueDidChange, this);
+ this._valueEditor.addEventListener(WebInspector.ColorPicker.Event.FormatChanged, (event) => popover.update());
+ } else if (this._type === WebInspector.InlineSwatch.Type.Gradient) {
+ this._valueEditor = new WebInspector.GradientEditor;
+ this._valueEditor.addEventListener(WebInspector.GradientEditor.Event.GradientChanged, this._valueEditorValueDidChange, this);
+ this._valueEditor.addEventListener(WebInspector.GradientEditor.Event.ColorPickerToggled, (event) => popover.update());
+ } else if (this._type === WebInspector.InlineSwatch.Type.Bezier) {
+ this._valueEditor = new WebInspector.BezierEditor;
+ this._valueEditor.addEventListener(WebInspector.BezierEditor.Event.BezierChanged, this._valueEditorValueDidChange, this);
+ } else if (this._type === WebInspector.InlineSwatch.Type.Spring) {
+ this._valueEditor = new WebInspector.SpringEditor;
+ this._valueEditor.addEventListener(WebInspector.SpringEditor.Event.SpringChanged, this._valueEditorValueDidChange, this);
+ } else if (this._type === WebInspector.InlineSwatch.Type.Variable) {
+ this._valueEditor = {};
+
+ this._valueEditor.element = document.createElement("div");
+ this._valueEditor.element.classList.add("inline-swatch-variable-popover");
+
+ this._valueEditor.codeMirror = WebInspector.CodeMirrorEditor.create(this._valueEditor.element, {
+ mode: "css",
+ readOnly: "nocursor",
+ });
+ this._valueEditor.codeMirror.on("update", () => {
+ popover.update();
+ });
+ }
+
+ if (!this._valueEditor)
+ return;
+
+ popover.content = this._valueEditor.element;
+ popover.present(bounds.pad(2), [WebInspector.RectEdge.MIN_X]);
+
+ if (this._boundSwatchElementClicked)
+ this._swatchElement.removeEventListener("click", this._boundSwatchElementClicked);
+
+ this.dispatchEventToListeners(WebInspector.InlineSwatch.Event.Activated);
+
+ let value = this._value || this._fallbackValue();
+ if (this._type === WebInspector.InlineSwatch.Type.Color)
+ this._valueEditor.color = value;
+ else if (this._type === WebInspector.InlineSwatch.Type.Gradient)
+ this._valueEditor.gradient = value;
+ else if (this._type === WebInspector.InlineSwatch.Type.Bezier)
+ this._valueEditor.bezier = value;
+ else if (this._type === WebInspector.InlineSwatch.Type.Spring)
+ this._valueEditor.spring = value;
+ else if (this._type === WebInspector.InlineSwatch.Type.Variable)
+ this._valueEditor.codeMirror.setValue(value);
+ }
+
+ _valueEditorValueDidChange(event)
+ {
+ if (this._type === WebInspector.InlineSwatch.Type.Color)
+ this._value = event.data.color;
+ else if (this._type === WebInspector.InlineSwatch.Type.Gradient)
+ this._value = event.data.gradient;
+ else if (this._type === WebInspector.InlineSwatch.Type.Bezier)
+ this._value = event.data.bezier;
+ else if (this._type === WebInspector.InlineSwatch.Type.Spring)
+ this._value = event.data.spring;
+
+ this._updateSwatch();
+ }
+
+ _handleContextMenuEvent(event)
+ {
+ if (!this._value)
+ return;
+
+ let contextMenu = WebInspector.ContextMenu.createFromEvent(event);
+
+ if (this._value.isKeyword() && this._value.format !== WebInspector.Color.Format.Keyword) {
+ contextMenu.appendItem(WebInspector.UIString("Format: Keyword"), () => {
+ this._value.format = WebInspector.Color.Format.Keyword;
+ this._updateSwatch();
+ });
+ }
+
+ let hexInfo = this._getNextValidHEXFormat();
+ if (hexInfo) {
+ contextMenu.appendItem(hexInfo.title, () => {
+ this._value.format = hexInfo.format;
+ this._updateSwatch();
+ });
+ }
+
+ if (this._value.simple && this._value.format !== WebInspector.Color.Format.HSL) {
+ contextMenu.appendItem(WebInspector.UIString("Format: HSL"), () => {
+ this._value.format = WebInspector.Color.Format.HSL;
+ this._updateSwatch();
+ });
+ } else if (this._value.format !== WebInspector.Color.Format.HSLA) {
+ contextMenu.appendItem(WebInspector.UIString("Format: HSLA"), () => {
+ this._value.format = WebInspector.Color.Format.HSLA;
+ this._updateSwatch();
+ });
+ }
+
+ if (this._value.simple && this._value.format !== WebInspector.Color.Format.RGB) {
+ contextMenu.appendItem(WebInspector.UIString("Format: RGB"), () => {
+ this._value.format = WebInspector.Color.Format.RGB;
+ this._updateSwatch();
+ });
+ } else if (this._value.format !== WebInspector.Color.Format.RGBA) {
+ contextMenu.appendItem(WebInspector.UIString("Format: RGBA"), () => {
+ this._value.format = WebInspector.Color.Format.RGBA;
+ this._updateSwatch();
+ });
+ }
+ }
+
+ _getNextValidHEXFormat()
+ {
+ if (this._type !== WebInspector.InlineSwatch.Type.Color)
+ return false;
+
+ function hexMatchesCurrentColor(hexInfo) {
+ let nextIsSimple = hexInfo.format === WebInspector.Color.Format.ShortHEX || hexInfo.format === WebInspector.Color.Format.HEX;
+ if (nextIsSimple && !this._value.simple)
+ return false;
+
+ let nextIsShort = hexInfo.format === WebInspector.Color.Format.ShortHEX || hexInfo.format === WebInspector.Color.Format.ShortHEXAlpha;
+ if (nextIsShort && !this._value.canBeSerializedAsShortHEX())
+ return false;
+
+ return true;
+ }
+
+ const hexFormats = [
+ {
+ format: WebInspector.Color.Format.ShortHEX,
+ title: WebInspector.UIString("Format: Short Hex")
+ },
+ {
+ format: WebInspector.Color.Format.ShortHEXAlpha,
+ title: WebInspector.UIString("Format: Short Hex with Alpha")
+ },
+ {
+ format: WebInspector.Color.Format.HEX,
+ title: WebInspector.UIString("Format: Hex")
+ },
+ {
+ format: WebInspector.Color.Format.HEXAlpha,
+ title: WebInspector.UIString("Format: Hex with Alpha")
+ }
+ ];
+
+ let currentColorIsHEX = hexFormats.some((info) => info.format === this._value.format);
+
+ for (let i = 0; i < hexFormats.length; ++i) {
+ if (currentColorIsHEX && this._value.format !== hexFormats[i].format)
+ continue;
+
+ for (let j = ~~currentColorIsHEX; j < hexFormats.length; ++j) {
+ let nextIndex = (i + j) % hexFormats.length;
+ if (hexMatchesCurrentColor.call(this, hexFormats[nextIndex]))
+ return hexFormats[nextIndex];
+ }
+ return null;
+ }
+ return hexFormats[0];
+ }
+};
+
+WebInspector.InlineSwatch.Type = {
+ Color: "inline-swatch-type-color",
+ Gradient: "inline-swatch-type-gradient",
+ Bezier: "inline-swatch-type-bezier",
+ Spring: "inline-swatch-type-spring",
+ Variable: "inline-swatch-type-variable",
+};
+
+WebInspector.InlineSwatch.Event = {
+ BeforeClicked: "inline-swatch-before-clicked",
+ ValueChanged: "inline-swatch-value-changed",
+ Activated: "inline-swatch-activated",
+ Deactivated: "inline-swatch-deactivated",
+};