using System; using System.Collections.Generic; using UnityEngine; using FairyGUI.Utils; namespace FairyGUI { /// /// GComboBox class. /// public class GComboBox : GComponent { /// /// Visible item count of the drop down list. /// public int visibleItemCount; /// /// /// public GComponent dropdown; /// /// Play sound when button is clicked. /// public NAudioClip sound; /// /// Volume of the click sound. (0-1) /// public float soundVolumeScale; protected GObject _titleObject; protected GObject _iconObject; protected GList _list; protected List _items; protected List _icons; protected List _values; protected PopupDirection _popupDirection; protected Controller _selectionController; bool _itemsUpdated; int _selectedIndex; Controller _buttonController; bool _down; bool _over; EventListener _onChanged; public GComboBox() { visibleItemCount = UIConfig.defaultComboBoxVisibleItemCount; _itemsUpdated = true; _selectedIndex = -1; _items = new List(); _values = new List(); _popupDirection = PopupDirection.Auto; soundVolumeScale = 1; } /// /// Dispatched when selection was changed. /// public EventListener onChanged { get { return _onChanged ?? (_onChanged = new EventListener(this, "onChanged")); } } /// /// Icon of the combobox. /// override public string icon { get { if (_iconObject != null) return _iconObject.icon; else return null; } set { if (_iconObject != null) _iconObject.icon = value; UpdateGear(7); } } /// /// Title of the combobox. /// public string title { get { if (_titleObject != null) return _titleObject.text; else return null; } set { if (_titleObject != null) _titleObject.text = value; UpdateGear(6); } } /// /// Same of the title. /// override public string text { get { return this.title; } set { this.title = value; } } /// /// Text color /// public Color titleColor { get { GTextField tf = GetTextField(); if (tf != null) return tf.color; else return Color.black; } set { GTextField tf = GetTextField(); if (tf != null) tf.color = value; } } /// /// /// public int titleFontSize { get { GTextField tf = GetTextField(); if (tf != null) return tf.textFormat.size; else return 0; } set { GTextField tf = GetTextField(); if (tf != null) { TextFormat format = tf.textFormat; format.size = value; tf.textFormat = format; } } } /// /// Items to build up drop down list. /// public string[] items { get { return _items.ToArray(); } set { _items.Clear(); if (value != null) _items.AddRange(value); ApplyListChange(); } } /// /// /// public string[] icons { get { return _icons != null ? _icons.ToArray() : null; } set { this.iconList.Clear(); if (value != null) _icons.AddRange(value); ApplyListChange(); } } /// /// Values, should be same size of the items. /// public string[] values { get { return _values.ToArray(); } set { _values.Clear(); if (value != null) _values.AddRange(value); } } /// /// /// public List itemList { get { return _items; } } /// /// /// public List valueList { get { return _values; } } /// /// /// public List iconList { get { return _icons ?? (_icons = new List()); } } /// /// Call this method after you made changes on itemList or iconList /// public void ApplyListChange() { if (_items.Count > 0) { if (_selectedIndex >= _items.Count) _selectedIndex = _items.Count - 1; else if (_selectedIndex == -1) _selectedIndex = 0; this.text = _items[_selectedIndex]; if (_icons != null && _selectedIndex < _icons.Count) this.icon = _icons[_selectedIndex]; } else { this.text = string.Empty; if (_icons != null) this.icon = null; _selectedIndex = -1; } _itemsUpdated = true; } /// /// Selected index. /// public int selectedIndex { get { return _selectedIndex; } set { if (_selectedIndex == value) return; _selectedIndex = value; if (_selectedIndex >= 0 && _selectedIndex < _items.Count) { this.text = (string)_items[_selectedIndex]; if (_icons != null && _selectedIndex < _icons.Count) this.icon = _icons[_selectedIndex]; } else { this.text = string.Empty; if (_icons != null) this.icon = null; } UpdateSelectionController(); } } /// /// /// public Controller selectionController { get { return _selectionController; } set { _selectionController = value; } } /// /// Selected value. /// public string value { get { if (_selectedIndex >= 0 && _selectedIndex < _values.Count) return _values[_selectedIndex]; else return null; } set { int index = _values.IndexOf(value); if (index == -1 && value == null) index = _values.IndexOf(string.Empty); if (index == -1) index = 0; this.selectedIndex = index; } } /// /// /// public PopupDirection popupDirection { get { return _popupDirection; } set { _popupDirection = value; } } /// /// /// /// public GTextField GetTextField() { if (_titleObject is GTextField) return (GTextField)_titleObject; else if (_titleObject is GLabel) return ((GLabel)_titleObject).GetTextField(); else if (_titleObject is GButton) return ((GButton)_titleObject).GetTextField(); else return null; } protected void SetState(string value) { if (_buttonController != null) _buttonController.selectedPage = value; } protected void SetCurrentState() { if (this.grayed && _buttonController != null && _buttonController.HasPage(GButton.DISABLED)) SetState(GButton.DISABLED); else if (dropdown != null && dropdown.parent != null) SetState(GButton.DOWN); else SetState(_over ? GButton.OVER : GButton.UP); } override protected void HandleGrayedChanged() { if (_buttonController != null && _buttonController.HasPage(GButton.DISABLED)) { if (this.grayed) SetState(GButton.DISABLED); else SetState(GButton.UP); } else base.HandleGrayedChanged(); } override public void HandleControllerChanged(Controller c) { base.HandleControllerChanged(c); if (_selectionController == c) this.selectedIndex = c.selectedIndex; } void UpdateSelectionController() { if (_selectionController != null && !_selectionController.changing && _selectedIndex < _selectionController.pageCount) { Controller c = _selectionController; _selectionController = null; c.selectedIndex = _selectedIndex; _selectionController = c; } } public override void Dispose() { if (dropdown != null) { dropdown.Dispose(); dropdown = null; } _selectionController = null; base.Dispose(); } override protected void ConstructExtension(ByteBuffer buffer) { buffer.Seek(0, 6); _buttonController = GetController("button"); _titleObject = GetChild("title"); _iconObject = GetChild("icon"); string str = buffer.ReadS(); if (str != null) { dropdown = UIPackage.CreateObjectFromURL(str) as GComponent; if (dropdown == null) { Debug.LogWarning("FairyGUI: " + this.resourceURL + " should be a component."); return; } _list = dropdown.GetChild("list") as GList; if (_list == null) { Debug.LogWarning("FairyGUI: " + this.resourceURL + ": should container a list component named list."); return; } _list.onClickItem.Add(__clickItem); _list.AddRelation(dropdown, RelationType.Width); _list.RemoveRelation(dropdown, RelationType.Height); dropdown.AddRelation(_list, RelationType.Height); dropdown.RemoveRelation(_list, RelationType.Width); dropdown.SetHome(this); } displayObject.onRollOver.Add(__rollover); displayObject.onRollOut.Add(__rollout); displayObject.onTouchBegin.Add(__touchBegin); displayObject.onTouchEnd.Add(__touchEnd); displayObject.onClick.Add(__click); } override public void Setup_AfterAdd(ByteBuffer buffer, int beginPos) { base.Setup_AfterAdd(buffer, beginPos); if (!buffer.Seek(beginPos, 6)) return; if ((ObjectType)buffer.ReadByte() != packageItem.objectType) return; string str; int itemCount = buffer.ReadShort(); for (int i = 0; i < itemCount; i++) { int nextPos = buffer.ReadUshort(); nextPos += buffer.position; _items.Add(buffer.ReadS()); _values.Add(buffer.ReadS()); str = buffer.ReadS(); if (str != null) { if (_icons == null) _icons = new List(); _icons.Add(str); } buffer.position = nextPos; } str = buffer.ReadS(); if (str != null) { this.text = str; _selectedIndex = _items.IndexOf(str); } else if (_items.Count > 0) { _selectedIndex = 0; this.text = _items[0]; } else _selectedIndex = -1; str = buffer.ReadS(); if (str != null) this.icon = str; if (buffer.ReadBool()) this.titleColor = buffer.ReadColor(); int iv = buffer.ReadInt(); if (iv > 0) visibleItemCount = iv; _popupDirection = (PopupDirection)buffer.ReadByte(); iv = buffer.ReadShort(); if (iv >= 0) _selectionController = parent.GetControllerAt(iv); if (buffer.version >= 5) { str = buffer.ReadS(); if (str != null) sound = UIPackage.GetItemAssetByURL(str) as NAudioClip; soundVolumeScale = buffer.ReadFloat(); } } public void UpdateDropdownList() { if (_itemsUpdated) { _itemsUpdated = false; RenderDropdownList(); _list.ResizeToFit(visibleItemCount); } } protected void ShowDropdown() { UpdateDropdownList(); if (_list.selectionMode == ListSelectionMode.Single) _list.selectedIndex = -1; dropdown.width = this.width; _list.EnsureBoundsCorrect(); //avoid flicker this.root.TogglePopup(dropdown, this, _popupDirection); if (dropdown.parent != null) { dropdown.displayObject.onRemovedFromStage.Add(__popupWinClosed); SetState(GButton.DOWN); } } virtual protected void RenderDropdownList() { _list.RemoveChildrenToPool(); int cnt = _items.Count; for (int i = 0; i < cnt; i++) { GObject item = _list.AddItemFromPool(); item.text = _items[i]; item.icon = (_icons != null && i < _icons.Count) ? _icons[i] : null; item.name = i < _values.Count ? _values[i] : string.Empty; } } private void __popupWinClosed(object obj) { dropdown.displayObject.onRemovedFromStage.Remove(__popupWinClosed); SetCurrentState(); RequestFocus(); } private void __clickItem(EventContext context) { if (dropdown.parent is GRoot) ((GRoot)dropdown.parent).HidePopup(dropdown); _selectedIndex = int.MinValue; this.selectedIndex = _list.GetChildIndex((GObject)context.data); DispatchEvent("onChanged", null); } private void __rollover() { _over = true; if (_down || dropdown != null && dropdown.parent != null) return; SetCurrentState(); } private void __rollout() { _over = false; if (_down || dropdown != null && dropdown.parent != null) return; SetCurrentState(); } private void __touchBegin(EventContext context) { if (context.initiator is InputTextField) return; _down = true; if (dropdown != null) ShowDropdown(); context.CaptureTouch(); } private void __touchEnd(EventContext context) { if (_down) { _down = false; if (dropdown != null && dropdown.parent != null) SetCurrentState(); } } private void __click() { if (sound != null && sound.nativeClip != null) Stage.inst.PlayOneShotSound(sound.nativeClip, soundVolumeScale); } } }