using System; using System.Collections.Generic; using System.Windows; using System.Linq; using RainmeterStudio.Business; using RainmeterStudio.Core.Editor; using RainmeterStudio.Core.Model.Events; using RainmeterStudio.UI.Dialogs; using RainmeterStudio.UI.ViewModel; using RainmeterStudio.Core.Model; using System.IO; using Microsoft.Win32; using RainmeterStudio.Core.Utils; 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 { get; private set; } public Command DocumentOpenCommand { get; private set; } public Command DocumentSaveCommand { get; private set; } public Command DocumentSaveAsCommand { get; private set; } public Command DocumentSaveACopyCommand { get; private set; } public Command DocumentSaveAllCommand { get; private set; } public Command DocumentCloseCommand { get; private set; } #endregion #region Events /// /// Triggered when a document is opened /// public event EventHandler DocumentOpened { add { DocumentManager.DocumentOpened += value; } remove { DocumentManager.DocumentOpened -= value; } } /// /// Triggered when a document is closed /// public event EventHandler DocumentClosed { add { DocumentManager.DocumentClosed += value; } remove { DocumentManager.DocumentClosed -= value; } } /// /// Triggered when the active document editor changes. /// public event EventHandler ActiveDocumentEditorChanged; #endregion #region Properties private IDocumentEditor _activeDocumentEditor = null; /// /// Gets or sets the active document editor. /// This must be set by the main window when active document changes. /// public IDocumentEditor ActiveDocumentEditor { get { return _activeDocumentEditor; } set { _activeDocumentEditor = value; if (ActiveDocumentEditorChanged != null) ActiveDocumentEditorChanged(this, new EventArgs()); } } public MainWindow OwnerWindow { get; set; } #endregion /// /// Initializes a document controller /// /// /// public DocumentController(DocumentManager documentManager, ProjectManager projectManager) { DocumentManager = documentManager; ProjectManager = projectManager; DocumentCreateCommand = new Command("DocumentCreate", Create, () => ProjectManager.ActiveProject != null); DocumentOpenCommand = new Command("DocumentOpen", arg => { if (arg is Reference) { Open((Reference)arg); } else { Open(); } }); DocumentSaveCommand = new Command("DocumentSave", () => Save(), HasActiveDocumentEditor); DocumentSaveAsCommand = new Command("DocumentSaveAs", () => SaveAs(), HasActiveDocumentEditor); DocumentSaveACopyCommand = new Command("DocumentSaveACopy", () => SaveACopy(), HasActiveDocumentEditor); DocumentSaveAllCommand = new Command("DocumentSaveAll", SaveAll, () => ProjectManager.ActiveProject != null); DocumentCloseCommand = new Command("DocumentClose", () => Close(), HasActiveDocumentEditor); ProjectManager.ActiveProjectChanged += new EventHandler((sender, e) => { DocumentCreateCommand.NotifyCanExecuteChanged(); DocumentSaveAllCommand.NotifyCanExecuteChanged(); }); ActiveDocumentEditorChanged += new EventHandler((sender, e) => { DocumentSaveCommand.NotifyCanExecuteChanged(); DocumentSaveAsCommand.NotifyCanExecuteChanged(); DocumentSaveACopyCommand.NotifyCanExecuteChanged(); DocumentCloseCommand.NotifyCanExecuteChanged(); }); } private bool HasActiveDocumentEditor() { return ActiveDocumentEditor != null; } #region Document operations /// /// Shows the new item dialog, and creates a new document /// public void Create() { // Show dialog var dialog = new CreateDocumentDialog(this); dialog.Owner = OwnerWindow; bool? res = dialog.ShowDialog(); if (!res.HasValue || !res.Value) return; var format = dialog.SelectedTemplate; // Call manager var editor = DocumentManager.Create(format.Template); // Set the reference var name = dialog.SelectedName; string folder = OwnerWindow.ProjectPanel.ActiveItem.StoragePath; if (!Directory.Exists(folder)) folder = Path.GetDirectoryName(folder); var reference = new Reference(name, Path.Combine(folder, name), ReferenceTargetKind.File); editor.AttachedDocument.Reference = reference; // Save document DocumentManager.Save(editor.AttachedDocument); // Add to parent OwnerWindow.ProjectPanel.ActiveItem.Add(reference); ProjectManager.SaveActiveProject(); } /// /// Shows an 'open document' dialog, and opens a document /// public void Open() { // Show open dialog OpenFileDialog dialog = new OpenFileDialog(); dialog.Title = Resources.Strings.Dialog_OpenDocument_Title; dialog.Filter = Resources.Strings.Dialog_FileType_AllFiles + "|*.*"; dialog.InitialDirectory = Properties.Settings.Default.Project_SavedLocation; bool? res = dialog.ShowDialog(); if (res.HasValue && res.Value) { // Open file DocumentManager.Open(dialog.FileName); } } /// /// Opens the document pointed to by a reference /// /// public void Open(Reference reference) { DocumentManager.Open(reference.StoragePath); } /// /// Saves the active document /// public bool Save() { return Save(ActiveDocumentEditor); } /// /// Saves the active document /// public bool Save(IDocumentEditor editor) { if (editor.AttachedDocument.Reference != null) { DocumentManager.Save(editor.AttachedDocument); return true; } else { return SaveAs(editor); } } /// /// Displays a 'save as' dialog, and saves active document /// public bool SaveAs() { return SaveAs(ActiveDocumentEditor); } /// /// Displays a 'save as' dialog, and saves active document /// public bool SaveAs(IDocumentEditor editor) { // Show save dialog SaveFileDialog dialog = new SaveFileDialog(); dialog.Title = Resources.Strings.Dialog_SaveDocument_Title; dialog.Filter = Resources.Strings.Dialog_FileType_AllFiles + "|*.*"; dialog.FileName = editor.AttachedDocument.Reference.StoragePath; bool? res = dialog.ShowDialog(); if (res.HasValue && res.Value) { DocumentManager.SaveAs(dialog.FileName, editor.AttachedDocument); return true; } return false; } /// /// Displays a 'save' dialog, and saves a copy of the active document /// public void SaveACopy() { // Show save dialog SaveFileDialog dialog = new SaveFileDialog(); dialog.Title = Resources.Strings.Dialog_SaveDocument_Title; dialog.Filter = Resources.Strings.Dialog_FileType_AllFiles + "|*.*"; dialog.FileName = ActiveDocumentEditor.AttachedDocument.Reference.StoragePath; bool? res = dialog.ShowDialog(); if (res.HasValue && res.Value) { DocumentManager.SaveACopy(dialog.FileName, ActiveDocumentEditor.AttachedDocument); } } /// /// Saves all opened documents /// public void SaveAll() { foreach (var editor in DocumentManager.Editors) { if (!Save(editor)) return; } } /// /// Closes an active document. /// /// The document editor attached /// True if closed successfully /// Shows the 'are you sure' prompt if there are unsaved edits. public bool Close(IDocumentEditor editor) { // Show the 'are you sure' prompt if necesary if (editor.AttachedDocument.IsDirty) { switch(CloseUnsavedDialog.ShowDialog(OwnerWindow, editor.AttachedDocument)) { case CloseUnsavedDialogResult.Save: Save(); break; case CloseUnsavedDialogResult.Cancel: return false; } } // Close DocumentManager.Close(editor); // Update ActiveDocument if (editor == ActiveDocumentEditor) ActiveDocumentEditor = null; return true; } /// /// Closes the active document. /// /// True if closed successfully /// Shows the 'are you sure' prompt if there are unsaved edits. public bool Close() { return Close(ActiveDocumentEditor); } /// /// Closes all the opened documents /// /// True if closed successfully, false if user hit 'cancel'. public bool CloseAll() { // Get dirty documents var unsaved = DocumentManager.Editors .Select(editor => editor.AttachedDocument) .Where(document => document.IsDirty); // There are unsaved documents? Display save dialog if (unsaved.Any()) { switch (CloseUnsavedDialog.ShowDialog(OwnerWindow, unsaved)) { case CloseUnsavedDialogResult.Save: SaveAll(); break; case CloseUnsavedDialogResult.Cancel: return false; } } // Close all documents // To array is used because DocumentManager.Editors is modified when closing a document. DocumentManager.Editors.ToArray().ForEach(DocumentManager.Close); // Done return true; } #endregion /// /// Gets a list of document templates view models /// public IEnumerable DocumentTemplates { get { return DocumentManager.DocumentTemplates.Select(t => new DocumentTemplateViewModel(t)); } } } }