Files
MonoGame.Extended/Source/MonoGame.Extended.Gui/GuiControlStyle.cs
T
tspayne87andDylan Wilson 61614b5ffa [GUI] Binding Context / Control Style Fixes (#443)
* Adding in changes to deal with custom control types for loading from a GuiScreen, also adding in block text if a width for the element exists.  Adding in Padding to some elements to give the developer some more options in styles.  Adding in some changes to the textbox to deal with selecting a section of text.

* Adding in a few changes to deal with propagation down the GuiControl tree, this was added to most events.  Also, adding in the idea of a form and submit button to deal with keyboard controls when inside of a form.  This gives simalar behavier to how forms work in the browser.

* Adding in the enter key skip for the textbox.

* Fixing issue where GuiSystem would call initialize twice

* Adding in a fix for Issue #428, by leveraging the propegation system to deal with hover styles.

* Adding in some changes to seperate the global binding context and have it isolated in the screen.  Also adding in code to deal with a global style binding as well.
2017-12-17 21:36:10 +10:00

109 lines
4.0 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using MonoGame.Extended.Gui.Controls;
namespace MonoGame.Extended.Gui
{
public class GuiControlStyle : IDictionary<string, object>
{
private Dictionary<Guid, Dictionary<string, object>> _previousStates = new Dictionary<Guid, Dictionary<string, object>>();
public GuiControlStyle(Type targetType)
: this(targetType.FullName, targetType)
{
}
public GuiControlStyle(string name, Type targetType)
{
Name = name;
TargetType = targetType;
_setters = new Dictionary<string, object>();
}
public string Name { get; }
public Type TargetType { get; set; }
private readonly Dictionary<string, object> _setters;
public void ApplyIf(GuiControl control, bool predicate)
{
if (predicate)
Apply(control);
else
Revert(control);
}
public void Apply(GuiControl control)
{
_previousStates[control.Id] = _setters
.ToDictionary(i => i.Key, i => TargetType.GetRuntimeProperty(i.Key)?.GetValue(control));
ChangePropertyValues(control, _setters);
}
public void Revert(GuiControl control)
{
if (_previousStates.ContainsKey(control.Id) && _previousStates[control.Id] != null)
ChangePropertyValues(control, _previousStates[control.Id]);
_previousStates[control.Id] = null;
}
private static void ChangePropertyValues(GuiControl control, Dictionary<string, object> setters)
{
var targetType = control.GetType();
foreach (var propertyName in setters.Keys)
{
var propertyInfo = targetType.GetRuntimeProperty(propertyName);
var value = setters[propertyName];
if (propertyInfo != null)
{
if(propertyInfo.CanWrite)
propertyInfo.SetValue(control, value);
// special case when we have a list of items as objects (like on a list box)
if (propertyInfo.PropertyType == typeof(List<object>))
{
var items = (List<object>)value;
var addMethod = propertyInfo.PropertyType.GetRuntimeMethod("Add", new[] { typeof(object) });
foreach (var item in items)
addMethod.Invoke(propertyInfo.GetValue(control), new[] {item});
}
}
}
}
public object this[string key]
{
get { return _setters[key]; }
set { _setters[key] = value; }
}
public ICollection<string> Keys => _setters.Keys;
public ICollection<object> Values => _setters.Values;
public int Count => _setters.Count;
public bool IsReadOnly => false;
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() => _setters.GetEnumerator();
public void Add(string key, object value) => _setters.Add(key, value);
public void Add(KeyValuePair<string, object> item) => _setters.Add(item.Key, item.Value);
public bool Remove(string key) => _setters.Remove(key);
public bool Remove(KeyValuePair<string, object> item) => _setters.Remove(item.Key);
public void Clear() => _setters.Clear();
public bool Contains(KeyValuePair<string, object> item) => _setters.Contains(item);
public bool ContainsKey(string key) => _setters.ContainsKey(key);
public bool TryGetValue(string key, out object value) => _setters.TryGetValue(key, out value);
public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
throw new NotSupportedException();
}
}
}