Commits

Spruce Weber  committed 031bf89

Implemented infrastructure for common ui elements.

  • Participants
  • Parent commits 9772078

Comments (0)

Files changed (27)

File UserProjects/sprucely/CSharp/Composer/Composer/Common/Collections/EnumerableExtensions.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Collections;
+using ReactiveUI;
+using System.Collections.ObjectModel;
+
+namespace Composer.Common.Collections
+{
+	public static class EnumerableExtensions
+	{
+		#region < Methods >
+
+		public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source)
+			where T : IHaveChildren<T>
+		{
+			return Traverse(source, x => x.Children);
+		}
+
+		public static IEnumerable<T> Traverse<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> getChildren)
+		{
+			if (null == source) throw new ArgumentNullException("source");
+			if (null == getChildren) return source;
+			return GetTraversalIterator(source, getChildren);
+		}
+
+		private static IEnumerable<T> GetTraversalIterator<T>(IEnumerable<T> source, Func<T, IEnumerable<T>> getChildren)
+		{
+			var stack = new Stack<IEnumerator<T>>();
+
+			try
+			{
+				stack.Push(source.GetEnumerator());
+				while (0 != stack.Count)
+				{
+					var iter = stack.Peek();
+					if (iter.MoveNext())
+					{
+						T current = iter.Current;
+						yield return current;
+
+						var children = getChildren(current);
+						if (null != children) stack.Push(children.GetEnumerator());
+					}
+					else
+					{
+						iter.Dispose();
+						stack.Pop();
+					}
+				}
+			}
+			finally
+			{
+				while (0 != stack.Count)
+				{
+					stack.Pop().Dispose();
+				}
+			}
+		}
+
+		public static void AddRange<T>(this ICollection<T> list, IEnumerable<T> items)
+		{
+			if (list == null) throw new ArgumentNullException("list");
+			if (items == null) throw new ArgumentNullException("items");
+
+			if (list is List<T>)
+				((List<T>)list).AddRange(items);
+			else
+				foreach (T item in items) list.Add(item);
+		}
+
+		public static void RemoveRange<T>(this ICollection<T> list, IEnumerable<T> items)
+		{
+			if (list == null) throw new ArgumentNullException("list");
+			if (items == null) throw new ArgumentNullException("items");
+
+			if (list is List<T>)
+				((List<T>)list).RemoveRange(items);
+			else
+				foreach (T item in items) list.Remove(item);
+		}
+
+		/// <summary>
+		/// Copies elements from <paramref name="source"/> to <paramref name="destination"/>, optionally
+		/// first clearing <paramref name="destionation"/>
+		/// </summary>
+		public static void CopyTo(this IEnumerable source, IList destination, bool clearDestination = false)
+		{
+			if (clearDestination)
+				destination.Clear();
+
+			foreach (var item in source.Cast<object>().ToArray())
+				destination.Add(item);
+		}
+
+		/// <summary>
+		/// Copies elements from <paramref name="source"/> to <paramref name="destination"/>, optionally
+		/// first clearing <paramref name="destionation"/>
+		/// </summary>
+		public static void CopyTo<T>(this IEnumerable<T> source, IList<T> destination, bool clearDestination = false)
+		{
+			if (clearDestination)
+				destination.Clear();
+
+			foreach (var item in source.ToArray())
+				destination.Add(item);
+		}
+
+		/// <summary>
+		/// Returns a collection that is split into one or more instances of 
+		/// <see cref="EnumerableExtensions.Chunk"/>, using a default equality comparer
+		/// </summary>
+		/// <remarks>
+		/// Chunking is similar to grouping, but only contiguous groups of matching 
+		/// elements are returned in a <see cref="Chunk"/>.
+		/// </remarks>
+		public static IEnumerable<IGrouping<TKey, TSource>> ChunkBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
+		{
+			return source.ChunkBy(keySelector, EqualityComparer<TKey>.Default);
+		}
+
+		/// <summary>
+		/// Returns a collection that is split into one or more instances of 
+		/// <see cref="EnumerableExtensions.Chunk"/>, using the specified equality comparer
+		/// </summary>
+		/// <remarks>
+		/// Chunking is similar to grouping, but only contiguous groups of matching 
+		/// elements are returned in a <see cref="Chunk"/>.
+		/// </remarks>
+		public static IEnumerable<IGrouping<TKey, TSource>> ChunkBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
+		{
+			// Flag to signal end of source sequence.
+			const bool noMoreSourceElements = true;
+
+			// Auto-generated iterator for the source array.       
+			var enumerator = source.GetEnumerator();
+
+			// Move to the first element in the source sequence.
+			if (!enumerator.MoveNext()) yield break;
+
+			// Iterate through source sequence and create a copy of each Chunk.
+			// On each pass, the iterator advances to the first element of the next "Chunk"
+			// in the source sequence. This loop corresponds to the outer foreach loop that
+			// executes the query.
+			Chunk<TKey, TSource> current = null;
+			while (true)
+			{
+				// Get the key for the current Chunk. The source iterator will churn through
+				// the source sequence until it finds an element with a key that doesn't match.
+				var key = keySelector(enumerator.Current);
+
+				// Make a new Chunk (group) object that initially has one GroupItem, which is a copy of the current source element.
+				current = new Chunk<TKey, TSource>(key, enumerator, value => comparer.Equals(key, keySelector(value)));
+
+				// Return the Chunk. A Chunk is an IGrouping<TKey,TSource>, which is the return value of the ChunkBy method.
+				// At this point the Chunk only has the first element in its source sequence. The remaining elements will be
+				// returned only when the client code foreach's over this chunk. See Chunk.GetEnumerator for more info.
+				yield return current;
+
+				// Check to see whether (a) the chunk has made a copy of all its source elements or 
+				// (b) the iterator has reached the end of the source sequence. If the caller uses an inner
+				// foreach loop to iterate the chunk items, and that loop ran to completion,
+				// then the Chunk.GetEnumerator method will already have made
+				// copies of all chunk items before we get here. If the Chunk.GetEnumerator loop did not
+				// enumerate all elements in the chunk, we need to do it here to avoid corrupting the iterator
+				// for clients that may be calling us on a separate thread.
+				if (current.CopyAllChunkElements() == noMoreSourceElements)
+				{
+					yield break;
+				}
+			}
+		}
+
+		/// <summary>
+		/// Searches through an enumerable to find the index of the first matching item using 
+		/// a default comparer
+		/// </summary>
+		public static int IndexOf<T>(this IEnumerable<T> source, T item)
+		{
+			return source.IndexOf(item, EqualityComparer<T>.Default);
+		}
+
+		/// <summary>
+		/// Searches through an enumerable to find the index of the first matching item using 
+		/// the specified comparer
+		/// </summary>
+		public static int IndexOf<T>(this IEnumerable<T> source, T item, IEqualityComparer<T> comparer)
+		{
+			int i = 0;
+			foreach (T x in source)
+			{
+				if (comparer.Equals(x, item))
+					return i;
+				i++;
+			}
+			return -1;
+		}
+
+		/// <summary>
+		/// Assigns an incrementing numerical index to corresponding items, returning a dicionary to 
+		/// map the keys to values
+		/// </summary>
+		public static Dictionary<int, T> WithIndex<T>(this IEnumerable<T> source)
+		{
+			return source.WithIndex(0.To(int.MaxValue), EqualityComparer<int>.Default);
+		}
+
+		/// <summary>
+		/// Returns a Dictionary that maps items in <paramref name="index"/> to corresponding items 
+		/// in <paramref name="source"/> a default key comparer
+		/// </summary>
+		public static Dictionary<T1, T2> WithIndex<T1, T2>(this IEnumerable<T2> source, IEnumerable<T1> index)
+		{
+			return source.WithIndex(index, EqualityComparer<T1>.Default);
+		}
+
+		/// <summary>
+		/// Returns a Dictionary that maps items in <paramref name="index"/> to corresponding items 
+		/// in <paramref name="source"/>, using the specified key comparer
+		/// </summary>
+		public static Dictionary<T1, T2> WithIndex<T1, T2>(this IEnumerable<T2> source, IEnumerable<T1> index, IEqualityComparer<T1> comparer)
+		{
+			var dictionary = new Dictionary<T1, T2>(comparer);
+			using (var source_enum = source.GetEnumerator())
+			{
+				using (var index_enum = index.GetEnumerator())
+				{
+					while (source_enum.MoveNext())
+					{
+						if (!index_enum.MoveNext())
+							throw new ArgumentException("index cannot has less length than source", "index");
+						dictionary.Add(index_enum.Current, source_enum.Current);
+					}
+				}
+			}
+			return dictionary;
+		}
+
+		/// <summary>
+		/// Returns an incrementing range of integers from <paramref name="from"/> to <paramref name="to"/>
+		/// </summary>
+		public static IEnumerable<int> To(this int from, int to)
+		{
+			for (int x = from; x <= to; x++)
+				yield return x;
+		}
+
+		/// <summary>
+		/// Returns a decrementing range of integers from <paramref name="from"/> down to <paramref name="to"/>
+		/// </summary>
+		public static IEnumerable<int> DownTo(this int from, int to)
+		{
+			for (int x = from; x >= to; x--)
+				yield return x;
+		}
+
+		/// <summary>
+		/// Returns a range of integers from <paramref name="from"/> to <paramref name="to"/> that
+		/// increments/decrements by the value <paramref name="step"/>
+		/// </summary>
+		public static IEnumerable<int> StepTo(this int from, int to, int step)
+		{
+			if (step > 0)
+			{
+				for (int x = from; x <= to; x += step)
+					yield return x;
+			}
+			else if (step < 0)
+			{
+				for (int x = from; x >= to; x += step)
+					yield return x;
+			}
+			else
+			{
+				throw new ArgumentException("Step cannot be zero.", "step");
+			}
+		}
+
+		/// <summary>
+		/// An implementation of Enumerable.Distinct() that uses a delegate to provide the values to be compared
+		/// </summary>
+		/// <remarks>
+		/// Multiple properties can be compared by using a delegate that returns an anonymous type
+		/// </remarks>
+		public static IEnumerable<TSource> Distinct<TSource, TResult>(
+			this IEnumerable<TSource> source, Func<TSource, TResult> comparer)
+		{
+			return source.Distinct(new KeyEqualityComparer<TSource, TResult>(comparer));
+		}
+
+		/// <summary>
+		/// An implementation of Enumerable.Contains() that uses a delegate to provide the values to be compared
+		/// </summary>
+		/// <remarks>
+		/// Multiple properties can be compared by using a delegate that returns an anonymous type
+		/// </remarks>
+		public static bool Contains<TSource, TResult>(
+			this IEnumerable<TSource> source, TResult value, Func<TSource, TResult> selector)
+		{
+			foreach (TSource sourceItem in source)
+			{
+				TResult sourceValue = selector(sourceItem);
+				if (sourceValue.Equals(value))
+					return true;
+			}
+			return false;
+		}
+
+		public static IEnumerable<T> AsEnumerable<T>(this T item)
+		{
+			yield return item;
+		}
+
+		public static IEnumerable<T> AsEnumerable<T>(this Func<IEnumerator<T>> getEnumerator)
+		{
+			return new EnumeratorWrapper<T>(getEnumerator);
+		}
+
+		public static IEnumerable AsEnumerable(this Func<IEnumerator> getEnumerator)
+		{
+			return new EnumeratorWrapper(getEnumerator);
+		}
+
+		/// <summary>
+		/// Applies the action to each element in the list.
+		/// </summary>
+		/// <typeparam name="T">The enumerable item's type.</typeparam>
+		/// <param name="enumerable">The elements to enumerate.</param>
+		/// <param name="action">The action to apply to each item in the list.</param>
+		public static void Apply<T>(this IEnumerable<T> enumerable, Action<T> action)
+		{
+			foreach (var item in enumerable)
+				action(item);
+		}
+
+		///// <summary>
+		///// Applies the action to each element in the list.
+		///// </summary>
+		///// <param name="enumerable">The elements to enumerate.</param>
+		///// <param name="action">The action to apply to each item in the list.</param>
+		//public static void Apply(this IEnumerable enumerable, Action<object> action)
+		//{
+		//    foreach (var item in enumerable)
+		//        action(item);
+		//}
+
+		//public static void RemoveAll<T>(this IList<T> list, Func<T, bool> predicate)
+		//{
+		//    for (int i = 0; i < list.Count; i++)
+		//    {
+		//        if (predicate(list[i]))
+		//        {
+		//            list.RemoveAt(i--);
+		//        }
+		//    }
+		//}
+
+		//public static void RemoveAll<T>(this ICollection<T> list, Func<T, bool> predicate)
+		//{
+		//    var toRemove = list.Where(predicate).ToArray();
+		//    toRemove.Apply(x => list.Remove(x));
+		//}
+
+		/// <summary>
+		/// Applies the action to each pair of elements from two lists zipped together.
+		/// </summary>
+		public static void ApplyZip<TA, TB>(this IEnumerable<TA> enumerableA, IEnumerable<TB> enumerableB, Action<TA, TB> action)
+		{
+			enumerableA.Zip(enumerableB, (a, b) =>
+			{
+				action(a, b);
+				return 0;
+			});
+		}
+
+		/// <summary>
+		/// Applies the action to each element in a list for every other element in the list.
+		/// </summary>
+		/// <typeparam name="T">The enumerable item's type.</typeparam>
+		/// <param name="enumerable">The elements to enumerate.</param>
+		/// <param name="action">The action to apply</param>
+		/// <remarks>
+		/// The number of times that <paramref name="action"/> is called is triangular to the number of elements. Ie:
+		/// n:
+		/// 1 element: 0 calls
+		/// 2 elements: 1 call
+		/// 3 elements: 3 calls
+		/// 4 elements: 6 calls
+		/// 5 elements: 10 calls
+		/// 6 elements: 15 calls...
+		/// </remarks>
+		public static void ApplyToEachOther<T>(this IEnumerable<T> enumerable, Action<T, T> action)
+		{
+			var i = 0;
+			enumerable.Apply(x =>
+			{
+				enumerable.Skip(i).Apply(y =>
+				{
+					action(x, y);
+				});
+				i += 1;
+			});
+		}
+
+		/// <summary>
+		/// Similar to String.Join, but useable on any <see cref="IEnumerable<T>"/>
+		/// </summary>
+		public static string Join<T>(this IEnumerable<T> source, string seperator)
+		{
+			return Join(source, i => i.ToString(), seperator);
+		}
+
+		/// <summary>
+		/// Similar to String.Join, but useable on any <see cref="IEnumerable<T>"/>
+		/// </summary>
+		public static string Join<T>(this IEnumerable<T> source, char seperator)
+		{
+			return Join(source, i => i.ToString(), seperator.ToString());
+		}
+
+		/// <summary>
+		/// Similar to String.Join, but useable on any <see cref="IEnumerable<T>"/>
+		/// </summary>
+		/// <param name="stringConverter">A delegate that returns a string representation of each element in <param name="source"/></param>
+		public static string Join<T>(this IEnumerable<T> source, Func<T, string> stringConverter, string seperator)
+		{
+			var builder = new StringBuilder();
+			foreach (var item in source)
+			{
+				if (builder.Length > 0)
+					builder.Append(seperator);
+
+				builder.Append(stringConverter(item));
+			}
+			return builder.ToString();
+		}
+
+		public static string ToCsv<T>(this IEnumerable<T> source)
+		{
+			return Join(source, i => i.ToString(), ",");
+		}
+
+		public static string ToCsv<T>(this IEnumerable<T> source, Func<T, string> selector)
+		{
+			return Join(source, selector, ",");
+		}
+
+		/// <summary>
+		/// Use <param name="transform"/> to convert <param name="source"/> to <see cref="IEnumerable<V>"/>
+		/// </summary>
+		public static IEnumerable<V> Convert<T, V>(this IEnumerable<T> source, Func<T, V> transform)
+		{
+			return from item in source
+				   select transform(item);
+		}
+
+
+
+		/// <summary>
+		/// Provides a simple way of making hierarchical structures easily traversable.
+		/// </summary>
+		public static IEnumerable<T> FlattenHierarchy<T>(this IEnumerable<T> nodes, Func<T, IEnumerable<T>> getChildEnumerator, bool breadthFirst = false)
+		{
+			if (breadthFirst)
+			{
+				foreach (var node in nodes)
+					yield return node;
+				foreach (var node in nodes)
+				{
+					if (!object.Equals(node, default(T)))
+					{
+						foreach (var childOrDescendent in getChildEnumerator(node).FlattenHierarchy(getChildEnumerator, breadthFirst))
+							yield return childOrDescendent;
+					}
+				}
+			}
+			else
+			{
+				foreach (var node in nodes)
+				{
+					yield return node;
+					if (!object.Equals(node, default(T)))
+					{
+						foreach (var childOrDescendent in getChildEnumerator(node).FlattenHierarchy(getChildEnumerator, breadthFirst))
+							yield return childOrDescendent;
+					}
+				}
+			}
+		}
+
+		/// <summary>
+		/// Performs a partial (topological) sort on items using a default comparer
+		/// </summary>
+		public static IEnumerable<TSource> PartialOrderBy<TSource, TKey>(
+			this IEnumerable<TSource> source,
+			Func<TSource, TKey> keySelector)
+		{
+			return PartialOrderBy(source, keySelector, null);
+		}
+
+		/// <summary>
+		/// Performs a partial (topological) sort on items using a specified comparer
+		/// </summary>
+		public static IEnumerable<TSource> PartialOrderBy<TSource, TKey>(
+			this IEnumerable<TSource> source,
+			Func<TSource, TKey> keySelector,
+			IComparer<TKey> comparer)
+		{
+			if (source == null) throw new ArgumentNullException("source");
+			if (keySelector == null) throw new ArgumentNullException("keySelector");
+			if (comparer == null) comparer = (IComparer<TKey>)Comparer<TKey>.Default;
+
+			return PartialOrderByIterator(source, keySelector, comparer);
+		}
+
+		private static IEnumerable<TSource> PartialOrderByIterator<TSource, TKey>(
+			IEnumerable<TSource> source,
+			Func<TSource, TKey> keySelector,
+			IComparer<TKey> comparer)
+		{
+			var values = source.ToArray();
+			var keys = values.Select(keySelector).ToArray();
+			int count = values.Length;
+			var notYieldedIndexes = System.Linq.Enumerable.Range(0, count).ToArray();
+			int valuesToGo = count;
+
+			while (valuesToGo > 0)
+			{
+				//Start with first value not yielded yet
+				int minIndex = notYieldedIndexes.First(i => i >= 0);
+
+				//Find minimum value amongst the values not yielded yet
+				for (int i = 0; i < count; i++)
+					if (notYieldedIndexes[i] >= 0)
+						if (comparer.Compare(keys[i], keys[minIndex]) < 0)
+						{
+							minIndex = i;
+						}
+
+				//Yield minimum value and mark it as yielded
+				yield return values[minIndex];
+				notYieldedIndexes[minIndex] = -1;
+				valuesToGo--;
+			}
+		}
+
+		#endregion < Methods >
+
+		#region < Nested Types >
+
+		// A Chunk is a contiguous group of one or more source elements that have the same key. A Chunk 
+		// has a key and a list of ChunkItem objects, which are copies of the elements in the source sequence.
+		class Chunk<TKey, TSource> : IGrouping<TKey, TSource>
+		{
+			// INVARIANT: DoneCopyingChunk == true || 
+			//   (predicate != null && predicate(enumerator.Current) && current.Value == enumerator.Current)
+
+			// A Chunk has a linked list of ChunkItems, which represent the elements in the current chunk. Each ChunkItem
+			// has a reference to the next ChunkItem in the list.
+			class ChunkItem
+			{
+				public ChunkItem(TSource value)
+				{
+					Value = value;
+				}
+				public readonly TSource Value;
+				public ChunkItem Next = null;
+			}
+			// The value that is used to determine matching elements
+			private readonly TKey key;
+
+			// Stores a reference to the enumerator for the source sequence
+			private IEnumerator<TSource> enumerator;
+
+			// A reference to the predicate that is used to compare keys.
+			private Func<TSource, bool> predicate;
+
+			// Stores the contents of the first source element that
+			// belongs with this chunk.
+			private readonly ChunkItem head;
+
+			// End of the list. It is repositioned each time a new
+			// ChunkItem is added.
+			private ChunkItem tail;
+
+			// Flag to indicate the source iterator has reached the end of the source sequence.
+			internal bool isLastSourceElement = false;
+
+			// Private object for thread syncronization
+			private object m_Lock;
+
+			// REQUIRES: enumerator != null && predicate != null
+			public Chunk(TKey key, IEnumerator<TSource> enumerator, Func<TSource, bool> predicate)
+			{
+				this.key = key;
+				this.enumerator = enumerator;
+				this.predicate = predicate;
+
+				// A Chunk always contains at least one element.
+				head = new ChunkItem(enumerator.Current);
+
+				// The end and beginning are the same until the list contains > 1 elements.
+				tail = head;
+
+				m_Lock = new object();
+			}
+
+			// Indicates that all chunk elements have been copied to the list of ChunkItems, 
+			// and the source enumerator is either at the end, or else on an element with a new key.
+			// the tail of the linked list is set to null in the CopyNextChunkElement method if the
+			// key of the next element does not match the current chunk's key, or there are no more elements in the source.
+			private bool DoneCopyingChunk { get { return tail == null; } }
+
+			// Adds one ChunkItem to the current group
+			// REQUIRES: !DoneCopyingChunk && lock(this)
+			private void CopyNextChunkElement()
+			{
+				// Try to advance the iterator on the source sequence.
+				// If MoveNext returns false we are at the end, and isLastSourceElement is set to true
+				isLastSourceElement = !enumerator.MoveNext();
+
+				// If we are (a) at the end of the source, or (b) at the end of the current chunk
+				// then null out the enumerator and predicate for reuse with the next chunk.
+				if (isLastSourceElement || !predicate(enumerator.Current))
+				{
+					enumerator = null;
+					predicate = null;
+				}
+				else
+				{
+					tail.Next = new ChunkItem(enumerator.Current);
+				}
+
+				// tail will be null if we are at the end of the chunk elements
+				// This check is made in DoneCopyingChunk.
+				tail = tail.Next;
+			}
+
+			// Called after the end of the last chunk was reached. It first checks whether
+			// there are more elements in the source sequence. If there are, it 
+			// Returns true if enumerator for this chunk was exhausted.
+			internal bool CopyAllChunkElements()
+			{
+				while (true)
+				{
+					lock (m_Lock)
+					{
+						if (DoneCopyingChunk)
+						{
+							// If isLastSourceElement is false,
+							// it signals to the outer iterator
+							// to continue iterating.
+							return isLastSourceElement;
+						}
+						else
+						{
+							CopyNextChunkElement();
+						}
+					}
+				}
+			}
+
+			public TKey Key { get { return key; } }
+
+			// Invoked by the inner foreach loop. This method stays just one step ahead
+			// of the client requests. It adds the next element of the chunk only after
+			// the clients requests the last element in the list so far.
+			public IEnumerator<TSource> GetEnumerator()
+			{
+				//Specify the initial element to enumerate.
+				ChunkItem current = head;
+
+				// There should always be at least one ChunkItem in a Chunk.
+				while (current != null)
+				{
+					// Yield the current item in the list.
+					yield return current.Value;
+
+					// Copy the next item from the source sequence, 
+					// if we are at the end of our local list.
+					lock (m_Lock)
+					{
+						if (current == tail)
+						{
+							CopyNextChunkElement();
+						}
+					}
+
+					// Move to the next ChunkItem in the list.
+					current = current.Next;
+				}
+			}
+
+			System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+			{
+				return GetEnumerator();
+			}
+		}
+
+		#endregion < Nested Types >
+	}
+}

