Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RecentFiles module #237

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions src/Gemini/Framework/Document.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ Task ICommandHandler<RedoCommandDefinition>.Run(Command command)

void ICommandHandler<SaveFileCommandDefinition>.Update(Command command)
{
command.Enabled = this is IPersistedDocument;
var persistedDocument = this as IPersistedDocument;
command.Enabled = (persistedDocument != null && persistedDocument.IsDirty);
}

async Task ICommandHandler<SaveFileCommandDefinition>.Run(Command command)
Expand Down Expand Up @@ -138,7 +139,7 @@ private static async Task DoSaveAs(IPersistedDocument persistedDocument)
if (fileType != null)
filter = fileType.Name + "|*" + fileType.FileExtension + "|";

filter += "All Files|*.*";
filter += Properties.Resources.AllFiles + "|*.*";
dialog.Filter = filter;

if (dialog.ShowDialog() != true)
Expand All @@ -148,6 +149,10 @@ private static async Task DoSaveAs(IPersistedDocument persistedDocument)

// Save file.
await persistedDocument.Save(filePath);

// Add to recent files
IShell _shell = IoC.Get<IShell>();
_shell.RecentFiles.Update(filePath);
}
}
}
1 change: 1 addition & 0 deletions src/Gemini/Framework/IPersistedDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ namespace Gemini.Framework
public interface IPersistedDocument : IDocument
{
bool IsNew { get; }
bool IsDirty { get; }
string FileName { get; }
string FilePath { get; }

Expand Down
11 changes: 8 additions & 3 deletions src/Gemini/Framework/Services/IShell.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using System;
using System;
using Caliburn.Micro;
using Gemini.Modules.MainMenu;
using Gemini.Modules.StatusBar;
using Gemini.Modules.ToolBars;
using Gemini.Modules.RecentFiles;

namespace Gemini.Framework.Services
{
Expand All @@ -16,6 +17,7 @@ public interface IShell : IGuardClose, IDeactivate
IMenu MainMenu { get; }
IToolBars ToolBars { get; }
IStatusBar StatusBar { get; }
IRecentFiles RecentFiles { get; }

// TODO: Rename this to ActiveItem.
ILayoutItem ActiveLayoutItem { get; set; }
Expand All @@ -29,9 +31,12 @@ public interface IShell : IGuardClose, IDeactivate
void ShowTool<TTool>() where TTool : ITool;
void ShowTool(ITool model);

void OpenDocument(IDocument model);
bool TryActivateDocumentByPath(string path);
void TryOpenDocumentByPath(string path);

void OpenDocument(IDocument model);
void CloseDocument(IDocument document);

void Close();
}
}
}
8 changes: 8 additions & 0 deletions src/Gemini/Gemini.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@
<Compile Include="Modules\MainMenu\Views\MainMenuSettingsView.xaml.cs">
<DependentUpon>MainMenuSettingsView.xaml</DependentUpon>
</Compile>
<Compile Include="Modules\RecentFiles\Commands\OpenRecentFileCommandHandler.cs" />
<Compile Include="Modules\RecentFiles\Commands\OpenRecentFileCommandListDefinition.cs" />
<Compile Include="Modules\RecentFiles\Commands\RecentFilesCommandDefinition.cs" />
<Compile Include="Modules\RecentFiles\Commands\RecentFilesCommandHandler.cs" />
<Compile Include="Modules\RecentFiles\IRecentFiles.cs" />
<Compile Include="Modules\RecentFiles\MenuDefinitions.cs" />
<Compile Include="Modules\RecentFiles\ViewModels\RecentFileItemViewModel.cs" />
<Compile Include="Modules\RecentFiles\ViewModels\RecentFileViewModel.cs" />
<Compile Include="Modules\Settings\Commands\OpenSettingsCommandDefinition.cs" />
<Compile Include="Modules\Settings\Commands\OpenSettingsCommandHandler.cs" />
<Compile Include="Modules\Settings\ISettingsEditor.cs" />
Expand Down
3 changes: 3 additions & 0 deletions src/Gemini/Modules/MainMenu/MenuDefinitions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ public static class MenuDefinitions
[Export]
public static MenuItemGroupDefinition FileSaveMenuGroup = new MenuItemGroupDefinition(FileMenu, 6);

[Export]
public static MenuItemGroupDefinition FileOpenRecentMenuGroup = new MenuItemGroupDefinition(FileMenu, 9);

