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>
public Project()
{
Root = new Reference(String.Empty);
Root = new Reference(String.Empty, Reference.ReferenceTargetKind.Project);
VariableFiles = new ObservableCollection<Reference>();
Version = new Version();
MinimumRainmeter = new Version("3.1");

View File

@ -2,7 +2,9 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
@ -14,9 +16,52 @@ namespace RainmeterStudio.Core.Model
/// Reference to a file or folder
/// </summary>
[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 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
@ -24,7 +69,30 @@ namespace RainmeterStudio.Core.Model
/// Gets or sets the parent of this reference
/// </summary>
[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>
/// Gets the children references
@ -61,7 +129,17 @@ namespace RainmeterStudio.Core.Model
[XmlAttribute("name")]
public string Name
{
get; set;
get
{
return _name;
}
set
{
_name = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
/// <summary>
@ -110,8 +188,33 @@ namespace RainmeterStudio.Core.Model
[XmlAttribute("storagePath")]
public string StoragePath
{
get;
set;
get
{
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
@ -119,19 +222,31 @@ namespace RainmeterStudio.Core.Model
#region Constructors
/// <summary>
/// Initializes the reference
/// Initializes the reference as a file reference
/// </summary>
public Reference()
: this(null, null)
: this(null, null, ReferenceTargetKind.File)
{
}
/// <summary>
/// Initializes the reference
/// </summary>
/// <param name="projectPath">Project path to item referenced</param>
public Reference(string name)
: this(name, null)
/// <param name="name">Name of this reference</param>
/// <param name="kind">Reference kind</param>
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>
/// <param name="name">Name of reference</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;
Name = name;
TargetKind = kind;
_children = new Dictionary<string, Reference>();
}
#endregion
#region Exists
/// <summary>
/// Checks if the reference has a file on disk
/// Checks if the file exists
/// </summary>
/// <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>
/// Adds a child reference
/// </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>
/// Compares a reference to another objects
/// </summary>
@ -275,10 +413,27 @@ namespace RainmeterStudio.Core.Model
return QualifiedName;
}
/// <summary>
/// Triggered when children are added or removed.
/// </summary>
public event NotifyCollectionChangedEventHandler CollectionChanged;
#endregion
#region Helper methods
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>

View File

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

View File

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

View File

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

View File

@ -33,7 +33,7 @@ namespace RainmeterStudio.UI.Controller
string key = "ProjectItem";
// 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)))
key += "Unknown";
@ -43,7 +43,7 @@ namespace RainmeterStudio.UI.Controller
}
// 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";
}

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>
/// Gets an enumerable of this object's children
/// </summary>
@ -120,9 +109,16 @@ namespace RainmeterStudio.UI.ViewModel
{
Reference = reference;
Reference.CollectionChanged += Reference_CollectionChanged;
Reference.PropertyChanged += Reference_PropertyChanged;
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)
{
List<ReferenceViewModel> newItems = new List<ReferenceViewModel>();