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
}
}