Skip to content

Commit

Permalink
Merge pull request #22 from Haacked/haacked/browse-folder-dialog
Browse files Browse the repository at this point in the history
Haacked browse folder dialog
  • Loading branch information
haacked committed Mar 11, 2015
2 parents e268287 + 89a87b3 commit 53a0383
Show file tree
Hide file tree
Showing 15 changed files with 283 additions and 69 deletions.
2 changes: 1 addition & 1 deletion src/DependencyRegistrationHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ private static ReadOnlyDictionary<Type, DependencyInfo> CreateDependencyDictiona
var operatingSystemFacade = new OperatingSystemFacade();

var dependencies = new Dictionary<Type, DependencyInfo>();
dependencies.Add<IOperatingSystemFacade>(operatingSystemFacade);
dependencies.Add<IOperatingSystem>(operatingSystemFacade);
dependencies.Add(operatingSystemFacade.Assembly);
dependencies.Add(operatingSystemFacade.Environment);
dependencies.Add(operatingSystemFacade.Dialog);
Expand Down
4 changes: 2 additions & 2 deletions src/Environment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public class Environment : IEnvironment
{
public Environment()
{
OSVersion = new OperatingSystem(Env.OSVersion);
OSVersion = new OperatingSystemInfo(Env.OSVersion);
}

public string CommandLine
Expand Down Expand Up @@ -53,7 +53,7 @@ public string NewLine
get { return Env.NewLine; }
}

public IOperatingSystem OSVersion
public IOperatingSystemInfo OSVersion
{
get; private set;
}
Expand Down
58 changes: 58 additions & 0 deletions src/Infrastructure/BrowseDirectoryResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System;
using NullGuard;

namespace Rothko
{
public struct BrowseDirectoryResult
{
readonly bool _success;
readonly string _directoryPath;

/// <summary>
/// Represents a failed browse result.
/// </summary>
public static readonly BrowseDirectoryResult Failed = new BrowseDirectoryResult();

public BrowseDirectoryResult(string directoryPath)
{
if (directoryPath.Length == 0) throw new ArgumentException("Selected path cannot be empty", "directoryPath");

_success = true;
_directoryPath = directoryPath;
}

public bool Success
{
get { return _success; }
}

public string DirectoryPath
{
get { return _directoryPath; }
}

public override bool Equals([AllowNull]object obj)
{
if (!(obj is BrowseDirectoryResult)) return false;
return this == ((BrowseDirectoryResult)obj);
}

public static bool operator ==(BrowseDirectoryResult a, BrowseDirectoryResult b)
{
return a._success == b._success && a._directoryPath == b._directoryPath;
}

public static bool operator !=(BrowseDirectoryResult a, BrowseDirectoryResult b)
{
return !(a == b);
}

public override int GetHashCode()
{
unchecked
{
return (17327 * 67 + _success.GetHashCode()) * 67 + (_directoryPath ?? "").GetHashCode();
}
}
}
}
59 changes: 59 additions & 0 deletions src/Infrastructure/Browser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;

namespace Rothko.Infrastructure
{
public class Browser : IBrowser
{
readonly IProcessStarter processStarter;
readonly IEnvironment environment;

public Browser(IProcessStarter processStarter, IEnvironment environment)
{
this.processStarter = processStarter;
this.environment = environment;
}

[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
Justification = "We can't anticipate the type of exception it'll throw and we want to have the fallback behavior")]
public void OpenUrl(Uri url)
{
if (url.IsAbsoluteUri) throw new ArgumentException("URL must be an absolute uri", "url");

try
{
processStarter.Start(url.ToString(), null);
}
catch (Exception firstAttemptException)
{
try
{
var programFiles = environment.GetFolderPath(System.Environment.SpecialFolder.ProgramFiles);

processStarter.Start(Path.Combine(programFiles, @"Internet Explorer", "iexplore.exe"),
url.ToString());
}
catch (Exception secondAttemptException)
{
throw new AggregateException(firstAttemptException, secondAttemptException);
}
}
}

[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
Justification = "By design, this method should not throw.")]
public bool TryOpenUrl(Uri url)
{
try
{
OpenUrl(url);
return true;
}
catch (Exception)
{
}
return false;
}
}
}
28 changes: 25 additions & 3 deletions src/Infrastructure/DialogFacade.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Microsoft.Win32;
using System.Windows.Forms;
using SaveFileDialog = Microsoft.Win32.SaveFileDialog;

namespace Rothko
{
Expand All @@ -12,8 +13,29 @@ public SaveDialogResult ShowSaveFileDialog(string filterPattern)
};

return dialog.ShowDialog() == true
? new SaveDialogResult(true, dialog.FileName)
: new SaveDialogResult(false, null);
? new SaveDialogResult(dialog.FileName)
: SaveDialogResult.Failed;
}

