GComboBox.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. using System;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using FairyGUI.Utils;
  5. namespace FairyGUI
  6. {
  7. /// <summary>
  8. /// GComboBox class.
  9. /// </summary>
  10. public class GComboBox : GComponent
  11. {
  12. /// <summary>
  13. /// Visible item count of the drop down list.
  14. /// </summary>
  15. public int visibleItemCount;
  16. /// <summary>
  17. ///
  18. /// </summary>
  19. public GComponent dropdown;
  20. /// <summary>
  21. /// Play sound when button is clicked.
  22. /// </summary>
  23. public NAudioClip sound;
  24. /// <summary>
  25. /// Volume of the click sound. (0-1)
  26. /// </summary>
  27. public float soundVolumeScale;
  28. protected GObject _titleObject;
  29. protected GObject _iconObject;
  30. protected GList _list;
  31. protected List<string> _items;
  32. protected List<string> _icons;
  33. protected List<string> _values;
  34. protected PopupDirection _popupDirection;
  35. protected Controller _selectionController;
  36. bool _itemsUpdated;
  37. int _selectedIndex;
  38. Controller _buttonController;
  39. bool _down;
  40. bool _over;
  41. EventListener _onChanged;
  42. public GComboBox()
  43. {
  44. visibleItemCount = UIConfig.defaultComboBoxVisibleItemCount;
  45. _itemsUpdated = true;
  46. _selectedIndex = -1;
  47. _items = new List<string>();
  48. _values = new List<string>();
  49. _popupDirection = PopupDirection.Auto;
  50. soundVolumeScale = 1;
  51. }
  52. /// <summary>
  53. /// Dispatched when selection was changed.
  54. /// </summary>
  55. public EventListener onChanged
  56. {
  57. get { return _onChanged ?? (_onChanged = new EventListener(this, "onChanged")); }
  58. }
  59. /// <summary>
  60. /// Icon of the combobox.
  61. /// </summary>
  62. override public string icon
  63. {
  64. get
  65. {
  66. if (_iconObject != null)
  67. return _iconObject.icon;
  68. else
  69. return null;
  70. }
  71. set
  72. {
  73. if (_iconObject != null)
  74. _iconObject.icon = value;
  75. UpdateGear(7);
  76. }
  77. }
  78. /// <summary>
  79. /// Title of the combobox.
  80. /// </summary>
  81. public string title
  82. {
  83. get
  84. {
  85. if (_titleObject != null)
  86. return _titleObject.text;
  87. else
  88. return null;
  89. }
  90. set
  91. {
  92. if (_titleObject != null)
  93. _titleObject.text = value;
  94. UpdateGear(6);
  95. }
  96. }
  97. /// <summary>
  98. /// Same of the title.
  99. /// </summary>
  100. override public string text
  101. {
  102. get { return this.title; }
  103. set { this.title = value; }
  104. }
  105. /// <summary>
  106. /// Text color
  107. /// </summary>
  108. public Color titleColor
  109. {
  110. get
  111. {
  112. GTextField tf = GetTextField();
  113. if (tf != null)
  114. return tf.color;
  115. else
  116. return Color.black;
  117. }
  118. set
  119. {
  120. GTextField tf = GetTextField();
  121. if (tf != null)
  122. tf.color = value;
  123. }
  124. }
  125. /// <summary>
  126. ///
  127. /// </summary>
  128. public int titleFontSize
  129. {
  130. get
  131. {
  132. GTextField tf = GetTextField();
  133. if (tf != null)
  134. return tf.textFormat.size;
  135. else
  136. return 0;
  137. }
  138. set
  139. {
  140. GTextField tf = GetTextField();
  141. if (tf != null)
  142. {
  143. TextFormat format = tf.textFormat;
  144. format.size = value;
  145. tf.textFormat = format;
  146. }
  147. }
  148. }
  149. /// <summary>
  150. /// Items to build up drop down list.
  151. /// </summary>
  152. public string[] items
  153. {
  154. get
  155. {
  156. return _items.ToArray();
  157. }
  158. set
  159. {
  160. _items.Clear();
  161. if (value != null)
  162. _items.AddRange(value);
  163. ApplyListChange();
  164. }
  165. }
  166. /// <summary>
  167. ///
  168. /// </summary>
  169. public string[] icons
  170. {
  171. get { return _icons != null ? _icons.ToArray() : null; }
  172. set
  173. {
  174. this.iconList.Clear();
  175. if (value != null)
  176. _icons.AddRange(value);
  177. ApplyListChange();
  178. }
  179. }
  180. /// <summary>
  181. /// Values, should be same size of the items.
  182. /// </summary>
  183. public string[] values
  184. {
  185. get { return _values.ToArray(); }
  186. set
  187. {
  188. _values.Clear();
  189. if (value != null)
  190. _values.AddRange(value);
  191. }
  192. }
  193. /// <summary>
  194. ///
  195. /// </summary>
  196. public List<string> itemList
  197. {
  198. get { return _items; }
  199. }
  200. /// <summary>
  201. ///
  202. /// </summary>
  203. public List<string> valueList
  204. {
  205. get { return _values; }
  206. }
  207. /// <summary>
  208. ///
  209. /// </summary>
  210. public List<string> iconList
  211. {
  212. get { return _icons ?? (_icons = new List<string>()); }
  213. }
  214. /// <summary>
  215. /// Call this method after you made changes on itemList or iconList
  216. /// </summary>
  217. public void ApplyListChange()
  218. {
  219. if (_items.Count > 0)
  220. {
  221. if (_selectedIndex >= _items.Count)
  222. _selectedIndex = _items.Count - 1;
  223. else if (_selectedIndex == -1)
  224. _selectedIndex = 0;
  225. this.text = _items[_selectedIndex];
  226. if (_icons != null && _selectedIndex < _icons.Count)
  227. this.icon = _icons[_selectedIndex];
  228. }
  229. else
  230. {
  231. this.text = string.Empty;
  232. if (_icons != null)
  233. this.icon = null;
  234. _selectedIndex = -1;
  235. }
  236. _itemsUpdated = true;
  237. }
  238. /// <summary>
  239. /// Selected index.
  240. /// </summary>
  241. public int selectedIndex
  242. {
  243. get
  244. {
  245. return _selectedIndex;
  246. }
  247. set
  248. {
  249. if (_selectedIndex == value)
  250. return;
  251. _selectedIndex = value;
  252. if (_selectedIndex >= 0 && _selectedIndex < _items.Count)
  253. {
  254. this.text = (string)_items[_selectedIndex];
  255. if (_icons != null && _selectedIndex < _icons.Count)
  256. this.icon = _icons[_selectedIndex];
  257. }
  258. else
  259. {
  260. this.text = string.Empty;
  261. if (_icons != null)
  262. this.icon = null;
  263. }
  264. UpdateSelectionController();
  265. }
  266. }
  267. /// <summary>
  268. ///
  269. /// </summary>
  270. public Controller selectionController
  271. {
  272. get { return _selectionController; }
  273. set { _selectionController = value; }
  274. }
  275. /// <summary>
  276. /// Selected value.
  277. /// </summary>
  278. public string value
  279. {
  280. get
  281. {
  282. if (_selectedIndex >= 0 && _selectedIndex < _values.Count)
  283. return _values[_selectedIndex];
  284. else
  285. return null;
  286. }
  287. set
  288. {
  289. int index = _values.IndexOf(value);
  290. if (index == -1 && value == null)
  291. index = _values.IndexOf(string.Empty);
  292. if (index == -1)
  293. index = 0;
  294. this.selectedIndex = index;
  295. }
  296. }
  297. /// <summary>
  298. ///
  299. /// </summary>
  300. public PopupDirection popupDirection
  301. {
  302. get { return _popupDirection; }
  303. set { _popupDirection = value; }
  304. }
  305. /// <summary>
  306. ///
  307. /// </summary>
  308. /// <returns></returns>
  309. public GTextField GetTextField()
  310. {
  311. if (_titleObject is GTextField)
  312. return (GTextField)_titleObject;
  313. else if (_titleObject is GLabel)
  314. return ((GLabel)_titleObject).GetTextField();
  315. else if (_titleObject is GButton)
  316. return ((GButton)_titleObject).GetTextField();
  317. else
  318. return null;
  319. }
  320. protected void SetState(string value)
  321. {
  322. if (_buttonController != null)
  323. _buttonController.selectedPage = value;
  324. }
  325. protected void SetCurrentState()
  326. {
  327. if (this.grayed && _buttonController != null && _buttonController.HasPage(GButton.DISABLED))
  328. SetState(GButton.DISABLED);
  329. else if (dropdown != null && dropdown.parent != null)
  330. SetState(GButton.DOWN);
  331. else
  332. SetState(_over ? GButton.OVER : GButton.UP);
  333. }
  334. override protected void HandleGrayedChanged()
  335. {
  336. if (_buttonController != null && _buttonController.HasPage(GButton.DISABLED))
  337. {
  338. if (this.grayed)
  339. SetState(GButton.DISABLED);
  340. else
  341. SetState(GButton.UP);
  342. }
  343. else
  344. base.HandleGrayedChanged();
  345. }
  346. override public void HandleControllerChanged(Controller c)
  347. {
  348. base.HandleControllerChanged(c);
  349. if (_selectionController == c)
  350. this.selectedIndex = c.selectedIndex;
  351. }
  352. void UpdateSelectionController()
  353. {
  354. if (_selectionController != null && !_selectionController.changing
  355. && _selectedIndex < _selectionController.pageCount)
  356. {
  357. Controller c = _selectionController;
  358. _selectionController = null;
  359. c.selectedIndex = _selectedIndex;
  360. _selectionController = c;
  361. }
  362. }
  363. public override void Dispose()
  364. {
  365. if (dropdown != null)
  366. {
  367. dropdown.Dispose();
  368. dropdown = null;
  369. }
  370. _selectionController = null;
  371. base.Dispose();
  372. }
  373. override protected void ConstructExtension(ByteBuffer buffer)
  374. {
  375. buffer.Seek(0, 6);
  376. _buttonController = GetController("button");
  377. _titleObject = GetChild("title");
  378. _iconObject = GetChild("icon");
  379. string str = buffer.ReadS();
  380. if (str != null)
  381. {
  382. dropdown = UIPackage.CreateObjectFromURL(str) as GComponent;
  383. if (dropdown == null)
  384. {
  385. Debug.LogWarning("FairyGUI: " + this.resourceURL + " should be a component.");
  386. return;
  387. }
  388. _list = dropdown.GetChild("list") as GList;
  389. if (_list == null)
  390. {
  391. Debug.LogWarning("FairyGUI: " + this.resourceURL + ": should container a list component named list.");
  392. return;
  393. }
  394. _list.onClickItem.Add(__clickItem);
  395. _list.AddRelation(dropdown, RelationType.Width);
  396. _list.RemoveRelation(dropdown, RelationType.Height);
  397. dropdown.AddRelation(_list, RelationType.Height);
  398. dropdown.RemoveRelation(_list, RelationType.Width);
  399. dropdown.SetHome(this);
  400. }
  401. displayObject.onRollOver.Add(__rollover);
  402. displayObject.onRollOut.Add(__rollout);
  403. displayObject.onTouchBegin.Add(__touchBegin);
  404. displayObject.onTouchEnd.Add(__touchEnd);
  405. displayObject.onClick.Add(__click);
  406. }
  407. override public void Setup_AfterAdd(ByteBuffer buffer, int beginPos)
  408. {
  409. base.Setup_AfterAdd(buffer, beginPos);
  410. if (!buffer.Seek(beginPos, 6))
  411. return;
  412. if ((ObjectType)buffer.ReadByte() != packageItem.objectType)
  413. return;
  414. string str;
  415. int itemCount = buffer.ReadShort();
  416. for (int i = 0; i < itemCount; i++)
  417. {
  418. int nextPos = buffer.ReadUshort();
  419. nextPos += buffer.position;
  420. _items.Add(buffer.ReadS());
  421. _values.Add(buffer.ReadS());
  422. str = buffer.ReadS();
  423. if (str != null)
  424. {
  425. if (_icons == null)
  426. _icons = new List<string>();
  427. _icons.Add(str);
  428. }
  429. buffer.position = nextPos;
  430. }
  431. str = buffer.ReadS();
  432. if (str != null)
  433. {
  434. this.text = str;
  435. _selectedIndex = _items.IndexOf(str);
  436. }
  437. else if (_items.Count > 0)
  438. {
  439. _selectedIndex = 0;
  440. this.text = _items[0];
  441. }
  442. else
  443. _selectedIndex = -1;
  444. str = buffer.ReadS();
  445. if (str != null)
  446. this.icon = str;
  447. if (buffer.ReadBool())
  448. this.titleColor = buffer.ReadColor();
  449. int iv = buffer.ReadInt();
  450. if (iv > 0)
  451. visibleItemCount = iv;
  452. _popupDirection = (PopupDirection)buffer.ReadByte();
  453. iv = buffer.ReadShort();
  454. if (iv >= 0)
  455. _selectionController = parent.GetControllerAt(iv);
  456. if (buffer.version >= 5)
  457. {
  458. str = buffer.ReadS();
  459. if (str != null)
  460. sound = UIPackage.GetItemAssetByURL(str) as NAudioClip;
  461. soundVolumeScale = buffer.ReadFloat();
  462. }
  463. }
  464. public void UpdateDropdownList()
  465. {
  466. if (_itemsUpdated)
  467. {
  468. _itemsUpdated = false;
  469. RenderDropdownList();
  470. _list.ResizeToFit(visibleItemCount);
  471. }
  472. }
  473. protected void ShowDropdown()
  474. {
  475. UpdateDropdownList();
  476. if (_list.selectionMode == ListSelectionMode.Single)
  477. _list.selectedIndex = -1;
  478. dropdown.width = this.width;
  479. _list.EnsureBoundsCorrect(); //avoid flicker
  480. this.root.TogglePopup(dropdown, this, _popupDirection);
  481. if (dropdown.parent != null)
  482. {
  483. dropdown.displayObject.onRemovedFromStage.Add(__popupWinClosed);
  484. SetState(GButton.DOWN);
  485. }
  486. }
  487. virtual protected void RenderDropdownList()
  488. {
  489. _list.RemoveChildrenToPool();
  490. int cnt = _items.Count;
  491. for (int i = 0; i < cnt; i++)
  492. {
  493. GObject item = _list.AddItemFromPool();
  494. item.text = _items[i];
  495. item.icon = (_icons != null && i < _icons.Count) ? _icons[i] : null;
  496. item.name = i < _values.Count ? _values[i] : string.Empty;
  497. }
  498. }
  499. private void __popupWinClosed(object obj)
  500. {
  501. dropdown.displayObject.onRemovedFromStage.Remove(__popupWinClosed);
  502. SetCurrentState();
  503. RequestFocus();
  504. }
  505. private void __clickItem(EventContext context)
  506. {
  507. if (dropdown.parent is GRoot)
  508. ((GRoot)dropdown.parent).HidePopup(dropdown);
  509. _selectedIndex = int.MinValue;
  510. this.selectedIndex = _list.GetChildIndex((GObject)context.data);
  511. DispatchEvent("onChanged", null);
  512. }
  513. private void __rollover()
  514. {
  515. _over = true;
  516. if (_down || dropdown != null && dropdown.parent != null)
  517. return;
  518. SetCurrentState();
  519. }
  520. private void __rollout()
  521. {
  522. _over = false;
  523. if (_down || dropdown != null && dropdown.parent != null)
  524. return;
  525. SetCurrentState();
  526. }
  527. private void __touchBegin(EventContext context)
  528. {
  529. if (context.initiator is InputTextField)
  530. return;
  531. _down = true;
  532. if (dropdown != null)
  533. ShowDropdown();
  534. context.CaptureTouch();
  535. }
  536. private void __touchEnd(EventContext context)
  537. {
  538. if (_down)
  539. {
  540. _down = false;
  541. if (dropdown != null && dropdown.parent != null)
  542. SetCurrentState();
  543. }
  544. }
  545. private void __click()
  546. {
  547. if (sound != null && sound.nativeClip != null)
  548. Stage.inst.PlayOneShotSound(sound.nativeClip, soundVolumeScale);
  549. }
  550. }
  551. }