Added INotifyPropertyChanged interface and target kind to reference.

This commit is contained in:
Tiberiu Chibici 2014-09-12 18:22:24 +03:00
parent f0071e552f
commit 0090059531
7 changed files with 204 additions and 51 deletions

View File

@ -223,7 +223,7 @@ namespace RainmeterStudio.Core.Model
/// </summary> /// </summary>
public Project() public Project()
{ {
Root = new Reference(String.Empty); Root = new Reference(String.Empty, Reference.ReferenceTargetKind.Project);
VariableFiles = new ObservableCollection<Reference>(); VariableFiles = new ObservableCollection<Reference>();
Version = new Version(); Version = new Version();
MinimumRainmeter = new Version("3.1"); MinimumRainmeter = new Version("3.1");

View File

@ -2,7 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Xml.Serialization; using System.Xml.Serialization;
@ -14,9 +16,52 @@ namespace RainmeterStudio.Core.Model
/// Reference to a file or folder /// Reference to a file or folder
/// </summary> /// </summary>
[DebuggerDisplay("QualifiedName = {QualifiedName}, StoragePath = {StoragePath}")] [DebuggerDisplay("QualifiedName = {QualifiedName}, StoragePath = {StoragePath}")]
public class Reference : INotifyCollectionChanged public class Reference : INotifyCollectionChanged, INotifyPropertyChanged
{ {
/// <summary>
/// The kind of item the reference points to
/// </summary>
public enum ReferenceTargetKind
{
/// <summary>
/// Invalid state
/// </summary>
None,
/// <summary>
/// Reference points to a file
/// </summary>
File,
/// <summary>
/// Reference points to a directory
/// </summary>
Directory,
/// <summary>
/// Reference points to a project
/// </summary>
Project
}
private Dictionary<string, Reference> _children; private Dictionary<string, Reference> _children;
private Reference _parent;
private string _name, _storagePath;
private ReferenceTargetKind _kind;
#region Events
/// <summary>
/// Triggered when children are added or removed.
/// </summary>
public event NotifyCollectionChangedEventHandler CollectionChanged;
/// <summary>
/// Triggered when a property changes its value
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Properties #region Properties
@ -24,7 +69,30 @@ namespace RainmeterStudio.Core.Model
/// Gets or sets the parent of this reference /// Gets or sets the parent of this reference
/// </summary> /// </summary>
[XmlIgnore] [XmlIgnore]
public Reference Parent { get; set; } public Reference Parent
{
get
{
return _parent;
}
set
{
// Unsubscribe from old parent
if (_parent != null)
_parent.PropertyChanged -= Parent_PropertyChanged;
// Set new parent
_parent = value;
// Subscribe to new parent
if (_parent != null)
_parent.PropertyChanged += Parent_PropertyChanged;
// Notify
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Parent"));
}
}
/// <summary> /// <summary>
/// Gets the children references /// Gets the children references
@ -34,7 +102,7 @@ namespace RainmeterStudio.Core.Model
{ {
get get
{ {
return new ReadOnlyDictionary<string,Reference>(_children); return new ReadOnlyDictionary<string, Reference>(_children);
} }
} }
@ -61,7 +129,17 @@ namespace RainmeterStudio.Core.Model
[XmlAttribute("name")] [XmlAttribute("name")]
public string Name public string Name
{ {
get; set; get
{
return _name;
}
set
{
_name = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
} }
/// <summary> /// <summary>
@ -110,8 +188,33 @@ namespace RainmeterStudio.Core.Model
[XmlAttribute("storagePath")] [XmlAttribute("storagePath")]
public string StoragePath public string StoragePath
{ {
get; get
set; {
return _storagePath;
}
set
{
_storagePath = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("StoragePath"));
}
}
[XmlAttribute("targetKind")]
public ReferenceTargetKind TargetKind
{
get
{
return _kind;
}
set
{
_kind = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Kind"));
}
} }
#endregion #endregion
@ -119,19 +222,31 @@ namespace RainmeterStudio.Core.Model
#region Constructors #region Constructors
/// <summary> /// <summary>
/// Initializes the reference /// Initializes the reference as a file reference
/// </summary> /// </summary>
public Reference() public Reference()
: this(null, null) : this(null, null, ReferenceTargetKind.File)
{ {
} }
/// <summary> /// <summary>
/// Initializes the reference /// Initializes the reference
/// </summary> /// </summary>
/// <param name="projectPath">Project path to item referenced</param> /// <param name="name">Name of this reference</param>
public Reference(string name) /// <param name="kind">Reference kind</param>
: this(name, null) public Reference(string name, ReferenceTargetKind kind)
: this(name, null, kind)
{
}
/// <summary>
/// Initializes the reference.
/// Kind is inferred by testing the file on disk.
/// </summary>
/// <param name="name">Name of reference</param>
/// <param name="storagePath">Path to item on disk</param>
public Reference(string name, string storagePath)
: this(name, storagePath, InferKind(storagePath))
{ {
} }
@ -140,24 +255,37 @@ namespace RainmeterStudio.Core.Model
/// </summary> /// </summary>
/// <param name="name">Name of reference</param> /// <param name="name">Name of reference</param>
/// <param name="storagePath">Path to item on disk</param> /// <param name="storagePath">Path to item on disk</param>
public Reference(string name, string storagePath) /// <param name="kind">Reference kind</param>
public Reference(string name, string storagePath, ReferenceTargetKind kind)
{ {
StoragePath = storagePath; StoragePath = storagePath;
Name = name; Name = name;
TargetKind = kind;
_children = new Dictionary<string, Reference>(); _children = new Dictionary<string, Reference>();
} }
#endregion #endregion
#region Exists
/// <summary> /// <summary>
/// Checks if the reference has a file on disk /// Checks if the file exists
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public bool IsOnStorage() public bool ExistsOnStorage()
{ {
return (StoragePath != null); if (StoragePath != null)
{
return File.Exists(StoragePath) || Directory.Exists(StoragePath);
} }
return false;
}
#endregion
#region Children/parenting operations
/// <summary> /// <summary>
/// Adds a child reference /// Adds a child reference
/// </summary> /// </summary>
@ -241,6 +369,16 @@ namespace RainmeterStudio.Core.Model
} }
} }
private void Parent_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (PropertyChanged != null && (e.PropertyName == "Parent" || e.PropertyName == "Name" || e.PropertyName == "QualifiedName"))
PropertyChanged(this, new PropertyChangedEventArgs("QualifiedName"));
}
#endregion
#region Object overrides
/// <summary> /// <summary>
/// Compares a reference to another objects /// Compares a reference to another objects
/// </summary> /// </summary>
@ -275,10 +413,27 @@ namespace RainmeterStudio.Core.Model
return QualifiedName; return QualifiedName;
} }
/// <summary> #endregion
/// Triggered when children are added or removed.
/// </summary> #region Helper methods
public event NotifyCollectionChangedEventHandler CollectionChanged;
private static ReferenceTargetKind InferKind(string storagePath)
{
ReferenceTargetKind kind = ReferenceTargetKind.None;
if (Path.GetExtension(storagePath) == ".rsproj")
kind = ReferenceTargetKind.Project;
else if (File.Exists(storagePath))
kind = ReferenceTargetKind.File;
else if (Directory.Exists(storagePath))
kind = ReferenceTargetKind.Directory;
return kind;
}
#endregion
} }
/// <summary> /// <summary>

