|
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
// RightToCopy & PublishAndPerish: OrlandoCurioso 2006
namespace OC.Windows.Forms
{
// Provides navigational history (go back/forward) in conjunction with 2 ToolStripSplitButtons
public class History<T>
{
#region Events & Delegates
// Occurs when user chose from menu or clicked button
public event EventHandler<HistoryEventArgs<T>> GotoItem;
// Represents the method which retrieves the menu text for an item.
// If delegate is null, item's ToString method is used.
public delegate string GetHistoryMenuText(T item);
// Represents the method which retrieves the menu image for an item.
// If delegate is null, none is used.
public delegate Image GetHistoryMenuImage(T item);
#endregion
// forward button may be null
// limitList == 0 for unlimited history
public History(ToolStripSplitButton back, ToolStripSplitButton forward, uint limitList)
{
list = new LinkedList<T>();
cms = new ToolStripDropDownMenu();
cms.Opening += new CancelEventHandler(cms_Opening);
cms.Closed += new ToolStripDropDownClosedEventHandler(cms_Closed);
cms.ItemClicked += new ToolStripItemClickedEventHandler(cms_ItemClicked);
cms.RightToLeft = RightToLeft.No; // if buttons are mirrored
ensureOpeningOfMenu();
tssbBack = back;
tssbForward = forward;
assignButton(back);
assignButton(forward);
limit = (int)limitList;
}
#region Fields
private T _CurrentItem;
private LinkedList<T> list;
private LinkedListNode<T> current;
private ToolStripDropDownMenu cms;
private ToolStripSplitButton tssbBack;
private ToolStripSplitButton tssbForward;
private bool _AllowDuplicates;
private bool inProc;
private int limit;
private GetHistoryMenuText _GetMenuText;
private GetHistoryMenuImage _GetMenuImage;
#endregion
#region Public Interface
public void Clear()
{
_CurrentItem = default(T);
current = null;
list.Clear();
ensureOpeningOfMenu();
enableButtons();
}
public bool AllowDuplicates
{
get { return _AllowDuplicates; }
set { _AllowDuplicates = value; }
}
public GetHistoryMenuText MenuTexts
{
//get { return _GetMenuText; }
set { _GetMenuText = value; }
}
public GetHistoryMenuImage MenuImages
{
//get { return _GetMenuImage; }
set { _GetMenuImage = value; }
}
public T CurrentItem
{
get { return _CurrentItem; }
set
{
_CurrentItem = value;
if (!inProc && _CurrentItem != null)
{
addCurrentItem(value);
}
}
}
#endregion
#region Private Interface
private void addCurrentItem( T item)
{
if (!_AllowDuplicates && list.Contains(item))
{
list.Remove(item);
}
list.AddFirst(item);
current = list.First;
limitList();
enableButtons();
}
private void tssb_ButtonClick(object sender, EventArgs e)
{
LinkedListNode<T> node = sender.Equals(tssbBack) ? current.Next : current.Previous;
OnGotoItem(node);
current = node;
limitList();
enableButtons();
}
private void cms_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
LinkedListNode<T> node = (LinkedListNode<T>)e.ClickedItem.Tag;
OnGotoItem(node);
current = node;
limitList();
enableButtons();
}
// dynamic filling of menu
private void cms_Opening(object sender, CancelEventArgs e)
{
Debug.Assert(list.Count != 0 && current != null);
cms.Items.Clear();
ToolStripItem tssb = ((ToolStripDropDownMenu)sender).OwnerItem;
bool isBackMenu = tssb.Equals(tssbBack);
LinkedListNode<T> node = isBackMenu ? current.Next : current.Previous;
while (node != null)
{
ToolStripMenuItem tsmi = new ToolStripMenuItem();
tsmi.Tag = node;
if (_GetMenuText != null)
tsmi.Text = _GetMenuText(node.Value);
else
tsmi.Text = node.Value.ToString();
if (_GetMenuImage != null)
tsmi.Image = _GetMenuImage(node.Value);
cms.Items.Add(tsmi);
node = isBackMenu ? node.Next : node.Previous;
}
}
private void cms_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
ensureOpeningOfMenu();
}
private void ensureOpeningOfMenu()
{
cms.Items.Clear();
cms.Items.Add("dummy");
}
// limiting Back history is sufficient (by design Forward is less or equal to Back)
private void limitList()
{
if (limit != 0 && list.Count > limit)
{
LinkedListNode<T> node = current.Next;
int count = 0;
while (node != null)
{
if (++count > limit)
{
list.RemoveLast();
}
node = node.Next;
}
}
}
private void assignButton(ToolStripSplitButton tssb)
{
if (tssb != null)
{
tssb.ButtonClick += new EventHandler(tssb_ButtonClick);
tssb.DropDown = cms;
tssb.Enabled = false;
}
}
private void enableButtons()
{
if (tssbBack != null)
tssbBack.Enabled = (current != null && current.Next != null);
if (tssbForward != null)
tssbForward.Enabled = (current != null && current.Previous != null);
}
private void OnGotoItem(LinkedListNode<T> node)
{
Debug.Assert(node != null && node.Value != null);
T item = node.Value;
// block client setting CurrentItem
inProc = true;
if (GotoItem != null)
{
GotoItem(this, new HistoryEventArgs<T>(item));
}
inProc = false;
}
#endregion
}
// Provides data for the History<T>.GotoItem event
public class HistoryEventArgs<T> : EventArgs
{
public HistoryEventArgs(T item) : base()
{
_Item = item;
}
private T _Item;
public T Item { get { return _Item; } }
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.