Add databinding support to ScrollPanelWidget

This commit is contained in:
ScottNZ
2013-09-20 20:50:24 +12:00
parent 8b89952d59
commit 3ee1628b13

View File

@@ -11,6 +11,7 @@
using System;
using System.Drawing;
using System.Linq;
using OpenRA.FileFormats.Primitives;
using OpenRA.Graphics;
namespace OpenRA.Widgets
@@ -45,6 +46,7 @@ namespace OpenRA.Widgets
base.RemoveChildren();
}
public override void AddChild(Widget child)
{
// Initial setup of margins/height
@@ -61,7 +63,6 @@ namespace OpenRA.Widgets
public void ReplaceChild(Widget oldChild, Widget newChild)
{
oldChild.Removed();
newChild.Parent = this;
Children[Children.IndexOf(oldChild)] = newChild;
@@ -69,8 +70,6 @@ namespace OpenRA.Widgets
Scroll(0);
}
public override void DrawOuter()
{
if (!IsVisible())
@@ -85,7 +84,7 @@ namespace OpenRA.Widgets
if (thumbHeight == ScrollbarHeight)
thumbHeight = 0;
backgroundRect = new Rectangle(rb.X, rb.Y, rb.Width - ScrollbarWidth+1, rb.Height);
backgroundRect = new Rectangle(rb.X, rb.Y, rb.Width - ScrollbarWidth + 1, rb.Height);
upButtonRect = new Rectangle(rb.Right - ScrollbarWidth, rb.Y, ScrollbarWidth, ScrollbarWidth);
downButtonRect = new Rectangle(rb.Right - ScrollbarWidth, rb.Bottom - ScrollbarWidth, ScrollbarWidth, ScrollbarWidth);
scrollbarRect = new Rectangle(rb.Right - ScrollbarWidth, rb.Y + ScrollbarWidth - 1, ScrollbarWidth, ScrollbarHeight + 2);
@@ -145,6 +144,11 @@ namespace OpenRA.Widgets
ListOffset = 0;
}
public bool ScrolledToBottom
{
get { return ListOffset == Math.Min(0, Bounds.Height - ContentHeight); }
}
public void ScrollToItem(string itemKey)
{
var item = Children.FirstOrDefault(c =>
@@ -226,5 +230,116 @@ namespace OpenRA.Widgets
return UpPressed || DownPressed || ThumbPressed;
}
IObservableCollection collection;
Func<object, Widget> makeWidget;
Func<Widget, object, bool> widgetItemEquals;
bool autoScroll;
public void Unbind()
{
Bind(null, null, null, false);
}
public void Bind(IObservableCollection c, Func<object, Widget> makeWidget, Func<Widget, object, bool> widgetItemEquals, bool autoScroll)
{
this.autoScroll = autoScroll;
Game.RunAfterTick(() =>
{
if (collection != null)
{
collection.OnAdd -= BindingAdd;
collection.OnRemove -= BindingRemove;
collection.OnRemoveAt -= BindingRemoveAt;
collection.OnSet -= BindingSet;
collection.OnRefresh -= BindingRefresh;
}
this.makeWidget = makeWidget;
this.widgetItemEquals = widgetItemEquals;
RemoveChildren();
collection = c;
if (c != null)
{
foreach (var item in c.ObservedItems)
BindingAddImpl(item);
c.OnAdd += BindingAdd;
c.OnRemove += BindingRemove;
c.OnRemoveAt += BindingRemoveAt;
c.OnSet += BindingSet;
c.OnRefresh += BindingRefresh;
}
});
}
void BindingAdd(object item)
{
Game.RunAfterTick(() => BindingAddImpl(item));
}
void BindingAddImpl(object item)
{
var widget = makeWidget(item);
var scrollToBottom = autoScroll && ScrolledToBottom;
AddChild(widget);
if (scrollToBottom)
ScrollToBottom();
}
void BindingRemove(object item)
{
Game.RunAfterTick(() =>
{
var widget = Children.FirstOrDefault(w => widgetItemEquals(w, item));
if (widget != null)
RemoveChild(widget);
});
}
void BindingRemoveAt(int index)
{
Game.RunAfterTick(() =>
{
if (index < 0 || index >= Children.Count)
return;
RemoveChild(Children[index]);
});
}
void BindingSet(object oldItem, object newItem)
{
Game.RunAfterTick(() =>
{
var newWidget = makeWidget(newItem);
newWidget.Parent = this;
var i = Children.FindIndex(w => widgetItemEquals(w, oldItem));
if (i >= 0)
{
var oldWidget = Children[i];
oldWidget.Removed();
Children[i] = newWidget;
Layout.AdjustChildren();
}
else
AddChild(newWidget);
});
}
void BindingRefresh()
{
Game.RunAfterTick(() =>
{
RemoveChildren();
foreach (var item in collection.ObservedItems)
BindingAddImpl(item);
});
}
}
}