[Export]
public static MenuItemGroupDefinition FileExitOpenMenuGroup = new MenuItemGroupDefinition(FileMenu, 10);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Caliburn.Micro;
using Gemini.Framework;
using Gemini.Framework.Commands;
using Gemini.Framework.Services;
using Gemini.Modules.Shell.Commands;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace Gemini.Modules.RecentFiles.Commands
{
[CommandHandler]
public class OpenRecentFileCommandHandler : ICommandListHandler<OpenRecentFileCommandListDefinition>
{
private readonly IShell _shell;

[ImportingConstructor]
public OpenRecentFileCommandHandler(IShell shell)
{
_shell = shell;
}

public void Populate(Command command, List<Command> commands)
{
for (var i = 0; i < _shell.RecentFiles.Items.Count; i++)
{
var item = _shell.RecentFiles.Items[i];
commands.Add(new Command(command.CommandDefinition)
{
Text = string.Format("_{0} {1}", i + 1, item.DisplayName),
ToolTip = item.FilePath,
Tag = item.FilePath
});
}
}

public async Task Run(Command command)
{
var newPath = (string)command.Tag;

// Check if the document is already open
foreach (var document in _shell.Documents.OfType<PersistedDocument>().Where(d => !d.IsNew))
{
if (string.IsNullOrEmpty(document.FilePath))
continue;

var docPath = Path.GetFullPath(document.FilePath);
if (string.Equals(newPath, docPath, System.StringComparison.OrdinalIgnoreCase))
{
_shell.OpenDocument(document);
return;
}
}

_shell.OpenDocument(await OpenFileCommandHandler.GetEditor(newPath));

// Add the file to the recent documents list
_shell.RecentFiles.Update(newPath);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Gemini.Framework.Commands;

namespace Gemini.Modules.RecentFiles.Commands
{
[CommandDefinition]
public class OpenRecentFileCommandListDefinition : CommandListDefinition
{
public const string CommandName = "File.OpenRecentFileList";

public override string Name
{
get { return CommandName; }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Gemini.Framework.Commands;
using Gemini.Properties;

namespace Gemini.Modules.RecentFiles.Commands
{
[CommandDefinition]
public class RecentFilesCommandDefinition : CommandDefinition
{
public const string CommandName = "File.RecentFiles";

public override string Name
{
get { return CommandName; }
}

public override string Text
{
get { return Resources.FileRecentFilesCommandText; }
}

public override string ToolTip
{
get { return Resources.FileRecentFilesCommandToolTip; }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Gemini.Framework.Commands;
using Gemini.Framework.Services;
using System.ComponentModel.Composition;
using System.Threading.Tasks;

namespace Gemini.Modules.RecentFiles.Commands
{
[CommandHandler]
public class RecentFilesCommandHandler : CommandHandlerBase<RecentFilesCommandDefinition>
{
private readonly IShell _shell;

[ImportingConstructor]
public RecentFilesCommandHandler(IShell shell)
{
_shell = shell;
}

public override void Update(Command command)
{
command.Enabled = (_shell.RecentFiles.Items.Count > 0);
}

public override Task Run(Command command)
{
return null;
}
}
}
12 changes: 12 additions & 0 deletions src/Gemini/Modules/RecentFiles/IRecentFiles.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Caliburn.Micro;
using Gemini.Modules.RecentFiles.ViewModels;

namespace Gemini.Modules.RecentFiles
{
public interface IRecentFiles
{
IObservableCollection<RecentFileItemViewModel> Items { get; }

void Update(string filePath);
}
}
26 changes: 26 additions & 0 deletions src/Gemini/Modules/RecentFiles/MenuDefinitions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Gemini.Framework.Menus;
using Gemini.Modules.RecentFiles.Commands;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Gemini.Modules.RecentFiles
{
public static class MenuDefinitions
{
[Export]
public static MenuItemDefinition FileRecentFilesMenuItem = new CommandMenuItemDefinition<RecentFilesCommandDefinition>(
MainMenu.MenuDefinitions.FileOpenRecentMenuGroup, 0);

[Export]
public static MenuItemGroupDefinition FileRecentFilesCascadeGroup = new MenuItemGroupDefinition(
FileRecentFilesMenuItem, 0);

[Export]
public static MenuItemDefinition FileOpenRecentMenuItemList = new CommandMenuItemDefinition<OpenRecentFileCommandListDefinition>(
FileRecentFilesCascadeGroup, 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using Caliburn.Micro;

namespace Gemini.Modules.RecentFiles.ViewModels
{
public class RecentFileItemViewModel : PropertyChangedBase
{
private int _index;
public int Index
{
get { return _index; }
internal set
{
_index = value;
NotifyOfPropertyChange(() => Index);
}
}

private string _filePath;
public string FilePath
{
get { return _filePath; }
set
{
_filePath = value;
_displayName = ShortenPath(_filePath);
NotifyOfPropertyChange(() => FilePath);
}
}

private string _displayName;
public string DisplayName
{
get { return _displayName; }
}

// TODO: will implement Pinned
private bool _pinned = false;
public bool Pinned
{
get { return _pinned; }
set
{
_pinned = value;
NotifyOfPropertyChange(() => Pinned);
}
}

public RecentFileItemViewModel(string filePath, bool pinned = false)
{
_filePath = filePath;
_displayName = ShortenPath(filePath);

_pinned = pinned;
}

// http://stackoverflow.com/questions/8360360/function-to-shrink-file-path-to-be-more-human-readable
private string ShortenPath(string path, int maxLength = 50)
{
string[] splits = path.Split('\\');

string output = "";

if (splits.Length > 4)
output = splits[0] + "\\" + splits[1] + "\\...\\" + splits[splits.Length - 2] + "\\" + splits[splits.Length - 1];
else
output = string.Join("\\", splits, 0, splits.Length);

return output;
}
}
}
Loading