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:
		@@ -3,9 +3,14 @@ using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using System.Windows;
 | 
			
		||||
using System.Xml.Serialization;
 | 
			
		||||
using RainmeterStudio.Core.Model;
 | 
			
		||||
using RainmeterStudio.Core.Storage;
 | 
			
		||||
using RainmeterStudio.Core.Utils;
 | 
			
		||||
using RainmeterStudio.Editor.ProjectEditor;
 | 
			
		||||
using RainmeterStudio.Storage;
 | 
			
		||||
 | 
			
		||||
namespace RainmeterStudio.Business
 | 
			
		||||
{
 | 
			
		||||
@@ -20,11 +25,6 @@ namespace RainmeterStudio.Business
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public Project ActiveProject { get; protected set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets or sets the project storage
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        protected ProjectStorage Storage { get; set; }
 | 
			
		||||
 | 
			
		||||
        #endregion
 | 
			
		||||
 | 
			
		||||
        #region Events
 | 
			
		||||
@@ -42,9 +42,8 @@ namespace RainmeterStudio.Business
 | 
			
		||||
        /// Initializes the project manager
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="storage">Project storage</param>
 | 
			
		||||
        public ProjectManager(ProjectStorage storage)
 | 
			
		||||
        public ProjectManager()
 | 
			
		||||
        {
 | 
			
		||||
            Storage = storage;
 | 
			
		||||
            ActiveProject = null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -69,7 +68,10 @@ namespace RainmeterStudio.Business
 | 
			
		||||
            ActiveProject.Path = path;
 | 
			
		||||
 | 
			
		||||
            // Save to file
 | 
			
		||||
            Directory.CreateDirectory(Path.GetDirectoryName(path));
 | 
			
		||||
            string directory = Path.GetDirectoryName(path);
 | 
			
		||||
            if (!String.IsNullOrEmpty(directory))
 | 
			
		||||
                Directory.CreateDirectory(Path.GetDirectoryName(path));
 | 
			
		||||
            
 | 
			
		||||
            SaveActiveProject();
 | 
			
		||||
 | 
			
		||||
            // Raise event
 | 
			
		||||
@@ -81,14 +83,14 @@ namespace RainmeterStudio.Business
 | 
			
		||||
        /// Opens a project from disk
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <param name="path"></param>
 | 
			
		||||
        public void OpenProject(string path) 
 | 
			
		||||
        public void OpenProject(string path)
 | 
			
		||||
        {
 | 
			
		||||
            // If there is an opened project, close it
 | 
			
		||||
            if (ActiveProject != null)
 | 
			
		||||
                Close();
 | 
			
		||||
 | 
			
		||||
            // Open using storage
 | 
			
		||||
            ActiveProject = Storage.Read(path);
 | 
			
		||||
            ActiveProject = ProjectStorage.Read(path);
 | 
			
		||||
            ActiveProject.Path = path;
 | 
			
		||||
 | 
			
		||||
            // Raise event
 | 
			
		||||
@@ -106,13 +108,13 @@ namespace RainmeterStudio.Business
 | 
			
		||||
                throw new InvalidOperationException("Cannot save a project that is not opened.");
 | 
			
		||||
 | 
			
		||||
            // Save
 | 
			
		||||
            Storage.Write(ActiveProject);
 | 
			
		||||
            ProjectStorage.Write(ActiveProject);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Closes an opened project
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public void Close() 
 | 
			
		||||
        public void Close()
 | 
			
		||||
        {
 | 
			
		||||
            ActiveProject = null;
 | 
			
		||||
 | 
			
		||||
@@ -133,12 +135,245 @@ namespace RainmeterStudio.Business
 | 
			
		||||
        {
 | 
			
		||||
            _projectTemplates.Add(template);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Gets a list of existing project templates
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public IEnumerable<IProjectTemplate> ProjectTemplates { get { return _projectTemplates; } }
 | 
			
		||||
 | 
			
		||||
        #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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user