Skip to content

Commit

Permalink
Add RecentFiles module
Browse files Browse the repository at this point in the history
  • Loading branch information
diluculo committed Jun 1, 2018
1 parent ac0b9da commit e467131
Show file tree
Hide file tree
Showing 18 changed files with 466 additions and 8 deletions.
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
3 changes: 3 additions & 0 deletions src/Gemini/Framework/Services/IShell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
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,6 +31,7 @@ public interface IShell : IGuardClose, IDeactivate
void ShowTool<TTool>() where TTool : ITool;
void ShowTool(ITool model);

bool TryActivateDocumentByPath(string path);
void OpenDocument(IDocument model);
void CloseDocument(IDocument document);

Expand Down
8 changes: 8 additions & 0 deletions src/Gemini/Gemini.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,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

0 comments on commit e467131

Please sign in to comment.