// Copyright 2007 The Closure Library Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS-IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /** * @fileoverview A color picker component. A color picker can compose several * instances of goog.ui.ColorPalette. * * NOTE: The ColorPicker is in a state of transition towards the common * component/control/container interface we are developing. If the API changes * we will do our best to update your code. The end result will be that a * color picker will compose multiple color palettes. In the simple case this * will be one grid, but may consistute 3 distinct grids, a custom color picker * or even a color wheel. * */ goog.provide('goog.ui.ColorPicker'); goog.provide('goog.ui.ColorPicker.EventType'); goog.require('goog.ui.ColorPalette'); goog.require('goog.ui.Component'); /** * Create a new, empty color picker. * * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper. * @param {goog.ui.ColorPalette=} opt_colorPalette Optional color palette to * use for this color picker. * @extends {goog.ui.Component} * @constructor * @final */ goog.ui.ColorPicker = function(opt_domHelper, opt_colorPalette) { goog.ui.Component.call(this, opt_domHelper); /** * The color palette used inside the color picker. * @type {goog.ui.ColorPalette?} * @private */ this.colorPalette_ = opt_colorPalette || null; this.getHandler().listen( this, goog.ui.Component.EventType.ACTION, this.onColorPaletteAction_); }; goog.inherits(goog.ui.ColorPicker, goog.ui.Component); /** * Default number of columns in the color palette. May be overridden by calling * setSize. * * @type {number} */ goog.ui.ColorPicker.DEFAULT_NUM_COLS = 5; /** * Constants for event names. * @enum {string} */ goog.ui.ColorPicker.EventType = { CHANGE: 'change' }; /** * Whether the component is focusable. * @type {boolean} * @private */ goog.ui.ColorPicker.prototype.focusable_ = true; /** * Gets the array of colors displayed by the color picker. * Modifying this array will lead to unexpected behavior. * @return {Array?} The colors displayed by this widget. */ goog.ui.ColorPicker.prototype.getColors = function() { return this.colorPalette_ ? this.colorPalette_.getColors() : null; }; /** * Sets the array of colors to be displayed by the color picker. * @param {Array} colors The array of colors to be added. */ goog.ui.ColorPicker.prototype.setColors = function(colors) { // TODO(user): Don't add colors directly, we should add palettes and the // picker should support multiple palettes. if (!this.colorPalette_) { this.createColorPalette_(colors); } else { this.colorPalette_.setColors(colors); } }; /** * Sets the array of colors to be displayed by the color picker. * @param {Array} colors The array of colors to be added. * @deprecated Use setColors. */ goog.ui.ColorPicker.prototype.addColors = function(colors) { this.setColors(colors); }; /** * Sets the size of the palette. Will throw an error after the picker has been * rendered. * @param {goog.math.Size|number} size The size of the grid. */ goog.ui.ColorPicker.prototype.setSize = function(size) { // TODO(user): The color picker should contain multiple palettes which will // all be resized at this point. if (!this.colorPalette_) { this.createColorPalette_([]); } this.colorPalette_.setSize(size); }; /** * Gets the number of columns displayed. * @return {goog.math.Size?} The size of the grid. */ goog.ui.ColorPicker.prototype.getSize = function() { return this.colorPalette_ ? this.colorPalette_.getSize() : null; }; /** * Sets the number of columns. Will throw an error after the picker has been * rendered. * @param {number} n The number of columns. * @deprecated Use setSize. */ goog.ui.ColorPicker.prototype.setColumnCount = function(n) { this.setSize(n); }; /** * @return {number} The index of the color selected. */ goog.ui.ColorPicker.prototype.getSelectedIndex = function() { return this.colorPalette_ ? this.colorPalette_.getSelectedIndex() : -1; }; /** * Sets which color is selected. A value that is out-of-range means that no * color is selected. * @param {number} ind The index in this.colors_ of the selected color. */ goog.ui.ColorPicker.prototype.setSelectedIndex = function(ind) { if (this.colorPalette_) { this.colorPalette_.setSelectedIndex(ind); } }; /** * Gets the color that is currently selected in this color picker. * @return {?string} The hex string of the color selected, or null if no * color is selected. */ goog.ui.ColorPicker.prototype.getSelectedColor = function() { return this.colorPalette_ ? this.colorPalette_.getSelectedColor() : null; }; /** * Sets which color is selected. Noop if the color palette hasn't been created * yet. * @param {string} color The selected color. */ goog.ui.ColorPicker.prototype.setSelectedColor = function(color) { // TODO(user): This will set the color in the first available palette that // contains it if (this.colorPalette_) { this.colorPalette_.setSelectedColor(color); } }; /** * Returns true if the component is focusable, false otherwise. The default * is true. Focusable components always have a tab index and allocate a key * handler to handle keyboard events while focused. * @return {boolean} True iff the component is focusable. */ goog.ui.ColorPicker.prototype.isFocusable = function() { return this.focusable_; }; /** * Sets whether the component is focusable. The default is true. * Focusable components always have a tab index and allocate a key handler to * handle keyboard events while focused. * @param {boolean} focusable True iff the component is focusable. */ goog.ui.ColorPicker.prototype.setFocusable = function(focusable) { this.focusable_ = focusable; if (this.colorPalette_) { this.colorPalette_.setSupportedState( goog.ui.Component.State.FOCUSED, focusable); } }; /** * ColorPickers cannot be used to decorate pre-existing html, since the * structure they build is fairly complicated. * @param {Element} element Element to decorate. * @return {boolean} Returns always false. * @override */ goog.ui.ColorPicker.prototype.canDecorate = function(element) { return false; }; /** * Renders the color picker inside the provided element. This will override the * current content of the element. * @override */ goog.ui.ColorPicker.prototype.enterDocument = function() { goog.ui.ColorPicker.superClass_.enterDocument.call(this); if (this.colorPalette_) { this.colorPalette_.render(this.getElement()); } this.getElement().unselectable = 'on'; }; /** @override */ goog.ui.ColorPicker.prototype.disposeInternal = function() { goog.ui.ColorPicker.superClass_.disposeInternal.call(this); if (this.colorPalette_) { this.colorPalette_.dispose(); this.colorPalette_ = null; } }; /** * Sets the focus to the color picker's palette. */ goog.ui.ColorPicker.prototype.focus = function() { if (this.colorPalette_) { this.colorPalette_.getElement().focus(); } }; /** * Handles actions from the color palette. * * @param {goog.events.Event} e The event. * @private */ goog.ui.ColorPicker.prototype.onColorPaletteAction_ = function(e) { e.stopPropagation(); this.dispatchEvent(goog.ui.ColorPicker.EventType.CHANGE); }; /** * Create a color palette for the color picker. * @param {Array} colors Array of colors. * @private */ goog.ui.ColorPicker.prototype.createColorPalette_ = function(colors) { // TODO(user): The color picker should eventually just contain a number of // palettes and manage the interactions between them. This will go away then. var cp = new goog.ui.ColorPalette(colors, null, this.getDomHelper()); cp.setSize(goog.ui.ColorPicker.DEFAULT_NUM_COLS); cp.setSupportedState(goog.ui.Component.State.FOCUSED, this.focusable_); // TODO(user): Use addChild(cp, true) and remove calls to render. this.addChild(cp); this.colorPalette_ = cp; if (this.isInDocument()) { this.colorPalette_.render(this.getElement()); } }; /** * Returns an unrendered instance of the color picker. The colors and layout * are a simple color grid, the same as the old Gmail color picker. * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper. * @return {!goog.ui.ColorPicker} The unrendered instance. */ goog.ui.ColorPicker.createSimpleColorGrid = function(opt_domHelper) { var cp = new goog.ui.ColorPicker(opt_domHelper); cp.setSize(7); cp.setColors(goog.ui.ColorPicker.SIMPLE_GRID_COLORS); return cp; }; /** * Array of colors for a 7-cell wide simple-grid color picker. * @type {Array} */ goog.ui.ColorPicker.SIMPLE_GRID_COLORS = [ // grays '#ffffff', '#cccccc', '#c0c0c0', '#999999', '#666666', '#333333', '#000000', // reds '#ffcccc', '#ff6666', '#ff0000', '#cc0000', '#990000', '#660000', '#330000', // oranges '#ffcc99', '#ff9966', '#ff9900', '#ff6600', '#cc6600', '#993300', '#663300', // yellows '#ffff99', '#ffff66', '#ffcc66', '#ffcc33', '#cc9933', '#996633', '#663333', // olives '#ffffcc', '#ffff33', '#ffff00', '#ffcc00', '#999900', '#666600', '#333300', // greens '#99ff99', '#66ff99', '#33ff33', '#33cc00', '#009900', '#006600', '#003300', // turquoises '#99ffff', '#33ffff', '#66cccc', '#00cccc', '#339999', '#336666', '#003333', // blues '#ccffff', '#66ffff', '#33ccff', '#3366ff', '#3333ff', '#000099', '#000066', // purples '#ccccff', '#9999ff', '#6666cc', '#6633ff', '#6600cc', '#333399', '#330099', // violets '#ffccff', '#ff99ff', '#cc66cc', '#cc33cc', '#993399', '#663366', '#330033' ];