+2012-02-13 Brian Grinstead <briangrinstead@gmail.com>
+
+ Web Inspector: Add colorpicker functionality to color swatches in Styles Sidebar
+ https://bugs.webkit.org/show_bug.cgi?id=71262
+
+ Reviewed by Pavel Feldman.
+
+ * English.lproj/localizedStrings.js:
+ * WebCore.gypi:
+ * WebCore.vcproj/WebCore.vcproj:
+ * inspector/front-end/Settings.js:
+ * inspector/front-end/Spectrum.js: Added.
+ (WebInspector.Spectrum.hueDrag):
+ (WebInspector.Spectrum.colorDrag):
+ (WebInspector.Spectrum.alphaDrag):
+ (WebInspector.Spectrum):
+ (WebInspector.Spectrum.hsvaToRGBA):
+ (WebInspector.Spectrum.rgbaToHSVA):
+ (WebInspector.Spectrum.draggable.prevent):
+ (WebInspector.Spectrum.draggable.move):
+ (WebInspector.Spectrum.draggable.start):
+ (WebInspector.Spectrum.draggable.stop):
+ (WebInspector.Spectrum.draggable):
+ (WebInspector.Spectrum.prototype.set color):
+ (WebInspector.Spectrum.prototype.get color):
+ (WebInspector.Spectrum.prototype.get outputColorFormat):
+ (WebInspector.Spectrum.prototype.get colorHueOnly):
+ (WebInspector.Spectrum.prototype.set displayText):
+ (WebInspector.Spectrum.prototype._onchange):
+ (WebInspector.Spectrum.prototype._updateHelperLocations):
+ (WebInspector.Spectrum.prototype._updateUI):
+ (WebInspector.Spectrum.prototype.toggle):
+ (WebInspector.Spectrum.prototype.show):
+ (WebInspector.Spectrum.prototype.reposition):
+ (WebInspector.Spectrum.prototype.hide):
+ * inspector/front-end/StylesSidebarPane.js:
+ (WebInspector.StylesSidebarPane):
+ (WebInspector.StylePropertyTreeElement.prototype.updateTitle.):
+ * inspector/front-end/WebKit.qrc:
+ * inspector/front-end/inspector.css:
+ (.swatch):
+ (.swatch-inner):
+ (.spectrum-container):
+ (.spectrum-top):
+ (.spectrum-color):
+ (.spectrum-hue):
+ (.spectrum-fill):
+ (.spectrum-range-container):
+ (.spectrum-range-container *):
+ (.spectrum-range-container label):
+ (.spectrum-range-container input):
+ (.swatch, .spectrum-dragger, .spectrum-slider):
+ (.spectrum-sat):
+ (.spectrum-val):
+ (.spectrum-dragger):
+ (.spectrum-slider):
+ * inspector/front-end/inspector.html:
+
2012-02-15 Kenneth Rohde Christiansen <kenneth@webkit.org>
[Qt] Be smarter with tile usages during tiling
--- /dev/null
+/*
+ * Copyright (C) 2011 Brian Grinstead 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE 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 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.Spectrum = function(container)
+{
+ this._popover = new WebInspector.Popover();
+ this._popover.element.addEventListener("mousedown", stopPropagation, false);
+
+ this._containerElement = document.createElement('div');
+ this._containerElement.className = "spectrum-container";
+
+ var topElement = this._containerElement.createChild("div", "spectrum-top");
+ topElement.createChild("div", "spectrum-fill");
+
+ var topInnerElement = topElement.createChild("div", "spectrum-top-inner fill");
+ this._draggerElement = topInnerElement.createChild("div", "spectrum-color");
+ this._dragHelperElement = this._draggerElement.createChild("div", "spectrum-sat fill").createChild("div", "spectrum-val fill").createChild("div", "spectrum-dragger");
+
+ this._sliderElement = topInnerElement.createChild("div", "spectrum-hue");
+ this.slideHelper = this._sliderElement.createChild("div", "spectrum-slider");
+
+ var rangeContainer = this._containerElement.createChild("div", "spectrum-range-container");
+ var alphaLabel = rangeContainer.createChild("label");
+ alphaLabel.textContent = WebInspector.UIString("alpha: ");
+
+ this._alphaElement = rangeContainer.createChild("input", "spectrum-range");
+ this._alphaElement.setAttribute("type", "range");
+ this._alphaElement.setAttribute("min", "0");
+ this._alphaElement.setAttribute("max", "100");
+ this._alphaElement.addEventListener("change", alphaDrag.bind(this), false);
+
+ var swatchElement = document.createElement("span");
+ swatchElement.className = "swatch";
+ this._swatchInnerElement = swatchElement.createChild("span", "swatch-inner");
+
+ var displayContainer = rangeContainer.createChild("div");
+
+ var colorLabel = displayContainer.createChild("label");
+ colorLabel.textContent = WebInspector.UIString("color: ");
+
+ displayContainer.appendChild(swatchElement);
+
+ this._displayElement = displayContainer.createChild("span");
+
+ WebInspector.Spectrum.draggable(this._sliderElement, hueDrag.bind(this));
+ WebInspector.Spectrum.draggable(this._draggerElement, colorDrag.bind(this));
+
+ function hueDrag(element, dragX, dragY)
+ {
+ this.hsv[0] = (dragY / this.slideHeight);
+
+ this._onchange();
+ }
+
+ function colorDrag(element, dragX, dragY)
+ {
+ this.hsv[1] = dragX / this.dragWidth;
+ this.hsv[2] = (this.dragHeight - dragY) / this.dragHeight;
+
+ this._onchange();
+ }
+
+ function alphaDrag()
+ {
+ this.hsv[3] = this._alphaElement.value / 100;
+
+ this._onchange();
+ }
+
+ this._hideProxy = this.hide.bind(this);
+};
+
+WebInspector.Spectrum.Events = {
+ ColorChanged: "ColorChanged",
+ Hidden: "Hidden"
+};
+
+WebInspector.Spectrum.hsvaToRGBA = function(h, s, v, a)
+{
+ var r, g, b;
+
+ var i = Math.floor(h * 6);
+ var f = h * 6 - i;
+ var p = v * (1 - s);
+ var q = v * (1 - f * s);
+ var t = v * (1 - (1 - f) * s);
+
+ switch(i % 6) {
+ case 0:
+ r = v, g = t, b = p;
+ break;
+ case 1:
+ r = q, g = v, b = p;
+ break;
+ case 2:
+ r = p, g = v, b = t;
+ break;
+ case 3:
+ r = p, g = q, b = v;
+ break;
+ case 4:
+ r = t, g = p, b = v;
+ break;
+ case 5:
+ r = v, g = p, b = q;
+ break;
+ }
+
+ return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), a];
+};
+
+WebInspector.Spectrum.rgbaToHSVA = function(r, g, b, a)
+{
+ r = r / 255;
+ g = g / 255;
+ b = b / 255;
+
+ var max = Math.max(r, g, b);
+ var min = Math.min(r, g, b);
+ var h;
+ var s;
+ var v = max;
+
+ var d = max - min;
+ s = max ? d / max : 0;
+
+ if(max === min) {
+ // Achromatic.
+ h = 0;
+ } else {
+ switch(max) {
+ case r:
+ h = (g - b) / d + (g < b ? 6 : 0);
+ break;
+ case g:
+ h = (b - r) / d + 2;
+ break;
+ case b:
+ h = (r - g) / d + 4;
+ break;
+ }
+ h /= 6;
+ }
+ return [h, s, v, a];
+};
+
+//FIXME: migrate to WebInspector.elementDragStart
+WebInspector.Spectrum.draggable = function(element, onmove, onstart, onstop) {
+
+ var doc = document;
+ var dragging;
+ var offset;
+ var scrollOffset;
+ var maxHeight;
+ var maxWidth;
+
+ function prevent(e)
+ {
+ if (e.stopPropagation)
+ e.stopPropagation();
+
+ if (e.preventDefault)
+ e.preventDefault();
+ }
+
+ function move(e)
+ {
+ if (dragging) {
+ var dragX = Math.max(0, Math.min(e.pageX - offset.left + scrollOffset.left, maxWidth));
+ var dragY = Math.max(0, Math.min(e.pageY - offset.top + scrollOffset.top, maxHeight));
+
+ if (onmove)
+ onmove(element, dragX, dragY);
+ }
+ }
+
+ function start(e)
+ {
+ var rightClick = e.which ? (e.which === 3) : (e.button === 2);
+
+ if (!rightClick && !dragging) {
+
+ if (onstart)
+ onstart(element, e)
+
+ dragging = true;
+ maxHeight = element.clientHeight;
+ maxWidth = element.clientWidth;
+
+ scrollOffset = element.scrollOffset();
+ offset = element.totalOffset();
+
+ doc.addEventListener("selectstart", prevent, false);
+ doc.addEventListener("dragstart", prevent, false);
+ doc.addEventListener("mousemove", move, false);
+ doc.addEventListener("mouseup", stop, false);
+
+ move(e);
+ prevent(e);
+ }
+ }
+
+ function stop(e)
+ {
+ if (dragging) {
+ doc.removeEventListener("selectstart", prevent, false);
+ doc.removeEventListener("dragstart", prevent, false);
+ doc.removeEventListener("mousemove", move, false);
+ doc.removeEventListener("mouseup", stop, false);
+
+ if (onstop)
+ onstop(element, e);
+ }
+
+ dragging = false;
+ }
+
+ element.addEventListener("mousedown", start, false);
+};
+
+WebInspector.Spectrum.prototype = {
+ set color(color)
+ {
+ var rgba = (color.rgba || color.rgb).slice(0);
+
+ if (rgba.length === 3)
+ rgba[3] = 1;
+
+ this.hsv = WebInspector.Spectrum.rgbaToHSVA(rgba[0], rgba[1], rgba[2], rgba[3]);
+ },
+
+ get color()
+ {
+ var rgba = WebInspector.Spectrum.hsvaToRGBA(this.hsv[0], this.hsv[1], this.hsv[2], this.hsv[3]);
+ var color;
+
+ if (rgba[3] === 1)
+ color = WebInspector.Color.fromRGB(rgba[0], rgba[1], rgba[2]);
+ else
+ color = WebInspector.Color.fromRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
+
+ var colorValue = color.toString(this.outputColorFormat);
+ if (!colorValue)
+ colorValue = color.toString(); // this.outputColorFormat can be invalid for current color (e.g. "nickname").
+ return new WebInspector.Color(colorValue);
+ },
+
+ get outputColorFormat()
+ {
+ var cf = WebInspector.StylesSidebarPane.ColorFormat;
+ var format = this._originalFormat;
+
+ if (this.hsv[3] === 1) {
+ // Simplify transparent formats.
+ if (format === cf.RGBA)
+ format = cf.RGB;
+ else if (format === cf.HSLA)
+ format = cf.HSL;
+ } else {
+ // Everything except HSL(A) should be returned as RGBA if transparency is involved.
+ if (format === cf.HSL || format === cf.HSLA)
+ format = cf.HSLA;
+ else
+ format = cf.RGBA;
+ }
+
+ return format;
+ },
+
+ get colorHueOnly()
+ {
+ var rgba = WebInspector.Spectrum.hsvaToRGBA(this.hsv[0], 1, 1, 1);
+ return WebInspector.Color.fromRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
+ },
+
+ set displayText(text)
+ {
+ this._displayElement.textContent = text;
+ },
+
+ _onchange: function()
+ {
+ this._updateUI();
+ this.dispatchEventToListeners(WebInspector.Spectrum.Events.ColorChanged, this.color);
+ },
+
+ _updateHelperLocations: function()
+ {
+ var h = this.hsv[0];
+ var s = this.hsv[1];
+ var v = this.hsv[2];
+
+ // Where to show the little circle that displays your current selected color.
+ var dragX = s * this.dragWidth;
+ var dragY = this.dragHeight - (v * this.dragHeight);
+
+ dragX = Math.max(-this._dragHelperElementHeight,
+ Math.min(this.dragWidth - this._dragHelperElementHeight, dragX - this._dragHelperElementHeight));
+ dragY = Math.max(-this._dragHelperElementHeight,
+ Math.min(this.dragHeight - this._dragHelperElementHeight, dragY - this._dragHelperElementHeight));
+
+ this._dragHelperElement.positionAt(dragX, dragY);
+
+ // Where to show the bar that displays your current selected hue.
+ var slideY = (h * this.slideHeight) - this.slideHelperHeight;
+ this.slideHelper.style.top = slideY + "px";
+
+ this._alphaElement.value = this.hsv[3] * 100;
+ },
+
+ _updateUI: function()
+ {
+ this._updateHelperLocations();
+
+ var rgb = (this.color.rgba || this.color.rgb).slice(0);
+
+ if (rgb.length === 3)
+ rgb[3] = 1;
+
+ var rgbHueOnly = this.colorHueOnly.rgb;
+
+ var flatColor = "rgb(" + rgbHueOnly[0] + ", " + rgbHueOnly[1] + ", " + rgbHueOnly[2] + ")";
+ var fullColor = "rgba(" + rgb[0] + ", " + rgb[1] + ", " + rgb[2] + ", " + rgb[3] + ")";
+
+ this._draggerElement.style.backgroundColor = flatColor;
+ this._swatchInnerElement.style.backgroundColor = fullColor;
+
+ this._alphaElement.value = this.hsv[3] * 100;
+ },
+
+ toggle: function(element, color, format)
+ {
+ if (this._isShown)
+ this.hide();
+ else
+ this.show(element, color, format);
+
+ return this._isShown;
+ },
+
+ show: function(element, color, format)
+ {
+ if (this._isShown)
+ return;
+
+ this._isShown = true;
+ this.reposition(element);
+
+ document.addEventListener("mousedown", this._hideProxy);
+ window.addEventListener("blur", this._hideProxy);
+
+ this.slideHeight = this._sliderElement.offsetHeight;
+ this.dragWidth = this._draggerElement.offsetWidth;
+ this.dragHeight = this._draggerElement.offsetHeight;
+ this._dragHelperElementHeight = this._dragHelperElement.offsetHeight / 2;
+ this.slideHelperHeight = this.slideHelper.offsetHeight / 2;
+
+ this.color = color;
+ this._originalFormat = format || color.format;
+
+ this._updateUI();
+ },
+
+ reposition: function(element)
+ {
+ this._popover.show(this._containerElement, element);
+ },
+
+ hide: function()
+ {
+ delete this._isShown;
+ this._popover.hide();
+
+ document.removeEventListener("mousedown", this._hideProxy);
+ window.removeEventListener("blur", this._hideProxy);
+
+ this.dispatchEventToListeners(WebInspector.Spectrum.Events.Hidden);
+
+ // Only want to allow one instance to be open at a time, so clear out any
+ // existing event listeners.
+ this.removeAllListeners();
+ }
+};
+
+WebInspector.Spectrum.prototype.__proto__ = WebInspector.Object.prototype;
this._sectionsContainer = document.createElement("div");
this.bodyElement.appendChild(this._sectionsContainer);
+ if (Preferences.useSpectrum)
+ this._spectrum = new WebInspector.Spectrum();
+
WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetOrMediaQueryResultChanged, this);
WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.MediaQueryResultChanged, this._styleSheetOrMediaQueryResultChanged, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributesModified, this);
return document.createTextNode(text);
}
+ var format = getFormat();
+ var hasColorpicker = self._parentPane;
+ var spectrum = hasColorpicker ? self._parentPane._spectrum : null;
+
var swatchElement = document.createElement("span");
- swatchElement.title = WebInspector.UIString("Click to change color format");
- swatchElement.className = "swatch";
- swatchElement.style.setProperty("background-color", text);
-
- swatchElement.addEventListener("click", changeColorDisplay, false);
- swatchElement.addEventListener("dblclick", function(event) { event.stopPropagation() }, false);
-
- var format;
- var formatSetting = WebInspector.settings.colorFormat.get();
- if (formatSetting === cf.Original)
- format = cf.Original;
- else if (color.nickname)
- format = cf.Nickname;
- else if (formatSetting === cf.RGB)
- format = (color.simple ? cf.RGB : cf.RGBA);
- else if (formatSetting === cf.HSL)
- format = (color.simple ? cf.HSL : cf.HSLA);
- else if (color.simple)
- format = (color.hasShortHex() ? cf.ShortHEX : cf.HEX);
+ var swatchInnerElement = swatchElement.createChild("span", "swatch-inner");
+ if (hasColorpicker)
+ swatchElement.title = WebInspector.UIString("Click to open a colorpicker");
else
- format = cf.RGBA;
+ swatchElement.title = WebInspector.UIString("Click to change color format");
+
+ swatchElement.className = "swatch";
+
+ swatchElement.addEventListener("mousedown", stopPropagation, false);
+ swatchElement.addEventListener("click", swatchClick, false);
+ swatchElement.addEventListener("dblclick", stopPropagation, false);
+
+ swatchInnerElement.style.backgroundColor = text;
+
+ var scrollerElement = hasColorpicker ? self._parentPane._computedStylePane.element.parentElement : null;
+
+ function spectrumChange(e)
+ {
+ color = e.data;
+
+ var colorString = color.toString();
+
+ colorValueElement.textContent = colorString;
+ spectrum.displayText = colorString;
+ swatchInnerElement.style.backgroundColor = colorString;
+
+ self.applyStyleText(nameElement.textContent + ": " + valueElement.textContent, false, false, false);
+ }
+
+ function spectrumHide()
+ {
+ scrollerElement.removeEventListener("scroll", repositionSpectrum, false);
+ self.applyStyleText(nameElement.textContent + ": " + valueElement.textContent, true, true, false);
+ spectrum.removeEventListener(WebInspector.Spectrum.Events.ColorChanged, spectrumChange);
+ spectrum.removeEventListener(WebInspector.Spectrum.Events.Hidden, spectrumHide);
+
+ delete self._parentPane._isEditingStyle;
+ }
+
+ function repositionSpectrum()
+ {
+ spectrum.reposition(swatchElement);
+ }
+
+ function swatchClick(e)
+ {
+ // Alt + click toggles color formats.
+ // Click opens colorpicker, only if the element is not in computed styles section.
+
+ if (!spectrum || e.altKey)
+ changeColorDisplay(e);
+ else if (hasColorpicker) {
+ var isShown = spectrum.toggle(swatchElement, color, format);
+
+ if (isShown) {
+ spectrum.displayText = color.toString(format);
+ self._parentPane._isEditingStyle = true;
+ spectrum.addEventListener(WebInspector.Spectrum.Events.ColorChanged, spectrumChange);
+ spectrum.addEventListener(WebInspector.Spectrum.Events.Hidden, spectrumHide);
+
+ scrollerElement.addEventListener("scroll", repositionSpectrum, false);
+ }
+ }
+ }
+
+ function getFormat()
+ {
+ var format;
+ var formatSetting = WebInspector.settings.colorFormat.get();
+ if (formatSetting === cf.Original)
+ format = cf.Original;
+ else if (color.nickname)
+ format = cf.Nickname;
+ else if (formatSetting === cf.RGB)
+ format = (color.simple ? cf.RGB : cf.RGBA);
+ else if (formatSetting === cf.HSL)
+ format = (color.simple ? cf.HSL : cf.HSLA);
+ else if (color.simple)
+ format = (color.hasShortHex() ? cf.ShortHEX : cf.HEX);
+ else
+ format = cf.RGBA;
+
+ return format;
+ }
var colorValueElement = document.createElement("span");
colorValueElement.textContent = color.toString(format);