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