using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System;
public class ComboBox : MonoBehaviour
{
private Dictionary< object, object> dataSource;
private object currentValue;
private object currentDisplayText;
private int currentIndex;
private GUISkin skin;
private Rect rect;
private Rect relativeRect;
private Rect parentWinRect;
private Rect rectList;
private Rect rectListView;
private Rect rectListViewGroupTop;
private Rect rectListViewGroupBottom;
private bool showList;
private int listItemCount;
private Vector2 scrollPosition;
private Texture2D scrollBarBg;
private Texture2D scrollBarThumb;
private float showListTime;
private int guiDepth;
private bool alreadyInitGuiDepth;
/// <summary>
/// 選擇項更改事件參數
/// </summary>
public class SelectItemChangedArgs : EventArgs
{
private object itemValue;
private object itemDisplayText;
public object ItemValue{
get{
return itemValue;
}
}
public object ItemDisplayText{
get{
return itemDisplayText;
}
}
public SelectItemChangedArgs ( object iValue, object iDisplayText)
{
itemValue = iValue;
itemDisplayText = iDisplayText;
}
}
/// <summary>
/// 選擇項更改事件
/// </summary>
public event EventHandler<SelectItemChangedArgs> OnSelectItemChanged;
public object SelectValue {
get { return currentValue; }
}
public object SelectDisplayText {
get { return currentDisplayText; }
}
public float ShowListTime {
get { return showListTime; }
}
/// <summary>
/// 數據源
/// </summary>
public Dictionary< object, object> DataSource{
set{
dataSource = value;
currentDisplayText = null;
currentValue = null;
}
get{
return dataSource;
}
}
/// <summary>
/// 初始化各項參數,控件應該只調用一次此方法,進行重置數據源直接使用DataSource屬性即可
/// </summary>
/// <param name="s">
/// A <see cref="GUISkin"/>
/// </param>
/// <param name="data">
/// A <see cref="Dictionary<System.Object, System.Object> "/>
/// </param>
/// <param name="r">
/// A <see cref="Rect"/>
/// </param>
/// <param name="listCount">
/// A <see cref="System.Int32"/>
/// </param>
/// <param name="barBg">
/// A <see cref="Texture2D"/>
/// </param>
/// <param name="barThumb">
/// A <see cref="Texture2D"/>
/// </param>
/// <param name="depth">
/// A <see cref="System.Int32"/>
/// </param>
public void Init(GUISkin s, Dictionary< object, object> data, Rect r, int listCount, Texture2D barBg, Texture2D barThumb, int depth)
{
skin = s;
dataSource = data;
relativeRect = r;
listItemCount = listCount;
scrollBarBg = barBg;
scrollBarThumb = barThumb;
currentIndex = - 1;
// 將控件置於當前GUI元素之上,並且只在第一次調用初始化方法設置GUI深度,防止循環中重復調用
if (!alreadyInitGuiDepth){
guiDepth = GUI.depth - 1;
alreadyInitGuiDepth = true;
}
currentDisplayText = null;
currentValue = null;
GUI.skin.verticalScrollbar.normal.background = scrollBarBg;
GUI.skin.verticalScrollbar.margin = new RectOffset ( 0, 0, 0, 0);
GUI.skin.verticalScrollbarThumb.normal.background = scrollBarThumb;
}
/// <summary>
/// 設置父類容器的坐標范圍,計算控件在屏幕上真正的坐標位置
/// </summary>
/// <param name="rectParent">
/// A <see cref="Rect"/>
/// </param>
public void SetParentRect(Rect rectParent)
{
parentWinRect = rectParent;
rect = new Rect(parentWinRect.x + relativeRect.x, parentWinRect.y + relativeRect.y,relativeRect.width,relativeRect.height);
}
/// <summary>
/// 強行設置下拉列表是否是示
/// </summary>
/// <param name="show">
/// A <see cref="System.Boolean"/>
/// </param>
public void SetShowList( bool show)
{
if (showList){
showList = show;
}
}
/// <summary>
/// 繪制下拉列表框
/// </summary>
public void Draw ()
{
if (skin == null || dataSource == null) {
return;
}
if (currentDisplayText == null || currentValue == null) {
if (dataSource.Count > 0) {
currentDisplayText = dataSource.Values.First ();
currentValue = dataSource.Keys.First ();
currentIndex = 0;
}
else{
currentDisplayText = " 無 ";
currentValue = - 1;
currentIndex = - 1;
}
}
if (GUI.Button (rect, currentDisplayText == null ? "" : currentDisplayText.ToString (), skin.GetStyle ( " combobox "))) {
showList = !showList;
if (showList) {
showListTime = Time.time;
} else {
showListTime = 0f;
}
}
this.DrawList();
}
/// <summary>
/// 繪制列表項
/// </summary>
public void DrawList ()
{
if (showList == true) {
this.calculateItemCount();
if (listItemCount < dataSource.Count) {
// 為了留出最方下的橫線,這里高度減1
rectList = new Rect (rect.x, rect.y + rect.height, rect.width, rect.height * listItemCount - 1);
rectListView = new Rect (rect.x, rect.y + rect.height, rect.width - GUI.skin.verticalScrollbar.fixedWidth, rect.height * dataSource.Count);
rectListViewGroupTop = new Rect (rectList.x, rectList.y, rectList.width, rectList.height + 1 - rect.height);
rectListViewGroupBottom = new Rect (rectList.x, rectList.y + rectListViewGroupTop.height, rectList.width, rect.height);
GUI.Box(rectListViewGroupTop, "", skin.GetStyle ( " comboxlist "));
GUI.Box(rectListViewGroupBottom, "", skin.GetStyle ( " comboxlistbottom "));
// scrollPosition = GUI.BeginScrollView (rectList, scrollPosition, rectListView, false, true);
scrollPosition = Vector2.Lerp(scrollPosition,GUI.BeginScrollView(rectList, scrollPosition, rectListView, false, true), 0.5f);
float top = rectList.y;
for ( int i = 0; i < dataSource.Count; i++) {
drawItem( new Rect (rectList.x, top, rect.width, rect.height),i);
top += rect.height;
}
GUI.EndScrollView ();
}
else if (dataSource.Count> 0){
rectList = new Rect (rect.x, rect.y + rect.height, rect.width, rect.height * dataSource.Count - 1);
rectListViewGroupTop = new Rect (rectList.x, rectList.y, rectList.width, rectList.height + 1 - rect.height);
rectListViewGroupBottom = new Rect (rectList.x, rectList.y + rectListViewGroupTop.height, rectList.width, rect.height);
GUI.Box(rectListViewGroupTop, "", skin.GetStyle ( " comboxlist "));
GUI.Box(rectListViewGroupBottom, "", skin.GetStyle ( " comboxlistbottom "));
GUI.BeginGroup(rectList);
float top = 0;
for ( int i = 0; i < dataSource.Count; i++) {
drawItem( new Rect ( 0, top, rect.width, rect.height),i);
top += rect.height;
}
GUI.EndGroup();
}
}
}
/// <summary>
/// 當listItemCount為0時,動態計算可以容納的數據行數
/// </summary>
private void calculateItemCount()
{
if (listItemCount== 0){
int availableAreaHeight = ( int)(parentWinRect.height - relativeRect.y - relativeRect.height - 1);
listItemCount = availableAreaHeight/( int)relativeRect.height;
}
}
/// <summary>
/// 繪制內容項,並響應事件
/// </summary>
/// <param name="r">
/// A <see cref="Rect"/>
/// </param>
/// <param name="index">
/// A <see cref="System.Int32"/>
/// </param>
private void drawItem (Rect r, int index)
{
if (GUI.Button (r, dataSource.Values.ElementAt(index).ToString (), skin.GetStyle ( " comboxitem "))) {
currentDisplayText = dataSource.Values.ElementAt (index);
currentValue = dataSource.Keys.ElementAt (index);
if (currentIndex!=index){
currentIndex = index;
if (OnSelectItemChanged!= null){
OnSelectItemChanged( this, new SelectItemChangedArgs(currentValue,currentDisplayText));
}
}
showList = false;
}
}
void OnGUI()
{
GUI.depth = guiDepth;
this.Draw();
}
/// <summary>
/// 按時間比較各ComboBox控件的順序,初衷是為了點擊新的控件時,其它ComboBox控件下拉列表自動隱藏
/// </summary>
public class ShowListComparer : IComparer<ComboBox>
{
#region IComparer[ComboBox] implementation
int IComparer<ComboBox>.Compare (ComboBox x, ComboBox y)
{
return x.showListTime.CompareTo (y.showListTime) * - 1;
}
#endregion
}
}
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System;
public class ComboBox : MonoBehaviour
{
private Dictionary< object, object> dataSource;
private object currentValue;
private object currentDisplayText;
private int currentIndex;
private GUISkin skin;
private Rect rect;
private Rect relativeRect;
private Rect parentWinRect;
private Rect rectList;
private Rect rectListView;
private Rect rectListViewGroupTop;
private Rect rectListViewGroupBottom;
private bool showList;
private int listItemCount;
private Vector2 scrollPosition;
private Texture2D scrollBarBg;
private Texture2D scrollBarThumb;
private float showListTime;
private int guiDepth;
private bool alreadyInitGuiDepth;
/// <summary>
/// 選擇項更改事件參數
/// </summary>
public class SelectItemChangedArgs : EventArgs
{
private object itemValue;
private object itemDisplayText;
public object ItemValue{
get{
return itemValue;
}
}
public object ItemDisplayText{
get{
return itemDisplayText;
}
}
public SelectItemChangedArgs ( object iValue, object iDisplayText)
{
itemValue = iValue;
itemDisplayText = iDisplayText;
}
}
/// <summary>
/// 選擇項更改事件
/// </summary>
public event EventHandler<SelectItemChangedArgs> OnSelectItemChanged;
public object SelectValue {
get { return currentValue; }
}
public object SelectDisplayText {
get { return currentDisplayText; }
}
public float ShowListTime {
get { return showListTime; }
}
/// <summary>
/// 數據源
/// </summary>
public Dictionary< object, object> DataSource{
set{
dataSource = value;
currentDisplayText = null;
currentValue = null;
}
get{
return dataSource;
}
}
/// <summary>
/// 初始化各項參數,控件應該只調用一次此方法,進行重置數據源直接使用DataSource屬性即可
/// </summary>
/// <param name="s">
/// A <see cref="GUISkin"/>
/// </param>
/// <param name="data">
/// A <see cref="Dictionary<System.Object, System.Object> "/>
/// </param>
/// <param name="r">
/// A <see cref="Rect"/>
/// </param>
/// <param name="listCount">
/// A <see cref="System.Int32"/>
/// </param>
/// <param name="barBg">
/// A <see cref="Texture2D"/>
/// </param>
/// <param name="barThumb">
/// A <see cref="Texture2D"/>
/// </param>
/// <param name="depth">
/// A <see cref="System.Int32"/>
/// </param>
public void Init(GUISkin s, Dictionary< object, object> data, Rect r, int listCount, Texture2D barBg, Texture2D barThumb, int depth)
{
skin = s;
dataSource = data;
relativeRect = r;
listItemCount = listCount;
scrollBarBg = barBg;
scrollBarThumb = barThumb;
currentIndex = - 1;
// 將控件置於當前GUI元素之上,並且只在第一次調用初始化方法設置GUI深度,防止循環中重復調用
if (!alreadyInitGuiDepth){
guiDepth = GUI.depth - 1;
alreadyInitGuiDepth = true;
}
currentDisplayText = null;
currentValue = null;
GUI.skin.verticalScrollbar.normal.background = scrollBarBg;
GUI.skin.verticalScrollbar.margin = new RectOffset ( 0, 0, 0, 0);
GUI.skin.verticalScrollbarThumb.normal.background = scrollBarThumb;
}
/// <summary>
/// 設置父類容器的坐標范圍,計算控件在屏幕上真正的坐標位置
/// </summary>
/// <param name="rectParent">
/// A <see cref="Rect"/>
/// </param>
public void SetParentRect(Rect rectParent)
{
parentWinRect = rectParent;
rect = new Rect(parentWinRect.x + relativeRect.x, parentWinRect.y + relativeRect.y,relativeRect.width,relativeRect.height);
}
/// <summary>
/// 強行設置下拉列表是否是示
/// </summary>
/// <param name="show">
/// A <see cref="System.Boolean"/>
/// </param>
public void SetShowList( bool show)
{
if (showList){
showList = show;
}
}
/// <summary>
/// 繪制下拉列表框
/// </summary>
public void Draw ()
{
if (skin == null || dataSource == null) {
return;
}
if (currentDisplayText == null || currentValue == null) {
if (dataSource.Count > 0) {
currentDisplayText = dataSource.Values.First ();
currentValue = dataSource.Keys.First ();
currentIndex = 0;
}
else{
currentDisplayText = " 無 ";
currentValue = - 1;
currentIndex = - 1;
}
}
if (GUI.Button (rect, currentDisplayText == null ? "" : currentDisplayText.ToString (), skin.GetStyle ( " combobox "))) {
showList = !showList;
if (showList) {
showListTime = Time.time;
} else {
showListTime = 0f;
}
}
this.DrawList();
}
/// <summary>
/// 繪制列表項
/// </summary>
public void DrawList ()
{
if (showList == true) {
this.calculateItemCount();
if (listItemCount < dataSource.Count) {
// 為了留出最方下的橫線,這里高度減1
rectList = new Rect (rect.x, rect.y + rect.height, rect.width, rect.height * listItemCount - 1);
rectListView = new Rect (rect.x, rect.y + rect.height, rect.width - GUI.skin.verticalScrollbar.fixedWidth, rect.height * dataSource.Count);
rectListViewGroupTop = new Rect (rectList.x, rectList.y, rectList.width, rectList.height + 1 - rect.height);
rectListViewGroupBottom = new Rect (rectList.x, rectList.y + rectListViewGroupTop.height, rectList.width, rect.height);
GUI.Box(rectListViewGroupTop, "", skin.GetStyle ( " comboxlist "));
GUI.Box(rectListViewGroupBottom, "", skin.GetStyle ( " comboxlistbottom "));
// scrollPosition = GUI.BeginScrollView (rectList, scrollPosition, rectListView, false, true);
scrollPosition = Vector2.Lerp(scrollPosition,GUI.BeginScrollView(rectList, scrollPosition, rectListView, false, true), 0.5f);
float top = rectList.y;
for ( int i = 0; i < dataSource.Count; i++) {
drawItem( new Rect (rectList.x, top, rect.width, rect.height),i);
top += rect.height;
}
GUI.EndScrollView ();
}
else if (dataSource.Count> 0){
rectList = new Rect (rect.x, rect.y + rect.height, rect.width, rect.height * dataSource.Count - 1);
rectListViewGroupTop = new Rect (rectList.x, rectList.y, rectList.width, rectList.height + 1 - rect.height);
rectListViewGroupBottom = new Rect (rectList.x, rectList.y + rectListViewGroupTop.height, rectList.width, rect.height);
GUI.Box(rectListViewGroupTop, "", skin.GetStyle ( " comboxlist "));
GUI.Box(rectListViewGroupBottom, "", skin.GetStyle ( " comboxlistbottom "));
GUI.BeginGroup(rectList);
float top = 0;
for ( int i = 0; i < dataSource.Count; i++) {
drawItem( new Rect ( 0, top, rect.width, rect.height),i);
top += rect.height;
}
GUI.EndGroup();
}
}
}
/// <summary>
/// 當listItemCount為0時,動態計算可以容納的數據行數
/// </summary>
private void calculateItemCount()
{
if (listItemCount== 0){
int availableAreaHeight = ( int)(parentWinRect.height - relativeRect.y - relativeRect.height - 1);
listItemCount = availableAreaHeight/( int)relativeRect.height;
}
}
/// <summary>
/// 繪制內容項,並響應事件
/// </summary>
/// <param name="r">
/// A <see cref="Rect"/>
/// </param>
/// <param name="index">
/// A <see cref="System.Int32"/>
/// </param>
private void drawItem (Rect r, int index)
{
if (GUI.Button (r, dataSource.Values.ElementAt(index).ToString (), skin.GetStyle ( " comboxitem "))) {
currentDisplayText = dataSource.Values.ElementAt (index);
currentValue = dataSource.Keys.ElementAt (index);
if (currentIndex!=index){
currentIndex = index;
if (OnSelectItemChanged!= null){
OnSelectItemChanged( this, new SelectItemChangedArgs(currentValue,currentDisplayText));
}
}
showList = false;
}
}
void OnGUI()
{
GUI.depth = guiDepth;
this.Draw();
}
/// <summary>
/// 按時間比較各ComboBox控件的順序,初衷是為了點擊新的控件時,其它ComboBox控件下拉列表自動隱藏
/// </summary>
public class ShowListComparer : IComparer<ComboBox>
{
#region IComparer[ComboBox] implementation
int IComparer<ComboBox>.Compare (ComboBox x, ComboBox y)
{
return x.showListTime.CompareTo (y.showListTime) * - 1;
}
#endregion
}
}