diff --git a/browser/devtools/jar.mn b/browser/devtools/jar.mn index 2e63d0f93a3..94363347a8f 100644 --- a/browser/devtools/jar.mn +++ b/browser/devtools/jar.mn @@ -141,6 +141,8 @@ browser.jar: content/browser/devtools/spectrum.css (shared/widgets/spectrum.css) content/browser/devtools/cubic-bezier-frame.xhtml (shared/widgets/cubic-bezier-frame.xhtml) content/browser/devtools/cubic-bezier.css (shared/widgets/cubic-bezier.css) + content/browser/devtools/filter-frame.xhtml (shared/widgets/filter-frame.xhtml) + content/browser/devtools/filter-widget.css (shared/widgets/filter-widget.css) content/browser/devtools/eyedropper.xul (eyedropper/eyedropper.xul) content/browser/devtools/eyedropper/crosshairs.css (eyedropper/crosshairs.css) content/browser/devtools/eyedropper/nocursor.css (eyedropper/nocursor.css) diff --git a/browser/devtools/shared/moz.build b/browser/devtools/shared/moz.build index 8db2ced3c9d..b558e789035 100644 --- a/browser/devtools/shared/moz.build +++ b/browser/devtools/shared/moz.build @@ -64,6 +64,7 @@ EXTRA_JS_MODULES.devtools.shared.widgets += [ 'widgets/CubicBezierPresets.js', 'widgets/CubicBezierWidget.js', 'widgets/FastListWidget.js', + 'widgets/FilterWidget.js', 'widgets/FlameGraph.js', 'widgets/Spectrum.js', 'widgets/TableWidget.js', diff --git a/browser/devtools/shared/widgets/FilterWidget.js b/browser/devtools/shared/widgets/FilterWidget.js new file mode 100644 index 00000000000..51c6a99d1f6 --- /dev/null +++ b/browser/devtools/shared/widgets/FilterWidget.js @@ -0,0 +1,720 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +/** + * This is a CSS Filter Editor widget used + * for Rule View's filter swatches + */ + +const EventEmitter = require("devtools/toolkit/event-emitter"); +const { Cu } = require("chrome"); +const { ViewHelpers } = Cu.import("resource:///modules/devtools/ViewHelpers.jsm", {}); +const STRINGS_URI = "chrome://browser/locale/devtools/filterwidget.properties"; +const L10N = new ViewHelpers.L10N(STRINGS_URI); + +const DEFAULT_FILTER_TYPE = "length"; +const UNIT_MAPPING = { + percentage: "%", + length: "px", + angle: "deg", + string: "" +}; + +const FAST_VALUE_MULTIPLIER = 10; +const SLOW_VALUE_MULTIPLIER = 0.1; +const DEFAULT_VALUE_MULTIPLIER = 1; + +const LIST_PADDING = 7; +const LIST_ITEM_HEIGHT = 32; + +const filterList = [ + { + "name": "blur", + "range": [0, Infinity], + "type": "length" + }, + { + "name": "brightness", + "range": [0, Infinity], + "type": "percentage" + }, + { + "name": "contrast", + "range": [0, Infinity], + "type": "percentage" + }, + { + "name": "drop-shadow", + "placeholder": L10N.getStr("dropShadowPlaceholder"), + "type": "string" + }, + { + "name": "grayscale", + "range": [0, 100], + "type": "percentage" + }, + { + "name": "hue-rotate", + "range": [0, 360], + "type": "angle" + }, + { + "name": "invert", + "range": [0, 100], + "type": "percentage" + }, + { + "name": "opacity", + "range": [0, 100], + "type": "percentage" + }, + { + "name": "saturate", + "range": [0, Infinity], + "type": "percentage" + }, + { + "name": "sepia", + "range": [0, 100], + "type": "percentage" + }, + { + "name": "url", + "placeholder": "example.svg#c1", + "type": "string" + } +]; + +/** + * A CSS Filter editor widget used to add/remove/modify + * filters. + * + * Normally, it takes a CSS filter value as input, parses it + * and creates the required elements / bindings. + * + * You can, however, use add/remove/update methods manually. + * See each method's comments for more details + * + * @param {nsIDOMNode} el + * The widget container. + * @param {String} value + * CSS filter value + */ +function CSSFilterEditorWidget(el, value = "") { + this.doc = el.ownerDocument; + this.win = this.doc.ownerGlobal; + this.el = el; + + this._addButtonClick = this._addButtonClick.bind(this); + this._removeButtonClick = this._removeButtonClick.bind(this); + this._mouseMove = this._mouseMove.bind(this); + this._mouseUp = this._mouseUp.bind(this); + this._mouseDown = this._mouseDown.bind(this); + this._input = this._input.bind(this); + + this._initMarkup(); + this._buildFilterItemMarkup(); + this._addEventListeners(); + + EventEmitter.decorate(this); + + this.filters = []; + this.setCssValue(value); +} + +exports.CSSFilterEditorWidget = CSSFilterEditorWidget; + +CSSFilterEditorWidget.prototype = { + _initMarkup: function() { + const list = this.el.querySelector(".filters"); + this.el.appendChild(list); + this.el.insertBefore(list, this.el.firstChild); + this.container = this.el; + this.list = list; + + this.filterSelect = this.el.querySelector("select"); + this._populateFilterSelect(); + }, + + /** + * Creates