Skip to content

Commit

Permalink
Add save prompt and modify CodeEditor and TextEditor
Browse files Browse the repository at this point in the history
  • Loading branch information
diluculo committed Jun 1, 2018
1 parent ac0b9da commit 3ce5eca
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 19 deletions.
16 changes: 16 additions & 0 deletions src/Gemini.Demo/Modules/TextEditor/ViewModels/EditorViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@
using Gemini.Demo.Modules.TextEditor.Views;
using Gemini.Framework;
using Gemini.Framework.Threading;
using System.ComponentModel.Composition;

namespace Gemini.Demo.Modules.TextEditor.ViewModels
{
[Export(typeof(EditorViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
#pragma warning disable 659
public class EditorViewModel : PersistedDocument
#pragma warning restore 659
{
private EditorView _view;
private string _originalText;
private bool notYetLoaded = false;

protected override Task DoNew()
{
Expand All @@ -38,6 +42,12 @@ protected override Task DoSave(string filePath)

private void ApplyOriginalText()
{
// At StartUp, _view is null, so notYetLoaded flag is added
if (_view == null)
{
notYetLoaded = true;
return;
}
_view.textBox.Text = _originalText;

_view.textBox.TextChanged += delegate
Expand All @@ -49,6 +59,12 @@ private void ApplyOriginalText()
protected override void OnViewLoaded(object view)
{
_view = (EditorView) view;

if (notYetLoaded)
{
ApplyOriginalText();
notYetLoaded = false;
}
}

public override bool Equals(object obj)
Expand Down
2 changes: 1 addition & 1 deletion src/Gemini.Demo/Modules/TextEditor/Views/EditorView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@
FontFamily="Consolas"
FontSize="14"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.HorizontalScrollBarVisibility="Visible"/>
ScrollViewer.HorizontalScrollBarVisibility="Visible" TextWrapping="Wrap" AcceptsReturn="True"/>
</UserControl>
59 changes: 44 additions & 15 deletions src/Gemini.Modules.CodeEditor/ViewModels/CodeEditorViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
using Gemini.Framework;
using Gemini.Framework.Threading;
using Gemini.Modules.CodeEditor.Views;
using Gemini.Modules.StatusBar;
using System.ComponentModel;
using Caliburn.Micro;

namespace Gemini.Modules.CodeEditor.ViewModels
{
Expand All @@ -17,31 +20,25 @@ public class CodeEditorViewModel : PersistedDocument
private readonly LanguageDefinitionManager _languageDefinitionManager;
private string _originalText;
private ICodeEditorView _view;
private IStatusBar _statusBar;
private bool notYetLoaded = false;

[ImportingConstructor]
public CodeEditorViewModel(LanguageDefinitionManager languageDefinitionManager)
{
_languageDefinitionManager = languageDefinitionManager;
}

public override bool ShouldReopenOnStart
{
get { return true; }
}

public override void SaveState(BinaryWriter writer)
{
writer.Write(FilePath);
}

public override void LoadState(BinaryReader reader)
{
Load(reader.ReadString());
}

protected override void OnViewLoaded(object view)
{
_view = (ICodeEditorView) view;
_statusBar = IoC.Get<IStatusBar>();

if (notYetLoaded)
{
ApplyOriginalText();
notYetLoaded = false;
}
}

public override bool Equals(object obj)
Expand Down Expand Up @@ -76,20 +73,52 @@ protected override Task DoSave(string filePath)

private void ApplyOriginalText()
{
// At StartUp, _view is null, so notYetLoaded flag is added
if (_view == null)
{
notYetLoaded = true;
return;
}
_view.TextEditor.Text = _originalText;

_view.TextEditor.TextChanged += delegate
{
IsDirty = string.Compare(_originalText, _view.TextEditor.Text) != 0;
};

UpdateStatusBar();

// To update status bar items, Caret PositionChanged event is added
_view.TextEditor.TextArea.Caret.PositionChanged += delegate
{
UpdateStatusBar();
};

var fileExtension = Path.GetExtension(FileName).ToLower();

ILanguageDefinition languageDefinition = _languageDefinitionManager.GetDefinitionByExtension(fileExtension);

SetLanguage(languageDefinition);
}

/// <summary>
/// Update Column and Line position properties when caret position is changed
/// </summary>
private void UpdateStatusBar()
{
int lineNumber = _view.TextEditor.Document.GetLineByOffset(_view.TextEditor.CaretOffset).LineNumber;
int colPosition = _view.TextEditor.TextArea.Caret.VisualColumn + 1;

// TODO: Now I don't know about Ch#
//int charPosition = _view.TextEditor.CaretOffset;

if (_statusBar != null && _statusBar.Items.Count >= 3)
{
_statusBar.Items[1].Message = string.Format("Ln {0}", lineNumber);
_statusBar.Items[2].Message = string.Format("Col {0}", colPosition);
}
}

private void SetLanguage(ILanguageDefinition languageDefinition)
{
_view.TextEditor.SyntaxHighlighting = (languageDefinition != null)
Expand Down
80 changes: 77 additions & 3 deletions src/Gemini/Framework/PersistedDocument.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
using Caliburn.Micro;
using Gemini.Framework.Services;
using Gemini.Properties;
using Microsoft.Win32;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace Gemini.Framework
{
Expand All @@ -25,10 +31,78 @@ public bool IsDirty
}
}

public override void CanClose(System.Action<bool> callback)
// ShouldReopenOnStart, SaveState and LoadState are default methods of PersistedDocument.
public override bool ShouldReopenOnStart
{
// TODO: Show save prompt.
callback(!IsDirty);
get { return (FilePath != null); } // if FilePath is null, SaveState() will generate an NullExceptionError
}

public override void SaveState(BinaryWriter writer)
{
writer.Write(FilePath);
}

public override async void LoadState(BinaryReader reader)
{
await Load(reader.ReadString());
}

public override async void CanClose(System.Action<bool> callback)
{
if (IsDirty)
{
// Show save prompt.
// Note that CanClose method of Demo ShellViewModel blocks this.
string title = IoC.Get<IMainWindow>().Title;
string fileName = Path.GetFileNameWithoutExtension(FileName);
string fileExtension = Path.GetExtension(FileName);
var fileType = IoC.GetAll<IEditorProvider>()
.SelectMany(x => x.FileTypes)
.SingleOrDefault(x => x.FileExtension == fileExtension);

string message = string.Format(Resources.SaveChangesBeforeClosingMessage, fileType.Name, fileName);
var result = MessageBox.Show(message, title, MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);

if (result == MessageBoxResult.Yes)
{
if (IsNew)
{
// Ask new file path.
var filter = string.Empty;
if (fileType != null)
filter = fileType.Name + "|*" + fileType.FileExtension + "|";
filter += Properties.Resources.AllFiles + "|*.*";

var dialog = new SaveFileDialog() { FileName = this.FileName, Filter = filter };
if (dialog.ShowDialog() == true)
{
// Save file.
await Save(dialog.FileName);

// Add to recent files. Temporally, commented out.
//IShell _shell = IoC.Get<IShell>();
//_shell.RecentFiles.Update(dialog.FileName);
}
else
{
callback(false);
return;
}
}
else
{
// Save file.
await Save(FilePath);
}
}
else if (result == MessageBoxResult.Cancel)
{
callback(false);
return;
}
}

callback(true);
}

private void UpdateDisplayName()
Expand Down

0 comments on commit 3ce5eca

Please sign in to comment.