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.GradientType;
16import flash.utils.getQualifiedClassName;
17import flash.utils.describeType;
18import mx.containers.BoxDirection;
19import mx.core.IButton;
20import mx.core.UIComponent;
21import mx.skins.Border;
22import mx.styles.StyleManager;
23import mx.utils.ColorUtil;
24
25/**
26 *  The skin for all the states of the ButtonBarButtons in a ButtonBar.
27 *
28 *  @langversion 3.0
29 *  @playerversion Flash 9
30 *  @playerversion AIR 1.1
31 *  @productversion Flex 3
32 */
33public class ButtonBarButtonSkin extends Border
34{
35	include "../../core/Version.as";
36
37	//--------------------------------------------------------------------------
38	//
39	//  Class variables
40	//
41	//--------------------------------------------------------------------------
42
43	/**
44	 *  @private
45	 */
46	private static var cache:Object = {};
47
48	//--------------------------------------------------------------------------
49	//
50	//  Class methods
51	//
52	//--------------------------------------------------------------------------
53
54	/**
55	 *  @private
56	 *  Several colors used for drawing are calculated from the base colors
57	 *  of the component (themeColor, borderColor and fillColors).
58	 *  Since these calculations can be a bit expensive,
59	 *  we calculate once per color set and cache the results.
60	 */
61	private static function calcDerivedStyles(themeColor:uint,
62											  fillColor0:uint,
63											  fillColor1:uint):Object
64	{
65		var key:String = HaloColors.getCacheKey(themeColor,
66												fillColor0, fillColor1);
67
68		if (!cache[key])
69		{
70			var o:Object = cache[key] = {};
71
72			// Cross-component styles.
73			HaloColors.addHaloColors(o, themeColor, fillColor0, fillColor1);
74
75			// Button-specific styles.
76			o.innerEdgeColor1 = ColorUtil.adjustBrightness2(fillColor0, -10);
77			o.innerEdgeColor2 = ColorUtil.adjustBrightness2(fillColor1, -25);
78		}
79
80		return cache[key];
81	}
82
83	//--------------------------------------------------------------------------
84	//
85	//  Constructor
86	//
87	//--------------------------------------------------------------------------
88
89	/**
90	 *  Constructor.
91	 *
92	 *  @langversion 3.0
93	 *  @playerversion Flash 9
94	 *  @playerversion AIR 1.1
95	 *  @productversion Flex 3
96	 */
97	public function ButtonBarButtonSkin()
98	{
99		super();
100	}
101
102	//--------------------------------------------------------------------------
103	//
104	//  Overridden properties
105	//
106	//--------------------------------------------------------------------------
107
108	//----------------------------------
109	//  measuredWidth
110	//----------------------------------
111
112	/**
113	 *  @private
114	 */
115	override public function get measuredWidth():Number
116	{
117		return UIComponent.DEFAULT_MEASURED_MIN_WIDTH;
118	}
119
120	//----------------------------------
121	//  measuredHeight
122	//----------------------------------
123
124	/**
125	 *  @private
126	 */
127	override public function get measuredHeight():Number
128	{
129		return UIComponent.DEFAULT_MEASURED_MIN_HEIGHT;
130	}
131
132	//--------------------------------------------------------------------------
133	//
134	//  Overridden methods
135	//
136	//--------------------------------------------------------------------------
137
138	/**
139	 *  @private
140	 */
141	override protected function updateDisplayList(w:Number, h:Number):void
142	{
143		super.updateDisplayList(w, h);
144
145		// User-defined styles.
146		var borderColor:uint = getStyle("borderColor");
147		var cornerRadius:Number = getStyle("cornerRadius");
148		var fillAlphas:Array = getStyle("fillAlphas");
149		var fillColors:Array = getStyle("fillColors");
150
151        if (styleName is UIComponent)
152            styleName.styleManager.getColorNames(fillColors);
153        else
154            StyleManager.getStyleManager(null).getColorNames(fillColors);
155
156        var highlightAlphas:Array = getStyle("highlightAlphas");
157		var themeColor:uint = getStyle("themeColor");
158
159		// Derivative styles.
160		var derStyles:Object = calcDerivedStyles(themeColor, fillColors[0],
161												 fillColors[1]);
162
163		var borderColorDrk1:Number =
164			ColorUtil.adjustBrightness2(borderColor, -50);
165
166		var themeColorDrk1:Number =
167			ColorUtil.adjustBrightness2(themeColor, -25);
168
169		var emph:Boolean = false;
170
171		if (parent is IButton)
172			emph = (parent as IButton).emphasized;
173
174		var tmp:Number;
175
176		var bar:Object = parent && parent.parent && isButtonBar(parent.parent) ? parent.parent : null;
177		var horizontal:Boolean = true;
178		var pos:int = 0;
179
180		if (bar)
181		{
182			if (bar.direction == BoxDirection.VERTICAL)
183				horizontal = false;
184
185			// first: -1, middle: 0, last: 1
186			var index:int = bar.getChildIndex(parent);
187			pos = (index == 0 ? -1 : (index == bar.numChildren - 1 ? 1 : 0));
188		}
189
190		var radius:Object = getCornerRadius(pos, horizontal, cornerRadius);
191		var cr:Object = getCornerRadius(pos, horizontal, cornerRadius);
192		var cr1:Object = getCornerRadius(pos, horizontal, cornerRadius - 1);
193		var cr2:Object = getCornerRadius(pos, horizontal, cornerRadius - 2);
194		var cr3:Object = getCornerRadius(pos, horizontal, cornerRadius - 3);
195
196		graphics.clear();
197
198		switch (name)
199		{
200			case "selectedUpSkin":
201			case "selectedOverSkin":
202			{
203				// button border/edge
204				drawRoundRect(
205					0, 0, w, h, cr,
206					[ themeColor, themeColorDrk1 ], 1,
207					verticalGradientMatrix(0, 0, w, h ),
208					GradientType.LINEAR, null,
209					{ x: 2, y: 2, w: w - 4, h: h - 4, r: cr2 });
210
211				// button fill
212				drawRoundRect(
213					1, 1, w - 2, h - 2, cr1,
214					[ fillColors[1], fillColors[1] ],
215					[ fillAlphas[0], fillAlphas[1] ],
216					verticalGradientMatrix(0, 0, w - 2, h - 2));
217
218				break;
219			}
220
221			case "upSkin":
222			{
223   				var upFillColors:Array = [ fillColors[0], fillColors[1] ];
224   				var upFillAlphas:Array = [ fillAlphas[0], fillAlphas[1] ];
225
226				if (emph)
227				{
228					// button border/edge
229					drawRoundRect(
230						0, 0, w, h, cr,
231						[ themeColor, themeColorDrk1 ], 1,
232						verticalGradientMatrix(0, 0, w, h ),
233						GradientType.LINEAR, null,
234						{ x: 2, y: 2, w: w - 4, h: h - 4, r: cr2 });
235
236					// button fill
237					drawRoundRect(
238						2, 2, w - 4, h - 4, cr2,
239						upFillColors, upFillAlphas,
240						verticalGradientMatrix(1, 1, w - 2, h - 2));
241
242					// top highlight
243					if (!(radius is Number))
244						{ radius.bl = radius.br = 0;}
245					drawRoundRect(
246						2, 2, w - 4, (h - 4) / 2, radius,
247						[ 0xFFFFFF, 0xFFFFFF ], highlightAlphas,
248						verticalGradientMatrix(2, 2, w - 2, (h - 4) / 2));
249				}
250				else
251				{
252					// button border/edge
253					drawRoundRect(
254						0, 0, w, h, cr,
255						[ borderColor, borderColorDrk1 ], 1,
256						verticalGradientMatrix(0, 0, w, h ),
257						GradientType.LINEAR, null,
258						{ x: 1, y: 1, w: w - 2, h: h - 2, r: cr1 });
259
260					// button fill
261					drawRoundRect(
262						1, 1, w - 2, h - 2, cr1,
263						upFillColors, upFillAlphas,
264						verticalGradientMatrix(1, 1, w - 2, h - 2));
265
266					// top highlight
267					if (!(radius is Number))
268						{ radius.bl = radius.br = 0;}
269					drawRoundRect(
270						1, 1, w - 2, (h - 2) / 2, radius,
271						[ 0xFFFFFF, 0xFFFFFF ], highlightAlphas,
272						verticalGradientMatrix(1, 1, w - 2, (h - 2) / 2));
273				}
274				break;
275			}
276
277			case "overSkin":
278			{
279				var overFillColors:Array;
280				if (fillColors.length > 2)
281					overFillColors = [ fillColors[2], fillColors[3] ];
282				else
283					overFillColors = [ fillColors[0], fillColors[1] ];
284
285				var overFillAlphas:Array;
286				if (fillAlphas.length > 2)
287					overFillAlphas = [ fillAlphas[2], fillAlphas[3] ];
288  				else
289					overFillAlphas = [ fillAlphas[0], fillAlphas[1] ];
290
291				// button border/edge
292				drawRoundRect(
293					0, 0, w, h, cr,
294					[ themeColor, derStyles.themeColDrk1 ], 1,
295					verticalGradientMatrix(0, 0, w, h),
296					GradientType.LINEAR, null,
297					{ x: 1, y: 1, w: w - 2, h: h - 2, r: cr1 });
298
299				// button fill
300				drawRoundRect(
301					1, 1, w - 2, h - 2, cr1,
302					overFillColors, overFillAlphas,
303					verticalGradientMatrix(0, 0, w - 2, h - 2));
304
305				// top highlight
306				if (!(radius is Number))
307					{ radius.bl = radius.br = 0;}
308				drawRoundRect(
309					1, 1, w - 2, (h - 2) / 2, radius,
310					[ 0xFFFFFF, 0xFFFFFF ], highlightAlphas,
311					verticalGradientMatrix(1, 1, w - 2, (h - 2) / 2));
312				break;
313			}
314
315			case "downSkin":
316			case "selectedDownSkin":
317			{
318				// button border/edge
319				drawRoundRect(
320					0, 0, w, h, cr,
321					[ themeColor, derStyles.themeColDrk1 ], 1,
322					verticalGradientMatrix(0, 0, w, h));
323
324				// button fill
325				drawRoundRect(
326					1, 1, w - 2, h - 2, cr1,
327					[ derStyles.fillColorPress1, derStyles.fillColorPress2 ], 1,
328					verticalGradientMatrix(0, 0, w - 2, h - 2));
329
330				// top highlight
331				if (!(radius is Number))
332					{ radius.bl = radius.br = 0;}
333				drawRoundRect(
334					1, 1, w - 2, (h - 2) / 2, radius,
335					[ 0xFFFFFF, 0xFFFFFF ], highlightAlphas,
336					verticalGradientMatrix(1, 1, w - 2, (h - 2) / 2));
337
338				break;
339			}
340
341			case "disabledSkin":
342			case "selectedDisabledSkin":
343			{
344                var disFillColors:Array = [ fillColors[0], fillColors[1] ];
345
346                var disFillAlphas:Array =
347                    [ Math.max( 0, fillAlphas[0] - 0.15),
348                      Math.max( 0, fillAlphas[1] - 0.15) ];
349
350				// outer edge
351				drawRoundRect(
352					0, 0, w, h, cr,
353					[ borderColor, borderColorDrk1 ], 0.5,
354					verticalGradientMatrix(0, 0, w, h ),
355					GradientType.LINEAR, null,
356					{ x: 1, y: 1, w: w - 2, h: h - 2, r: cr1 } );
357
358				// button fill
359                drawRoundRect(
360                    1, 1, w - 2, h - 2, cr1,
361                    disFillColors, disFillAlphas,
362                    verticalGradientMatrix(0, 0, w - 2, h - 2));
363
364				break;
365			}
366		}
367	}
368
369	//--------------------------------------------------------------------------
370	//
371	//  Methods
372	//
373	//--------------------------------------------------------------------------
374
375	/**
376	 *  @private
377	 */
378	private function getCornerRadius(pos:int, horizontal:Boolean,
379									 radius:Number):Object
380	{
381		if (pos == 0)
382			return 0;
383
384		radius = Math.max(0, radius);
385
386		if (horizontal)
387		{
388			if (pos == -1)
389				return { tl: radius, tr: 0, bl: radius, br: 0 };
390			else // pos == 1
391				return { tl: 0, tr: radius, bl: 0, br: radius };
392		}
393		else
394		{
395			if (pos == -1)
396				return { tl: radius, tr: radius, bl: 0, br: 0 };
397			else // pos == 1
398				return { tl: 0, tr: 0, bl: radius, br: radius };
399		}
400	}
401
402	/**
403	 *  We don't use 'is' to prevent dependency issues
404	 *
405	 *  @langversion 3.0
406	 *  @playerversion Flash 9
407	 *  @playerversion AIR 1.1
408	 *  @productversion Flex 3
409	 */
410	private static var bbars:Object = {};
411
412	private static function isButtonBar(parent:Object):Boolean
413	{
414		var s:String = getQualifiedClassName(parent);
415		if (bbars[s] == 1)
416			return true;
417
418		if (bbars[s] == 0)
419			return false;
420
421		if (s == "mx.controls::ButtonBar")
422		{
423			bbars[s] == 1;
424			return true;
425		}
426
427		var x:XML = describeType(parent);
428		var xmllist:XMLList = x.extendsClass.(@type == "mx.controls::ButtonBar");
429		if (xmllist.length() == 0)
430		{
431			bbars[s] = 0;
432			return false;
433		}
434
435		bbars[s] = 1;
436		return true;
437	}
438
439}
440
441}
442