blob: 2dec2f5c521ac65b8f246cd81be648166f809441 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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.
//
////////////////////////////////////////////////////////////////////////////////
package mx.controls
{
import flash.display.DisplayObject;
import flash.events.Event;
import flash.events.FocusEvent;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.ui.Keyboard;
import flash.utils.getTimer;
import mx.controls.colorPickerClasses.SwatchPanel;
import mx.controls.colorPickerClasses.WebSafePalette;
import mx.core.LayoutDirection;
import mx.core.UIComponent;
import mx.core.UIComponentGlobals;
import mx.core.mx_internal;
import mx.effects.Tween;
import mx.events.ColorPickerEvent;
import mx.events.DropdownEvent;
import mx.events.FlexEvent;
import mx.events.FlexMouseEvent;
import mx.events.InterManagerRequest;
import mx.events.SandboxMouseEvent;
import mx.managers.IFocusManager;
import mx.managers.ISystemManager;
import mx.managers.PopUpManager;
import mx.managers.SystemManager;
import mx.skins.halo.SwatchSkin;
import mx.styles.StyleProxy;
use namespace mx_internal;
//--------------------------------------
// Events
//--------------------------------------
/**
* Dispatched when the selected color
* changes as a result of user interaction.
*
* @eventType mx.events.ColorPickerEvent.CHANGE
* @helpid 4918
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="change", type="mx.events.ColorPickerEvent")]
/**
* Dispatched when the swatch panel closes.
*
* @eventType mx.events.DropdownEvent.CLOSE
* @helpid 4921
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="close", type="mx.events.DropdownEvent")]
/**
* Dispatched if the ColorPicker <code>editable</code>
* property is set to <code>true</code>
* and the user presses Enter after typing in a hexadecimal color value.
*
* @eventType mx.events.ColorPickerEvent.ENTER
* @helpid 4919
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="enter", type="mx.events.ColorPickerEvent")]
/**
* Dispatched when the user rolls the mouse out of a swatch
* in the SwatchPanel object.
*
* @eventType mx.events.ColorPickerEvent.ITEM_ROLL_OUT
* @helpid 4924
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="itemRollOut", type="mx.events.ColorPickerEvent")]
/**
* Dispatched when the user rolls the mouse over a swatch
* in the SwatchPanel object.
*
* @eventType mx.events.ColorPickerEvent.ITEM_ROLL_OVER
* @helpid 4923
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="itemRollOver", type="mx.events.ColorPickerEvent")]
/**
* Dispatched when the color swatch panel opens.
*
* @eventType mx.events.DropdownEvent.OPEN
* @helpid 4920
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Event(name="open", type="mx.events.DropdownEvent")]
//--------------------------------------
// Styles
//--------------------------------------
include "../styles/metadata/FocusStyles.as"
include "../styles/metadata/IconColorStyles.as"
include "../styles/metadata/LeadingStyle.as"
include "../styles/metadata/TextStyles.as"
/**
* Color of the outer border on the SwatchPanel object.
* The default value is <code>0xA5A9AE</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="borderColor", type="uint", format="Color", inherit="no", theme="halo")]
/**
* Length of a close transition, in milliseconds.
*
* The default value for the Halo theme is 250.
* The default value for the Spark theme is 50.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="closeDuration", type="Number", format="Time", inherit="no")]
/**
* Easing function to control component tweening.
* The default value is <code>undefined</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="closeEasingFunction", type="Function", inherit="no")]
/**
* Alphas used for the background fill of controls.
* The default value is <code>[ 0.6, 0.4 ]</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="fillAlphas", type="Array", arrayType="Number", inherit="no", theme="halo")]
/**
* Colors used to tint the background of the control.
* Pass the same color for both values for a flat-looking control.
* The default value is <code>[ 0xFFFFFF, 0xCCCCCC ]</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="fillColors", type="Array", arrayType="uint", format="Color", inherit="no", theme="halo")]
/**
* Alphas used for the highlight fill of controls.
* The default value is <code>[ 0.3, 0.0 ]</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="highlightAlphas", type="Array", arrayType="Number", inherit="no", theme="halo")]
/**
* Length of an open transition, in milliseconds.
*
* The default value for the Halo theme is 250.
* The default value for the Spark theme is 0.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="openDuration", type="Number", format="Time", inherit="no")]
/**
* Easing function to control component tweening.
* The default value is <code>undefined</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="openEasingFunction", type="Function", inherit="no")]
/**
* Bottom padding of SwatchPanel object below the swatch grid.
* The default value is 5.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="paddingBottom", type="Number", format="Length", inherit="no")]
/**
* Left padding of SwatchPanel object to the side of the swatch grid.
* The default value is 5.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="paddingLeft", type="Number", format="Length", inherit="no")]
/**
* Right padding of SwatchPanel object to the side of the swatch grid.
* The default value is 5.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="paddingRight", type="Number", format="Length", inherit="no")]
/**
* Top padding of SwatchPanel object above the swatch grid.
* The default value is 4.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="paddingTop", type="Number", format="Length", inherit="no")]
/**
* Color of the swatches' borders.
* The default value is <code>0x000000</code>.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="swatchBorderColor", type="uint", format="Color", inherit="no", theme="halo")]
/**
* Size of the outlines of the swatches' borders.
* The default value is 1.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="swatchBorderSize", type="Number", format="Length", inherit="no")]
/**
* Name of the class selector that defines style properties for the swatch panel.
* The default value is <code>undefined</code>. The following example shows the default style properties
* that are defined by the <code>swatchPanelStyleName</code>.
* <pre>
* ColorPicker {
* swatchPanelStyleName:mySwatchPanelStyle;
* }
*
* .mySwatchPanelStyle {
* backgroundColor:#E5E6E7;
* columnCount:20;
* horizontalGap:0;
* previewHeight:22;
* previewWidth:45;
* swatchGridBackgroundColor:#000000;
* swatchGridBorderSize:0;
* swatchHeight:12;
* swatchHighlightColor:#FFFFFF;
* swatchHighlightSize:1;
* swatchWidth:12;
* textFieldWidth:72;
* verticalGap:0;
* }
* </pre>
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
[Style(name="swatchPanelStyleName", type="String", inherit="no")]
//--------------------------------------
// Excluded APIs
//--------------------------------------
[Exclude(name="text", kind="property")]
[Exclude(name="fillAlphas", kind="style")]
[Exclude(name="fillColors", kind="style")]
[Exclude(name="highlightAlphas", kind="style")]
//--------------------------------------
// Other metadata
//--------------------------------------
[AccessibilityClass(implementation="mx.accessibility.ColorPickerAccImpl")]
[DataBindingInfo("acceptedTypes", "{ dataProvider: { label: &quot;String&quot; } }")]
[DefaultBindingProperty(source="selectedItem", destination="dataProvider")]
[DefaultTriggerEvent("change")]
[IconFile("ColorPicker.png")]
/**
* The ColorPicker control provides a way for a user to choose a color from a swatch list.
* The default mode of the component shows a single swatch in a square button.
* When the user clicks the swatch button, the swatch panel appears and
* displays the entire swatch list.
*
* <p>The ColorPicker control has the following default sizing characteristics:</p>
* <table class="innertable">
* <tr>
* <th>Characteristic</th>
* <th>Description</th>
* </tr>
* <tr>
* <td>Default size</td>
* <td>ColorPicker: 22 by 22 pixels
* <br>Swatch panel: Sized to fit the ColorPicker control width</br></td>
* </tr>
* <tr>
* <td>Minimum size</td>
* <td>0 pixels by 0 pixels</td>
* </tr>
* <tr>
* <td>Maximum size</td>
* <td>Undefined</td>
* </tr>
* </table>
*
* @mxml
*
* <p>The <code>&lt;mx:ColorPicker&gt;</code> tag inherits all of the properties of its
* superclass, and the following properties:</p>
*
* <pre>
* &lt;mx:ColorPicker
* <b>Properties</b>
* colorField="color"
* labelField="label"
* selectedColor="0x000000"
* selectedIndex="0"
* showTextField="true|false"
*
* <b>Styles</b>
* borderColor="0xA5A9AE"
* closeDuration="250"
* closeEasingFunction="undefined"
* color="0x0B333C"
* disabledIconColor="0x999999"
* fillAlphas="[0.6,0.4]"
* fillColors="[0xFFFFFF, 0xCCCCCC]"
* focusAlpha="0.5"
* focusRoundedCorners="tl tr bl br"
* fontAntiAliasType="advanced"
* fontfamily="Verdana"
* fontGridFitType="pixel"
* fontSharpness="0""
* fontSize="10"
* fontStyle="normal"
* fontThickness="0"
* fontWeight="normal"
* highlightAlphas="[0.3,0.0]"
* iconColor="0x000000"
* leading="2"
* openDuration="250"
* openEasingFunction="undefined"
* paddingBottom="5"
* paddingLeft="5"
* paddingRight="5"
* paddingTop="4"
* swatchBorderColor="0x000000"
* swatchBorderSize="1"
* swatchPanelStyleName="undefined"
* textAlign="left"
* textDecoration="none"
* textIndent="0"
*
* <b>Events</b>
* change="<i>No default</i>"
* close="<i>No default</i>"
* enter="<i>No default</i>"
* itemRollOut="<i>No default</i>"
* itemRollOver="<i>No default</i>"
* open="<i>No default</i>"
* /&gt;
* </pre>
*
* @see mx.controls.List
* @see mx.effects.Tween
* @see mx.managers.PopUpManager
*
* @includeExample examples/ColorPickerExample.mxml
*
* @helpid 4917
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public class ColorPicker extends ComboBase
{
include "../core/Version.as";
//--------------------------------------------------------------------------
//
// Class mixins
//
//--------------------------------------------------------------------------
/**
* @private
* Placeholder for mixin by SliderAccImpl.
*/
mx_internal static var createAccessibilityImplementation:Function;
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function ColorPicker()
{
super();
if (!isModelInited)
loadDefaultPalette();
// Make editable false so that focus doesn't go
// to the comboBase's textInput which is not used by CP
super.editable = false;
// Register for events.
addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* @private
* Used by SwatchPanel
*/
mx_internal var showingDropdown:Boolean = false;
/**
* @private
* Used by SwatchPanel
*/
mx_internal var isDown:Boolean = false;
/**
* @private
* Used by SwatchPanel
*/
mx_internal var isOpening:Boolean = false;
/**
* @private
*/
private var dropdownGap:Number = 6;
/**
* @private
*/
private var indexFlag:Boolean = false;
/**
* @private
*/
private var initializing:Boolean = true;
/**
* @private
*/
private var isModelInited:Boolean = false;
/**
* @private
*/
private var collectionChanged:Boolean = false;
/**
* @private
*/
private var swatchPreview:SwatchSkin;
/**
* @private
*/
private var dropdownSwatch:SwatchPanel;
/**
* @private
*/
private var triggerEvent:Event;
//--------------------------------------------------------------------------
//
// Overridden Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// dataProvider
//----------------------------------
[Bindable("collectionChange")]
[Inspectable(category="Data")]
/**
* @private
* The dataProvider for the ColorPicker control.
* The default dataProvider is an Array that includes all
* the web-safe colors.
*
* @helpid 4929
*/
override public function set dataProvider(value:Object):void
{
super.dataProvider = value;
isModelInited = true;
if (dropdownSwatch)
dropdownSwatch.dataProvider = value;
}
//----------------------------------
// editable
//----------------------------------
[Bindable("editableChanged")]
[Inspectable(category="General", defaultValue="true")]
/**
* @private
*/
private var _editable:Boolean = true;
/**
* @private
* Specifies whether the user can type a hexadecimal color value
* in the text box.
*
* @default true
* @helpid 4930
*/
override public function get editable():Boolean
{
return _editable;
}
/**
* @private
*/
override public function set editable(value:Boolean):void
{
_editable = value;
if (dropdownSwatch)
dropdownSwatch.editable = value;
dispatchEvent(new Event("editableChanged"));
}
//----------------------------------
// selectedIndex
//----------------------------------
[Bindable("change")]
[Bindable("collectionChange")]
[Inspectable(defaultValue="0")]
/**
* Index in the dataProvider of the selected item in the
* SwatchPanel object.
* Setting this property sets the selected color to the color that
* corresponds to the index, sets the selected index in the drop-down
* swatch to the <code>selectedIndex</code> property value,
* and displays the associated label in the text box.
* The default value is the index corresponding to
* black(0x000000) color if found, else it is 0.
*
* @helpid 4931
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
override public function set selectedIndex(value:int):void
{
if ((selectedIndex != -1 || !isNaN(selectedColor)) &&
value != selectedIndex)
{
if (value >= 0)
{
indexFlag = true;
selectedColor = getColor(value);
// Call super in mixed-in DataSelector
super.selectedIndex = value;
}
if (dropdownSwatch)
dropdownSwatch.selectedIndex = value;
}
}
//----------------------------------
// selectedItem
//----------------------------------
[Bindable("change")]
[Bindable("collectionChange")]
[Inspectable(defaultValue="0")]
/**
* @private
* If the dataProvider is a complex object, this property is a
* reference to the selected item in the SwatchPanel object.
* If the dataProvider is an Array of color values, this
* property is the selected color value.
* If the dataProvider is a complex object, modifying fields of
* this property modifies the dataProvider and its views.
*
* <p>If the dataProvider is a complex object, this property is
* read-only. You cannot change its value directly.
* If the dataProvider is an Array of hexadecimal color values,
* you can change this value directly.
* The default value is undefined for complex dataProviders;
* 0 if the dataProvider is an Array of color values.
*
* @helpid 4933
*/
override public function set selectedItem(value:Object):void
{
if (value != selectedItem)
{
// Call super in mixed-in DataSelector
super.selectedItem = value;
if (typeof(value) == "object")
selectedColor = Number(value[colorField]);
else if (typeof(value) == "number")
selectedColor = Number(value);
indexFlag = true;
if (dropdownSwatch)
dropdownSwatch.selectedItem = value;
}
}
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// colorField
//----------------------------------
/**
* @private
* Storage for the colorField property.
*/
private var _colorField:String = "color";
[Bindable("colorFieldChanged")]
[Inspectable(category="Data", defaultValue="color")]
/**
* Name of the field in the objects of the dataProvider Array that
* specifies the hexadecimal values of the colors that the swatch
* panel displays.
*
* <p>If the dataProvider objects do not contain a color
* field, set the <code>colorField</code> property to use the correct field name.
* This property is available, but not meaningful, if the
* dataProvider is an Array of hexadecimal color values.</p>
*
* @default "color"
* @helpid 4927
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get colorField():String
{
return _colorField;
}
/**
* @private
*/
public function set colorField(value:String):void
{
_colorField = value;
if (dropdownSwatch)
dropdownSwatch.colorField = value;
dispatchEvent(new Event("colorFieldChanged"));
}
//----------------------------------
// dropdown
//----------------------------------
/**
* A reference to the SwatchPanel object that appears when you expand
* the ColorPicker control.
*
* @helpid 4922
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
mx_internal function get dropdown():SwatchPanel
{
return dropdownSwatch; // null if not created yet
}
//----------------------------------
// labelField
//----------------------------------
/**
* Storage for the labelField property.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
private var _labelField:String = "label";
[Bindable("labelFieldChanged")]
[Inspectable(category="Data", defaultValue="label")]
/**
* Name of the field in the objects of the dataProvider Array that
* contain text to display as the label in the SwatchPanel object text box.
*
* <p>If the dataProvider objects do not contain a label
* field, set the <code>labelField</code> property to use the correct field name.
* This property is available, but not meaningful, if the
* dataProvider is an Array of hexadecimal color values.</p>
*
* @default "label"
* @helpid 4928
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get labelField():String
{
return _labelField;
}
/**
* @private
*/
public function set labelField(value:String):void
{
_labelField = value;
if (dropdownSwatch)
dropdownSwatch.labelField = value;
dispatchEvent(new Event("labelFieldChanged"));
}
//----------------------------------
// selectedColor
//----------------------------------
/**
* @private
* Storage for the selectedColor property.
*/
private var _selectedColor:uint = 0x000000;
[Bindable("change")]
[Bindable("valueCommit")]
[Inspectable(category="General", defaultValue="0", format="Color")]
/**
* The value of the currently selected color in the
* SwatchPanel object.
* In the &lt;mx:ColorPicker&gt; tag only, you can set this property to
* a standard string color name, such as "blue".
* If the dataProvider contains an entry for black (0x000000), the
* default value is 0; otherwise, the default value is the color of
* the item at index 0 of the data provider.
*
* @helpid 4932
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get selectedColor():uint
{
return _selectedColor;
}
/**
* @private
*/
public function set selectedColor(value:uint):void
{
if (!indexFlag)
{
super.selectedIndex = findColorByName(value);
}
else
{
indexFlag = false;
}
if (value != selectedColor)
{
_selectedColor = value;
updateColor(value);
if (dropdownSwatch)
dropdownSwatch.selectedColor = value;
}
dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
}
//----------------------------------
// showTextField
//----------------------------------
/**
* @private
* Storage for the showTextField property.
*/
private var _showTextField:Boolean = true;
[Inspectable(category="General", defaultValue="true")]
/**
* Specifies whether to show the text box that displays the color
* label or hexadecimal color value.
*
* @default true
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function get showTextField():Boolean
{
return _showTextField;
}
/**
* @private
*/
public function set showTextField(value:Boolean):void
{
_showTextField = value;
if (dropdownSwatch)
dropdownSwatch.showTextField = value;
}
//----------------------------------
// swatchStyleFilters
//----------------------------------
/**
* Set of styles to pass from the ColorPicker through to the preview swatch.
* @see mx.styles.StyleProxy
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
protected function get swatchStyleFilters():Object
{
return _swatchStyleFilters;
}
private static const _swatchStyleFilters:Object =
{
"swatchBorderColor" : "swatchBorderColor",
"swatchBorderSize" : "swatchBorderSize"
};
//--------------------------------------------------------------------------
//
// Overridden methods: UIComponent
//
//--------------------------------------------------------------------------
/**
* @private
*/
override protected function initializeAccessibility():void
{
if (ColorPicker.createAccessibilityImplementation != null)
ColorPicker.createAccessibilityImplementation(this);
}
/**
* @private
*/
override protected function createChildren():void
{
super.createChildren();
// Create swatch preview
if (!swatchPreview)
{
swatchPreview = new SwatchSkin();
swatchPreview.styleName = new StyleProxy(this, swatchStyleFilters);
swatchPreview.color = selectedColor;
swatchPreview.name = "colorPickerSwatch";
addChild(swatchPreview);
}
setChildIndex(swatchPreview, getChildIndex(downArrowButton));
textInput.visible = false;
// Update the preview swatch
if (!enabled)
super.enabled = enabled;
initializing = false;
}
/**
* @private
*/
override protected function commitProperties():void
{
super.commitProperties();
// Code executed when model (dataProvider changes)
// If dataProvider is changed, selectedColor if found in
// the new dataProvider is selected
// else selectedColor is color at selectedIndex = 0;
if (collectionChanged)
{
if (findColorByName(selectedColor) == -1)
{
if (dataProvider.length > 0 && selectedIndex > dataProvider.length)
selectedIndex = 0;
if (getColor(selectedIndex) >= 0)
{
selectedColor = getColor(selectedIndex);
swatchPreview.color = selectedColor;
}
else
{
if (dropdownSwatch)
swatchPreview.color = dropdownSwatch.selectedColor;
}
}
else
selectedIndex = findColorByName(selectedColor);
collectionChanged = false;
}
}
/**
* @private
*/
override protected function measure():void
{
// Though deriving from ComboBase this doesnot implement
// calcPreferredSizeFromData required by the super measure.
// Hence do not call it.
// super.measure();
// Make sure we're a small square, so we use HEIGHT for both
measuredMinWidth = measuredWidth = DEFAULT_MEASURED_MIN_HEIGHT;
measuredMinHeight = measuredHeight = DEFAULT_MEASURED_MIN_HEIGHT;
}
/**
* @private
*/
override protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
swatchPreview.color = selectedColor;
swatchPreview.setActualSize(unscaledWidth, unscaledHeight);
// super may push it around
downArrowButton.move(0, 0);
downArrowButton.setActualSize(unscaledWidth, unscaledHeight);
if (dropdownSwatch)
{
dropdownSwatch.setActualSize(
dropdownSwatch.getExplicitOrMeasuredWidth(),
dropdownSwatch.getExplicitOrMeasuredHeight());
}
}
/**
* @private
* Invalidate Style
*/
override public function styleChanged(styleProp:String):void
{
if (dropdownSwatch)
{
if (styleProp == "swatchPanelStyleName")
{
var swatchPanelStyleName:Object = getStyle("swatchPanelStyleName");
if (swatchPanelStyleName)
dropdownSwatch.styleName = swatchPanelStyleName;
}
dropdownSwatch.styleChanged(styleProp);
}
super.styleChanged(styleProp);
// Adjust tweenMask size if needed
invalidateDisplayList();
}
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
/**
* Displays the drop-down SwatchPanel object
* that shows colors that users can select.
*
* @helpid 4925
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function open():void
{
displayDropdown(true);
}
/**
* Hides the drop-down SwatchPanel object.
*
* @param trigger The event to dispatch when the
* drop-down list closes.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
public function close(trigger:Event = null):void
{
displayDropdown(false, trigger);
}
/**
* @private
* Dropdown Creation
*/
mx_internal function getDropdown():SwatchPanel
{
if (initializing)
return null;
if (!dropdownSwatch)
{
dropdownSwatch = new SwatchPanel();
dropdownSwatch.owner = this;
dropdownSwatch.editable = editable;
dropdownSwatch.colorField = colorField;
dropdownSwatch.labelField = labelField;
dropdownSwatch.dataProvider = dataProvider;
dropdownSwatch.showTextField = showTextField;
dropdownSwatch.selectedColor = selectedColor;
dropdownSwatch.selectedIndex = selectedIndex;
dropdownSwatch.textInputClass = getStyle("textInputClass");
var swatchPanelStyleName:Object = getStyle("swatchPanelStyleName");
if (swatchPanelStyleName)
dropdownSwatch.styleName = swatchPanelStyleName;
// Assign event handlers
dropdownSwatch.addEventListener(ColorPickerEvent.ITEM_ROLL_OVER,
dropdownSwatch_itemRollOverHandler);
dropdownSwatch.addEventListener(ColorPickerEvent.ITEM_ROLL_OUT,
dropdownSwatch_itemRollOutHandler);
dropdownSwatch.cacheAsBitmap = true;
dropdownSwatch.scrollRect = new Rectangle(0, 0, 0, 0);
PopUpManager.addPopUp(dropdownSwatch, this);
UIComponentGlobals.layoutManager.validateClient(dropdownSwatch, true);
dropdownSwatch.setActualSize(
dropdownSwatch.getExplicitOrMeasuredWidth(),
dropdownSwatch.getExplicitOrMeasuredHeight());
dropdownSwatch.validateDisplayList();
}
dropdownSwatch.layoutDirection = layoutDirection;
dropdownSwatch.scaleX = scaleX;
dropdownSwatch.scaleY = scaleY;
return dropdownSwatch;
}
/**
* @private
* Display Dropdown
*/
mx_internal function displayDropdown(show:Boolean, trigger:Event = null):void
{
if (show == showingDropdown)
return;
// Show or hide the dropdown
var initY:Number;
var endY:Number;
var tween:Tween = null;
var easingFunction:Function;
var duration:Number;
// Save the current triggerEvent
triggerEvent = trigger;
if (show) // Open
{
getDropdown();
// Find global position for the dropdown
var point:Point = new Point(layoutDirection == LayoutDirection.RTL ?
dropdownSwatch.getExplicitOrMeasuredWidth() : 0,
0);
point = localToGlobal(point);
if (dropdownSwatch.parent == null)
PopUpManager.addPopUp(dropdownSwatch, this, false);
else
PopUpManager.bringToFront(dropdownSwatch);
dropdownSwatch.addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE,
dropdownSwatch_mouseDownOutsideHandler);
dropdownSwatch.addEventListener(FlexMouseEvent.MOUSE_WHEEL_OUTSIDE,
dropdownSwatch_mouseDownOutsideHandler);
dropdownSwatch.addEventListener(SandboxMouseEvent.MOUSE_DOWN_SOMEWHERE,
dropdownSwatch_mouseDownOutsideHandler);
dropdownSwatch.addEventListener(SandboxMouseEvent.MOUSE_WHEEL_SOMEWHERE,
dropdownSwatch_mouseDownOutsideHandler);
dropdownSwatch.isOpening = true;
dropdownSwatch.showTextField = showTextField;
dropdownSwatch.selectedColor = selectedColor;
dropdownSwatch.owner = this;
// Position: top or bottom
var sm:ISystemManager = systemManager.topLevelSystemManager;
var screen:Rectangle = sm.getVisibleApplicationRect(null, true);
if (point.y + height + dropdownGap + dropdownSwatch.height > screen.bottom &&
point.y > (screen.top + dropdownGap + dropdownSwatch.height)) // Up
{
// Dropdown opens up instead of down
point.y -= dropdownGap + dropdownSwatch.height;
initY = -dropdownSwatch.height/scaleY;
dropdownSwatch.tweenUp = true;
}
else // Down
{
point.y += dropdownGap + height;
initY = dropdownSwatch.height/scaleY;
dropdownSwatch.tweenUp = false;
}
// Position: left or right
if (point.x + dropdownSwatch.width > screen.right &&
point.x > (screen.left + dropdownSwatch.width))
{
// Dropdown appears to the left instead of right
point.x -= (dropdownSwatch.width - width);
}
point.x = Math.max(point.x, 0);
// Position the dropdown
point = dropdownSwatch.parent.globalToLocal(point);
dropdownSwatch.move(point.x, point.y);
//dropdownSwatch.setFocus();
isDown = true;
isOpening = true;
endY = 0;
duration = getStyle("openDuration");
easingFunction = getStyle("openEasingFunction") as Function;
showingDropdown = show;
}
else // Close
{
initY = 0;
endY = dropdownSwatch.tweenUp ?
-dropdownSwatch.height/scaleY :
dropdownSwatch.height/scaleY;
isDown = false;
duration = getStyle("closeDuration");
easingFunction = getStyle("closeEasingFunction") as Function;
showingDropdown = show;
dropdownSwatch.removeEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE,
dropdownSwatch_mouseDownOutsideHandler);
dropdownSwatch.removeEventListener(FlexMouseEvent.MOUSE_WHEEL_OUTSIDE,
dropdownSwatch_mouseDownOutsideHandler);
dropdownSwatch.removeEventListener(SandboxMouseEvent.MOUSE_DOWN_SOMEWHERE,
dropdownSwatch_mouseDownOutsideHandler);
dropdownSwatch.removeEventListener(SandboxMouseEvent.MOUSE_WHEEL_SOMEWHERE,
dropdownSwatch_mouseDownOutsideHandler);
PopUpManager.removePopUp(dropdownSwatch);
}
if (dropdownSwatch)
{
dropdownSwatch.visible = true;
dropdownSwatch.enabled = false;
}
UIComponentGlobals.layoutManager.validateNow();
// Block all layout, responses from web service, and other background
// processing until the tween finishes executing.
UIComponent.suspendBackgroundProcessing();
tween = new Tween(this, initY, endY, duration);
if (easingFunction != null)
tween.easingFunction = easingFunction;
}
/**
* @private
* Load Default Palette
*/
private function loadDefaultPalette():void
{
// Initialize default swatch list
if (!dataProvider || dataProvider.length < 1)
{
var wsp:WebSafePalette = new WebSafePalette();
dataProvider = wsp.getList();
}
selectedIndex = findColorByName(selectedColor);
}
/**
* @private
* Update Color Preview
*/
private function updateColor(color:Number):void
{
if (initializing || isNaN(color))
return;
// Update the preview swatch
swatchPreview.updateSkin(color);
}
/**
* @private
* Find Color by Name
*/
private function findColorByName(name:Number):int
{
if (name == getColor(selectedIndex))
return selectedIndex;
var n:int = dataProvider.length;
for (var i:int = 0; i < dataProvider.length; i++)
{
if (name == getColor(i))
return i;
}
return -1;
}
/**
* @private
* Get Color Value
*/
private function getColor(location:int):Number
{
if (!dataProvider || dataProvider.length < 1 ||
location < 0 || location >= dataProvider.length)
{
return -1;
}
return Number(typeof(dataProvider.getItemAt(location)) == "object" ?
dataProvider.getItemAt(location)[colorField] :
dataProvider.getItemAt(location));
}
//--------------------------------------------------------------------------
//
// Overridden event handlers: UIComponent
//
//--------------------------------------------------------------------------
/**
* @private
*/
override protected function focusInHandler(event:FocusEvent):void
{
var fm:IFocusManager = focusManager;
if (fm)
fm.showFocusIndicator = true;
if (isDown && !isOpening)
close();
else if (isOpening)
isOpening = false;
super.focusInHandler(event);
}
/**
* @private
*/
override protected function keyDownHandler(event:KeyboardEvent):void
{
var cpEvent:ColorPickerEvent = null;
// If rtl layout, need to swap LEFT and RIGHT so correct action
// is done.
var keyCode:uint = mapKeycodeForLayoutDirection(event);
if (event.ctrlKey && keyCode == Keyboard.DOWN)
{
displayDropdown(true, event);
}
else if ((event.ctrlKey && keyCode == Keyboard.UP) ||
keyCode == Keyboard.ESCAPE)
{
if (dropdownSwatch && dropdownSwatch.enabled)
close(event);
}
else if (showingDropdown && keyCode == Keyboard.ENTER && dropdownSwatch.enabled)
{
if (!dropdownSwatch.isOverGrid && editable)
{
if (selectedColor != dropdownSwatch.selectedColor)
{
selectedColor = dropdownSwatch.selectedColor;
cpEvent = new ColorPickerEvent(ColorPickerEvent.CHANGE);
cpEvent.index = selectedIndex;
cpEvent.color = selectedColor;
dispatchEvent(cpEvent);
cpEvent = new ColorPickerEvent(ColorPickerEvent.ENTER);
// The index isn't set for an ENTER event,
// because the user can enter an RGB hex string that
// doesn't correspond to any color in the dataProvider.
cpEvent.color = selectedColor;
dispatchEvent(cpEvent);
}
}
else if (selectedIndex != dropdownSwatch.focusedIndex)
{
dropdownSwatch.selectedIndex = dropdownSwatch.focusedIndex;
selectedIndex = dropdownSwatch.selectedIndex;
cpEvent = new ColorPickerEvent(ColorPickerEvent.CHANGE);
cpEvent.index = selectedIndex;
cpEvent.color = selectedColor;
dispatchEvent(cpEvent);
}
close();
event.stopPropagation();
}
else if (showingDropdown &&
(keyCode == Keyboard.HOME ||
keyCode == Keyboard.END ||
keyCode == Keyboard.PAGE_UP ||
keyCode == Keyboard.PAGE_DOWN ||
keyCode == Keyboard.LEFT ||
keyCode == Keyboard.RIGHT ||
keyCode == Keyboard.UP ||
keyCode == Keyboard.DOWN))
{
// Redispatch the event from the SwatchPanel
// so that its keyDownHandler() can handle it.
dropdownSwatch.dispatchEvent(event);
}
else if (keyCode == Keyboard.LEFT)
{
if (selectedIndex == -1)
{
selectedIndex = findColorByName(selectedColor);
}
if (selectedIndex - 1 >= 0)
{
selectedIndex--;
cpEvent = new ColorPickerEvent(ColorPickerEvent.CHANGE);
cpEvent.index = selectedIndex;
cpEvent.color = selectedColor;
dispatchEvent(cpEvent);
}
}
else if (keyCode == Keyboard.RIGHT)
{
if (selectedIndex == -1)
{
selectedIndex = findColorByName(selectedColor);
}
if (selectedIndex + 1 < dataProvider.length)
{
selectedIndex++;
cpEvent = new ColorPickerEvent(ColorPickerEvent.CHANGE);
cpEvent.index = selectedIndex;
cpEvent.color = selectedColor;
dispatchEvent(cpEvent);
}
}
}
//--------------------------------------------------------------------------
//
// Overridden event handlers: ComboBase
//
//--------------------------------------------------------------------------
/**
* @private
*/
override protected function collectionChangeHandler(event:Event):void
{
// Change index to match selectedcolor if the model changes.
if (!initializing)
{
if (dataProvider.length > 0)
invalidateProperties();
else
{
selectedColor = 0x000000;
selectedIndex = -1;
}
collectionChanged = true;
}
if (dropdownSwatch)
dropdownSwatch.dataProvider = dataProvider;
}
/**
* @private
* On Down Arrow
*/
override protected function downArrowButton_buttonDownHandler(
event:FlexEvent):void
{
// The down arrow should always toggle the visibility of the dropdown
displayDropdown(!showingDropdown, event);
}
//--------------------------------------------------------------------------
//
// Event handlers
//
//--------------------------------------------------------------------------
/**
* @private
*/
private function dropdownSwatch_itemRollOverHandler(event:ColorPickerEvent):void
{
dispatchEvent(event);
}
/**
* @private
*/
private function dropdownSwatch_itemRollOutHandler(event:ColorPickerEvent):void
{
dispatchEvent(event);
}
/**
* @private
*/
private function dropdownSwatch_mouseDownOutsideHandler(event:Event):void
{
if (event is MouseEvent)
{
var mouseEvent:MouseEvent = MouseEvent(event);
if (!hitTestPoint(mouseEvent.stageX, mouseEvent.stageY, true))
close(event);
}
else if (event is SandboxMouseEvent)
close(event);
}
/**
* @private
*/
mx_internal function onTweenUpdate(value:Number):void
{
dropdownSwatch.scrollRect = new Rectangle(0, value, dropdownSwatch.width, dropdownSwatch.height);
}
/**
* @private
*/
mx_internal function onTweenEnd(value:Number):void
{
if (showingDropdown)
{
dropdownSwatch.scrollRect = null;
}
else
{
onTweenUpdate(value);
dropdownSwatch.visible = false;
isOpening = false;
}
UIComponent.resumeBackgroundProcessing();
if (showingDropdown && showTextField)
dropdownSwatch.callLater(dropdownSwatch.setFocus);
else
setFocus();
dropdownSwatch.enabled = true;
dispatchEvent(new DropdownEvent(showingDropdown ? DropdownEvent.OPEN : DropdownEvent.CLOSE, false, false, triggerEvent));
}
}
}