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:
parent
425d7d62f1
commit
7691a3c326
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user