mirror of
				https://github.com/chibicitiberiu/rainmeter-studio.git
				synced 2024-02-24 04:33:31 +00:00 
			
		
		
		
	Rewrote references
This commit is contained in:
		| @@ -4,6 +4,8 @@ using System.Linq; | ||||
| using System.Text; | ||||
| using System.Xml.Serialization; | ||||
| using RainmeterStudio.Core.Storage; | ||||
| using RainmeterStudio.Core.Utils; | ||||
| using Version = RainmeterStudio.Core.Utils.Version; | ||||
|  | ||||
| namespace RainmeterStudio.Core.Model | ||||
| { | ||||
| @@ -12,85 +14,114 @@ namespace RainmeterStudio.Core.Model | ||||
|     /// </summary> | ||||
|     public class Project | ||||
|     { | ||||
|         #region Private fields | ||||
|  | ||||
|         private string _name; | ||||
|         private string _path; | ||||
|          | ||||
|         #endregion | ||||
|  | ||||
|         #region Properties | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the name of the project | ||||
|         /// </summary> | ||||
|         [XmlElement(ElementName = "name", Order = 1)] | ||||
|         public string Name | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _name; | ||||
|                 return Root.Name; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 _name = value; | ||||
|  | ||||
|                 if (Root != null) | ||||
|                     Root.Data = new Reference(Name, Path); | ||||
|                 Root.Name = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the file path of this project | ||||
|         /// </summary> | ||||
|         [XmlIgnore] | ||||
|         public string Path | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _path; | ||||
|                 return Root.StoragePath; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 _path = value; | ||||
|  | ||||
|                 if (Root != null) | ||||
|                     Root.Data = new Reference(Name, Path); | ||||
|                 Root.StoragePath = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the author of the project | ||||
|         /// </summary> | ||||
|         [XmlElement(ElementName = "author", Order = 2)] | ||||
|         public string Author { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the version of the project | ||||
|         /// </summary> | ||||
|         [XmlElement(ElementName = "version", Order = 3)] | ||||
|         public Version Version { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the reference to the file to automatically load at package installation | ||||
|         /// Gets or sets the reference to the file that automatically loads at package installation | ||||
|         /// </summary> | ||||
|         [XmlIgnore] | ||||
|         public Reference AutoLoadFile { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the qualified name of the auto load file | ||||
|         /// </summary> | ||||
|         [XmlElement(ElementName = "autoLoadFile", Order = 7)] | ||||
|         public string AutoLoadFileQualifiedName | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return ((AutoLoadFile == null) ? null : AutoLoadFile.QualifiedName); | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 AutoLoadFile = Root.GetReference(value); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the list of variable files | ||||
|         /// </summary> | ||||
|         [XmlIgnore] | ||||
|         public List<Reference> VariableFiles { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the list of variable files qualified names | ||||
|         /// </summary> | ||||
|         [XmlArray(ElementName = "variableFiles", Order = 8)] | ||||
|         public string[] VariableFilesQualifiedNames | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return VariableFiles.Select(x => x.QualifiedName).ToArray(); | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 VariableFiles.Clear(); | ||||
|                 VariableFiles.AddRange(value.Select(x => Root.GetReference(x))); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the minimum rainmeter version | ||||
|         /// </summary> | ||||
|         [XmlElement(ElementName = "minimumRainmeter", Order = 4)] | ||||
|         public Version MinimumRainmeter { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the minimum Windows version | ||||
|         /// </summary> | ||||
|         [XmlElement(ElementName = "minimumWindows", Order = 5)] | ||||
|         public Version MinimumWindows { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the root node | ||||
|         /// </summary> | ||||
|         public Tree<Reference> Root { get; set; } | ||||
|         [XmlElement(ElementName = "root", Order = 6)] | ||||
|         public Reference Root { get; set; } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
| @@ -101,7 +132,7 @@ namespace RainmeterStudio.Core.Model | ||||
|         /// </summary> | ||||
|         public Project() | ||||
|         { | ||||
|             Root = new Tree<Reference>(); | ||||
|             Root = new Reference(String.Empty); | ||||
|             VariableFiles = new List<Reference>(); | ||||
|             Version = new Version(); | ||||
|             MinimumRainmeter = new Version("3.1"); | ||||
| @@ -109,5 +140,20 @@ namespace RainmeterStudio.Core.Model | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|  | ||||
|         #region Operations | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Looks for reference in project | ||||
|         /// </summary> | ||||
|         /// <param name="reference">Reference</param> | ||||
|         /// <returns>True if reference was found</returns> | ||||
|         public bool Contains(Reference reference) | ||||
|         { | ||||
|             return Root.TreeContains(reference); | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,90 +1,153 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.ObjectModel; | ||||
| using System.Collections.Specialized; | ||||
| using System.Diagnostics; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Xml.Serialization; | ||||
| using RainmeterStudio.Core.Utils; | ||||
|  | ||||
| namespace RainmeterStudio.Core.Model | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Reference to a file or folder | ||||
|     /// </summary> | ||||
|     [DebuggerDisplay("ProjectPath = {ProjectPath}, StoragePath = {StoragePath}")] | ||||
|     public struct Reference | ||||
|     [DebuggerDisplay("QualifiedName = {QualifiedName}, StoragePath = {StoragePath}")] | ||||
|     public class Reference : INotifyCollectionChanged | ||||
|     { | ||||
|         private string[] _projectPath; | ||||
|         private string _storagePath; | ||||
|         private Dictionary<string, Reference> _children; | ||||
|  | ||||
|         #region Properties | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the parent of this reference | ||||
|         /// </summary> | ||||
|         [XmlIgnore] | ||||
|         public Reference Parent { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the children references | ||||
|         /// </summary> | ||||
|         [XmlIgnore] | ||||
|         public ReadOnlyDictionary<string, Reference> ChildrenDictionary | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return new ReadOnlyDictionary<string,Reference>(_children); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets children | ||||
|         /// </summary> | ||||
|         [XmlArray("children")] | ||||
|         public Reference[] Children | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _children.Values.ToArray(); | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 Clear(); | ||||
|                 value.ForEach(Add); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the name of the reference | ||||
|         /// </summary> | ||||
|         [XmlAttribute("name")] | ||||
|         public string Name | ||||
|         { | ||||
|             get; set; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the full qualified name of this reference | ||||
|         /// </summary> | ||||
|         [XmlIgnore] | ||||
|         public string QualifiedName | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 // Try to get the last item from the project path | ||||
|                 if (_projectPath != null && _projectPath.Length > 0) | ||||
|                     return _projectPath[_projectPath.Length - 1]; | ||||
|                 if (Parent == null) | ||||
|                 { | ||||
|                     // Return name | ||||
|                     return Name; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // If it has a parent, get the parent's name | ||||
|                     return Parent.QualifiedName + '/' + Name; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|                 // None found, return null | ||||
|                 return null; | ||||
|         /// <summary> | ||||
|         /// Gets the parts of the full qualified name of this reference | ||||
|         /// </summary> | ||||
|         [XmlIgnore] | ||||
|         public IEnumerable<string> QualifiedParts | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 if (Parent == null) | ||||
|                 { | ||||
|                     return Enumerable.Repeat(Name, 1); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     return Parent.QualifiedParts.Append(Name); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the path to the file on the disk. If reference is in a project, the path should be relative. | ||||
|         /// </summary> | ||||
|         [XmlAttribute("storagePath")] | ||||
|         public string StoragePath | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _storagePath; | ||||
|             } | ||||
|             get; | ||||
|             set; | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         #region Constructors | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes the reference | ||||
|         /// </summary> | ||||
|         public Reference() | ||||
|             : this(null, null) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the qualified path | ||||
|         /// Initializes the reference | ||||
|         /// </summary> | ||||
|         public string ProjectPath | ||||
|         /// <param name="projectPath">Project path to item referenced</param> | ||||
|         public Reference(string name) | ||||
|             : this(name, null) | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 if (_projectPath != null) | ||||
|                 { | ||||
|                     return _projectPath.Aggregate(String.Empty, (a, b) => a + "/" + b); | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes the reference | ||||
|         /// </summary> | ||||
|         /// <param name="name">Name of reference</param> | ||||
|         /// <param name="path">Path to item referenced</param> | ||||
|         public Reference(string filePath, string projectPath = null) | ||||
|         /// <param name="storagePath">Path to item on disk</param> | ||||
|         public Reference(string name, string storagePath) | ||||
|         { | ||||
|             _storagePath = filePath; | ||||
|  | ||||
|             if (projectPath != null) | ||||
|             { | ||||
|                 _projectPath = projectPath.Split('/').Skip(1).ToArray(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 _projectPath = null; | ||||
|             } | ||||
|             StoragePath = storagePath; | ||||
|             Name = name; | ||||
|             _children = new Dictionary<string, Reference>(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Checks if the reference points to a project item | ||||
|         /// </summary> | ||||
|         public bool IsInProject() | ||||
|         { | ||||
|             return (_projectPath != null); | ||||
|         } | ||||
|         #endregion | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Checks if the reference has a file on disk | ||||
| @@ -92,7 +155,90 @@ namespace RainmeterStudio.Core.Model | ||||
|         /// <returns></returns> | ||||
|         public bool IsOnStorage() | ||||
|         { | ||||
|             return (_storagePath != null); | ||||
|             return (StoragePath != null); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a child reference | ||||
|         /// </summary> | ||||
|         /// <param name="reference"></param> | ||||
|         public void Add(Reference reference) | ||||
|         { | ||||
|             // Make sure object is not parented yet | ||||
|             if (reference.Parent != null) | ||||
|                 throw new ArgumentException("Reference must be removed from its current parent first."); | ||||
|  | ||||
|             // Add and parent | ||||
|             reference.Parent = this; | ||||
|             _children.Add(reference.Name, reference); | ||||
|  | ||||
|             // Trigger event | ||||
|             if (CollectionChanged != null) | ||||
|                 CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, reference)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Removes a reference | ||||
|         /// </summary> | ||||
|         /// <param name="reference">Reference to remove</param> | ||||
|         /// <returns>True if removed successfully</returns> | ||||
|         public bool Remove(Reference reference) | ||||
|         { | ||||
|             // Make sure we are the parent | ||||
|             if (reference.Parent != this) | ||||
|                 return false; | ||||
|  | ||||
|             // Remove | ||||
|             reference.Parent = null; | ||||
|             bool res = _children.Remove(reference.Name); | ||||
|  | ||||
|             // Trigger event | ||||
|             if (CollectionChanged != null) | ||||
|                 CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, reference)); | ||||
|  | ||||
|             return res; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Removes this reference from its parent | ||||
|         /// </summary> | ||||
|         /// <returns>True if unparented successfully</returns> | ||||
|         public bool Unparent() | ||||
|         { | ||||
|             if (Parent != null) | ||||
|                 return Parent.Remove(this); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Removes all children | ||||
|         /// </summary> | ||||
|         public void Clear() | ||||
|         { | ||||
|             // Unparent | ||||
|             foreach (var pair in _children) | ||||
|             { | ||||
|                 pair.Value.Parent = null; | ||||
|             } | ||||
|  | ||||
|             // Clear | ||||
|             _children.Clear(); | ||||
|  | ||||
|             // Trigger event | ||||
|             if (CollectionChanged != null) | ||||
|                 CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the number of children | ||||
|         /// </summary> | ||||
|         public int Count | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _children.Count; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
| @@ -105,14 +251,7 @@ namespace RainmeterStudio.Core.Model | ||||
|             if (obj is Reference) | ||||
|             { | ||||
|                 Reference other = (Reference)obj; | ||||
|  | ||||
|                 // 2 references are equal if they point to the same project item | ||||
|                 if (_projectPath != null && other._projectPath != null) | ||||
|                     return _projectPath.SequenceEqual(other._projectPath); | ||||
|  | ||||
|                 // If there is no project item, compare storage paths | ||||
|                 if (_projectPath == null && other._projectPath == null) | ||||
|                     return String.Equals(_storagePath, other._storagePath); | ||||
|                 return (String.Equals(QualifiedName, other.QualifiedName)); | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
| @@ -124,28 +263,114 @@ namespace RainmeterStudio.Core.Model | ||||
|         /// <returns>Hash code</returns> | ||||
|         public override int GetHashCode() | ||||
|         { | ||||
|             int hash = (_projectPath == null) ? 0 : _projectPath.GetHashCode(); | ||||
|  | ||||
|             if (_projectPath != null) | ||||
|             { | ||||
|                 foreach (var item in _projectPath) | ||||
|                     hash = hash * 7 + item.GetHashCode(); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 hash = hash * 2113 + ((_storagePath == null) ? 0 : _storagePath.GetHashCode()); | ||||
|             } | ||||
|  | ||||
|             return hash; | ||||
|             return QualifiedName.GetHashCode(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the string representation of this reference | ||||
|         /// </summary> | ||||
|         /// <returns></returns> | ||||
|         /// <returns>String representation</returns> | ||||
|         public override string ToString() | ||||
|         { | ||||
|             return ProjectPath; | ||||
|             return QualifiedName; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Triggered when children are added or removed. | ||||
|         /// </summary> | ||||
|         public event NotifyCollectionChangedEventHandler CollectionChanged; | ||||
|     } | ||||
|  | ||||
|     /// <summary> | ||||
|     /// Provides useful methods for references | ||||
|     /// </summary> | ||||
|     public static class ReferenceExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Tries to get a reference from the same tree having specified qualified name | ||||
|         /// </summary> | ||||
|         /// <param name="this">Reference contained in the tree</param> | ||||
|         /// <param name="qualifiedName">Full qualified name</param> | ||||
|         /// <param name="output">Found reference</param> | ||||
|         /// <returns>True if succeeded to find the reference</returns> | ||||
|         public static bool TryGetReference(this Reference @this, string qualifiedName, out Reference output) | ||||
|         { | ||||
|             var thisQualifiedName = @this.QualifiedName; | ||||
|  | ||||
|             // Am I the reference? return myself | ||||
|             if (qualifiedName.Equals(thisQualifiedName)) | ||||
|             { | ||||
|                 output = @this; | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // Qualified name is a child, look child up | ||||
|             else if (qualifiedName.StartsWith(thisQualifiedName)) | ||||
|             { | ||||
|                 int startIndex = thisQualifiedName.Length + 1; | ||||
|                 int endIndex = qualifiedName.IndexOf('/', startIndex); | ||||
|  | ||||
|                 string child; | ||||
|                 Reference childRef; | ||||
|  | ||||
|                 if (endIndex < 0) | ||||
|                 { | ||||
|                     child = qualifiedName.Substring(startIndex); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     child = qualifiedName.Substring(startIndex, endIndex - startIndex); | ||||
|                 } | ||||
|  | ||||
|                 // Try to get child | ||||
|                 if (@this.ChildrenDictionary.TryGetValue(child, out childRef)) | ||||
|                 { | ||||
|                     return childRef.TryGetReference(qualifiedName, out output); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Qualified name is not a child and not 'this', so ask parent to find it | ||||
|             else if (@this.Parent != null) | ||||
|             { | ||||
|                 return @this.Parent.TryGetReference(qualifiedName, out output); | ||||
|             } | ||||
|  | ||||
|             // Failed to find child | ||||
|             output = null; | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets a reference from the same tree having specified qualified name | ||||
|         /// </summary> | ||||
|         /// <param name="this">Reference contained in the tree</param> | ||||
|         /// <param name="qualifiedName">Full qualified name</param> | ||||
|         /// <returns>Found reference</returns> | ||||
|         /// <exception cref="ArgumentException">If qualified name not found</exception> | ||||
|         public static Reference GetReference(this Reference @this, string qualifiedName) | ||||
|         { | ||||
|             Reference res; | ||||
|  | ||||
|             if (TryGetReference(@this, qualifiedName, out res)) | ||||
|             { | ||||
|                 return res; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 throw new ArgumentException("Could not find reference."); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Checks if a reference is in the same tree as this | ||||
|         /// </summary> | ||||
|         /// <param name="this">Reference that is in the tree we search in</param> | ||||
|         /// <param name="other">Reference to search</param> | ||||
|         /// <returns>True if the tree contains the reference.</returns> | ||||
|         public static bool TreeContains(this Reference @this, Reference reference) | ||||
|         { | ||||
|             Reference temp; | ||||
|             return TryGetReference(@this, reference.QualifiedName, out temp); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -153,5 +153,10 @@ namespace RainmeterStudio.Core.Model | ||||
|         { | ||||
|             return Children.GetEnumerator(); | ||||
|         } | ||||
|  | ||||
|         public void TreeExpand(bool p) | ||||
|         { | ||||
|             throw new NotImplementedException(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -9,8 +9,9 @@ | ||||
|     <AppDesignerFolder>Properties</AppDesignerFolder> | ||||
|     <RootNamespace>RainmeterStudio.Core</RootNamespace> | ||||
|     <AssemblyName>RainmeterStudio.Core</AssemblyName> | ||||
|     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> | ||||
|     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | ||||
|     <FileAlignment>512</FileAlignment> | ||||
|     <TargetFrameworkProfile /> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||||
|     <DebugSymbols>true</DebugSymbols> | ||||
| @@ -21,6 +22,7 @@ | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <PlatformTarget>x86</PlatformTarget> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||||
|     <DebugType>pdbonly</DebugType> | ||||
| @@ -29,6 +31,7 @@ | ||||
|     <DefineConstants>TRACE</DefineConstants> | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <ItemGroup> | ||||
|     <Reference Include="PresentationCore" /> | ||||
| @@ -62,8 +65,6 @@ | ||||
|     <Compile Include="Model\Reference.cs" /> | ||||
|     <Compile Include="Model\Tree.cs" /> | ||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
|     <Compile Include="Storage\SerializableProject.cs" /> | ||||
|     <Compile Include="Storage\SerializableReference.cs" /> | ||||
|     <Compile Include="Storage\SerializableTree.cs" /> | ||||
|     <Compile Include="Utils\DirectoryHelper.cs" /> | ||||
|     <Compile Include="Utils\InputHelper.cs" /> | ||||
| @@ -71,6 +72,7 @@ | ||||
|     <Compile Include="Utils\BitmapHelper.cs" /> | ||||
|     <Compile Include="Utils\PathHelper.cs" /> | ||||
|     <Compile Include="Utils\TreeExtensions.cs" /> | ||||
|     <Compile Include="Utils\Version.cs" /> | ||||
|   </ItemGroup> | ||||
|   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | ||||
|   <!-- To modify your build process, add your task inside one of the targets below and uncomment it.  | ||||
|   | ||||
| @@ -1,212 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Xml.Serialization; | ||||
| using RainmeterStudio.Core.Model; | ||||
| using RainmeterStudio.Core.Utils; | ||||
|  | ||||
| namespace RainmeterStudio.Core.Storage | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Helper class to serialize or deserialize project objects | ||||
|     /// </summary> | ||||
|     public class SerializableProject | ||||
|     { | ||||
|         private Project _project; | ||||
|         private SerializableReference _autoLoadFile; | ||||
|         private List<SerializableReference> _variableFiles; | ||||
|         private SerializableTree<SerializableReference> _root; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the project | ||||
|         /// </summary> | ||||
|         [XmlIgnore] | ||||
|         public Project Project | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 _project.AutoLoadFile = _autoLoadFile.Reference; | ||||
|                 _project.VariableFiles = _variableFiles.Select(x => x.Reference).ToList(); | ||||
|                 _project.Root = _root.AsTree().TransformData(x => x.Reference); | ||||
|                 return _project; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 _project = value; | ||||
|                 UpdateSelf(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the project name | ||||
|         /// </summary> | ||||
|         [XmlElement("name")] | ||||
|         public string Name | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return Project.Name; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 Project.Name = value; | ||||
|                 UpdateSelf(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the project path | ||||
|         /// </summary> | ||||
|         [XmlIgnore] | ||||
|         public string Path | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return Project.Path; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 Project.Path = value; | ||||
|                 UpdateSelf(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the author of the project | ||||
|         /// </summary> | ||||
|         [XmlElement("author")] | ||||
|         public string Author | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return Project.Author; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 Project.Author = value; | ||||
|                 UpdateSelf(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the project version | ||||
|         /// </summary> | ||||
|         [XmlElement("version")] | ||||
|         public string Version | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return Project.Version.ToString(); | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 Project.Version = new Version(value); | ||||
|                 UpdateSelf(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the reference to the file to automatically load at package installation | ||||
|         /// </summary> | ||||
|         [XmlElement("autoLoadFile")] | ||||
|         public SerializableReference AutoLoadFile | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _autoLoadFile; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 _autoLoadFile = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the list of variable files | ||||
|         /// </summary> | ||||
|         [XmlArray("variableFiles")] | ||||
|         public List<SerializableReference> VariableFiles | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _variableFiles; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 _variableFiles = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the minimum rainmeter version | ||||
|         /// </summary> | ||||
|         public string MinimumRainmeter | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return Project.MinimumRainmeter.ToString(); | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 Project.MinimumRainmeter = new Version(value); | ||||
|                 UpdateSelf(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the minimum Windows version | ||||
|         /// </summary> | ||||
|         public string MinimumWindows | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return Project.MinimumWindows.ToString(); | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 Project.MinimumWindows = new Version(value); | ||||
|                 UpdateSelf(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the root node | ||||
|         /// </summary> | ||||
|         public SerializableTree<SerializableReference> Root | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _root; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 _root = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes the serializable project | ||||
|         /// </summary> | ||||
|         public SerializableProject() | ||||
|         { | ||||
|             Project = new Project(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes the serializable project | ||||
|         /// </summary> | ||||
|         /// <param name="project">Base project</param> | ||||
|         public SerializableProject(Project project) | ||||
|         { | ||||
|             Project = project; | ||||
|         } | ||||
|  | ||||
|         private void UpdateSelf() | ||||
|         { | ||||
|             _autoLoadFile = new SerializableReference(_project.AutoLoadFile); | ||||
|             _variableFiles = _project.VariableFiles.Select(x => new SerializableReference(x)).ToList(); | ||||
|             _root = _project.Root.TransformData(x => new SerializableReference(x)).AsSerializableTree(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,81 +0,0 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Xml.Serialization; | ||||
| using RainmeterStudio.Core.Model; | ||||
| using RainmeterStudio.Core.Utils; | ||||
|  | ||||
| namespace RainmeterStudio.Core.Storage | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a reference that can be serialized | ||||
|     /// </summary> | ||||
|     public class SerializableReference | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets or sets the name of the reference | ||||
|         /// </summary> | ||||
|         [XmlElement("storagePath")] | ||||
|         public string StoragePath | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 // Return only relative paths | ||||
|                 if (Path.IsPathRooted(Reference.StoragePath)) | ||||
|                 { | ||||
|                     return PathHelper.GetRelativePath(Reference.StoragePath); | ||||
|                 } | ||||
|  | ||||
|                 return Reference.StoragePath; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 Reference = new Reference(value, ProjectPath); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the path of the reference | ||||
|         /// </summary> | ||||
|         [XmlElement("projectPath")] | ||||
|         public string ProjectPath | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return Reference.ProjectPath; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 Reference = new Reference(StoragePath, value); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the (immutable) reference | ||||
|         /// </summary> | ||||
|         [XmlIgnore] | ||||
|         public Reference Reference | ||||
|         { | ||||
|             get; | ||||
|             set; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes this serializable reference | ||||
|         /// </summary> | ||||
|         public SerializableReference() | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes this serializable reference | ||||
|         /// </summary> | ||||
|         /// <param name="reference">Reference to use</param> | ||||
|         public SerializableReference(Reference reference) | ||||
|         { | ||||
|             Reference = reference; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -14,24 +14,23 @@ namespace RainmeterStudio.Core.Utils | ||||
|         /// </summary> | ||||
|         /// <param name="folder">Folder</param> | ||||
|         /// <returns>A tree</returns> | ||||
|         public static Tree<Reference> GetFolderTree(string folder) | ||||
|         public static Reference GetFolderTree(string folder) | ||||
|         { | ||||
|             // Build tree object | ||||
|             Reference reference = new Reference(Path.GetFileName(folder), folder); | ||||
|             Tree<Reference> tree = new Tree<Reference>(reference); | ||||
|  | ||||
|             Reference refTree = new Reference(Path.GetFileName(folder), folder); | ||||
|              | ||||
|             // Navigate folder structure | ||||
|             if (Directory.Exists(folder)) | ||||
|             { | ||||
|                 foreach (var item in Directory.EnumerateDirectories(folder) | ||||
|                     .Concat(Directory.EnumerateFiles(folder))) | ||||
|                 { | ||||
|                     tree.Add(GetFolderTree(item)); | ||||
|                     refTree.Add(GetFolderTree(item)); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Return tree | ||||
|             return tree; | ||||
|             return refTree; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|   | ||||
							
								
								
									
										435
									
								
								RainmeterStudio.Core/Utils/Version.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										435
									
								
								RainmeterStudio.Core/Utils/Version.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,435 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Globalization; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using System.Xml.Serialization; | ||||
|  | ||||
| namespace RainmeterStudio.Core.Utils | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Serializable version of the System.Version class. | ||||
|     /// </summary> | ||||
|     public class Version : ICloneable, IComparable | ||||
|     { | ||||
|         private int _major, _minor, _build, _revision; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the major. | ||||
|         /// </summary> | ||||
|         /// <value></value> | ||||
|         [XmlAttribute("major")] | ||||
|         public int Major | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _major; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 if (value < 0) | ||||
|                     throw new ArgumentOutOfRangeException("Major out of range."); | ||||
|  | ||||
|                 _major = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the minor. | ||||
|         /// </summary> | ||||
|         /// <value></value> | ||||
|         [XmlAttribute("minor")] | ||||
|         public int Minor | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _minor; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 if (value < -1) | ||||
|                     throw new ArgumentOutOfRangeException("Minor out of range."); | ||||
|  | ||||
|                 _minor = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the build. | ||||
|         /// </summary> | ||||
|         /// <value></value> | ||||
|         [XmlAttribute("build")] | ||||
|         public int Build | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _build; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 if (value < -1) | ||||
|                     throw new ArgumentOutOfRangeException("Build out of range."); | ||||
|  | ||||
|                 _build = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the revision. | ||||
|         /// </summary> | ||||
|         /// <value></value> | ||||
|         [XmlAttribute("revision")] | ||||
|         public int Revision | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _revision; | ||||
|             } | ||||
|             set | ||||
|             { | ||||
|                 if (value < -1) | ||||
|                     throw new ArgumentOutOfRangeException("Revision out of range."); | ||||
|  | ||||
|                 _revision = value; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a new instance of version. | ||||
|         /// </summary> | ||||
|         public Version() | ||||
|         { | ||||
|             Major = 1; | ||||
|             Minor = 0; | ||||
|             Revision = -1; | ||||
|             Build = -1; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a new instance of Version. | ||||
|         /// </summary> | ||||
|         /// <param name="version">Version string</param> | ||||
|         public Version(string version) | ||||
|         { | ||||
|             // Parse | ||||
|             int major, minor, revision, build; | ||||
|             Parse(version, out major, out minor, out build, out revision); | ||||
|  | ||||
|             // Commit | ||||
|             Major = major; | ||||
|             Minor = minor; | ||||
|             Build = build; | ||||
|             Revision = revision; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a new instance of Version. | ||||
|         /// </summary> | ||||
|         /// <param name="major">Major</param> | ||||
|         public Version(int major) | ||||
|             : this(major, -1, -1, -1) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a new instance of Version. | ||||
|         /// </summary> | ||||
|         /// <param name="major">Major</param> | ||||
|         /// <param name="minor">Minor</param> | ||||
|         public Version(int major, int minor) | ||||
|             : this(major, minor, -1, -1) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a new instance of Version. | ||||
|         /// </summary> | ||||
|         /// <param name="major">Major</param> | ||||
|         /// <param name="minor">Minor</param> | ||||
|         /// <param name="build">Build</param> | ||||
|         public Version(int major, int minor, int build) | ||||
|             : this(major, minor, build, -1) | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Creates a new instance of Version. | ||||
|         /// </summary> | ||||
|         /// <param name="major">Major</param> | ||||
|         /// <param name="minor">Minor</param> | ||||
|         /// <param name="build">Build</param> | ||||
|         /// <param name="revision">Revision</param> | ||||
|         public Version(int major, int minor, int build, int revision) | ||||
|         { | ||||
|             Major = major; | ||||
|             Minor = minor; | ||||
|             Build = build; | ||||
|             Revision = revision; | ||||
|         } | ||||
|  | ||||
|         #region ICloneable Members | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Clones this instance. | ||||
|         /// </summary> | ||||
|         /// <returns></returns> | ||||
|         public object Clone() | ||||
|         { | ||||
|             return new Version(Major, Minor, Build, Revision); | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         #region IComparable Members | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Compares to another object. | ||||
|         /// </summary> | ||||
|         /// <param name="obj">Other object</param> | ||||
|         /// <returns></returns> | ||||
|         public int CompareTo(object obj) | ||||
|         { | ||||
|             if (obj == null) | ||||
|             { | ||||
|                 return 1; | ||||
|             } | ||||
|  | ||||
|             Version version = obj as Version; | ||||
|  | ||||
|             if (version == null) | ||||
|             { | ||||
|                 throw new ArgumentException("Argument must be version"); | ||||
|             } | ||||
|  | ||||
|             if (Major != version.Major) | ||||
|             { | ||||
|                 return (Major - version.Major); | ||||
|             } | ||||
|             if (Minor != version.Minor) | ||||
|             { | ||||
|                 return (Minor - version.Minor); | ||||
|             } | ||||
|             if (Build != version.Build) | ||||
|             { | ||||
|                 return (Build - version.Build); | ||||
|             } | ||||
|             if (Revision != version.Revision) | ||||
|             { | ||||
|                 return (Revision - version.Revision); | ||||
|             } | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|         /// <summary> | ||||
|         /// Equalss the specified obj. | ||||
|         /// </summary> | ||||
|         /// <param name="obj">Obj.</param> | ||||
|         /// <returns></returns> | ||||
|         public override bool Equals(object obj) | ||||
|         { | ||||
|             Version version = obj as Version; | ||||
|  | ||||
|             if (version == null) | ||||
|             { | ||||
|                 return false; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 return this.CompareTo(obj) == 0; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the hash code. | ||||
|         /// </summary> | ||||
|         /// <returns></returns> | ||||
|         public override int GetHashCode() | ||||
|         { | ||||
|             int hash = Major; | ||||
|             hash = hash * 7 + Minor; | ||||
|             hash = hash * 7 + Build; | ||||
|             hash = hash * 7 + Revision; | ||||
|             return Revision; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Equals operator. | ||||
|         /// </summary> | ||||
|         /// <param name="v1">first object</param> | ||||
|         /// <param name="v2">second object</param> | ||||
|         /// <returns></returns> | ||||
|         public static bool operator ==(Version v1, Version v2) | ||||
|         { | ||||
|             return Object.Equals(v1, v2); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Not equals operator. | ||||
|         /// </summary> | ||||
|         /// <param name="v1">first object</param> | ||||
|         /// <param name="v2">second object</param> | ||||
|         /// <returns></returns> | ||||
|         public static bool operator !=(Version v1, Version v2) | ||||
|         { | ||||
|             return !Object.Equals(v1, v2); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Greater than operator. | ||||
|         /// </summary> | ||||
|         /// <param name="v1">first object</param> | ||||
|         /// <param name="v2">second object</param> | ||||
|         /// <returns></returns> | ||||
|         public static bool operator >(Version v1, Version v2) | ||||
|         { | ||||
|             return v1.CompareTo(v2) > 0; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Greater or equal than operator. | ||||
|         /// </summary> | ||||
|         /// <param name="v1">first object</param> | ||||
|         /// <param name="v2">second object</param> | ||||
|         /// <returns></returns> | ||||
|         public static bool operator >=(Version v1, Version v2) | ||||
|         { | ||||
|             return v1.CompareTo(v2) >= 0; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Less than operator. | ||||
|         /// </summary> | ||||
|         /// <param name="v1">first object</param> | ||||
|         /// <param name="v2">second object</param> | ||||
|         /// <returns></returns> | ||||
|         public static bool operator <(Version v1, Version v2) | ||||
|         { | ||||
|             return v1.CompareTo(v2) < 0; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Less or equal than operator. | ||||
|         /// </summary> | ||||
|         /// <param name="v1">first object</param> | ||||
|         /// <param name="v2">second object</param> | ||||
|         /// <returns></returns> | ||||
|         public static bool operator <=(Version v1, Version v2) | ||||
|         { | ||||
|             return v1.CompareTo(v2) <= 0; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Converts to string. | ||||
|         /// </summary> | ||||
|         /// <returns>String representation</returns> | ||||
|         public override string ToString() | ||||
|         { | ||||
|             StringBuilder builder = new StringBuilder(); | ||||
|  | ||||
|             builder.Append(Major); | ||||
|  | ||||
|             if (Minor >= 0) | ||||
|             { | ||||
|                 builder.Append('.'); | ||||
|                 builder.Append(Minor); | ||||
|  | ||||
|                 if (Build >= 0) | ||||
|                 { | ||||
|                     builder.Append('.'); | ||||
|                     builder.Append(Build); | ||||
|  | ||||
|                     if (Revision > 0) | ||||
|                     { | ||||
|                         builder.Append('.'); | ||||
|                         builder.Append(Revision); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return builder.ToString(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Converts to string. | ||||
|         /// </summary> | ||||
|         /// <param name="fieldCount">Field count</param> | ||||
|         /// <returns></returns> | ||||
|         public string ToString(int fieldCount) | ||||
|         { | ||||
|             StringBuilder builder = new StringBuilder(); | ||||
|  | ||||
|             if (fieldCount > 0) | ||||
|             { | ||||
|                 builder.Append(Major); | ||||
|  | ||||
|                 if (Minor >= 0 && fieldCount > 1) | ||||
|                 { | ||||
|                     builder.Append('.'); | ||||
|                     builder.Append(Minor); | ||||
|  | ||||
|                     if (Build >= 0 && fieldCount > 2) | ||||
|                     { | ||||
|                         builder.Append('.'); | ||||
|                         builder.Append(Build); | ||||
|  | ||||
|                         if (Revision > 0 && fieldCount > 3) | ||||
|                         { | ||||
|                             builder.Append('.'); | ||||
|                             builder.Append(Revision); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return builder.ToString(); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Parses a string | ||||
|         /// </summary> | ||||
|         /// <param name="value"></param> | ||||
|         private static void Parse(string value, out int major, out int minor, out int build, out int revision) | ||||
|         { | ||||
|             // Sanity check | ||||
|             if (value == null) | ||||
|             { | ||||
|                 throw new ArgumentNullException("version"); | ||||
|             } | ||||
|  | ||||
|             // Split into fields | ||||
|             string[] fields = value.Split('.'); | ||||
|  | ||||
|             major = 0; | ||||
|             minor = -1; | ||||
|             build = -1; | ||||
|             revision = -1; | ||||
|  | ||||
|             if (fields.Length > 4) | ||||
|             { | ||||
|                 throw new ArgumentException("Invalid version string."); | ||||
|             } | ||||
|             if (fields.Length > 3) | ||||
|             { | ||||
|                 revision = int.Parse(fields[3], CultureInfo.InvariantCulture); | ||||
|             } | ||||
|             if (fields.Length > 2) | ||||
|             { | ||||
|                 build = int.Parse(fields[2], CultureInfo.InvariantCulture); | ||||
|             } | ||||
|             if (fields.Length > 1) | ||||
|             { | ||||
|                 minor = int.Parse(fields[1], CultureInfo.InvariantCulture); | ||||
|             } | ||||
|             if (fields.Length > 0) | ||||
|             { | ||||
|                 major = int.Parse(fields[0], CultureInfo.InvariantCulture); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 throw new ArgumentException("Invalid version string."); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -9,8 +9,9 @@ | ||||
|     <AppDesignerFolder>Properties</AppDesignerFolder> | ||||
|     <RootNamespace>RainmeterStudio.Rainmeter</RootNamespace> | ||||
|     <AssemblyName>RainmeterStudio.Rainmeter</AssemblyName> | ||||
|     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> | ||||
|     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | ||||
|     <FileAlignment>512</FileAlignment> | ||||
|     <TargetFrameworkProfile /> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||||
|     <DebugSymbols>true</DebugSymbols> | ||||
| @@ -21,6 +22,7 @@ | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <PlatformTarget>x86</PlatformTarget> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||||
|     <DebugType>pdbonly</DebugType> | ||||
| @@ -29,6 +31,7 @@ | ||||
|     <DefineConstants>TRACE</DefineConstants> | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <ItemGroup> | ||||
|     <Reference Include="System" /> | ||||
|   | ||||
| @@ -9,8 +9,9 @@ | ||||
|     <AppDesignerFolder>Properties</AppDesignerFolder> | ||||
|     <RootNamespace>RainmeterStudio.SkinDesignerPlugin</RootNamespace> | ||||
|     <AssemblyName>RainmeterStudio.SkinDesignerPlugin</AssemblyName> | ||||
|     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> | ||||
|     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | ||||
|     <FileAlignment>512</FileAlignment> | ||||
|     <TargetFrameworkProfile /> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||||
|     <DebugSymbols>true</DebugSymbols> | ||||
| @@ -21,6 +22,7 @@ | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <PlatformTarget>x86</PlatformTarget> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||||
|     <DebugType>pdbonly</DebugType> | ||||
| @@ -29,6 +31,7 @@ | ||||
|     <DefineConstants>TRACE</DefineConstants> | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <ItemGroup> | ||||
|     <Reference Include="PresentationCore" /> | ||||
|   | ||||
							
								
								
									
										184
									
								
								RainmeterStudio.Tests/Model/ReferenceTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										184
									
								
								RainmeterStudio.Tests/Model/ReferenceTest.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,184 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.VisualStudio.TestTools.UnitTesting; | ||||
| using RainmeterStudio.Core.Model; | ||||
|  | ||||
| namespace RainmeterStudio.Tests.Model | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Tests the reference class | ||||
|     /// </summary> | ||||
|     [TestClass] | ||||
|     public class ReferenceTest | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Tests the constructors of the reference class | ||||
|         /// </summary> | ||||
|         [TestMethod] | ||||
|         public void ReferenceConstructorTest() | ||||
|         { | ||||
|             Reference root = new Reference("root", "D:\\Data\\Project"); | ||||
|             Reference file = new Reference("f ile__asdf.txt"); | ||||
|                          | ||||
|             // Test root | ||||
|             Assert.AreEqual("root", root.Name); | ||||
|             Assert.IsNull(root.Parent); | ||||
|             Assert.AreEqual("root", root.QualifiedName); | ||||
|             Assert.AreEqual("D:\\Data\\Project", root.StoragePath); | ||||
|             Assert.IsTrue(Enumerable.Repeat("root", 1).SequenceEqual(root.QualifiedParts)); | ||||
|              | ||||
|             // Test file | ||||
|             Assert.AreEqual("f ile__asdf.txt", file.Name); | ||||
|             Assert.IsNull(file.Parent); | ||||
|             Assert.AreEqual("f ile__asdf.txt", file.QualifiedName); | ||||
|             Assert.IsNull(file.StoragePath); | ||||
|             Assert.IsTrue(Enumerable.Repeat("f ile__asdf.txt", 1).SequenceEqual(file.QualifiedParts)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Tests parenting in the reference class | ||||
|         /// </summary> | ||||
|         [TestMethod] | ||||
|         public void ReferenceParentingTest() | ||||
|         { | ||||
|             Reference root = new Reference(String.Empty, "D:\\Data\\Project"); | ||||
|             Reference folder1 = new Reference("folder1"); | ||||
|             Reference folder2 = new Reference("folder 2"); | ||||
|             Reference file1 = new Reference("file1"); | ||||
|             Reference file2 = new Reference("file2.txt"); | ||||
|             Reference file3 = new Reference("file 3.png"); | ||||
|  | ||||
|             root.Add(folder1); | ||||
|             root.Add(file3); | ||||
|             folder1.Add(file1); | ||||
|             folder1.Add(folder2); | ||||
|             folder2.Add(file2); | ||||
|  | ||||
|             Assert.IsNull(root.Parent); | ||||
|             Assert.AreEqual(2, root.ChildrenDictionary.Count); | ||||
|             Assert.AreEqual(root, folder1.Parent); | ||||
|             Assert.AreEqual(root, file3.Parent); | ||||
|  | ||||
|             Assert.AreEqual(2, folder1.ChildrenDictionary.Count); | ||||
|             Assert.AreEqual(folder1, folder2.Parent); | ||||
|             Assert.AreEqual(folder1, file1.Parent); | ||||
|  | ||||
|             Assert.IsNotNull(folder2.Children.FirstOrDefault(x => x == file2)); | ||||
|  | ||||
|             // Unparent something | ||||
|             file3.Unparent(); | ||||
|             Assert.IsNull(file3.Parent); | ||||
|             Assert.IsNull(root.Children.FirstOrDefault(x => x == file3)); | ||||
|             Assert.AreEqual(1, root.ChildrenDictionary.Count); | ||||
|  | ||||
|             // Remove something | ||||
|             root.Remove(folder1); | ||||
|             Assert.IsNull(folder1.Parent); | ||||
|             Assert.AreEqual(0, root.ChildrenDictionary.Count); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Tests qualified names in the reference class | ||||
|         /// </summary> | ||||
|         [TestMethod] | ||||
|         public void ReferenceQualifiedNameTest() | ||||
|         { | ||||
|             Reference root = new Reference(String.Empty, "D:\\Data\\Project"); | ||||
|             Reference folder1 = new Reference("folder1"); | ||||
|             Reference folder2 = new Reference("folder 2"); | ||||
|             Reference file1 = new Reference("file1"); | ||||
|             Reference file2 = new Reference("file2.txt"); | ||||
|             Reference file3 = new Reference("file 3.png"); | ||||
|  | ||||
|             root.Add(folder1); | ||||
|             root.Add(file3); | ||||
|             folder1.Add(file1); | ||||
|             folder1.Add(folder2); | ||||
|             folder2.Add(file2); | ||||
|  | ||||
|             // Test qualified names | ||||
|             Assert.AreEqual(String.Empty, root.QualifiedName); | ||||
|             Assert.AreEqual("/folder1", folder1.QualifiedName); | ||||
|             Assert.AreEqual("/folder1/folder 2", folder2.QualifiedName); | ||||
|             Assert.AreEqual("/folder1/file1", file1.QualifiedName); | ||||
|             Assert.AreEqual("/folder1/folder 2/file2.txt", file2.QualifiedName); | ||||
|             Assert.AreEqual("/file 3.png", file3.QualifiedName); | ||||
|  | ||||
|             // Test qualified parts | ||||
|             Assert.IsTrue(new[] { String.Empty } | ||||
|                 .SequenceEqual(root.QualifiedParts)); | ||||
|  | ||||
|             Assert.IsTrue(new[] { String.Empty, "folder1" } | ||||
|                 .SequenceEqual(folder1.QualifiedParts)); | ||||
|  | ||||
|             Assert.IsTrue(new[] { String.Empty, "folder1", "folder 2" } | ||||
|                 .SequenceEqual(folder2.QualifiedParts)); | ||||
|  | ||||
|             Assert.IsTrue(new[] { String.Empty, "folder1", "file1" } | ||||
|                 .SequenceEqual(file1.QualifiedParts)); | ||||
|  | ||||
|             Assert.IsTrue(new[] { String.Empty, "folder1", "folder 2", "file2.txt" } | ||||
|                 .SequenceEqual(file2.QualifiedParts)); | ||||
|  | ||||
|             Assert.IsTrue(new[] { String.Empty, "file 3.png" } | ||||
|                 .SequenceEqual(file3.QualifiedParts)); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Tests the 'get reference' extension methods | ||||
|         /// </summary> | ||||
|         [TestMethod] | ||||
|         public void ReferenceGetReferenceTest() | ||||
|         { | ||||
|             Reference root = new Reference(String.Empty, "D:\\Data\\Project"); | ||||
|             Reference folder1 = new Reference("folder1"); | ||||
|             Reference folder2 = new Reference("folder 2"); | ||||
|             Reference file1 = new Reference("file1"); | ||||
|             Reference file2 = new Reference("file2.txt"); | ||||
|             Reference file3 = new Reference("file 3.png"); | ||||
|  | ||||
|             root.Add(folder1); | ||||
|             root.Add(file3); | ||||
|             folder1.Add(file1); | ||||
|             folder1.Add(folder2); | ||||
|             folder2.Add(file2); | ||||
|  | ||||
|             // Test 'get reference' method | ||||
|             Assert.AreEqual(root, root.GetReference("")); | ||||
|             Assert.AreEqual(folder2, root.GetReference("/folder1/folder 2")); | ||||
|             Assert.AreEqual(file3, file2.GetReference("/file 3.png")); | ||||
|             Assert.AreEqual(file2, file2.GetReference("/folder1/folder 2/file2.txt")); | ||||
|             Assert.AreEqual(file2, file3.GetReference("/folder1/folder 2/file2.txt")); | ||||
|  | ||||
|             try | ||||
|             { | ||||
|                 file3.GetReference("/file 3.png/some nonexistant file"); | ||||
|                 Assert.Fail(); | ||||
|             } | ||||
|             catch (ArgumentException) | ||||
|             { | ||||
|             } | ||||
|  | ||||
|             // Test 'try get reference' method | ||||
|             Reference res; | ||||
|  | ||||
|             Assert.IsTrue(root.TryGetReference("", out res)); | ||||
|             Assert.AreEqual(root, res); | ||||
|  | ||||
|             Assert.IsTrue(root.TryGetReference("/folder1/folder 2", out res)); | ||||
|             Assert.AreEqual(folder2, res); | ||||
|  | ||||
|             Assert.IsTrue(file2.TryGetReference("/file 3.png", out res)); | ||||
|             Assert.AreEqual(file3, res); | ||||
|  | ||||
|             Assert.IsTrue(file2.TryGetReference("/folder1/folder 2/file2.txt", out res)); | ||||
|             Assert.AreEqual(file2, res); | ||||
|  | ||||
|             Assert.IsTrue(file3.TryGetReference("/folder1/folder 2/file2.txt", out res)); | ||||
|             Assert.AreEqual(file2, res); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -8,7 +8,7 @@ | ||||
|     <AppDesignerFolder>Properties</AppDesignerFolder> | ||||
|     <RootNamespace>RainmeterStudio.Tests</RootNamespace> | ||||
|     <AssemblyName>RainmeterStudio.Tests</AssemblyName> | ||||
|     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> | ||||
|     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | ||||
|     <FileAlignment>512</FileAlignment> | ||||
|     <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> | ||||
|     <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion> | ||||
| @@ -16,6 +16,7 @@ | ||||
|     <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages</ReferencePath> | ||||
|     <IsCodedUITest>False</IsCodedUITest> | ||||
|     <TestProjectType>UnitTest</TestProjectType> | ||||
|     <TargetFrameworkProfile /> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||||
|     <DebugSymbols>true</DebugSymbols> | ||||
| @@ -26,6 +27,7 @@ | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <PlatformTarget>x86</PlatformTarget> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||||
|     <DebugType>pdbonly</DebugType> | ||||
| @@ -34,6 +36,7 @@ | ||||
|     <DefineConstants>TRACE</DefineConstants> | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <ItemGroup> | ||||
|     <Reference Include="System" /> | ||||
| @@ -54,6 +57,7 @@ | ||||
|     </Otherwise> | ||||
|   </Choose> | ||||
|   <ItemGroup> | ||||
|     <Compile Include="Model\ReferenceTest.cs" /> | ||||
|     <Compile Include="Storage\ProjectStorageTest.cs" /> | ||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
|   </ItemGroup> | ||||
|   | ||||
| @@ -6,6 +6,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; | ||||
| using RainmeterStudio.Storage; | ||||
| using System.IO; | ||||
| using RainmeterStudio.Core.Model; | ||||
| using Version = RainmeterStudio.Core.Utils.Version; | ||||
|  | ||||
| namespace RainmeterStudio.Tests.Storage | ||||
| { | ||||
| @@ -34,7 +35,7 @@ namespace RainmeterStudio.Tests.Storage | ||||
|             Project project = CreateProject(); | ||||
|  | ||||
|             // Save and load | ||||
|             ProjectStorage.Save(filename, project); | ||||
|             ProjectStorage.Save(project, filename); | ||||
|             Project res = ProjectStorage.Load(filename); | ||||
|  | ||||
|             // Verify results | ||||
| @@ -58,7 +59,7 @@ namespace RainmeterStudio.Tests.Storage | ||||
|             Project project = new Project(); | ||||
|  | ||||
|             // Save and load project | ||||
|             ProjectStorage.Save(filename, project); | ||||
|             ProjectStorage.Save(project, filename); | ||||
|             Project res = ProjectStorage.Load(filename); | ||||
|  | ||||
|             // Test results | ||||
| @@ -76,11 +77,11 @@ namespace RainmeterStudio.Tests.Storage | ||||
|         private Project CreateProject() | ||||
|         { | ||||
|             // Create some file references | ||||
|             Reference folder1 = new Reference("folder1"); | ||||
|             Reference folder2 = new Reference("folder2"); | ||||
|             Reference file1 = new Reference("file1.txt"); | ||||
|             Reference file2 = new Reference("file2.ini"); | ||||
|             Reference file3 = new Reference("file3.bmp"); | ||||
|             Reference folder1 = new Reference("folder1", "folder1"); | ||||
|             Reference folder2 = new Reference("folder2", "folder2"); | ||||
|             Reference file1 = new Reference("file1.txt", "folder1/file1.txt"); | ||||
|             Reference file2 = new Reference("file2.ini", "folder2/file2.ini"); | ||||
|             Reference file3 = new Reference("file3.bmp", "file3.bmp"); | ||||
|  | ||||
|             // Create a project | ||||
|             Project project = new Project(); | ||||
| @@ -96,8 +97,8 @@ namespace RainmeterStudio.Tests.Storage | ||||
|             // Set project references | ||||
|             project.Root.Add(folder1); | ||||
|             project.Root.Add(folder2); | ||||
|             project.Root[0].Add(file1); | ||||
|             project.Root[1].Add(file2); | ||||
|             folder1.Add(file1); | ||||
|             folder2.Add(file2); | ||||
|             project.Root.Add(file3); | ||||
|  | ||||
|             return project; | ||||
|   | ||||
| @@ -9,8 +9,9 @@ | ||||
|     <AppDesignerFolder>Properties</AppDesignerFolder> | ||||
|     <RootNamespace>RainmeterStudio.TextEditorPlugin</RootNamespace> | ||||
|     <AssemblyName>RainmeterStudio.TextEditorPlugin</AssemblyName> | ||||
|     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> | ||||
|     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | ||||
|     <FileAlignment>512</FileAlignment> | ||||
|     <TargetFrameworkProfile /> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | ||||
|     <DebugSymbols>true</DebugSymbols> | ||||
| @@ -21,6 +22,7 @@ | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <PlatformTarget>x86</PlatformTarget> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||||
|     <DebugType>pdbonly</DebugType> | ||||
| @@ -29,6 +31,7 @@ | ||||
|     <DefineConstants>TRACE</DefineConstants> | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <ItemGroup> | ||||
|     <Reference Include="PresentationCore" /> | ||||
|   | ||||
| @@ -100,7 +100,7 @@ namespace RainmeterStudio.Business | ||||
|                 throw new InvalidOperationException("Cannot save a project that is not opened."); | ||||
|  | ||||
|             // Save | ||||
|             Storage.Save(ActiveProject.Path, ActiveProject); | ||||
|             Storage.Save(ActiveProject); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
|     <AppDesignerFolder>Properties</AppDesignerFolder> | ||||
|     <RootNamespace>RainmeterStudio</RootNamespace> | ||||
|     <AssemblyName>RainmeterStudio</AssemblyName> | ||||
|     <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> | ||||
|     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> | ||||
|     <FileAlignment>512</FileAlignment> | ||||
|     <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
| @@ -24,6 +24,7 @@ | ||||
|     <DefineConstants>DEBUG;TRACE</DefineConstants> | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | ||||
|     <PlatformTarget>AnyCPU</PlatformTarget> | ||||
| @@ -33,6 +34,7 @@ | ||||
|     <DefineConstants>TRACE</DefineConstants> | ||||
|     <ErrorReport>prompt</ErrorReport> | ||||
|     <WarningLevel>4</WarningLevel> | ||||
|     <Prefer32Bit>false</Prefer32Bit> | ||||
|   </PropertyGroup> | ||||
|   <ItemGroup> | ||||
|     <Reference Include="System" /> | ||||
|   | ||||
| @@ -9,37 +9,61 @@ using RainmeterStudio.Core.Storage; | ||||
|  | ||||
| namespace RainmeterStudio.Storage | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Project storage, loads and saves project files | ||||
|     /// </summary> | ||||
|     public class ProjectStorage | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Loads a project from file | ||||
|         /// </summary> | ||||
|         /// <param name="path">Path to file to load</param> | ||||
|         /// <returns>Loaded project</returns> | ||||
|         public Project Load(string path) | ||||
|         { | ||||
|             // Open file | ||||
|             var file = File.OpenText(path); | ||||
|  | ||||
|             // Deserialize file | ||||
|             var serializer = new XmlSerializer(typeof(SerializableProject), new XmlRootAttribute("project")); | ||||
|             SerializableProject project = serializer.Deserialize(file) as SerializableProject; | ||||
|             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.Project; | ||||
|             return project; | ||||
|         } | ||||
|  | ||||
|         public void Save(string path, Project 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 Save(Project project, string path) | ||||
|         { | ||||
|             // Open file | ||||
|             var file = File.OpenWrite(path); | ||||
|  | ||||
|             // Serialize file | ||||
|             var sProject = new SerializableProject(project); | ||||
|             var serializer = new XmlSerializer(typeof(SerializableProject), new XmlRootAttribute("project")); | ||||
|             serializer.Serialize(file, sProject); | ||||
|             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 Save(Project project) | ||||
|         { | ||||
|             Save(project, project.Path); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -90,7 +90,7 @@ namespace RainmeterStudio.UI.Controller | ||||
|             // Set the reference | ||||
|             var name = dialog.SelectedName; | ||||
|  | ||||
|             string folder = OwnerWindow.ProjectPanel.ActiveItem.Data.StoragePath; | ||||
|             string folder = OwnerWindow.ProjectPanel.ActiveItem.StoragePath; | ||||
|             if (!Directory.Exists(folder)) | ||||
|                 folder = Path.GetDirectoryName(folder); | ||||
|  | ||||
|   | ||||
| @@ -32,12 +32,23 @@ namespace RainmeterStudio.UI.Controller | ||||
|             // Resource name | ||||
|             string key = "ProjectItem"; | ||||
|  | ||||
|             if (Directory.Exists(item.StoragePath)) | ||||
|             // Is a file? | ||||
|             if (File.Exists(item.StoragePath)) | ||||
|             { | ||||
|                 if (String.IsNullOrEmpty(Path.GetExtension(item.StoragePath))) | ||||
|                     key += "Unknown"; | ||||
|  | ||||
|                 else | ||||
|                     key += "_" + Path.GetExtension(item.StoragePath).Substring(1); | ||||
|             } | ||||
|  | ||||
|             // Not a file, try to figure out if a directory | ||||
|             else if (item.Count > 0 || Directory.Exists(item.StoragePath)) | ||||
|             { | ||||
|                 key += "Directory"; | ||||
|             } | ||||
|  | ||||
|             else if (File.Exists(item.StoragePath)) | ||||
|                 key += "_" + Path.GetExtension(item.StoragePath).Substring(1); | ||||
|  | ||||
|             // None | ||||
|             else key += "None"; | ||||
|  | ||||
|             // Get icon | ||||
|   | ||||
| @@ -13,6 +13,7 @@ using System.Windows.Navigation; | ||||
| using System.Windows.Shapes; | ||||
| using RainmeterStudio.Business; | ||||
| using RainmeterStudio.Core.Documents; | ||||
| using RainmeterStudio.Core.Model; | ||||
| using RainmeterStudio.Core.Model.Events; | ||||
| using RainmeterStudio.Storage; | ||||
| using RainmeterStudio.UI.Controller; | ||||
| @@ -70,22 +71,24 @@ namespace RainmeterStudio.UI | ||||
|             e.Document.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler((obj, args) => | ||||
|             { | ||||
|                 string documentName; | ||||
|  | ||||
|                 if (!e.Document.Reference.IsInProject()) | ||||
|                  | ||||
|                 // Get title | ||||
|                 if (!ProjectController.ActiveProject.Contains(e.Document.Reference)) | ||||
|                 { | ||||
|                     documentName = e.Document.Reference.StoragePath; | ||||
|  | ||||
|                     if (documentName == null) | ||||
|                         documentName = "New document"; | ||||
|                     documentName = e.Document.Reference.StoragePath ?? "New document"; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     documentName = e.Document.Reference.Name; | ||||
|                 } | ||||
|  | ||||
|                 // Is document dirty? Append star | ||||
|                 if (e.Document.IsDirty) | ||||
|                 { | ||||
|                     documentName += "*"; | ||||
|                 } | ||||
|  | ||||
|                 // Set document title | ||||
|                 document.Title = documentName; | ||||
|             }); | ||||
|         } | ||||
|   | ||||
| @@ -46,8 +46,8 @@ | ||||
|         <TreeView Grid.Row="2" Name="treeProjectItems"> | ||||
|             <TreeView.ItemContainerStyle> | ||||
|                 <Style TargetType="{x:Type TreeViewItem}"> | ||||
|                     <Setter Property="IsExpanded" Value="{Binding Data.IsExpanded, Mode=TwoWay}" /> | ||||
|                     <Setter Property="IsSelected" Value="{Binding Data.IsSelected, Mode=TwoWay}" /> | ||||
|                     <Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" /> | ||||
|                     <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> | ||||
|                     <EventSetter Event="Expanded" Handler="TreeViewItem_ExpandedOrCollapsed" /> | ||||
|                     <EventSetter Event="Collapsed" Handler="TreeViewItem_ExpandedOrCollapsed" /> | ||||
|                 </Style> | ||||
| @@ -55,8 +55,8 @@ | ||||
|             <TreeView.ItemTemplate> | ||||
|                 <HierarchicalDataTemplate ItemsSource="{Binding Children}"> | ||||
|                     <DockPanel LastChildFill="True"> | ||||
|                         <Image DockPanel.Dock="Left" Width="16" Height="16" Source="{Binding Data.Reference.Data, Converter={StaticResource IconConverter}}" /> | ||||
|                         <TextBlock Text="{Binding Data.Name}" /> | ||||
|                         <Image DockPanel.Dock="Left" Width="16" Height="16" Source="{Binding Reference, Converter={StaticResource IconConverter}}" /> | ||||
|                         <TextBlock Text="{Binding Name}" /> | ||||
|                     </DockPanel> | ||||
|                 </HierarchicalDataTemplate> | ||||
|             </TreeView.ItemTemplate> | ||||
|   | ||||
| @@ -67,7 +67,7 @@ namespace RainmeterStudio.UI.Panels | ||||
|         /// <summary> | ||||
|         /// Gets the selected tree view item | ||||
|         /// </summary> | ||||
|         public Tree<Reference> ActiveItem | ||||
|         public Reference ActiveItem | ||||
|         { | ||||
|             get | ||||
|             { | ||||
| @@ -136,57 +136,36 @@ namespace RainmeterStudio.UI.Panels | ||||
|                 this.IsEnabled = true; | ||||
|  | ||||
|                 // Get tree | ||||
|                 Tree<ReferenceViewModel> tree; | ||||
|                 Reference refTree; | ||||
|  | ||||
|                 if (toggleShowAllFiles.IsChecked.HasValue && toggleShowAllFiles.IsChecked.Value) | ||||
|                 { | ||||
|                     tree = GetAllFiles(); | ||||
|                     // Get directory name | ||||
|                     string projectFolder = System.IO.Path.GetDirectoryName(Controller.ActiveProjectPath); | ||||
|  | ||||
|                     // Get folder tree | ||||
|                     refTree = DirectoryHelper.GetFolderTree(projectFolder); | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     tree = GetProjectItems(); | ||||
|                     refTree = Controller.ActiveProject.Root; | ||||
|                 } | ||||
|  | ||||
|                 // Add tree to tree view | ||||
|                 treeProjectItems.Items.Clear(); | ||||
|                 treeProjectItems.Items.Add(tree); | ||||
|                 treeProjectItems.Items.Add(new ReferenceViewModel(refTree)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private Tree<ReferenceViewModel> GetAllFiles() | ||||
|         { | ||||
|             // Get directory name | ||||
|             string projectFolder = System.IO.Path.GetDirectoryName(Controller.ActiveProjectPath); | ||||
|  | ||||
|             // Get folder tree | ||||
|             Tree<Reference> refTree = DirectoryHelper.GetFolderTree(projectFolder); | ||||
|             refTree.Data = Controller.ActiveProject.Root.Data; | ||||
|  | ||||
|             // Remove the project file from the list | ||||
|             Tree<Reference> project = refTree.First(x => DirectoryHelper.PathsEqual(x.Data.StoragePath, Controller.ActiveProjectPath)); | ||||
|             refTree.Remove(project); | ||||
|  | ||||
|             // Transform to reference view model and return | ||||
|             return refTree.Transform<Reference, ReferenceViewModel>((node) => new Tree<ReferenceViewModel>(new ReferenceViewModel(node))); | ||||
|         } | ||||
|  | ||||
|         private Tree<ReferenceViewModel> GetProjectItems() | ||||
|         { | ||||
|             // Get project items | ||||
|             Tree<Reference> refTree = Controller.ActiveProject.Root; | ||||
|  | ||||
|             // Transform to reference view model and return | ||||
|             return refTree.Transform<Reference, ReferenceViewModel>((node) => new Tree<ReferenceViewModel>(new ReferenceViewModel(node))); | ||||
|         } | ||||
|  | ||||
|         private void ExpandAll() | ||||
|         { | ||||
|             // Get tree | ||||
|             var tree = treeProjectItems.Items[0] as Tree<ReferenceViewModel>; | ||||
|             var tree = treeProjectItems.Items[0] as ReferenceViewModel; | ||||
|             if (tree == null) | ||||
|                 return; | ||||
|  | ||||
|             // Expand all | ||||
|             tree.Apply((node) => node.Data.IsExpanded = true); | ||||
|             tree.TreeExpand(true); | ||||
|  | ||||
|             // Set can expand property | ||||
|             CanExpand = false; | ||||
| @@ -195,12 +174,12 @@ namespace RainmeterStudio.UI.Panels | ||||
|         private void CollapseAll() | ||||
|         { | ||||
|             // Get tree | ||||
|             var tree = treeProjectItems.Items[0] as Tree<ReferenceViewModel>; | ||||
|             var tree = treeProjectItems.Items[0] as ReferenceViewModel; | ||||
|             if (tree == null) | ||||
|                 return; | ||||
|  | ||||
|             // Expand all | ||||
|             tree.Apply((node) => node.Data.IsExpanded = false); | ||||
|             tree.TreeExpand(false); | ||||
|  | ||||
|             // Set can expand property | ||||
|             CanExpand = true; | ||||
| @@ -209,12 +188,12 @@ namespace RainmeterStudio.UI.Panels | ||||
|         void TreeViewItem_ExpandedOrCollapsed(object sender, RoutedEventArgs e) | ||||
|         { | ||||
|             // Get tree | ||||
|             var tree = treeProjectItems.Items[0] as Tree<ReferenceViewModel>; | ||||
|             var tree = treeProjectItems.Items[0] as ReferenceViewModel; | ||||
|             if (tree == null) | ||||
|                 return; | ||||
|              | ||||
|             // We can expand if the root is not expanded | ||||
|             CanExpand = (!tree.Data.IsExpanded); | ||||
|             CanExpand = (!tree.IsExpanded); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Collections.Specialized; | ||||
| using System.ComponentModel; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| @@ -10,14 +11,16 @@ namespace RainmeterStudio.UI.ViewModel | ||||
|     /// <summary> | ||||
|     /// Contains the view model of a reference | ||||
|     /// </summary> | ||||
|     public class ReferenceViewModel : INotifyPropertyChanged | ||||
|     public class ReferenceViewModel : INotifyPropertyChanged, INotifyCollectionChanged | ||||
|     { | ||||
|         private List<ReferenceViewModel> _children = null; | ||||
|  | ||||
|         #region Properties | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the linked reference | ||||
|         /// </summary> | ||||
|         public Tree<Reference> Reference { get; private set; } | ||||
|         public Reference Reference { get; private set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the name | ||||
| @@ -26,7 +29,7 @@ namespace RainmeterStudio.UI.ViewModel | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return Reference.Data.Name; | ||||
|                 return Reference.Name; | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -37,10 +40,20 @@ namespace RainmeterStudio.UI.ViewModel | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return Reference.Data.StoragePath; | ||||
|                 return Reference.StoragePath; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets an enumerable of this object's children | ||||
|         /// </summary> | ||||
|         public IEnumerable<ReferenceViewModel> Children | ||||
|         { | ||||
|             get | ||||
|             { | ||||
|                 return _children; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private bool _isExpanded = true; | ||||
|  | ||||
| @@ -101,11 +114,70 @@ namespace RainmeterStudio.UI.ViewModel | ||||
|         /// Creates a new instance of reference view model | ||||
|         /// </summary> | ||||
|         /// <param name="reference">Reference</param> | ||||
|         public ReferenceViewModel(Tree<Reference> reference) | ||||
|         public ReferenceViewModel(Reference reference) | ||||
|         { | ||||
|             Reference = reference; | ||||
|             Reference.CollectionChanged += Reference_CollectionChanged; | ||||
|             UpdateChildren(); | ||||
|         } | ||||
|  | ||||
|         void Reference_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) | ||||
|         { | ||||
|             List<ReferenceViewModel> newItems = new List<ReferenceViewModel>(); | ||||
|             List<ReferenceViewModel> oldItems = new List<ReferenceViewModel>(); | ||||
|  | ||||
|             // Update collection | ||||
|             switch (e.Action) | ||||
|             { | ||||
|                 case NotifyCollectionChangedAction.Add: | ||||
|                     newItems = e.NewItems.Cast<Reference>().Select(x => new ReferenceViewModel(x)).ToList(); | ||||
|                     break; | ||||
|  | ||||
|                 case NotifyCollectionChangedAction.Remove: | ||||
|                     oldItems = _children.Where(x => e.OldItems.Contains(x.Reference)).ToList(); | ||||
|                     break; | ||||
|  | ||||
|                 case NotifyCollectionChangedAction.Replace: | ||||
|                     newItems = e.NewItems.Cast<Reference>().Select(x => new ReferenceViewModel(x)).ToList(); | ||||
|                     oldItems = _children.Where(x => e.OldItems.Contains(x.Reference)).ToList(); | ||||
|                     break; | ||||
|  | ||||
|                 default: | ||||
|                     UpdateChildren(); | ||||
|                     break; | ||||
|             } | ||||
|  | ||||
|             _children.RemoveAll(oldItems.Contains); | ||||
|             _children.AddRange(newItems); | ||||
|  | ||||
|             // Pass event | ||||
|             if (CollectionChanged != null) | ||||
|                 CollectionChanged(this, new NotifyCollectionChangedEventArgs(e.Action, newItems, oldItems)); | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         #region Operations | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets the 'IsExpanded' property for the entire subtree | ||||
|         /// </summary> | ||||
|         /// <param name="value">Value to set</param> | ||||
|         public void TreeExpand(bool value) | ||||
|         { | ||||
|             IsExpanded = value; | ||||
|         } | ||||
|  | ||||
|         private void UpdateChildren() | ||||
|         { | ||||
|             _children = Reference.Children.Select(x => new ReferenceViewModel(x)).ToList(); | ||||
|         } | ||||
|  | ||||
|         #endregion | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Triggered when the linked reference collection changes | ||||
|         /// </summary> | ||||
|         public event NotifyCollectionChangedEventHandler CollectionChanged; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,17 +1,16 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <configuration> | ||||
| <configSections> | ||||
|     <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > | ||||
|         <section name="RainmeterStudio.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" /> | ||||
|     <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> | ||||
|         <section name="RainmeterStudio.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/> | ||||
|     </sectionGroup> | ||||
| </configSections> | ||||
| <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup><userSettings> | ||||
| <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup><userSettings> | ||||
|         <RainmeterStudio.Properties.Settings> | ||||
|             <setting name="Command_ProjectCreateCommand_Shortcut" serializeAs="String"> | ||||
|                 <value>Ctrl+Shift+N</value> | ||||
|             </setting> | ||||
|             <setting name="Command_ProjectPanel_RefreshCommand_Shortcut" | ||||
|                 serializeAs="String"> | ||||
|             <setting name="Command_ProjectPanel_RefreshCommand_Shortcut" serializeAs="String"> | ||||
|                 <value>F5</value> | ||||
|             </setting> | ||||
|             <setting name="Command_DocumentCreateCommand_Shortcut" serializeAs="String"> | ||||
| @@ -39,10 +38,10 @@ | ||||
|                 <value>10</value> | ||||
|             </setting> | ||||
|             <setting name="CreateProjectDialog_RecentLocations" serializeAs="String"> | ||||
|                 <value /> | ||||
|                 <value/> | ||||
|             </setting> | ||||
|             <setting name="Project_SavedLocation" serializeAs="String"> | ||||
|                 <value /> | ||||
|                 <value/> | ||||
|             </setting> | ||||
|             <setting name="CreateProjectDialog_CreateDirectoryCheckbox" serializeAs="String"> | ||||
|                 <value>True</value> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user