File UserProjects/sprucely/CSharp/Composer/Composer/Common/EnumerableExtensions.cs

-namespace Composer.Common
-{
-	using System;
-	using System.Collections.Generic;
-	using System.Linq;
-	using System.Text;
-	using System.Collections;
-	using System.Collections.ObjectModel;
-
-	public static class EnumerableExtensions
-	{
-		#region < Methods >
-
-		public static void AddRange<T>(this IList<T> list, IEnumerable<T> items)
-		{
-			if (list == null) throw new ArgumentNullException("list");
-			if (items == null) throw new ArgumentNullException("items");
-
-			else if (list is List<T>)
-				((List<T>)list).AddRange(items);
-			else
-				foreach (T item in items) list.Add(item);
-		}
-
-		/// <summary>
-		/// Copies elements from <paramref name="source"/> to <paramref name="destination"/>, optionally
-		/// first clearing <paramref name="destionation"/>
-		/// </summary>
-		public static void CopyTo(this IEnumerable source, IList destination, bool clearDestination = false)
-		{
-			//Checks.NonNull(source, () => source);
-			//Checks.NonNull(destination, () => destination);
-
-			if (clearDestination)
-				destination.Clear();
-
-			foreach (var item in source.Cast<object>().ToArray())
-				destination.Add(item);
-		}
-
-		/// <summary>
-		/// Copies elements from <paramref name="source"/> to <paramref name="destination"/>, optionally
-		/// first clearing <paramref name="destionation"/>
-		/// </summary>
-		public static void CopyTo<T>(this IEnumerable<T> source, IList<T> destination, bool clearDestination = false)
-		{
-			//Checks.NonNull(source, () => source);
-			//Checks.NonNull(destination, () => destination);
-
-			if (clearDestination)
-				destination.Clear();
-
-			foreach (var item in source.ToArray())
-				destination.Add(item);
-		}
-
-		/// <summary>
-		/// Returns a collection that is split into one or more instances of 
-		/// <see cref="EnumerableExtensions.Chunk"/>, using a default equality comparer
-		/// </summary>
-		/// <remarks>
-		/// Chunking is similar to grouping, but only contiguous groups of matching 
-		/// elements are returned in a <see cref="Chunk"/>.
-		/// </remarks>
-		public static IEnumerable<IGrouping<TKey, TSource>> ChunkBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
-		{
-			return source.ChunkBy(keySelector, EqualityComparer<TKey>.Default);
-		}
-
-		/// <summary>
-		/// Returns a collection that is split into one or more instances of 
-		/// <see cref="EnumerableExtensions.Chunk"/>, using the specified equality comparer
-		/// </summary>
-		/// <remarks>
-		/// Chunking is similar to grouping, but only contiguous groups of matching 
-		/// elements are returned in a <see cref="Chunk"/>.
-		/// </remarks>
-		public static IEnumerable<IGrouping<TKey, TSource>> ChunkBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
-		{
-			// Flag to signal end of source sequence.
-			const bool noMoreSourceElements = true;
-
-			// Auto-generated iterator for the source array.       
-			var enumerator = source.GetEnumerator();
-
-			// Move to the first element in the source sequence.
-			if (!enumerator.MoveNext()) yield break;
-
-			// Iterate through source sequence and create a copy of each Chunk.
-			// On each pass, the iterator advances to the first element of the next "Chunk"
-			// in the source sequence. This loop corresponds to the outer foreach loop that
-			// executes the query.
-			Chunk<TKey, TSource> current = null;
-			while (true)
-			{
-				// Get the key for the current Chunk. The source iterator will churn through
-				// the source sequence until it finds an element with a key that doesn't match.
-				var key = keySelector(enumerator.Current);
-
-				// Make a new Chunk (group) object that initially has one GroupItem, which is a copy of the current source element.
-				current = new Chunk<TKey, TSource>(key, enumerator, value => comparer.Equals(key, keySelector(value)));
-
-				// Return the Chunk. A Chunk is an IGrouping<TKey,TSource>, which is the return value of the ChunkBy method.
-				// At this point the Chunk only has the first element in its source sequence. The remaining elements will be
-				// returned only when the client code foreach's over this chunk. See Chunk.GetEnumerator for more info.
-				yield return current;
-
-				// Check to see whether (a) the chunk has made a copy of all its source elements or 
-				// (b) the iterator has reached the end of the source sequence. If the caller uses an inner
-				// foreach loop to iterate the chunk items, and that loop ran to completion,
-				// then the Chunk.GetEnumerator method will already have made
-				// copies of all chunk items before we get here. If the Chunk.GetEnumerator loop did not
-				// enumerate all elements in the chunk, we need to do it here to avoid corrupting the iterator
-				// for clients that may be calling us on a separate thread.
-				if (current.CopyAllChunkElements() == noMoreSourceElements)
-				{
-					yield break;
-				}
-			}
-		}
-
-		/// <summary>
-		/// Searches through an enumerable to find the index of the first matching item using 
-		/// a default comparer
-		/// </summary>
-		public static int IndexOf<T>(this IEnumerable<T> source, T item)
-		{
-			return source.IndexOf(item, EqualityComparer<T>.Default);
-		}
-
-		/// <summary>
-		/// Searches through an enumerable to find the index of the first matching item using 
-		/// the specified comparer
-		/// </summary>
-		public static int IndexOf<T>(this IEnumerable<T> source, T item, IEqualityComparer<T> comparer)
-		{
-			IList<T> list = source as IList<T>;
-			if (list != null)
-				return list.IndexOf(item);
-
-			int i = 0;
-			foreach (T x in source)
-			{
-				if (comparer.Equals(x, item))
-					return i;
-			}
-			return -1;
-		}
-
-		/// <summary>
-		/// Assigns an incrementing numerical index to corresponding items, returning a dicionary to 
-		/// map the keys to values
-		/// </summary>
-		public static Dictionary<int, T> WithIndex<T>(this IEnumerable<T> source)
-		{
-			return source.WithIndex(0.To(int.MaxValue), EqualityComparer<int>.Default);
-		}
-		
-		/// <summary>
-		/// Returns a Dictionary that maps items in <paramref name="index"/> to corresponding items 
-		/// in <paramref name="source"/> a default key comparer
-		/// </summary>
-		public static Dictionary<T1, T2> WithIndex<T1, T2>(this IEnumerable<T2> source, IEnumerable<T1> index)
-		{
-			return source.WithIndex(index, EqualityComparer<T1>.Default);
-		}
-
-		/// <summary>
-		/// Returns a Dictionary that maps items in <paramref name="index"/> to corresponding items 
-		/// in <paramref name="source"/>, using the specified key comparer
-		/// </summary>
-		public static Dictionary<T1, T2> WithIndex<T1, T2>(this IEnumerable<T2> source, IEnumerable<T1> index, IEqualityComparer<T1> comparer)
-		{
-			var dictionary = new Dictionary<T1, T2>(comparer);
-			using (var source_enum = source.GetEnumerator())
-			{
-				using (var index_enum = index.GetEnumerator())
-				{
-					while (source_enum.MoveNext())
-					{
-						if (!index_enum.MoveNext())
-							throw new ArgumentException("index cannot has less length than source", "index");
-						dictionary.Add(index_enum.Current, source_enum.Current);
-					}
-				}
-			}
-			return dictionary;
-		}
-
-		/// <summary>
-		/// Returns an incrementing range of integers from <paramref name="from"/> to <paramref name="to"/>
-		/// </summary>
-		public static IEnumerable<int> To(this int from, int to)
-		{
-			for (int x = from; x <= to; x++)
-				yield return x;
-		}
-
-		/// <summary>
-		/// Returns a decrementing range of integers from <paramref name="from"/> down to <paramref name="to"/>
-		/// </summary>
-		public static IEnumerable<int> DownTo(this int from, int to)
-		{
-			for (int x = from; x >= to; x--)
-				yield return x;
-		}
-
-		/// <summary>
-		/// Returns a range of integers from <paramref name="from"/> to <paramref name="to"/> that
-		/// increments/decrements by the value <paramref name="step"/>
-		/// </summary>
-		public static IEnumerable<int> StepTo(this int from, int to, int step)
-		{
-			if (step > 0)
-			{
-				for (int x = from; x <= to; x += step)
-					yield return x;
-			}
-			else if (step < 0)
-			{
-				for (int x = from; x >= to; x += step)
-					yield return x;
-			}
-			else
-			{
-				throw new ArgumentException("Step cannot be zero.", "step");
-			}
-		}
-
-		/// <summary>
-		/// An implementation of Enumerable.Distinct() that uses a delegate to provide the values to be compared
-		/// </summary>
-		/// <remarks>
-		/// Multiple properties can be compared by using a delegate that returns an anonymous type
-		/// </remarks>
-		public static IEnumerable<TSource> Distinct<TSource, TResult>(
-			this IEnumerable<TSource> source, Func<TSource, TResult> comparer)
-		{
-			return source.Distinct(new KeyEqualityComparer<TSource, TResult>(comparer));
-		}
-
-		/// <summary>
-		/// An implementation of Enumerable.Contains() that uses a delegate to provide the values to be compared
-		/// </summary>
-		/// <remarks>
-		/// Multiple properties can be compared by using a delegate that returns an anonymous type
-		/// </remarks>
-		public static bool Contains<TSource, TResult>(
-			this IEnumerable<TSource> source, TResult value, Func<TSource, TResult> selector)
-		{
-			foreach (TSource sourceItem in source)
-			{
-				TResult sourceValue = selector(sourceItem);
-				if (sourceValue.Equals(value))
-					return true;
-			}
-			return false;
-		}
-
-		public static IEnumerable<T> AsEnumerable<T>(this T item)
-		{
-			yield return item;
-		}
-
-		public static IEnumerable<T> AsEnumerable<T>(this Func<IEnumerator<T>> getEnumerator)
-		{
-			return new EnumeratorWrapper<T>(getEnumerator);
-		}
-
-		public static IEnumerable AsEnumerable(this Func<IEnumerator> getEnumerator)
-		{
-			return new EnumeratorWrapper(getEnumerator);
-		}
-
-		/// <summary>
-		/// Applies the action to each element in the list.
-		/// </summary>
-		/// <typeparam name="T">The enumerable item's type.</typeparam>
-		/// <param name="enumerable">The elements to enumerate.</param>
-		/// <param name="action">The action to apply to each item in the list.</param>
-		public static void Apply<T>(this IEnumerable<T> enumerable, Action<T> action)
-		{
-			foreach (var item in enumerable)
-				action(item);
-		}
-
-		/// <summary>
-		/// Applies the action to each element in the list.
-		/// </summary>
-		/// <param name="enumerable">The elements to enumerate.</param>
-		/// <param name="action">The action to apply to each item in the list.</param>
-		public static void Apply(this IEnumerable enumerable, Action<object> action)
-		{
-			enumerable.Cast<object>().Apply(action);
-		}
-
-		public static void RemoveAll<T>(this IList<T> list, Func<T, bool> predicate)
-		{
-			for (int i = 0; i < list.Count; i++)
-			{
-				if (predicate(list[i]))
-				{
-					list.RemoveAt(i--);
-				}
-			}
-		}
-
-		public static void RemoveAll<T>(this ICollection<T> list, Func<T, bool> predicate)
-		{
-			var toRemove = list.Where(predicate).ToArray();
-			toRemove.Apply(x => list.Remove(x));
-		}
-
-		/// <summary>
-		/// Applies the action to each pair of elements from two lists zipped together.
-		/// </summary>
-		public static void ApplyZip<TA, TB>(this IEnumerable<TA> enumerableA, IEnumerable<TB> enumerableB, Action<TA, TB> action)
-		{
-			enumerableA.Zip(enumerableB, (a, b) =>
-				{
-					action(a, b);
-					return 0;
-				});
-		}
-
-		/// <summary>
-		/// Applies the action to each element in a list for every other element in the list.
-		/// </summary>
-		/// <typeparam name="T">The enumerable item's type.</typeparam>
-		/// <param name="enumerable">The elements to enumerate.</param>
-		/// <param name="action">The action to apply</param>
-		/// <remarks>
-		/// The number of times that <paramref name="action"/> is called is triangular to the number of elements. Ie:
-		/// n:
-		/// 1 element: 0 calls
-		/// 2 elements: 1 call
-		/// 3 elements: 3 calls
-		/// 4 elements: 6 calls
-		/// 5 elements: 10 calls
-		/// 6 elements: 15 calls...
-		/// </remarks>
-		public static void ApplyToEachOther<T>(this IEnumerable<T> enumerable, Action<T, T> action)
-		{
-			var i = 0;
-			enumerable.Apply(x =>
-				{
-					enumerable.Skip(i).Apply(y =>
-						{
-							action(x, y);
-						});
-					i += 1;
-				});
-		}
-
-
-
-		/// <summary>
-		/// Applies the action to each element in the list.
-		/// </summary>
-		/// <param name="enumerable">The elements to enumerate.</param>
-		/// <param name="action">The action to apply to each item in the list.</param>
-		public static void ApplyToEachOther(this IEnumerable enumerable, Action<object> action)
-		{
-			foreach (var item in enumerable)
-				action(item);
-		}
-
-
-		/// <summary>
-		/// Similar to String.Join, but useable on any <see cref="IEnumerable<T>"/>
-		/// </summary>
-		public static string Join<T>(this IEnumerable<T> source, string seperator)
-		{
-			return Join(source, i => i.ToString(), seperator);
-		}
-
-		/// <summary>
-		/// Similar to String.Join, but useable on any <see cref="IEnumerable<T>"/>
-		/// </summary>
-		public static string Join<T>(this IEnumerable<T> source, char seperator)
-		{
-			return Join(source, i => i.ToString(), seperator.ToString());
-		}
-
-		/// <summary>
-		/// Similar to String.Join, but useable on any <see cref="IEnumerable<T>"/>
-		/// </summary>
-		/// <param name="stringConverter">A delegate that returns a string representation of each element in <param name="source"/></param>
-		public static string Join<T>(this IEnumerable<T> source, Func<T, string> stringConverter, string seperator)
-		{
-			var builder = new StringBuilder();
-			foreach (var item in source)
-			{
-				if (builder.Length > 0)
-					builder.Append(seperator);
-
-				builder.Append(stringConverter(item));
-			}
-			return builder.ToString();
-		}
-
-		public static string ToCsv<T>(this IEnumerable<T> source)
-		{
-			return Join(source, i => i.ToString(), ",");
-		}
-
-		public static string ToCsv<T>(this IEnumerable<T> source, Func<T, string> selector)
-		{
-			return Join(source, selector, ",");
-		}
-
-		/// <summary>
-		/// Use <param name="transform"/> to convert <param name="source"/> to <see cref="IEnumerable<V>"/>
-		/// </summary>
-		public static IEnumerable<V> Convert<T, V>(this IEnumerable<T> source, Func<T, V> transform)
-		{
-			return from item in source
-				   select transform(item);
-		}
-
-
-
-		/// <summary>
-		/// Provides a simple way of making hierarchical structures easily traversable.
-		/// </summary>
-		public static IEnumerable<T> FlattenHierarchy<T>(this IEnumerable<T> nodes, Func<T, IEnumerable<T>> getChildEnumerator, bool breadthFirst = false)
-		{
-			if (breadthFirst)
-			{
-				foreach (var node in nodes)
-					yield return node;
-				foreach (var node in nodes)
-				{
-					if (!object.Equals(node, default(T)))
-					{
-						foreach (var childOrDescendent in getChildEnumerator(node).FlattenHierarchy(getChildEnumerator, breadthFirst))
-							yield return childOrDescendent;
-					}
-				}
-			}
-			else
-			{
-				foreach (var node in nodes)
-				{
-					yield return node;
-					if (!object.Equals(node, default(T)))
-					{
-						foreach (var childOrDescendent in getChildEnumerator(node).FlattenHierarchy(getChildEnumerator, breadthFirst))
-							yield return childOrDescendent;
-					}
-				}
-			}
-		}
-
-		/// <summary>
-		/// Performs a partial (topological) sort on items using a default comparer
-		/// </summary>
-		public static IEnumerable<TSource> PartialOrderBy<TSource, TKey>(
-			this IEnumerable<TSource> source,
-			Func<TSource, TKey> keySelector)
-		{
-			return PartialOrderBy(source, keySelector, null);
-		}
-
-		/// <summary>
-		/// Performs a partial (topological) sort on items using a specified comparer
-		/// </summary>
-		public static IEnumerable<TSource> PartialOrderBy<TSource, TKey>(
-			this IEnumerable<TSource> source,
-			Func<TSource, TKey> keySelector,
-			IComparer<TKey> comparer)
-		{
-			if (source == null) throw new ArgumentNullException("source");
-			if (keySelector == null) throw new ArgumentNullException("keySelector");
-			if (comparer == null) comparer = (IComparer<TKey>)Comparer<TKey>.Default;
-
-			return PartialOrderByIterator(source, keySelector, comparer);
-		}
-
-		private static IEnumerable<TSource> PartialOrderByIterator<TSource, TKey>(
-			IEnumerable<TSource> source,
-			Func<TSource, TKey> keySelector,
-			IComparer<TKey> comparer)
-		{
-			var values = source.ToArray();
-			var keys = values.Select(keySelector).ToArray();
-			int count = values.Length;
-			var notYieldedIndexes = System.Linq.Enumerable.Range(0, count).ToArray();
-			int valuesToGo = count;
-
-			while (valuesToGo > 0)
-			{
-				//Start with first value not yielded yet
-				int minIndex = notYieldedIndexes.First(i => i >= 0);
-
-				//Find minimum value amongst the values not yielded yet
-				for (int i = 0; i < count; i++)
-					if (notYieldedIndexes[i] >= 0)
-						if (comparer.Compare(keys[i], keys[minIndex]) < 0)
-						{
-							minIndex = i;
-						}
-
-				//Yield minimum value and mark it as yielded
-				yield return values[minIndex];
-				notYieldedIndexes[minIndex] = -1;
-				valuesToGo--;
-			}
-		}
-
-		#endregion < Methods >
-
-		#region < Nested Types >
-
-		// A Chunk is a contiguous group of one or more source elements that have the same key. A Chunk 
-		// has a key and a list of ChunkItem objects, which are copies of the elements in the source sequence.
-		class Chunk<TKey, TSource> : IGrouping<TKey, TSource>
-		{
-			// INVARIANT: DoneCopyingChunk == true || 
-			//   (predicate != null && predicate(enumerator.Current) && current.Value == enumerator.Current)
-
-			// A Chunk has a linked list of ChunkItems, which represent the elements in the current chunk. Each ChunkItem
-			// has a reference to the next ChunkItem in the list.
-			class ChunkItem
-			{
-				public ChunkItem(TSource value)
-				{
-					Value = value;
-				}
-				public readonly TSource Value;
-				public ChunkItem Next = null;
-			}
-			// The value that is used to determine matching elements
-			private readonly TKey key;
-
-			// Stores a reference to the enumerator for the source sequence
-			private IEnumerator<TSource> enumerator;
-
-			// A reference to the predicate that is used to compare keys.
-			private Func<TSource, bool> predicate;
-
-			// Stores the contents of the first source element that
-			// belongs with this chunk.
-			private readonly ChunkItem head;
-
-			// End of the list. It is repositioned each time a new
-			// ChunkItem is added.
-			private ChunkItem tail;
-
-			// Flag to indicate the source iterator has reached the end of the source sequence.
-			internal bool isLastSourceElement = false;
-
-			// Private object for thread syncronization
-			private object m_Lock;
-
-			// REQUIRES: enumerator != null && predicate != null
-			public Chunk(TKey key, IEnumerator<TSource> enumerator, Func<TSource, bool> predicate)
-			{
-				this.key = key;
-				this.enumerator = enumerator;
-				this.predicate = predicate;
-
-				// A Chunk always contains at least one element.
-				head = new ChunkItem(enumerator.Current);
-
-				// The end and beginning are the same until the list contains > 1 elements.
-				tail = head;
-
-				m_Lock = new object();
-			}
-
-			// Indicates that all chunk elements have been copied to the list of ChunkItems, 
-			// and the source enumerator is either at the end, or else on an element with a new key.
-			// the tail of the linked list is set to null in the CopyNextChunkElement method if the
-			// key of the next element does not match the current chunk's key, or there are no more elements in the source.
-			private bool DoneCopyingChunk { get { return tail == null; } }
-
-			// Adds one ChunkItem to the current group
-			// REQUIRES: !DoneCopyingChunk && lock(this)
-			private void CopyNextChunkElement()
-			{
-				// Try to advance the iterator on the source sequence.
-				// If MoveNext returns false we are at the end, and isLastSourceElement is set to true
-				isLastSourceElement = !enumerator.MoveNext();
-
-				// If we are (a) at the end of the source, or (b) at the end of the current chunk
-				// then null out the enumerator and predicate for reuse with the next chunk.
-				if (isLastSourceElement || !predicate(enumerator.Current))
-				{
-					enumerator = null;
-					predicate = null;
-				}
-				else
-				{
-					tail.Next = new ChunkItem(enumerator.Current);
-				}
-
-				// tail will be null if we are at the end of the chunk elements
-				// This check is made in DoneCopyingChunk.
-				tail = tail.Next;
-			}
-
-			// Called after the end of the last chunk was reached. It first checks whether
-			// there are more elements in the source sequence. If there are, it 
-			// Returns true if enumerator for this chunk was exhausted.
-			internal bool CopyAllChunkElements()
-			{
-				while (true)
-				{
-					lock (m_Lock)
-					{
-						if (DoneCopyingChunk)
-						{
-							// If isLastSourceElement is false,
-							// it signals to the outer iterator
-							// to continue iterating.
-							return isLastSourceElement;
-						}
-						else
-						{
-							CopyNextChunkElement();
-						}
-					}
-				}
-			}
-
-			public TKey Key { get { return key; } }
-
-			// Invoked by the inner foreach loop. This method stays just one step ahead
-			// of the client requests. It adds the next element of the chunk only after
-			// the clients requests the last element in the list so far.
-			public IEnumerator<TSource> GetEnumerator()
-			{
-				//Specify the initial element to enumerate.
-				ChunkItem current = head;
-
-				// There should always be at least one ChunkItem in a Chunk.
-				while (current != null)
-				{
-					// Yield the current item in the list.
-					yield return current.Value;
-
-					// Copy the next item from the source sequence, 
-					// if we are at the end of our local list.
-					lock (m_Lock)
-					{
-						if (current == tail)
-						{
-							CopyNextChunkElement();
-						}
-					}
-
-					// Move to the next ChunkItem in the list.
-					current = current.Next;
-				}
-			}
-
-			System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
-			{
-				return GetEnumerator();
-			}
-		}
-
-		#endregion < Nested Types >
-	}
-}

