1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2005-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.skins.halo 13{ 14 15import flash.display.DisplayObject; 16import flash.display.GradientType; 17import mx.core.IFlexDisplayObject; 18import mx.core.UIComponent; 19import mx.core.mx_internal; 20import mx.styles.StyleManager; 21import mx.utils.ColorUtil; 22import mx.core.IProgrammaticSkin; 23 24/** 25 * The skin for all the states of a PopUpButton. 26 */ 27public class PopUpButtonSkin extends UIComponent implements IProgrammaticSkin 28{ 29 include "../../core/Version.as"; 30 31 //-------------------------------------------------------------------------- 32 // 33 // Class variables 34 // 35 //-------------------------------------------------------------------------- 36 37 /** 38 * @private 39 */ 40 private static var cache:Object = {}; 41 42 //-------------------------------------------------------------------------- 43 // 44 // Class methods 45 // 46 //-------------------------------------------------------------------------- 47 48 /** 49 * @private 50 * Several colors used for drawing are calculated from the base colors 51 * of the component (themeColor, borderColor and fillColors). 52 * Since these calculations can be a bit expensive, 53 * we calculate once per color set and cache the results. 54 */ 55 private static function calcDerivedStyles(themeColor:uint, 56 fillColor0:uint, 57 fillColor1:uint):Object 58 { 59 var key:String = HaloColors.getCacheKey(themeColor, 60 fillColor0, fillColor1); 61 62 if (!cache[key]) 63 { 64 var o:Object = cache[key] = {}; 65 66 // Cross-component styles. 67 HaloColors.addHaloColors(o, themeColor, fillColor0, fillColor1); 68 } 69 70 return cache[key]; 71 } 72 73 //-------------------------------------------------------------------------- 74 // 75 // Constructor 76 // 77 //-------------------------------------------------------------------------- 78 79 /** 80 * Constructor. 81 */ 82 public function PopUpButtonSkin() 83 { 84 super(); 85 86 mouseEnabled = false; 87 } 88 89 //-------------------------------------------------------------------------- 90 // 91 // Overridden properties 92 // 93 //-------------------------------------------------------------------------- 94 95 96 //---------------------------------- 97 // measuredWidth 98 //---------------------------------- 99 100 /** 101 * @private 102 */ 103 override public function get measuredWidth():Number 104 { 105 return DEFAULT_MEASURED_MIN_WIDTH; 106 } 107 108 //---------------------------------- 109 // measuredHeight 110 //---------------------------------- 111 112 /** 113 * @private 114 */ 115 override public function get measuredHeight():Number 116 { 117 return DEFAULT_MEASURED_MIN_HEIGHT; 118 } 119 120 //-------------------------------------------------------------------------- 121 // 122 // Overridden methods 123 // 124 //-------------------------------------------------------------------------- 125 126 /** 127 * @private 128 */ 129 override protected function updateDisplayList(w:Number, h:Number):void 130 { 131 super.updateDisplayList(w, h); 132 133 // User-defined styles. 134 var arrowColor:uint = getStyle("iconColor"); 135 var borderColor:uint = getStyle("borderColor"); 136 var cornerRadius:Number = getStyle("cornerRadius"); 137 var fillAlphas:Array = getStyle("fillAlphas"); 138 var fillColors:Array = getStyle("fillColors"); 139 StyleManager.getColorNames(fillColors); 140 var highlightAlphas:Array = getStyle("highlightAlphas"); 141 var themeColor:uint = getStyle("themeColor"); 142 143 // Derivative styles. 144 var derStyles:Object = calcDerivedStyles(themeColor, fillColors[0], 145 fillColors[1]); 146 147 var borderColorDrk1:Number = 148 ColorUtil.adjustBrightness2(borderColor, -50); 149 150 var themeColorDrk1:Number = 151 ColorUtil.adjustBrightness2(themeColor, -25); 152 153 var popUpIcon:IFlexDisplayObject = 154 IFlexDisplayObject(getChildByName("popUpIcon")); 155 156 if (!popUpIcon) 157 { 158 var popUpIconClass:Class = Class(getStyle("popUpIcon")); 159 popUpIcon = new popUpIconClass(); 160 DisplayObject(popUpIcon).name = "popUpIcon"; 161 addChild(DisplayObject(popUpIcon)); 162 DisplayObject(popUpIcon).visible = true; 163 } 164 165 var arrowButtonWidth:Number = Math.max(getStyle("arrowButtonWidth"), 166 popUpIcon.width + 3 + 1); 167 168 var dividerPosX:Number = w - arrowButtonWidth; 169 170 popUpIcon.move(w - (arrowButtonWidth + popUpIcon.width) / 2, 171 (h - popUpIcon.height) / 2); 172 173 var cr:Number = Math.max(0, cornerRadius); 174 var cr1:Number = Math.max(0, cornerRadius - 1); 175 176 var upFillColors:Array; 177 var upFillAlphas:Array; 178 179 var overFillColors:Array; 180 var overFillAlphas:Array; 181 182 graphics.clear(); 183 184 switch (name) 185 { 186 case "upSkin": 187 { 188 upFillColors = [ fillColors[0], fillColors[1] ]; 189 upFillAlphas = [ fillAlphas[0], fillAlphas[1] ]; 190 191 // button border/edge 192 drawRoundRect( 193 0, 0, w, h, cr, 194 [ borderColor, borderColorDrk1 ], 1, 195 verticalGradientMatrix(0, 0, w, h), 196 GradientType.LINEAR, null, 197 { x: 1, y: 1, w: w - 2, h: h - 2, r: cornerRadius - 1 }); 198 199 drawRoundRect( 200 dividerPosX, 1, 1, h - 2, 0, 201 [ borderColor, borderColorDrk1 ], 1, 202 verticalGradientMatrix(0, 0, w, h)); 203 204 // button fill 205 drawRoundRect( 206 1, 1, w - 2, h - 2, cr1, 207 upFillColors, upFillAlphas, 208 verticalGradientMatrix(1, 1, w - 2, h - 2), 209 GradientType.LINEAR, null, 210 { x: dividerPosX, y: 1, w: 1, h: h - 2, r: 0 }); 211 212 // top highlight 213 drawRoundRect( 214 1, 1, w - 2, (h - 2) / 2, 215 { tl: cr1, tr: cr1, bl: 0, br: 0 }, 216 [ 0xFFFFFF, 0xFFFFFF ], highlightAlphas, 217 verticalGradientMatrix(1, 1, w - 2, (h - 2) / 2), 218 GradientType.LINEAR, null, 219 { x: dividerPosX, y: 1, w: 1, h: (h - 2) / 2, r: 0 }); 220 221 // side bevel highlight edges 222 drawRoundRect( 223 dividerPosX - 1, 1, 1, h - 2, 0, 224 borderColor, 0); 225 drawRoundRect( 226 dividerPosX + 1, 1, 1, h - 2, 0, 227 borderColor, 0); 228 229 break; 230 } 231 232 case "overSkin": // for hover on the main button (left) side 233 { 234 upFillColors = [ fillColors[0], fillColors[1] ]; 235 upFillAlphas = [ fillAlphas[0], fillAlphas[1] ]; 236 237 if (fillColors.length > 2) 238 overFillColors = [ fillColors[2], fillColors[3] ]; 239 else 240 overFillColors = [ fillColors[0], fillColors[1] ]; 241 242 if (fillAlphas.length > 2) 243 overFillAlphas = [ fillAlphas[2], fillAlphas[3] ]; 244 else 245 overFillAlphas = [ fillAlphas[0], fillAlphas[1] ]; 246 247 // button border/edge 248 drawRoundRect( 249 0, 0, w, h, cr, 250 [ themeColor, themeColorDrk1 ], 1, 251 verticalGradientMatrix(0, 0, w, h), 252 GradientType.LINEAR, null, 253 { x: 1, y: 1, w: w - 2, h: h - 2, r: cornerRadius - 1 }); 254 255 drawRoundRect( 256 dividerPosX, 1, 1, h - 2, 0, 257 [ themeColor, themeColorDrk1 ], 1, 258 verticalGradientMatrix(0, 0, w, h)); 259 // button fill 260 drawRoundRect( 261 1, 1, w - 2, h - 2, cr1, 262 upFillColors, upFillAlphas, 263 verticalGradientMatrix(1, 1, w - 2, h - 2), 264 GradientType.LINEAR, null, 265 { x: dividerPosX, y: 1, w: 1, h: h - 2, 266 r: getRadius(cr1, true) }); 267 268 // left/main button fill 269 drawRoundRect( 270 1, 1, w - arrowButtonWidth - 2, h - 2, 271 getRadius(cr1, true), 272 overFillColors, overFillAlphas, 273 verticalGradientMatrix(1, 1, dividerPosX - 2, h - 2)); 274 275 // top highlight 276 drawRoundRect( 277 1, 1, w - 2, (h -2) / 2, 278 { tl: cr1, tr: cr1, bl: 0, br: 0 }, 279 [ 0xFFFFFF, 0xFFFFFF ], highlightAlphas, 280 verticalGradientMatrix(1, 1, w - 2, (h - 2) / 2), 281 GradientType.LINEAR, null, 282 { x: dividerPosX, y: 1, w: 1, h: (h - 2) / 2, r: 0 }); 283 284 // side bevel highlight edges 285 drawRoundRect( 286 dividerPosX - 1, 1, 1, h - 2, 0, 287 themeColor, 0.35); 288 289 break; 290 } 291 292 case "popUpOverSkin": // for hover on the arrow-button (right) side 293 { 294 upFillColors = [ fillColors[0], fillColors[1] ]; 295 upFillAlphas = [ fillAlphas[0], fillAlphas[1] ]; 296 297 if (fillColors.length > 2) 298 overFillColors = [ fillColors[2], fillColors[3] ]; 299 else 300 overFillColors = [ fillColors[0], fillColors[1] ]; 301 302 if (fillAlphas.length > 2) 303 overFillAlphas = [ fillAlphas[2], fillAlphas[3] ]; 304 else 305 overFillAlphas = [ fillAlphas[0], fillAlphas[1] ]; 306 307 // button border/edge 308 drawRoundRect( 309 0, 0, w, h, cr, 310 [ themeColor, themeColorDrk1 ], 1, 311 verticalGradientMatrix(0, 0, w, h), 312 GradientType.LINEAR, null, 313 { x: 1, y: 1, w: w - 2, h: h - 2, r: cornerRadius - 1 }); 314 315 drawRoundRect( 316 dividerPosX, 1, 1, h - 2, 0, 317 [ themeColor, themeColorDrk1 ], 1, 318 verticalGradientMatrix(0, 0, w, h)); 319 320 // button fill 321 drawRoundRect( 322 1, 1, w - 2, h - 2, getRadius(cr1, true), 323 upFillColors, upFillAlphas, 324 verticalGradientMatrix(1, 1, w - 2, h - 2), 325 GradientType.LINEAR, null, 326 { x: dividerPosX, y: 1, w: arrowButtonWidth - 1, h: h - 2, 327 r: getRadius(cr1, true) }); 328 329 // right button fill 330 drawRoundRect( 331 dividerPosX + 1, 1, arrowButtonWidth - 2, h - 2, 332 getRadius(cr1, false), 333 overFillColors, overFillAlphas, 334 verticalGradientMatrix(dividerPosX, 0, 335 arrowButtonWidth - 1, h - 2)); 336 337 // top highlight 338 drawRoundRect( 339 1, 1, w - 2, (h -2) / 2, 340 { tl: cr1, tr: cr1, bl: 0, br: 0 }, 341 [ 0xFFFFFF, 0xFFFFFF ], highlightAlphas, 342 verticalGradientMatrix(1, 1, w - 2, (h - 2) / 2), 343 GradientType.LINEAR, null, 344 { x: dividerPosX, y: 1, w: 1, h: (h - 2) / 2, r: 0 }); 345 346 // side bevel highlight edges 347 drawRoundRect( 348 dividerPosX + 1, 1, 1, h - 2, 0, 349 themeColor, 0.35); 350 351 break; 352 } 353 354 case "downSkin": // for press on the main button (left) side 355 { 356 upFillColors = [ fillColors[0], fillColors[1] ]; 357 upFillAlphas = [ fillAlphas[0], fillAlphas[1] ]; 358 359 // button border/ddge 360 drawRoundRect( 361 0, 0, w, h, cr, 362 [ themeColor, themeColorDrk1 ], 1, 363 verticalGradientMatrix(0, 0, w, h ), 364 GradientType.LINEAR, null, 365 { x: 1, y: 1, w: w - 2, h: h - 2, r: cornerRadius - 1 }); 366 367 drawRoundRect( 368 dividerPosX, 1, 1, h - 2, 0, 369 [ themeColor, themeColorDrk1 ], 1, 370 verticalGradientMatrix(0, 0, w, h)); 371 372 // button fill 373 drawRoundRect( 374 1, 1, w - 2, h - 2, cr1, 375 upFillColors, upFillAlphas, 376 verticalGradientMatrix(1, 1, w - 2, h - 2), 377 GradientType.LINEAR, null, 378 { x: dividerPosX, y: 1, w: 1, h: h - 2, r: 0 }); 379 380 // left/main button fill 381 drawRoundRect( 382 1, 1, w - arrowButtonWidth - 2, h - 2, 383 getRadius(cr1, true), 384 [ derStyles.fillColorPress1, derStyles.fillColorPress2], 1, 385 verticalGradientMatrix(1, 1, dividerPosX - 2, h - 2)); 386 387 // top highlight (checked, works) 388 drawRoundRect( 389 1, 1, w - 2, (h -2) / 2, 390 { tl: cr1, tr: cr1, bl: 0, br: 0 }, 391 [ 0xFFFFFF, 0xFFFFFF ], highlightAlphas, 392 verticalGradientMatrix(1, 1, w - 2, (h - 2) / 2), 393 GradientType.LINEAR, null, 394 { x: dividerPosX, y: 1, w: 1, h: (h -2) / 2, r: 0 }); 395 396 // side bevel highlight edges 397 drawRoundRect( 398 dividerPosX - 1, 1, 1, h - 2, 0, 399 themeColorDrk1, 0.3); 400 drawRoundRect( 401 dividerPosX + 1, 1, 1, h - 2, 0, 402 borderColor, 0); 403 404 break; 405 } 406 407 case "popUpDownSkin": // for press on the arrow-button (right) side 408 { 409 upFillColors = [ fillColors[0], fillColors[1] ]; 410 upFillAlphas = [ fillAlphas[0], fillAlphas[1] ]; 411 412 // button border/edge 413 drawRoundRect( 414 0, 0, w, h, cr, 415 [ themeColor, themeColorDrk1 ], 1, 416 verticalGradientMatrix(0, 0, w, h ), 417 GradientType.LINEAR, null, 418 { x: 1, y: 1, w: w - 2, h: h - 2, r: cornerRadius - 1 }); 419 420 drawRoundRect( 421 dividerPosX, 1, 1, h - 2, 0, 422 [ themeColor, themeColorDrk1 ], 1, 423 verticalGradientMatrix(0, 0, w, h)); 424 425 // button fill 426 drawRoundRect( 427 1, 1, w - 2, h - 2, cr1, 428 upFillColors, upFillAlphas, 429 verticalGradientMatrix(1, 1, w - 2, h - 2), 430 GradientType.LINEAR, null, 431 { x: dividerPosX, y: 1, w: 1, h: h - 2, r: 0 }); 432 433 // right button fill 434 drawRoundRect( 435 dividerPosX + 1, 1, arrowButtonWidth - 2, h - 2, 436 getRadius(cr1, false), 437 [ derStyles.fillColorPress1, 438 derStyles.fillColorPress2], 1, 439 verticalGradientMatrix(dividerPosX, 0, 440 arrowButtonWidth - 1, h - 2)); 441 442 // top highlight 443 drawRoundRect( 444 1, 1, w - 2, (h -2) / 2, 445 { tl: cr1, tr: cr1, bl: 0, br: 0 }, 446 [ 0xFFFFFF, 0xFFFFFF ], highlightAlphas, 447 verticalGradientMatrix(1, 1, w - 2, (h - 2) / 2), 448 GradientType.LINEAR, null, 449 { x: dividerPosX, y: 1, w: 1, h: (h - 2) / 2, r: 0 }); 450 451 // side bevel highlight edges 452 drawRoundRect( 453 dividerPosX - 1, 1, 1, h - 2, 0, 454 borderColor, 0); 455 drawRoundRect( 456 dividerPosX + 1, 1, 1, h - 2, 0, 457 themeColorDrk1, 0.3); 458 459 break; 460 } 461 462 case "disabledSkin": 463 { 464 arrowColor = getStyle("disabledIconColor"); 465 466 var disFillColors:Array = [ fillColors[0], fillColors[1] ]; 467 468 var disFillAlphas:Array = 469 [ Math.max(0, fillAlphas[0] - 0.15), 470 Math.max(0, fillAlphas[1] - 0.15) ]; 471 472 // outer edge 473 drawRoundRect( 474 0, 0, w, h, cornerRadius, 475 [ borderColor, borderColorDrk1 ], 0.5, 476 verticalGradientMatrix(0, 0, w, h ), 477 GradientType.LINEAR, null, 478 { x: 1, y: 1, w: w - 2, h: h - 2, r: cornerRadius - 1 }); 479 480 drawRoundRect( 481 dividerPosX, 1, 1, h - 2, 0, 482 [ borderColor, borderColorDrk1 ], 0.5); 483 484 // button fill 485 drawRoundRect( 486 1, 1, w - 2, h - 2, cr1, 487 disFillColors, disFillAlphas, 488 verticalGradientMatrix(1, 1, w - 2, h - 2), 489 null, null, 490 { x: dividerPosX, y: 1, w: 1, h: h - 2, r: 0 }); 491 492 break; 493 } 494 } 495 496 if (popUpIcon is PopUpIcon) 497 PopUpIcon(popUpIcon).mx_internal::arrowColor = arrowColor; 498 } 499 500 //-------------------------------------------------------------------------- 501 // 502 // Methods 503 // 504 //-------------------------------------------------------------------------- 505 506 /** 507 * @private 508 */ 509 private function getRadius(r:Number, left:Boolean):Object 510 { 511 return left ? 512 { br: 0, bl: r, tr: 0, tl: r } : 513 { br: r, bl: 0, tr: r, tl: 0 }; 514 } 515} 516 517} 518