PageRenderTime 50ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/client/lib/haxegui/controls/ComboBox.hx

http://github.com/ericmuyser/mmo
Haxe | 457 lines | 214 code | 112 blank | 131 comment | 17 complexity | 1036ddde79679179813fbcf8d2b0db7f MD5 | raw file
  1. // Copyright (c) 2009 The haxegui developers
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy of
  4. // this software and associated documentation files (the "Software"), to deal in
  5. // the Software without restriction, including without limitation the rights to
  6. // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  7. // the Software, and to permit persons to whom the Software is furnished to do so,
  8. // subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in all
  11. // copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  15. // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  16. // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  17. // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  18. // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  19. package haxegui.controls;
  20. //{{{ Imports
  21. import flash.display.DisplayObject;
  22. import flash.display.DisplayObjectContainer;
  23. import flash.display.Sprite;
  24. import flash.events.Event;
  25. import flash.events.FocusEvent;
  26. import flash.events.KeyboardEvent;
  27. import flash.events.MouseEvent;
  28. import flash.geom.Rectangle;
  29. import haxegui.DataSource;
  30. import haxegui.XmlParser;
  31. import haxegui.controls.Button;
  32. import haxegui.controls.Component;
  33. import haxegui.controls.IAdjustable;
  34. import haxegui.controls.UiList;
  35. import haxegui.controls.PopupMenu;
  36. import haxegui.events.MenuEvent;
  37. import haxegui.events.MoveEvent;
  38. import haxegui.events.ResizeEvent;
  39. import haxegui.managers.CursorManager;
  40. import haxegui.managers.StyleManager;
  41. import haxegui.toys.Arrow;
  42. import haxegui.toys.Socket;
  43. import haxegui.utils.Color;
  44. import haxegui.utils.Opts;
  45. import haxegui.utils.Size;
  46. //}}}
  47. using haxegui.controls.Component;
  48. using haxegui.utils.Color;
  49. //{{{ ComboBoxDropButton
  50. /**
  51. *
  52. * The pulldown button for a ComboBox.<br/>
  53. * <p>
  54. * This is a child of the ComboBox, so any calculations regarding the
  55. * box should refer to parent.box
  56. * </p>
  57. * @version 0.1
  58. * @author Omer Goshen <gershon@goosemoose.com>
  59. * @author Russell Weir <damonsbane@gmail.com>
  60. */
  61. class ComboBoxDropButton extends PushButton, implements IComposite {
  62. //{{{ Members
  63. public var arrow : Arrow;
  64. static var xml = Xml.parse('
  65. <haxegui:Layout name="ComboBoxDropButton">
  66. <haxegui:toys:Arrow
  67. width="8" height="8"
  68. x="10" y="11"
  69. rotation="90" color="{Color.darken(parent.color, 10)}"/>
  70. </haxegui:Layout>
  71. ').firstElement();
  72. //}}}
  73. //{{{ Functions
  74. //{{{ init
  75. public override function init(opts:Dynamic=null) {
  76. if(!Std.is(parent, ComboBox)) throw parent+" not a ComboBox";
  77. selected = false;
  78. mouseChildren = false;
  79. super.init(opts);
  80. xml.set("name", name);
  81. XmlParser.apply(ComboBoxDropButton.xml, this);
  82. // arrow = new haxegui.toys.Arrow(this);
  83. // arrow.init({ width: 8, height: 8, color: haxegui.utils.Color.darken(this.color, 10)});
  84. // arrow.rotation = 90;
  85. // arrow.move(6,7);
  86. arrow = cast firstChild();
  87. arrow.mouseEnabled = false;
  88. parent.addEventListener(ResizeEvent.RESIZE, onParentResize, false, 0, true);
  89. }
  90. //}}}
  91. //{{{ onAdded
  92. public override function onAdded(e:Event) {}
  93. //}}}
  94. //{{{ onMouseClick
  95. public override function onMouseClick(e:MouseEvent) {
  96. if(this.disabled) return;
  97. var p = new flash.geom.Point( parent.x, parent.y );
  98. p = parent.parent.localToGlobal(p);
  99. (cast parent).menu = new PopupMenu();
  100. var menu = (cast parent).menu;
  101. menu.dataSource = (cast parent).dataSource;
  102. menu.addEventListener(MenuEvent.MENU_SHOW, (cast parent).onMenuShow, false, 0, true);
  103. menu.addEventListener(MenuEvent.MENU_HIDE, onMenuHide, false, 0, true);
  104. menu.init({width:(cast parent).box.width - 22, color: DefaultStyle.INPUT_BACK});
  105. menu.x = p.x + 1;
  106. menu.y = p.y;
  107. // menu.box.width = (cast parent).box.width - 22;
  108. super.onMouseClick(e);
  109. }
  110. //}}}
  111. //{{{ onMenuShow
  112. public function onMenuShow(e:MenuEvent) {
  113. parent.dispatchEvent(e);
  114. //(cast parent).menu.addEventListener(MenuEvent.MENU_HIDE, onMenuHide, false, 0, true);
  115. }
  116. //}}}
  117. //{{{ onMenuHide
  118. public function onMenuHide(e:MenuEvent) {
  119. selected = false;
  120. //dirty = true;
  121. redraw();
  122. //trace(selected);
  123. }
  124. //}}}
  125. //{{{ onParentResize
  126. public function onParentResize(e:ResizeEvent) {
  127. moveTo(parent.asComponent().box.width - box.width, -1);
  128. box = parent.asComponent().box.clone();
  129. box.width = box.height;
  130. dirty = true;
  131. dispatchEvent(new ResizeEvent(ResizeEvent.RESIZE));
  132. }
  133. //}}}
  134. //{{{ onResize
  135. public override function onResize(e:ResizeEvent) {
  136. arrow.box = new Size(box.height - 12, box.width - 12).setAtLeastZero().toRect();
  137. arrow.dirty = true;
  138. arrow.center();
  139. arrow.move(.5*arrow.box.width, .5*arrow.box.height+1);
  140. // super.onResize(e);
  141. }
  142. //}}}
  143. //{{{ __init__
  144. static function __init__() {
  145. haxegui.Haxegui.register(ComboBoxDropButton);
  146. }
  147. //}}}
  148. //}}}
  149. }
  150. //}}}
  151. //{{{ ComboBoxBackground
  152. /**
  153. * The background for a non-editable ComboBox.<br/>
  154. * <p>
  155. * This is a child of the ComboBox, so any calculations regarding the
  156. * box should refer to parent.box
  157. * </p>
  158. * @author Omer Goshen <gershon@goosemoose.com>
  159. * @author Russell Weir <damonsbane@gmail.com>
  160. **/
  161. class ComboBoxBackground extends Component, implements IComposite {
  162. public var label : Label;
  163. //{{{ init
  164. override public function init(?opts:Dynamic=null) {
  165. // color = DefaultStyle.BACKGROUND;
  166. // color = parent.asComponent().color;
  167. super.init(opts);
  168. label = new Label(this);
  169. label.init({text: Opts.optString(opts, "label", name), disabled: this.disabled});
  170. label.move(4,4);
  171. label.tf.defaultTextFormat = DefaultStyle.getTextFormat(8, DefaultStyle.BACKGROUND.darken(100));
  172. label.tf.setTextFormat(DefaultStyle.getTextFormat(8, DefaultStyle.BACKGROUND.darken(100)));
  173. }
  174. //}}}
  175. //{{{ onAdded
  176. public override function onAdded(e:Event) {
  177. //if(.hasNext())
  178. for(child in parent.asComponent().getElementsByClass(ComboBoxBackground))
  179. if(child!=null && child!=this)
  180. throw "ComboBoxBackground is composited, and should be singular";
  181. }
  182. //}}}
  183. //{{{ __init__
  184. static function __init__() {
  185. haxegui.Haxegui.register(ComboBoxBackground);
  186. }
  187. //}}}
  188. }
  189. //}}}
  190. //{{{ ComboBox
  191. /**
  192. *
  193. * ComboBox is composited of a button for the pull-down menu, and an optional Input for custom values.
  194. *
  195. * @version 0.1
  196. * @author Omer Goshen <gershon@goosemoose.com>
  197. * @author Russell Weir <damonsbane@gmail.com>
  198. */
  199. class ComboBox extends Component, implements IDataSource, implements IAdjustable {
  200. //{{{ Members
  201. //{{{ Public
  202. public var adjustment : Adjustment;
  203. public var background : ComboBoxBackground;
  204. public var dropButton : ComboBoxDropButton;
  205. public var input : Input;
  206. public var dataSource(default, setDataSource) : DataSource;
  207. public var menu : PopupMenu;
  208. public var slot : Socket;
  209. //}}}
  210. //{{{ Private
  211. private var editable : Bool;
  212. //}}}
  213. //{{{ Static
  214. static var xml = Xml.parse('
  215. <haxegui:Layout name="ComboBox">
  216. </haxegui:Layout>
  217. ').firstElement();
  218. //}}}
  219. //}}}
  220. //{{{ Functions
  221. //{{{ init
  222. public override function init(?opts:Dynamic) {
  223. adjustment = new Adjustment({ value: 0, min: 0, max: 1, step:null, page: null});
  224. box = new Size(140,20).toRect();
  225. color = DefaultStyle.BACKGROUND;
  226. menu = new PopupMenu();
  227. super.init(opts);
  228. xml.set("name", name);
  229. XmlParser.apply(ComboBox.xml, this);
  230. editable = Opts.optBool(opts, "editable", true);
  231. mouseEnabled = true;
  232. focusRect = false;
  233. tabEnabled = false;
  234. tabChildren = true;
  235. // Input \ Background
  236. if(editable) {
  237. input = new Input(this);
  238. input.init({width: this.box.width, height: this.box.height, text: Opts.optString(opts, "text", this.name), disabled: this.disabled});
  239. input.redraw();
  240. }
  241. else {
  242. background = new ComboBoxBackground(this);
  243. background.init({width: box.width, height: box.height, color:this.color, label: Opts.optString(opts, "text", this.name), disabled: this.disabled});
  244. }
  245. // Drop Button
  246. dropButton = new ComboBoxDropButton(this);
  247. var bOpts = Opts.clone(opts);
  248. Opts.removeFields(bOpts, ["x", "y"]);
  249. dropButton.init(bOpts);
  250. dropButton.box = new Size(20,20).toRect();
  251. dropButton.place(box.width-box.height,-1);
  252. // Slot
  253. slot = new haxegui.toys.Socket(this);
  254. slot.init({visible: false});
  255. slot.place(-14,Std.int(this.box.height)>>1);
  256. slot.color = Color.tint(slot.color, .5);
  257. //
  258. if(input==null) return;
  259. input.addEventListener(MoveEvent.MOVE, onInputMoved, false, 0, true);
  260. input.addEventListener(ResizeEvent.RESIZE, onInputResized, false, 0, true);
  261. input.addEventListener(Event.CHANGE, onInputChanged, false, 0, true);
  262. dispatchEvent(new ResizeEvent(ResizeEvent.RESIZE));
  263. }
  264. //}}}
  265. private override function __setDisabled(b:Bool) : Bool {
  266. if(input!=null)
  267. input.disabled = b;
  268. if(dropButton!=null)
  269. dropButton.disabled = b;
  270. return super.__setDisabled(b);
  271. }
  272. //{{{ onInputChanged
  273. public function onInputChanged(e:Event) {
  274. dispatchEvent(e);
  275. }
  276. //}}}
  277. //{{{ onMenuItemSelected
  278. public function onMenuItemSelected(e:MouseEvent) {
  279. if(!Std.is(e.target, ListItem)) return;
  280. if(input!=null)
  281. input.setText(e.target.getChildAt(0).tf.text);
  282. if(background!=null)
  283. background.label.setText(e.target.getChildAt(0).tf.text);
  284. }
  285. //}}}
  286. //{{{ onMenuShow
  287. public function onMenuShow(e:MenuEvent) {
  288. menu.addEventListener(MouseEvent.MOUSE_DOWN, onMenuItemSelected, false, 0, true);
  289. }
  290. //}}}
  291. //{{{ onInputMoved
  292. private function onInputMoved(e:MoveEvent) {
  293. if(input==null) return;
  294. move(input.x, input.y);
  295. e.target.place(0,0);
  296. }
  297. //}}}
  298. //{{{ onInputResized
  299. private function onInputResized(e:ResizeEvent) {
  300. if(input==null) return;
  301. this.box = input.box.clone();
  302. dispatchEvent(new ResizeEvent(ResizeEvent.RESIZE));
  303. }
  304. //}}}
  305. //{{{ onResize
  306. public override function onResize(e:ResizeEvent) {
  307. if(input==null) return;
  308. input.box = box.clone();
  309. input.dirty=true;
  310. input.tf.width = box.width;
  311. input.tf.height = box.height;
  312. super.onResize(e);
  313. }
  314. //}}}
  315. //{{{ setDataSource
  316. public function setDataSource(d:DataSource) : DataSource {
  317. dataSource = d;
  318. return dataSource;
  319. }
  320. //}}}
  321. //{{{ __init__
  322. static function __init__() {
  323. haxegui.Haxegui.register(ComboBox);
  324. }
  325. //}}}
  326. //}}}
  327. }
  328. //}}}
  329. //{{{ DropDown
  330. /**
  331. * Alias for a non-editable [ComboBox]
  332. */
  333. class DropDown extends ComboBox {
  334. public override function init(?opts:Dynamic) {
  335. if(opts==null) opts = {};
  336. Reflect.setField(opts, "editable", false);
  337. super.init(opts);
  338. }
  339. //{{{ __init__
  340. static function __init__() {
  341. haxegui.Haxegui.register(DropDown);
  342. }
  343. //}}}
  344. }
  345. //}}}