File UserProjects/sprucely/CSharp/Composer/Composer/Common/Interfaces.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Composer.UI.Framework;
+using ReactiveUI;
+
+namespace Composer.Common
+{
+	public interface IHaveChildren
+	{
+		IReactiveCollection Children
+		{
+			get;
+		}
+	}
+
+	public interface IHaveChildren<TChild> : IHaveChildren
+	{
+		new IReactiveCollection<TChild> Children
+		{
+			get;
+		}
+	}
+
+	public interface IHaveParent
+	{
+		object Parent
+		{
+			get;
+		}
+	}
+
+	public interface IHaveParent<TParent> : IHaveParent
+	{
+		new TParent Parent
+		{
+			get;
+		}
+	}
+
+	public interface IHaveOwner
+	{
+		object Owner
+		{
+			get;
+		}
+	}
+
+	public interface IHaveOwner<TOwner> : IHaveOwner
+	{
+		new TOwner Owner
+		{
+			get;
+		}
+	}
+
+}

File UserProjects/sprucely/CSharp/Composer/Composer/Common/TypeInfo.cs

 	using System.Collections.Generic;
 	using System.ComponentModel;
 
+	using Composer.Common.Collections;
+
 	/// <summary>
 	/// Provides "InfoOf" pattern for accessing details of class members using Linq expressions
 	/// </summary>

