1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using MonoGame.Extended.Input.InputListeners;
namespace MonoGame.Extended.Gui.Controls
{
public abstract class SelectorControl : Control
{
protected SelectorControl()
{
}
private int _selectedIndex = -1;
public virtual int SelectedIndex
{
get { return _selectedIndex; }
set
{
if (_selectedIndex != value)
{
_selectedIndex = value;
SelectedIndexChanged?.Invoke(this, EventArgs.Empty);
}
}
}
public override IEnumerable<Control> Children => Items.OfType<Control>();
public virtual List<object> Items { get; } = new List<object>();
public virtual Color SelectedTextColor { get; set; } = Color.White;
public virtual Color SelectedItemColor { get; set; } = Color.CornflowerBlue;
public virtual Thickness ItemPadding { get; set; } = new Thickness(4, 2);
public virtual string NameProperty { get; set; }
public event EventHandler SelectedIndexChanged;
protected int FirstIndex;
public object SelectedItem
{
get { return SelectedIndex >= 0 && SelectedIndex <= Items.Count - 1 ? Items[SelectedIndex] : null; }
set { SelectedIndex = Items.IndexOf(value); }
}
public override bool OnKeyPressed(IGuiContext context, KeyboardEventArgs args)
{
if (args.Key == Keys.Down) ScrollDown();
if (args.Key == Keys.Up) ScrollUp();
return base.OnKeyPressed(context, args);
}
public override void OnScrolled(int delta)
{
base.OnScrolled(delta);
if (delta < 0) ScrollDown();
if (delta > 0) ScrollUp();
}
private void ScrollDown()
{
if (SelectedIndex < Items.Count - 1)
SelectedIndex++;
}
private void ScrollUp()
{
if (SelectedIndex > 0)
SelectedIndex--;
}
public override bool OnPointerDown(IGuiContext context, PointerEventArgs args)
{
var contentRectangle = GetListAreaRectangle(context);
for (var i = FirstIndex; i < Items.Count; i++)
{
var itemRectangle = GetItemRectangle(context, i - FirstIndex, contentRectangle);
if (itemRectangle.Contains(args.Position))
{
SelectedIndex = i;
OnItemClicked(context, args);
break;
}
}
return base.OnPointerDown(context, args);
}
protected virtual void OnItemClicked(IGuiContext context, PointerEventArgs args) { }
protected TextInfo GetItemTextInfo(IGuiContext context, Rectangle itemRectangle, object item)
{
var textRectangle = new Rectangle(itemRectangle.X + ItemPadding.Left, itemRectangle.Y + ItemPadding.Top,
itemRectangle.Width - ItemPadding.Right, itemRectangle.Height - ItemPadding.Bottom);
var itemTextInfo = GetTextInfo(context, GetItemName(item), textRectangle, HorizontalTextAlignment, VerticalTextAlignment);
return itemTextInfo;
}
private string GetItemName(object item)
{
if (item != null)
{
if (NameProperty != null)
{
return item.GetType()
.GetRuntimeProperty(NameProperty)
.GetValue(item)
?.ToString() ?? string.Empty;
}
return item.ToString();
}
return string.Empty;
}
protected Rectangle GetItemRectangle(IGuiContext context, int index, Rectangle contentRectangle)
{
var font = Font ?? context.DefaultFont;
var itemHeight = font.LineHeight + ItemPadding.Top + ItemPadding.Bottom;
return new Rectangle(contentRectangle.X, contentRectangle.Y + itemHeight * index, contentRectangle.Width, itemHeight);
}
protected void ScrollIntoView(IGuiContext context)
{
var contentRectangle = GetListAreaRectangle(context);
var selectedItemRectangle = GetItemRectangle(context, SelectedIndex - FirstIndex, contentRectangle);
if (selectedItemRectangle.Bottom > ClippingRectangle.Bottom)
FirstIndex++;
if (selectedItemRectangle.Top < ClippingRectangle.Top && FirstIndex > 0)
FirstIndex--;
}
protected Size GetItemSize(IGuiContext context, object item)
{
var text = GetItemName(item);
var font = Font ?? context.DefaultFont;
var textSize = (Size)font.MeasureString(text ?? string.Empty);
var itemWidth = textSize.Width + ItemPadding.Width;
var itemHeight = textSize.Height + ItemPadding.Height;
return new Size(itemWidth, itemHeight);
}
protected abstract Rectangle GetListAreaRectangle(IGuiContext context);
protected void DrawItemList(IGuiContext context, IGuiRenderer renderer)
{
var listRectangle = GetListAreaRectangle(context);
for (var i = FirstIndex; i < Items.Count; i++)
{
var item = Items[i];
var itemRectangle = GetItemRectangle(context, i - FirstIndex, listRectangle);
var itemTextInfo = GetItemTextInfo(context, itemRectangle, item);
var textColor = i == SelectedIndex ? SelectedTextColor : itemTextInfo.Color;
if (SelectedIndex == i)
renderer.FillRectangle(itemRectangle, SelectedItemColor, listRectangle);
renderer.DrawText(itemTextInfo.Font, itemTextInfo.Text, itemTextInfo.Position + TextOffset, textColor, itemTextInfo.ClippingRectangle);
}
}
}
}
|