View File

@ -20,8 +20,8 @@ namespace RainmeterStudio.Tests.Model
[TestMethod] [TestMethod]
public void ReferenceConstructorTest() public void ReferenceConstructorTest()
{ {
Reference root = new Reference("root", "D:\\Data\\Project"); Reference root = new Reference("root", "D:\\Data\\Project", Reference.ReferenceTargetKind.Directory);
Reference file = new Reference("f ile__asdf.txt"); Reference file = new Reference("f ile__asdf.txt", Reference.ReferenceTargetKind.File);
// Test root // Test root
Assert.AreEqual("root", root.Name); Assert.AreEqual("root", root.Name);
@ -45,11 +45,11 @@ namespace RainmeterStudio.Tests.Model
public void ReferenceParentingTest() public void ReferenceParentingTest()
{ {
Reference root = new Reference(String.Empty, "D:\\Data\\Project"); Reference root = new Reference(String.Empty, "D:\\Data\\Project");
Reference folder1 = new Reference("folder1"); Reference folder1 = new Reference("folder1", Reference.ReferenceTargetKind.Directory);
Reference folder2 = new Reference("folder 2"); Reference folder2 = new Reference("folder 2", Reference.ReferenceTargetKind.Directory);
Reference file1 = new Reference("file1"); Reference file1 = new Reference("file1", Reference.ReferenceTargetKind.File);
Reference file2 = new Reference("file2.txt"); Reference file2 = new Reference("file2.txt", Reference.ReferenceTargetKind.File);
Reference file3 = new Reference("file 3.png"); Reference file3 = new Reference("file 3.png", Reference.ReferenceTargetKind.File);
root.Add(folder1); root.Add(folder1);
root.Add(file3); root.Add(file3);
@ -87,11 +87,11 @@ namespace RainmeterStudio.Tests.Model
public void ReferenceQualifiedNameTest() public void ReferenceQualifiedNameTest()
{ {
Reference root = new Reference(String.Empty, "D:\\Data\\Project"); Reference root = new Reference(String.Empty, "D:\\Data\\Project");
Reference folder1 = new Reference("folder1"); Reference folder1 = new Reference("folder1", Reference.ReferenceTargetKind.Directory);
Reference folder2 = new Reference("folder 2"); Reference folder2 = new Reference("folder 2", Reference.ReferenceTargetKind.Directory);
Reference file1 = new Reference("file1"); Reference file1 = new Reference("file1", Reference.ReferenceTargetKind.File);
Reference file2 = new Reference("file2.txt"); Reference file2 = new Reference("file2.txt", Reference.ReferenceTargetKind.File);
Reference file3 = new Reference("file 3.png"); Reference file3 = new Reference("file 3.png", Reference.ReferenceTargetKind.File);
root.Add(folder1); root.Add(folder1);
root.Add(file3); root.Add(file3);
@ -134,11 +134,11 @@ namespace RainmeterStudio.Tests.Model
public void ReferenceGetReferenceTest() public void ReferenceGetReferenceTest()
{ {
Reference root = new Reference(String.Empty, "D:\\Data\\Project"); Reference root = new Reference(String.Empty, "D:\\Data\\Project");
Reference folder1 = new Reference("folder1"); Reference folder1 = new Reference("folder1", Reference.ReferenceTargetKind.Directory);
Reference folder2 = new Reference("folder 2"); Reference folder2 = new Reference("folder 2", Reference.ReferenceTargetKind.Directory);
Reference file1 = new Reference("file1"); Reference file1 = new Reference("file1", Reference.ReferenceTargetKind.File);
Reference file2 = new Reference("file2.txt"); Reference file2 = new Reference("file2.txt", Reference.ReferenceTargetKind.File);
Reference file3 = new Reference("file 3.png"); Reference file3 = new Reference("file 3.png", Reference.ReferenceTargetKind.File);
root.Add(folder1); root.Add(folder1);
root.Add(file3); root.Add(file3);

View File

@ -98,10 +98,12 @@
</Compile> </Compile>
<Compile Include="Editor\ProjectEditor\ProjectStorage.cs" /> <Compile Include="Editor\ProjectEditor\ProjectStorage.cs" />
<Compile Include="UI\Command.cs" /> <Compile Include="UI\Command.cs" />
<Compile Include="UI\CommandGroup.cs" />
<Compile Include="UI\Controller\IconProvider.cs" /> <Compile Include="UI\Controller\IconProvider.cs" />
<Compile Include="UI\Controller\IContextMenuProvider.cs" /> <Compile Include="UI\Controller\IContextMenuProvider.cs" />
<Compile Include="UI\Controller\ProjectController.cs" /> <Compile Include="UI\Controller\ProjectController.cs" />
<Compile Include="Business\SettingsProvider.cs" /> <Compile Include="Business\SettingsProvider.cs" />
<Compile Include="UI\Controller\ReferenceContextMenuProvider.cs" />
<Compile Include="UI\Dialogs\CloseUnsavedDialog.xaml.cs"> <Compile Include="UI\Dialogs\CloseUnsavedDialog.xaml.cs">
<DependentUpon>CloseUnsavedDialog.xaml</DependentUpon> <DependentUpon>CloseUnsavedDialog.xaml</DependentUpon>
</Compile> </Compile>

View File

@ -210,7 +210,7 @@ namespace RainmeterStudio.UI.Controller
/// </summary> /// </summary>
public bool Save(IDocumentEditor editor) public bool Save(IDocumentEditor editor)
{ {
if (editor.AttachedDocument.Reference.IsOnStorage()) if (editor.AttachedDocument.Reference != null)
{ {
DocumentManager.Save(editor.AttachedDocument); DocumentManager.Save(editor.AttachedDocument);
return true; return true;

View File

@ -33,7 +33,7 @@ namespace RainmeterStudio.UI.Controller
string key = "ProjectItem"; string key = "ProjectItem";
// Is a file? // Is a file?
if (File.Exists(item.StoragePath)) if (item.TargetKind == Reference.ReferenceTargetKind.File || item.TargetKind == Reference.ReferenceTargetKind.Project)
{ {
if (String.IsNullOrEmpty(Path.GetExtension(item.StoragePath))) if (String.IsNullOrEmpty(Path.GetExtension(item.StoragePath)))
key += "Unknown"; key += "Unknown";
@ -43,7 +43,7 @@ namespace RainmeterStudio.UI.Controller
} }
// Not a file, try to figure out if a directory // Not a file, try to figure out if a directory
else if (item.Count > 0 || Directory.Exists(item.StoragePath)) else if (item.TargetKind == Reference.ReferenceTargetKind.Directory)
{ {
key += "Directory"; key += "Directory";
} }

View File

@ -35,17 +35,6 @@ namespace RainmeterStudio.UI.ViewModel
} }
} }
/// <summary>
/// Gets or sets the path
/// </summary>
public string Path
{
get
{
return Reference.StoragePath;
}
}
/// <summary> /// <summary>
/// Gets an enumerable of this object's children /// Gets an enumerable of this object's children
/// </summary> /// </summary>
@ -120,9 +109,16 @@ namespace RainmeterStudio.UI.ViewModel
{ {
Reference = reference; Reference = reference;
Reference.CollectionChanged += Reference_CollectionChanged; Reference.CollectionChanged += Reference_CollectionChanged;
Reference.PropertyChanged += Reference_PropertyChanged;
RefreshChildren(); RefreshChildren();
} }
private void Reference_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Name" && PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
private void Reference_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) private void Reference_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{ {
List<ReferenceViewModel> newItems = new List<ReferenceViewModel>(); List<ReferenceViewModel> newItems = new List<ReferenceViewModel>();