File UserProjects/sprucely/CSharp/Composer/Composer/Composer.csproj

       <SpecificVersion>False</SpecificVersion>
       <HintPath>..\lib\System.Reactive.Windows.Threading.dll</HintPath>
     </Reference>
+    <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Windows.Interactivity">
       <HintPath>..\lib\System.Windows.Interactivity.dll</HintPath>
     </Reference>
       <DependentUpon>App.xaml</DependentUpon>
       <SubType>Code</SubType>
     </Compile>
+    <Compile Include="Common\Collections\EnumerableExtensions.cs" />
     <Compile Include="Common\Collections\ReadOnlyDictionary.cs" />
+    <Compile Include="Common\Interfaces.cs" />
     <Compile Include="Common\TypeUtilities.cs" />
     <Compile Include="Graph\CellEffector.cs" />
     <Compile Include="Graph\EffectorMessage.cs" />
     <Compile Include="UI\Controls\RubberBandAdorner.cs" />
     <Compile Include="UI\Converters\EqualityToBooleanConverter.cs" />
     <Compile Include="UI\DispatcherHelper.cs" />
+    <Compile Include="UI\Elements\IShortcut.cs" />
+    <Compile Include="UI\Elements\Menu\MenuModel.cs" />
+    <Compile Include="UI\Elements\Tree\ITreeNodeViewModel.cs" />
+    <Compile Include="UI\Elements\Tree\ITreeViewModel.cs" />
+    <Compile Include="UI\Elements\Tree\MdiViewModelFactory.cs" />
+    <Compile Include="UI\Elements\Tree\TreeNodeViewModelBase.cs" />
+    <Compile Include="UI\Elements\Tree\TreeViewModelBase.cs" />
+    <Compile Include="UI\Interaction\Prompt\Answer.cs" />
+    <Compile Include="UI\Interaction\Prompt\IPromptResult.cs" />
+    <Compile Include="UI\Interaction\Prompt\ShowFileDialogResultBase.cs" />
+    <Compile Include="UI\Interaction\Prompt\ShowFileOpenDialogResult.cs" />
+    <Compile Include="UI\Interaction\Prompt\ShowFileSaveDialogResult.cs" />
+    <Compile Include="UI\Interaction\Prompt\ShowFolderBrowserDialogResult.cs" />
+    <Compile Include="UI\Interaction\Prompt\ShowPrintDialogResult.cs" />
+    <Compile Include="UI\Interaction\Show.cs" />
     <Compile Include="UI\ItemsControlExtensions.cs" />
     <Compile Include="UI\Screens\GraphEditor\LayoutAlgorithmFactory.cs" />
     <Compile Include="UI\Screens\GraphEditor\LayoutAlgorithm_Manual.cs" />
     <Compile Include="UI\Screens\ObjectExplorer\ObjectInfo.cs" />
     <Compile Include="UI\Utilities.cs" />
     <Compile Include="UI\Behaviors\RxDragBehavior.cs" />
