mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
Added project item commands, work on project manager, implemented project manager tests
This commit is contained in:
@ -223,7 +223,7 @@ namespace RainmeterStudio.Core.Model
|
||||
/// </summary>
|
||||
public Project()
|
||||
{
|
||||
Root = new Reference(String.Empty, Reference.ReferenceTargetKind.Project);
|
||||
Root = new Reference(String.Empty, ReferenceTargetKind.Project);
|
||||
VariableFiles = new ObservableCollection<Reference>();
|
||||
Version = new Version();
|
||||
MinimumRainmeter = new Version("3.1");
|
||||
|
@ -12,38 +12,38 @@ using RainmeterStudio.Core.Utils;
|
||||
|
||||
namespace RainmeterStudio.Core.Model
|
||||
{
|
||||
/// <summary>
|
||||
/// The kind of item the reference points to
|
||||
/// </summary>
|
||||
public enum ReferenceTargetKind
|
||||
{
|
||||
/// <summary>
|
||||
/// Invalid state
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// Reference points to a file
|
||||
/// </summary>
|
||||
File,
|
||||
|
||||
/// <summary>
|
||||
/// Reference points to a directory
|
||||
/// </summary>
|
||||
Directory,
|
||||
|
||||
/// <summary>
|
||||
/// Reference points to a project
|
||||
/// </summary>
|
||||
Project
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference to a file or folder
|
||||
/// </summary>
|
||||
[DebuggerDisplay("QualifiedName = {QualifiedName}, StoragePath = {StoragePath}")]
|
||||
public class Reference : INotifyCollectionChanged, INotifyPropertyChanged
|
||||
public class Reference : INotifyCollectionChanged, INotifyPropertyChanged, ICloneable
|
||||
{
|
||||
/// <summary>
|
||||
/// The kind of item the reference points to
|
||||
/// </summary>
|
||||
public enum ReferenceTargetKind
|
||||
{
|
||||
/// <summary>
|
||||
/// Invalid state
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// Reference points to a file
|
||||
/// </summary>
|
||||
File,
|
||||
|
||||
/// <summary>
|
||||
/// Reference points to a directory
|
||||
/// </summary>
|
||||
Directory,
|
||||
|
||||
/// <summary>
|
||||
/// Reference points to a project
|
||||
/// </summary>
|
||||
Project
|
||||
}
|
||||
|
||||
private Dictionary<string, Reference> _children;
|
||||
private Reference _parent;
|
||||
private string _name, _storagePath;
|
||||
@ -90,7 +90,10 @@ namespace RainmeterStudio.Core.Model
|
||||
|
||||
// Notify
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("Parent"));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("QualifiedName"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,7 +141,10 @@ namespace RainmeterStudio.Core.Model
|
||||
_name = value;
|
||||
|
||||
if (PropertyChanged != null)
|
||||
{
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("QualifiedName"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,7 +222,7 @@ namespace RainmeterStudio.Core.Model
|
||||
_kind = value;
|
||||
|
||||
if (PropertyChanged != null)
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("Kind"));
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("TargetKind"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -374,7 +380,7 @@ namespace RainmeterStudio.Core.Model
|
||||
|
||||
private void Parent_PropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (PropertyChanged != null && (e.PropertyName == "Parent" || e.PropertyName == "Name" || e.PropertyName == "QualifiedName"))
|
||||
if (PropertyChanged != null && e.PropertyName == "QualifiedName")
|
||||
PropertyChanged(this, new PropertyChangedEventArgs("QualifiedName"));
|
||||
}
|
||||
|
||||
@ -437,6 +443,23 @@ namespace RainmeterStudio.Core.Model
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Creates a clone of this reference
|
||||
/// </summary>
|
||||
/// <returns>The clone</returns>
|
||||
/// <remarks>The clone doesn't keep the parent.</remarks>
|
||||
public object Clone()
|
||||
{
|
||||
var cloneReference = new Reference(Name, StoragePath, TargetKind);
|
||||
|
||||
foreach (var r in Children)
|
||||
{
|
||||
cloneReference.Add((Reference)r.Clone());
|
||||
}
|
||||
|
||||
return cloneReference;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -159,4 +159,158 @@ namespace RainmeterStudio.Core.Model
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for trees
|
||||
/// </summary>
|
||||
public static class TreeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Tree traversal orders
|
||||
/// </summary>
|
||||
public enum TreeTraversalOrder
|
||||
{
|
||||
BreadthFirst,
|
||||
DepthFirst,
|
||||
DepthFirstPreOrder = DepthFirst,
|
||||
DepthFirstPostOrder
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Traverses a tree
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Tree data type</typeparam>
|
||||
/// <param name="root">Root node of tree</param>
|
||||
/// <param name="order">Traversal order</param>
|
||||
/// <returns>An enumeration of the nodes in the specified traverse order</returns>
|
||||
public static IEnumerable<Tree<T>> Traverse<T>(this Tree<T> root, TreeTraversalOrder order = TreeTraversalOrder.BreadthFirst)
|
||||
{
|
||||
if (order == TreeTraversalOrder.BreadthFirst)
|
||||
return TraverseBF(root);
|
||||
|
||||
else return TraverseDF(root, order);
|
||||
}
|
||||
|
||||
private static IEnumerable<Tree<T>> TraverseDF<T>(this Tree<T> root, TreeTraversalOrder order)
|
||||
{
|
||||
// Preorder - return root first
|
||||
if (order == TreeTraversalOrder.DepthFirstPreOrder)
|
||||
yield return root;
|
||||
|
||||
// Return children
|
||||
foreach (var child in root.Children)
|
||||
foreach (var node in TraverseDF(child, order))
|
||||
yield return node;
|
||||
|
||||
// Postorder - return root last
|
||||
if (order == TreeTraversalOrder.DepthFirstPostOrder)
|
||||
yield return root;
|
||||
}
|
||||
|
||||
private static IEnumerable<Tree<T>> TraverseBF<T>(this Tree<T> root)
|
||||
{
|
||||
// Create a queue containing the root
|
||||
Queue<Tree<T>> queue = new Queue<Tree<T>>();
|
||||
queue.Enqueue(root);
|
||||
|
||||
// While there are elements in the queue
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
// Return next node in tree
|
||||
var node = queue.Dequeue();
|
||||
yield return node;
|
||||
|
||||
// Enqueue node's children
|
||||
foreach (var child in node.Children)
|
||||
queue.Enqueue(child);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies an action to every node of the tree
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Tree data type</typeparam>
|
||||
/// <param name="root">Root node of tree</param>
|
||||
/// <param name="action">Action to apply</param>
|
||||
/// <param name="order">Traversal order</param>
|
||||
public static void Apply<T>(this Tree<T> root, Action<Tree<T>> action, TreeTraversalOrder order = TreeTraversalOrder.BreadthFirst)
|
||||
{
|
||||
// Safety check
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
// Apply action
|
||||
foreach (var node in Traverse(root, order))
|
||||
action(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies an action to every node of the tree
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Tree data type</typeparam>
|
||||
/// <param name="root">Root node of tree</param>
|
||||
/// <param name="action">Action to apply</param>
|
||||
/// <param name="order">Traversal order</param>
|
||||
public static void ApplyToData<T>(this Tree<T> root, Action<T> action, TreeTraversalOrder order = TreeTraversalOrder.BreadthFirst)
|
||||
where T : class
|
||||
{
|
||||
// Safety check
|
||||
if (action == null)
|
||||
return;
|
||||
|
||||
// Apply action
|
||||
foreach (var node in Traverse(root, order))
|
||||
action(node.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rebuilds the tree by applying the specified transform function
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Data type of tree</typeparam>
|
||||
/// <typeparam name="TResult">Data type of rebuilt tree</typeparam>
|
||||
/// <param name="root">The root node</param>
|
||||
/// <param name="transformFunction">The transform function</param>
|
||||
/// <returns>The transformed tree</returns>
|
||||
public static Tree<TResult> Transform<T, TResult>(this Tree<T> root, Func<Tree<T>, Tree<TResult>> transformFunction)
|
||||
{
|
||||
// Safety check
|
||||
if (transformFunction == null)
|
||||
throw new ArgumentNullException("Transform function cannot be null.");
|
||||
|
||||
// Build root
|
||||
Tree<TResult> resRoot = transformFunction(root);
|
||||
|
||||
// Add children
|
||||
foreach (var node in root.Children)
|
||||
resRoot.Children.Add(Transform(node, transformFunction));
|
||||
|
||||
// Return
|
||||
return resRoot;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Rebuilds the tree by applying the specified transform function
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Data type of tree</typeparam>
|
||||
/// <typeparam name="TResult">Data type of rebuilt tree</typeparam>
|
||||
/// <param name="root">The root node</param>
|
||||
/// <param name="transformFunction">The transform function</param>
|
||||
/// <returns>The transformed tree</returns>
|
||||
public static Tree<TResult> TransformData<T, TResult>(this Tree<T> root, Func<T, TResult> transformFunction)
|
||||
{
|
||||
// Safety check
|
||||
if (transformFunction == null)
|
||||
throw new ArgumentNullException("Transform function cannot be null.");
|
||||
|
||||
// Build root
|
||||
Tree<TResult> resRoot = new Tree<TResult>(transformFunction(root.Data));
|
||||
|
||||
// Add children
|
||||
foreach (var node in root.Children)
|
||||
resRoot.Children.Add(TransformData(node, transformFunction));
|
||||
|
||||
// Return
|
||||
return resRoot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user