Files
MonoGame.Extended/Source/MonoGame.Extended.Gui/Controls/GuiItemsControl.cs
T
Dylan WilsonandGitHub b3a631aff5 Gui dialogs (#410)
* started refactoring for gui windows

* a bit more work on gui windows

* fixed some bugs and broken build stuff

* fixed some bugs in gui controls

* a little code cleanup

* got gui dialogs positioning and experimenting with named styles by type

* apply control styles directly in the constructor of controls

* got everything compiling again

* all gui controls have skinnable constructors

* rework uniform grid desired size calculations

* turns out gui layouts are complicated

* include pdb files in nuget packages

* fixed a bug in find nearest glyph

* custom control styling

* added a range constructor overload that takes one value

* rethinking control desired size behaviour

* made particle emitters more editable at runtime

* moved the auto trigger code to the particle effect instead of the emitters

* tweaks

* changed the particle modifer interface to an abstract base with an optional name

* changed the particle modifer interface to an abstract base with an optional name

* an attempt at creating a gui combo box

* rolled back the nested control experiment

* pretty good (but not perfect) combo boxes

* tweaks

* name property bindings on lists

* removed and cleaned up the hacks from the gui combo box

* minor combo box styling tweaks

* minor bug fix in gui combo box

* experiments with data binding

* fixed a mistake on the texture region service interface

* working on the ability to serialize particles

* finished particle serialization

* more robust range deserialization

* added editor browable attributes

* fixed some broken demos

* made the particle modifiers editable at runtime

* fixed some issues with particle serialization

* fixed some issues with interpolators
2017-07-22 21:22:13 +10:00

177 lines
6.2 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 GuiItemsControl : GuiControl
{
protected GuiItemsControl()
: this(null)
{
}
protected GuiItemsControl(GuiSkin skin)
: base(skin)
{
}
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 void OnKeyPressed(IGuiContext context, KeyboardEventArgs args)
{
base.OnKeyPressed(context, args);
if (args.Key == Keys.Down) ScrollDown();
if (args.Key == Keys.Up) ScrollUp();
}
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 void OnPointerDown(IGuiContext context, GuiPointerEventArgs args)
{
base.OnPointerDown(context, 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;
}
}
}
protected virtual void OnItemClicked(IGuiContext context, GuiPointerEventArgs 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, Size2 availableSize, object item)
{
var text = GetItemName(item);
var textInfo = GetTextInfo(context, text, new Rectangle(0, 0, (int)availableSize.Width, (int)availableSize.Height), HorizontalAlignment.Left, VerticalAlignment.Top);
var itemWidth = textInfo.Size.X + ItemPadding.Size.Height;
var itemHeight = textInfo.Size.Y + ItemPadding.Size.Width;
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);
}
}
}
}