PageRenderTime 64ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Sample/mx/controls/sliderClasses/Slider.as

https://github.com/ingydotnet/yaml-oscon2009-talk
ActionScript | 2555 lines | 1253 code | 387 blank | 915 comment | 227 complexity | 3b7a341f81bbe90e7756a1544cf52794 MD5 | raw file
  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. package mx.controls.sliderClasses
  12. {
  13. import flash.display.DisplayObject;
  14. import flash.display.Graphics;
  15. import flash.display.Sprite;
  16. import flash.events.Event;
  17. import flash.events.FocusEvent;
  18. import flash.events.KeyboardEvent;
  19. import flash.events.MouseEvent;
  20. import flash.geom.Point;
  21. import flash.utils.getTimer;
  22. import mx.core.FlexVersion;
  23. import mx.core.IFlexDisplayObject;
  24. import mx.core.mx_internal;
  25. import mx.core.UIComponent;
  26. import mx.effects.Tween;
  27. import mx.events.FlexEvent;
  28. import mx.events.SliderEvent;
  29. import mx.events.SliderEventClickTarget;
  30. import mx.formatters.NumberFormatter;
  31. import mx.managers.ISystemManager;
  32. import mx.managers.SystemManager;
  33. import mx.styles.ISimpleStyleClient;
  34. import mx.styles.StyleProxy;
  35. use namespace mx_internal;
  36. //--------------------------------------
  37. // Events
  38. //--------------------------------------
  39. /**
  40. * Dispatched when the slider changes value due to mouse or keyboard interaction.
  41. *
  42. * <p>If the <code>liveDragging</code> property is <code>true</code>,
  43. * the event is dispatched continuously as the user moves the thumb.
  44. * If <code>liveDragging</code> is <code>false</code>,
  45. * the event is dispatched when the user releases the slider thumb.</p>
  46. *
  47. * @eventType mx.events.SliderEvent.CHANGE
  48. */
  49. [Event(name="change", type="mx.events.SliderEvent")]
  50. /**
  51. * Dispatched when the slider's thumb is pressed and then moved by the mouse.
  52. * This event is always preceded by a <code>thumbPress</code> event.
  53. * @eventType mx.events.SliderEvent.THUMB_DRAG
  54. */
  55. [Event(name="thumbDrag", type="mx.events.SliderEvent")]
  56. /**
  57. * Dispatched when the slider's thumb is pressed, meaning
  58. * the user presses the mouse button over the thumb.
  59. *
  60. * @eventType mx.events.SliderEvent.THUMB_PRESS
  61. */
  62. [Event(name="thumbPress", type="mx.events.SliderEvent")]
  63. /**
  64. * Dispatched when the slider's thumb is released,
  65. * meaning the user releases the mouse button after
  66. * a <code>thumbPress</code> event.
  67. *
  68. * @eventType mx.events.SliderEvent.THUMB_RELEASE
  69. */
  70. [Event(name="thumbRelease", type="mx.events.SliderEvent")]
  71. //--------------------------------------
  72. // Styles
  73. //--------------------------------------
  74. include "../../styles/metadata/FillStyles.as";
  75. /**
  76. * The color of the black section of the border.
  77. *
  78. * @default 0x919999
  79. */
  80. [Style(name="borderColor", type="uint", format="Color", inherit="no")]
  81. /**
  82. * Invert the direction of the thumbs.
  83. * If <code>true</code>, the thumbs will be flipped.
  84. *
  85. * @default false
  86. */
  87. [Style(name="invertThumbDirection", type="Boolean", inherit="no")]
  88. /**
  89. * The y-position offset (if direction is horizontal)
  90. * or x-position offset (if direction is vertical)
  91. * of the labels relative to the track.
  92. *
  93. * @default -10
  94. */
  95. [Style(name="labelOffset", type="Number", format="Length", inherit="no")]
  96. /**
  97. * The name of the style to use for the slider label.
  98. *
  99. * @default undefined
  100. */
  101. [Style(name="labelStyleName", type="String", inherit="no")]
  102. /**
  103. * Duration in milliseconds for the sliding animation
  104. * when you click on the track to move a thumb.
  105. *
  106. * @default 300
  107. */
  108. [Style(name="slideDuration", type="Number", format="Time", inherit="no")]
  109. /**
  110. * Tweening function used by the sliding animation
  111. * when you click on the track to move a thumb.
  112. *
  113. * @default undefined
  114. */
  115. [Style(name="slideEasingFunction", type="Function", inherit="no")]
  116. /**
  117. * The y-position offset (if direction is horizontal)
  118. * or x-position offset (if direction is vertical)
  119. * of the thumb relative to the track.
  120. *
  121. * @default 0
  122. */
  123. [Style(name="thumbOffset", type="Number", format="Length", inherit="no")]
  124. /**
  125. * The color of the tick marks.
  126. * Can be a hex color value or the string name of a known color.
  127. *
  128. * @default 0x6F7777.
  129. */
  130. [Style(name="tickColor", type="uint", format="Color", inherit="no")]
  131. /**
  132. * The length in pixels of the tick marks.
  133. * If <code>direction</code> is <code>Direction.HORIZONTAL</code>,
  134. * then adjust the height of the tick marks.
  135. * If <code>direction</code> is <code>Direction.VERTICAL</code>,
  136. * then adjust the width.
  137. *
  138. * @default 3
  139. */
  140. [Style(name="tickLength", type="Number", format="Length", inherit="no")]
  141. /**
  142. * The y-position offset (if direction is horizontal)
  143. * or x-position offset (if direction is vertical)
  144. * of the tick marks relative to the track.
  145. *
  146. * @default -6
  147. */
  148. [Style(name="tickOffset", type="Number", format="Length", inherit="no")]
  149. /**
  150. * The thickness in pixels of the tick marks.
  151. * If direction is horizontal,
  152. * then adjust the width of the tick marks.
  153. * If direction is vertical,
  154. * then adjust the height.
  155. *
  156. * @default 1
  157. */
  158. [Style(name="tickThickness", type="Number", format="Length", inherit="no")]
  159. /**
  160. * The colors of the track, as an array of two colors.
  161. * You can use the same color twice for a solid track color.
  162. *
  163. * <p>You use this property along with the <code>fillAlphas</code>
  164. * property. Typically you set <code>fillAlphas</code> to [ 1.0, 1.0 ]
  165. * when setting <code>trackColors</code>.</p>
  166. *
  167. * @default [ 0xE7E7E7, 0xE7E7E7 ]
  168. */
  169. [Style(name="trackColors", type="Array", arrayType="uint", format="Color", inherit="no")]
  170. /**
  171. * Specifies whether to enable track highlighting between thumbs
  172. * (or a single thumb and the beginning of the track).
  173. *
  174. * @default false
  175. */
  176. [Style(name="showTrackHighlight", type="Boolean", inherit="no")]
  177. /**
  178. * The size of the track margins, in pixels.
  179. * If <code>undefined</code>, then the track margins will be determined
  180. * by the length of the first and last labels.
  181. * If given a value, Flex attempts to fit the labels in the available space.
  182. *
  183. * @default undefined
  184. */
  185. [Style(name="trackMargin", type="Number", format="Length", inherit="no")]
  186. /**
  187. * The name of the style declaration to use for the data tip.
  188. *
  189. * @default undefined
  190. */
  191. [Style(name="dataTipStyleName", type="String", inherit="no")]
  192. /**
  193. * The offset, in pixels, of the data tip relative to the thumb.
  194. * Used in combination with the <code>dataTipPlacement</code>
  195. * style property of the HSlider and VSlider controls.
  196. *
  197. * @default 16
  198. */
  199. [Style(name="dataTipOffset", type="Number", format="Length", inherit="no")]
  200. /**
  201. * Number of decimal places to use for the data tip text.
  202. * A value of 0 means to round all values to an integer.
  203. *
  204. * @default 2
  205. */
  206. [Style(name="dataTipPrecision", type="int", inherit="no")]
  207. /**
  208. * The default skin for the slider thumb.
  209. *
  210. * @default SliderThumbSkin
  211. */
  212. [Style(name="thumbSkin", type="Class", inherit="no", states="up, over, down, disabled")]
  213. /**
  214. * The skin for the slider thumb up state.
  215. *
  216. * @default SliderThumbSkin
  217. */
  218. [Style(name="thumbUpSkin", type="Class", inherit="no")]
  219. /**
  220. * The skin for the slider thumb over state.
  221. *
  222. * @default SliderThumbSkin
  223. */
  224. [Style(name="thumbOverSkin", type="Class", inherit="no")]
  225. /**
  226. * The skin for the slider thumb down state.
  227. *
  228. * @default SliderThumbSkin
  229. */
  230. [Style(name="thumbDownSkin", type="Class", inherit="no")]
  231. /**
  232. * The skin for the slider thumb disabled state.
  233. *
  234. * @default SliderThumbSkin
  235. */
  236. [Style(name="thumbDisabledSkin", type="Class", inherit="no")]
  237. /**
  238. * The skin for the slider track when it is selected.
  239. */
  240. [Style(name="trackHighlightSkin", type="Class", inherit="no")]
  241. /**
  242. * The skin for the slider track.
  243. */
  244. [Style(name="trackSkin", type="Class", inherit="no")]
  245. //--------------------------------------
  246. // Other metadata
  247. //--------------------------------------
  248. [AccessibilityClass(implementation="mx.accessibility.SliderAccImpl")]
  249. [ResourceBundle("SharedResources")]
  250. /**
  251. * The Slider class is the base class for the Flex slider controls.
  252. * The slider controls let users select a value by moving a slider thumb
  253. * between the end points of the slider
  254. * track. The current value of the slider is determined by
  255. * the relative location of the thumb between the
  256. * end points of the slider, corresponding to the slider's minimum and maximum values.
  257. * The Slider class is subclassed by HSlider and VSlider.
  258. *
  259. * @mxml
  260. *
  261. * <p>The Slider class cannot be used as an MXML tag. Use the <code>&lt;mx:HSlider&gt;</code>
  262. * and <code>&lt;mx:VSlider&gt;</code> tags instead. However, the Slider class does define tag
  263. * attributes used by the <code>&lt;mx:HSlider&gt;</code> and <code>&lt;mx:VSlider&gt;</code> tags. </p>
  264. *
  265. * <p>The Slider class inherits all of the tag attributes
  266. * of its superclass, and adds the following tag attributes:</p>
  267. *
  268. * <pre>
  269. * &lt;mx:<i>tagname</i>
  270. * <strong>Properties</strong>
  271. * allowThumbOverlap="false|true"
  272. * allowTrackClick="true|false"
  273. * dataTipFormatFunction="undefined"
  274. * direction="horizontal|vertical"
  275. * labels="undefined"
  276. * liveDragging="false|true"
  277. * maximum="10"
  278. * minimum="0"
  279. * showDataTip="true|false"
  280. * sliderDataTipClass="sliderDataTip"
  281. * sliderThumbClass="SliderThumb"
  282. * snapInterval="0"
  283. * thumbCount="1"
  284. * tickInterval="0"
  285. * tickValues="undefined"
  286. * value="<i>The value of the minimum property.</i>"
  287. *
  288. * <strong>Styles</strong>
  289. * borderColor="0x919999"
  290. * dataTipOffset="16"
  291. * dataTipPrecision="2"
  292. * dataTipStyleName="undefined"
  293. * fillAlphas="[0.6, 0.4, 0.75, 0.65]"
  294. * fillColors="[0xFFFFFF, 0xCCCCCC, 0xFFFFFF, 0xEEEEEE;]"
  295. * labelOffset="-10"
  296. * labelStyleName="undefined"
  297. * showTrackHighlight="false"
  298. * slideDuration="300"
  299. * slideEasingFunction="undefined"
  300. * thumbDisabledSkin="SliderThumbSkin"
  301. * thumbDownSkin="SliderThumbSkin"
  302. * thumbOffset="0"
  303. * thumbOverSkin="SliderThumbSkin"
  304. * thumbUpSkin="SliderThumbSkin"
  305. * tickColor="0x6F7777"
  306. * tickLength="3"
  307. * tickOffset="-6"
  308. * tickThickness="1"
  309. * trackColors="[ 0xEEEEEE, 0xFFFFFF ]"
  310. * tracHighlightSkin="SliderHighlightSkin"
  311. * trackMargin="undefined"
  312. * trackSkin="SliderTrackSkin"
  313. *
  314. * <strong>Events</strong>
  315. * change="<i>No default</i>"
  316. * thumbDrag="<i>No default</i>"
  317. * thumbPress="<i>No default</i>"
  318. * thumbRelease="<i>No default</i>"
  319. * /&gt;
  320. * </pre>
  321. */
  322. public class Slider extends UIComponent
  323. {
  324. include "../../core/Version.as";
  325. //--------------------------------------------------------------------------
  326. //
  327. // Class mixins
  328. //
  329. //--------------------------------------------------------------------------
  330. /**
  331. * @private
  332. * Placeholder for mixin by SliderAccImpl.
  333. */
  334. mx_internal static var createAccessibilityImplementation:Function;
  335. //--------------------------------------------------------------------------
  336. //
  337. // Constructor
  338. //
  339. //--------------------------------------------------------------------------
  340. /**
  341. * Constructor.
  342. */
  343. public function Slider()
  344. {
  345. super();
  346. tabChildren = true;
  347. }
  348. //--------------------------------------------------------------------------
  349. //
  350. // Variables
  351. //
  352. //--------------------------------------------------------------------------
  353. /**
  354. * @private
  355. */
  356. private var track:IFlexDisplayObject;
  357. /**
  358. * @private
  359. */
  360. private var thumbs:UIComponent;
  361. /**
  362. * @private
  363. */
  364. private var thumbsChanged:Boolean = true;
  365. /**
  366. * @private
  367. */
  368. private var ticks:UIComponent;
  369. /**
  370. * @private
  371. */
  372. private var ticksChanged:Boolean = false;
  373. /**
  374. * @private
  375. */
  376. private var labelObjects:UIComponent;
  377. /**
  378. * @private
  379. */
  380. private var highlightTrack:IFlexDisplayObject;
  381. /**
  382. * @private
  383. */
  384. mx_internal var innerSlider:UIComponent;
  385. /**
  386. * @private
  387. */
  388. private var trackHitArea:UIComponent;
  389. /**
  390. * @private
  391. */
  392. mx_internal var dataTip:SliderDataTip;
  393. /**
  394. * @private
  395. */
  396. private var trackHighlightChanged:Boolean = true;
  397. /**
  398. * @private
  399. */
  400. private var initValues:Boolean = true; // Always initValues at startup
  401. /**
  402. * @private
  403. */
  404. private var dataFormatter:NumberFormatter;
  405. /**
  406. * @private
  407. */
  408. private var interactionClickTarget:String;
  409. /**
  410. * @private
  411. */
  412. private var labelStyleChanged:Boolean = false;
  413. /**
  414. * @private
  415. * is the last interaction from the keyboard?
  416. */
  417. mx_internal var keyInteraction:Boolean = false;
  418. //--------------------------------------------------------------------------
  419. //
  420. // Overridden properties
  421. //
  422. //--------------------------------------------------------------------------
  423. //----------------------------------
  424. // baselinePosition
  425. //----------------------------------
  426. /**
  427. * @private
  428. */
  429. override public function get baselinePosition():Number
  430. {
  431. if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_3_0)
  432. return super.baselinePosition;
  433. if (!validateBaselinePosition())
  434. return NaN;
  435. return int(0.75 * height);
  436. }
  437. //----------------------------------
  438. // enabled
  439. //----------------------------------
  440. /**
  441. * @private
  442. */
  443. private var _enabled:Boolean;
  444. /**
  445. * @private
  446. */
  447. private var enabledChanged:Boolean = false;
  448. [Inspectable(category="General", enumeration="true,false", defaultValue="true")]
  449. /**
  450. * @private
  451. */
  452. override public function get enabled():Boolean
  453. {
  454. return _enabled;
  455. }
  456. /**
  457. * @private
  458. */
  459. override public function set enabled(value:Boolean):void
  460. {
  461. _enabled = value;
  462. enabledChanged = true;
  463. invalidateProperties();
  464. }
  465. /**
  466. * @private
  467. */
  468. private var _tabIndex:Number;
  469. /**
  470. * @private
  471. */
  472. private var tabIndexChanged:Boolean;
  473. /**
  474. * @private
  475. */
  476. override public function set tabIndex(value:int):void
  477. {
  478. super.tabIndex = value;
  479. _tabIndex = value;
  480. tabIndexChanged = true;
  481. invalidateProperties();
  482. }
  483. //--------------------------------------------------------------------------
  484. //
  485. // Properties
  486. //
  487. //--------------------------------------------------------------------------
  488. //----------------------------------
  489. // allowThumbOverlap
  490. //----------------------------------
  491. [Inspectable(defaultValue="false")]
  492. /**
  493. * If set to <code>false</code>, then each thumb can only be moved to the edge of
  494. * the adjacent thumb.
  495. * If <code>true</code>, then each thumb can be moved to any position on the track.
  496. *
  497. * @default false
  498. */
  499. public var allowThumbOverlap:Boolean = false;
  500. //----------------------------------
  501. // allowTrackClick
  502. //----------------------------------
  503. [Inspectable(defaultValue="true")]
  504. /**
  505. * Specifies whether clicking on the track will move the slider thumb.
  506. *
  507. * @default true
  508. */
  509. public var allowTrackClick:Boolean = true;
  510. //----------------------------------
  511. // dataTipFormatFunction
  512. //----------------------------------
  513. /**
  514. * @private
  515. */
  516. private var _dataTipFormatFunction:Function;
  517. /**
  518. * Callback function that formats the data tip text.
  519. * The function takes a single Number as an argument
  520. * and returns a formatted String.
  521. *
  522. * <p>The function has the following signature:</p>
  523. * <pre>
  524. * funcName(value:Number):String
  525. * </pre>
  526. *
  527. * <p>The following example prefixes the data tip text with a dollar sign and
  528. * formats the text using the <code>dataTipPrecision</code>
  529. * of a Slider Control named 'slide': </p>
  530. *
  531. * <pre>
  532. * import mx.formatters.NumberBase;
  533. * function myDataTipFormatter(value:Number):String {
  534. * var dataFormatter:NumberBase = new NumberBase(".", ",", ".", "");
  535. * return "$ " + dataFormatter.formatPrecision(String(value), slide.getStyle("dataTipPrecision"));
  536. * }
  537. * </pre>
  538. *
  539. * @default undefined
  540. */
  541. public function get dataTipFormatFunction():Function
  542. {
  543. return _dataTipFormatFunction;
  544. }
  545. /**
  546. * @private
  547. */
  548. public function set dataTipFormatFunction(value:Function):void
  549. {
  550. _dataTipFormatFunction = value;
  551. }
  552. //----------------------------------
  553. // direction
  554. //----------------------------------
  555. /**
  556. * @private
  557. */
  558. private var _direction:String = SliderDirection.HORIZONTAL;
  559. /**
  560. * @private
  561. */
  562. private var directionChanged:Boolean = false;
  563. [Inspectable(defaultValue="horizontal")]
  564. /**
  565. * The orientation of the slider control.
  566. * Valid values in MXML are <code>"horizontal"</code> or <code>"vertical"</code>.
  567. *
  568. * <p>In ActionScript, you use the following constants
  569. * to set this property:
  570. * <code>SliderDirection.VERTICAL</code> and
  571. * <code>SliderDirection.HORIZONTAL</code>.</p>
  572. *
  573. * The HSlider and VSlider controls set this property for you;
  574. * do not set it when using those controls.
  575. *
  576. * @default SliderDirection.HORIZONTAL
  577. * @see mx.controls.sliderClasses.SliderDirection
  578. */
  579. public function get direction():String
  580. {
  581. return _direction;
  582. }
  583. /**
  584. * @private
  585. */
  586. public function set direction(value:String):void
  587. {
  588. _direction = value;
  589. directionChanged = true;
  590. invalidateProperties();
  591. invalidateSize();
  592. invalidateDisplayList();
  593. }
  594. //----------------------------------
  595. // labels
  596. //----------------------------------
  597. /**
  598. * @private
  599. */
  600. private var _labels:Array = [];
  601. /**
  602. * @private
  603. */
  604. private var labelsChanged:Boolean = false;
  605. [Inspectable(category="General", arrayType="String", defaultValue="undefined")]
  606. /**
  607. * An array of strings used for the slider labels.
  608. * Flex positions the labels at the beginning of the track,
  609. * and spaces them evenly between the beginning of the track
  610. * and the end of the track.
  611. *
  612. * <p>For example, if the array contains three items,
  613. * the first item is placed at the beginning of the track,
  614. * the second item in the middle, and the last item
  615. * at the end of the track.</p>
  616. *
  617. * <p>If only one label is specified, it is placed at the
  618. * beginning of the track.
  619. * By default, labels are placed above the tick marks
  620. * (if present) or above the track.
  621. * To align the labels with the tick marks, make sure that
  622. * the number of tick marks is equal to the number of labels.</p>
  623. *
  624. * @default undefined
  625. */
  626. public function get labels():Array
  627. {
  628. return _labels;
  629. }
  630. /**
  631. * @private
  632. */
  633. public function set labels(value:Array):void
  634. {
  635. _labels = value;
  636. labelsChanged = true;
  637. invalidateProperties();
  638. invalidateSize();
  639. invalidateDisplayList();
  640. }
  641. //----------------------------------
  642. // liveDragging
  643. //----------------------------------
  644. [Inspectable(category="General", defaultValue="false")]
  645. /**
  646. * Specifies whether live dragging is enabled for the slider.
  647. * If <code>false</code>, Flex sets the <code>value</code> and
  648. * <code>values</code> properties and dispatches the <code>change</code>
  649. * event when the user stops dragging the slider thumb.
  650. * If <code>true</code>, Flex sets the <code>value</code> and
  651. * <code>values</code> properties and dispatches the <code>change</code>
  652. * event continuously as the user moves the thumb.
  653. *
  654. * @default false
  655. */
  656. public var liveDragging:Boolean = false;
  657. //----------------------------------
  658. // maximum
  659. //----------------------------------
  660. /**
  661. * @private
  662. * Storage for the maximum property.
  663. */
  664. private var _maximum:Number = 10;
  665. [Inspectable(category="General", defaultValue="10")]
  666. /**
  667. * The maximum allowed value on the slider.
  668. *
  669. * @default 10
  670. */
  671. public function get maximum():Number
  672. {
  673. return _maximum;
  674. }
  675. /**
  676. * @private
  677. */
  678. public function set maximum(value:Number):void
  679. {
  680. _maximum = value;
  681. ticksChanged = true;
  682. if (!initValues)
  683. valuesChanged = true;
  684. invalidateProperties();
  685. invalidateDisplayList();
  686. }
  687. //----------------------------------
  688. // minimum
  689. //----------------------------------
  690. /**
  691. * @private
  692. * Storage for the minimum property.
  693. */
  694. private var _minimum:Number = 0;
  695. /**
  696. * @private
  697. */
  698. private var minimumSet:Boolean = false;
  699. [Inspectable(category="General", defaultValue="0")]
  700. /**
  701. * The minimum allowed value on the slider control.
  702. *
  703. * @default 0
  704. */
  705. public function get minimum():Number
  706. {
  707. return _minimum;
  708. }
  709. /**
  710. * @private
  711. */
  712. public function set minimum(value:Number):void
  713. {
  714. _minimum = value;
  715. ticksChanged = true;
  716. if (!initValues)
  717. valuesChanged = true;
  718. invalidateProperties();
  719. invalidateDisplayList();
  720. }
  721. //----------------------------------
  722. // showDataTip
  723. //----------------------------------
  724. [Inspectable(category="General", defaultValue="true")]
  725. /**
  726. * If set to <code>true</code>, show a data tip during user interaction
  727. * containing the current value of the slider.
  728. *
  729. * @default true
  730. */
  731. public var showDataTip:Boolean = true;
  732. //----------------------------------
  733. // sliderThumbClass
  734. //----------------------------------
  735. /**
  736. * @private
  737. */
  738. private var _thumbClass:Class = SliderThumb;
  739. /**
  740. * A reference to the class to use for each thumb.
  741. *
  742. * @default SliderThumb
  743. */
  744. public function get sliderThumbClass():Class
  745. {
  746. return _thumbClass;
  747. }
  748. /**
  749. * @private
  750. */
  751. public function set sliderThumbClass(value:Class):void
  752. {
  753. _thumbClass = value;
  754. thumbsChanged = true;
  755. invalidateProperties();
  756. invalidateDisplayList();
  757. }
  758. //----------------------------------
  759. // sliderDataTipClass
  760. //----------------------------------
  761. /**
  762. * @private
  763. */
  764. private var _sliderDataTipClass:Class = SliderDataTip;
  765. /**
  766. * A reference to the class to use for the data tip.
  767. *
  768. * @default SliderDataTip
  769. */
  770. public function get sliderDataTipClass():Class
  771. {
  772. return _sliderDataTipClass;
  773. }
  774. /**
  775. * @private
  776. */
  777. public function set sliderDataTipClass(value:Class):void
  778. {
  779. _sliderDataTipClass = value;
  780. invalidateProperties();
  781. }
  782. //----------------------------------
  783. // snapInterval
  784. //----------------------------------
  785. /**
  786. * @private
  787. */
  788. private var _snapInterval:Number = 0;
  789. /**
  790. * @private
  791. */
  792. private var snapIntervalPrecision:int = -1;
  793. /**
  794. * @private
  795. */
  796. private var snapIntervalChanged:Boolean = false;
  797. [Inspectable(category="General", defaultValue="0")]
  798. /**
  799. * Specifies the increment value of the slider thumb
  800. * as the user moves the thumb.
  801. * For example, if <code>snapInterval</code> is 2,
  802. * the <code>minimum</code> value is 0,
  803. * and the <code>maximum</code> value is 10,
  804. * the thumb snaps to the values 0, 2, 4, 6, 8, and 10
  805. * as the user move the thumb.
  806. * A value of 0, means that the slider moves continuously
  807. * between the <code>minimum</code> and <code>maximum</code> values.
  808. *
  809. * @default 0
  810. */
  811. public function get snapInterval():Number
  812. {
  813. return _snapInterval;
  814. }
  815. /**
  816. * @private
  817. */
  818. public function set snapInterval(value:Number):void
  819. {
  820. _snapInterval = value;
  821. var parts:Array = (new String(1 + value)).split(".");
  822. if (parts.length == 2)
  823. snapIntervalPrecision = parts[1].length;
  824. else
  825. snapIntervalPrecision = -1;
  826. if (!isNaN(value) && value != 0)
  827. {
  828. snapIntervalChanged = true;
  829. invalidateProperties();
  830. invalidateDisplayList();
  831. }
  832. }
  833. //----------------------------------
  834. // thumbCount
  835. //----------------------------------
  836. /**
  837. * @private
  838. * Storage for the thumbCount property.
  839. */
  840. private var _thumbCount:int = 1;
  841. [Inspectable(category="General", defaultValue="1")]
  842. /**
  843. * The number of thumbs allowed on the slider.
  844. * Possible values are 1 or 2.
  845. * If set to 1, then the <code>value</code> property contains
  846. * the current value of the slider.
  847. * If set to 2, then the <code>values</code> property contains
  848. * an array of values representing the value for each thumb.
  849. *
  850. * @default 1
  851. */
  852. public function get thumbCount():int
  853. {
  854. return _thumbCount;
  855. }
  856. /**
  857. * @private
  858. */
  859. public function set thumbCount(value:int):void
  860. {
  861. var numThumbs:int = (value > 2) ? 2 : value;
  862. numThumbs = value < 1 ? 1 : value;
  863. if (numThumbs != _thumbCount)
  864. {
  865. _thumbCount = numThumbs;
  866. thumbsChanged = true;
  867. initValues = true;
  868. invalidateProperties();
  869. invalidateDisplayList();
  870. }
  871. }
  872. //----------------------------------
  873. // thumbStyleFilters
  874. //----------------------------------
  875. /**
  876. * Set of styles to pass from the Slider to the thumbs.
  877. * @see mx.styles.StyleProxy
  878. */
  879. protected function get thumbStyleFilters():Object
  880. {
  881. return null;
  882. }
  883. //----------------------------------
  884. // tickInterval
  885. //----------------------------------
  886. /**
  887. * @private
  888. */
  889. private var _tickInterval:Number = 0;
  890. [Inspectable(category="General", defaultValue="0")]
  891. /**
  892. * The spacing of the tick marks relative to the <code>maximum</code> value
  893. * of the control.
  894. * Flex displays tick marks whenever you set the <code>tickInterval</code>
  895. * property to a nonzero value.
  896. *
  897. * <p>For example, if <code>tickInterval</code> is 1 and
  898. * <code>maximum</code> is 10, then a tick mark is placed at each
  899. * 1/10th interval along the slider.
  900. * A value of 0 shows no tick marks. If the <code>tickValues</code> property
  901. * is set to a non-empty Array, then this property is ignored.</p>
  902. *
  903. * @default 0
  904. */
  905. public function get tickInterval():Number
  906. {
  907. return _tickInterval;
  908. }
  909. /**
  910. * @private
  911. */
  912. public function set tickInterval(value:Number):void
  913. {
  914. _tickInterval = value;
  915. ticksChanged = true;
  916. invalidateProperties();
  917. invalidateDisplayList();
  918. }
  919. //----------------------------------
  920. // tickValues
  921. //----------------------------------
  922. /**
  923. * @private
  924. */
  925. private var _tickValues:Array = [];
  926. [Inspectable(category="General", defaultValue="undefined", arrayType="Number")]
  927. /**
  928. * The positions of the tick marks on the slider. The positions correspond
  929. * to the values on the slider and should be between
  930. * the <code>minimum</code> and <code>maximum</code> values.
  931. * For example, if the <code>tickValues</code> property
  932. * is [0, 2.5, 7.5, 10] and <code>maximum</code> is 10, then a tick mark is placed
  933. * in the following positions along the slider: the beginning of the slider,
  934. * 1/4 of the way in from the left,
  935. * 3/4 of the way in from the left, and at the end of the slider.
  936. *
  937. * <p>If this property is set to a non-empty Array, then the <code>tickInterval</code> property
  938. * is ignored.</p>
  939. *
  940. * @default undefined
  941. */
  942. public function get tickValues():Array
  943. {
  944. return _tickValues;
  945. }
  946. /**
  947. * @private
  948. */
  949. public function set tickValues(value:Array):void
  950. {
  951. _tickValues = value;
  952. ticksChanged = true;
  953. invalidateProperties();
  954. invalidateDisplayList();
  955. }
  956. //----------------------------------
  957. // value
  958. //----------------------------------
  959. [Bindable("change")]
  960. [Bindable("valueCommit")]
  961. [Inspectable(category="General", defaultValue="undefined")]
  962. /**
  963. * Contains the position of the thumb, and is a number between the
  964. * <code>minimum</code> and <code>maximum</code> properties.
  965. * Use the <code>value</code> property when <code>thumbCount</code> is 1.
  966. * When <code>thumbCount</code> is greater than 1, use the
  967. * <code>values</code> property instead.
  968. * The default value is equal to the minimum property.
  969. */
  970. public function get value():Number
  971. {
  972. return _values[0];
  973. }
  974. /**
  975. * @private
  976. */
  977. public function set value(val:Number):void
  978. {
  979. setValueAt(val, 0, true);
  980. valuesChanged = true;
  981. minimumSet = true;
  982. invalidateProperties();
  983. invalidateDisplayList();
  984. dispatchEvent(new FlexEvent(FlexEvent.VALUE_COMMIT));
  985. }
  986. //----------------------------------
  987. // values
  988. //----------------------------------
  989. /**
  990. * @private
  991. */
  992. private var _values:Array = [ 0, 0 ];
  993. /**
  994. * @private
  995. */
  996. private var valuesChanged:Boolean = false;
  997. [Bindable("change")]
  998. [Inspectable(category="General", arrayType="Number")]
  999. /**
  1000. * An array of values for each thumb when <code>thumbCount</code>
  1001. * is greater than 1.
  1002. */
  1003. public function get values():Array
  1004. {
  1005. return _values;
  1006. }
  1007. /**
  1008. * @private
  1009. */
  1010. public function set values(value:Array):void
  1011. {
  1012. _values = value;
  1013. valuesChanged = true;
  1014. minimumSet = true;
  1015. invalidateProperties();
  1016. invalidateDisplayList();
  1017. }
  1018. //--------------------------------------------------------------------------
  1019. //
  1020. // Overridden methods
  1021. //
  1022. //--------------------------------------------------------------------------
  1023. /**
  1024. * @private
  1025. */
  1026. override protected function initializeAccessibility():void
  1027. {
  1028. if (Slider.createAccessibilityImplementation != null)
  1029. Slider.createAccessibilityImplementation(this);
  1030. }
  1031. /**
  1032. * @private
  1033. */
  1034. override protected function createChildren():void
  1035. {
  1036. super.createChildren();
  1037. if (!innerSlider)
  1038. {
  1039. innerSlider = new UIComponent();
  1040. UIComponent(innerSlider).tabChildren = true;
  1041. addChild(innerSlider);
  1042. }
  1043. createBackgroundTrack();
  1044. if (!trackHitArea)
  1045. {
  1046. trackHitArea = new UIComponent();
  1047. innerSlider.addChild(trackHitArea); // trackHitArea should always be on top
  1048. trackHitArea.addEventListener(MouseEvent.MOUSE_DOWN,
  1049. track_mouseDownHandler);
  1050. }
  1051. invalidateProperties(); // Force commitProperties to be called on instantiation
  1052. }
  1053. /**
  1054. * @private
  1055. */
  1056. override public function styleChanged(styleProp:String):void
  1057. {
  1058. var anyStyle:Boolean = styleProp == null || styleProp == "styleName";
  1059. super.styleChanged(styleProp);
  1060. if (styleProp == "showTrackHighlight" || anyStyle)
  1061. {
  1062. trackHighlightChanged = true;
  1063. invalidateProperties();
  1064. }
  1065. if (styleProp == "trackHighlightSkin" || anyStyle)
  1066. {
  1067. if (innerSlider && highlightTrack)
  1068. {
  1069. innerSlider.removeChild(DisplayObject(highlightTrack));
  1070. highlightTrack = null;
  1071. }
  1072. trackHighlightChanged = true;
  1073. invalidateProperties();
  1074. }
  1075. if (styleProp == "labelStyleName" || anyStyle)
  1076. {
  1077. labelStyleChanged = true;
  1078. invalidateProperties();
  1079. }
  1080. if (styleProp == "trackMargin" || anyStyle)
  1081. {
  1082. invalidateSize();
  1083. }
  1084. if (styleProp == "trackSkin" || anyStyle)
  1085. {
  1086. if (track)
  1087. {
  1088. innerSlider.removeChild(DisplayObject(track));
  1089. track = null;
  1090. createBackgroundTrack();
  1091. }
  1092. }
  1093. invalidateDisplayList();
  1094. }
  1095. /**
  1096. * @private
  1097. */
  1098. override protected function commitProperties():void
  1099. {
  1100. super.commitProperties();
  1101. var n:int;
  1102. var i:int;
  1103. if (trackHighlightChanged)
  1104. {
  1105. trackHighlightChanged = false;
  1106. if (getStyle("showTrackHighlight"))
  1107. {
  1108. createHighlightTrack();
  1109. }
  1110. else if (highlightTrack)
  1111. {
  1112. innerSlider.removeChild(DisplayObject(highlightTrack));
  1113. highlightTrack = null;
  1114. }
  1115. }
  1116. if (directionChanged)
  1117. {
  1118. directionChanged = false;
  1119. var isHorizontal:Boolean = _direction == SliderDirection.HORIZONTAL;
  1120. if (isHorizontal)
  1121. {
  1122. DisplayObject(innerSlider).rotation = 0;
  1123. }
  1124. else
  1125. {
  1126. DisplayObject(innerSlider).rotation = -90;
  1127. innerSlider.y = unscaledHeight;
  1128. }
  1129. if (labelObjects)
  1130. {
  1131. for (var labelIndex:int = labelObjects.numChildren - 1; labelIndex >= 0; labelIndex--)
  1132. {
  1133. var labelObj:SliderLabel = SliderLabel(
  1134. labelObjects.getChildAt(labelIndex));
  1135. labelObj.rotation = isHorizontal ? 0 : 90;
  1136. }
  1137. }
  1138. }
  1139. if (labelStyleChanged && !labelsChanged)
  1140. {
  1141. labelStyleChanged = false;
  1142. if (labelObjects)
  1143. {
  1144. var labelStyleName:String = getStyle("labelStyleName");
  1145. n = labelObjects.numChildren;
  1146. for (i = 0; i < n; i++)
  1147. {
  1148. ISimpleStyleClient(labelObjects.getChildAt(i)).styleName = labelStyleName;
  1149. }
  1150. }
  1151. }
  1152. if (ticksChanged)
  1153. {
  1154. ticksChanged = false;
  1155. createTicks();
  1156. }
  1157. if (labelsChanged)
  1158. {
  1159. labelsChanged = false;
  1160. createLabels();
  1161. }
  1162. if (thumbsChanged)
  1163. {
  1164. thumbsChanged = false;
  1165. createThumbs();
  1166. }
  1167. if (initValues)
  1168. {
  1169. initValues = false;
  1170. if (!valuesChanged)
  1171. {
  1172. var val:Number = minimum;
  1173. n = _thumbCount;
  1174. for (i = 0; i < n; i++)
  1175. {
  1176. _values[i] = val;
  1177. setValueAt(val, i);
  1178. if (_snapInterval && _snapInterval != 0)
  1179. val += snapInterval;
  1180. else
  1181. val++;
  1182. }
  1183. snapIntervalChanged = false;
  1184. }
  1185. }
  1186. if (snapIntervalChanged)
  1187. {
  1188. snapIntervalChanged = false;
  1189. if (!valuesChanged)
  1190. {
  1191. n = thumbs.numChildren;
  1192. for (i = 0; i < n; i++)
  1193. {
  1194. setValueAt(getValueFromX(SliderThumb(thumbs.getChildAt(i)).xPosition), i);
  1195. }
  1196. }
  1197. }
  1198. if (valuesChanged)
  1199. {
  1200. valuesChanged = false;
  1201. n = _thumbCount;
  1202. for (i = 0; i < n; i++)
  1203. {
  1204. setValueAt(getValueFromX(getXFromValue(Math.min(Math.max(values[i], minimum), maximum))), i);
  1205. }
  1206. }
  1207. if (enabledChanged)
  1208. {
  1209. enabledChanged = false;
  1210. n = thumbs.numChildren;
  1211. for (i = 0; i < n; i++)
  1212. {
  1213. SliderThumb(thumbs.getChildAt(i)).enabled = _enabled;
  1214. }
  1215. n = labelObjects ? labelObjects.numChildren : 0;
  1216. for (i = 0; i < n; i++)
  1217. {
  1218. SliderLabel(labelObjects.getChildAt(i)).enabled = _enabled;
  1219. }
  1220. }
  1221. if (tabIndexChanged)
  1222. {
  1223. tabIndexChanged = false;
  1224. n = thumbs.numChildren;
  1225. for (i = 0; i < n; i++)
  1226. {
  1227. SliderThumb(thumbs.getChildAt(i)).tabIndex = _tabIndex;
  1228. }
  1229. }
  1230. }
  1231. /**
  1232. * Calculates the amount of space that the component takes up.
  1233. * A horizontal slider control calculates its height by examining
  1234. * the position of its labels, tick marks, and thumbs
  1235. * relative to the track.
  1236. * The height of the control is equivalent to the position
  1237. * of the bottom of the lowest element subtracted
  1238. * from the position of the top of the highest element.
  1239. * The width of a horizontal slider control defaults to 250 pixels.
  1240. * For a vertical slider control, the width and the length
  1241. * measurements are reversed.
  1242. */
  1243. override protected function measure():void
  1244. {
  1245. super.measure();
  1246. var isHorizontal:Boolean = (direction == SliderDirection.HORIZONTAL);
  1247. var numLabels:int = labelObjects ? labelObjects.numChildren : 0;
  1248. var trackMargin:Number = getStyle("trackMargin");
  1249. var length:Number = DEFAULT_MEASURED_WIDTH;
  1250. if (!isNaN(trackMargin))
  1251. {
  1252. if (numLabels > 0)
  1253. {
  1254. length += (isHorizontal ?
  1255. SliderLabel(labelObjects.getChildAt(0)).getExplicitOrMeasuredWidth() / 2 :
  1256. SliderLabel(labelObjects.getChildAt(0)).getExplicitOrMeasuredHeight() / 2);
  1257. }
  1258. if (numLabels > 1)
  1259. {
  1260. length += (isHorizontal ?
  1261. SliderLabel(labelObjects.getChildAt(numLabels - 1)).getExplicitOrMeasuredWidth() / 2 :
  1262. SliderLabel(labelObjects.getChildAt(numLabels - 1)).getExplicitOrMeasuredHeight() / 2);
  1263. }
  1264. //length += track.width;
  1265. }
  1266. var bounds:Object = getComponentBounds();
  1267. var thickness:Number = bounds.lower - bounds.upper;
  1268. measuredMinWidth = measuredWidth = isHorizontal ? length : thickness;
  1269. measuredMinHeight = measuredHeight = isHorizontal ? thickness : length;
  1270. }
  1271. /**
  1272. * Positions the elements of the control.
  1273. * The track, thumbs, labels, and tick marks are all positioned
  1274. * and sized by this method.
  1275. * The track is sized based on the length of the labels and on the track margin.
  1276. * If you specify a <code>trackMargin</code>, then the size of the track
  1277. * is equal to the available width minus the <code>trackMargin</code> times 2.
  1278. *
  1279. * <p>Tick marks are spaced at even intervals along the track starting from the beginning of the track. An additional tick mark is placed
  1280. * at the end of the track if one doesn't already exist (if the tick interval isn't a multiple of the maximum value). The tick mark
  1281. * y-position is based on the <code>tickOffset</code>. An offset of 0 places the bottom of the tick at the top of the track. Negative offsets
  1282. * move the ticks upwards while positive offsets move them downward through the track.</p>
  1283. *
  1284. * <p>Labels are positioned at even intervals along the track. The labels are always horizontally centered above their
  1285. * interval position unless the <code>trackMargin</code> setting is too small. If you specify a <code>trackMargin</code>, then the first and last labels will
  1286. * position themselves at the left and right borders of the control. Labels will not crop or resize themselves if they overlap,
  1287. * so be sure to allow enough space for them to fit on the track. The y-position is based on the <code>labelOffset</code> property. An offset of 0
  1288. * places the bottom of the label at the top of the track. Unlike tick marks, the labels can not be positioned to overlap the track.
  1289. * If the offset is a positive number, then the top of the label will be positioned below the bottom of the track.</p>
  1290. *
  1291. * <p>The thumbs are positioned to overlap the track. Their x-position is determined by their value. The y-position is
  1292. * controlled by the <code>thumbOffset</code> property. An offset of 0 places the center of the thumb at the center of the track. A negative
  1293. * offset moves the thumbs upwards while a positive offset moves the thumbs downwards.</p>
  1294. *
  1295. * <p>The placement of the tick marks, labels and thumbs are all independent from each other. They will not attempt to reposition
  1296. * themselves if they overlap.</p>
  1297. *
  1298. * <p>For a vertical slider control, the same rules apply. In the above description, substitute width for height, height for width,
  1299. * left for up or top, right for down or bottom, x-position for y-position, and y-position for x-position.</p>
  1300. *
  1301. * @param unscaledWidth Specifies the width of the component, in pixels,
  1302. * in the component's coordinates, regardless of the value of the
  1303. * <code>scaleX</code> property of the component.
  1304. *
  1305. * @param unscaledHeight Specifies the height of the component, in pixels,
  1306. * in the component's coordinates, regardless of the value of the
  1307. * <code>scaleY</code> property of the component.
  1308. */
  1309. override protected function updateDisplayList(unscaledWidth:Number,
  1310. unscaledHeight:Number):void
  1311. {
  1312. super.updateDisplayList(unscaledWidth, unscaledHeight);
  1313. // graphics.beginFill(0xEEEEEE);
  1314. // graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
  1315. // graphics.endFill();
  1316. var isHorizontal:Boolean = (_direction == SliderDirection.HORIZONTAL);
  1317. var numLabels:int = labelObjects ? labelObjects.numChildren : 0;
  1318. var numThumbs:int = thumbs ? thumbs.numChildren : 0;
  1319. var trackMargin:Number = getStyle("trackMargin");
  1320. var widestThumb:Number = 6;
  1321. var firstThumb:SliderThumb = SliderThumb(thumbs.getChildAt(0));
  1322. if (thumbs && firstThumb)
  1323. widestThumb = firstThumb.getExplicitOrMeasuredWidth();
  1324. var trackLeftOffset:Number = widestThumb / 2; // Enough space for the thumb to rest at the edges
  1325. var trackRightOffset:Number = trackLeftOffset;
  1326. var availSpace:Number;
  1327. var firstLabelSize:Number = 0;
  1328. if (numLabels > 0)
  1329. {
  1330. var firstLabel:SliderLabel =
  1331. SliderLabel(labelObjects.getChildAt(0));
  1332. firstLabelSize = isHorizontal ?
  1333. firstLabel.getExplicitOrMeasuredWidth() :
  1334. firstLabel.getExplicitOrMeasuredHeight();
  1335. }
  1336. var lastLabelSize:Number = 0;
  1337. if (numLabels > 1)
  1338. {
  1339. var lastLabel:SliderLabel =
  1340. SliderLabel(labelObjects.getChildAt(numLabels - 1));
  1341. lastLabelSize = isHorizontal ?
  1342. lastLabel.getExplicitOrMeasuredWidth():
  1343. lastLabel.getExplicitOrMeasuredHeight();
  1344. }
  1345. if (!isNaN(trackMargin))
  1346. availSpace = trackMargin;
  1347. else
  1348. availSpace = (firstLabelSize + lastLabelSize) / 2;
  1349. if (numLabels > 0)
  1350. {
  1351. if (!isNaN(trackMargin))
  1352. {
  1353. trackLeftOffset = Math.max(trackLeftOffset,
  1354. availSpace / (numLabels > 1 ? 2 : 1));
  1355. }
  1356. else
  1357. {
  1358. trackLeftOffset = Math.max(trackLeftOffset, firstLabelSize / 2);
  1359. }
  1360. }
  1361. else
  1362. {
  1363. trackLeftOffset = Math.max(trackLeftOffset, availSpace / 2);
  1364. }
  1365. var bounds:Object = getComponentBounds();
  1366. //track.x = Math.round(trackLeftOffset);
  1367. var trackY:Number = (((isHorizontal ? unscaledHeight : unscaledWidth) -
  1368. (Number(bounds.lower) - Number(bounds.upper))) / 2) - Number(bounds.upper);
  1369. track.move(Math.round(trackLeftOffset), Math.round(trackY));
  1370. track.setActualSize((isHorizontal ? unscaledWidth: unscaledHeight) - (trackLeftOffset * 2), track.height);
  1371. // Layout the thumbs' y positions.
  1372. var tY:Number = track.y +
  1373. (track.height - firstThumb.getExplicitOrMeasuredHeight()) / 2 +
  1374. getStyle("thumbOffset");
  1375. var n:int = _thumbCount;
  1376. for (var i:int = 0; i < n; i++)
  1377. {
  1378. var currentThumb:SliderThumb = SliderThumb(thumbs.getChildAt(i));
  1379. currentThumb.move(currentThumb.x, tY);
  1380. currentThumb.visible = true;
  1381. currentThumb.setActualSize(currentThumb.getExplicitOrMeasuredWidth(),
  1382. currentThumb.getExplicitOrMeasuredHeight());
  1383. }
  1384. var g:Graphics = trackHitArea.graphics;
  1385. var tLength:Number = 0
  1386. if (_tickInterval > 0 || (_tickValues && _tickValues.length > 0))
  1387. tLength = getStyle("tickLength");
  1388. g.clear();
  1389. g.beginFill(0,0);
  1390. var fullThumbHeight:Number = firstThumb.getExplicitOrMeasuredHeight();
  1391. var halfThumbHeight:Number = (!fullThumbHeight) ? 0 : (fullThumbHeight / 2);
  1392. g.drawRect(track.x,
  1393. track.y - halfThumbHeight - tLength,
  1394. track.width,
  1395. track.height + fullThumbHeight + tLength);
  1396. g.endFill();
  1397. if (_direction != SliderDirection.HORIZONTAL)
  1398. innerSlider.y = unscaledHeight;
  1399. layoutTicks();
  1400. layoutLabels();
  1401. setPosFromValue(); // use the value to position the thumb's x
  1402. drawTrackHighlight();
  1403. }
  1404. //--------------------------------------------------------------------------
  1405. //
  1406. // Methods
  1407. //
  1408. //--------------------------------------------------------------------------
  1409. /**
  1410. * @private
  1411. */
  1412. private function createBackgroundTrack():void
  1413. {
  1414. if (!track)
  1415. {
  1416. var trackSkinClass:Class = getStyle("trackSkin");
  1417. track = new trackSkinClass();
  1418. if (track is ISimpleStyleClient)
  1419. ISimpleStyleClient(track).styleName = this;
  1420. innerSlider.addChildAt(DisplayObject(track),0);
  1421. }
  1422. }
  1423. /**
  1424. * @private
  1425. */
  1426. private function createHighlightTrack():void
  1427. {
  1428. var showTrackHighlight:Boolean = getStyle("showTrackHighlight");
  1429. if (!highlightTrack && showTrackHighlight)
  1430. {
  1431. var trackHighlightClass:Class =
  1432. getStyle("trackHighlightSkin");
  1433. highlightTrack = new trackHighlightClass();
  1434. if (highlightTrack is ISimpleStyleClient)
  1435. ISimpleStyleClient(highlightTrack).styleName = this;
  1436. innerSlider.addChildAt(DisplayObject(highlightTrack),
  1437. innerSlider.getChildIndex(DisplayObject(track)) + 1);
  1438. }
  1439. }
  1440. /**
  1441. * @private
  1442. */
  1443. private function createThumbs():void
  1444. {
  1445. var n:int;
  1446. var i:int;
  1447. // Delete all thumb children
  1448. if (thumbs)
  1449. {
  1450. n = thumbs.numChildren;
  1451. for (i = n - 1; i >= 0; i--)
  1452. {
  1453. // we don't need to bother to remove the event listeners here
  1454. // they will be removed by the garbage collector automatically
  1455. thumbs.removeChildAt(i);
  1456. }
  1457. }
  1458. else
  1459. {
  1460. thumbs = new UIComponent();
  1461. thumbs.tabChildren = true;
  1462. thumbs.tabEnabled = false;
  1463. innerSlider.addChild(thumbs);
  1464. }
  1465. var thumb:SliderThumb; // We want to force the thumb to be a subclass of SliderThumb
  1466. n = _thumbCount;
  1467. for (i = 0; i < n; i++)
  1468. {
  1469. thumb = SliderThumb(new _thumbClass());
  1470. thumb.owner = this;
  1471. thumb.styleName = new StyleProxy(this, thumbStyleFilters);
  1472. thumb.thumbIndex = i;
  1473. thumb.visible = true;
  1474. thumb.enabled = enabled;
  1475. thumb.upSkinName = "thumbUpSkin";
  1476. thumb.downSkinName = "thumbDownSkin";
  1477. thumb.disabledSkinName = "thumbDisabledSkin";
  1478. thumb.overSkinName = "thumbOverSkin";
  1479. thumb.skinName = "thumbSkin";
  1480. thumbs.addChild(thumb);
  1481. thumb.addEventListener(FocusEvent.FOCUS_IN,
  1482. thumb_focusInHandler);
  1483. thumb.addEventListener(FocusEvent.FOCUS_OUT,
  1484. thumb_focusOutHandler);
  1485. }
  1486. }
  1487. /**
  1488. * @private
  1489. */
  1490. private function createLabels():void
  1491. {
  1492. var labelObj:SliderLabel;
  1493. if (labelObjects)
  1494. {
  1495. for (var i:int = labelObjects.numChildren - 1; i >= 0; i--)
  1496. {
  1497. labelObjects.removeChildAt(i);
  1498. }
  1499. }
  1500. else
  1501. {
  1502. labelObjects = new UIComponent();
  1503. innerSlider.addChildAt(labelObjects, innerSlider.getChildIndex(trackHitArea));
  1504. }
  1505. if (_labels)
  1506. {
  1507. var numLabels:int = _labels.length;
  1508. for (var j:int = 0; j < numLabels; j++)
  1509. {
  1510. labelObj = new SliderLabel();
  1511. labelObj.text = _labels[j] is String ?
  1512. _labels[j] :
  1513. _labels[j].toString();
  1514. if (_direction != SliderDirection.HORIZONTAL)
  1515. labelObj.rotation = 90;
  1516. var labelStyleName:String = getStyle("labelStyleName");
  1517. if (labelStyleName)
  1518. labelObj.styleName = labelStyleName;
  1519. labelObjects.addChild(labelObj);
  1520. }
  1521. }
  1522. }
  1523. /**
  1524. * @private
  1525. */
  1526. private function createTicks():void
  1527. {
  1528. if (!ticks)
  1529. {
  1530. ticks = new UIComponent();
  1531. innerSlider.addChild(ticks);
  1532. }
  1533. }
  1534. /**
  1535. * @private
  1536. */
  1537. private function getComponentBounds():Object
  1538. {
  1539. var isHorizontal:Boolean = (direction == SliderDirection.HORIZONTAL);
  1540. var numLabels:int = labelObjects ? labelObjects.numChildren : 0;
  1541. var labelY:Number;
  1542. var labelSize:Number = 0;
  1543. var thumbY:Number;
  1544. var upperBound:Number = 0;
  1545. var lowerBound:Number = track.height;
  1546. if (numLabels > 0)
  1547. {
  1548. var sliderLabel:SliderLabel =
  1549. SliderLabel(labelObjects.getChildAt(0));
  1550. if (isHorizontal)
  1551. {
  1552. labelSize = sliderLabel.getExplicitOrMeasuredHeight();
  1553. }
  1554. else
  1555. {
  1556. for (var i:int = 0; i < numLabels; i++)
  1557. {
  1558. sliderLabel = SliderLabel(labelObjects.getChildAt(i));
  1559. labelSize = Math.max(labelSize,
  1560. sliderLabel.getExplicitOrMeasuredWidth());
  1561. }
  1562. }
  1563. var labOffset:Number = getStyle("labelOffset");
  1564. labelY = labOffset - (labOffset > 0 ? 0 : labelSize);
  1565. upperBound = Math.min(upperBound, labelY);
  1566. lowerBound = Math.max(lowerBound, labOffset + (labOffset > 0 ? labelSize : 0));
  1567. }
  1568. if (ticks)
  1569. {
  1570. var tLen:Number = getStyle("tickLength");
  1571. var tOff:Number = getStyle("tickOffset");
  1572. upperBound = Math.min(upperBound, tOff - tLen);
  1573. lowerBound = Math.max(lowerBound, tOff);
  1574. }
  1575. if (thumbs.numChildren > 0)
  1576. {
  1577. thumbY = (track.height - SliderThumb(thumbs.getChildAt(0)).getExplicitOrMeasuredHeight()) / 2 +
  1578. getStyle("thumbOffset");
  1579. upperBound = Math.min(upperBound, thumbY);
  1580. lowerBound = Math.max(lowerBound, thumbY + SliderThumb(thumbs.getChildAt(0)).getExplicitOrMeasuredHeight());
  1581. }
  1582. return { lower: lowerBound, upper: upperBound };
  1583. }
  1584. /**
  1585. * @private
  1586. */
  1587. private function layoutTicks():void
  1588. {
  1589. if (ticks)
  1590. {
  1591. var g:Graphics = ticks.graphics;
  1592. var tLength:Number = getStyle("tickLength");
  1593. var tOffset:Number = getStyle("tickOffset");
  1594. var tickWidth:Number = getStyle("tickThickness");
  1595. var xOffset:Number = tickWidth / 2;
  1596. var xPos:Number;
  1597. var tColor:Number = getStyle("tickColor");
  1598. var usePositions:Boolean = _tickValues && _tickValues.length > 0 ? true : false;
  1599. var positionIndex:int = 0;
  1600. var val:Number = usePositions ? _tickValues[positionIndex++] : minimum;
  1601. g.clear();
  1602. if (_tickInterval > 0 || usePositions)
  1603. {
  1604. g.lineStyle(tickWidth,tColor,100);
  1605. do
  1606. {
  1607. xPos = Math.round(getXFromValue(val) - xOffset);
  1608. g.moveTo(xPos, tLength);
  1609. g.lineTo(xPos, 0);
  1610. val = usePositions ? (positionIndex < _tickValues.length ? _tickValues[positionIndex++] : NaN) : _tickInterval + val;
  1611. } while (val < maximum || (usePositions && positionIndex < _tickValues.length))
  1612. // draw the last tick
  1613. if (!usePositions || val == maximum)
  1614. {
  1615. xPos = track.x + track.width - 1 - xOffset;
  1616. g.moveTo(xPos, tLength);
  1617. g.lineTo(xPos, 0);
  1618. }
  1619. ticks.y = Math.round(track.y + tOffset - tLength);
  1620. }
  1621. }
  1622. }
  1623. /**
  1624. * @private
  1625. */
  1626. private function layoutLabels():void
  1627. {
  1628. var numLabels:Number = labelObjects ? labelObjects.numChildren : 0;
  1629. var availSpace:Number;
  1630. if (numLabels > 0)
  1631. {
  1632. var labelInterval:Number = track.width / (numLabels - 1);
  1633. // The amount of space we have available for the labels to hang past the track
  1634. availSpace = Math.max((_direction == SliderDirection.HORIZONTAL ?
  1635. unscaledWidth :
  1636. unscaledHeight) - track.width,
  1637. SliderThumb(thumbs.getChildAt(0)).getExplicitOrMeasuredWidth());
  1638. var labelPos:Number;
  1639. var left:Number = track.x;
  1640. var curLabel:Object;
  1641. for (var i:int = 0; i < numLabels; i++)
  1642. {
  1643. curLabel = labelObjects.getChildAt(i);
  1644. curLabel.setActualSize(curLabel.getExplicitOrMeasuredWidth(), curLabel.getExplicitOrMeasuredHeight());
  1645. var yPos:Number = track.y - curLabel.height + getStyle("labelOffset");
  1646. if (_direction == SliderDirection.HORIZONTAL)
  1647. {
  1648. labelPos = curLabel.getExplicitOrMeasuredWidth() / 2;
  1649. if (i == 0)
  1650. labelPos = Math.min(labelPos, availSpace / (numLabels > Number(1) ? Number(2) : Number(1)));
  1651. else if (i == (numLabels - 1))
  1652. labelPos = Math.max(labelPos, curLabel.getExplicitOrMeasuredWidth() - availSpace / 2);
  1653. curLabel.move(left - labelPos,yPos);
  1654. }
  1655. else
  1656. {
  1657. var labelOff:Number = getStyle("labelOffset");
  1658. labelPos = curLabel.getExplicitOrMeasuredHeight() / 2;
  1659. if (i == 0)
  1660. labelPos = Math.max(labelPos, curLabel.getExplicitOrMeasuredHeight() - availSpace / (numLabels > Number(1) ? Number(2) : Number(1)));
  1661. else if (i == (numLabels-1))
  1662. labelPos = Math.min(labelPos,availSpace / 2);
  1663. curLabel.move(left + labelPos,track.y + labelOff +
  1664. (labelOff > 0 ? 0 : -curLabel.getExplicitOrMeasuredWidth()));
  1665. }
  1666. left += labelInterval;
  1667. }
  1668. }
  1669. }
  1670. /**
  1671. * @private
  1672. */
  1673. mx_internal function drawTrackHighlight():void
  1674. {
  1675. if (highlightTrack)
  1676. {
  1677. var xPos:Number;
  1678. var tWidth:Number;
  1679. var firstThumb:SliderThumb = SliderThumb(thumbs.getChildAt(0));
  1680. if (_thumbCount > 1)
  1681. {
  1682. xPos = firstThumb.xPosition;
  1683. var secondThumb:SliderThumb = SliderThumb(thumbs.getChildAt(1));
  1684. tWidth = secondThumb.xPosition - firstThumb.xPosition;
  1685. }
  1686. else
  1687. {
  1688. xPos = track.x;
  1689. tWidth = firstThumb.xPosition - xPos;
  1690. }
  1691. highlightTrack.move(xPos, track.y + 1);
  1692. highlightTrack.setActualSize(tWidth > 0 ? tWidth : 0, highlightTrack.height);
  1693. }
  1694. }
  1695. /**
  1696. * @private
  1697. * Helper function that starts the dataTip and dispatches the press event.
  1698. */
  1699. mx_internal function onThumbPress(thumb:Object):void
  1700. {
  1701. if (showDataTip)
  1702. {
  1703. // Setup number formatter
  1704. dataFormatter = new NumberFormatter();
  1705. dataFormatter.precision = getStyle("dataTipPrecision");
  1706. if (!dataTip)
  1707. {
  1708. dataTip = SliderDataTip(new sliderDataTipClass());
  1709. systemManager.toolTipChildren.addChild(dataTip);
  1710. var dataTipStyleName:String = getStyle("dataTipStyleName");
  1711. if (dataTipStyleName)
  1712. {
  1713. dataTip.styleName = dataTipStyleName;
  1714. }
  1715. }
  1716. var formattedVal:String;
  1717. if (_dataTipFormatFunction != null)
  1718. {
  1719. formattedVal = this._dataTipFormatFunction(
  1720. getValueFromX(thumb.xPosition));
  1721. }
  1722. else
  1723. {
  1724. formattedVal = dataFormatter.format(getValueFromX(thumb.xPosition));
  1725. }
  1726. dataTip.text = formattedVal;
  1727. // Tool tip has been freshly created and new text assigned to it.
  1728. // Hence force a validation so that we can set the
  1729. // size required to show the text completely.
  1730. dataTip.validateNow();
  1731. dataTip.setActualSize(dataTip.getExplicitOrMeasuredWidth(),dataTip.getExplicitOrMeasuredHeight());
  1732. positionDataTip(thumb);
  1733. }
  1734. keyInteraction = false;
  1735. var event:SliderEvent = new SliderEvent(SliderEvent.THUMB_PRESS);
  1736. event.value = getValueFromX(thumb.xPosition);;
  1737. event.thumbIndex = thumb.thumbIndex;
  1738. dispatchEvent(event);
  1739. }
  1740. /**
  1741. * @private
  1742. */
  1743. mx_internal function onThumbRelease(thumb:Object):void
  1744. {
  1745. interactionClickTarget = SliderEventClickTarget.THUMB;
  1746. destroyDataTip();
  1747. setValueFromPos(thumb.thumbIndex);
  1748. dataFormatter = null;
  1749. var event:SliderEvent = new SliderEvent(SliderEvent.THUMB_RELEASE);
  1750. event.value = getValueFromX(thumb.xPosition);;
  1751. event.thumbIndex = thumb.thumbIndex;
  1752. dispatchEvent(event);
  1753. }
  1754. /**
  1755. * @private
  1756. */
  1757. mx_internal function onThumbMove(thumb:Object):void
  1758. {
  1759. var value:Number = getValueFromX(thumb.xPosition);
  1760. if (showDataTip)
  1761. {
  1762. dataTip.text = _dataTipFormatFunction != null ?
  1763. _dataTipFormatFunction(value) :
  1764. dataFormatter.format(value);
  1765. dataTip.setActualSize(dataTip.getExplicitOrMeasuredWidth(),
  1766. dataTip.getExplicitOrMeasuredHeight());
  1767. positionDataTip(thumb);
  1768. }
  1769. if (liveDragging)
  1770. {
  1771. interactionClickTarget = SliderEventClickTarget.THUMB;
  1772. setValueAt(value, thumb.thumbIndex);
  1773. }
  1774. var event:SliderEvent = new SliderEvent(SliderEvent.THUMB_DRAG);
  1775. event.value = value;
  1776. event.thumbIndex = thumb.thumbIndex;
  1777. dispatchEvent(event);
  1778. }
  1779. /**
  1780. * @private
  1781. */
  1782. private function positionDataTip(thumb:Object):void
  1783. {
  1784. var relX:Number;
  1785. var relY:Number;
  1786. var tX:Number = thumb.x;
  1787. var tY:Number = thumb.y;
  1788. var tPlacement:String = getStyle("dataTipPlacement");
  1789. var tOffset:Number = getStyle("dataTipOffset");
  1790. // Need to special case tooltip position because the tooltip movieclip
  1791. // resides in the root movie clip, instead of the Slider movieclip
  1792. if (_direction == SliderDirection.HORIZONTAL)
  1793. {
  1794. relX = tX;
  1795. relY = tY;
  1796. if (tPlacement == "left")
  1797. {
  1798. relX -= tOffset + dataTip.width;
  1799. relY += (thumb.height - dataTip.height) / 2;
  1800. }
  1801. else if (tPlacement == "right")
  1802. {
  1803. relX += tOffset + thumb.width;
  1804. relY += (thumb.height - dataTip.height) / 2;
  1805. }
  1806. else if (tPlacement == "top")
  1807. {
  1808. relY -= tOffset + dataTip.height;
  1809. relX -= (dataTip.width - thumb.width) / 2;
  1810. }
  1811. else if (tPlacement == "bottom")
  1812. {
  1813. relY += tOffset + thumb.height;
  1814. relX -= (dataTip.width - thumb.width) / 2;
  1815. }
  1816. }
  1817. else
  1818. {
  1819. relX = tY;
  1820. relY = unscaledHeight - tX - (dataTip.height + thumb.width) / 2;
  1821. if (tPlacement == "left")
  1822. {
  1823. relX -= tOffset + dataTip.width;
  1824. }
  1825. else if (tPlacement == "right")
  1826. {
  1827. relX += tOffset + thumb.height;
  1828. }
  1829. else if (tPlacement == "top")
  1830. {
  1831. relY -= tOffset + (dataTip.height + thumb.width) / 2;
  1832. relX -= (dataTip.width - thumb.height) / 2;
  1833. }
  1834. else if (tPlacement == "bottom")
  1835. {
  1836. relY += tOffset + (dataTip.height + thumb.width) / 2;
  1837. relX -= (dataTip.width - thumb.height) / 2;
  1838. }
  1839. }
  1840. var o:Point = new Point(relX, relY);
  1841. var r:Point = localToGlobal(o);
  1842. r = dataTip.parent.globalToLocal(r);
  1843. dataTip.x = r.x < 0 ? 0 : r.x;
  1844. dataTip.y = r.y < 0 ? 0 : r.y;
  1845. }
  1846. /**
  1847. * @private
  1848. */
  1849. private function destroyDataTip():void
  1850. {
  1851. if (dataTip)
  1852. {
  1853. systemManager.toolTipChildren.removeChild(dataTip);
  1854. dataTip = null;
  1855. }
  1856. }
  1857. /**
  1858. * @private
  1859. * Utility for finding the x position which corresponds
  1860. * to the given value.
  1861. */
  1862. mx_internal function getXFromValue(v:Number):Number
  1863. {
  1864. var val:Number;
  1865. if (v == minimum)
  1866. val = track.x;
  1867. else if (v == maximum)
  1868. val = track.x + track.width;
  1869. else
  1870. val = track.x + (v - minimum) * (track.width) / (maximum - minimum);
  1871. return val;
  1872. }
  1873. /**
  1874. * @private
  1875. */
  1876. mx_internal function getXBounds(selectedThumbIndex:int):Object
  1877. {
  1878. var maxX:Number = track.x + track.width;
  1879. var minX:Number = track.x;
  1880. if (allowThumbOverlap)
  1881. {
  1882. return { max: maxX, min: minX };
  1883. }
  1884. var minBound:Number = NaN;
  1885. var maxBound:Number = NaN;
  1886. var prevThumb:SliderThumb =
  1887. selectedThumbIndex > 0 ?
  1888. SliderThumb(thumbs.getChildAt(selectedThumbIndex - 1)) :
  1889. null;
  1890. var nextThumb:SliderThumb =
  1891. selectedThumbIndex + 1 < thumbs.numChildren ?
  1892. SliderThumb(thumbs.getChildAt(selectedThumbIndex + 1)) :
  1893. null;
  1894. if (prevThumb)
  1895. minBound = prevThumb.xPosition + prevThumb.width / 2;
  1896. if (nextThumb)
  1897. maxBound = nextThumb.xPosition - nextThumb.width / 2;
  1898. if (isNaN(minBound))
  1899. minBound = minX;
  1900. else
  1901. minBound = Math.min(Math.max(minX,minBound),maxX);
  1902. if (isNaN(maxBound))
  1903. maxBound = maxX;
  1904. else
  1905. maxBound = Math.max(Math.min(maxX, maxBound),minX);
  1906. return { max: maxBound, min: minBound };
  1907. }
  1908. /**
  1909. * @private
  1910. * Utility for positioning the thumb(s) from the current value.
  1911. */
  1912. private function setPosFromValue():void
  1913. {
  1914. var n:int = _thumbCount;
  1915. for (var i:int = 0; i < n; i++)
  1916. {
  1917. var thumb:SliderThumb = SliderThumb(thumbs.getChildAt(i));
  1918. thumb.xPosition = getXFromValue(values[i]);
  1919. }
  1920. }
  1921. /**
  1922. * @private
  1923. * Utility for getting a value corresponding to a given x.
  1924. */
  1925. mx_internal function getValueFromX(xPos:Number):Number
  1926. {
  1927. var v:Number = (xPos - track.x) *
  1928. (maximum - minimum) /
  1929. (track.width) + minimum;
  1930. // kill rounding error at the edges.
  1931. if (v - minimum <= 0.002)
  1932. {
  1933. v = minimum;
  1934. }
  1935. else if (maximum - v <= 0.002)
  1936. {
  1937. v = maximum;
  1938. }
  1939. else if (!isNaN(_snapInterval) && _snapInterval != 0)
  1940. {
  1941. v = Math.round((v - minimum) / _snapInterval) *
  1942. _snapInterval + minimum;
  1943. }
  1944. return v;
  1945. }
  1946. /**
  1947. * @private
  1948. * Utility for committing a value of a given thumb.
  1949. */
  1950. private function setValueFromPos(thumbIndex:int):void
  1951. {
  1952. var thumb:SliderThumb = SliderThumb(thumbs.getChildAt(thumbIndex));
  1953. setValueAt(getValueFromX(thumb.xPosition), thumbIndex);
  1954. }
  1955. /**
  1956. * @private
  1957. */
  1958. mx_internal function getSnapValue(value:Number, thumb:SliderThumb = null):Number
  1959. {
  1960. if (!isNaN(_snapInterval) && _snapInterval != 0)
  1961. {
  1962. var val:Number = getValueFromX(value);
  1963. if (thumb && (thumbs.numChildren > 1) && !allowThumbOverlap)
  1964. {
  1965. var check_bounds:Boolean = true;
  1966. var bounds:Object
  1967. bounds = getXBounds(thumb.thumbIndex);
  1968. var prevThumb:SliderThumb =
  1969. thumb.thumbIndex > 0 ?
  1970. SliderThumb(thumbs.getChildAt(thumb.thumbIndex- 1)) :
  1971. null;
  1972. var nextThumb:SliderThumb =
  1973. thumb.thumbIndex + 1 < thumbs.numChildren ?
  1974. SliderThumb(thumbs.getChildAt(thumb.thumbIndex + 1)) :
  1975. null;
  1976. if (prevThumb)
  1977. {
  1978. bounds.min -= (prevThumb.width / 2);
  1979. // check if thumb is at minimum, if not we can ignore the bounds logic
  1980. if (val == minimum)
  1981. if (getValueFromX((prevThumb.xPosition - prevThumb.width/2)) != minimum)
  1982. check_bounds = false;
  1983. }
  1984. else
  1985. {
  1986. if (val == minimum)
  1987. check_bounds = false;
  1988. }
  1989. if (nextThumb)
  1990. {
  1991. bounds.max += (nextThumb.width / 2);
  1992. // check if thumb is at maximum, if not we can ignore the bounds logic
  1993. if (val == maximum)
  1994. if (getValueFromX((nextThumb.xPosition + nextThumb.width/2)) != maximum)
  1995. check_bounds = false;
  1996. }
  1997. else
  1998. {
  1999. if (val == maximum)
  2000. check_bounds = false;
  2001. }
  2002. if (check_bounds)
  2003. val = Math.min(Math.max(val, getValueFromX(Math.round(bounds.min)) + _snapInterval),
  2004. getValueFromX(Math.round(bounds.max)) - _snapInterval);
  2005. }
  2006. return getXFromValue(val);
  2007. }
  2008. return value;
  2009. }
  2010. /**
  2011. * @private Accessed by the Thumb to find out the snap interval
  2012. */
  2013. mx_internal function getSnapIntervalWidth():Number
  2014. {
  2015. return _snapInterval * track.width / (maximum - minimum);
  2016. }
  2017. /**
  2018. * @private
  2019. */
  2020. mx_internal function updateThumbValue(thumbIndex:int):void
  2021. {
  2022. setValueFromPos(thumbIndex);
  2023. }
  2024. /**
  2025. * Returns the thumb object at the given index. Use this method to
  2026. * style and customize individual thumbs in a slider control.
  2027. *
  2028. * @param index The zero-based index number of the thumb.
  2029. *
  2030. * @return A reference to the SliderThumb object.
  2031. */
  2032. public function getThumbAt(index:int):SliderThumb
  2033. {
  2034. return index >= 0 && index < thumbs.numChildren ?
  2035. SliderThumb(thumbs.getChildAt(index)) :
  2036. null;
  2037. }
  2038. /**
  2039. * This method sets the value of a slider thumb, and updates the display.
  2040. *
  2041. * @param index The zero-based index number of the thumb to set
  2042. * the value of, where a value of 0 corresponds to the first thumb.
  2043. *
  2044. * @param value The value to set the thumb to
  2045. */
  2046. public function setThumbValueAt(index:int, value:Number):void
  2047. {
  2048. setValueAt(value, index, true);
  2049. valuesChanged = true;
  2050. invalidateProperties();
  2051. invalidateDisplayList();
  2052. }
  2053. /**
  2054. * @private
  2055. */
  2056. private function setValueAt(value:Number, index:int,
  2057. isProgrammatic:Boolean = false):void
  2058. {
  2059. var oldValue:Number = _values[index];
  2060. // we need to do the round of (to remove the floating point error)
  2061. // if the stepSize had a fractional value
  2062. if (snapIntervalPrecision != -1)
  2063. {
  2064. var scale:Number = Math.pow(10, snapIntervalPrecision);
  2065. value = Math.round(value * scale) / scale;
  2066. }
  2067. _values[index] = value;
  2068. if (!isProgrammatic)
  2069. {
  2070. var event:SliderEvent = new SliderEvent(SliderEvent.CHANGE);
  2071. event.value = value;
  2072. event.thumbIndex = index;
  2073. event.clickTarget = interactionClickTarget;
  2074. //set the triggerEvent correctly
  2075. if (keyInteraction)
  2076. {
  2077. event.triggerEvent = new KeyboardEvent(KeyboardEvent.KEY_DOWN);
  2078. //reset to mouse default
  2079. keyInteraction = false;
  2080. }
  2081. else
  2082. event.triggerEvent = new MouseEvent(MouseEvent.CLICK);
  2083. if (!isNaN(oldValue) && Math.abs(oldValue - value) > 0.002)
  2084. dispatchEvent(event);
  2085. }
  2086. invalidateDisplayList();
  2087. }
  2088. /**
  2089. * @private
  2090. */
  2091. mx_internal function registerMouseMove(listener:Function):void
  2092. {
  2093. innerSlider.addEventListener(MouseEvent.MOUSE_MOVE, listener);
  2094. }
  2095. /**
  2096. * @private
  2097. */
  2098. mx_internal function unRegisterMouseMove(listener:Function):void
  2099. {
  2100. innerSlider.removeEventListener(MouseEvent.MOUSE_MOVE, listener);
  2101. }
  2102. //--------------------------------------------------------------------------
  2103. //
  2104. // Event handlers
  2105. //
  2106. //--------------------------------------------------------------------------
  2107. /**
  2108. * @private
  2109. * Move the thumb when pressed.
  2110. */
  2111. private function track_mouseDownHandler(event:MouseEvent):void
  2112. {
  2113. if (event.target != trackHitArea && event.target != ticks)
  2114. return;
  2115. if (enabled && allowTrackClick)
  2116. {
  2117. interactionClickTarget = SliderEventClickTarget.TRACK;
  2118. //this is a mouse event
  2119. keyInteraction = false;
  2120. var pt:Point = new Point(event.localX, event.localY);
  2121. var xM:Number = pt.x;
  2122. var minIndex:Number = 0;
  2123. var minDistance:Number = 10000000;
  2124. // find the nearest thumb
  2125. var n:int = _thumbCount;
  2126. for (var i:int = 0; i < n; i++)
  2127. {
  2128. var d:Number = Math.abs(SliderThumb(thumbs.getChildAt(i)).xPosition - xM);
  2129. if (d < minDistance)
  2130. {
  2131. minIndex = i;
  2132. minDistance = d;
  2133. }
  2134. }
  2135. var thumb:SliderThumb = SliderThumb(thumbs.getChildAt(minIndex));
  2136. if (!isNaN(_snapInterval) && _snapInterval != 0)
  2137. xM = getXFromValue(getValueFromX(xM));
  2138. var duration:Number = getStyle("slideDuration");
  2139. var t:Tween = new Tween(thumb, thumb.xPosition, xM, duration);
  2140. var easingFunction:Function = getStyle("slideEasingFunction") as Function;
  2141. if (easingFunction != null)
  2142. t.easingFunction = easingFunction;
  2143. drawTrackHighlight();
  2144. }
  2145. }
  2146. /**
  2147. * @private
  2148. */
  2149. private function thumb_focusInHandler(event:FocusEvent):void
  2150. {
  2151. dispatchEvent(event);
  2152. }
  2153. /**
  2154. * @private
  2155. */
  2156. private function thumb_focusOutHandler(event:FocusEvent):void
  2157. {
  2158. dispatchEvent(event);
  2159. }
  2160. /**
  2161. * @private
  2162. */
  2163. mx_internal function getTrackHitArea():UIComponent
  2164. {
  2165. return trackHitArea;
  2166. }
  2167. }
  2168. }