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>
 | 
					        /// </summary>
 | 
				
			||||||
        public Project()
 | 
					        public Project()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Root = new Reference(String.Empty, Reference.ReferenceTargetKind.Project);
 | 
					            Root = new Reference(String.Empty, ReferenceTargetKind.Project);
 | 
				
			||||||
            VariableFiles = new ObservableCollection<Reference>();
 | 
					            VariableFiles = new ObservableCollection<Reference>();
 | 
				
			||||||
            Version = new Version();
 | 
					            Version = new Version();
 | 
				
			||||||
            MinimumRainmeter = new Version("3.1");
 | 
					            MinimumRainmeter = new Version("3.1");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,38 +12,38 @@ using RainmeterStudio.Core.Utils;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace RainmeterStudio.Core.Model
 | 
					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>
 | 
					    /// <summary>
 | 
				
			||||||
    /// Reference to a file or folder
 | 
					    /// Reference to a file or folder
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    [DebuggerDisplay("QualifiedName = {QualifiedName}, StoragePath = {StoragePath}")]
 | 
					    [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 Dictionary<string, Reference> _children;
 | 
				
			||||||
        private Reference _parent;
 | 
					        private Reference _parent;
 | 
				
			||||||
        private string _name, _storagePath;
 | 
					        private string _name, _storagePath;
 | 
				
			||||||
@@ -90,7 +90,10 @@ namespace RainmeterStudio.Core.Model
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                // Notify
 | 
					                // Notify
 | 
				
			||||||
                if (PropertyChanged != null)
 | 
					                if (PropertyChanged != null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
                    PropertyChanged(this, new PropertyChangedEventArgs("Parent"));
 | 
					                    PropertyChanged(this, new PropertyChangedEventArgs("Parent"));
 | 
				
			||||||
 | 
					                    PropertyChanged(this, new PropertyChangedEventArgs("QualifiedName"));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -138,7 +141,10 @@ namespace RainmeterStudio.Core.Model
 | 
				
			|||||||
                _name = value;
 | 
					                _name = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (PropertyChanged != null)
 | 
					                if (PropertyChanged != null)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
                    PropertyChanged(this, new PropertyChangedEventArgs("Name"));
 | 
					                    PropertyChanged(this, new PropertyChangedEventArgs("Name"));
 | 
				
			||||||
 | 
					                    PropertyChanged(this, new PropertyChangedEventArgs("QualifiedName"));
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -216,7 +222,7 @@ namespace RainmeterStudio.Core.Model
 | 
				
			|||||||
                _kind = value;
 | 
					                _kind = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (PropertyChanged != null)
 | 
					                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)
 | 
					        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"));
 | 
					                PropertyChanged(this, new PropertyChangedEventArgs("QualifiedName"));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -437,6 +443,23 @@ namespace RainmeterStudio.Core.Model
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #endregion
 | 
					        #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>
 | 
					    /// <summary>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -159,4 +159,158 @@ namespace RainmeterStudio.Core.Model
 | 
				
			|||||||
            throw new NotImplementedException();
 | 
					            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;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -71,7 +71,6 @@
 | 
				
			|||||||
    <Compile Include="Utils\LinqExtension.cs" />
 | 
					    <Compile Include="Utils\LinqExtension.cs" />
 | 
				
			||||||
    <Compile Include="Utils\BitmapHelper.cs" />
 | 
					    <Compile Include="Utils\BitmapHelper.cs" />
 | 
				
			||||||
    <Compile Include="Utils\PathHelper.cs" />
 | 
					    <Compile Include="Utils\PathHelper.cs" />
 | 
				
			||||||
    <Compile Include="Utils\TreeExtensions.cs" />
 | 
					 | 
				
			||||||
    <Compile Include="Utils\Version.cs" />
 | 
					    <Compile Include="Utils\Version.cs" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 | 
					  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,11 +17,13 @@ namespace RainmeterStudio.Core.Utils
 | 
				
			|||||||
        public static Reference GetFolderTree(string folder)
 | 
					        public static Reference GetFolderTree(string folder)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Build tree object
 | 
					            // Build tree object
 | 
				
			||||||
            Reference refTree = new Reference(Path.GetFileName(folder), folder);
 | 
					            Reference refTree = new Reference(Path.GetFileName(folder), folder, ReferenceTargetKind.File);
 | 
				
			||||||
            
 | 
					            
 | 
				
			||||||
            // Navigate folder structure
 | 
					            // Navigate folder structure
 | 
				
			||||||
            if (Directory.Exists(folder))
 | 
					            if (Directory.Exists(folder))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
					                refTree.TargetKind = ReferenceTargetKind.Directory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                foreach (var item in Directory.EnumerateDirectories(folder)
 | 
					                foreach (var item in Directory.EnumerateDirectories(folder)
 | 
				
			||||||
                    .Concat(Directory.EnumerateFiles(folder)))
 | 
					                    .Concat(Directory.EnumerateFiles(folder)))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@@ -46,5 +48,33 @@ namespace RainmeterStudio.Core.Utils
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            return String.Equals(path1, path2, StringComparison.InvariantCultureIgnoreCase);
 | 
					            return String.Equals(path1, path2, StringComparison.InvariantCultureIgnoreCase);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Copies a directory from source to destination
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="source">Directory to copy</param>
 | 
				
			||||||
 | 
					        /// <param name="destination">Destination directory</param>
 | 
				
			||||||
 | 
					        /// <param name="merge"></param>
 | 
				
			||||||
 | 
					        /// <remarks>If destination exists, the contents of 'source' will be copied to destination.
 | 
				
			||||||
 | 
					        /// Else, destination will be created, and the contents of source will be copied to destination.</remarks>
 | 
				
			||||||
 | 
					        public static void CopyDirectory(string source, string destination, bool merge = false)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (source == destination)
 | 
				
			||||||
 | 
					                throw new IOException("You cannot copy a folder in the same folder.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (Directory.Exists(destination) && !merge)
 | 
				
			||||||
 | 
					                throw new IOException("Destination folder already exists.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            foreach (var file in Directory.EnumerateFiles(source, "*", SearchOption.AllDirectories))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                string newFile = file.StartsWith(source) ? Path.Combine(destination, file.Substring(source.Length).Trim('\\')) : file;
 | 
				
			||||||
 | 
					                string newDirectory = Path.GetDirectoryName(newFile);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (!String.IsNullOrEmpty(newDirectory) && !Directory.Exists(newDirectory))
 | 
				
			||||||
 | 
					                    Directory.CreateDirectory(newDirectory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                File.Copy(file, newFile);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,162 +0,0 @@
 | 
				
			|||||||
using System;
 | 
					 | 
				
			||||||
using System.Collections.Generic;
 | 
					 | 
				
			||||||
using System.Linq;
 | 
					 | 
				
			||||||
using System.Text;
 | 
					 | 
				
			||||||
using RainmeterStudio.Core.Model;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
namespace RainmeterStudio.Core.Utils
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /// <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;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										22
									
								
								RainmeterStudio.Tests/Business/DocumentManagerTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								RainmeterStudio.Tests/Business/DocumentManagerTest.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
				
			||||||
 | 
					using RainmeterStudio.Business;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace RainmeterStudio.Tests.Business
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [TestClass]
 | 
				
			||||||
 | 
					    public class DocumentManagerTest
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        DocumentManager documentManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestInitialize]
 | 
				
			||||||
 | 
					        public void Initialize()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            documentManager = new DocumentManager();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										553
									
								
								RainmeterStudio.Tests/Business/ProjectManagerClipboardTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										553
									
								
								RainmeterStudio.Tests/Business/ProjectManagerClipboardTest.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,553 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
				
			||||||
 | 
					using RainmeterStudio.Core.Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace RainmeterStudio.Tests.Business
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Tests the project item operations for the project manager
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    /// <remarks>
 | 
				
			||||||
 | 
					    /// Initial project structure:
 | 
				
			||||||
 | 
					    ///   root
 | 
				
			||||||
 | 
					    ///   +  folder1
 | 
				
			||||||
 | 
					    ///   |  +  sub1
 | 
				
			||||||
 | 
					    ///   |  |  +  file2.png
 | 
				
			||||||
 | 
					    ///   |  |  +  file3.txt
 | 
				
			||||||
 | 
					    ///   |  +  file1.txt
 | 
				
			||||||
 | 
					    ///   +  folder2
 | 
				
			||||||
 | 
					    ///   +  file1.txt
 | 
				
			||||||
 | 
					    ///   +  sub1
 | 
				
			||||||
 | 
					    /// </remarks>
 | 
				
			||||||
 | 
					    [TestClass]
 | 
				
			||||||
 | 
					    public class ProjectManagerProjectItemOperationsTest : ProjectManagerTestBase
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private Reference Root
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return ProjectManager.ActiveProject.Root;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Sets up test
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public override void OnInitialize()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Create a new project
 | 
				
			||||||
 | 
					            string projectName = "test";
 | 
				
			||||||
 | 
					            string projectPath = projectName + ".rsproj";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ProjectManager.CreateProject(projectName, projectPath, ProjectTemplate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Create a project structure
 | 
				
			||||||
 | 
					            var root = ProjectManager.ActiveProject.Root;
 | 
				
			||||||
 | 
					            ProjectManager.CreateFolder("folder1", root);
 | 
				
			||||||
 | 
					            ProjectManager.CreateFolder("folder2", root);
 | 
				
			||||||
 | 
					            ProjectManager.CreateFolder("sub1", root.Children[0]);
 | 
				
			||||||
 | 
					            ProjectManager.CreateFolder("sub1", root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            File.Create("file1.txt").Close();
 | 
				
			||||||
 | 
					            File.Create("folder1\\file1.txt").Close();
 | 
				
			||||||
 | 
					            File.Create("folder1\\sub1\\file2.png").Close();
 | 
				
			||||||
 | 
					            File.Create("folder1\\sub1\\file3.txt").Close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            root.Add(new Reference("file1.txt", "file1.txt"));
 | 
				
			||||||
 | 
					            root.Children[0].Add(new Reference("file1.txt", "folder1\\file1.txt"));
 | 
				
			||||||
 | 
					            root.Children[0].Children[0].Add(new Reference("file2.png", "folder1\\sub1\\file2.png"));
 | 
				
			||||||
 | 
					            root.Children[0].Children[0].Add(new Reference("file3.txt", "folder1\\sub1\\file3.txt"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Cut & paste for files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCutPasteFileTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            var folder2 = Root.GetReference("test/folder2");
 | 
				
			||||||
 | 
					            var file1 = Root.GetReference("test/folder1/file1.txt");
 | 
				
			||||||
 | 
					            var file2 = Root.GetReference("test/folder1/sub1/file2.png");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(0, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Cut
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCutClipboard(file1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(0, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in folder 2
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemPasteClipboard(folder2);
 | 
				
			||||||
 | 
					            Assert.IsFalse(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder2, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Cut and paste in root
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCutClipboard(file2);
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemPasteClipboard(Root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Assert.AreEqual(Root, file2.Parent);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCutPasteFileNameConflictTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            var file1 = Root.GetReference("test/folder1/file1.txt");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Cut
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCutClipboard(file1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in root
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ProjectManager.ProjectItemPasteClipboard(Root);
 | 
				
			||||||
 | 
					                Assert.Fail("File should already exist, should not overwrite.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (IOException)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Item shouldn't be in clipboard any more, but state should remain the same
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCutPasteFileSameDirectoryTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            var file1 = Root.GetReference("test/folder1/file1.txt");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Cut
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCutClipboard(file1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in root
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemPasteClipboard(folder1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Item shouldn't be in clipboard any more, but state should remain the same
 | 
				
			||||||
 | 
					            Assert.IsFalse(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Cut & paste for directories
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCutPasteDirectoryTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            var folder2 = Root.GetReference("test/folder2");
 | 
				
			||||||
 | 
					            var sub1 = Root.GetReference("test/folder1/sub1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(0, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder1/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder1\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Cut
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCutClipboard(sub1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(0, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in folder 2
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemPasteClipboard(folder2);
 | 
				
			||||||
 | 
					            Assert.IsFalse(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder2, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder2/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder2\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCutPasteDirectoryNameConflictTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            var sub1 = Root.GetReference("test/folder1/sub1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder1/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder1\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Cut
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCutClipboard(sub1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in root
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ProjectManager.ProjectItemPasteClipboard(Root);
 | 
				
			||||||
 | 
					                Assert.Fail("Directory already exists, should not overwrite.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (IOException)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Object remains in clipboard, state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder1/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder1\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCutPasteDirectorySameDirectoryTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            var sub1 = Root.GetReference("test/folder1/sub1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder1/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder1\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Cut
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCutClipboard(sub1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in folder 2
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ProjectManager.ProjectItemPasteClipboard(folder1);
 | 
				
			||||||
 | 
					                Assert.Fail("Directory is same.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (IOException)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder1/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder1\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Copy & paste for files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCopyPasteFileTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            var folder2 = Root.GetReference("test/folder2");
 | 
				
			||||||
 | 
					            var file1 = Root.GetReference("test/folder1/file1.txt");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(0, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Copy
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCopyClipboard(file1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(0, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in folder 2
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemPasteClipboard(folder2);
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCopyPasteFileNameConflictTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Reference folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            Reference file1 = Root.GetReference("test/folder1/file1.txt");
 | 
				
			||||||
 | 
					            Reference copy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Copy
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCopyClipboard(file1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in root
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemPasteClipboard(Root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(5, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					            Assert.IsTrue(Root.TryGetReference("test/file1_2.txt", out copy));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste again in root
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemPasteClipboard(Root);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(6, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					            Assert.IsTrue(Root.TryGetReference("test/file1_3.txt", out copy));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCopyPasteFileSameDirectoryTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            var file1 = Root.GetReference("test/folder1/file1.txt");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Copy
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCopyClipboard(file1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in root
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemPasteClipboard(folder1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(3, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					            Assert.IsTrue(Root.TryGetReference("test/folder1/file1_2.txt", out file1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Past again in root
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemPasteClipboard(folder1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, file1.Parent);
 | 
				
			||||||
 | 
					            Assert.IsTrue(Root.TryGetReference("test/folder1/file1_3.txt", out file1));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Copy & paste for directories
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCopyPasteDirectoryTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            var folder2 = Root.GetReference("test/folder2");
 | 
				
			||||||
 | 
					            var sub1 = Root.GetReference("test/folder1/sub1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(0, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder1/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder1\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Copy
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCopyClipboard(sub1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(0, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in folder 2
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemPasteClipboard(folder2);
 | 
				
			||||||
 | 
					            Reference sub2;
 | 
				
			||||||
 | 
					            Assert.IsTrue(Root.TryGetReference("test/folder2/sub1", out sub2));
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, folder2.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub2.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub2.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder2, sub2.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder1/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder1\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder2/sub1/file2.png", sub2.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder2\\sub1\\file2.png", sub2.Children[0].StoragePath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCopyPasteDirectoryNameConflictTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            var sub1 = Root.GetReference("test/folder1/sub1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder1/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder1\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Copy
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCopyClipboard(sub1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in root
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ProjectManager.ProjectItemPasteClipboard(Root);
 | 
				
			||||||
 | 
					                Assert.Fail("Directory already exists, should not overwrite.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (IOException)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Object remains in clipboard, state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(4, Root.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder1/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder1\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCopyPasteDirectorySameDirectoryTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var folder1 = Root.GetReference("test/folder1");
 | 
				
			||||||
 | 
					            var sub1 = Root.GetReference("test/folder1/sub1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial state
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder1/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder1\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Copy
 | 
				
			||||||
 | 
					            ProjectManager.ProjectItemCopyClipboard(sub1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // The item should be in the clipboard, but state unchanged
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Paste in folder 2
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ProjectManager.ProjectItemPasteClipboard(folder1);
 | 
				
			||||||
 | 
					                Assert.Fail("Directory is same.");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (IOException)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Assert.IsTrue(ProjectManager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, folder1.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, sub1.Count);
 | 
				
			||||||
 | 
					            Assert.IsFalse(sub1.Children.Any(x => !File.Exists(x.StoragePath)));
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, sub1.Parent);
 | 
				
			||||||
 | 
					            Assert.AreEqual("test/folder1/sub1/file2.png", sub1.Children[0].QualifiedName);
 | 
				
			||||||
 | 
					            Assert.AreEqual("folder1\\sub1\\file2.png", sub1.Children[0].StoragePath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										79
									
								
								RainmeterStudio.Tests/Business/ProjectManagerTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								RainmeterStudio.Tests/Business/ProjectManagerTest.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,79 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
				
			||||||
 | 
					using RainmeterStudio.Business;
 | 
				
			||||||
 | 
					using RainmeterStudio.Core.Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace RainmeterStudio.Tests.Business
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    [TestClass]
 | 
				
			||||||
 | 
					    public class ProjectManagerTest : ProjectManagerTestBase
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Tests if the sample template is registered
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerTemplatesTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, ProjectManager.ProjectTemplates.Count());
 | 
				
			||||||
 | 
					            Assert.AreEqual(ProjectTemplate, ProjectManager.ProjectTemplates.First());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Tests the project create functionality
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerCreateProjectTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            bool loaded = false;
 | 
				
			||||||
 | 
					            string projName = "test";
 | 
				
			||||||
 | 
					            string projPath = TestContext.TestName + ".rsproj";
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            ProjectManager.ActiveProjectChanged += new EventHandler((sender, e) => loaded = true);
 | 
				
			||||||
 | 
					            ProjectManager.CreateProject(projName, projPath, ProjectTemplate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Assert.IsTrue(loaded);
 | 
				
			||||||
 | 
					            Assert.AreEqual(projName, ProjectManager.ActiveProject.Name);
 | 
				
			||||||
 | 
					            Assert.AreEqual(projPath, ProjectManager.ActiveProject.Path);
 | 
				
			||||||
 | 
					            Assert.IsTrue(File.Exists(projPath));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Tests the open project functionality
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ProjectManagerOpenProjectTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Create a new project
 | 
				
			||||||
 | 
					            bool changed = false;
 | 
				
			||||||
 | 
					            string projName = "test";
 | 
				
			||||||
 | 
					            string projPath = TestContext.TestName + ".rsproj";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ProjectManager.ActiveProjectChanged += new EventHandler((sender, e) => changed = true);
 | 
				
			||||||
 | 
					            ProjectManager.CreateProject(projName, projPath, ProjectTemplate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Reopen new project
 | 
				
			||||||
 | 
					            changed = false;
 | 
				
			||||||
 | 
					            ProjectManager.OpenProject(projPath);
 | 
				
			||||||
 | 
					            Assert.IsTrue(changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Close project
 | 
				
			||||||
 | 
					            changed = false;
 | 
				
			||||||
 | 
					            ProjectManager.Close();
 | 
				
			||||||
 | 
					            Assert.IsTrue(changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Open a copy
 | 
				
			||||||
 | 
					            changed = false;
 | 
				
			||||||
 | 
					            Directory.CreateDirectory("projectDir");
 | 
				
			||||||
 | 
					            string proj2Path = Path.Combine("projectDir", TestContext.TestName + "2.rsproj");
 | 
				
			||||||
 | 
					            File.Copy(projPath, proj2Path);
 | 
				
			||||||
 | 
					            ProjectManager.OpenProject(proj2Path);
 | 
				
			||||||
 | 
					            Assert.AreEqual(proj2Path, ProjectManager.ActiveProject.Path);
 | 
				
			||||||
 | 
					            Assert.AreEqual(projName, ProjectManager.ActiveProject.Name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										84
									
								
								RainmeterStudio.Tests/Business/ProjectManagerTestBase.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								RainmeterStudio.Tests/Business/ProjectManagerTestBase.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
				
			||||||
 | 
					using RainmeterStudio.Business;
 | 
				
			||||||
 | 
					using RainmeterStudio.Core.Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace RainmeterStudio.Tests.Business
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Common stuff for project manager tests
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public class ProjectManagerTestBase
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        #region Project template
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// A sample project template
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        protected class TestTemplate : IProjectTemplate
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public string Name
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                get { return "TestTemplate"; }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public IEnumerable<Property> Properties
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                get { return Enumerable.Empty<Property>(); }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            public Project CreateProject()
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return new Project();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets or sets the text context
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public TestContext TestContext { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets or sets the project manager
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        protected virtual ProjectManager ProjectManager { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets or sets the sample project template
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        protected virtual IProjectTemplate ProjectTemplate { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Sets up the test
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        [TestInitialize]
 | 
				
			||||||
 | 
					        public void Initialize()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            string testDirectory = Path.Combine(TestContext.DeploymentDirectory, TestContext.TestName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Directory.CreateDirectory(testDirectory);
 | 
				
			||||||
 | 
					            Directory.SetCurrentDirectory(testDirectory);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Set up project manager
 | 
				
			||||||
 | 
					            ProjectManager = new ProjectManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Set up project template
 | 
				
			||||||
 | 
					            ProjectTemplate = new TestTemplate();
 | 
				
			||||||
 | 
					            ProjectManager.RegisterProjectTemplate(ProjectTemplate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            OnInitialize();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public virtual void OnInitialize()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,5 +1,7 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Collections.Specialized;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using System.Threading.Tasks;
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
@@ -14,14 +16,22 @@ namespace RainmeterStudio.Tests.Model
 | 
				
			|||||||
    [TestClass]
 | 
					    [TestClass]
 | 
				
			||||||
    public class ReferenceTest
 | 
					    public class ReferenceTest
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					        public TestContext TestContext { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [TestInitialize]
 | 
				
			||||||
 | 
					        public void Initialize()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Directory.SetCurrentDirectory(TestContext.DeploymentDirectory);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Tests the constructors of the reference class
 | 
					        /// Tests the constructors of the reference class
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        [TestMethod]
 | 
					        [TestMethod]
 | 
				
			||||||
        public void ReferenceConstructorTest()
 | 
					        public void ReferenceConstructorTest()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Reference root = new Reference("root", "D:\\Data\\Project", Reference.ReferenceTargetKind.Directory);
 | 
					            Reference root = new Reference("root", "D:\\Data\\Project", ReferenceTargetKind.Directory);
 | 
				
			||||||
            Reference file = new Reference("f ile__asdf.txt", Reference.ReferenceTargetKind.File);
 | 
					            Reference file = new Reference("f ile__asdf.txt", ReferenceTargetKind.File);
 | 
				
			||||||
                        
 | 
					                        
 | 
				
			||||||
            // Test root
 | 
					            // Test root
 | 
				
			||||||
            Assert.AreEqual("root", root.Name);
 | 
					            Assert.AreEqual("root", root.Name);
 | 
				
			||||||
@@ -29,13 +39,15 @@ namespace RainmeterStudio.Tests.Model
 | 
				
			|||||||
            Assert.AreEqual("root", root.QualifiedName);
 | 
					            Assert.AreEqual("root", root.QualifiedName);
 | 
				
			||||||
            Assert.AreEqual("D:\\Data\\Project", root.StoragePath);
 | 
					            Assert.AreEqual("D:\\Data\\Project", root.StoragePath);
 | 
				
			||||||
            Assert.IsTrue(Enumerable.Repeat("root", 1).SequenceEqual(root.QualifiedParts));
 | 
					            Assert.IsTrue(Enumerable.Repeat("root", 1).SequenceEqual(root.QualifiedParts));
 | 
				
			||||||
            
 | 
					            Assert.AreEqual(ReferenceTargetKind.Directory, root.TargetKind);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Test file
 | 
					            // Test file
 | 
				
			||||||
            Assert.AreEqual("f ile__asdf.txt", file.Name);
 | 
					            Assert.AreEqual("f ile__asdf.txt", file.Name);
 | 
				
			||||||
            Assert.IsNull(file.Parent);
 | 
					            Assert.IsNull(file.Parent);
 | 
				
			||||||
            Assert.AreEqual("f ile__asdf.txt", file.QualifiedName);
 | 
					            Assert.AreEqual("f ile__asdf.txt", file.QualifiedName);
 | 
				
			||||||
            Assert.IsNull(file.StoragePath);
 | 
					            Assert.IsNull(file.StoragePath);
 | 
				
			||||||
            Assert.IsTrue(Enumerable.Repeat("f ile__asdf.txt", 1).SequenceEqual(file.QualifiedParts));
 | 
					            Assert.IsTrue(Enumerable.Repeat("f ile__asdf.txt", 1).SequenceEqual(file.QualifiedParts));
 | 
				
			||||||
 | 
					            Assert.AreEqual(ReferenceTargetKind.File, file.TargetKind);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
@@ -45,11 +57,11 @@ namespace RainmeterStudio.Tests.Model
 | 
				
			|||||||
        public void ReferenceParentingTest()
 | 
					        public void ReferenceParentingTest()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Reference root = new Reference(String.Empty, "D:\\Data\\Project");
 | 
					            Reference root = new Reference(String.Empty, "D:\\Data\\Project");
 | 
				
			||||||
            Reference folder1 = new Reference("folder1", Reference.ReferenceTargetKind.Directory);
 | 
					            Reference folder1 = new Reference("folder1", ReferenceTargetKind.Directory);
 | 
				
			||||||
            Reference folder2 = new Reference("folder 2", Reference.ReferenceTargetKind.Directory);
 | 
					            Reference folder2 = new Reference("folder 2", ReferenceTargetKind.Directory);
 | 
				
			||||||
            Reference file1 = new Reference("file1", Reference.ReferenceTargetKind.File);
 | 
					            Reference file1 = new Reference("file1", ReferenceTargetKind.File);
 | 
				
			||||||
            Reference file2 = new Reference("file2.txt", Reference.ReferenceTargetKind.File);
 | 
					            Reference file2 = new Reference("file2.txt", ReferenceTargetKind.File);
 | 
				
			||||||
            Reference file3 = new Reference("file 3.png", Reference.ReferenceTargetKind.File);
 | 
					            Reference file3 = new Reference("file 3.png", ReferenceTargetKind.File);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            root.Add(folder1);
 | 
					            root.Add(folder1);
 | 
				
			||||||
            root.Add(file3);
 | 
					            root.Add(file3);
 | 
				
			||||||
@@ -87,11 +99,11 @@ namespace RainmeterStudio.Tests.Model
 | 
				
			|||||||
        public void ReferenceQualifiedNameTest()
 | 
					        public void ReferenceQualifiedNameTest()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Reference root = new Reference(String.Empty, "D:\\Data\\Project");
 | 
					            Reference root = new Reference(String.Empty, "D:\\Data\\Project");
 | 
				
			||||||
            Reference folder1 = new Reference("folder1", Reference.ReferenceTargetKind.Directory);
 | 
					            Reference folder1 = new Reference("folder1", ReferenceTargetKind.Directory);
 | 
				
			||||||
            Reference folder2 = new Reference("folder 2", Reference.ReferenceTargetKind.Directory);
 | 
					            Reference folder2 = new Reference("folder 2", ReferenceTargetKind.Directory);
 | 
				
			||||||
            Reference file1 = new Reference("file1", Reference.ReferenceTargetKind.File);
 | 
					            Reference file1 = new Reference("file1", ReferenceTargetKind.File);
 | 
				
			||||||
            Reference file2 = new Reference("file2.txt", Reference.ReferenceTargetKind.File);
 | 
					            Reference file2 = new Reference("file2.txt", ReferenceTargetKind.File);
 | 
				
			||||||
            Reference file3 = new Reference("file 3.png", Reference.ReferenceTargetKind.File);
 | 
					            Reference file3 = new Reference("file 3.png", ReferenceTargetKind.File);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            root.Add(folder1);
 | 
					            root.Add(folder1);
 | 
				
			||||||
            root.Add(file3);
 | 
					            root.Add(file3);
 | 
				
			||||||
@@ -134,11 +146,12 @@ namespace RainmeterStudio.Tests.Model
 | 
				
			|||||||
        public void ReferenceGetReferenceTest()
 | 
					        public void ReferenceGetReferenceTest()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Reference root = new Reference(String.Empty, "D:\\Data\\Project");
 | 
					            Reference root = new Reference(String.Empty, "D:\\Data\\Project");
 | 
				
			||||||
            Reference folder1 = new Reference("folder1", Reference.ReferenceTargetKind.Directory);
 | 
					            Reference folder1 = new Reference("folder1", ReferenceTargetKind.Directory);
 | 
				
			||||||
            Reference folder2 = new Reference("folder 2", Reference.ReferenceTargetKind.Directory);
 | 
					            Reference folder2 = new Reference("folder 2", ReferenceTargetKind.Directory);
 | 
				
			||||||
            Reference file1 = new Reference("file1", Reference.ReferenceTargetKind.File);
 | 
					            Reference file1 = new Reference("file1", ReferenceTargetKind.File);
 | 
				
			||||||
            Reference file2 = new Reference("file2.txt", Reference.ReferenceTargetKind.File);
 | 
					            Reference file2 = new Reference("file2.txt", ReferenceTargetKind.File);
 | 
				
			||||||
            Reference file3 = new Reference("file 3.png", Reference.ReferenceTargetKind.File);
 | 
					            Reference file3 = new Reference("file 3.png", ReferenceTargetKind.File);
 | 
				
			||||||
 | 
					            Reference notInTree = new Reference("file4.txt", ReferenceTargetKind.File);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            root.Add(folder1);
 | 
					            root.Add(folder1);
 | 
				
			||||||
            root.Add(file3);
 | 
					            root.Add(file3);
 | 
				
			||||||
@@ -179,6 +192,150 @@ namespace RainmeterStudio.Tests.Model
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            Assert.IsTrue(file3.TryGetReference("/folder1/folder 2/file2.txt", out res));
 | 
					            Assert.IsTrue(file3.TryGetReference("/folder1/folder 2/file2.txt", out res));
 | 
				
			||||||
            Assert.AreEqual(file2, res);
 | 
					            Assert.AreEqual(file2, res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Assert.IsFalse(root.TryGetReference("/file 3.png/some nonexistant file", out res));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Test 'tree contains' method
 | 
				
			||||||
 | 
					            Assert.IsTrue(file2.TreeContains(root));
 | 
				
			||||||
 | 
					            Assert.IsTrue(root.TreeContains(file3));
 | 
				
			||||||
 | 
					            Assert.IsFalse(root.TreeContains(notInTree));
 | 
				
			||||||
 | 
					            Assert.IsFalse(notInTree.TreeContains(root));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Tests the collection notify behavior
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ReferenceCollectionChangedTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            NotifyCollectionChangedEventArgs args = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initialize
 | 
				
			||||||
 | 
					            Reference root = new Reference(String.Empty, "D:\\Data\\Project");
 | 
				
			||||||
 | 
					            Reference folder1 = new Reference("folder1", ReferenceTargetKind.Directory);
 | 
				
			||||||
 | 
					            Reference file1 = new Reference("file1.txt", ReferenceTargetKind.File);
 | 
				
			||||||
 | 
					            Reference file2 = new Reference("file2.txt", ReferenceTargetKind.File);
 | 
				
			||||||
 | 
					            Reference file3 = new Reference("file3.txt", ReferenceTargetKind.File);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            root.CollectionChanged += new NotifyCollectionChangedEventHandler((sender, e) => args = e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Add item
 | 
				
			||||||
 | 
					            args = null;
 | 
				
			||||||
 | 
					            root.Add(folder1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Assert.IsNotNull(args);
 | 
				
			||||||
 | 
					            Assert.AreEqual(NotifyCollectionChangedAction.Add, args.Action);
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, args.NewItems.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(folder1, args.NewItems[0]);
 | 
				
			||||||
 | 
					            Assert.IsNull(args.OldItems);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            args = null;
 | 
				
			||||||
 | 
					            folder1.Add(file1);
 | 
				
			||||||
 | 
					            Assert.IsNull(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            args = null;
 | 
				
			||||||
 | 
					            root.Add(file2);
 | 
				
			||||||
 | 
					            root.Add(file3);
 | 
				
			||||||
 | 
					            Assert.IsNotNull(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Remove
 | 
				
			||||||
 | 
					            args = null;
 | 
				
			||||||
 | 
					            root.Remove(file3);
 | 
				
			||||||
 | 
					            Assert.IsNotNull(root);
 | 
				
			||||||
 | 
					            Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action);
 | 
				
			||||||
 | 
					            Assert.IsNull(args.NewItems);
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, args.OldItems.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(file3, args.OldItems[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Unparent
 | 
				
			||||||
 | 
					            args = null;
 | 
				
			||||||
 | 
					            file2.Unparent();
 | 
				
			||||||
 | 
					            Assert.IsNotNull(args);
 | 
				
			||||||
 | 
					            Assert.AreEqual(NotifyCollectionChangedAction.Remove, args.Action);
 | 
				
			||||||
 | 
					            Assert.IsNull(args.NewItems);
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, args.OldItems.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual(file2, args.OldItems[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Clear
 | 
				
			||||||
 | 
					            args = null;
 | 
				
			||||||
 | 
					            root.Clear();
 | 
				
			||||||
 | 
					            Assert.IsNotNull(args);
 | 
				
			||||||
 | 
					            Assert.AreEqual(NotifyCollectionChangedAction.Reset, args.Action);
 | 
				
			||||||
 | 
					            Assert.IsNull(args.NewItems);
 | 
				
			||||||
 | 
					            Assert.IsNull(args.OldItems);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Tests the property notify behavior
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ReferencePropertyChangedTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            List<string> propNames = new List<string>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initialize
 | 
				
			||||||
 | 
					            Reference root = new Reference("Project", "D:\\Data\\Project", ReferenceTargetKind.Project);
 | 
				
			||||||
 | 
					            Reference folder1 = new Reference("folder1", ReferenceTargetKind.Directory);
 | 
				
			||||||
 | 
					            Reference file1 = new Reference("file1.txt", ReferenceTargetKind.File);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            file1.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler((sender, e) => propNames.Add(e.PropertyName));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Parent
 | 
				
			||||||
 | 
					            propNames.Clear();
 | 
				
			||||||
 | 
					            folder1.Add(file1);
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, propNames.Count);
 | 
				
			||||||
 | 
					            Assert.IsTrue(propNames.Contains("Parent"));
 | 
				
			||||||
 | 
					            Assert.IsTrue(propNames.Contains("QualifiedName"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Storage path
 | 
				
			||||||
 | 
					            propNames.Clear();
 | 
				
			||||||
 | 
					            file1.StoragePath = "D:\\Data\\Project\\folder1\\file1.txt";
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, propNames.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual("StoragePath", propNames[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Target kind
 | 
				
			||||||
 | 
					            propNames.Clear();
 | 
				
			||||||
 | 
					            file1.TargetKind = ReferenceTargetKind.None;
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, propNames.Count);
 | 
				
			||||||
 | 
					            Assert.AreEqual("TargetKind", propNames[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Name
 | 
				
			||||||
 | 
					            propNames.Clear();
 | 
				
			||||||
 | 
					            file1.Name = "file10.txt";
 | 
				
			||||||
 | 
					            Assert.AreEqual(2, propNames.Count);
 | 
				
			||||||
 | 
					            Assert.IsTrue(propNames.Contains("Name"));
 | 
				
			||||||
 | 
					            Assert.IsTrue(propNames.Contains("QualifiedName"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Qualified name propagation
 | 
				
			||||||
 | 
					            propNames.Clear();
 | 
				
			||||||
 | 
					            root.Add(folder1);
 | 
				
			||||||
 | 
					            Assert.AreEqual(1, propNames.Count);
 | 
				
			||||||
 | 
					            Assert.IsTrue(propNames.Contains("QualifiedName"));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Tests the automatic detection of target kinds
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        [TestMethod]
 | 
				
			||||||
 | 
					        public void ReferenceTargetKindTest()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Create some files and folders
 | 
				
			||||||
 | 
					            Directory.CreateDirectory("folder1");
 | 
				
			||||||
 | 
					            File.Create("file1.txt").Close();
 | 
				
			||||||
 | 
					            File.Create("file2.rsproj").Close();
 | 
				
			||||||
 | 
					            File.Create("folder1/file3").Close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Reference folder1 = new Reference("folder1", "folder1");
 | 
				
			||||||
 | 
					            Reference file1 = new Reference("file1.txt", "file1.txt");
 | 
				
			||||||
 | 
					            Reference file2 = new Reference("file2.rsproj", "file2.rsproj");
 | 
				
			||||||
 | 
					            Reference file3 = new Reference("file3", "folder1/file3");
 | 
				
			||||||
 | 
					            Reference file4 = new Reference("file4", "file4.txt");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Assert.AreEqual(ReferenceTargetKind.Directory, folder1.TargetKind);
 | 
				
			||||||
 | 
					            Assert.AreEqual(ReferenceTargetKind.File, file1.TargetKind);
 | 
				
			||||||
 | 
					            Assert.AreEqual(ReferenceTargetKind.Project, file2.TargetKind);
 | 
				
			||||||
 | 
					            Assert.AreEqual(ReferenceTargetKind.File, file3.TargetKind);
 | 
				
			||||||
 | 
					            Assert.AreEqual(ReferenceTargetKind.None, file4.TargetKind);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -57,6 +57,10 @@
 | 
				
			|||||||
    </Otherwise>
 | 
					    </Otherwise>
 | 
				
			||||||
  </Choose>
 | 
					  </Choose>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <Compile Include="Business\DocumentManagerTest.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Business\ProjectManagerClipboardTest.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Business\ProjectManagerTest.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Business\ProjectManagerTestBase.cs" />
 | 
				
			||||||
    <Compile Include="Model\ReferenceTest.cs" />
 | 
					    <Compile Include="Model\ReferenceTest.cs" />
 | 
				
			||||||
    <Compile Include="Storage\ProjectStorageTest.cs" />
 | 
					    <Compile Include="Storage\ProjectStorageTest.cs" />
 | 
				
			||||||
    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
					    <Compile Include="Properties\AssemblyInfo.cs" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,6 +3,7 @@ using System.Linq;
 | 
				
			|||||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
					using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
				
			||||||
using RainmeterStudio.Core.Model;
 | 
					using RainmeterStudio.Core.Model;
 | 
				
			||||||
using RainmeterStudio.Editor.ProjectEditor;
 | 
					using RainmeterStudio.Editor.ProjectEditor;
 | 
				
			||||||
 | 
					using RainmeterStudio.Storage;
 | 
				
			||||||
using Version = RainmeterStudio.Core.Utils.Version;
 | 
					using Version = RainmeterStudio.Core.Utils.Version;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace RainmeterStudio.Tests.Storage
 | 
					namespace RainmeterStudio.Tests.Storage
 | 
				
			||||||
@@ -13,8 +14,6 @@ namespace RainmeterStudio.Tests.Storage
 | 
				
			|||||||
    [TestClass]
 | 
					    [TestClass]
 | 
				
			||||||
    public class ProjectStorageTest
 | 
					    public class ProjectStorageTest
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private ProjectStorage ProjectStorage = new ProjectStorage();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public TestContext TestContext { get; set; }
 | 
					        public TestContext TestContext { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        [TestInitialize]
 | 
					        [TestInitialize]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,9 +3,14 @@ using System.Collections.Generic;
 | 
				
			|||||||
using System.IO;
 | 
					using System.IO;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Text.RegularExpressions;
 | 
				
			||||||
 | 
					using System.Windows;
 | 
				
			||||||
 | 
					using System.Xml.Serialization;
 | 
				
			||||||
using RainmeterStudio.Core.Model;
 | 
					using RainmeterStudio.Core.Model;
 | 
				
			||||||
using RainmeterStudio.Core.Storage;
 | 
					using RainmeterStudio.Core.Storage;
 | 
				
			||||||
 | 
					using RainmeterStudio.Core.Utils;
 | 
				
			||||||
using RainmeterStudio.Editor.ProjectEditor;
 | 
					using RainmeterStudio.Editor.ProjectEditor;
 | 
				
			||||||
 | 
					using RainmeterStudio.Storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace RainmeterStudio.Business
 | 
					namespace RainmeterStudio.Business
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -20,11 +25,6 @@ namespace RainmeterStudio.Business
 | 
				
			|||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public Project ActiveProject { get; protected set; }
 | 
					        public Project ActiveProject { get; protected set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// Gets or sets the project storage
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        protected ProjectStorage Storage { get; set; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        #endregion
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #region Events
 | 
					        #region Events
 | 
				
			||||||
@@ -42,9 +42,8 @@ namespace RainmeterStudio.Business
 | 
				
			|||||||
        /// Initializes the project manager
 | 
					        /// Initializes the project manager
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="storage">Project storage</param>
 | 
					        /// <param name="storage">Project storage</param>
 | 
				
			||||||
        public ProjectManager(ProjectStorage storage)
 | 
					        public ProjectManager()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Storage = storage;
 | 
					 | 
				
			||||||
            ActiveProject = null;
 | 
					            ActiveProject = null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -69,7 +68,10 @@ namespace RainmeterStudio.Business
 | 
				
			|||||||
            ActiveProject.Path = path;
 | 
					            ActiveProject.Path = path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Save to file
 | 
					            // Save to file
 | 
				
			||||||
            Directory.CreateDirectory(Path.GetDirectoryName(path));
 | 
					            string directory = Path.GetDirectoryName(path);
 | 
				
			||||||
 | 
					            if (!String.IsNullOrEmpty(directory))
 | 
				
			||||||
 | 
					                Directory.CreateDirectory(Path.GetDirectoryName(path));
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            SaveActiveProject();
 | 
					            SaveActiveProject();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Raise event
 | 
					            // Raise event
 | 
				
			||||||
@@ -81,14 +83,14 @@ namespace RainmeterStudio.Business
 | 
				
			|||||||
        /// Opens a project from disk
 | 
					        /// Opens a project from disk
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        /// <param name="path"></param>
 | 
					        /// <param name="path"></param>
 | 
				
			||||||
        public void OpenProject(string path) 
 | 
					        public void OpenProject(string path)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // If there is an opened project, close it
 | 
					            // If there is an opened project, close it
 | 
				
			||||||
            if (ActiveProject != null)
 | 
					            if (ActiveProject != null)
 | 
				
			||||||
                Close();
 | 
					                Close();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Open using storage
 | 
					            // Open using storage
 | 
				
			||||||
            ActiveProject = Storage.Read(path);
 | 
					            ActiveProject = ProjectStorage.Read(path);
 | 
				
			||||||
            ActiveProject.Path = path;
 | 
					            ActiveProject.Path = path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Raise event
 | 
					            // Raise event
 | 
				
			||||||
@@ -106,13 +108,13 @@ namespace RainmeterStudio.Business
 | 
				
			|||||||
                throw new InvalidOperationException("Cannot save a project that is not opened.");
 | 
					                throw new InvalidOperationException("Cannot save a project that is not opened.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Save
 | 
					            // Save
 | 
				
			||||||
            Storage.Write(ActiveProject);
 | 
					            ProjectStorage.Write(ActiveProject);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Closes an opened project
 | 
					        /// Closes an opened project
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public void Close() 
 | 
					        public void Close()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            ActiveProject = null;
 | 
					            ActiveProject = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -133,12 +135,245 @@ namespace RainmeterStudio.Business
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            _projectTemplates.Add(template);
 | 
					            _projectTemplates.Add(template);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets a list of existing project templates
 | 
					        /// Gets a list of existing project templates
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public IEnumerable<IProjectTemplate> ProjectTemplates { get { return _projectTemplates; } }
 | 
					        public IEnumerable<IProjectTemplate> ProjectTemplates { get { return _projectTemplates; } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #endregion
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Project item operations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        [Serializable]
 | 
				
			||||||
 | 
					        protected struct ClipboardData
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public bool Cut;
 | 
				
			||||||
 | 
					            public string QualifiedName;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Places a project item in the clipboard, and marks it for deletion
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="ref">Project item to cut</param>
 | 
				
			||||||
 | 
					        public void ProjectItemCutClipboard(Reference @ref)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var dataFormat = DataFormats.GetDataFormat(typeof(ClipboardData).FullName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ClipboardData data = new ClipboardData();
 | 
				
			||||||
 | 
					            data.Cut = true;
 | 
				
			||||||
 | 
					            data.QualifiedName = @ref.QualifiedName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Clipboard.SetData(dataFormat.Name, data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Places a project item in the clipboard
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="ref">Project item to copy</param>
 | 
				
			||||||
 | 
					        public void ProjectItemCopyClipboard(Reference @ref)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var dataFormat = DataFormats.GetDataFormat(typeof(ClipboardData).FullName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ClipboardData data = new ClipboardData();
 | 
				
			||||||
 | 
					            data.Cut = false;
 | 
				
			||||||
 | 
					            data.QualifiedName = @ref.QualifiedName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Clipboard.SetData(dataFormat.Name, data);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Pastes a project item from clipboard
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="dest">Destination</param>
 | 
				
			||||||
 | 
					        public void ProjectItemPasteClipboard(Reference dest)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var dataFormat = DataFormats.GetDataFormat(typeof(ClipboardData).FullName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (Clipboard.ContainsData(dataFormat.Name))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ClipboardData data = (ClipboardData)Clipboard.GetData(dataFormat.Name);
 | 
				
			||||||
 | 
					                var reference = ActiveProject.Root.GetReference(data.QualifiedName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (data.Cut)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ProjectItemMove(reference, dest);
 | 
				
			||||||
 | 
					                    Clipboard.Clear();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    ProjectItemCopy(reference, dest);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Moves a project item to another folder
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="ref">Project item to move</param>
 | 
				
			||||||
 | 
					        /// <param name="dest">Destination folder</param>
 | 
				
			||||||
 | 
					        public void ProjectItemMove(Reference @ref, Reference dest)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Move storage file
 | 
				
			||||||
 | 
					            string refPath = Path.GetFileName(@ref.StoragePath.TrimEnd('\\'));
 | 
				
			||||||
 | 
					            string destinationPath = (dest.TargetKind == ReferenceTargetKind.Directory) ? dest.StoragePath : Path.GetDirectoryName(dest.StoragePath);
 | 
				
			||||||
 | 
					            string newPath = Path.Combine(destinationPath, refPath);
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if (@ref.TargetKind == ReferenceTargetKind.Directory)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Directory.Move(@ref.StoragePath, newPath);
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                // Update children
 | 
				
			||||||
 | 
					                UpdateRenameChildren(@ref, @ref.StoragePath, newPath);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                File.Move(@ref.StoragePath, newPath);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Set up reference object
 | 
				
			||||||
 | 
					            @ref.Unparent();
 | 
				
			||||||
 | 
					            @ref.StoragePath = newPath;
 | 
				
			||||||
 | 
					            dest.Add(@ref);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void UpdateRenameChildren(Reference root, string oldPath, string newPath)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            foreach (var pair in root.ChildrenDictionary)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                pair.Value.StoragePath = pair.Value.StoragePath.Replace(oldPath, newPath);
 | 
				
			||||||
 | 
					                UpdateRenameChildren(pair.Value, oldPath, newPath);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Creates a copy of a project item to another folder
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="ref">Project item to copy</param>
 | 
				
			||||||
 | 
					        /// <param name="dest">Destination folder</param>
 | 
				
			||||||
 | 
					        /// <returns>Reference to the copy</returns>
 | 
				
			||||||
 | 
					        public Reference ProjectItemCopy(Reference @ref, Reference dest)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Create a clone reference
 | 
				
			||||||
 | 
					            var copyRef = (Reference)@ref.Clone();
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Copy storage file
 | 
				
			||||||
 | 
					            string refPath = Path.GetFileName(@ref.StoragePath.TrimEnd('\\'));
 | 
				
			||||||
 | 
					            string destinationPath = (dest.TargetKind == ReferenceTargetKind.Directory) ? dest.StoragePath : Path.GetDirectoryName(dest.StoragePath);
 | 
				
			||||||
 | 
					            string newPath = Path.Combine(destinationPath, refPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (@ref.TargetKind == ReferenceTargetKind.Directory)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                DirectoryHelper.CopyDirectory(@ref.StoragePath, newPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Update children
 | 
				
			||||||
 | 
					                UpdateRenameChildren(copyRef, copyRef.StoragePath, newPath);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // Find a nonconflicting file name
 | 
				
			||||||
 | 
					                newPath = GetNonConflictingPath(refPath, destinationPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Copy
 | 
				
			||||||
 | 
					                File.Copy(@ref.StoragePath, newPath);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Parent reference
 | 
				
			||||||
 | 
					            copyRef.Name = Path.GetFileName(newPath);
 | 
				
			||||||
 | 
					            copyRef.StoragePath = newPath;
 | 
				
			||||||
 | 
					            dest.Add(copyRef);
 | 
				
			||||||
 | 
					            return copyRef;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private static string GetNonConflictingPath(string filename, string destinationPath)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Initial path - destination path + file name
 | 
				
			||||||
 | 
					            string newPath = Path.Combine(destinationPath, filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Initial number
 | 
				
			||||||
 | 
					            int i = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Try to find if there already is a number
 | 
				
			||||||
 | 
					            var match = Regex.Match(newPath, "_([0-9])$");
 | 
				
			||||||
 | 
					            if (match.Success)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                i = Int32.Parse(match.Groups[1].Value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Find non-conflicting number
 | 
				
			||||||
 | 
					            while (File.Exists(newPath))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                ++i;
 | 
				
			||||||
 | 
					                newPath = Path.Combine(destinationPath, Path.GetFileNameWithoutExtension(filename) + "_" + i.ToString() + Path.GetExtension(filename));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            return newPath;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void ProjectItemRename(Reference @ref, string newName)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Rename on disk
 | 
				
			||||||
 | 
					            string refPath = @ref.StoragePath.TrimEnd('\\');
 | 
				
			||||||
 | 
					            string refDir = Path.GetDirectoryName(refPath);
 | 
				
			||||||
 | 
					            string newPath = Path.Combine(refDir, newName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (@ref.TargetKind == ReferenceTargetKind.Directory)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Directory.Move(refPath, newPath);
 | 
				
			||||||
 | 
					                newPath += '\\';
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                File.Move(refPath, newPath);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Set reference
 | 
				
			||||||
 | 
					            @ref.Name = newName;
 | 
				
			||||||
 | 
					            @ref.StoragePath = newPath;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Deletes a project item
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="ref"></param>
 | 
				
			||||||
 | 
					        public void ProjectItemDelete(Reference @ref, bool fromDisk)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (fromDisk)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (@ref.TargetKind == ReferenceTargetKind.File)
 | 
				
			||||||
 | 
					                    File.Delete(@ref.StoragePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                else Directory.Delete(@ref.StoragePath, true);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            @ref.Unparent();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Checks if there is a project item in the clipboard
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns>True if there is a project item in the clipboard</returns>
 | 
				
			||||||
 | 
					        public bool HaveProjectItemInClipboard()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var dataFormat = DataFormats.GetDataFormat(typeof(ClipboardData).FullName);
 | 
				
			||||||
 | 
					            return Clipboard.ContainsData(dataFormat.Name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Creates a new folder with given name
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="name">Name of folder</param>
 | 
				
			||||||
 | 
					        /// <param name="parent">Parent folder</param>
 | 
				
			||||||
 | 
					        public void CreateFolder(string name, Reference parent)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            string dir = (parent.TargetKind == ReferenceTargetKind.Directory) ?
 | 
				
			||||||
 | 
					                parent.StoragePath : Path.GetDirectoryName(parent.StoragePath);
 | 
				
			||||||
 | 
					            string newDirPath = Path.Combine(dir, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Directory.CreateDirectory(newDirPath);
 | 
				
			||||||
 | 
					            parent.Add(new Reference(name, newDirPath, ReferenceTargetKind.Directory));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,6 +7,7 @@ using System.Xml.Serialization;
 | 
				
			|||||||
using RainmeterStudio.Core;
 | 
					using RainmeterStudio.Core;
 | 
				
			||||||
using RainmeterStudio.Core.Model;
 | 
					using RainmeterStudio.Core.Model;
 | 
				
			||||||
using RainmeterStudio.Core.Storage;
 | 
					using RainmeterStudio.Core.Storage;
 | 
				
			||||||
 | 
					using RainmeterStudio.Storage;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace RainmeterStudio.Editor.ProjectEditor
 | 
					namespace RainmeterStudio.Editor.ProjectEditor
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -14,60 +15,8 @@ namespace RainmeterStudio.Editor.ProjectEditor
 | 
				
			|||||||
    /// Project storage, loads and saves project files
 | 
					    /// Project storage, loads and saves project files
 | 
				
			||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    [PluginExport]
 | 
					    [PluginExport]
 | 
				
			||||||
    public class ProjectStorage : IDocumentStorage
 | 
					    public class ProjectDocumentStorage : IDocumentStorage
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// Loads a project from file
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        /// <param name="path">Path to file to load</param>
 | 
					 | 
				
			||||||
        /// <returns>Loaded project</returns>
 | 
					 | 
				
			||||||
        public Project Read(string path)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            // Open file
 | 
					 | 
				
			||||||
            var file = File.OpenText(path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Deserialize file
 | 
					 | 
				
			||||||
            var serializer = new XmlSerializer(typeof(Project), new XmlRootAttribute("project"));
 | 
					 | 
				
			||||||
            Project project = serializer.Deserialize(file) as Project;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (project != null)
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                project.Path = path;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Clean up
 | 
					 | 
				
			||||||
            file.Close();
 | 
					 | 
				
			||||||
            return project;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// Saves a project to file
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        /// <param name="project">Project to save</param>
 | 
					 | 
				
			||||||
        /// <param name="path">File to save to</param>
 | 
					 | 
				
			||||||
        public void Write(Project project, string path)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            // Open file
 | 
					 | 
				
			||||||
            var file = File.OpenWrite(path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Serialize file
 | 
					 | 
				
			||||||
            var serializer = new XmlSerializer(typeof(Project), new XmlRootAttribute("project"));
 | 
					 | 
				
			||||||
            serializer.Serialize(file, project);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Clean up
 | 
					 | 
				
			||||||
            file.Close();
 | 
					 | 
				
			||||||
            project.Path = path;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					 | 
				
			||||||
        /// Saves a project
 | 
					 | 
				
			||||||
        /// </summary>
 | 
					 | 
				
			||||||
        /// <param name="project">Saves a project to the path specified in the 'Path' property</param>
 | 
					 | 
				
			||||||
        public void Write(Project project)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            Write(project, project.Path);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Reads the project as a ProjectDocument.
 | 
					        /// Reads the project as a ProjectDocument.
 | 
				
			||||||
        /// Use Load to get only the Project.
 | 
					        /// Use Load to get only the Project.
 | 
				
			||||||
@@ -76,9 +25,9 @@ namespace RainmeterStudio.Editor.ProjectEditor
 | 
				
			|||||||
        /// <returns>A project document</returns>
 | 
					        /// <returns>A project document</returns>
 | 
				
			||||||
        public IDocument ReadDocument(string path)
 | 
					        public IDocument ReadDocument(string path)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            Project project = Read(path);
 | 
					            Project project = ProjectStorage.Read(path);
 | 
				
			||||||
            var document = new ProjectDocument(project);
 | 
					            var document = new ProjectDocument(project);
 | 
				
			||||||
            document.Reference = new Reference(Path.GetFileName(path), path);
 | 
					            document.Reference = new Reference(Path.GetFileName(path), path, ReferenceTargetKind.Project);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return document;
 | 
					            return document;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -91,7 +40,7 @@ namespace RainmeterStudio.Editor.ProjectEditor
 | 
				
			|||||||
        public void WriteDocument(IDocument document, string path)
 | 
					        public void WriteDocument(IDocument document, string path)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var projectDocument = (ProjectDocument)document;
 | 
					            var projectDocument = (ProjectDocument)document;
 | 
				
			||||||
            Write(projectDocument.Project, path);
 | 
					            ProjectStorage.Write(projectDocument.Project, path);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
@@ -23,11 +23,8 @@ namespace RainmeterStudio
 | 
				
			|||||||
            SplashScreen splash = new SplashScreen("Resources/splash.png");
 | 
					            SplashScreen splash = new SplashScreen("Resources/splash.png");
 | 
				
			||||||
            splash.Show(true);
 | 
					            splash.Show(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Initialize project manager
 | 
					            // Initialize project, document manager
 | 
				
			||||||
            ProjectStorage projectStorage = new ProjectStorage();
 | 
					            ProjectManager projectManager = new ProjectManager();
 | 
				
			||||||
            ProjectManager projectManager = new ProjectManager(projectStorage);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Initialize document manager
 | 
					 | 
				
			||||||
            DocumentManager documentManager = new DocumentManager();
 | 
					            DocumentManager documentManager = new DocumentManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Initialize plugin manager
 | 
					            // Initialize plugin manager
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -96,14 +96,12 @@
 | 
				
			|||||||
      <DesignTime>True</DesignTime>
 | 
					      <DesignTime>True</DesignTime>
 | 
				
			||||||
      <DependentUpon>Strings.resx</DependentUpon>
 | 
					      <DependentUpon>Strings.resx</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
    <Compile Include="Editor\ProjectEditor\ProjectStorage.cs" />
 | 
					    <Compile Include="Editor\ProjectEditor\ProjectDocumentStorage.cs" />
 | 
				
			||||||
 | 
					    <Compile Include="Storage\ProjectStorage.cs" />
 | 
				
			||||||
    <Compile Include="UI\Command.cs" />
 | 
					    <Compile Include="UI\Command.cs" />
 | 
				
			||||||
    <Compile Include="UI\CommandGroup.cs" />
 | 
					 | 
				
			||||||
    <Compile Include="UI\Controller\IconProvider.cs" />
 | 
					    <Compile Include="UI\Controller\IconProvider.cs" />
 | 
				
			||||||
    <Compile Include="UI\Controller\IContextMenuProvider.cs" />
 | 
					 | 
				
			||||||
    <Compile Include="UI\Controller\ProjectController.cs" />
 | 
					    <Compile Include="UI\Controller\ProjectController.cs" />
 | 
				
			||||||
    <Compile Include="Business\SettingsProvider.cs" />
 | 
					    <Compile Include="Business\SettingsProvider.cs" />
 | 
				
			||||||
    <Compile Include="UI\Controller\ReferenceContextMenuProvider.cs" />
 | 
					 | 
				
			||||||
    <Compile Include="UI\Dialogs\CloseUnsavedDialog.xaml.cs">
 | 
					    <Compile Include="UI\Dialogs\CloseUnsavedDialog.xaml.cs">
 | 
				
			||||||
      <DependentUpon>CloseUnsavedDialog.xaml</DependentUpon>
 | 
					      <DependentUpon>CloseUnsavedDialog.xaml</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
@@ -114,6 +112,9 @@
 | 
				
			|||||||
    <Compile Include="UI\Dialogs\CreateProjectDialog.xaml.cs">
 | 
					    <Compile Include="UI\Dialogs\CreateProjectDialog.xaml.cs">
 | 
				
			||||||
      <DependentUpon>CreateProjectDialog.xaml</DependentUpon>
 | 
					      <DependentUpon>CreateProjectDialog.xaml</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
 | 
					    <Compile Include="UI\Dialogs\InputDialog.xaml.cs">
 | 
				
			||||||
 | 
					      <DependentUpon>InputDialog.xaml</DependentUpon>
 | 
				
			||||||
 | 
					    </Compile>
 | 
				
			||||||
    <Compile Include="UI\Panels\ProjectPanel.xaml.cs">
 | 
					    <Compile Include="UI\Panels\ProjectPanel.xaml.cs">
 | 
				
			||||||
      <DependentUpon>ProjectPanel.xaml</DependentUpon>
 | 
					      <DependentUpon>ProjectPanel.xaml</DependentUpon>
 | 
				
			||||||
    </Compile>
 | 
					    </Compile>
 | 
				
			||||||
@@ -133,6 +134,10 @@
 | 
				
			|||||||
      <SubType>Designer</SubType>
 | 
					      <SubType>Designer</SubType>
 | 
				
			||||||
      <Generator>MSBuild:Compile</Generator>
 | 
					      <Generator>MSBuild:Compile</Generator>
 | 
				
			||||||
    </Page>
 | 
					    </Page>
 | 
				
			||||||
 | 
					    <Page Include="UI\Dialogs\InputDialog.xaml">
 | 
				
			||||||
 | 
					      <SubType>Designer</SubType>
 | 
				
			||||||
 | 
					      <Generator>MSBuild:Compile</Generator>
 | 
				
			||||||
 | 
					    </Page>
 | 
				
			||||||
    <Page Include="UI\MainWindow.xaml">
 | 
					    <Page Include="UI\MainWindow.xaml">
 | 
				
			||||||
      <Generator>MSBuild:Compile</Generator>
 | 
					      <Generator>MSBuild:Compile</Generator>
 | 
				
			||||||
      <SubType>Designer</SubType>
 | 
					      <SubType>Designer</SubType>
 | 
				
			||||||
@@ -260,9 +265,7 @@
 | 
				
			|||||||
    <Resource Include="Resources\Icons\16\disk.png" />
 | 
					    <Resource Include="Resources\Icons\16\disk.png" />
 | 
				
			||||||
    <Resource Include="Resources\Icons\16\disk_multiple.png" />
 | 
					    <Resource Include="Resources\Icons\16\disk_multiple.png" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup />
 | 
				
			||||||
    <Folder Include="Storage\" />
 | 
					 | 
				
			||||||
  </ItemGroup>
 | 
					 | 
				
			||||||
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 | 
					  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 | 
				
			||||||
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
 | 
					  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
 | 
				
			||||||
       Other similar extension points exist, see Microsoft.Common.targets.
 | 
					       Other similar extension points exist, see Microsoft.Common.targets.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										207
									
								
								RainmeterStudio/Resources/Strings.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										207
									
								
								RainmeterStudio/Resources/Strings.Designer.cs
									
									
									
										generated
									
									
									
								
							@@ -108,6 +108,15 @@ namespace RainmeterStudio.Resources {
 | 
				
			|||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to _File....
 | 
					        ///   Looks up a localized string similar to _File....
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_DocumentCreate_AltDisplayText {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_DocumentCreate_AltDisplayText", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to _New item.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
        public static string Command_DocumentCreate_DisplayText {
 | 
					        public static string Command_DocumentCreate_DisplayText {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                return ResourceManager.GetString("Command_DocumentCreate_DisplayText", resourceCulture);
 | 
					                return ResourceManager.GetString("Command_DocumentCreate_DisplayText", resourceCulture);
 | 
				
			||||||
@@ -126,6 +135,15 @@ namespace RainmeterStudio.Resources {
 | 
				
			|||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to _File....
 | 
					        ///   Looks up a localized string similar to _File....
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_DocumentOpen_AltDisplayText {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_DocumentOpen_AltDisplayText", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to _Open.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
        public static string Command_DocumentOpen_DisplayText {
 | 
					        public static string Command_DocumentOpen_DisplayText {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                return ResourceManager.GetString("Command_DocumentOpen_DisplayText", resourceCulture);
 | 
					                return ResourceManager.GetString("Command_DocumentOpen_DisplayText", resourceCulture);
 | 
				
			||||||
@@ -234,6 +252,15 @@ namespace RainmeterStudio.Resources {
 | 
				
			|||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to _Project....
 | 
					        ///   Looks up a localized string similar to _Project....
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectCreate_AltDisplayText {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectCreate_AltDisplayText", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to New _Project.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
        public static string Command_ProjectCreate_DisplayText {
 | 
					        public static string Command_ProjectCreate_DisplayText {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                return ResourceManager.GetString("Command_ProjectCreate_DisplayText", resourceCulture);
 | 
					                return ResourceManager.GetString("Command_ProjectCreate_DisplayText", resourceCulture);
 | 
				
			||||||
@@ -249,9 +276,144 @@ namespace RainmeterStudio.Resources {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to _Copy.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemCopy_DisplayText {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemCopy_DisplayText", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Copy the selected item to clipboard.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemCopy_ToolTip {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemCopy_ToolTip", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Cu_t.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemCut_DisplayText {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemCut_DisplayText", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Cut the selected item to clipboard.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemCut_ToolTip {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemCut_ToolTip", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to _Delete.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemDelete_DisplayText {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemDelete_DisplayText", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Delete selected item.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemDelete_ToolTip {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemDelete_ToolTip", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Open Containing _Folder.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemOpenContainingFolder_DisplayText {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemOpenContainingFolder_DisplayText", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Open containing folder of selected item in Explorer.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemOpenContainingFolder_ToolTip {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemOpenContainingFolder_ToolTip", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Open in _Explorer.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemOpenInExplorer_DisplayText {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemOpenInExplorer_DisplayText", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Open selected folder in Explorer.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemOpenInExplorer_ToolTip {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemOpenInExplorer_ToolTip", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to _Paste.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemPaste_DisplayText {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemPaste_DisplayText", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Paste the clipboard contents in selected folder.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemPaste_ToolTip {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemPaste_ToolTip", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to _Rename.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemRename_DisplayText {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemRename_DisplayText", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Rename selected item.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectItemRename_ToolTip {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectItemRename_ToolTip", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to _Project....
 | 
					        ///   Looks up a localized string similar to _Project....
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string Command_ProjectOpen_AltDisplayText {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("Command_ProjectOpen_AltDisplayText", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to O_pen Project.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
        public static string Command_ProjectOpen_DisplayText {
 | 
					        public static string Command_ProjectOpen_DisplayText {
 | 
				
			||||||
            get {
 | 
					            get {
 | 
				
			||||||
                return ResourceManager.GetString("Command_ProjectOpen_DisplayText", resourceCulture);
 | 
					                return ResourceManager.GetString("Command_ProjectOpen_DisplayText", resourceCulture);
 | 
				
			||||||
@@ -447,6 +609,24 @@ namespace RainmeterStudio.Resources {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Do you also want to delete the selected project items from disk?.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string DeleteReferenceDialog_Caption {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("DeleteReferenceDialog_Caption", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Delete from disk?.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string DeleteReferenceDialog_Prompt {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("DeleteReferenceDialog_Prompt", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        ///   Looks up a localized string similar to Browse.
 | 
					        ///   Looks up a localized string similar to Browse.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
@@ -599,5 +779,32 @@ namespace RainmeterStudio.Resources {
 | 
				
			|||||||
                return ResourceManager.GetString("ProjectTemplate_EmptyProject_DisplayText", resourceCulture);
 | 
					                return ResourceManager.GetString("ProjectTemplate_EmptyProject_DisplayText", resourceCulture);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Rename project item.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string RenameReferenceDialog_Caption {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("RenameReferenceDialog_Caption", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Rename.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string RenameReferenceDialog_OKCaption {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("RenameReferenceDialog_OKCaption", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        ///   Looks up a localized string similar to Enter the new name:.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static string RenameReferenceDialog_Prompt {
 | 
				
			||||||
 | 
					            get {
 | 
				
			||||||
 | 
					                return ResourceManager.GetString("RenameReferenceDialog_Prompt", resourceCulture);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -154,7 +154,7 @@
 | 
				
			|||||||
    <value>Close active document</value>
 | 
					    <value>Close active document</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
  <data name="Command_DocumentCreate_DisplayText" xml:space="preserve">
 | 
					  <data name="Command_DocumentCreate_DisplayText" xml:space="preserve">
 | 
				
			||||||
    <value>_File...</value>
 | 
					    <value>_New item</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
  <data name="Command_DocumentCreate_ToolTip" xml:space="preserve">
 | 
					  <data name="Command_DocumentCreate_ToolTip" xml:space="preserve">
 | 
				
			||||||
    <value>Create a new file</value>
 | 
					    <value>Create a new file</value>
 | 
				
			||||||
@@ -168,7 +168,7 @@
 | 
				
			|||||||
  <data name="MainWindow_File_Open" xml:space="preserve">
 | 
					  <data name="MainWindow_File_Open" xml:space="preserve">
 | 
				
			||||||
    <value>_Open</value>
 | 
					    <value>_Open</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
  <data name="Command_ProjectCreate_DisplayText" xml:space="preserve">
 | 
					  <data name="Command_ProjectCreate_AltDisplayText" xml:space="preserve">
 | 
				
			||||||
    <value>_Project...</value>
 | 
					    <value>_Project...</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
  <data name="Command_ProjectCreate_ToolTip" xml:space="preserve">
 | 
					  <data name="Command_ProjectCreate_ToolTip" xml:space="preserve">
 | 
				
			||||||
@@ -192,7 +192,7 @@
 | 
				
			|||||||
  <data name="CreateProjectDialog_Title" xml:space="preserve">
 | 
					  <data name="CreateProjectDialog_Title" xml:space="preserve">
 | 
				
			||||||
    <value>Create project</value>
 | 
					    <value>Create project</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
  <data name="Command_ProjectOpen_DisplayText" xml:space="preserve">
 | 
					  <data name="Command_ProjectOpen_AltDisplayText" xml:space="preserve">
 | 
				
			||||||
    <value>_Project...</value>
 | 
					    <value>_Project...</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
  <data name="Command_ProjectOpen_ToolTip" xml:space="preserve">
 | 
					  <data name="Command_ProjectOpen_ToolTip" xml:space="preserve">
 | 
				
			||||||
@@ -268,7 +268,7 @@
 | 
				
			|||||||
    <value>Save document</value>
 | 
					    <value>Save document</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
  <data name="Command_DocumentOpen_DisplayText" xml:space="preserve">
 | 
					  <data name="Command_DocumentOpen_DisplayText" xml:space="preserve">
 | 
				
			||||||
    <value>_File...</value>
 | 
					    <value>_Open</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
  <data name="Command_DocumentOpen_ToolTip" xml:space="preserve">
 | 
					  <data name="Command_DocumentOpen_ToolTip" xml:space="preserve">
 | 
				
			||||||
    <value>Open a file</value>
 | 
					    <value>Open a file</value>
 | 
				
			||||||
@@ -297,4 +297,73 @@
 | 
				
			|||||||
  <data name="Command_DocumentSave_ToolTip" xml:space="preserve">
 | 
					  <data name="Command_DocumentSave_ToolTip" xml:space="preserve">
 | 
				
			||||||
    <value>Save the current document</value>
 | 
					    <value>Save the current document</value>
 | 
				
			||||||
  </data>
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="DeleteReferenceDialog_Caption" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Do you also want to delete the selected project items from disk?</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="DeleteReferenceDialog_Prompt" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Delete from disk?</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="RenameReferenceDialog_Caption" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Rename project item</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="RenameReferenceDialog_OKCaption" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Rename</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="RenameReferenceDialog_Prompt" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Enter the new name:</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_DocumentCreate_AltDisplayText" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>_File...</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_DocumentOpen_AltDisplayText" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>_File...</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemCopy_DisplayText" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>_Copy</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemCopy_ToolTip" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Copy the selected item to clipboard</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemCut_DisplayText" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Cu_t</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemCut_ToolTip" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Cut the selected item to clipboard</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemDelete_DisplayText" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>_Delete</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemDelete_ToolTip" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Delete selected item</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemOpenContainingFolder_DisplayText" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Open Containing _Folder</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemOpenContainingFolder_ToolTip" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Open containing folder of selected item in Explorer</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemOpenInExplorer_DisplayText" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Open in _Explorer</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemOpenInExplorer_ToolTip" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Open selected folder in Explorer</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemPaste_DisplayText" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>_Paste</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemPaste_ToolTip" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Paste the clipboard contents in selected folder</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemRename_DisplayText" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>_Rename</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectItemRename_ToolTip" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>Rename selected item</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectCreate_DisplayText" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>New _Project</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
 | 
					  <data name="Command_ProjectOpen_DisplayText" xml:space="preserve">
 | 
				
			||||||
 | 
					    <value>O_pen Project</value>
 | 
				
			||||||
 | 
					  </data>
 | 
				
			||||||
</root>
 | 
					</root>
 | 
				
			||||||
							
								
								
									
										69
									
								
								RainmeterStudio/Storage/ProjectStorage.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								RainmeterStudio/Storage/ProjectStorage.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.IO;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using System.Xml.Serialization;
 | 
				
			||||||
 | 
					using RainmeterStudio.Core.Model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace RainmeterStudio.Storage
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Reads or writes projects
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public static class ProjectStorage
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Loads a project from file
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="path">Path to file to load</param>
 | 
				
			||||||
 | 
					        /// <returns>Loaded project</returns>
 | 
				
			||||||
 | 
					        public static Project Read(string path)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Open file
 | 
				
			||||||
 | 
					            var file = File.OpenText(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Deserialize file
 | 
				
			||||||
 | 
					            var serializer = new XmlSerializer(typeof(Project), new XmlRootAttribute("project"));
 | 
				
			||||||
 | 
					            Project project = serializer.Deserialize(file) as Project;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (project != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                project.Path = path;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Clean up
 | 
				
			||||||
 | 
					            file.Close();
 | 
				
			||||||
 | 
					            return project;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Saves a project
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="project">Saves a project to the path specified in the 'Path' property</param>
 | 
				
			||||||
 | 
					        public static void Write(Project project)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Write(project, project.Path);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Saves a project to file
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="project">Project to save</param>
 | 
				
			||||||
 | 
					        /// <param name="path">File to save to</param>
 | 
				
			||||||
 | 
					        public static void Write(Project project, string path)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // Open file
 | 
				
			||||||
 | 
					            var file = File.OpenWrite(path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Serialize file
 | 
				
			||||||
 | 
					            var serializer = new XmlSerializer(typeof(Project), new XmlRootAttribute("project"));
 | 
				
			||||||
 | 
					            serializer.Serialize(file, project);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Clean up
 | 
				
			||||||
 | 
					            file.Close();
 | 
				
			||||||
 | 
					            project.Path = path;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -13,7 +13,13 @@
 | 
				
			|||||||
            <Style TargetType="ToolBarTray">
 | 
					            <Style TargetType="ToolBarTray">
 | 
				
			||||||
                <Setter Property="Background" Value="Transparent" />
 | 
					                <Setter Property="Background" Value="Transparent" />
 | 
				
			||||||
            </Style>
 | 
					            </Style>
 | 
				
			||||||
            
 | 
					
 | 
				
			||||||
 | 
					            <Style x:Key="CommandContextMenuItemStyle" TargetType="MenuItem">
 | 
				
			||||||
 | 
					                <Setter Property="Command" Value="{Binding}" />
 | 
				
			||||||
 | 
					                <Setter Property="Header" Value="{Binding DisplayText}" />
 | 
				
			||||||
 | 
					                <Setter Property="ToolTip" Value="{Binding ToolTip}" />
 | 
				
			||||||
 | 
					            </Style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <Style x:Key="CommandMenuItemStyle" TargetType="MenuItem">
 | 
					            <Style x:Key="CommandMenuItemStyle" TargetType="MenuItem">
 | 
				
			||||||
                <Setter Property="Command" Value="{Binding}" />
 | 
					                <Setter Property="Command" Value="{Binding}" />
 | 
				
			||||||
                <Setter Property="Header" Value="{Binding DisplayText}" />
 | 
					                <Setter Property="Header" Value="{Binding DisplayText}" />
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -114,7 +114,17 @@ namespace RainmeterStudio.UI.Controller
 | 
				
			|||||||
            ProjectManager = projectManager;
 | 
					            ProjectManager = projectManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            DocumentCreateCommand = new Command("DocumentCreate", Create, () => ProjectManager.ActiveProject != null);
 | 
					            DocumentCreateCommand = new Command("DocumentCreate", Create, () => ProjectManager.ActiveProject != null);
 | 
				
			||||||
            DocumentOpenCommand = new Command("DocumentOpen", Open);
 | 
					            DocumentOpenCommand = new Command("DocumentOpen", arg =>
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if (arg is Reference)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Open((Reference)arg);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Open(); 
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
            DocumentSaveCommand = new Command("DocumentSave", () => Save(), HasActiveDocumentEditor);
 | 
					            DocumentSaveCommand = new Command("DocumentSave", () => Save(), HasActiveDocumentEditor);
 | 
				
			||||||
            DocumentSaveAsCommand = new Command("DocumentSaveAs", () => SaveAs(), HasActiveDocumentEditor);
 | 
					            DocumentSaveAsCommand = new Command("DocumentSaveAs", () => SaveAs(), HasActiveDocumentEditor);
 | 
				
			||||||
            DocumentSaveACopyCommand = new Command("DocumentSaveACopy", () => SaveACopy(), HasActiveDocumentEditor);
 | 
					            DocumentSaveACopyCommand = new Command("DocumentSaveACopy", () => SaveACopy(), HasActiveDocumentEditor);
 | 
				
			||||||
@@ -168,7 +178,7 @@ namespace RainmeterStudio.UI.Controller
 | 
				
			|||||||
            if (!Directory.Exists(folder))
 | 
					            if (!Directory.Exists(folder))
 | 
				
			||||||
                folder = Path.GetDirectoryName(folder);
 | 
					                folder = Path.GetDirectoryName(folder);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var reference = new Reference(name, Path.Combine(folder, name), Reference.ReferenceTargetKind.File);
 | 
					            var reference = new Reference(name, Path.Combine(folder, name), ReferenceTargetKind.File);
 | 
				
			||||||
            editor.AttachedDocument.Reference = reference;
 | 
					            editor.AttachedDocument.Reference = reference;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Save document
 | 
					            // Save document
 | 
				
			||||||
@@ -198,6 +208,15 @@ namespace RainmeterStudio.UI.Controller
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Opens the document pointed to by a reference
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="reference"></param>
 | 
				
			||||||
 | 
					        public void Open(Reference reference)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            DocumentManager.Open(reference.StoragePath);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Saves the active document
 | 
					        /// Saves the active document
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -33,7 +33,7 @@ namespace RainmeterStudio.UI.Controller
 | 
				
			|||||||
            string key = "ProjectItem";
 | 
					            string key = "ProjectItem";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Is a file?
 | 
					            // Is a file?
 | 
				
			||||||
            if (item.TargetKind == Reference.ReferenceTargetKind.File || item.TargetKind == Reference.ReferenceTargetKind.Project)
 | 
					            if (item.TargetKind == ReferenceTargetKind.File || item.TargetKind == ReferenceTargetKind.Project)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var extension = Path.GetExtension(item.StoragePath);
 | 
					                var extension = Path.GetExtension(item.StoragePath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -45,7 +45,7 @@ namespace RainmeterStudio.UI.Controller
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Not a file, try to figure out if a directory
 | 
					            // Not a file, try to figure out if a directory
 | 
				
			||||||
            else if (item.TargetKind == Reference.ReferenceTargetKind.Directory)
 | 
					            else if (item.TargetKind == ReferenceTargetKind.Directory)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                key += "Directory";
 | 
					                key += "Directory";
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ using RainmeterStudio.Core.Model;
 | 
				
			|||||||
using RainmeterStudio.UI.Dialogs;
 | 
					using RainmeterStudio.UI.Dialogs;
 | 
				
			||||||
using RainmeterStudio.UI.ViewModel;
 | 
					using RainmeterStudio.UI.ViewModel;
 | 
				
			||||||
using RainmeterStudio.Properties;
 | 
					using RainmeterStudio.Properties;
 | 
				
			||||||
 | 
					using RainmeterStudio.Core.Utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace RainmeterStudio.UI.Controller
 | 
					namespace RainmeterStudio.UI.Controller
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -97,6 +98,42 @@ namespace RainmeterStudio.UI.Controller
 | 
				
			|||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public Command ProjectCloseCommand { get; private set; }
 | 
					        public Command ProjectCloseCommand { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Cut command
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public Command ProjectItemCutCommand { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Copy command
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public Command ProjectItemCopyCommand { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Paste command
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public Command ProjectItemPasteCommand { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Rename command
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public Command ProjectItemRenameCommand { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Delete command
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public Command ProjectItemDeleteCommand { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Open folder command
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public Command ProjectItemOpenInExplorerCommand { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Open folder command
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public Command ProjectItemOpenContainingFolderCommand { get; private set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #endregion
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
@@ -111,9 +148,19 @@ namespace RainmeterStudio.UI.Controller
 | 
				
			|||||||
            ProjectCreateCommand = new Command("ProjectCreate", CreateProject);
 | 
					            ProjectCreateCommand = new Command("ProjectCreate", CreateProject);
 | 
				
			||||||
            ProjectOpenCommand = new Command("ProjectOpen", OpenProject);
 | 
					            ProjectOpenCommand = new Command("ProjectOpen", OpenProject);
 | 
				
			||||||
            ProjectCloseCommand = new Command("ProjectClose", CloseProject, () => ActiveProject != null);
 | 
					            ProjectCloseCommand = new Command("ProjectClose", CloseProject, () => ActiveProject != null);
 | 
				
			||||||
 | 
					            ProjectItemCutCommand = new Command("ProjectItemCut", r => ProjectItemCutClipboard((Reference)r));
 | 
				
			||||||
 | 
					            ProjectItemCopyCommand = new Command("ProjectItemCopy", r => ProjectItemCopyClipboard((Reference)r));
 | 
				
			||||||
 | 
					            ProjectItemPasteCommand = new Command("ProjectItemPaste", r => ProjectItemPasteClipboard((Reference)r), r => Manager.HaveProjectItemInClipboard());
 | 
				
			||||||
 | 
					            ProjectItemRenameCommand = new Command("ProjectItemRename", r => ProjectItemRename((Reference)r));
 | 
				
			||||||
 | 
					            ProjectItemDeleteCommand = new Command("ProjectItemDelete", r => ProjectItemDelete((Reference)r));
 | 
				
			||||||
 | 
					            ProjectItemOpenInExplorerCommand = new Command("ProjectItemOpenInExplorer", r => ProjectItemOpenInExplorer((Reference)r));
 | 
				
			||||||
 | 
					            ProjectItemOpenContainingFolderCommand = new Command("ProjectItemOpenContainingFolder", r => ProjectItemOpenInExplorer((Reference)r));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ActiveProjectChanged += new EventHandler((sender, e) => ProjectCloseCommand.NotifyCanExecuteChanged());
 | 
					            ActiveProjectChanged += new EventHandler((sender, e) => ProjectCloseCommand.NotifyCanExecuteChanged());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Project operations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Displays the 'create project' dialog and creates a new project
 | 
					        /// Displays the 'create project' dialog and creates a new project
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
@@ -167,5 +214,144 @@ namespace RainmeterStudio.UI.Controller
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            Manager.Close();
 | 
					            Manager.Close();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Project item operations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        protected struct ClipboardData
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public bool Cut;
 | 
				
			||||||
 | 
					            public Reference Ref;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Places a project item in the clipboard, and marks it for deletion
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="ref">Project item to cut</param>
 | 
				
			||||||
 | 
					        public void ProjectItemCutClipboard(Reference @ref)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Manager.ProjectItemCutClipboard(@ref);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (Exception ex)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                MessageBox.Show(ex.Message, "Error");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Places a project item in the clipboard
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="ref">Project item to copy</param>
 | 
				
			||||||
 | 
					        public void ProjectItemCopyClipboard(Reference @ref)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Manager.ProjectItemCopyClipboard(@ref);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (Exception ex)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                MessageBox.Show(ex.Message, "Error");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Pastes a project item from clipboard
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="ref">Destination</param>
 | 
				
			||||||
 | 
					        public void ProjectItemPasteClipboard(Reference @ref)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Manager.ProjectItemPasteClipboard(@ref);
 | 
				
			||||||
 | 
					                Manager.SaveActiveProject();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (Exception ex)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                MessageBox.Show(ex.Message, "Error");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Renames a project item
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="ref">Reference to project item</param>
 | 
				
			||||||
 | 
					        public void ProjectItemRename(Reference @ref)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            string initialValue = Path.GetFileName(@ref.StoragePath.TrimEnd('\\'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Show an input dialog
 | 
				
			||||||
 | 
					            var newName = InputDialog.Show(Resources.Strings.RenameReferenceDialog_Prompt,
 | 
				
			||||||
 | 
					                Resources.Strings.RenameReferenceDialog_Caption,
 | 
				
			||||||
 | 
					                initialValue,
 | 
				
			||||||
 | 
					                PathHelper.IsFileNameValid,
 | 
				
			||||||
 | 
					                Resources.Strings.RenameReferenceDialog_OKCaption,
 | 
				
			||||||
 | 
					                Resources.Strings.Dialog_Cancel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (newName != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                try
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Manager.ProjectItemRename(@ref, newName);
 | 
				
			||||||
 | 
					                    Manager.SaveActiveProject();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                catch(Exception ex)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    MessageBox.Show(ex.Message, "Error");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Deletes a project item
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="ref">Reference to project item</param>
 | 
				
			||||||
 | 
					        public void ProjectItemDelete(Reference @ref)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var res = MessageBox.Show(Resources.Strings.DeleteReferenceDialog_Prompt,
 | 
				
			||||||
 | 
					                Resources.Strings.DeleteReferenceDialog_Caption,
 | 
				
			||||||
 | 
					                MessageBoxButton.YesNoCancel,
 | 
				
			||||||
 | 
					                MessageBoxImage.Question);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                switch(res)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    case MessageBoxResult.Yes:
 | 
				
			||||||
 | 
					                        Manager.ProjectItemDelete(@ref, true);
 | 
				
			||||||
 | 
					                        Manager.SaveActiveProject();
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    case MessageBoxResult.No:
 | 
				
			||||||
 | 
					                        Manager.ProjectItemDelete(@ref, false);
 | 
				
			||||||
 | 
					                        Manager.SaveActiveProject();
 | 
				
			||||||
 | 
					                        break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            catch (Exception ex)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                MessageBox.Show(ex.Message, "Error");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Opens the containing folder if reference is a file, or folder if reference is a folder in windows explorer
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="ref">Reference</param>
 | 
				
			||||||
 | 
					        public void ProjectItemOpenInExplorer(Reference @ref)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (@ref.TargetKind == ReferenceTargetKind.Directory)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                System.Diagnostics.Process.Start(@ref.StoragePath);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                System.Diagnostics.Process.Start(Path.GetDirectoryName(@ref.StoragePath));
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								RainmeterStudio/UI/Dialogs/InputDialog.xaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								RainmeterStudio/UI/Dialogs/InputDialog.xaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					<Window x:Class="RainmeterStudio.UI.Dialogs.InputDialog"
 | 
				
			||||||
 | 
					        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 | 
				
			||||||
 | 
					        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 | 
				
			||||||
 | 
					        xmlns:r="clr-namespace:RainmeterStudio.Resources"
 | 
				
			||||||
 | 
					        Height="100" Width="360"
 | 
				
			||||||
 | 
					        WindowStartupLocation="CenterOwner"
 | 
				
			||||||
 | 
					        WindowStyle="ToolWindow" ShowInTaskbar="False"
 | 
				
			||||||
 | 
					        Background="WhiteSmoke" >
 | 
				
			||||||
 | 
					    <Grid>
 | 
				
			||||||
 | 
					        <Grid.RowDefinitions>
 | 
				
			||||||
 | 
					            <RowDefinition Height="Auto" />
 | 
				
			||||||
 | 
					            <RowDefinition Height="Auto" />
 | 
				
			||||||
 | 
					            <RowDefinition Height="Auto" />
 | 
				
			||||||
 | 
					        </Grid.RowDefinitions>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <TextBlock Name="textPrompt" Grid.Row="0" 
 | 
				
			||||||
 | 
					                   Text="[placeholder]" Margin="4" Grid.ColumnSpan="2"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <TextBox Name="textInput" Grid.Row="1" Margin="3"
 | 
				
			||||||
 | 
					                 TextChanged="textInput_TextChanged" Grid.ColumnSpan="2"/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <StackPanel Grid.Row="2" Orientation="Horizontal"
 | 
				
			||||||
 | 
					                    HorizontalAlignment="Right" Grid.Column="1">
 | 
				
			||||||
 | 
					            <Button Name="buttonOK" Content="{x:Static r:Strings.Dialog_OK}" IsDefault="True" Margin="1px" Click="buttonOK_Click" />
 | 
				
			||||||
 | 
					            <Button Name="buttonCancel" Content="{x:Static r:Strings.Dialog_Cancel}" IsCancel="True" Margin="1px" Click="buttonCancel_Click" />
 | 
				
			||||||
 | 
					        </StackPanel>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    </Grid>
 | 
				
			||||||
 | 
					</Window>
 | 
				
			||||||
							
								
								
									
										380
									
								
								RainmeterStudio/UI/Dialogs/InputDialog.xaml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										380
									
								
								RainmeterStudio/UI/Dialogs/InputDialog.xaml.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,380 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using System.Windows;
 | 
				
			||||||
 | 
					using System.Windows.Controls;
 | 
				
			||||||
 | 
					using System.Windows.Data;
 | 
				
			||||||
 | 
					using System.Windows.Documents;
 | 
				
			||||||
 | 
					using System.Windows.Input;
 | 
				
			||||||
 | 
					using System.Windows.Media;
 | 
				
			||||||
 | 
					using System.Windows.Media.Imaging;
 | 
				
			||||||
 | 
					using System.Windows.Shapes;
 | 
				
			||||||
 | 
					using RainmeterStudio.Resources;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace RainmeterStudio.UI.Dialogs
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// Interaction logic for InputDialog.xaml
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
 | 
					    public partial class InputDialog : Window
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        private Func<string, bool> _validateFunction;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// A validate function that always returns true
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public static readonly Func<string, bool> AlwaysValid = (str => true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Properties
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets or sets the prompt text
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public string Prompt
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return textPrompt.Text;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                textPrompt.Text = value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets or sets the text on the 'ok' button
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public string OKCaption
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return (string)buttonOK.Content;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                buttonOK.Content = value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets or sets the text on the 'cancel' button
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public string CancelCaption
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return (string)buttonCancel.Content;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                buttonCancel.Content = value;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets or sets the text inputted by the user
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public string InputText
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return textInput.Text;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                textInput.Text = value;
 | 
				
			||||||
 | 
					                Validate();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets or sets a function used to validate the input
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        public Func<string, bool> ValidateFunction
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            get
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return _validateFunction;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            set
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _validateFunction = value;
 | 
				
			||||||
 | 
					                Validate();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes the input dialog
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        public InputDialog(string prompt)
 | 
				
			||||||
 | 
					            :this(prompt, String.Empty, String.Empty, AlwaysValid)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes the input dialog
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        public InputDialog(string prompt, string caption)
 | 
				
			||||||
 | 
					            : this(prompt, caption, String.Empty, AlwaysValid)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes the input dialog
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="okCaption">Caption of the 'OK' button</param>
 | 
				
			||||||
 | 
					        /// <param name="cancelCaption">Caption of the 'Cancel' button</param>
 | 
				
			||||||
 | 
					        public InputDialog(string prompt, string caption, string okCaption, string cancelCaption)
 | 
				
			||||||
 | 
					            : this(prompt, caption, String.Empty, AlwaysValid, okCaption, cancelCaption)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes the input dialog
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="validateFunction">Callback function which validates the inputted text</param>
 | 
				
			||||||
 | 
					        public InputDialog(string prompt, string caption, Func<string, bool> validateFunction)
 | 
				
			||||||
 | 
					            : this(prompt, caption, String.Empty, validateFunction)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes the input dialog
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="validateFunction">Callback function which validates the inputted text</param>
 | 
				
			||||||
 | 
					        /// <param name="okCaption">Caption of the 'OK' button</param>
 | 
				
			||||||
 | 
					        /// <param name="cancelCaption">Caption of the 'Cancel' button</param>
 | 
				
			||||||
 | 
					        public InputDialog(string prompt, string caption, Func<string, bool> validateFunction, string okCaption, string cancelCaption)
 | 
				
			||||||
 | 
					            : this(prompt, caption, String.Empty, validateFunction, okCaption, cancelCaption)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes the input dialog
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="initialValue">Initial value of the input dialog</param>
 | 
				
			||||||
 | 
					        public InputDialog(string prompt, string caption, string initialValue)
 | 
				
			||||||
 | 
					            : this(prompt, caption, initialValue, AlwaysValid)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes the input dialog
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="initialValue">Initial value of the input dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="okCaption">Caption of the 'OK' button</param>
 | 
				
			||||||
 | 
					        /// <param name="cancelCaption">Caption of the 'Cancel' button</param>
 | 
				
			||||||
 | 
					        public InputDialog(string prompt, string caption, string initialValue, string okCaption, string cancelCaption)
 | 
				
			||||||
 | 
					            : this(prompt, caption, initialValue, AlwaysValid, okCaption, cancelCaption)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes the input dialog
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="initialValue">Initial value of the input dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="validateFunction">Callback function which validates the inputted text</param>
 | 
				
			||||||
 | 
					        public InputDialog(string prompt, string caption, string initialValue, Func<string, bool> validateFunction)
 | 
				
			||||||
 | 
					            : this(prompt, caption, initialValue, validateFunction, Strings.Dialog_OK, Strings.Dialog_Cancel)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Initializes the input dialog
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="initialValue">Initial value of the input dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="validateFunction">Callback function which validates the inputted text</param>
 | 
				
			||||||
 | 
					        /// <param name="okCaption">Caption of the 'OK' button</param>
 | 
				
			||||||
 | 
					        /// <param name="cancelCaption">Caption of the 'Cancel' button</param>
 | 
				
			||||||
 | 
					        public InputDialog(string prompt, string caption, string initialValue, Func<string, bool> validateFunction, string okCaption, string cancelCaption)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            InitializeComponent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Prompt = prompt;
 | 
				
			||||||
 | 
					            Title = caption;
 | 
				
			||||||
 | 
					            InputText = initialValue;
 | 
				
			||||||
 | 
					            ValidateFunction = validateFunction;
 | 
				
			||||||
 | 
					            OKCaption = okCaption;
 | 
				
			||||||
 | 
					            CancelCaption = cancelCaption;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void buttonOK_Click(object sender, RoutedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            DialogResult = true;
 | 
				
			||||||
 | 
					            Close();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void buttonCancel_Click(object sender, RoutedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            DialogResult = false;
 | 
				
			||||||
 | 
					            Close();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void textInput_TextChanged(object sender, TextChangedEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            Validate();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void Validate()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            bool res = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (ValidateFunction != null)
 | 
				
			||||||
 | 
					                res = ValidateFunction(textInput.Text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            buttonOK.IsEnabled = res;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region Static show
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Shows a dialog prompting the user for input
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <returns>Input text, or null if canceled</returns>
 | 
				
			||||||
 | 
					        public static string Show(string prompt)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ShowCommon(new InputDialog(prompt));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Shows a dialog prompting the user for input
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <returns>Input text, or null if canceled</returns>
 | 
				
			||||||
 | 
					        public static string Show(string prompt, string caption)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ShowCommon(new InputDialog(prompt, caption));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Shows a dialog prompting the user for input
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="okCaption">Caption of the 'OK' button</param>
 | 
				
			||||||
 | 
					        /// <param name="cancelCaption">Caption of the 'Cancel' button</param>
 | 
				
			||||||
 | 
					        /// <returns>Input text, or null if canceled</returns>
 | 
				
			||||||
 | 
					        public static string Show(string prompt, string caption, string okCaption, string cancelCaption)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ShowCommon(new InputDialog(prompt, caption, okCaption, cancelCaption));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Shows a dialog prompting the user for input
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="validateFunction">Callback function which validates the inputted text</param>
 | 
				
			||||||
 | 
					        /// <returns>Input text, or null if canceled</returns>
 | 
				
			||||||
 | 
					        public static string Show(string prompt, string caption, Func<string, bool> validateFunction)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ShowCommon(new InputDialog(prompt, caption, validateFunction));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Shows a dialog prompting the user for input
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="validateFunction">Callback function which validates the inputted text</param>
 | 
				
			||||||
 | 
					        /// <param name="okCaption">Caption of the 'OK' button</param>
 | 
				
			||||||
 | 
					        /// <param name="cancelCaption">Caption of the 'Cancel' button</param>
 | 
				
			||||||
 | 
					        /// <returns>Input text, or null if canceled</returns>
 | 
				
			||||||
 | 
					        public static string Show(string prompt, string caption, Func<string, bool> validateFunction, string okCaption, string cancelCaption)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ShowCommon(new InputDialog(prompt, caption, validateFunction, okCaption, cancelCaption));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Shows a dialog prompting the user for input
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="initialValue">Initial value of the input dialog</param>
 | 
				
			||||||
 | 
					        /// <returns>Input text, or null if canceled</returns>
 | 
				
			||||||
 | 
					        public static string Show(string prompt, string caption, string initialValue)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ShowCommon(new InputDialog(prompt, caption, initialValue));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Shows a dialog prompting the user for input
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="initialValue">Initial value of the input dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="okCaption">Caption of the 'OK' button</param>
 | 
				
			||||||
 | 
					        /// <param name="cancelCaption">Caption of the 'Cancel' button</param>
 | 
				
			||||||
 | 
					        /// <returns>Input text, or null if canceled</returns>
 | 
				
			||||||
 | 
					        public static string Show(string prompt, string caption, string initialValue, string okCaption, string cancelCaption)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ShowCommon(new InputDialog(prompt, caption, initialValue, okCaption, cancelCaption));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Shows a dialog prompting the user for input
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="initialValue">Initial value of the input dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="validateFunction">Callback function which validates the inputted text</param>
 | 
				
			||||||
 | 
					        /// <returns>Input text, or null if canceled</returns>
 | 
				
			||||||
 | 
					        public static string Show(string prompt, string caption, string initialValue, Func<string, bool> validateFunction)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ShowCommon(new InputDialog(prompt, caption, initialValue, validateFunction));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Shows a dialog prompting the user for input
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="prompt">Message displayed to user</param>
 | 
				
			||||||
 | 
					        /// <param name="caption">Title of dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="initialValue">Initial value of the input dialog</param>
 | 
				
			||||||
 | 
					        /// <param name="validateFunction">Callback function which validates the inputted text</param>
 | 
				
			||||||
 | 
					        /// <param name="okCaption">Caption of the 'OK' button</param>
 | 
				
			||||||
 | 
					        /// <param name="cancelCaption">Caption of the 'Cancel' button</param>
 | 
				
			||||||
 | 
					        /// <returns>Input text, or null if canceled</returns>
 | 
				
			||||||
 | 
					        public static string Show(string prompt, string caption, string initialValue, Func<string, bool> validateFunction, string okCaption, string cancelCaption)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            return ShowCommon(new InputDialog(prompt, caption, initialValue, validateFunction, okCaption, cancelCaption));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private static string ShowCommon(InputDialog dialog)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            bool? res = dialog.ShowDialog();
 | 
				
			||||||
 | 
					            if (res.HasValue && res.Value)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return dialog.InputText;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -34,13 +34,15 @@
 | 
				
			|||||||
            <MenuItem Header="{x:Static r:Strings.MainWindow_File}">
 | 
					            <MenuItem Header="{x:Static r:Strings.MainWindow_File}">
 | 
				
			||||||
                <MenuItem Header="{x:Static r:Strings.MainWindow_File_New}">
 | 
					                <MenuItem Header="{x:Static r:Strings.MainWindow_File_New}">
 | 
				
			||||||
                    <MenuItem DataContext="{Binding DocumentController.DocumentCreateCommand}"
 | 
					                    <MenuItem DataContext="{Binding DocumentController.DocumentCreateCommand}"
 | 
				
			||||||
                              Style="{StaticResource CommandMenuItemStyle}" >
 | 
					                              Style="{StaticResource CommandMenuItemStyle}" 
 | 
				
			||||||
 | 
					                              Header="{x:Static r:Strings.Command_DocumentCreate_AltDisplayText}">
 | 
				
			||||||
                        <MenuItem.Icon>
 | 
					                        <MenuItem.Icon>
 | 
				
			||||||
                            <Image Source="{Binding Icon}" />
 | 
					                            <Image Source="{Binding Icon}" />
 | 
				
			||||||
                        </MenuItem.Icon>
 | 
					                        </MenuItem.Icon>
 | 
				
			||||||
                    </MenuItem>
 | 
					                    </MenuItem>
 | 
				
			||||||
                    <MenuItem DataContext="{Binding ProjectController.ProjectCreateCommand}"
 | 
					                    <MenuItem DataContext="{Binding ProjectController.ProjectCreateCommand}"
 | 
				
			||||||
                              Style="{StaticResource CommandMenuItemStyle}">
 | 
					                              Style="{StaticResource CommandMenuItemStyle}"
 | 
				
			||||||
 | 
					                              Header="{x:Static r:Strings.Command_ProjectCreate_AltDisplayText}">
 | 
				
			||||||
                        <MenuItem.Icon>
 | 
					                        <MenuItem.Icon>
 | 
				
			||||||
                            <Image Source="{Binding Icon}" />
 | 
					                            <Image Source="{Binding Icon}" />
 | 
				
			||||||
                        </MenuItem.Icon>
 | 
					                        </MenuItem.Icon>
 | 
				
			||||||
@@ -49,13 +51,15 @@
 | 
				
			|||||||
                <Separator />
 | 
					                <Separator />
 | 
				
			||||||
                <MenuItem Header="{x:Static r:Strings.MainWindow_File_Open}">
 | 
					                <MenuItem Header="{x:Static r:Strings.MainWindow_File_Open}">
 | 
				
			||||||
                    <MenuItem DataContext="{Binding DocumentController.DocumentOpenCommand}"
 | 
					                    <MenuItem DataContext="{Binding DocumentController.DocumentOpenCommand}"
 | 
				
			||||||
                              Style="{StaticResource CommandMenuItemStyle}">
 | 
					                              Style="{StaticResource CommandMenuItemStyle}"
 | 
				
			||||||
 | 
					                              Header="{x:Static r:Strings.Command_DocumentOpen_AltDisplayText}">
 | 
				
			||||||
                        <MenuItem.Icon>
 | 
					                        <MenuItem.Icon>
 | 
				
			||||||
                            <Image Source="{Binding Icon}" />
 | 
					                            <Image Source="{Binding Icon}" />
 | 
				
			||||||
                        </MenuItem.Icon>
 | 
					                        </MenuItem.Icon>
 | 
				
			||||||
                    </MenuItem>
 | 
					                    </MenuItem>
 | 
				
			||||||
                    <MenuItem DataContext="{Binding ProjectController.ProjectOpenCommand}"
 | 
					                    <MenuItem DataContext="{Binding ProjectController.ProjectOpenCommand}"
 | 
				
			||||||
                              Style="{StaticResource CommandMenuItemStyle}">
 | 
					                              Style="{StaticResource CommandMenuItemStyle}"
 | 
				
			||||||
 | 
					                              Header="{x:Static r:Strings.Command_ProjectOpen_AltDisplayText}">
 | 
				
			||||||
                        <MenuItem.Icon>
 | 
					                        <MenuItem.Icon>
 | 
				
			||||||
                            <Image Source="{Binding Icon}" />
 | 
					                            <Image Source="{Binding Icon}" />
 | 
				
			||||||
                        </MenuItem.Icon>
 | 
					                        </MenuItem.Icon>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -55,7 +55,8 @@ namespace RainmeterStudio.UI
 | 
				
			|||||||
            DocumentController.DocumentOpened += documentController_DocumentOpened;
 | 
					            DocumentController.DocumentOpened += documentController_DocumentOpened;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Initialize panels
 | 
					            // Initialize panels
 | 
				
			||||||
            projectPanel.Controller = ProjectController;
 | 
					            projectPanel.ProjectController = ProjectController;
 | 
				
			||||||
 | 
					            projectPanel.DocumentController = DocumentController;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        void documentController_DocumentOpened(object sender, DocumentOpenedEventArgs e)
 | 
					        void documentController_DocumentOpened(object sender, DocumentOpenedEventArgs e)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -44,12 +44,15 @@
 | 
				
			|||||||
        
 | 
					        
 | 
				
			||||||
        <!-- Project item tree  -->
 | 
					        <!-- Project item tree  -->
 | 
				
			||||||
        <TreeView Grid.Row="2" Name="treeProjectItems">
 | 
					        <TreeView Grid.Row="2" Name="treeProjectItems">
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            <TreeView.ItemContainerStyle>
 | 
					            <TreeView.ItemContainerStyle>
 | 
				
			||||||
                <Style TargetType="{x:Type TreeViewItem}">
 | 
					                <Style TargetType="{x:Type TreeViewItem}">
 | 
				
			||||||
                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
 | 
					                    <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
 | 
				
			||||||
                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
 | 
					                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
 | 
				
			||||||
                    <EventSetter Event="Expanded" Handler="TreeViewItem_ExpandedOrCollapsed" />
 | 
					                    <EventSetter Event="Expanded" Handler="TreeViewItem_ExpandedOrCollapsed" />
 | 
				
			||||||
                    <EventSetter Event="Collapsed" Handler="TreeViewItem_ExpandedOrCollapsed" />
 | 
					                    <EventSetter Event="Collapsed" Handler="TreeViewItem_ExpandedOrCollapsed" />
 | 
				
			||||||
 | 
					                    <EventSetter Event="PreviewMouseRightButtonDown" Handler="TreeViewItem_PreviewMouseRightButtonDown" />
 | 
				
			||||||
 | 
					                    <EventSetter Event="PreviewMouseDoubleClick" Handler="TreeViewItem_PreviewMouseDoubleClick" />
 | 
				
			||||||
                </Style>
 | 
					                </Style>
 | 
				
			||||||
            </TreeView.ItemContainerStyle>
 | 
					            </TreeView.ItemContainerStyle>
 | 
				
			||||||
            <TreeView.ItemTemplate>
 | 
					            <TreeView.ItemTemplate>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,9 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Windows;
 | 
					using System.Windows;
 | 
				
			||||||
using System.Windows.Controls;
 | 
					using System.Windows.Controls;
 | 
				
			||||||
 | 
					using System.Windows.Input;
 | 
				
			||||||
 | 
					using System.Windows.Media;
 | 
				
			||||||
using RainmeterStudio.Core.Model;
 | 
					using RainmeterStudio.Core.Model;
 | 
				
			||||||
using RainmeterStudio.Core.Utils;
 | 
					using RainmeterStudio.Core.Utils;
 | 
				
			||||||
using RainmeterStudio.UI.Controller;
 | 
					using RainmeterStudio.UI.Controller;
 | 
				
			||||||
@@ -13,28 +16,31 @@ namespace RainmeterStudio.UI.Panels
 | 
				
			|||||||
    /// </summary>
 | 
					    /// </summary>
 | 
				
			||||||
    public partial class ProjectPanel : UserControl
 | 
					    public partial class ProjectPanel : UserControl
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        private ProjectController _controller;
 | 
					        private ProjectController _projectController;
 | 
				
			||||||
        public ProjectController Controller
 | 
					
 | 
				
			||||||
 | 
					        public ProjectController ProjectController
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            get
 | 
					            get
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return _controller;
 | 
					                return _projectController;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            set
 | 
					            set
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Unsubscribe from old controller
 | 
					                // Unsubscribe from old controller
 | 
				
			||||||
                if (_controller != null)
 | 
					                if (_projectController != null)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    Controller.ActiveProjectChanged -= Controller_ActiveProjectChanged;
 | 
					                    ProjectController.ActiveProjectChanged -= Controller_ActiveProjectChanged;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Set new project
 | 
					                // Set new project
 | 
				
			||||||
                _controller = value;
 | 
					                _projectController = value;
 | 
				
			||||||
                _controller.ActiveProjectChanged += Controller_ActiveProjectChanged;
 | 
					                _projectController.ActiveProjectChanged += Controller_ActiveProjectChanged;
 | 
				
			||||||
                Refresh();
 | 
					                Refresh();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public DocumentController DocumentController { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #region Commands
 | 
					        #region Commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public Command SyncWithActiveViewCommand { get; private set; }
 | 
					        public Command SyncWithActiveViewCommand { get; private set; }
 | 
				
			||||||
@@ -60,7 +66,7 @@ namespace RainmeterStudio.UI.Panels
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                if (selected == null)
 | 
					                if (selected == null)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    return Controller.ActiveProject.Root;
 | 
					                    return ProjectController.ActiveProject.Root;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@@ -85,7 +91,6 @@ namespace RainmeterStudio.UI.Panels
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        public ProjectPanel()
 | 
					        public ProjectPanel()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            InitializeComponent();
 | 
					            InitializeComponent();
 | 
				
			||||||
@@ -116,7 +121,7 @@ namespace RainmeterStudio.UI.Panels
 | 
				
			|||||||
            treeProjectItems.Items.Clear();
 | 
					            treeProjectItems.Items.Clear();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // No project
 | 
					            // No project
 | 
				
			||||||
            if (Controller == null || Controller.ActiveProject == null)
 | 
					            if (ProjectController == null || ProjectController.ActiveProject == null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                this.IsEnabled = false;
 | 
					                this.IsEnabled = false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@@ -130,14 +135,14 @@ namespace RainmeterStudio.UI.Panels
 | 
				
			|||||||
                if (toggleShowAllFiles.IsChecked.HasValue && toggleShowAllFiles.IsChecked.Value)
 | 
					                if (toggleShowAllFiles.IsChecked.HasValue && toggleShowAllFiles.IsChecked.Value)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    // Get directory name
 | 
					                    // Get directory name
 | 
				
			||||||
                    string projectFolder = System.IO.Path.GetDirectoryName(Controller.ActiveProjectPath);
 | 
					                    string projectFolder = System.IO.Path.GetDirectoryName(ProjectController.ActiveProjectPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // Get folder tree
 | 
					                    // Get folder tree
 | 
				
			||||||
                    refTree = DirectoryHelper.GetFolderTree(projectFolder);
 | 
					                    refTree = DirectoryHelper.GetFolderTree(projectFolder);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    refTree = Controller.ActiveProject.Root;
 | 
					                    refTree = ProjectController.ActiveProject.Root;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Add tree to tree view
 | 
					                // Add tree to tree view
 | 
				
			||||||
@@ -183,5 +188,106 @@ namespace RainmeterStudio.UI.Panels
 | 
				
			|||||||
            // We can expand if the root is not expanded
 | 
					            // We can expand if the root is not expanded
 | 
				
			||||||
            CanExpand = (!tree.IsExpanded);
 | 
					            CanExpand = (!tree.IsExpanded);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void TreeViewItem_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var treeViewItem = sender as TreeViewItem;
 | 
				
			||||||
 | 
					            var referenceViewModel = treeViewItem.Header as ReferenceViewModel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (referenceViewModel != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                treeViewItem.ContextMenu = new ContextMenu();
 | 
				
			||||||
 | 
					                treeViewItem.ContextMenu.ItemsSource = GetContextMenuItems(referenceViewModel.Reference);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private void TreeViewItem_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var treeViewItem = sender as TreeViewItem;
 | 
				
			||||||
 | 
					            var refViewModel = treeViewItem.Header as ReferenceViewModel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (refViewModel != null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                Command command = GetDefaultCommand(refViewModel.Reference);
 | 
				
			||||||
 | 
					                command.Execute(refViewModel.Reference);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets the default command (double click) for a specific reference
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="reference">The reference</param>
 | 
				
			||||||
 | 
					        /// <returns>The command</returns>
 | 
				
			||||||
 | 
					        public Command GetDefaultCommand(Reference reference)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            switch (reference.TargetKind)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                case ReferenceTargetKind.File:
 | 
				
			||||||
 | 
					                    return DocumentController.DocumentOpenCommand;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case ReferenceTargetKind.Project:
 | 
				
			||||||
 | 
					                    return DocumentController.DocumentOpenCommand;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case ReferenceTargetKind.Directory:
 | 
				
			||||||
 | 
					                    return null; // TODO: expand command
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                default:
 | 
				
			||||||
 | 
					                    return null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private MenuItem GetMenuItem(Command cmd, Reference reference)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var icon = new Image();
 | 
				
			||||||
 | 
					            icon.Source = cmd.Icon;
 | 
				
			||||||
 | 
					            icon.Width = 16;
 | 
				
			||||||
 | 
					            icon.Height = 16;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            var menuItem = new MenuItem();
 | 
				
			||||||
 | 
					            menuItem.DataContext = cmd;
 | 
				
			||||||
 | 
					            menuItem.Style = Application.Current.TryFindResource("CommandContextMenuItemStyle") as Style;
 | 
				
			||||||
 | 
					            menuItem.Icon = icon;
 | 
				
			||||||
 | 
					            menuItem.CommandParameter = reference;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (GetDefaultCommand(reference) == cmd)
 | 
				
			||||||
 | 
					                menuItem.FontWeight = FontWeights.Bold;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return menuItem;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public IEnumerable<UIElement> GetContextMenuItems(Reference @ref)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (@ref.TargetKind == ReferenceTargetKind.File || @ref.TargetKind == ReferenceTargetKind.Project)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                yield return GetMenuItem(DocumentController.DocumentOpenCommand, @ref);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (@ref.TargetKind == ReferenceTargetKind.Directory || @ref.TargetKind == ReferenceTargetKind.Project)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                // TODO: expand command
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            yield return new Separator();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (@ref.TargetKind != ReferenceTargetKind.Project)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                yield return GetMenuItem(ProjectController.ProjectItemCutCommand, @ref);
 | 
				
			||||||
 | 
					                yield return GetMenuItem(ProjectController.ProjectItemCopyCommand, @ref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (@ref.TargetKind == ReferenceTargetKind.Directory)
 | 
				
			||||||
 | 
					                    yield return GetMenuItem(ProjectController.ProjectItemPasteCommand, @ref);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            yield return GetMenuItem(ProjectController.ProjectItemRenameCommand, @ref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (@ref.TargetKind != ReferenceTargetKind.Project)
 | 
				
			||||||
 | 
					                yield return GetMenuItem(ProjectController.ProjectItemDeleteCommand, @ref);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            yield return new Separator();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (@ref.TargetKind == ReferenceTargetKind.Directory)
 | 
				
			||||||
 | 
					                yield return GetMenuItem(ProjectController.ProjectItemOpenInExplorerCommand, @ref);
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                yield return GetMenuItem(ProjectController.ProjectItemOpenContainingFolderCommand, @ref);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user