From 09224d9af768c051ea34e54fa5686fc3c5f234af Mon Sep 17 00:00:00 2001 From: Tiberiu Chibici Date: Tue, 29 Jul 2014 19:42:52 +0300 Subject: [PATCH] Work on document manager --- RainmeterStudio/App.xaml.cs | 2 +- RainmeterStudio/Business/DocumentManager.cs | 233 +++++++++++++++--- .../ICustomDocumentTitleProvider.cs | 13 + .../ISelectionPropertiesProvider.cs | 16 ++ .../IToolboxProvider.cs | 15 ++ .../DocumentEditorFeatures/IUndoSupport.cs | 12 + RainmeterStudio/Documents/DocumentTemplate.cs | 132 ++++++++++ RainmeterStudio/Documents/IDocumentEditor.cs | 15 ++ .../Documents/IDocumentEditorFactory.cs | 25 ++ .../{Model => Documents}/IDocumentStorage.cs | 15 +- .../Documents/Text/TextDocument.cs | 62 ++++- RainmeterStudio/Documents/Text/TextEditor.cs | 4 +- .../Documents/Text/TextEditorFactory.cs | 5 +- RainmeterStudio/Documents/Text/TextStorage.cs | 8 +- RainmeterStudio/Model/DocumentFormat.cs | 14 -- RainmeterStudio/Model/DocumentTemplate.cs | 35 +++ .../Model/Events/DocumentOpenedEventArgs.cs | 47 +++- RainmeterStudio/Model/IDocument.cs | 7 +- RainmeterStudio/Model/IDocumentEditor.cs | 136 ---------- .../Model/IDocumentEditorFactory.cs | 39 --- RainmeterStudio/Model/Property.cs | 32 ++- RainmeterStudio/RainmeterStudio.csproj | 14 +- RainmeterStudio/Resources/Strings.Designer.cs | 9 + RainmeterStudio/Resources/Strings.resx | 3 + .../UI/Controller/DocumentController.cs | 44 ++-- .../UI/Dialogs/CreateDocumentDialog.xaml.cs | 3 +- .../UI/Dialogs/CreateProjectDialog.xaml | 5 - RainmeterStudio/UI/MainWindow.xaml.cs | 5 +- .../UI/ViewModel/DocumentTemplateViewModel.cs | 128 ++++++++++ 29 files changed, 798 insertions(+), 280 deletions(-) create mode 100644 RainmeterStudio/Documents/DocumentEditorFeatures/ICustomDocumentTitleProvider.cs create mode 100644 RainmeterStudio/Documents/DocumentEditorFeatures/ISelectionPropertiesProvider.cs create mode 100644 RainmeterStudio/Documents/DocumentEditorFeatures/IToolboxProvider.cs create mode 100644 RainmeterStudio/Documents/DocumentEditorFeatures/IUndoSupport.cs create mode 100644 RainmeterStudio/Documents/DocumentTemplate.cs create mode 100644 RainmeterStudio/Documents/IDocumentEditor.cs create mode 100644 RainmeterStudio/Documents/IDocumentEditorFactory.cs rename RainmeterStudio/{Model => Documents}/IDocumentStorage.cs (61%) delete mode 100644 RainmeterStudio/Model/DocumentFormat.cs create mode 100644 RainmeterStudio/Model/DocumentTemplate.cs delete mode 100644 RainmeterStudio/Model/IDocumentEditor.cs delete mode 100644 RainmeterStudio/Model/IDocumentEditorFactory.cs create mode 100644 RainmeterStudio/UI/ViewModel/DocumentTemplateViewModel.cs diff --git a/RainmeterStudio/App.xaml.cs b/RainmeterStudio/App.xaml.cs index 36ae7304..27c83f97 100644 --- a/RainmeterStudio/App.xaml.cs +++ b/RainmeterStudio/App.xaml.cs @@ -16,7 +16,7 @@ namespace RainmeterStudio { private void Application_Startup(object sender, StartupEventArgs e) { - DocumentManager.Instance.RegisterEditorFactory(new TextEditorFactory()); + //DocumentManager.Instance.RegisterEditorFactory(new TextEditorFactory()); } } } diff --git a/RainmeterStudio/Business/DocumentManager.cs b/RainmeterStudio/Business/DocumentManager.cs index 7e5eb36d..01471cbc 100644 --- a/RainmeterStudio/Business/DocumentManager.cs +++ b/RainmeterStudio/Business/DocumentManager.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; +using RainmeterStudio.Documents; using RainmeterStudio.Model; using RainmeterStudio.Model.Events; @@ -9,34 +11,57 @@ namespace RainmeterStudio.Business { public class DocumentManager { - #region Singleton instance - private static DocumentManager _instance = null; + #region Events /// - /// Gets the instance of DocumentManager + /// Triggered when a document is opened /// - public static DocumentManager Instance - { - get - { - if (_instance == null) - _instance = new DocumentManager(); + public event EventHandler DocumentOpened; - return _instance; - } - } + /// + /// Triggered when a document is closed + /// + public event EventHandler DocumentClosed; #endregion - private DocumentManager() + #region Properties + + /// + /// Gets a list of factories + /// + public IEnumerable Factories { get { return _factories; } } + + /// + /// Gets a list of editors + /// + public IEnumerable Editors { get { return _editors; } } + + /// + /// Gets a list of storages + /// + public IEnumerable Storages { get { return _storages; } } + + #endregion + + #region Private fields + + private List _factories = new List(); + private List _editors = new List(); + private List _storages = new List(); + private List _templates = new List(); + + #endregion + + #region Initialization + + /// + /// Initializes this document manager + /// + public DocumentManager() { } - List _factories = new List(); - List _editors = new List(); - - public event EventHandler DocumentOpened; - /// /// Registers a document editor factory /// @@ -46,33 +71,181 @@ namespace RainmeterStudio.Business _factories.Add(factory); } + /// + /// Registers a document storage + /// + /// The storage + public void RegisterStorage(IDocumentStorage storage) + { + _storages.Add(storage); + } + + /// + /// Registers a document template + /// + /// The document template + public void RegisterTemplate(DocumentTemplate template) + { + _templates.Add(template); + } + + #endregion + + #region Document operations + /// /// Creates a new document in the specified path, with the specified format, and opens it /// /// /// - public void Create(DocumentTemplate format, string path) + public IDocumentEditor Create(DocumentTemplate format) { // Create document - var document = format.Factory.CreateDocument(format, path); + var document = format.CreateDocument(); + document.IsDirty = true; - // Create editor - var editor = format.Factory.CreateEditor(document); - _editors.Add(editor); + // Find and create editor + IDocumentEditor editor = CreateEditor(document); // Trigger event if (DocumentOpened != null) DocumentOpened(this, new DocumentOpenedEventArgs(editor)); + + return editor; } - public IEnumerable DocumentFormats + /// + /// Opens the specified document + /// + public IDocumentEditor Open(string path) { - get - { - foreach (var f in _factories) - foreach (var df in f.CreateDocumentFormats) - yield return df; - } + // Try to open + IDocument document = Read(path); + + // Create factory + var editor = CreateEditor(document); + + // Trigger event + if (DocumentOpened != null) + DocumentOpened(this, new DocumentOpenedEventArgs(editor)); + + return editor; } + + public void Save(IDocument document) + { + // Find a storage + var storage = FindStorage(document); + + if (document.Reference == null) + throw new ArgumentException("Reference cannot be empty"); + + // Save + storage.Write(document.Reference.Path, document); + + // Clear dirty flag + document.IsDirty = false; + } + + public void SaveAs(string path, IDocument document) + { + // Find a storage + var storage = FindStorage(document); + + // Save + storage.Write(path, document); + + // Update reference + document.Reference.Name = Path.GetFileName(path); + document.Reference.Path = path; + + // Clear dirty flag + document.IsDirty = false; + } + + public void SaveACopy(string path, IDocument document) + { + // Find a storage + var storage = FindStorage(document); + + // Save + storage.Write(path, document); + } + + #endregion + + #region Private functions + + /// + /// Attempts to create an editor for the document + /// + /// The document + /// Thrown if failed to create editor + /// The editor + private IDocumentEditor CreateEditor(IDocument document) + { + IDocumentEditor editor = null; + + foreach (var factory in Factories) + if (factory.CanEdit(document.GetType())) + { + editor = factory.CreateEditor(document); + break; + } + + if (editor == null) + throw new ArgumentException("Failed to create editor."); + + _editors.Add(editor); + return editor; + } + + /// + /// Attempts to read a document + /// + /// Path of file + /// Thrown when failed to open the document + /// + private IDocument Read(string path) + { + IDocument document = null; + + foreach (var storage in Storages) + if (storage.CanRead(path)) + { + document = storage.Read(path); + break; + } + + // Failed to open + if (document == null) + throw new ArgumentException("Failed to open document."); + + return document; + } + + /// + /// Attempts to find a storage for the specified document + /// + /// + /// + private IDocumentStorage FindStorage(IDocument document) + { + IDocumentStorage storage = null; + + foreach (var s in Storages) + if (s.CanWrite(document.GetType())) + { + storage = s; + break; + } + + if (storage == null) + throw new ArgumentException("Failed to find storage object."); + + return storage; + } + + #endregion } } diff --git a/RainmeterStudio/Documents/DocumentEditorFeatures/ICustomDocumentTitleProvider.cs b/RainmeterStudio/Documents/DocumentEditorFeatures/ICustomDocumentTitleProvider.cs new file mode 100644 index 00000000..832673c2 --- /dev/null +++ b/RainmeterStudio/Documents/DocumentEditorFeatures/ICustomDocumentTitleProvider.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RainmeterStudio.Documents.DocumentEditorFeatures +{ + public interface ICustomDocumentTitleProvider + { + string Title { get; } + event EventHandler TitleChanged; + } +} diff --git a/RainmeterStudio/Documents/DocumentEditorFeatures/ISelectionPropertiesProvider.cs b/RainmeterStudio/Documents/DocumentEditorFeatures/ISelectionPropertiesProvider.cs new file mode 100644 index 00000000..2d912322 --- /dev/null +++ b/RainmeterStudio/Documents/DocumentEditorFeatures/ISelectionPropertiesProvider.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RainmeterStudio.Model; + +namespace RainmeterStudio.Documents.DocumentEditorFeatures +{ + interface ISelectionPropertiesProvider + { + string SelectionName { get; } + IEnumerable SelectionProperties { get; } + + event EventHandler SelectionChanged; + } +} diff --git a/RainmeterStudio/Documents/DocumentEditorFeatures/IToolboxProvider.cs b/RainmeterStudio/Documents/DocumentEditorFeatures/IToolboxProvider.cs new file mode 100644 index 00000000..8946ad90 --- /dev/null +++ b/RainmeterStudio/Documents/DocumentEditorFeatures/IToolboxProvider.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RainmeterStudio.Documents.DocumentEditorFeatures +{ + public interface IToolboxProvider + { + bool SupportsToolboxDrop { get; } + IEnumerable ToolboxItems { get; } + + event EventHandler ToolboxItemsChanged; + } +} diff --git a/RainmeterStudio/Documents/DocumentEditorFeatures/IUndoSupport.cs b/RainmeterStudio/Documents/DocumentEditorFeatures/IUndoSupport.cs new file mode 100644 index 00000000..7db25a2a --- /dev/null +++ b/RainmeterStudio/Documents/DocumentEditorFeatures/IUndoSupport.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace RainmeterStudio.Documents.DocumentEditorFeatures +{ + public interface IUndoSupport + { + // TODO + } +} diff --git a/RainmeterStudio/Documents/DocumentTemplate.cs b/RainmeterStudio/Documents/DocumentTemplate.cs new file mode 100644 index 00000000..34ed377f --- /dev/null +++ b/RainmeterStudio/Documents/DocumentTemplate.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Media; +using RainmeterStudio.Model; +using RainmeterStudio.UI.Controller; + +namespace RainmeterStudio.Documents +{ + /// + /// Represents a document template + /// + public class DocumentTemplate where T : IDocument + { + #region Private fields + + private Func _createFunction; + + #endregion + + /// + /// Gets the document template name + /// + public string Name { get; private set; } + + #region Icon property + + private ImageSource _icon = null; + + /// + /// Gets or sets the template's icon + /// + public virtual ImageSource Icon + { + get + { + if (_icon == null) + return IconProvider.GetIcon("Template_" + Name); + + return _icon; + } + set + { + _icon = value; + } + } + + #endregion + + #region Display text property + + private string _displayText = null; + + /// + /// Gets or sets the display text + /// + public virtual string DisplayText + { + get + { + if (_displayText == null) + return Resources.Strings.ResourceManager.GetString("Template_" + Name + "_DisplayText"); + + return _displayText; + } + set + { + _displayText = value; + } + } + + #endregion + + #region Description property + + private string _description = null; + + /// + /// Gets or sets the description + /// + public virtual string Description + { + get + { + if (_description == null) + return Resources.Strings.ResourceManager.GetString("Template_" + Name + "_Description"); + + return _description; + } + set + { + _description = value; + } + } + + #endregion + + /// + /// Gets or sets the default extension of this template + /// + public string DefaultExtension { get; set; } + + /// + /// Gets or sets the category in which this template belongs + /// + public virtual string Category { get; set; } + + /// + /// Initializes the document template + /// + /// Name of document template + public DocumentTemplate(string name, string defaultExtension = null, string category = null, Func createDocument = null) + { + Name = name; + DefaultExtension = defaultExtension; + _createFunction = createDocument; + } + + /// + /// Creates a document of type T + /// + /// + public virtual T CreateDocument() + { + if (_createFunction != null) + return _createFunction(); + + return default(T); + } + } +} diff --git a/RainmeterStudio/Documents/IDocumentEditor.cs b/RainmeterStudio/Documents/IDocumentEditor.cs new file mode 100644 index 00000000..0318e14e --- /dev/null +++ b/RainmeterStudio/Documents/IDocumentEditor.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows; +using RainmeterStudio.Model; + +namespace RainmeterStudio.Documents +{ + public interface IDocumentEditor + { + IDocument AttachedDocument { get; } + UIElement EditorUI { get; } + } +} diff --git a/RainmeterStudio/Documents/IDocumentEditorFactory.cs b/RainmeterStudio/Documents/IDocumentEditorFactory.cs new file mode 100644 index 00000000..fc2ca33d --- /dev/null +++ b/RainmeterStudio/Documents/IDocumentEditorFactory.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RainmeterStudio.Model; + +namespace RainmeterStudio.Documents +{ + public interface IDocumentEditorFactory + { + /// + /// Creates a new editor object + /// + /// Document to be edited by the editor + /// A new document editor + IDocumentEditor CreateEditor(IDocument document); + + /// + /// Tests if this editor can edit this document type + /// + /// Document type + /// True if the editor can edit the document type + bool CanEdit(Type type); + } +} diff --git a/RainmeterStudio/Model/IDocumentStorage.cs b/RainmeterStudio/Documents/IDocumentStorage.cs similarity index 61% rename from RainmeterStudio/Model/IDocumentStorage.cs rename to RainmeterStudio/Documents/IDocumentStorage.cs index 7215dedc..427be2fd 100644 --- a/RainmeterStudio/Model/IDocumentStorage.cs +++ b/RainmeterStudio/Documents/IDocumentStorage.cs @@ -1,4 +1,10 @@ -namespace RainmeterStudio.Model +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using RainmeterStudio.Model; + +namespace RainmeterStudio.Documents { public interface IDocumentStorage { @@ -22,5 +28,12 @@ /// Path to file /// True if file can be read bool CanRead(string path); + + /// + /// Tests if the document can be written by this storage + /// + /// Document type + /// True if the document can be written + bool CanWrite(Type documentType); } } diff --git a/RainmeterStudio/Documents/Text/TextDocument.cs b/RainmeterStudio/Documents/Text/TextDocument.cs index f6050965..04470fae 100644 --- a/RainmeterStudio/Documents/Text/TextDocument.cs +++ b/RainmeterStudio/Documents/Text/TextDocument.cs @@ -4,29 +4,67 @@ using System.IO; using System.Linq; using System.Text; using RainmeterStudio.Model; +using System.ComponentModel; namespace RainmeterStudio.Documents.Text { public class TextDocument : IDocument { - public string Name - { - get - { - return Path.GetFileName(FilePath); - } - } - - public string FilePath - { - get; set; - } + private Reference _reference; + private bool _isDirty; + /// + /// Gets or sets the text associated with this document + /// public string Text { get; set; } + /// + /// Gets or sets the reference of this document + /// + public Reference Reference + { + get + { + return _reference; + } + set + { + _reference = value; + + if (PropertyChanged != null) + PropertyChanged(this, new PropertyChangedEventArgs("Reference")); + } + } + + /// + /// Gets a property indicating if this file was modified and not saved + /// + public bool IsDirty + { + get + { + return _isDirty; + } + set + { + _isDirty = value; + + if (PropertyChanged != null) + PropertyChanged(this, new PropertyChangedEventArgs("IsDirty")); + } + } + + /// + /// Triggered when the value of a property changes + /// + public event PropertyChangedEventHandler PropertyChanged; + + /// + /// Initializes the text document + /// public TextDocument() { Text = String.Empty; diff --git a/RainmeterStudio/Documents/Text/TextEditor.cs b/RainmeterStudio/Documents/Text/TextEditor.cs index 1496cb9c..67d1f187 100644 --- a/RainmeterStudio/Documents/Text/TextEditor.cs +++ b/RainmeterStudio/Documents/Text/TextEditor.cs @@ -7,7 +7,7 @@ using RainmeterStudio.Model; namespace RainmeterStudio.Documents.Text { - public class TextEditor : IDocumentEditor + /*public class TextEditor : IDocumentEditor { private TextDocument _document; private TextEditorControl _control; @@ -23,5 +23,5 @@ namespace RainmeterStudio.Documents.Text public override string Title { get { return _document.Name; } } public override System.Windows.UIElement EditorUI { get { return _control; } } - } + }*/ } diff --git a/RainmeterStudio/Documents/Text/TextEditorFactory.cs b/RainmeterStudio/Documents/Text/TextEditorFactory.cs index 9122a800..3db15c29 100644 --- a/RainmeterStudio/Documents/Text/TextEditorFactory.cs +++ b/RainmeterStudio/Documents/Text/TextEditorFactory.cs @@ -8,7 +8,7 @@ using RainmeterStudio.Model; namespace RainmeterStudio.Documents.Text { - public class TextEditorFactory : IDocumentEditorFactory + /*public class TextEditorFactory : IDocumentEditorFactory { private TextStorage _storage = new TextStorage(); @@ -35,7 +35,6 @@ namespace RainmeterStudio.Documents.Text } } - public IDocumentEditor CreateEditor(IDocument document) { TextDocument textDocument = document as TextDocument; @@ -55,5 +54,5 @@ namespace RainmeterStudio.Documents.Text return document; } - } + }*/ } diff --git a/RainmeterStudio/Documents/Text/TextStorage.cs b/RainmeterStudio/Documents/Text/TextStorage.cs index ddde402c..c4bf336c 100644 --- a/RainmeterStudio/Documents/Text/TextStorage.cs +++ b/RainmeterStudio/Documents/Text/TextStorage.cs @@ -13,7 +13,8 @@ namespace RainmeterStudio.Documents.Text IDocument IDocumentStorage.Read(string path) { TextDocument document = new TextDocument(); - document.FilePath = path; + document.Reference.Path = path; + document.Reference.Name = Path.GetFileName(path); document.Text = File.ReadAllText(path); return document; @@ -60,5 +61,10 @@ namespace RainmeterStudio.Documents.Text // Not found, probably text file return true; } + + public bool CanWrite(Type documentType) + { + return documentType.Equals(typeof(TextDocument)); + } } } diff --git a/RainmeterStudio/Model/DocumentFormat.cs b/RainmeterStudio/Model/DocumentFormat.cs deleted file mode 100644 index f525ca6a..00000000 --- a/RainmeterStudio/Model/DocumentFormat.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Windows.Media; - -namespace RainmeterStudio.Model -{ - public class DocumentTemplate - { - public string Name { get; set; } - public ImageSource Icon { get; set; } - public string Description { get; set; } - public string DefaultExtension { get; set; } - public IDocumentEditorFactory Factory { get; set; } - public string Category { get; set; } - } -} diff --git a/RainmeterStudio/Model/DocumentTemplate.cs b/RainmeterStudio/Model/DocumentTemplate.cs new file mode 100644 index 00000000..591f1811 --- /dev/null +++ b/RainmeterStudio/Model/DocumentTemplate.cs @@ -0,0 +1,35 @@ +namespace RainmeterStudio.Model +{ + /// + /// Represents a document template + /// + public abstract class DocumentTemplate + { + /// + /// Gets the document template name + /// + public string Name { get; private set; } + + /// + /// Gets the default extension of this template + /// + public string DefaultExtension { get; private set; } + + /// + /// Initializes the document template + /// + /// Name of template + /// Default extension + public DocumentTemplate(string name, string defaultExtension) + { + Name = name; + DefaultExtension = defaultExtension; + } + + /// + /// Creates a document using this template + /// + /// + public abstract IDocument CreateDocument(); + } +} diff --git a/RainmeterStudio/Model/Events/DocumentOpenedEventArgs.cs b/RainmeterStudio/Model/Events/DocumentOpenedEventArgs.cs index 4769fe89..16960dce 100644 --- a/RainmeterStudio/Model/Events/DocumentOpenedEventArgs.cs +++ b/RainmeterStudio/Model/Events/DocumentOpenedEventArgs.cs @@ -2,16 +2,59 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using RainmeterStudio.Documents; namespace RainmeterStudio.Model.Events { - public class DocumentOpenedEventArgs : EventArgs + public abstract class DocumentEventArgsBase : EventArgs { + /// + /// Gets the newly created document editor + /// public IDocumentEditor Editor { get; private set; } - public DocumentOpenedEventArgs(IDocumentEditor editor) + /// + /// Gets the opened document + /// + public IDocument Document { get { return Editor.AttachedDocument; } } + + /// + /// Initializes the DocumentOpenedEventArgs + /// + /// The document editor + public DocumentEventArgsBase(IDocumentEditor editor) { Editor = editor; } } + + /// + /// Event arguments for the document opened event + /// + public class DocumentOpenedEventArgs : DocumentEventArgsBase + { + /// + /// Initializes the DocumentOpenedEventArgs + /// + /// The document editor + public DocumentOpenedEventArgs(IDocumentEditor editor) + : base(editor) + { + } + } + + /// + /// Event arguments for the document closed event + /// + public class DocumentClosedEventArgs : DocumentEventArgsBase + { + /// + /// Initializes the DocumentClosedEventArgs + /// + /// The document editor + public DocumentClosedEventArgs(IDocumentEditor editor) + : base(editor) + { + } + } } diff --git a/RainmeterStudio/Model/IDocument.cs b/RainmeterStudio/Model/IDocument.cs index 84b8ddb9..2588d756 100644 --- a/RainmeterStudio/Model/IDocument.cs +++ b/RainmeterStudio/Model/IDocument.cs @@ -1,13 +1,14 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Text; namespace RainmeterStudio.Model { - public interface IDocument + public interface IDocument : INotifyPropertyChanged { - string Name { get; } - string FilePath { get; } + Reference Reference { get; } + bool IsDirty { get; set; } } } diff --git a/RainmeterStudio/Model/IDocumentEditor.cs b/RainmeterStudio/Model/IDocumentEditor.cs deleted file mode 100644 index 7cc5ff8d..00000000 --- a/RainmeterStudio/Model/IDocumentEditor.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Windows; - -namespace RainmeterStudio.Model -{ - public abstract class IDocumentEditor : IDisposable - { - #region Dirty flag - - private bool _dirty = false; - - /// - /// Gets a flag indicating if the active document is dirty (modified and not saved) - /// - public virtual bool Dirty - { - get - { - return _dirty; - } - protected set - { - _dirty = value; - if (DirtyChanged != null) - DirtyChanged(this, new EventArgs()); - } - } - - /// - /// Triggered when the dirty flag changes - /// - public event EventHandler DirtyChanged; - - #endregion - - #region Document - - /// - /// Gets the opened document - /// - public abstract IDocument Document { get; } - - /// - /// Gets the title to be displayed in the title bar - /// - public abstract string Title { get; } - - /// - /// Triggered when the title changes - /// - public event EventHandler TitleChanged; - - #endregion - - #region EditorUI - - /// - /// Gets the editor UI - /// - public abstract UIElement EditorUI { get; } - - #endregion - - #region Selection properties - - /// - /// Gets a value indicating if this editor uses the selection properties window - /// - public virtual bool UsesSelectionProperties - { - get - { - return false; - } - } - - /// - /// Gets the name of the selected object - /// - public virtual string SelectionName - { - get - { - return String.Empty; - } - } - - /// - /// Gets a list of properties for the currently selected object - /// - public virtual IEnumerable SelectionProperties - { - get - { - yield break; - } - } - - /// - /// Triggered when the selected object changes (used to update properties) - /// - public event EventHandler SelectionChanged; - - #endregion - - #region Toolbox - - /// - /// Gets a list of items to populate the toolbox - /// - public virtual IEnumerable ToolboxItems - { - get - { - yield break; - } - } - - public event EventHandler ToolboxChanged; - - #endregion - - #region Dispose - /// - /// Dispose - /// - public virtual void Dispose() - { - } - - #endregion - } -} diff --git a/RainmeterStudio/Model/IDocumentEditorFactory.cs b/RainmeterStudio/Model/IDocumentEditorFactory.cs deleted file mode 100644 index a1553509..00000000 --- a/RainmeterStudio/Model/IDocumentEditorFactory.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using RainmeterStudio.Storage; - -namespace RainmeterStudio.Model -{ - public interface IDocumentEditorFactory - { - /// - /// Name of the editor - /// - string EditorName { get; } - - /// - /// Formats that will be used to populate the 'create document' dialog - /// - IEnumerable CreateDocumentFormats { get; } - - /// - /// Creates a new editor object - /// - /// Document to be edited by the editor - /// A new document editor - IDocumentEditor CreateEditor(IDocument document); - - /// - /// Creates a new document - /// - /// A new document - IDocument CreateDocument(DocumentTemplate format, string path); - - /// - /// Gets the storage of this factory - /// - IDocumentStorage Storage { get; } - } -} diff --git a/RainmeterStudio/Model/Property.cs b/RainmeterStudio/Model/Property.cs index 40f2c6ae..b50510c5 100644 --- a/RainmeterStudio/Model/Property.cs +++ b/RainmeterStudio/Model/Property.cs @@ -1,15 +1,23 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Text; namespace RainmeterStudio.Model { - public class Property + public class Property : INotifyPropertyChanged { - public string Name { get; set; } + /// + /// Gets or sets the name of the property + /// + public string Name { get; private set; } private object _value; + + /// + /// Gets or sets the value of the property + /// public object Value { get @@ -20,11 +28,25 @@ namespace RainmeterStudio.Model { _value = value; - if (ValueChanged != null) - ValueChanged(this, new EventArgs()); + if (PropertyChanged != null) + PropertyChanged(this, new PropertyChangedEventArgs("Value")); } } + + /// + /// Triggered when the value changes + /// + public event PropertyChangedEventHandler PropertyChanged; - public event EventHandler ValueChanged; + /// + /// Initializes this property + /// + /// Name of the property + /// Value of the property + public Property(string name, object value = null) + { + Name = name; + Value = value; + } } } diff --git a/RainmeterStudio/RainmeterStudio.csproj b/RainmeterStudio/RainmeterStudio.csproj index 852c5e00..d6e30c79 100644 --- a/RainmeterStudio/RainmeterStudio.csproj +++ b/RainmeterStudio/RainmeterStudio.csproj @@ -72,15 +72,21 @@ + + + + + + + + TextEditorControl.xaml - + - - @@ -106,7 +112,6 @@ True Strings.resx - @@ -125,6 +130,7 @@ ProjectPanel.xaml + diff --git a/RainmeterStudio/Resources/Strings.Designer.cs b/RainmeterStudio/Resources/Strings.Designer.cs index b3f8239a..3e273e9d 100644 --- a/RainmeterStudio/Resources/Strings.Designer.cs +++ b/RainmeterStudio/Resources/Strings.Designer.cs @@ -401,5 +401,14 @@ namespace RainmeterStudio.Resources { return ResourceManager.GetString("ProjectPanel_SyncWithActiveViewCommand_ToolTip", resourceCulture); } } + + /// + /// Looks up a localized string similar to Utility. + /// + public static string TemplateCategory_Utility { + get { + return ResourceManager.GetString("TemplateCategory_Utility", resourceCulture); + } + } } } diff --git a/RainmeterStudio/Resources/Strings.resx b/RainmeterStudio/Resources/Strings.resx index c9838862..f483277d 100644 --- a/RainmeterStudio/Resources/Strings.resx +++ b/RainmeterStudio/Resources/Strings.resx @@ -231,4 +231,7 @@ Sync with active view + + Utility + \ No newline at end of file diff --git a/RainmeterStudio/UI/Controller/DocumentController.cs b/RainmeterStudio/UI/Controller/DocumentController.cs index 42c97bb5..8ad6bc64 100644 --- a/RainmeterStudio/UI/Controller/DocumentController.cs +++ b/RainmeterStudio/UI/Controller/DocumentController.cs @@ -14,21 +14,23 @@ namespace RainmeterStudio.UI.Controller { public class DocumentController { + #region Managers + + /// + /// Gets or sets the document manager + /// + protected DocumentManager DocumentManager { get; private set; } + + /// + /// Gets or sets the project manager + /// + protected ProjectManager ProjectManager { get; private set; } + + #endregion + #region Commands - public Command _documentCreateCommand; - public Command DocumentCreateCommand - { - get - { - if (_documentCreateCommand == null) - { - _documentCreateCommand = new Command("DocumentCreateCommand", () => CreateWindow()); - } - - return _documentCreateCommand; - } - } + public Command DocumentCreateCommand { get; private set; } #endregion @@ -36,19 +38,23 @@ namespace RainmeterStudio.UI.Controller { add { - DocumentManager.Instance.DocumentOpened += value; + DocumentManager.DocumentOpened += value; } remove { - DocumentManager.Instance.DocumentOpened -= value; + DocumentManager.DocumentOpened -= value; } } public event EventHandler DocumentClosed; public Window OwnerWindow { get; set; } - public DocumentController() + public DocumentController(DocumentManager documentManager, ProjectManager projectManager) { + DocumentManager = documentManager; + ProjectManager = projectManager; + + DocumentCreateCommand = new Command("DocumentCreateCommand", () => CreateWindow()); } public void CreateWindow(DocumentTemplate defaultFormat = null, string defaultPath = "") @@ -69,13 +75,13 @@ namespace RainmeterStudio.UI.Controller var path = dialog.SelectedPath; // Call manager - DocumentManager.Instance.Create(format, path); + DocumentManager.Create(format); } - public void Create(DocumentTemplate format, string path) + public void Create(DocumentTemplate format) { // Call manager - DocumentManager.Instance.Create(format, path); + DocumentManager.Create(format); } } diff --git a/RainmeterStudio/UI/Dialogs/CreateDocumentDialog.xaml.cs b/RainmeterStudio/UI/Dialogs/CreateDocumentDialog.xaml.cs index be5e69c2..fc8645d5 100644 --- a/RainmeterStudio/UI/Dialogs/CreateDocumentDialog.xaml.cs +++ b/RainmeterStudio/UI/Dialogs/CreateDocumentDialog.xaml.cs @@ -64,7 +64,8 @@ namespace RainmeterStudio.UI.Dialogs private void PopulateFormats() { - listFormats.ItemsSource = DocumentManager.Instance.DocumentFormats; + //listFormats.ItemsSource = DocumentManager.Instance.DocumentFormats; + CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(listFormats.ItemsSource); view.GroupDescriptions.Add(new PropertyGroupDescription("Category")); } diff --git a/RainmeterStudio/UI/Dialogs/CreateProjectDialog.xaml b/RainmeterStudio/UI/Dialogs/CreateProjectDialog.xaml index 2c38e379..b968b28c 100644 --- a/RainmeterStudio/UI/Dialogs/CreateProjectDialog.xaml +++ b/RainmeterStudio/UI/Dialogs/CreateProjectDialog.xaml @@ -2,7 +2,6 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:r="clr-namespace:RainmeterStudio.Resources" - xmlns:toremove="clr-namespace:RainmeterStudio.Model" Title="{x:Static r:Strings.ProjectCreateDialog_Title}" Height="320" Width="480" WindowStartupLocation="CenterOwner" WindowStyle="ToolWindow" ShowInTaskbar="False"> @@ -16,10 +15,6 @@ - - - diff --git a/RainmeterStudio/UI/MainWindow.xaml.cs b/RainmeterStudio/UI/MainWindow.xaml.cs index 1dc61312..19165553 100644 --- a/RainmeterStudio/UI/MainWindow.xaml.cs +++ b/RainmeterStudio/UI/MainWindow.xaml.cs @@ -42,7 +42,8 @@ namespace RainmeterStudio.UI this.AddKeyBinding(ProjectController.ProjectCreateCommand); // Initialize document controller - DocumentController = new DocumentController(); + DocumentManager documentManager = new DocumentManager(); + DocumentController = new DocumentController(documentManager, projectManager); DocumentController.OwnerWindow = this; DocumentController.DocumentOpened += documentController_DocumentOpened; this.AddKeyBinding(DocumentController.DocumentCreateCommand); @@ -56,7 +57,7 @@ namespace RainmeterStudio.UI // Spawn a new window LayoutDocument document = new LayoutDocument(); document.Content = e.Editor.EditorUI; - document.Title = e.Editor.Title; + document.Title = e.Editor.AttachedDocument.Reference.Name; document.Closing += document_Closing; documentPane.Children.Add(document); diff --git a/RainmeterStudio/UI/ViewModel/DocumentTemplateViewModel.cs b/RainmeterStudio/UI/ViewModel/DocumentTemplateViewModel.cs new file mode 100644 index 00000000..d638add9 --- /dev/null +++ b/RainmeterStudio/UI/ViewModel/DocumentTemplateViewModel.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Windows.Media; +using RainmeterStudio.Model; +using RainmeterStudio.UI.Controller; + +namespace RainmeterStudio.UI.ViewModel +{ + public class DocumentTemplateViewModel + { + /// + /// Gets the document template + /// + public DocumentTemplate Template { get; private set; } + + /// + /// Gets the document template name + /// + public string Name { get { return Template.Name; } } + + #region Icon property + + private ImageSource _icon = null; + + /// + /// Gets or sets the icon of this document template + /// + public virtual ImageSource Icon + { + get + { + if (_icon == null) + return IconProvider.GetIcon("Template_" + Name); + + return _icon; + } + set + { + _icon = value; + } + } + + #endregion + + #region Display text property + + private string _displayText = null; + + /// + /// Gets or sets the display text + /// + public string DisplayText + { + get + { + if (_displayText == null) + return Resources.Strings.ResourceManager.GetString("Template_" + Name + "_DisplayText"); + + return _displayText; + } + set + { + _displayText = value; + } + } + + #endregion + + #region Description property + + private string _description = null; + + /// + /// Gets or sets the description of this document template + /// + public string Description + { + get + { + if (_description == null) + return Resources.Strings.ResourceManager.GetString("Template_" + Name + "_Description"); + + return _description; + } + set + { + _description = value; + } + } + + #endregion + + #region Category property + + private string _category = null; + + /// + /// Gets or sets the category of this template + /// + public string Category + { + get + { + if (_category == null) + return Resources.Strings.ResourceManager.GetString("Template_" + Name + "_Category"); + + return _category; + } + set + { + _category = value; + } + } + + #endregion + + /// + /// Initializes the document template view model + /// + /// The document template + public DocumentTemplateViewModel(DocumentTemplate template) + { + this.Template = template; + } + } +}