PageRenderTime 44ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/FlexPadLib/src/com/flexpad/skin/ToggleSwitchSkin.as

http://flexpad.googlecode.com/
ActionScript | 865 lines | 455 code | 123 blank | 287 comment | 14 complexity | 377dbc3890e859d1bd5f273461813bf5 MD5 | raw file
  1. ////////////////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // ADOBE SYSTEMS INCORPORATED
  4. // Copyright 2011 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. package com.flexpad.skin
  12. {
  13. import flash.display.BlendMode;
  14. import flash.display.DisplayObject;
  15. import flash.display.GradientType;
  16. import flash.display.Graphics;
  17. import flash.display.Sprite;
  18. import flash.events.Event;
  19. import mx.core.DPIClassification;
  20. import mx.core.IVisualElement;
  21. import mx.core.UIComponent;
  22. import mx.core.mx_internal;
  23. import mx.utils.ColorUtil;
  24. import spark.components.ToggleSwitch;
  25. import spark.components.supportClasses.StyleableTextField;
  26. import spark.core.SpriteVisualElement;
  27. import spark.skins.mobile.supportClasses.MobileSkin;
  28. import spark.skins.mobile160.assets.ToggleSwitch_contentShadow;
  29. import spark.skins.mobile240.assets.ToggleSwitch_contentShadow;
  30. import spark.skins.mobile320.assets.ToggleSwitch_contentShadow;
  31. use namespace mx_internal;
  32. /**
  33. * ActionScript-based skin for the ToggleSwitch control.
  34. * The colors of the component can
  35. * be customized using styles. This class is responsible for most of the
  36. * graphics drawing, with some additional fxg assets.
  37. *
  38. * @langversion 3.0
  39. * @playerversion AIR 3
  40. * @productversion Flex 4.6
  41. *
  42. * @see spark.components.ToggleSwitch
  43. */
  44. public class ToggleSwitchSkin extends MobileSkin
  45. {
  46. //----------------------------------------------------------------------------------------------
  47. //
  48. // Constructor
  49. //
  50. //----------------------------------------------------------------------------------------------
  51. /**
  52. * Constructor.
  53. *
  54. * @langversion 3.0
  55. * @playerversion AIR 3
  56. * @productversion Flex 4.6
  57. **/
  58. public function ToggleSwitchSkin()
  59. {
  60. super();
  61. switch(applicationDPI)
  62. {
  63. case DPIClassification.DPI_320:
  64. {
  65. layoutThumbWidth = 94;
  66. layoutThumbHeight = 56;
  67. layoutStrokeWeight = 2;
  68. layoutBorderSize = 2;
  69. layoutTextShadowOffset = -2;
  70. layoutInnerPadding = 14;
  71. layoutOuterPadding = 22;
  72. slidingContentOverlayClass = spark.skins.mobile320.assets.ToggleSwitch_contentShadow;
  73. break;
  74. }
  75. case DPIClassification.DPI_240:
  76. {
  77. layoutThumbWidth = 70;
  78. layoutThumbHeight = 42;
  79. layoutStrokeWeight = 2;
  80. layoutBorderSize = 1;
  81. layoutTextShadowOffset = -1;
  82. layoutInnerPadding = 10;
  83. layoutOuterPadding = 17;
  84. slidingContentOverlayClass = spark.skins.mobile240.assets.ToggleSwitch_contentShadow;
  85. break;
  86. }
  87. case DPIClassification.DPI_160:
  88. default:
  89. {
  90. layoutThumbWidth = 47;
  91. layoutThumbHeight = 28;
  92. layoutStrokeWeight = 1;
  93. layoutBorderSize = 1;
  94. layoutTextShadowOffset = -1;
  95. layoutInnerPadding = 7;
  96. layoutOuterPadding = 11;
  97. slidingContentOverlayClass = spark.skins.mobile160.assets.ToggleSwitch_contentShadow;
  98. break;
  99. }
  100. }
  101. layoutCornerEllipseSize = layoutThumbHeight;
  102. selectedLabel = resourceManager.getString("components","toggleSwitchSelectedLabel");
  103. unselectedLabel = resourceManager.getString("components","toggleSwitchUnselectedLabel");
  104. }
  105. //----------------------------------------------------------------------------------------------
  106. //
  107. // Variables
  108. //
  109. //----------------------------------------------------------------------------------------------
  110. /**
  111. * The width to draw the thumb skin part.
  112. *
  113. * @langversion 3.0
  114. * @playerversion AIR 3
  115. * @productversion Flex 4.6
  116. */
  117. protected var layoutThumbWidth:Number;
  118. /**
  119. * The height to draw the thumb skin part.
  120. *
  121. * @langversion 3.0
  122. * @playerversion AIR 3
  123. * @productversion Flex 4.6
  124. */
  125. protected var layoutThumbHeight:Number;
  126. /**
  127. * The corner radius of the thumb and track.
  128. *
  129. * @langversion 3.0
  130. * @playerversion AIR 3
  131. * @productversion Flex 4.6
  132. */
  133. protected var layoutCornerEllipseSize:Number;
  134. /**
  135. * The stroke weight outlining the graphics of the skin.
  136. *
  137. * @langversion 3.0
  138. * @playerversion AIR 3
  139. * @productversion Flex 4.6
  140. */
  141. protected var layoutStrokeWeight:Number;
  142. /**
  143. * The size of the border surrounding the component.
  144. *
  145. * @langversion 3.0
  146. * @playerversion AIR 3
  147. * @productversion Flex 4.6
  148. */
  149. protected var layoutBorderSize:Number;
  150. /**
  151. * The padding between the labels and the thumb.
  152. *
  153. * @langversion 3.0
  154. * @playerversion AIR 3
  155. * @productversion Flex 4.6
  156. */
  157. protected var layoutInnerPadding:Number;
  158. /**
  159. * The padding between the labels and the edge of the track.
  160. *
  161. * @langversion 3.0
  162. * @playerversion AIR 3
  163. * @productversion Flex 4.6
  164. */
  165. protected var layoutOuterPadding:Number;
  166. /**
  167. * The offset between a label and its shadow.
  168. *
  169. * @langversion 3.0
  170. * @playerversion AIR 3
  171. * @productversion Flex 4.6
  172. */
  173. protected var layoutTextShadowOffset:Number;
  174. /**
  175. * The label for the selected side of the component.
  176. * Exposed for styling purposes only.
  177. *
  178. * @langversion 3.0
  179. * @playerversion AIR 3
  180. * @productversion Flex 4.6
  181. */
  182. public var selectedLabelDisplay:LabelDisplayComponent;
  183. /**
  184. * The label for the unselected side of the component.
  185. * Exposed for styling purposes only.
  186. *
  187. * @langversion 3.0
  188. * @playerversion AIR 3
  189. * @productversion Flex 4.6
  190. */
  191. public var unselectedLabelDisplay:LabelDisplayComponent;
  192. /**
  193. * The content clipped by the track that slides to match the thumb's
  194. * position.
  195. * Contents include a background and the (un)selected labels.
  196. * The sliding content is stacked, from back to front, as background,
  197. * shadow, foreground.
  198. */
  199. private var slidingContentBackground:SpriteVisualElement;
  200. private var slidingContentForeground:UIComponent;
  201. private var slidingContentOverlayClass:Class;
  202. private var slidingContentOverlay:DisplayObject;
  203. /**
  204. * The contents inside the skin, not including the outline
  205. * stroke
  206. */
  207. private var contents:UIComponent;
  208. /**
  209. * The thumb erase overlay erases pixels behind the thumb. The thumb
  210. * content contains the thumb graphics, and sits above the overlay.
  211. */
  212. private var thumbEraseOverlay:Sprite;
  213. private var thumbContent:Sprite;
  214. //----------------------------------------------------------------------------------------------
  215. //
  216. // Skin parts
  217. //
  218. //----------------------------------------------------------------------------------------------
  219. /**
  220. * The thumb skin part.
  221. *
  222. * @langversion 3.0
  223. * @playerversion AIR 3
  224. * @productversion Flex 4.6
  225. */
  226. public var thumb:IVisualElement;
  227. /**
  228. * The track skin part.
  229. *
  230. * @langversion 3.0
  231. * @playerversion AIR 3
  232. * @productversion Flex 4.6
  233. */
  234. public var track:IVisualElement;
  235. //----------------------------------------------------------------------------------------------
  236. //
  237. // Overridden properties
  238. //
  239. //----------------------------------------------------------------------------------------------
  240. //----------------------------------
  241. // currentState
  242. //----------------------------------
  243. /**
  244. * @private
  245. */
  246. override public function set currentState(value:String):void
  247. {
  248. var isDown:Boolean = currentState && currentState.indexOf("down") >=0;
  249. super.currentState = value;
  250. if (isDown != currentState.indexOf("down") >= 0)
  251. {
  252. invalidateDisplayList();
  253. }
  254. }
  255. //----------------------------------------------------------------------------------------------
  256. //
  257. // Properties
  258. //
  259. //----------------------------------------------------------------------------------------------
  260. //----------------------------------
  261. // hostComponent
  262. //----------------------------------
  263. private var _hostComponent:ToggleSwitch;
  264. /**
  265. * @copy spark.skins.spark.ApplicationSkin#hostComponent
  266. */
  267. public function get hostComponent():ToggleSwitch
  268. {
  269. return _hostComponent;
  270. }
  271. /**
  272. * @private
  273. */
  274. public function set hostComponent(value:ToggleSwitch):void
  275. {
  276. if (_hostComponent)
  277. _hostComponent.removeEventListener("thumbPositionChanged", thumbPositionChanged_handler);
  278. _hostComponent = value;
  279. if (_hostComponent)
  280. _hostComponent.addEventListener("thumbPositionChanged", thumbPositionChanged_handler);
  281. }
  282. //----------------------------------
  283. // selectedLabel
  284. //----------------------------------
  285. private var _selectedLabel:String;
  286. /**
  287. * The text of the label showing when the component is selected.
  288. * Subclasses can set or override this property to customize the selected label.
  289. *
  290. * @langversion 3.0
  291. * @playerversion AIR 3
  292. * @productversion Flex 4.6
  293. */
  294. protected function get selectedLabel():String
  295. {
  296. return _selectedLabel;
  297. }
  298. protected function set selectedLabel(value:String):void
  299. {
  300. _selectedLabel = value;
  301. }
  302. //----------------------------------
  303. // unselectedLabel
  304. //----------------------------------
  305. private var _unselectedLabel:String;
  306. /**
  307. * The text of the label showing when the component is not selected.
  308. * Subclasses can set or override this property to customize the unselected label.
  309. *
  310. * @langversion 3.0
  311. * @playerversion AIR 3
  312. * @productversion Flex 4.6
  313. */
  314. protected function get unselectedLabel():String
  315. {
  316. return _unselectedLabel;
  317. }
  318. protected function set unselectedLabel(value:String):void
  319. {
  320. _unselectedLabel = value;
  321. }
  322. //----------------------------------------------------------------------------------------------
  323. //
  324. // Overridden Methods
  325. //
  326. //----------------------------------------------------------------------------------------------
  327. /**
  328. * @private
  329. * Redraw the graphics of the skin as necessary
  330. */
  331. override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
  332. {
  333. super.drawBackground(unscaledWidth, unscaledHeight);
  334. // calculate skin dimensions - outer stroke
  335. var calculatedContentWidth:Number = Math.max(unscaledWidth - 2 * layoutBorderSize,
  336. getElementPreferredWidth(thumb));
  337. var calculatedContentHeight:Number = Math.max(unscaledHeight - 2 * layoutBorderSize,
  338. getElementPreferredHeight(thumb));
  339. drawSlidingContent(calculatedContentWidth, calculatedContentHeight);
  340. drawTrack(calculatedContentWidth, calculatedContentHeight);
  341. drawThumb(calculatedContentWidth, calculatedContentHeight);
  342. drawMask(calculatedContentWidth, calculatedContentHeight);
  343. // simulate outer stroke using a larger filled rounded rect
  344. graphics.beginFill(0xffffff, 0.3);
  345. graphics.drawRoundRect(0, (calculatedContentHeight - layoutThumbHeight) / 2,
  346. calculatedContentWidth + 2 * layoutBorderSize,
  347. layoutThumbHeight + 2 * layoutBorderSize,
  348. layoutCornerEllipseSize + layoutBorderSize);
  349. graphics.endFill();
  350. }
  351. /**
  352. * @private
  353. * Resize and reposition as necessary
  354. */
  355. override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
  356. {
  357. super.layoutContents(unscaledWidth, unscaledHeight);
  358. // calculate skin dimensions - outer stroke
  359. var calculatedContentWidth:Number = Math.max(unscaledWidth - 2 * layoutBorderSize,
  360. getElementPreferredWidth(thumb));
  361. var calculatedContentHeight:Number = Math.max(unscaledHeight - 2 * layoutBorderSize,
  362. getElementPreferredHeight(thumb));
  363. setElementSize(contents, calculatedContentWidth, layoutThumbHeight);
  364. setElementPosition(contents, layoutBorderSize,
  365. layoutBorderSize + (calculatedContentHeight - layoutThumbHeight) / 2);
  366. layoutTrack(calculatedContentWidth, layoutThumbHeight);
  367. layoutThumb(calculatedContentWidth, layoutThumbHeight);
  368. // Sliding content must be positioned after the track & thumb have been sized
  369. layoutSlidingContent(calculatedContentWidth, layoutThumbHeight);
  370. layoutMask(calculatedContentWidth, layoutThumbHeight);
  371. }
  372. /**
  373. * @private
  374. */
  375. override protected function measure():void
  376. {
  377. // The skin must be at least as large as the thumb + outer stroke
  378. measuredMinWidth = layoutThumbWidth + 2 * layoutBorderSize;
  379. measuredMinHeight = layoutThumbWidth + 2 * layoutBorderSize;
  380. // The preferred size will display all label text
  381. var labelWidth:Number = Math.max(getElementPreferredWidth(selectedLabelDisplay),
  382. getElementPreferredWidth(unselectedLabelDisplay));
  383. measuredWidth = layoutThumbWidth + labelWidth + layoutInnerPadding +
  384. layoutOuterPadding + 2 * layoutBorderSize;
  385. measuredHeight = layoutThumbHeight + 2 * layoutBorderSize;
  386. }
  387. /**
  388. * @private
  389. */
  390. override protected function commitCurrentState():void
  391. {
  392. if (currentState && currentState.indexOf("disabled") >= 0)
  393. {
  394. alpha = 0.5;
  395. selectedLabelDisplay.showShadow(false);
  396. unselectedLabelDisplay.showShadow(false);
  397. }
  398. else
  399. {
  400. alpha = 1.0;
  401. selectedLabelDisplay.showShadow(true);
  402. unselectedLabelDisplay.showShadow(true);
  403. }
  404. }
  405. /**
  406. * @private
  407. */
  408. override protected function createChildren():void
  409. {
  410. super.createChildren();
  411. contents = new UIComponent();
  412. contents.blendMode = BlendMode.LAYER;
  413. addChild(contents);
  414. // SlidingContent: background, overlay, labels
  415. slidingContentBackground = new SpriteVisualElement();
  416. contents.addChild(slidingContentBackground);
  417. slidingContentOverlay = new slidingContentOverlayClass();
  418. contents.addChild(slidingContentOverlay);
  419. slidingContentForeground = new UIComponent();
  420. contents.addChild(slidingContentForeground);
  421. selectedLabelDisplay = new LabelDisplayComponent();
  422. selectedLabelDisplay.id = "selectedLabelDisplay";
  423. selectedLabelDisplay.text = selectedLabel;
  424. selectedLabelDisplay.shadowYOffset = layoutTextShadowOffset;
  425. slidingContentForeground.addChild(selectedLabelDisplay);
  426. unselectedLabelDisplay = new LabelDisplayComponent();
  427. unselectedLabelDisplay.id = "unselectedLabelDisplay";
  428. unselectedLabelDisplay.text = unselectedLabel;
  429. unselectedLabelDisplay.shadowYOffset = layoutTextShadowOffset;
  430. slidingContentForeground.addChild(unselectedLabelDisplay);
  431. // Track
  432. track = new SpriteVisualElement();
  433. contents.addChild(SpriteVisualElement(track));
  434. // Thumb
  435. thumb = new SpriteVisualElement();
  436. contents.addChild(SpriteVisualElement(thumb));
  437. thumbEraseOverlay = new Sprite();
  438. thumbEraseOverlay.blendMode = BlendMode.ERASE;
  439. SpriteVisualElement(thumb).addChild(thumbEraseOverlay);
  440. thumbContent = new Sprite();
  441. SpriteVisualElement(thumb).addChild(thumbContent);
  442. // Content clipping mask
  443. var contentMask:Sprite = new SpriteVisualElement();
  444. contents.mask = contentMask;
  445. contents.addChild(contentMask);
  446. }
  447. //----------------------------------------------------------------------------------------------
  448. //
  449. // Methods
  450. //
  451. //----------------------------------------------------------------------------------------------
  452. /**
  453. * Draw the sliding content background
  454. * SlidingContent's x origin matches the thumb's x origin, meaning some of
  455. * the background is drawn to the left, and some to the right.
  456. */
  457. private function drawSlidingContent(skinWidth:Number, skinHeight:Number):void
  458. {
  459. slidingContentBackground.graphics.clear();
  460. // selected side of the sliding content
  461. slidingContentBackground.graphics.beginFill(getStyle("accentColor"));
  462. slidingContentBackground.graphics.drawRect(layoutThumbWidth - skinWidth, 0, skinWidth - layoutThumbWidth / 2,
  463. layoutThumbHeight);
  464. slidingContentBackground.graphics.endFill();
  465. // unselected side of the sliding content
  466. slidingContentBackground.graphics.beginFill(ColorUtil.adjustBrightness2(getStyle("chromeColor"), -25));
  467. slidingContentBackground.graphics.drawRect(layoutThumbWidth / 2, 0, skinWidth - layoutThumbWidth / 2,
  468. layoutThumbHeight);
  469. slidingContentBackground.graphics.endFill();
  470. }
  471. /**
  472. * Lay out SlidingContent and its children. Because we only need the x,y
  473. * coordinate of SlidingContent, we can ignore its size.
  474. * The origin of SlidingContent overlaps the origin of the thumb, and the
  475. * positioning is handled by thumbPositionChanged_handler.
  476. */
  477. private function layoutSlidingContent(skinWidth:Number, skinHeight:Number):void
  478. {
  479. var visibleTrackWidth:Number = skinWidth - layoutThumbWidth;
  480. var labelWidth:Number = visibleTrackWidth - layoutInnerPadding - layoutOuterPadding;
  481. setElementSize(selectedLabelDisplay, labelWidth, layoutThumbHeight);
  482. setElementPosition(selectedLabelDisplay, -visibleTrackWidth + layoutOuterPadding, 0);
  483. setElementSize(unselectedLabelDisplay, labelWidth, layoutThumbHeight);
  484. setElementPosition(unselectedLabelDisplay, layoutThumbWidth + layoutInnerPadding, 0);
  485. setElementSize(slidingContentOverlay, skinWidth, layoutThumbHeight);
  486. setElementPosition(slidingContentOverlay, 0, (skinHeight - layoutThumbHeight) / 2);
  487. moveSlidingContent();
  488. }
  489. /**
  490. * Draw the track and its shadow
  491. */
  492. private function drawTrack(skinWidth:Number, skinHeight:Number):void
  493. {
  494. var graphics:Graphics = SpriteVisualElement(track).graphics;
  495. graphics.clear();
  496. graphics.lineStyle(layoutStrokeWeight, 0, .3);
  497. graphics.drawRoundRect(layoutStrokeWeight / 2, layoutStrokeWeight / 2,
  498. skinWidth - layoutStrokeWeight,
  499. (layoutThumbHeight - layoutStrokeWeight), (layoutCornerEllipseSize - layoutStrokeWeight / 2));
  500. graphics.lineStyle();
  501. }
  502. /**
  503. * Resize and reposition the track
  504. */
  505. private function layoutTrack(skinWidth:Number, skinHeight:Number):void
  506. {
  507. setElementSize(track, skinWidth, layoutThumbHeight);
  508. setElementPosition(track, 0, (skinHeight - layoutThumbHeight) / 2);
  509. }
  510. /**
  511. * Draw the thumb. The thumb has an outer border, inner gradient, and
  512. * inner highlight stroke.
  513. */
  514. private function drawThumb(skinWidth:Number, skinHeight:Number):void
  515. {
  516. var graphics:Graphics = thumbContent.graphics;
  517. var colors:Array = [];
  518. var alphas:Array = [];
  519. var ratios:Array = [];
  520. var baseColor:Number = getStyle("chromeColor");
  521. if (currentState && currentState.indexOf("down") >= 0)
  522. baseColor = ColorUtil.adjustBrightness(baseColor, -60);
  523. graphics.clear();
  524. // Thumb outline
  525. colors[0] = ColorUtil.adjustBrightness2(baseColor, -70);
  526. colors[1] = ColorUtil.adjustBrightness2(baseColor, -55);
  527. alphas[0] = 1;
  528. alphas[1] = 1;
  529. ratios[0] = 0;
  530. ratios[1] = 255;
  531. colorMatrix.createGradientBox(layoutThumbWidth, layoutThumbHeight, Math.PI / 2);
  532. graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, colorMatrix);
  533. graphics.drawRoundRect(0, 0, layoutThumbWidth, layoutThumbHeight, layoutCornerEllipseSize);
  534. graphics.endFill();
  535. // Base gradient fill, one stroke weight inside outline
  536. colors[0] = ColorUtil.adjustBrightness2(baseColor, -30);
  537. colors[1] = baseColor;
  538. colors[2] = ColorUtil.adjustBrightness2(baseColor, 20);
  539. alphas[2] = 1;
  540. ratios[0] = 0;
  541. ratios[1] = .7 * 255;
  542. ratios[2] = 255;
  543. colorMatrix.createGradientBox(layoutThumbWidth - layoutStrokeWeight * 2,
  544. layoutThumbHeight - layoutStrokeWeight * 2, Math.PI / 2);
  545. graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, colorMatrix);
  546. graphics.drawRoundRect(layoutStrokeWeight, layoutStrokeWeight,
  547. layoutThumbWidth - layoutStrokeWeight * 2,
  548. layoutThumbHeight - layoutStrokeWeight * 2, layoutCornerEllipseSize - layoutStrokeWeight * 2);
  549. graphics.endFill();
  550. // Thumb highlight, one stroke weight inside outline
  551. colors[0] = 0xffffff;
  552. colors[1] = 0xffffff;
  553. colors[2] = 0x0;
  554. alphas[0] = .9;
  555. alphas[1] = 0;
  556. alphas[2] = .2;
  557. ratios[0] = .33 * 255;
  558. ratios[1] = .5 * 255;
  559. ratios[2] = 255;
  560. colorMatrix.createGradientBox(layoutThumbWidth - layoutStrokeWeight * 3,
  561. layoutThumbHeight - layoutStrokeWeight * 3, Math.PI / 2);
  562. graphics.lineStyle(layoutStrokeWeight);
  563. graphics.lineGradientStyle(GradientType.LINEAR, colors, alphas, ratios, colorMatrix);
  564. graphics.drawRoundRect(layoutStrokeWeight * 1.5, layoutStrokeWeight * 1.5,
  565. layoutThumbWidth - layoutStrokeWeight * 3, layoutThumbHeight - layoutStrokeWeight * 3,
  566. layoutCornerEllipseSize - layoutStrokeWeight * 3);
  567. graphics.lineStyle();
  568. // Redraw the erase overlay as a silhouette of the thumb
  569. thumbEraseOverlay.graphics.clear();
  570. thumbEraseOverlay.graphics.beginFill(0);
  571. thumbEraseOverlay.graphics.drawRoundRect(0, 0, layoutThumbWidth, layoutThumbHeight, layoutCornerEllipseSize);
  572. thumbEraseOverlay.graphics.endFill();
  573. }
  574. /**
  575. * Resize the thumb. Its position is handled by the component.
  576. */
  577. private function layoutThumb(skinWidth:Number, skinHeight:Number):void
  578. {
  579. setElementSize(thumb, layoutThumbWidth, layoutThumbHeight);
  580. }
  581. /**
  582. * Draw the clipping mask for the component. This is roughly the
  583. * same as the track area.
  584. */
  585. private function drawMask(skinWidth:Number, skinHeight:Number):void
  586. {
  587. var graphics:Graphics = SpriteVisualElement(contents.mask).graphics;
  588. graphics.clear();
  589. graphics.beginFill(0x0);
  590. graphics.drawRoundRect(0, 0, skinWidth, layoutThumbHeight, layoutCornerEllipseSize);
  591. graphics.endFill();
  592. }
  593. /**
  594. * Resize and reposition the clipping mask
  595. */
  596. private function layoutMask(skinWidth:Number, skinHeight:Number):void
  597. {
  598. setElementSize(contents.mask, skinWidth, layoutThumbHeight);
  599. setElementPosition(contents.mask, 0, (skinHeight - layoutThumbHeight) / 2);
  600. }
  601. /**
  602. * Move the sliding content to line up with thumbPosition.
  603. * This version assumes the thumb and track share the same coordinate system.
  604. */
  605. private function moveSlidingContent():void
  606. {
  607. if (!hostComponent)
  608. return;
  609. var x:Number = (track.getLayoutBoundsWidth() - thumb.getLayoutBoundsWidth()) *
  610. hostComponent.thumbPosition + track.getLayoutBoundsX();
  611. var y:Number = thumb.getLayoutBoundsY();
  612. setElementPosition(slidingContentBackground, x, y);
  613. setElementPosition(slidingContentForeground, x, y);
  614. }
  615. //----------------------------------------------------------------------------------------------
  616. //
  617. // Event handlers
  618. //
  619. //----------------------------------------------------------------------------------------------
  620. /**
  621. * When the thumb position changes, reposition the sliding content.
  622. */
  623. private function thumbPositionChanged_handler(event:Event):void
  624. {
  625. moveSlidingContent();
  626. }
  627. }
  628. }
  629. import flash.events.Event;
  630. import mx.core.UIComponent;
  631. import mx.core.mx_internal;
  632. import mx.events.FlexEvent;
  633. import spark.components.supportClasses.StyleableTextField;
  634. import spark.core.IDisplayText;
  635. use namespace mx_internal;
  636. /**
  637. * @private
  638. * Component combining two labels to create the effect of text and its drop
  639. * shadow. The component can be used with advanced style selectors and the
  640. * styles "color", "textShadowColor", and "textShadowAlpha". Based off of
  641. * ActionBar.TitleDisplayComponent. These two should eventually be factored.
  642. */
  643. class LabelDisplayComponent extends UIComponent implements IDisplayText
  644. {
  645. public var shadowYOffset:Number = 0;
  646. private var labelChanged:Boolean = false;
  647. private var labelDisplay:StyleableTextField;
  648. private var labelDisplayShadow:StyleableTextField;
  649. private var _text:String;
  650. public function LabelDisplayComponent()
  651. {
  652. super();
  653. _text = "";
  654. }
  655. override public function get baselinePosition():Number
  656. {
  657. return labelDisplay.baselinePosition;
  658. }
  659. override protected function createChildren():void
  660. {
  661. super.createChildren();
  662. labelDisplay = StyleableTextField(createInFontContext(StyleableTextField));
  663. labelDisplay.styleName = this;
  664. labelDisplay.editable = false;
  665. labelDisplay.selectable = false;
  666. labelDisplay.multiline = false;
  667. labelDisplay.wordWrap = false;
  668. labelDisplay.addEventListener(FlexEvent.VALUE_COMMIT,
  669. labelDisplay_valueCommitHandler);
  670. labelDisplayShadow = StyleableTextField(createInFontContext(StyleableTextField));
  671. labelDisplayShadow.styleName = this;
  672. labelDisplayShadow.colorName = "textShadowColor";
  673. labelDisplayShadow.editable = false;
  674. labelDisplayShadow.selectable = false;
  675. labelDisplayShadow.multiline = false;
  676. labelDisplayShadow.wordWrap = false;
  677. addChild(labelDisplayShadow);
  678. addChild(labelDisplay);
  679. }
  680. override protected function commitProperties():void
  681. {
  682. super.commitProperties();
  683. if (labelChanged)
  684. {
  685. labelDisplay.text = text;
  686. invalidateSize();
  687. invalidateDisplayList();
  688. labelChanged = false;
  689. }
  690. }
  691. override protected function measure():void
  692. {
  693. if (labelDisplay.isTruncated)
  694. labelDisplay.text = text;
  695. labelDisplay.commitStyles();
  696. measuredWidth = labelDisplay.getPreferredBoundsWidth();
  697. measuredHeight = labelDisplay.getPreferredBoundsHeight();
  698. }
  699. override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
  700. {
  701. if (labelDisplay.isTruncated)
  702. labelDisplay.text = text;
  703. labelDisplay.commitStyles();
  704. var labelHeight:Number = labelDisplay.getPreferredBoundsHeight();
  705. var labelY:Number = (unscaledHeight - labelHeight) / 2;
  706. var labelWidth:Number = Math.min(unscaledWidth, labelDisplay.getPreferredBoundsWidth());
  707. var labelX:Number = (unscaledWidth - labelWidth) / 2;
  708. labelDisplay.setLayoutBoundsSize(labelWidth, labelHeight);
  709. labelDisplay.setLayoutBoundsPosition(labelX, labelY);
  710. labelDisplay.truncateToFit();
  711. labelDisplayShadow.commitStyles();
  712. labelDisplayShadow.setLayoutBoundsSize(labelWidth, labelHeight);
  713. labelDisplayShadow.setLayoutBoundsPosition(labelX, labelY + shadowYOffset);
  714. labelDisplayShadow.alpha = getStyle("textShadowAlpha");
  715. // unless the label was truncated, labelDisplayShadow.text was set in
  716. // the value commit handler
  717. if (labelDisplay.isTruncated)
  718. labelDisplayShadow.text = labelDisplay.text;
  719. }
  720. private function labelDisplay_valueCommitHandler(event:Event):void
  721. {
  722. labelDisplayShadow.text = labelDisplay.text;
  723. }
  724. public function get text():String
  725. {
  726. return _text;
  727. }
  728. public function set text(value:String):void
  729. {
  730. _text = value;
  731. labelChanged = true;
  732. invalidateProperties();
  733. }
  734. public function get isTruncated():Boolean
  735. {
  736. return labelDisplay.isTruncated;
  737. }
  738. public function showShadow(value:Boolean):void
  739. {
  740. labelDisplayShadow.visible = value;
  741. }
  742. }