1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2004-2007 Adobe Systems Incorporated 5// All Rights Reserved. 6// 7// NOTICE: Adobe permits you to use, modify, and distribute this file 8// in accordance with the terms of the license agreement accompanying it. 9// 10//////////////////////////////////////////////////////////////////////////////// 11 12package mx.controls.colorPickerClasses 13{ 14 15import flash.events.Event; 16import flash.events.EventPhase; 17import flash.events.KeyboardEvent; 18import flash.events.MouseEvent; 19import flash.geom.Rectangle; 20import flash.ui.Keyboard; 21import mx.collections.ArrayList; 22import mx.collections.IList; 23import mx.controls.ColorPicker; 24import mx.controls.TextInput; 25import mx.core.FlexVersion; 26import mx.core.UIComponent; 27import mx.core.mx_internal; 28import mx.events.ColorPickerEvent; 29import mx.managers.IFocusManagerContainer; 30import mx.skins.halo.SwatchPanelSkin; 31import mx.skins.halo.SwatchSkin; 32import mx.styles.StyleManager; 33 34use namespace mx_internal; 35 36//-------------------------------------- 37// Events 38//-------------------------------------- 39 40/** 41 * Dispatched when the selected color changes. 42 * 43 * @eventType flash.events.Event.CHANGE 44 */ 45[Event(name="change", type="flash.events.Event")] 46 47/** 48 * Dispatched when the user presses the Enter key. 49 * 50 * @eventType mx.events.FlexEvent.ENTER 51 */ 52[Event(name="enter", type="flash.events.Event")] 53 54/** 55 * Dispatched when the mouse rolls over a color. 56 * 57 * @eventType mx.events.ColorPickerEvent.ITEM_ROLL_OVER 58 */ 59[Event(name="itemRollOver", type="mx.events.ColorPickerEvent")] 60 61/** 62 * Dispatched when the mouse rolls out of a color. 63 * 64 * @eventType mx.events.ColorPickerEvent.ITEM_ROLL_OUT 65 */ 66[Event(name="itemRollOut", type="mx.events.ColorPickerEvent")] 67 68//-------------------------------------- 69// Styles 70//-------------------------------------- 71 72include "../../styles/metadata/GapStyles.as" 73include "../../styles/metadata/PaddingStyles.as" 74 75/** 76 * Background color of the component. 77 * You can either have a <code>backgroundColor</code> or a 78 * <code>backgroundImage</code>, but not both. 79 * Note that some components, like a Button, do not have a background 80 * because they are completely filled with the button face or other graphics. 81 * The DataGrid control also ignores this style. 82 * The default value is <code>undefined</code>. If both this style and the 83 * backgroundImage style are undefined, the control has a transparent background. 84 */ 85[Style(name="backgroundColor", type="uint", format="Color", inherit="no")] 86 87/** 88 * Black section of a three-dimensional border, or the color section 89 * of a two-dimensional border. 90 * The following components support this style: Button, CheckBox, 91 * ComboBox, MenuBar, 92 * NumericStepper, ProgressBar, RadioButton, ScrollBar, Slider, and all 93 * components that support the <code>borderStyle</code> style. 94 * The default value depends on the component class; 95 * if not overriden for the class, it is <code>0xAAB3B3</code>. 96 */ 97[Style(name="borderColor", type="uint", format="Color", inherit="no")] 98 99/** 100 * Number of columns in the swatch grid. 101 * The default value is 20. 102 */ 103[Style(name="columnCount", type="int", inherit="no")] 104 105/** 106 * Color of the control border highlight. 107 * The default value is <code>0xC4CCCC</code> (medium gray) . 108 */ 109[Style(name="highlightColor", type="uint", format="Color", inherit="yes")] 110 111/** 112 * Color for the left and right inside edges of a component's skin. 113 * The default value is <code>0xD5DDDD</code>. 114 */ 115[Style(name="shadowCapColor", type="uint", format="Color", inherit="yes")] 116 117/** 118 * Bottom inside color of a button's skin. 119 * A section of the three-dimensional border. 120 * The default value is <code>0xEEEEEE</code> (light gray). 121 */ 122[Style(name="shadowColor", type="uint", format="Color", inherit="yes")] 123 124/** 125 * Height of the larger preview swatch that appears above the swatch grid on 126 * the top left of the SwatchPanel object. 127 * The default value is 22. 128 */ 129[Style(name="previewHeight", type="Number", format="Length", inherit="no")] 130 131/** 132 * Width of the larger preview swatch. 133 * The default value is 45. 134 */ 135[Style(name="previewWidth", type="Number", format="Length", inherit="no")] 136 137/** 138 * Size of the swatchBorder outlines. 139 * The default value is 1. 140 */ 141[Style(name="swatchBorderSize", type="Number", format="Length", inherit="no")] 142 143/** 144 * Color of the swatch borders. 145 * The default value is <code>0x000000</code>. 146 */ 147[Style(name="swatchBorderColor", type="uint", format="Color", inherit="no")] 148 149/** 150 * Size of the single border around the grid of swatches. 151 * The default value is 0. 152 */ 153[Style(name="swatchGridBorderSize", type="Number", format="Length", inherit="no")] 154 155/** 156 * Color of the background rectangle behind the swatch grid. 157 * The default value is <code>0x000000</code>. 158 */ 159[Style(name="swatchGridBackgroundColor", type="uint", format="Color", inherit="no")] 160 161/** 162 * Height of each swatch. 163 * The default value is 12. 164 */ 165[Style(name="swatchHeight", type="Number", format="Length", inherit="no")] 166 167/** 168 * Color of the highlight that appears around the swatch when the user 169 * rolls over a swatch. 170 * The default value is <code>0xFFFFFF</code>. 171 */ 172[Style(name="swatchHighlightColor", type="uint", format="Color", inherit="no")] 173 174/** 175 * Size of the highlight that appears around the swatch when the user 176 * rolls over a swatch. 177 * The default value is 1. 178 */ 179[Style(name="swatchHighlightSize", type="Number", format="Length", inherit="no")] 180 181/** 182 * Width of each swatch. 183 * The default value is 12. 184 */ 185[Style(name="swatchWidth", type="Number", format="Length", inherit="no")] 186 187/** 188 * @REVIEW 189 * Name of the style sheet definition to configure the text input control. 190 * The default value is "swatchPanelTextField" 191 */ 192[Style(name="textFieldStyleName", type="String", inherit="no")] 193 194/** 195 * Width of the hexadecimal text box that appears above the swatch grid. 196 * The default value is 72. 197 */ 198[Style(name="textFieldWidth", type="Number", format="Length", inherit="no")] 199 200//-------------------------------------- 201// Other metadata 202//-------------------------------------- 203 204[ExcludeClass] 205 206/** 207 * @private 208 */ 209public class SwatchPanel extends UIComponent implements IFocusManagerContainer 210{ 211 include "../../core/Version.as"; 212 213 //-------------------------------------------------------------------------- 214 // 215 // Constructor 216 // 217 //-------------------------------------------------------------------------- 218 219 /** 220 * Constructor. 221 */ 222 public function SwatchPanel() 223 { 224 super(); 225 226 // Register for events. 227 addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler); 228 addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); 229 } 230 231 //-------------------------------------------------------------------------- 232 // 233 // Variables 234 // 235 //-------------------------------------------------------------------------- 236 237 /** 238 * @private 239 */ 240 mx_internal var textInput:TextInput; 241 242 /** 243 * @private 244 */ 245 private var border:SwatchPanelSkin; 246 247 /** 248 * @private 249 */ 250 private var preview:SwatchSkin; 251 252 /** 253 * @private 254 */ 255 private var swatches:SwatchSkin; 256 257 /** 258 * @private 259 */ 260 private var highlight:SwatchSkin; 261 262 /** 263 * @private 264 * Used by ColorPicker 265 */ 266 mx_internal var isOverGrid:Boolean = false; 267 268 /** 269 * @private 270 * Used by ColorPicker 271 */ 272 mx_internal var isOpening:Boolean = false; 273 274 /** 275 * @private 276 * Used by ColorPicker 277 */ 278 mx_internal var focusedIndex:int = -1; 279 280 /** 281 * @private 282 * Used by ColorPicker 283 */ 284 mx_internal var tweenUp:Boolean = false; 285 286 /** 287 * @private 288 */ 289 private var initializing:Boolean = true; 290 291 /** 292 * @private 293 */ 294 private var indexFlag:Boolean = false; 295 296 /** 297 * @private 298 */ 299 private var lastIndex:int = -1; 300 301 /** 302 * @private 303 */ 304 private var grid:Rectangle; 305 306 /** 307 * @private 308 */ 309 private var rows:int; 310 311 /** 312 * @private 313 * Cached style. 314 */ 315 private var horizontalGap:Number; 316 317 /** 318 * @private 319 * Cached style. 320 */ 321 private var verticalGap:Number; 322 323 /** 324 * @private 325 * Cached style. 326 */ 327 private var columnCount:int; 328 329 /** 330 * @private 331 * Cached style. 332 */ 333 private var paddingLeft:Number; 334 335 /** 336 * @private 337 * Cached style. 338 */ 339 private var paddingRight:Number; 340 341 /** 342 * @private 343 * Cached style. 344 */ 345 private var paddingTop:Number; 346 347 /** 348 * @private 349 * Cached style. 350 */ 351 private var paddingBottom:Number; 352 353 /** 354 * @private 355 * Cached style. 356 */ 357 private var textFieldWidth:Number; 358 359 /** 360 * @private 361 * Cached style. 362 */ 363 private var previewWidth:Number; 364 365 /** 366 * @private 367 * Cached style. 368 */ 369 private var previewHeight:Number; 370 371 /** 372 * @private 373 * Cached style. 374 */ 375 private var swatchWidth:Number; 376 377 /** 378 * @private 379 * Cached style. 380 */ 381 private var swatchHeight:Number; 382 383 /** 384 * @private 385 * Cached style. 386 */ 387 private var swatchGridBorderSize:Number; 388 389 /** 390 * @private 391 */ 392 private var cellOffset:Number = 1; 393 394 /** 395 * @private 396 */ 397 private var itemOffset:Number = 3; 398 399 //-------------------------------------------------------------------------- 400 // 401 // Overridden Properties 402 // 403 //-------------------------------------------------------------------------- 404 405 //---------------------------------- 406 // height 407 //---------------------------------- 408 409 /** 410 * @private 411 * We set our size internally based on style values. 412 * Setting height has no effect on the panel. 413 * Override to return the preferred width and height of our contents. 414 */ 415 override public function get height():Number 416 { 417 return getExplicitOrMeasuredHeight(); 418 } 419 420 /** 421 * @private 422 */ 423 override public function set height(value:Number):void 424 { 425 // do nothing... 426 } 427 428 //---------------------------------- 429 // width 430 //---------------------------------- 431 432 /** 433 * @private 434 * We set our size internally based on style values. 435 * Setting width has no effect on the panel. 436 * Override to return the preferred width and height of our contents. 437 */ 438 override public function get width():Number 439 { 440 return getExplicitOrMeasuredWidth(); 441 } 442 443 /** 444 * @private 445 */ 446 override public function set width(value:Number):void 447 { 448 // do nothing... 449 } 450 451 //-------------------------------------------------------------------------- 452 // 453 // Properties 454 // 455 //-------------------------------------------------------------------------- 456 457 //---------------------------------- 458 // colorField 459 //---------------------------------- 460 461 /** 462 * Storage for the colorField property. 463 */ 464 private var _colorField:String = "color"; 465 466 /** 467 * @private 468 */ 469 public function get colorField():String 470 { 471 return _colorField; 472 } 473 474 /** 475 * @private 476 */ 477 public function set colorField(value:String):void 478 { 479 _colorField = value; 480 } 481 482 //---------------------------------- 483 // dataProvider 484 //---------------------------------- 485 486 /** 487 * Storage for the dataProvider property. 488 */ 489 private var _dataProvider:IList; 490 491 /** 492 * @private 493 */ 494 public function get dataProvider():Object 495 { 496 return _dataProvider; 497 } 498 499 /** 500 * @private 501 */ 502 public function set dataProvider(value:Object):void 503 { 504 if (value is IList) 505 { 506 _dataProvider = IList(value); 507 } 508 else if (value is Array) 509 { 510 var tmpDP:IList = new ArrayList(value as Array); 511 value = tmpDP; 512 } 513 else 514 { 515 _dataProvider = null; 516 } 517 518 if (!initializing) 519 { 520 // Adjust if dataProvider is empty 521 if (length == 0 || isNaN(length)) 522 { 523 highlight.visible = false; 524 _selectedIndex = -1; 525 } 526 527 // Redraw using new dataProvider 528 refresh(); 529 } 530 } 531 532 //---------------------------------- 533 // editable 534 //---------------------------------- 535 536 /** 537 * Storage for the editable property. 538 */ 539 private var _editable:Boolean = true; 540 541 /** 542 * @private 543 */ 544 public function get editable():Boolean 545 { 546 return _editable; 547 } 548 549 /** 550 * @private 551 */ 552 public function set editable(value:Boolean):void 553 { 554 _editable = value; 555 556 if (!initializing) 557 textInput.editable = value; 558 } 559 560 //---------------------------------- 561 // labelField 562 //---------------------------------- 563 564 /** 565 * Storage for the labelField property. 566 */ 567 private var _labelField:String = "label"; 568 569 /** 570 * @private 571 */ 572 public function get labelField():String 573 { 574 return _labelField; 575 } 576 577 /** 578 * @private 579 */ 580 public function set labelField(value:String):void 581 { 582 _labelField = value; 583 } 584 585 //---------------------------------- 586 // length 587 //---------------------------------- 588 589 /** 590 * @private 591 */ 592 public function get length():int 593 { 594 return _dataProvider ? _dataProvider.length : 0; 595 } 596 597 //---------------------------------- 598 // selectedColor 599 //---------------------------------- 600 601 /** 602 * Storage for the selectedColor property. 603 */ 604 private var _selectedColor:uint = 0x000000; 605 606 /** 607 * @private 608 */ 609 public function get selectedColor():uint 610 { 611 return _selectedColor; 612 } 613 614 /** 615 * @private 616 */ 617 public function set selectedColor(value:uint):void 618 { 619 // Set index unless it set us 620 if (!indexFlag) 621 { 622 var SI:int = findColorByName(value); 623 if (SI != -1) 624 { 625 focusedIndex = findColorByName(value); 626 _selectedIndex = focusedIndex; 627 } 628 else 629 { 630 selectedIndex = -1; 631 } 632 } 633 else 634 { 635 indexFlag = false; 636 } 637 638 if (value != selectedColor || !isOverGrid || isOpening) 639 { 640 _selectedColor = value; 641 updateColor(value); 642 643 if (isOverGrid || isOpening) 644 setFocusOnSwatch(selectedIndex); 645 if (isOpening) 646 isOpening = false; 647 } 648 } 649 650 //---------------------------------- 651 // selectedIndex 652 //---------------------------------- 653 654 /** 655 * Storage for the selectedIndex property. 656 */ 657 private var _selectedIndex:int = 0; 658 659 /** 660 * @private 661 */ 662 public function get selectedIndex():int 663 { 664 return _selectedIndex; 665 } 666 667 /** 668 * @private 669 */ 670 public function set selectedIndex(value:int):void 671 { 672 if (value != selectedIndex && !initializing) 673 { 674 focusedIndex = value; 675 _selectedIndex = focusedIndex; 676 677 if (value >= 0) 678 { 679 indexFlag = true; 680 selectedColor = getColor(value); 681 } 682 } 683 } 684 685 //---------------------------------- 686 // selectedItem 687 //---------------------------------- 688 689 /** 690 * @private 691 */ 692 public function get selectedItem():Object 693 { 694 return dataProvider ? dataProvider.getItemAt(selectedIndex) : null; 695 } 696 697 /** 698 * @private 699 */ 700 public function set selectedItem(value:Object):void 701 { 702 if (value != selectedItem) 703 { 704 var color:Number; 705 if (typeof(value) == "object") 706 color = Number(value[colorField]); 707 else if (typeof(value) == "number") 708 color = Number(value); 709 710 selectedIndex = findColorByName(color); 711 } 712 } 713 714 //---------------------------------- 715 // showTextField 716 //---------------------------------- 717 718 /** 719 * Storage for the showTextField property. 720 */ 721 private var _showTextField:Boolean = true; 722 723 /** 724 * @private 725 */ 726 public function get showTextField():Boolean 727 { 728 return _showTextField; 729 } 730 731 /** 732 * @private 733 */ 734 public function set showTextField(value:Boolean):void 735 { 736 _showTextField = value; 737 738 if (!initializing) 739 textInput.visible = value; 740 } 741 742 //-------------------------------------------------------------------------- 743 // 744 // Overridden methods: UIComponent 745 // 746 //-------------------------------------------------------------------------- 747 748 /** 749 * @private 750 */ 751 override protected function createChildren():void 752 { 753 super.createChildren(); 754 755 // Create the panel background 756 if (!border) 757 { 758 border = new SwatchPanelSkin(); 759 760 border.styleName = this; 761 border.name = "swatchPanelBorder"; 762 763 addChild(border); 764 } 765 766 // Create the preview swatch 767 if (!preview) 768 { 769 preview = new SwatchSkin(); 770 771 preview.styleName = this; 772 preview.color = selectedColor; 773 preview.name = "swatchPreview"; 774 775 preview.setStyle("swatchBorderSize", 0); 776 777 addChild(preview); 778 } 779 780 // Create the hex text field 781 if (!textInput) 782 { 783 textInput = new TextInput(); 784 785 if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_3_0) 786 { 787 textInput.styleName = this; 788 textInput.setStyle("borderCapColor", 0x919999); 789 textInput.setStyle("buttonColor", 0x6F7777); 790 textInput.setStyle("highlightColor", 0xC4CCCC); 791 textInput.setStyle("shadowColor", 0xc); 792 textInput.setStyle("shadowCapColor", 0xD5DDDD); 793 textInput.setStyle("borderStyle", "inset"); 794 textInput.setStyle("backgroundColor", 0xFFFFFF); 795 textInput.setStyle("borderColor", 0xD5DDDD); 796 } 797 else 798 { 799 textInput.styleName = getStyle("textFieldStyleName"); 800 } 801 802 textInput.editable = _editable; 803 textInput.maxChars = 6; 804 textInput.name = "inset"; 805 textInput.text = rgbToHex(selectedColor); 806 textInput.restrict = "#xa-fA-F0-9"; 807 808 textInput.addEventListener(Event.CHANGE, textInput_changeHandler); 809 textInput.addEventListener(KeyboardEvent.KEY_DOWN, textInput_keyDownHandler); 810 811 addChild(textInput); 812 } 813 814 // Create the swatches grid 815 if (!swatches) 816 { 817 swatches = new SwatchSkin(); 818 819 swatches.styleName = this; 820 swatches.colorField = colorField; 821 swatches.name = "swatchGrid"; 822 823 swatches.addEventListener(MouseEvent.CLICK, swatches_clickHandler); 824 825 addChild(swatches); 826 } 827 828 // Create the swatch highlight for grid rollovers 829 if (!highlight) 830 { 831 highlight = new SwatchSkin(); 832 833 highlight.styleName = this; 834 highlight.visible = false; 835 highlight.name = "swatchHighlight"; 836 837 addChild(highlight); 838 } 839 840 refresh(); 841 842 initializing = false; 843 } 844 845 /** 846 * @private 847 * Change 848 */ 849 override protected function measure():void 850 { 851 super.measure(); 852 853 swatches.updateGrid(IList(dataProvider)); 854 855 // Make sure we're at least 100 pixels wide 856 857 measuredWidth = Math.max( 858 paddingLeft + paddingRight + swatches.width, 100); 859 860 measuredHeight = Math.max( 861 paddingTop + previewHeight + itemOffset + 862 paddingBottom + swatches.height, 100); 863 } 864 865 /** 866 * @private 867 */ 868 override protected function updateDisplayList(unscaledWidth:Number, 869 unscaledHeight:Number):void 870 { 871 super.updateDisplayList(unscaledWidth, unscaledHeight); 872 873 // Layout preview position. 874 preview.updateSkin(selectedColor); 875 preview.move(paddingLeft, paddingTop); 876 877 // Layout hex text field position. 878 textInput.setActualSize(textFieldWidth, previewHeight); 879 textInput.move(paddingLeft + previewWidth + itemOffset, paddingTop); 880 881 // Layout grid position. 882 swatches.updateGrid(IList(dataProvider)); 883 swatches.move(paddingLeft, paddingTop + previewHeight + itemOffset); 884 885 // Layout highlight skin. 886 // Highlight doesn't require a color, hence we pass 0. 887 highlight.updateSkin(0); 888 889 // Layout panel skin. 890 border.setActualSize(unscaledWidth, unscaledHeight); 891 892 // Define area surrounding the swatches. 893 if (!grid) 894 grid = new Rectangle(); 895 grid.left = swatches.x + swatchGridBorderSize; 896 grid.top = swatches.y + swatchGridBorderSize; 897 grid.right = swatches.x + swatchGridBorderSize + 898 (swatchWidth - 1) * columnCount + 1 + 899 horizontalGap * (columnCount - 1); 900 grid.bottom = swatches.y + swatchGridBorderSize + 901 (swatchHeight - 1) * rows + 1 + 902 verticalGap * (rows - 1); 903 } 904 905 906 /** 907 * @private 908 */ 909 override public function styleChanged(styleProp:String):void 910 { 911 if (!initializing) 912 refresh(); 913 } 914 915 /** 916 * @private 917 */ 918 override public function drawFocus(isFocused:Boolean):void 919 { 920 // do nothing... 921 } 922 923 /** 924 * @private 925 */ 926 override public function setFocus():void 927 { 928 // Our text field controls focus 929 if (showTextField && editable) 930 { 931 textInput.setFocus(); 932 //ensure text field has the correct color value 933 textInput.text = rgbToHex(selectedColor); 934 } 935 } 936 937 //-------------------------------------------------------------------------- 938 // 939 // Methods 940 // 941 //-------------------------------------------------------------------------- 942 943 /** 944 * @private 945 */ 946 private function updateStyleCache():void 947 { 948 horizontalGap = getStyle("horizontalGap"); 949 verticalGap = getStyle("verticalGap"); 950 columnCount = getStyle("columnCount"); 951 paddingLeft = getStyle("paddingLeft"); 952 paddingRight = getStyle("paddingRight"); 953 paddingTop = getStyle("paddingTop"); 954 paddingBottom = getStyle("paddingBottom"); 955 textFieldWidth = getStyle("textFieldWidth"); 956 previewWidth = getStyle("previewWidth"); 957 previewHeight = getStyle("previewHeight"); 958 swatchWidth = getStyle("swatchWidth"); 959 swatchHeight = getStyle("swatchHeight"); 960 swatchGridBorderSize = getStyle("swatchGridBorderSize"); 961 962 // Adjust if columnCount is greater than # of swatches 963 if (columnCount > length) 964 columnCount = length; 965 966 // Rows based on columnCount and list length 967 rows = Math.ceil(length / columnCount); 968 } 969 970 /** 971 * @private 972 */ 973 private function refresh():void 974 { 975 updateStyleCache(); 976 updateDisplayList(unscaledWidth, unscaledHeight); 977 978 // Changes may have invalidated the size, so make sure we re-measure - SDK-13855 979 invalidateSize(); 980 } 981 982 /** 983 * @private 984 * Update color values in preview 985 */ 986 private function updateColor(color:uint):void 987 { 988 if (initializing || isNaN(color)) 989 return; 990 991 // Update the preview swatch 992 preview.updateSkin(color); 993 994 // Set hex field 995 if (isOverGrid) 996 { 997 var label:String = null; 998 999 if (focusedIndex >= 0 && 1000 typeof(dataProvider.getItemAt(focusedIndex)) == "object") 1001 { 1002 label = dataProvider.getItemAt(focusedIndex)[labelField]; 1003 } 1004 1005 textInput.text = label != null && label.length != 0 ? 1006 label : 1007 rgbToHex(color); 1008 } 1009 } 1010 1011 /** 1012 * @private 1013 * Convert RGB offset to Hex. 1014 */ 1015 private function rgbToHex(color:uint):String 1016 { 1017 // Find hex number in the RGB offset 1018 var colorInHex:String = color.toString(16); 1019 var c:String = "00000" + colorInHex; 1020 var e:int = c.length; 1021 c = c.substring(e - 6, e); 1022 return c.toUpperCase(); 1023 } 1024 1025 /** 1026 * @private 1027 */ 1028 private function findColorByName(name:Number):int 1029 { 1030 if (name == getColor(selectedIndex)) 1031 return selectedIndex; 1032 1033 for (var i:int = 0; i < length; i++) 1034 { 1035 if (name == getColor(i)) 1036 return i; 1037 } 1038 1039 return -1; 1040 } 1041 1042 /** 1043 * @private 1044 */ 1045 private function getColor(index:int):uint 1046 { 1047 if (!dataProvider || dataProvider.length < 1 || 1048 index < 0 || index >= length) 1049 { 1050 return StyleManager.NOT_A_COLOR; 1051 } 1052 1053 return uint(typeof(dataProvider.getItemAt(index)) == "object" ? 1054 dataProvider.getItemAt(index)[colorField] : 1055 dataProvider.getItemAt(index)); 1056 } 1057 1058 /** 1059 * @private 1060 */ 1061 private function setFocusOnSwatch(index:int):void 1062 { 1063 if (index < 0 || index > length - 1) 1064 { 1065 highlight.visible = false; 1066 return; 1067 } 1068 1069 // Swatch highlight activated by mouse move or key events 1070 var row:Number = Math.floor(index / columnCount); 1071 var column:Number = index - (row * columnCount); 1072 1073 var xPos:Number = swatchWidth * column + horizontalGap * column - 1074 cellOffset * column + paddingLeft + 1075 swatchGridBorderSize; 1076 var yPos:Number = swatchHeight * row + verticalGap * row - 1077 cellOffset * row + paddingTop + previewHeight + 1078 itemOffset + swatchGridBorderSize; 1079 1080 highlight.move(xPos, yPos); 1081 highlight.visible = true; 1082 1083 isOverGrid = true; 1084 1085 updateColor(getColor(index)); 1086 } 1087 1088 //-------------------------------------------------------------------------- 1089 // 1090 // Overridden event handlers: UIComponent 1091 // 1092 //-------------------------------------------------------------------------- 1093 1094 /** 1095 * @private 1096 */ 1097 override protected function keyDownHandler(event:KeyboardEvent):void 1098 { 1099 // Ignore events that bubbling from the owner ColorPicker. 1100 // through the textInput's keyDownHandler 1101 if (event.eventPhase != EventPhase.AT_TARGET || !enabled) 1102 return; 1103 1104 if (focusedIndex == -1 || isNaN(focusedIndex)) 1105 focusedIndex = 0; 1106 1107 var currentRow:int = Math.floor(focusedIndex / columnCount); 1108 1109 switch (event.keyCode) 1110 { 1111 case Keyboard.UP: 1112 { 1113 // Move up in column / jump to bottom of next column at end. 1114 focusedIndex = focusedIndex - columnCount < 0 ? 1115 (rows - 1) * columnCount + focusedIndex + 1 : 1116 focusedIndex - columnCount; 1117 isOverGrid = true; 1118 break; 1119 } 1120 1121 case Keyboard.DOWN: 1122 { 1123 // Move down in column / jump to top of last column at end. 1124 focusedIndex = focusedIndex + columnCount > length ? 1125 (focusedIndex - 1) - (rows - 1) * columnCount : 1126 focusedIndex + columnCount; 1127 isOverGrid = true; 1128 break; 1129 } 1130 1131 case Keyboard.LEFT: 1132 { 1133 // Move left in row / jump to right of last row at end. 1134 focusedIndex = focusedIndex < 1 ? 1135 length - 1 : 1136 focusedIndex - 1; 1137 isOverGrid = true; 1138 break; 1139 } 1140 1141 case Keyboard.RIGHT: 1142 { 1143 // Move right in row / jump to left of next row at end. 1144 focusedIndex = focusedIndex >= length - 1 ? 1145 0 : 1146 focusedIndex + 1; 1147 isOverGrid = true; 1148 break; 1149 } 1150 1151 case Keyboard.PAGE_UP: 1152 { 1153 // Move to first swatch in column. 1154 focusedIndex = focusedIndex - currentRow * columnCount; 1155 isOverGrid = true; 1156 break; 1157 } 1158 1159 case Keyboard.PAGE_DOWN: 1160 { 1161 // Move to last swatch in column. 1162 focusedIndex = focusedIndex + (rows - 1) * columnCount - 1163 currentRow * columnCount; 1164 isOverGrid = true; 1165 break; 1166 } 1167 1168 case Keyboard.HOME: 1169 { 1170 // Move to first swatch in row. 1171 focusedIndex = focusedIndex - 1172 (focusedIndex - currentRow * columnCount); 1173 isOverGrid = true; 1174 break; 1175 } 1176 1177 case Keyboard.END: 1178 { 1179 // Move to last swatch in row. 1180 focusedIndex = focusedIndex + 1181 (currentRow * columnCount - focusedIndex) + 1182 (columnCount - 1); 1183 isOverGrid = true; 1184 break; 1185 } 1186 } 1187 1188 // Draw focus on new swatch. 1189 if (focusedIndex < length && isOverGrid) 1190 { 1191 setFocusOnSwatch(focusedIndex); 1192 dispatchEvent(new Event("change")); 1193 } 1194 } 1195 1196 //-------------------------------------------------------------------------- 1197 // 1198 // Event handlers 1199 // 1200 //-------------------------------------------------------------------------- 1201 1202 /** 1203 * @private 1204 */ 1205 private function mouseMoveHandler(event:MouseEvent):void 1206 { 1207 if (ColorPicker(owner).isDown && enabled) 1208 { 1209 var colorPickerEvent:ColorPickerEvent; 1210 1211 // Only assess movements that occur over the swatch grid. 1212 if (mouseX > grid.left && mouseX < grid.right && 1213 mouseY > grid.top && mouseY < grid.bottom) 1214 { 1215 // Calculate location 1216 var column:Number = Math.floor( 1217 (Math.floor(mouseX) - (grid.left + verticalGap)) / 1218 (swatchWidth + horizontalGap - cellOffset)); 1219 var row:Number = Math.floor( 1220 (Math.floor(mouseY) - grid.top) / 1221 ((swatchHeight + verticalGap) - cellOffset)); 1222 var index:Number = row * columnCount + column; 1223 1224 // Adjust for edges 1225 if (column == -1) 1226 index++; 1227 else if (column > (columnCount - 1)) 1228 index--; 1229 else if (row > (rows - 1)) 1230 index -= columnCount; 1231 else if (index < 0) 1232 index += columnCount; 1233 1234 // Set state 1235 if ((lastIndex != index || highlight.visible == false) && 1236 index < length) 1237 { 1238 if (lastIndex != -1 && lastIndex != index) 1239 { 1240 // Dispatch a ColorPickerEvent with type "itemRollOut". 1241 colorPickerEvent = new ColorPickerEvent( 1242 ColorPickerEvent.ITEM_ROLL_OUT); 1243 colorPickerEvent.index = lastIndex; 1244 colorPickerEvent.color = getColor(lastIndex); 1245 dispatchEvent(colorPickerEvent); 1246 } 1247 1248 focusedIndex = index; 1249 lastIndex = focusedIndex; 1250 setFocusOnSwatch(focusedIndex); 1251 1252 // Dispatch a ColorPickerEvent with type "itemRollOver". 1253 colorPickerEvent = new ColorPickerEvent( 1254 ColorPickerEvent.ITEM_ROLL_OVER); 1255 colorPickerEvent.index = focusedIndex; 1256 colorPickerEvent.color = getColor(focusedIndex); 1257 dispatchEvent(colorPickerEvent); 1258 } 1259 } 1260 else 1261 { 1262 if (highlight.visible == true && isOverGrid && lastIndex != -1) 1263 { 1264 highlight.visible = false; 1265 1266 // Dispatch a ColorPickerEvent with type "itemRollOut". 1267 colorPickerEvent = new ColorPickerEvent( 1268 ColorPickerEvent.ITEM_ROLL_OUT); 1269 colorPickerEvent.index = lastIndex; 1270 colorPickerEvent.color = getColor(lastIndex); 1271 dispatchEvent(colorPickerEvent); 1272 } 1273 1274 isOverGrid = false; 1275 } 1276 } 1277 } 1278 1279 /** 1280 * @private 1281 */ 1282 private function swatches_clickHandler(event:MouseEvent):void 1283 { 1284 if (!enabled) 1285 return; 1286 1287 if (mouseX > grid.left && mouseX < grid.right && 1288 mouseY > grid.top && mouseY < grid.bottom) 1289 { 1290 selectedIndex = focusedIndex; 1291 1292 if (ColorPicker(owner).selectedIndex != selectedIndex) 1293 { 1294 ColorPicker(owner).selectedIndex = selectedIndex; 1295 1296 var cpEvent:ColorPickerEvent = 1297 new ColorPickerEvent(ColorPickerEvent.CHANGE); 1298 cpEvent.index = selectedIndex; 1299 cpEvent.color = getColor(selectedIndex); 1300 ColorPicker(owner).dispatchEvent(cpEvent); 1301 } 1302 1303 ColorPicker(owner).close(); // owner = ColorPicker 1304 } 1305 } 1306 1307 /** 1308 * @private 1309 */ 1310 private function textInput_keyDownHandler(event:KeyboardEvent):void 1311 { 1312 // Redispatch the event from the ColorPicker 1313 // and let its keyDownHandler() handle it. 1314 ColorPicker(owner).dispatchEvent(event); 1315 } 1316 1317 /** 1318 * @private 1319 */ 1320 private function textInput_changeHandler(event:Event):void 1321 { 1322 // Handle events from hex TextField. 1323 var color:String = TextInput(event.target).text; 1324 if (color.charAt(0) == "#") 1325 { 1326 textInput.maxChars = 7; 1327 color = "0x"+color.substring(1); 1328 } 1329 else if (color.substring(0,2) == "0x") 1330 { 1331 textInput.maxChars = 8; 1332 } 1333 else 1334 { 1335 textInput.maxChars = 6; 1336 color = "0x"+color; 1337 } 1338 1339 highlight.visible = false; 1340 isOverGrid = false; 1341 selectedColor = Number(color); 1342 1343 dispatchEvent(new Event("change")); 1344 } 1345} 1346 1347} 1348