using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
namespace SLCommandingDemo.Commanding
{
///
/// Maintains a mapping between ICommand and ButtonBase
/// objects, for the ButtonBaseExtensions class.
///
internal class CommandToButtonsMap
{
#region Fields
///
/// Maps ICommand objects to lists of ButtonBase objects. Stores the object references
/// as WeakReferences, so that the commands and buttons can be garbage collected as necessary.
///
readonly Dictionary> _map = new Dictionary>();
#endregion // Fields
#region Internal Methods
internal void AddButtonToMap(ButtonBase btn, ICommand cmd)
{
if (!ContainsCommand(cmd))
_map.Add(new WeakReference(cmd), new List());
List weakRefs = GetButtonsFromCommand(cmd);
weakRefs.Add(new WeakReference(btn));
}
internal bool ContainsCommand(ICommand cmd)
{
return GetButtonsFromCommand(cmd) != null;
}
internal void ForEachButton(ICommand cmd, Action callback)
{
List buttonRefs = GetButtonsFromCommand(cmd);
for (int i = buttonRefs.Count - 1; i > -1; --i)
{
WeakReference weakRef = buttonRefs[i];
ButtonBase btn = weakRef.Target as ButtonBase;
if (btn != null)
callback(btn);
}
}
internal void RemoveButtonFromMap(ButtonBase btn, ICommand cmd)
{
List buttonRefs = this.GetButtonsFromCommand(cmd);
if (buttonRefs == null)
return;
for (int i = buttonRefs.Count - 1; i > -1; --i)
{
WeakReference weakRef = buttonRefs[i];
if (weakRef.Target == btn)
{
buttonRefs.RemoveAt(i);
break;
}
}
}
#endregion // Internal Methods
#region Private Helpers
List GetButtonsFromCommand(ICommand cmd)
{
this.Prune();
return _map.FirstOrDefault(entry => entry.Key.Target == cmd).Value;
}
void Prune()
{
List cmds = _map.Keys.ToList();
for (int cmdIndex = cmds.Count - 1; cmdIndex > -1; --cmdIndex)
{
WeakReference cmdRef = cmds[cmdIndex];
if (!cmdRef.IsAlive)
{
_map.Remove(cmdRef);
}
else
{
List btns = _map[cmdRef];
for (int btnIndex = btns.Count - 1; btnIndex > -1; --btnIndex)
{
WeakReference btnRef = btns[btnIndex];
if (!btnRef.IsAlive)
btns.RemoveAt(btnIndex);
}
}
}
}
#endregion // Private Helpers
}
}