1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 * @extends {WebInspector.Object}
9 WebInspector.StylesPopoverHelper = function()
11 this._popover = new WebInspector.Popover();
12 this._popover.setCanShrink(false);
13 this._popover.setNoMargins(true);
14 this._popover.element.addEventListener("mousedown", consumeEvent, false);
16 this._hideProxy = this.hide.bind(this, true);
17 this._boundOnKeyDown = this._onKeyDown.bind(this);
18 this._repositionBound = this.reposition.bind(this);
19 this._boundFocusOut = this._onFocusOut.bind(this);
22 WebInspector.StylesPopoverHelper.prototype = {
24 * @param {!Event} event
26 _onFocusOut: function(event)
28 if (!event.relatedTarget || event.relatedTarget.isSelfOrDescendant(this._view.contentElement))
38 return this._popover.isShowing();
42 * @param {!WebInspector.Widget} view
43 * @param {!Element} anchorElement
44 * @param {function(boolean)=} hiddenCallback
46 show: function(view, anchorElement, hiddenCallback)
48 if (this._popover.isShowing()) {
49 if (this._anchorElement === anchorElement)
52 // Reopen the picker for another anchor element.
56 delete this._isHidden;
57 this._anchorElement = anchorElement;
59 this._hiddenCallback = hiddenCallback;
62 var document = this._popover.element.ownerDocument;
63 document.addEventListener("mousedown", this._hideProxy, false);
64 document.defaultView.addEventListener("resize", this._hideProxy, false);
65 this._view.contentElement.addEventListener("keydown", this._boundOnKeyDown, false);
67 this._scrollerElement = anchorElement.enclosingNodeOrSelfWithClass("style-panes-wrapper");
68 if (this._scrollerElement)
69 this._scrollerElement.addEventListener("scroll", this._repositionBound, false);
73 * @param {!Event=} event
75 reposition: function(event)
77 if (!this._previousFocusElement)
78 this._previousFocusElement = WebInspector.currentFocusElement();
79 // Unbind "blur" listener to avoid reenterability: |popover.showView| will hide the popover and trigger it synchronously.
80 this._view.contentElement.removeEventListener("focusout", this._boundFocusOut, false);
81 this._popover.showView(this._view, this._anchorElement);
82 this._view.contentElement.addEventListener("focusout", this._boundFocusOut, false);
83 WebInspector.setCurrentFocusElement(this._view.contentElement);
87 * @param {boolean=} commitEdit
89 hide: function(commitEdit)
93 var document = this._popover.element.ownerDocument;
94 this._isHidden = true;
97 if (this._scrollerElement)
98 this._scrollerElement.removeEventListener("scroll", this._repositionBound, false);
100 document.removeEventListener("mousedown", this._hideProxy, false);
101 document.defaultView.removeEventListener("resize", this._hideProxy, false);
103 if (this._hiddenCallback)
104 this._hiddenCallback.call(null, !!commitEdit);
106 WebInspector.setCurrentFocusElement(this._previousFocusElement);
107 delete this._previousFocusElement;
108 delete this._anchorElement;
111 this._view.contentElement.removeEventListener("keydown", this._boundOnKeyDown, false);
112 this._view.contentElement.removeEventListener("focusout", this._boundFocusOut, false);
118 * @param {!Event} event
120 _onKeyDown: function(event)
122 if (event.keyIdentifier === "Enter") {
127 if (event.keyIdentifier === "U+001B") { // Escape key
133 __proto__: WebInspector.Object.prototype
138 * @param {!WebInspector.StylePropertyTreeElement} treeElement
139 * @param {!WebInspector.StylesPopoverHelper} stylesPopoverHelper
140 * @param {string} text
142 WebInspector.BezierPopoverIcon = function(treeElement, stylesPopoverHelper, text)
144 this._treeElement = treeElement;
145 this._stylesPopoverHelper = stylesPopoverHelper;
146 this._createDOM(text);
148 this._boundBezierChanged = this._bezierChanged.bind(this);
151 WebInspector.BezierPopoverIcon.prototype = {
157 return this._element;
161 * @param {string} text
163 _createDOM: function(text)
165 this._element = createElement("nobr");
166 this._element.title = WebInspector.UIString("Open cubic bezier editor");
168 this._iconElement = this._element.createSVGChild("svg", "popover-icon bezier-icon");
169 this._iconElement.setAttribute("height", 10);
170 this._iconElement.setAttribute("width", 10);
171 this._iconElement.addEventListener("click", this._iconClick.bind(this), false);
172 var g = this._iconElement.createSVGChild("g");
173 var path = g.createSVGChild("path");
174 path.setAttribute("d", "M2,8 C2,3 8,7 8,2");
176 this._bezierValueElement = this._element.createChild("span");
177 this._bezierValueElement.textContent = text;
181 * @param {!Event} event
183 _iconClick: function(event)
186 if (this._stylesPopoverHelper.isShowing()) {
187 this._stylesPopoverHelper.hide(true);
191 this._bezierEditor = new WebInspector.BezierEditor();
192 var geometry = WebInspector.Geometry.CubicBezier.parse(this._bezierValueElement.textContent);
193 this._bezierEditor.setBezier(geometry);
194 this._bezierEditor.addEventListener(WebInspector.BezierEditor.Events.BezierChanged, this._boundBezierChanged);
195 this._stylesPopoverHelper.show(this._bezierEditor, this._iconElement, this._onPopoverHidden.bind(this));
197 this._originalPropertyText = this._treeElement.property.propertyText;
198 this._treeElement.parentPane().setEditingStyle(true);
202 * @param {!WebInspector.Event} event
204 _bezierChanged: function(event)
206 this._bezierValueElement.textContent = /** @type {string} */ (event.data);
207 this._treeElement.applyStyleText(this._treeElement.renderedPropertyText(), false);
211 * @param {boolean} commitEdit
213 _onPopoverHidden: function(commitEdit)
215 this._bezierEditor.removeEventListener(WebInspector.BezierEditor.Events.BezierChanged, this._boundBezierChanged);
216 delete this._bezierEditor;
218 var propertyText = commitEdit ? this._treeElement.renderedPropertyText() : this._originalPropertyText;
219 this._treeElement.applyStyleText(propertyText, true);
220 this._treeElement.parentPane().setEditingStyle(false);
221 delete this._originalPropertyText;
227 * @param {!WebInspector.StylePropertyTreeElement} treeElement
228 * @param {!WebInspector.StylesPopoverHelper} stylesPopoverHelper
229 * @param {string} colorText
231 WebInspector.ColorSwatchPopoverIcon = function(treeElement, stylesPopoverHelper, colorText)
233 this._treeElement = treeElement;
234 this._stylesPopoverHelper = stylesPopoverHelper;
236 this._swatch = WebInspector.ColorSwatch.create();
237 this._swatch.setColorText(colorText);
238 this._swatch.setFormat(WebInspector.ColorSwatchPopoverIcon._colorFormat(this._swatch.color()));
239 var shiftClickMessage = WebInspector.UIString("Shift + Click to change color format.");
240 this._swatch.iconElement().title = WebInspector.UIString("Open color picker. %s", shiftClickMessage);
241 this._swatch.iconElement().addEventListener("click", this._iconClick.bind(this));
242 this._contrastColor = null;
244 this._boundSpectrumChanged = this._spectrumChanged.bind(this);
248 * @param {!WebInspector.Color} color
249 * @return {!WebInspector.Color.Format}
251 WebInspector.ColorSwatchPopoverIcon._colorFormat = function(color)
253 const cf = WebInspector.Color.Format;
255 var formatSetting = WebInspector.moduleSetting("colorFormat").get();
256 if (formatSetting === cf.Original)
257 format = cf.Original;
258 else if (formatSetting === cf.RGB)
259 format = (color.hasAlpha() ? cf.RGBA : cf.RGB);
260 else if (formatSetting === cf.HSL)
261 format = (color.hasAlpha() ? cf.HSLA : cf.HSL);
262 else if (!color.hasAlpha())
263 format = (color.canBeShortHex() ? cf.ShortHEX : cf.HEX);
270 WebInspector.ColorSwatchPopoverIcon.prototype = {
280 * @param {!WebInspector.Color} color
282 setContrastColor: function(color)
284 this._contrastColor = color;
286 this._spectrum.setContrastColor(this._contrastColor);
290 * @param {!Event} event
292 _iconClick: function(event)
295 if (this._stylesPopoverHelper.isShowing()) {
296 this._stylesPopoverHelper.hide(true);
300 var color = this._swatch.color();
301 var format = this._swatch.format();
302 if (format === WebInspector.Color.Format.Original)
303 format = color.format();
304 this._spectrum = new WebInspector.Spectrum();
305 this._spectrum.setColor(color, format);
306 if (this._contrastColor)
307 this._spectrum.setContrastColor(this._contrastColor);
309 this._spectrum.addEventListener(WebInspector.Spectrum.Events.SizeChanged, this._spectrumResized, this);
310 this._spectrum.addEventListener(WebInspector.Spectrum.Events.ColorChanged, this._boundSpectrumChanged);
311 this._stylesPopoverHelper.show(this._spectrum, this._swatch.iconElement(), this._onPopoverHidden.bind(this));
313 this._originalPropertyText = this._treeElement.property.propertyText;
314 this._treeElement.parentPane().setEditingStyle(true);
318 * @param {!WebInspector.Event} event
320 _spectrumResized: function(event)
322 this._stylesPopoverHelper.reposition();
326 * @param {!WebInspector.Event} event
328 _spectrumChanged: function(event)
330 var colorString = /** @type {string} */ (event.data);
331 this._swatch.setColorText(colorString);
332 this._treeElement.applyStyleText(this._treeElement.renderedPropertyText(), false);
336 * @param {boolean} commitEdit
338 _onPopoverHidden: function(commitEdit)
340 this._spectrum.removeEventListener(WebInspector.Spectrum.Events.ColorChanged, this._boundSpectrumChanged);
341 delete this._spectrum;
343 var propertyText = commitEdit ? this._treeElement.renderedPropertyText() : this._originalPropertyText;
344 this._treeElement.applyStyleText(propertyText, true);
345 this._treeElement.parentPane().setEditingStyle(false);
346 delete this._originalPropertyText;