mirror of
https://github.com/AlexMacocian/MonoGame.Extended.git
synced 2026-07-24 12:06:37 +00:00
171 lines
6.0 KiB
C#
171 lines
6.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
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 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 = GetContentRectangle(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, Rectangle? clippingRectangle)
|
|
{
|
|
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, HorizontalAlignment.Left, VerticalAlignment.Top, clippingRectangle);
|
|
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 = GetContentRectangle(context);
|
|
var selectedItemRectangle = GetItemRectangle(context, SelectedIndex - FirstIndex, contentRectangle);
|
|
|
|
if (selectedItemRectangle.Bottom > ClippingRectangle.Bottom)
|
|
FirstIndex++;
|
|
|
|
if (selectedItemRectangle.Top < ClippingRectangle.Top && FirstIndex > 0)
|
|
FirstIndex--;
|
|
}
|
|
|
|
protected Size2 GetItemSize(IGuiContext context, object item)
|
|
{
|
|
var text = GetItemName(item);
|
|
var font = Font ?? context.DefaultFont;
|
|
var textSize = font.MeasureString(text ?? string.Empty);
|
|
var itemWidth = textSize.Width + ItemPadding.Size.Width;
|
|
var itemHeight = textSize.Height + ItemPadding.Size.Height;
|
|
return new Size2(itemWidth, itemHeight);
|
|
}
|
|
|
|
protected abstract Rectangle GetContentRectangle(IGuiContext context);
|
|
|
|
protected void DrawItemList(IGuiContext context, IGuiRenderer renderer)
|
|
{
|
|
var contentRectangle = GetContentRectangle(context);
|
|
|
|
for (var i = FirstIndex; i < Items.Count; i++)
|
|
{
|
|
var item = Items[i];
|
|
var itemRectangle = GetItemRectangle(context, i - FirstIndex, contentRectangle);
|
|
var itemTextInfo = GetItemTextInfo(context, itemRectangle, item, contentRectangle);
|
|
var textColor = i == SelectedIndex ? SelectedTextColor : itemTextInfo.Color;
|
|
|
|
if (SelectedIndex == i)
|
|
renderer.FillRectangle(itemRectangle, SelectedItemColor, contentRectangle);
|
|
|
|
renderer.DrawText(itemTextInfo.Font, itemTextInfo.Text, itemTextInfo.Position + TextOffset, textColor,
|
|
itemTextInfo.ClippingRectangle);
|
|
}
|
|
}
|
|
}
|
|
} |