public BrowseDirectoryResult BrowseForDirectory(string selectedPath, string title)
{
using (var folderBrowser = new FolderBrowserDialog())
{
folderBrowser.RootFolder = System.Environment.SpecialFolder.Desktop;
folderBrowser.SelectedPath = selectedPath;
folderBrowser.ShowNewFolderButton = false;

if (title != null)
{
folderBrowser.Description = title;
}

var dialogResult = folderBrowser.ShowDialog();

return dialogResult == DialogResult.OK
? new BrowseDirectoryResult(folderBrowser.SelectedPath)
: BrowseDirectoryResult.Failed;
}
}
}
}
20 changes: 20 additions & 0 deletions src/Infrastructure/IBrowser.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace Rothko
{
public interface IBrowser
{
/// <summary>
/// Opens the user's default browser to the specified URL.
/// </summary>
/// <param name="url"></param>
void OpenUrl(Uri url);

/// <summary>
/// Opens the user's default browser to the specified URL and returns false if it was unable to.
/// </summary>
/// <param name="url"></param>
bool TryOpenUrl(Uri url);
}
}

35 changes: 12 additions & 23 deletions src/Infrastructure/IDialogFacade.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,19 @@ namespace Rothko
{
public interface IDialogFacade
{
/// <summary>
/// Displays a save file dialog and returns the result of the user's interaction with the dialog.
/// </summary>
/// <param name="filterPattern">Pattern used to filter the files shown</param>
/// <returns></returns>
SaveDialogResult ShowSaveFileDialog(string filterPattern);
}

[SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes",
Justification = "TODO: Should this even be a struct?")]
public struct SaveDialogResult
{
readonly bool _success;
readonly string _fileName;

public SaveDialogResult(bool success, string chosenFileName)
{
_success = success;
_fileName = chosenFileName;
}

public bool Success
{
get { return _success; }
}

public string FileName
{
get { return _fileName; }
}
/// <summary>
/// Opens a standard Windows browse directory and returns the result.
/// </summary>
/// <param name="selectedPath">The default selected path</param>
/// <param name="title">The title to show on the dialog</param>
/// <returns></returns>
BrowseDirectoryResult BrowseForDirectory(string selectedPath, string title);
}
}
2 changes: 1 addition & 1 deletion src/Infrastructure/IEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public interface IEnvironment

string NewLine { get; }

IOperatingSystem OSVersion { get; }
IOperatingSystemInfo OSVersion { get; }

int ProcessorCount { get; }

Expand Down
25 changes: 13 additions & 12 deletions src/Infrastructure/IOperatingSystem.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
using System;
using System.Runtime.Serialization;

namespace Rothko
namespace Rothko
{
public interface IOperatingSystem : ICloneable, ISerializable
public interface IOperatingSystem
{
PlatformID Platform { get; }
string ServicePack { get; }
Version Version { get; }
string VersionString { get; }
string Name { get; }
string Edition { get; }
IAssemblyFacade Assembly { get; }
IDialogFacade Dialog { get; }
IDirectoryFacade Directory { get; }
IEnvironment Environment { get; }
IFileFacade File { get; }
IMemoryMappedFileFactory MemoryMappedFiles { get; }
IProcessLocator ProcessLocator { get; }
IProcessStarter ProcessStarter { get; }
IRegistry Registry { get; }
IBrowser Browser { get; }
}
}
}
15 changes: 0 additions & 15 deletions src/Infrastructure/IOperatingSystemFacade.cs

This file was deleted.

15 changes: 15 additions & 0 deletions src/Infrastructure/IOperatingSystemInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Runtime.Serialization;

namespace Rothko
{
public interface IOperatingSystemInfo : ICloneable, ISerializable
{
PlatformID Platform { get; }
string ServicePack { get; }
Version Version { get; }
string VersionString { get; }
string Name { get; }
string Edition { get; }
}
}
52 changes: 52 additions & 0 deletions src/Infrastructure/SaveDialogResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using NullGuard;

namespace Rothko
{
public struct SaveDialogResult
{
readonly bool _success;
readonly string _fileName;

public static readonly SaveDialogResult Failed = new SaveDialogResult();

public SaveDialogResult(string chosenFileName)
{
_success = true;
_fileName = chosenFileName;
}

public bool Success
{
get { return _success; }
}

public string FileName
{
get { return _fileName; }
}

public override bool Equals([AllowNull]object obj)
{
if (!(obj is SaveDialogResult)) return false;
return this == ((SaveDialogResult)obj);
}

public static bool operator ==(SaveDialogResult a, SaveDialogResult b)
{
return a._success == b._success && a._fileName == b._fileName;
}

public static bool operator !=(SaveDialogResult a, SaveDialogResult b)
{
return !(a == b);
}

public override int GetHashCode()
{
unchecked
{
return (17327 * 67 + _success.GetHashCode()) * 67 + (_fileName ?? "").GetHashCode();
}
}
}
}
Loading

0 comments on commit 53a0383

Please sign in to comment.