-    <Compile Include="Common\EnumerableExtensions.cs" />
     <Compile Include="Common\EnumeratorWrapper.cs" />
     <Compile Include="Common\KeyEqualityComparer.cs" />
     <Compile Include="Common\TypeInfo.cs" />
     <Compile Include="UI\Framework\AssemblySource.cs" />
     <Compile Include="UI\Framework\AttachedCollection.cs" />
     <Compile Include="UI\Framework\Bind.cs" />
-    <Compile Include="UI\Framework\BindableCollection.cs" />
     <Compile Include="UI\Framework\BooleanToVisibilityConverter.cs" />
     <Compile Include="UI\Framework\Bootstrapper.cs" />
     <Compile Include="UI\Framework\Conductor.cs" />
   <ItemGroup>
     <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
   </ItemGroup>
+  <ItemGroup />
 </Project>

File UserProjects/sprucely/CSharp/Composer/Composer/Graph/Component.cs

 using QuickGraph;
 
 using Composer.Common;
+using Composer.Common.Collections;
 
 namespace Composer.Graph
 {

File UserProjects/sprucely/CSharp/Composer/Composer/IShell.cs

+using Composer.UI.Framework;
 namespace Composer
 {
-	public interface IShell { }
+	public interface IShell : IScreen, IViewAware { }
 }

File UserProjects/sprucely/CSharp/Composer/Composer/ShellView.xaml

         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:converters="clr-namespace:Composer.UI.Converters"
+        xmlns:elements="clr-namespace:Composer.UI.Elements"
         xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
         xmlns:zoom="clr-namespace:WPFExtensions.Controls;assembly=WPFExtensions">
     <Window.Resources>
 
+        <Style TargetType="MenuItem">
+            <Setter Property="Header" Value="{Binding DisplayName}" />
+            <Setter Property="Command" Value="{Binding CmdExecuteMenuItem}" />
+        </Style>
 
-
+        <HierarchicalDataTemplate DataType="{x:Type elements:MenuModel}" ItemsSource="{Binding Path=Children}" />
     </Window.Resources>
 
-    <Grid Background="#ff656565">
-        <Grid.ColumnDefinitions>
-            <ColumnDefinition Width="200" />
-            <ColumnDefinition Width="*" />
-        </Grid.ColumnDefinitions>
-        <ContentControl x:Name="ObjectExplorer" Grid.Column="0" />
-        <ContentControl x:Name="GraphEditor" Grid.Column="1" />
-    </Grid>
-
+    <DockPanel>
+        <Menu DockPanel.Dock="Top" ItemsSource="{Binding Path=Menu.Children}" />
+        <Grid Background="#ff656565">
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="200" />
+                <ColumnDefinition Width="*" />
+            </Grid.ColumnDefinitions>
+            <ContentControl x:Name="ObjectExplorer" Grid.Column="0" />
+            <ContentControl x:Name="GraphEditor" Grid.Column="1" />
+        </Grid>
+    </DockPanel>
 </Window>

File UserProjects/sprucely/CSharp/Composer/Composer/ShellViewModel.cs

 	using Composer.UI.Screens;
 	using ReactiveUI;
 	using System.Linq;
+	using ReactiveUI.Xaml;
+using Composer.UI.Elements;
+	using Composer.UI.Interaction;
+	using Composer.UI.Interaction.Prompt;
 
 	[Export(typeof(IShell))]
 	public class ShellViewModel : Screen, IShell
 	{
+		public ReactiveCommand CmdCreateComponent { get; protected set; }
+
 
 		public ShellViewModel()
 		{
+			CmdCreateComponent = new ReactiveCommand(
+				this.ObservableForProperty(x => x.CanCreateComponent, val => val));
 
+			CmdCreateComponent.Subscribe(x => CreateComponent());
+
+			this.Menu = new MenuModel(
+				new MenuModel(
+					new MenuModel 
+					{ 
+						DisplayName = "_Open",
+						Action = () => this.OpenDatabase()
+					},
+					new MenuModel 
+					{
+						DisplayName = "_New",
+						Action = () => this.NewDatabase()
+					})
+				{ DisplayName = "_File" }
+				);
+		}
+
+		private void NewDatabase()
+		{
+			Answer answer = Answer.Cancel;
+			Show.FileOpenDialog(result => answer = result.Answer)
+				.Execute();
+
+			if (answer != Answer.Ok)
+				return;
+
+
+		}
+
+		private void OpenDatabase()
+		{
+			Answer answer = Answer.Cancel;
+			Show.FileOpenDialog(result => answer = result.Answer)
+				.Execute();
+
+			if (answer != Answer.Ok)
+				return;
+		}
+
+		private object CreateComponent()
+		{
+			throw new NotImplementedException();
 		}
 
 		protected override void OnInitialize()
 		{
-			var elements = new List<Vertex>
-			{
-				new EffectorMessage(),	//0
-				new EffectorMessage(),	//1
-				new EffectorMessage(),	//2
-				new EffectorMessage(),	//3
-				new EffectorMessage(),	//4
-			};
+			//var elements = new List<Vertex>
+			//{
+			//    new EffectorMessage(),	//0
+			//    new EffectorMessage(),	//1
+			//    new EffectorMessage(),	//2
+			//    new EffectorMessage(),	//3
+			//    new EffectorMessage(),	//4
+			//};
 
-			elements.Apply(x => _graphEditor.Component.AddVertex(x));
+			//elements.Apply(x => _graphEditor.Component.AddVertex(x));
 
-			_graphEditor.Component.Connect(elements[0], elements[1]);
-			_graphEditor.Component.Connect(elements[0], elements[2]);
-			_graphEditor.Component.Connect(elements[1], elements[3]);
-			_graphEditor.Component.Connect(elements[3], elements[4]);
-			_graphEditor.Component.Connect(elements[2], elements[4]);
-			_graphEditor.Component.Connect(elements[4], elements[0]);
+			//_graphEditor.Component.Connect(elements[0], elements[1]);
+			//_graphEditor.Component.Connect(elements[0], elements[2]);
+			//_graphEditor.Component.Connect(elements[1], elements[3]);
+			//_graphEditor.Component.Connect(elements[3], elements[4]);
+			//_graphEditor.Component.Connect(elements[2], elements[4]);
+			//_graphEditor.Component.Connect(elements[4], elements[0]);
+		}
+
+		private MenuModel _menu;
+		public MenuModel Menu
+		{
+			get { return _menu; }
+			set { this.RaiseAndSetIfChanged(x => x.Menu, ref _menu, value); }