PageRenderTime 54ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/com/bit101/components/RotarySelector.as

https://github.com/pombredanne/Elastic-Lists
ActionScript | 297 lines | 179 code | 39 blank | 79 comment | 17 complexity | debc7f74eb69fd7fda46d6a94d666966 MD5 | raw file
  1. /**
  2. * RotarySelector.as
  3. * Keith Peters
  4. * version 0.9.1
  5. *
  6. * A rotary selector component for choosing among different values.
  7. *
  8. * Copyright (c) 2010 Keith Peters
  9. *
  10. * Permission is hereby granted, free of charge, to any person obtaining a copy
  11. * of this software and associated documentation files (the "Software"), to deal
  12. * in the Software without restriction, including without limitation the rights
  13. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  14. * copies of the Software, and to permit persons to whom the Software is
  15. * furnished to do so, subject to the following conditions:
  16. *
  17. * The above copyright notice and this permission notice shall be included in
  18. * all copies or substantial portions of the Software.
  19. *
  20. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  21. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  22. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  23. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  24. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  25. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  26. * THE SOFTWARE.
  27. */
  28. package com.bit101.components
  29. {
  30. import flash.display.DisplayObjectContainer;
  31. import flash.display.Sprite;
  32. import flash.events.Event;
  33. import flash.events.MouseEvent;
  34. public class RotarySelector extends Component
  35. {
  36. public static const ALPHABETIC:String = "alphabetic";
  37. public static const NUMERIC:String = "numeric";
  38. public static const NONE:String = "none";
  39. public static const ROMAN:String = "roman";
  40. private var _label:Label;
  41. private var _labelText:String = "";
  42. private var _knob:Sprite;
  43. private var _numChoices:int = 2;
  44. private var _choice:Number = 0;
  45. private var _labels:Sprite;
  46. private var _labelMode:String = ALPHABETIC;
  47. /**
  48. * Constructor
  49. * @param parent The parent DisplayObjectContainer on which to add this CheckBox.
  50. * @param xpos The x position to place this component.
  51. * @param ypos The y position to place this component.
  52. * @param label String containing the label for this component.
  53. * @param defaultHandler The event handling function to handle the default event for this component (change in this case).
  54. */
  55. public function RotarySelector(parent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0, label:String = "", defaultHandler:Function = null)
  56. {
  57. _labelText = label;
  58. super(parent, xpos, ypos);
  59. if(defaultHandler != null)
  60. {
  61. addEventListener(Event.CHANGE, defaultHandler);
  62. }
  63. }
  64. /**
  65. * Initializes the component.
  66. */
  67. override protected function init():void
  68. {
  69. super.init();
  70. setSize(60, 60);
  71. }
  72. /**
  73. * Creates the children for this component
  74. */
  75. override protected function addChildren():void
  76. {
  77. _knob = new Sprite();
  78. _knob.buttonMode = true;
  79. _knob.useHandCursor = true;
  80. addChild(_knob);
  81. _label = new Label();
  82. _label.autoSize = true;
  83. addChild(_label);
  84. _labels = new Sprite();
  85. addChild(_labels);
  86. _knob.addEventListener(MouseEvent.CLICK, onClick);
  87. }
  88. /**
  89. * Decrements the index of the current choice.
  90. */
  91. protected function decrement():void
  92. {
  93. if(_choice > 0)
  94. {
  95. _choice--;
  96. draw();
  97. dispatchEvent(new Event(Event.CHANGE));
  98. }
  99. }
  100. /**
  101. * Increments the index of the current choice.
  102. */
  103. protected function increment():void
  104. {
  105. if(_choice < _numChoices - 1)
  106. {
  107. _choice++;
  108. draw();
  109. dispatchEvent(new Event(Event.CHANGE));
  110. }
  111. }
  112. /**
  113. * Removes old labels.
  114. */
  115. protected function resetLabels():void
  116. {
  117. while(_labels.numChildren > 0)
  118. {
  119. _labels.removeChildAt(0);
  120. }
  121. _labels.x = _width / 2 - 5;
  122. _labels.y = _height / 2 - 10;
  123. }
  124. /**
  125. * Draw the knob at the specified radius.
  126. * @param radius The radius with which said knob will be drawn.
  127. */
  128. protected function drawKnob(radius:Number):void
  129. {
  130. _knob.graphics.clear();
  131. _knob.graphics.beginFill(Style.BACKGROUND);
  132. _knob.graphics.drawCircle(0, 0, radius);
  133. _knob.graphics.endFill();
  134. _knob.graphics.beginFill(Style.BUTTON_FACE);
  135. _knob.graphics.drawCircle(0, 0, radius - 2);
  136. _knob.x = _width / 2;
  137. _knob.y = _height / 2;
  138. }
  139. ///////////////////////////////////
  140. // public methods
  141. ///////////////////////////////////
  142. /**
  143. * Draws the visual ui of the component.
  144. */
  145. override public function draw():void
  146. {
  147. super.draw();
  148. var radius:Number = Math.min(_width, _height) / 2;
  149. drawKnob(radius);
  150. resetLabels();
  151. var arc:Number = Math.PI * 1.5 / _numChoices; // the angle between each choice
  152. var start:Number = - Math.PI / 2 - arc * (_numChoices - 1) / 2; // the starting angle for choice 0
  153. graphics.clear();
  154. graphics.lineStyle(4, Style.BACKGROUND, .5);
  155. for(var i:int = 0; i < _numChoices; i++)
  156. {
  157. var angle:Number = start + arc * i;
  158. var sin:Number = Math.sin(angle);
  159. var cos:Number = Math.cos(angle);
  160. graphics.moveTo(_knob.x, _knob.y);
  161. graphics.lineTo(_knob.x + cos * (radius + 2), _knob.y + sin * (radius + 2));
  162. var lab:Label = new Label(_labels, cos * (radius + 10), sin * (radius + 10));
  163. lab.mouseEnabled = true;
  164. lab.buttonMode = true;
  165. lab.useHandCursor = true;
  166. lab.addEventListener(MouseEvent.CLICK, onLabelClick);
  167. if(_labelMode == ALPHABETIC)
  168. {
  169. lab.text = String.fromCharCode(65 + i);
  170. }
  171. else if(_labelMode == NUMERIC)
  172. {
  173. lab.text = (i + 1).toString();
  174. }
  175. else if(_labelMode == ROMAN)
  176. {
  177. var chars:Array = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"];
  178. lab.text = chars[i];
  179. }
  180. if(i != _choice)
  181. {
  182. lab.alpha = 0.5;
  183. }
  184. }
  185. angle = start + arc * _choice;
  186. graphics.lineStyle(4, Style.LABEL_TEXT);
  187. graphics.moveTo(_knob.x, _knob.y);
  188. graphics.lineTo(_knob.x + Math.cos(angle) * (radius + 2), _knob.y + Math.sin(angle) * (radius + 2));
  189. _label.text = _labelText;
  190. _label.draw();
  191. _label.x = _width / 2 - _label.width / 2;
  192. _label.y = _height + 2;
  193. }
  194. ///////////////////////////////////
  195. // event handler
  196. ///////////////////////////////////
  197. /**
  198. * Internal click handler.
  199. * @param event The MouseEvent passed by the system.
  200. */
  201. protected function onClick(event:MouseEvent):void
  202. {
  203. if(mouseX < _width / 2)
  204. {
  205. decrement();
  206. }
  207. else
  208. {
  209. increment();
  210. }
  211. }
  212. protected function onLabelClick(event:Event):void
  213. {
  214. var lab:Label = event.target as Label;
  215. choice = _labels.getChildIndex(lab);
  216. }
  217. ///////////////////////////////////
  218. // getter/setters
  219. ///////////////////////////////////
  220. /**
  221. * Gets / sets the number of available choices (maximum of 10).
  222. */
  223. public function set numChoices(value:uint):void
  224. {
  225. _numChoices = Math.min(value, 10);
  226. draw();
  227. }
  228. public function get numChoices():uint
  229. {
  230. return _numChoices;
  231. }
  232. /**
  233. * Gets / sets the current choice, keeping it in range of 0 to numChoices - 1.
  234. */
  235. public function set choice(value:uint):void
  236. {
  237. _choice = Math.max(0, Math.min(_numChoices - 1, value));
  238. draw();
  239. dispatchEvent(new Event(Event.CHANGE));
  240. }
  241. public function get choice():uint
  242. {
  243. return _choice;
  244. }
  245. /**
  246. * Specifies what will be used as labels for each choice. Valid values are "alphabetic", "numeric", and "none".
  247. */
  248. public function set labelMode(value:String):void
  249. {
  250. _labelMode = value;
  251. draw();
  252. }
  253. public function get labelMode():String
  254. {
  255. return _labelMode;
  256. }
  257. }
  258. }