OSDN Git Service

Ver.1.0.0.185 Task187 Interface based design
authorTakayoshi Matsuyama <tkys0515@gmail.com>
Wed, 1 Apr 2015 20:14:50 +0000 (05:14 +0900)
committerTakayoshi Matsuyama <tkys0515@gmail.com>
Thu, 2 Apr 2015 20:14:33 +0000 (05:14 +0900)
131 files changed:
Main/App.config
Main/App.xaml
Main/App.xaml.cs
Main/Bootstrapper.cs [new file with mode: 0644]
Main/Documents/Screenshot.png [new file with mode: 0644]
Main/Properties/AssemblyInfo.cs
Main/Properties/Settings.Designer.cs
Main/Properties/Settings.settings
Main/SimpleBackup.Core/AppInfrastructure/IAppComponent.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Models/BackupSourceType.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Models/BackupState.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Models/IBackupInfo.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Models/IBackupSetting.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Models/IDestinationPathInfo.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Models/IModelFactory.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Models/IResultInfo.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Models/ItemMovingDirection.cs [new file with mode: 0644]
Main/SimpleBackup.Core/ObjectContainer.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Services/FileBackupProgressEventArgs.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Services/IBackupService.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Services/IBackupSettingService.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Services/IClipboardService.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Services/ISettingsService.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Services/IUndoRedoService.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Services/SettingFileEventArgs.cs [new file with mode: 0644]
Main/SimpleBackup.Core/SimpleBackup.Core.csproj [new file with mode: 0644]
Main/SimpleBackup.Core/SimpleBackupKey.snk [new file with mode: 0644]
Main/SimpleBackup.Core/Utilities/Constants.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Utilities/HelperExtensions.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Utilities/Helpers.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Utilities/IdIndexPair.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Utilities/PropertyChangeNotificationBase.cs [new file with mode: 0644]
Main/SimpleBackup.Core/ViewModels/BackupInfoPathType.cs [new file with mode: 0644]
Main/SimpleBackup.Core/ViewModels/FocusOnGridRowEventArgs.cs [new file with mode: 0644]
Main/SimpleBackup.Core/ViewModels/IBackupInfoViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.Core/ViewModels/IDestinationColumnHeaderViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.Core/ViewModels/ILabelColumnHeaderViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.Core/ViewModels/IMainWindowViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.Core/ViewModels/ISourceColumnHeaderViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.Core/ViewModels/IViewModelFactory.cs [new file with mode: 0644]
Main/SimpleBackup.Core/ViewModels/PasteType.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Views/ExDataGridSelectedFirstCellItemChangedEventArgs.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Views/IFileFolderDialog.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Views/IMainWindow.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Views/IVersionInformationWindow.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Views/IViewFactory.cs [new file with mode: 0644]
Main/SimpleBackup.Core/Views/RelayCommand.cs [new file with mode: 0644]
Main/SimpleBackup.Models/BackupInfo.cs [new file with mode: 0644]
Main/SimpleBackup.Models/BackupSetting.cs [new file with mode: 0644]
Main/SimpleBackup.Models/DestinationPathInfo.cs [new file with mode: 0644]
Main/SimpleBackup.Models/ModelComponent.cs [new file with mode: 0644]
Main/SimpleBackup.Models/ModelFactory.cs [new file with mode: 0644]
Main/SimpleBackup.Models/ResultInfo.cs [new file with mode: 0644]
Main/SimpleBackup.Models/SimpleBackup.Models.csproj [new file with mode: 0644]
Main/SimpleBackup.Models/SimpleBackupKey.snk [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Activity_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/AddVariable_5541.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/ApplicationIcon.ico [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Arrow_RedoRetry_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Arrow_UndoRevertRestore_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Copy_6524.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Cut_6523.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Delete_black_32x32.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/FileGroup_10135_32x.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/NewFile_6276.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Open_6529.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Paste_6520.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Print_11009.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/StatusAnnotations_Complete_and_ok_32xLG_color.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/StatusAnnotations_Critical_32xLG_color.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Symbols_Complete_and_ok_32xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Synchronize_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/Warning.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/action_Cancel_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/arrow_Down_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/arrow_Up_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/arrow_all_run_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/arrow_run_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/document_32xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/flag_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/refresh_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/Images/save_16xLG.png [new file with mode: 0644]
Main/SimpleBackup.Resources/ResourceHelper.cs [new file with mode: 0644]
Main/SimpleBackup.Resources/Resources.Designer.cs [new file with mode: 0644]
Main/SimpleBackup.Resources/Resources.ja.resx [new file with mode: 0644]
Main/SimpleBackup.Resources/Resources.resx [new file with mode: 0644]
Main/SimpleBackup.Resources/SimpleBackup.Resources.csproj [new file with mode: 0644]
Main/SimpleBackup.Resources/SimpleBackupKey.snk [new file with mode: 0644]
Main/SimpleBackup.Services/BackupService.cs [new file with mode: 0644]
Main/SimpleBackup.Services/BackupSettingService.cs [new file with mode: 0644]
Main/SimpleBackup.Services/ClipboardService.cs [new file with mode: 0644]
Main/SimpleBackup.Services/Properties/Settings.Designer.cs [new file with mode: 0644]
Main/SimpleBackup.Services/Properties/Settings.settings [new file with mode: 0644]
Main/SimpleBackup.Services/ServiceComponent.cs [new file with mode: 0644]
Main/SimpleBackup.Services/SettingsService.cs [new file with mode: 0644]
Main/SimpleBackup.Services/SimpleBackup.Services.csproj [new file with mode: 0644]
Main/SimpleBackup.Services/SimpleBackupKey.snk [new file with mode: 0644]
Main/SimpleBackup.Services/UndoRedoActionSet.cs [new file with mode: 0644]
Main/SimpleBackup.Services/UndoRedoService.cs [new file with mode: 0644]
Main/SimpleBackup.Services/app.config [new file with mode: 0644]
Main/SimpleBackup.ViewModels/BackupInfoPasteInfo.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/BackupInfoViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/DataGridColumnHeaderBaseViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/DestinationColumnHeaderViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/EncodingInfoItemViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/IndexBackupInfoViewModelPair.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/IsZipArchiveColumnHeaderViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/LabelColumnHeaderViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/MainWindowViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/ProgressViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/SimpleBackup.ViewModels.csproj [new file with mode: 0644]
Main/SimpleBackup.ViewModels/SimpleBackupKey.snk [new file with mode: 0644]
Main/SimpleBackup.ViewModels/SourceColumnHeaderViewModel.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/ViewModelComponent.cs [new file with mode: 0644]
Main/SimpleBackup.ViewModels/ViewModelFactory.cs [new file with mode: 0644]
Main/SimpleBackup.Views/BackupSourceTypeToImageConverter.cs [new file with mode: 0644]
Main/SimpleBackup.Views/BackupStateToImageConverter.cs [new file with mode: 0644]
Main/SimpleBackup.Views/ExDataGrid.cs [new file with mode: 0644]
Main/SimpleBackup.Views/ExDataGridSelectedFirstCellItemBehavior.cs [new file with mode: 0644]
Main/SimpleBackup.Views/FileFolderDialog.cs [new file with mode: 0644]
Main/SimpleBackup.Views/MainWindow.xaml [new file with mode: 0644]
Main/SimpleBackup.Views/MainWindow.xaml.cs [new file with mode: 0644]
Main/SimpleBackup.Views/SimpleBackup.Views.csproj [new file with mode: 0644]
Main/SimpleBackup.Views/SimpleBackupKey.snk [new file with mode: 0644]
Main/SimpleBackup.Views/VersionInformationWindow.xaml [new file with mode: 0644]
Main/SimpleBackup.Views/VersionInformationWindow.xaml.cs [new file with mode: 0644]
Main/SimpleBackup.Views/ViewComponent.cs [new file with mode: 0644]
Main/SimpleBackup.Views/ViewFactory.cs [new file with mode: 0644]
Main/SimpleBackup.csproj
Main/SimpleBackup.psess [new file with mode: 0644]
Main/SimpleBackup.sln

index 4d0f454..89a67b9 100644 (file)
@@ -13,25 +13,12 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
 -->
 <configuration>
     <configSections>
-        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
-            <section name="SimpleBackup.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
-        </sectionGroup>
     </configSections>
     <startup> 
         <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
     </startup>
-    <userSettings>
-        <SimpleBackup.Properties.Settings>
-            <setting name="DefaultSettingFileName" serializeAs="String">
-                <value />
-            </setting>
-            <setting name="DefaultZipEncodingKeyText" serializeAs="String">
-                <value />
-            </setting>
-        </SimpleBackup.Properties.Settings>
-    </userSettings>
 </configuration>
\ No newline at end of file
index 89f7c69..55ca79c 100644 (file)
@@ -12,12 +12,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
 -->
+    
 <Application x:Class="SimpleBackup.App"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
-    <Application.Resources>
-         
-    </Application.Resources>
-</Application>
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"/>
index b3a2597..4fac83b 100644 (file)
 // GNU General Public License for more details.
 //
 // You should have received a copy of the GNU General Public License
-// along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
-
-using System;
-using System.Windows;
-using SimpleBackup.Services;
-using SimpleBackup.ViewModels;
-using SimpleBackup.Views;
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
 
 namespace SimpleBackup
 {
+    using System;
+    using System.Windows;
+    using SimpleBackup.Core;
+    using SimpleBackup.Core.Services;
+    using SimpleBackup.Core.ViewModels;
+    using SimpleBackup.Core.Views;
+
     /// <summary>
-    /// App.xaml の相互作用ロジック
+    /// The Code-Behind of App.xaml.
     /// </summary>
     public partial class App : Application
     {
+        /// <summary>
+        ///   Raises the <see cref="E:System.Windows.Application.Startup" /> event.
+        /// </summary>
+        /// <param name="e">A <see cref="T:System.Windows.StartupEventArgs" /> that contains the event data.</param>
         protected override void OnStartup(StartupEventArgs e)
         {
             try
             {
-                var mainWindow = new MainWindow();
-                var mainWindowViewModel = new MainWindowViewModel();
+                var bootStrapper = new Bootstrapper();
+                bootStrapper.Execute();
+
+                var viewFactory = ObjectContainer.Resolve<IViewFactory>();
+                var viewModelFactory = ObjectContainer.Resolve<IViewModelFactory>();
+                IMainWindow mainWindow = viewFactory.CreateMainWindow();
+                IMainWindowViewModel mainWindowViewModel = viewModelFactory.CreateMainWindowViewModel();
                 mainWindow.DataContext = mainWindowViewModel;
                 mainWindow.Show();
             }
@@ -47,15 +57,20 @@ namespace SimpleBackup
             }
         }
 
+        /// <summary>
+        ///   Raises the <see cref="E:System.Windows.Application.Exit" /> event.
+        /// </summary>
+        /// <param name="e">An <see cref="T:System.Windows.ExitEventArgs" /> that contains the event data.</param>
         protected override void OnExit(ExitEventArgs e)
         {
             base.OnExit(e);
 
-            if (BackupSettingService.Instance.CurrentSetting != null)
+            var backupSettingService = ObjectContainer.Resolve<IBackupSettingService>();
+            if (backupSettingService.CurrentSetting != null)
             {
-                SimpleBackup.Properties.Settings.Default.DefaultSettingFileName =
-                    BackupSettingService.Instance.CurrentSetting.SettingFileName;
-                SimpleBackup.Properties.Settings.Default.Save();
+                var settingsService = ObjectContainer.Resolve<ISettingsService>();
+                settingsService.DefaultSettingFileName =
+                    backupSettingService.CurrentSetting.SettingFileName;
             }
         }
     }
diff --git a/Main/Bootstrapper.cs b/Main/Bootstrapper.cs
new file mode 100644 (file)
index 0000000..5e3b8aa
--- /dev/null
@@ -0,0 +1,97 @@
+//-----------------------------------------------------------------------
+// <copyright file="Bootstrapper.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup
+{
+    using System;
+    using System.Collections.Generic;
+    using System.IO;
+    using System.Linq;
+    using System.Reflection;
+    using SimpleBackup.Core.AppInfrastructure;
+
+    /// <summary>
+    /// Executes application starting procedure.
+    /// </summary>
+    public class Bootstrapper
+    {
+        /// <summary>
+        /// Executes application starting procedure.
+        /// </summary>
+        public void Execute()
+        {
+            IAppComponent[] appComponents = SearchApplicationComponents();
+            InitializeAppComponents(appComponents);
+        }
+
+        /// <summary>
+        /// Searches the application components.
+        /// </summary>
+        /// <returns>The collection of application component.</returns>
+        private static IAppComponent[] SearchApplicationComponents()
+        {
+            Type appComponenType = typeof(IAppComponent);
+            var appComponents = new HashSet<IAppComponent>();
+
+            Assembly executingAssembly = Assembly.GetExecutingAssembly();
+            string executingAssemblyFolder = Path.GetDirectoryName(executingAssembly.Location);
+            string[] files = Directory.GetFiles(executingAssemblyFolder, "*.dll");
+            foreach (string file in files)
+            {
+                Assembly assembly = Assembly.LoadFrom(file);
+                Type[] types = assembly.GetTypes();
+                foreach (Type type in types)
+                {
+                    Type[] interfaceTypes = type.GetInterfaces();
+                    foreach (Type interfaceType in interfaceTypes)
+                    {
+                        if ((interfaceType.FullName == appComponenType.FullName) &&
+                            (interfaceType.Assembly.FullName == appComponenType.Assembly.FullName))
+                        {
+                            appComponents.Add((IAppComponent)Activator.CreateInstance(type));
+                        }
+                    }
+                }
+            }
+
+            return appComponents.ToArray();
+        }
+
+        /// <summary>
+        /// Initializes the application components.
+        /// </summary>
+        /// <param name="appComponents">The application components.</param>
+        private static void InitializeAppComponents(IEnumerable<IAppComponent> appComponents)
+        {
+            foreach (IAppComponent appComponent in appComponents)
+            {
+                try
+                {
+                    appComponent.Initialize();
+                }
+                catch (Exception e)
+                {
+                    Console.WriteLine(e);
+                }
+            }
+        }
+    }
+}
diff --git a/Main/Documents/Screenshot.png b/Main/Documents/Screenshot.png
new file mode 100644 (file)
index 0000000..4528a2a
Binary files /dev/null and b/Main/Documents/Screenshot.png differ
index 4188813..ea5202c 100644 (file)
@@ -17,7 +17,7 @@
 // GNU General Public License for more details.
 //
 // You should have received a copy of the GNU General Public License
-// along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
 
 using System.Reflection;
 using System.Resources;
@@ -34,10 +34,10 @@ using System.Windows;
 [assembly: AssemblyCulture("")]
 [assembly: ComVisible(false)]
 
-[assembly: ThemeInfo(
-    ResourceDictionaryLocation.None,
-    ResourceDictionaryLocation.SourceAssembly)]
+//[assembly: ThemeInfo(
+//   ResourceDictionaryLocation.None,
+//    ResourceDictionaryLocation.SourceAssembly)]
 
-[assembly: AssemblyVersion("1.0.0.182")]
-[assembly: AssemblyFileVersion("1.0.0.182")]
+[assembly: AssemblyVersion("1.0.0.185")]
+[assembly: AssemblyFileVersion("1.0.0.185")]
 [assembly: NeutralResourcesLanguageAttribute("en")]
index 1735088..99259b0 100644 (file)
@@ -22,29 +22,5 @@ namespace SimpleBackup.Properties {
                 return defaultInstance;
             }
         }
-        
-        [global::System.Configuration.UserScopedSettingAttribute()]
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-        [global::System.Configuration.DefaultSettingValueAttribute("")]
-        public string DefaultSettingFileName {
-            get {
-                return ((string)(this["DefaultSettingFileName"]));
-            }
-            set {
-                this["DefaultSettingFileName"] = value;
-            }
-        }
-        
-        [global::System.Configuration.UserScopedSettingAttribute()]
-        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-        [global::System.Configuration.DefaultSettingValueAttribute("")]
-        public string DefaultZipEncodingKeyText {
-            get {
-                return ((string)(this["DefaultZipEncodingKeyText"]));
-            }
-            set {
-                this["DefaultZipEncodingKeyText"] = value;
-            }
-        }
     }
 }
index cec136e..8e615f2 100644 (file)
@@ -1,12 +1,5 @@
 <?xml version='1.0' encoding='utf-8'?>
-<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="SimpleBackup.Properties" GeneratedClassName="Settings">
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
   <Profiles />
-  <Settings>
-    <Setting Name="DefaultSettingFileName" Type="System.String" Scope="User">
-      <Value Profile="(Default)" />
-    </Setting>
-    <Setting Name="DefaultZipEncodingKeyText" Type="System.String" Scope="User">
-      <Value Profile="(Default)" />
-    </Setting>
-  </Settings>
+  <Settings />
 </SettingsFile>
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/AppInfrastructure/IAppComponent.cs b/Main/SimpleBackup.Core/AppInfrastructure/IAppComponent.cs
new file mode 100644 (file)
index 0000000..9fed912
--- /dev/null
@@ -0,0 +1,34 @@
+//-----------------------------------------------------------------------
+// <copyright file="IAppComponent.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.AppInfrastructure
+{
+    /// <summary>
+    /// Interface of an application component.
+    /// </summary>
+    public interface IAppComponent
+    {
+        /// <summary>
+        /// Initializes this application component.
+        /// </summary>
+        void Initialize();
+    }
+}
diff --git a/Main/SimpleBackup.Core/Models/BackupSourceType.cs b/Main/SimpleBackup.Core/Models/BackupSourceType.cs
new file mode 100644 (file)
index 0000000..1befdbf
--- /dev/null
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="BackupSourceType.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Models
+{
+    /// <summary>
+    /// Represents backup source type.
+    /// </summary>
+    public enum BackupSourceType
+    {
+        /// <summary>
+        /// The file
+        /// </summary>
+        File,
+
+        /// <summary>
+        /// The folder
+        /// </summary>
+        Folder
+    }
+}
diff --git a/Main/SimpleBackup.Core/Models/BackupState.cs b/Main/SimpleBackup.Core/Models/BackupState.cs
new file mode 100644 (file)
index 0000000..57c755c
--- /dev/null
@@ -0,0 +1,59 @@
+//-----------------------------------------------------------------------
+// <copyright file="BackupState.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Models
+{
+    /// <summary>
+    /// Represents backup state.
+    /// </summary>
+    public enum BackupState
+    {
+        /// <summary>
+        /// The to do
+        /// </summary>
+        Todo,
+
+        /// <summary>
+        /// The in progress
+        /// </summary>
+        InProgress,
+
+        /// <summary>
+        /// The success
+        /// </summary>
+        Success,
+
+        /// <summary>
+        /// The failed
+        /// </summary>
+        Failed,
+
+        /// <summary>
+        /// The cancelled
+        /// </summary>
+        Cancelled,
+
+        /// <summary>
+        /// The skipped
+        /// </summary>
+        Skipped,
+    }
+}
diff --git a/Main/SimpleBackup.Core/Models/IBackupInfo.cs b/Main/SimpleBackup.Core/Models/IBackupInfo.cs
new file mode 100644 (file)
index 0000000..c5ac655
--- /dev/null
@@ -0,0 +1,101 @@
+//-----------------------------------------------------------------------
+// <copyright file="IBackupInfo.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Models
+{
+    using System;
+    using System.ComponentModel;
+    using System.Xml.Linq;
+
+    /// <summary>
+    /// A interface of single backup information.
+    /// </summary>
+    public interface IBackupInfo : INotifyPropertyChanged
+    {
+        /// <summary>
+        /// Occurs when a property which has to be saved in setting file is changed.
+        /// </summary>
+        event EventHandler<EventArgs> SettingFilePropertyChanged;
+
+        /// <summary>
+        /// Gets or sets the identifier.
+        /// </summary>
+        Guid Id { get; set; }
+
+        /// <summary>
+        /// Gets or sets the label.
+        /// </summary>
+        string Label { get; set; }
+
+        /// <summary>
+        /// Gets or sets the type of the backup source.
+        /// </summary>
+        BackupSourceType BackupSourceType { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the backup is enabled.
+        /// </summary>
+        bool IsEnabled { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the backup is zip archive.
+        /// </summary>
+        bool IsZipArchive { get; set; }
+
+        /// <summary>
+        /// Gets or sets the source path.
+        /// </summary>
+        string SourcePath { get; set; }
+
+        /// <summary>
+        /// Gets or sets the destination folder path.
+        /// </summary>
+        string DestinationFolderPath { get; set; }
+
+        /// <summary>
+        /// Gets or sets the state of the backup.
+        /// </summary>
+        BackupState BackupState { get; set; }
+
+        /// <summary>
+        /// Gets or sets the name of the latest successful backup target.
+        /// </summary>
+        string LatestSuccessfulBackupTargetName { get; set; }
+
+        /// <summary>
+        /// Saves this instance to a XElement.
+        /// </summary>
+        /// <returns>The generated XElement.</returns>
+        XElement ToXml();
+
+        /// <summary>
+        /// Gets the binary representation of this instance.
+        /// </summary>
+        /// <returns>The binary representation of this instance.</returns>
+        byte[] ToBinary();
+
+        /// <summary>
+        /// Gets the formatted text representation of this instance.
+        /// </summary>
+        /// <returns>The text representation of this instance.</returns>
+        string ToFormattedText();
+    }
+}
diff --git a/Main/SimpleBackup.Core/Models/IBackupSetting.cs b/Main/SimpleBackup.Core/Models/IBackupSetting.cs
new file mode 100644 (file)
index 0000000..ef11a85
--- /dev/null
@@ -0,0 +1,96 @@
+//-----------------------------------------------------------------------
+// <copyright file="IBackupSetting.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Models
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Xml.Linq;
+
+    /// <summary>
+    /// Interface of a backup setting.
+    /// </summary>
+    public interface IBackupSetting
+    {
+        /// <summary>
+        /// Occurs when backup setting is modified.
+        /// </summary>
+        event EventHandler SettingModified;
+
+        /// <summary>
+        /// Gets the name of the setting.
+        /// </summary>
+        string SettingName { get; }
+
+        /// <summary>
+        /// Gets or sets the name of the setting file.
+        /// </summary>
+        string SettingFileName { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this <see cref="IBackupSetting"/> is modified.
+        /// </summary>
+        bool Modified { get; set; }
+
+        /// <summary>
+        /// Gets the backup infos.
+        /// </summary>
+        IReadOnlyCollection<IBackupInfo> BackupInfos { get; }
+
+        /// <summary>
+        /// Gets the count of backup Information item.
+        /// </summary>
+        int Count { get; }
+
+        /// <summary>
+        /// Firsts the or default.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        /// <returns>The IBackupInfo which is firstly found or null.</returns>
+        IBackupInfo FirstOrDefault(Guid id);
+
+        /// <summary>
+        /// Inserts the specified index.
+        /// </summary>
+        /// <param name="index">The index.</param>
+        /// <param name="backupInfo">The backup information.</param>
+        void Insert(int index, IBackupInfo backupInfo);
+
+        /// <summary>
+        /// Removes the specified removing backup information.
+        /// </summary>
+        /// <param name="removingBackupInfo">The removing backup information.</param>
+        void Remove(IBackupInfo removingBackupInfo);
+
+        /// <summary>
+        /// Moves the item.
+        /// </summary>
+        /// <param name="backupInfoId">The backup information identifier.</param>
+        /// <param name="movingDirection">The moving direction.</param>
+        void MoveItem(Guid backupInfoId, ItemMovingDirection movingDirection);
+
+        /// <summary>
+        /// To the XML.
+        /// </summary>
+        /// <returns>The xml data.</returns>
+        XElement ToXml();
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/Models/IDestinationPathInfo.cs b/Main/SimpleBackup.Core/Models/IDestinationPathInfo.cs
new file mode 100644 (file)
index 0000000..9a72c73
--- /dev/null
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="IDestinationPathInfo.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Models
+{
+    /// <summary>
+    /// Interface of a destination path information.
+    /// </summary>
+    public interface IDestinationPathInfo
+    {
+        /// <summary>
+        /// Gets the type of the backup source.
+        /// </summary>
+        BackupSourceType BackupSourceType { get; }
+
+        /// <summary>
+        /// Gets the path.
+        /// </summary>
+        string Path { get; }
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/Models/IModelFactory.cs b/Main/SimpleBackup.Core/Models/IModelFactory.cs
new file mode 100644 (file)
index 0000000..542bea0
--- /dev/null
@@ -0,0 +1,130 @@
+//-----------------------------------------------------------------------
+// <copyright file="IModelFactory.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Models
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Xml.Linq;
+
+    /// <summary>
+    /// Interface of a model factory.
+    /// </summary>
+    public interface IModelFactory
+    {
+        /// <summary>
+        /// Creates the backup setting.
+        /// </summary>
+        /// <returns>The backup setting.</returns>
+        IBackupSetting CreateBackupSetting();
+
+        /// <summary>
+        /// Creates the backup setting.
+        /// </summary>
+        /// <param name="settingFileName">Name of the setting file.</param>
+        /// <param name="backupInfoCollection">The backup information collection.</param>
+        /// <returns>The backup setting.</returns>
+        IBackupSetting CreateBackupSetting(string settingFileName, IEnumerable<IBackupInfo> backupInfoCollection);
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <returns>The backup inforamtion.</returns>
+        IBackupInfo CreateBackupInfo();
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <param name="sourceBackupInfo">The source backup information.</param>
+        /// <returns>The backup inforamtion.</returns>
+        IBackupInfo CreateBackupInfo(IBackupInfo sourceBackupInfo);
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <param name="label">The label.</param>
+        /// <param name="backupSourceType">Type of the backup source.</param>
+        /// <param name="isEnabled">if set to <c>true</c> [is enabled].</param>
+        /// <param name="isZipArchive">if set to <c>true</c> [is zip archive].</param>
+        /// <param name="sourcePath">The source path.</param>
+        /// <param name="destinationFolderPath">The destination folder path.</param>
+        /// <returns>The backup inforamtion.</returns>
+        IBackupInfo CreateBackupInfo(
+            string label,
+            BackupSourceType backupSourceType,
+            bool isEnabled,
+            bool isZipArchive,
+            string sourcePath,
+            string destinationFolderPath);
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        /// <param name="label">The label.</param>
+        /// <param name="backupSourceType">Type of the backup source.</param>
+        /// <param name="isEnabled">if set to <c>true</c> [is enabled].</param>
+        /// <param name="isZipArchive">if set to <c>true</c> [is zip archive].</param>
+        /// <param name="sourcePath">The source path.</param>
+        /// <param name="destinationFolderPath">The destination folder path.</param>
+        /// <returns>The backup inforamtion.</returns>
+        IBackupInfo CreateBackupInfo(
+            Guid id,
+            string label,
+            BackupSourceType backupSourceType,
+            bool isEnabled,
+            bool isZipArchive,
+            string sourcePath,
+            string destinationFolderPath);
+
+        /// <summary>
+        /// Creates the backup information from binary.
+        /// </summary>
+        /// <param name="binaryData">The binary data.</param>
+        /// <param name="copySuffixNeeded">if set to <c>true</c> copy suffix is needed.</param>
+        /// <returns>The backup inforamtion.</returns>
+        IBackupInfo CreateBackupInfoFromBinary(byte[] binaryData, bool copySuffixNeeded);
+
+        /// <summary>
+        /// Creates the result information.
+        /// </summary>
+        /// <param name="category">The category.</param>
+        /// <param name="description">The description.</param>
+        /// <returns>The result inforamtion.</returns>
+        IResultInfo CreateResultInfo(BackupState category, string description);
+
+        /// <summary>
+        /// Creates the destination path information.
+        /// </summary>
+        /// <param name="backupSourceType">Type of the backup source.</param>
+        /// <param name="path">The path.</param>
+        /// <returns>The destination path information.</returns>
+        IDestinationPathInfo CreateDestinationPathInfo(BackupSourceType backupSourceType, string path);
+
+        /// <summary>
+        /// Restores the backup setting from XML.
+        /// </summary>
+        /// <param name="xml">The XML.</param>
+        /// <param name="fileName">Name of the file.</param>
+        /// <returns>The restored backup setting.</returns>
+        IBackupSetting RestoreBackupSettingFromXml(XElement xml, string fileName);
+    }
+}
diff --git a/Main/SimpleBackup.Core/Models/IResultInfo.cs b/Main/SimpleBackup.Core/Models/IResultInfo.cs
new file mode 100644 (file)
index 0000000..5a8f163
--- /dev/null
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="IResultInfo.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Models
+{
+    /// <summary>
+    /// Interface of a result information.
+    /// </summary>
+    public interface IResultInfo
+    {
+        /// <summary>
+        /// Gets the state of the backup.
+        /// </summary>
+        BackupState BackupState { get; }
+
+        /// <summary>
+        /// Gets the description.
+        /// </summary>
+        string Description { get; }
+    }
+}
diff --git a/Main/SimpleBackup.Core/Models/ItemMovingDirection.cs b/Main/SimpleBackup.Core/Models/ItemMovingDirection.cs
new file mode 100644 (file)
index 0000000..6d38734
--- /dev/null
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="ItemMovingDirection.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Models
+{
+    /// <summary>
+    /// Represents item moving direction.
+    /// </summary>
+    public enum ItemMovingDirection
+    {
+        /// <summary>
+        /// The move up
+        /// </summary>
+        MoveUp,
+
+        /// <summary>
+        /// The move down
+        /// </summary>
+        MoveDown
+    }
+}
diff --git a/Main/SimpleBackup.Core/ObjectContainer.cs b/Main/SimpleBackup.Core/ObjectContainer.cs
new file mode 100644 (file)
index 0000000..3b95341
--- /dev/null
@@ -0,0 +1,92 @@
+//-----------------------------------------------------------------------
+// <copyright file="ObjectContainer.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core
+{
+    using System;
+    using System.Collections.Generic;
+    using SimpleBackup.Core.Utilities;
+
+    /// <summary>
+    /// The container class which contains objects with corresponding interface type.
+    /// </summary>
+    public static class ObjectContainer
+    {
+        /// <summary>
+        /// The object dictionary.
+        /// </summary>
+        private static readonly Dictionary<Type, object> ObjectDictionary = new Dictionary<Type, object>();
+
+        /// <summary>
+        /// The lock object.
+        /// </summary>
+        private static readonly object LockObj = new object();
+
+        /// <summary>
+        /// Registers the specified object instance.
+        /// </summary>
+        /// <typeparam name="TInterface">The type of the interface.</typeparam>
+        /// <param name="objectInstance">The object instance.</param>
+        /// <exception cref="System.ArgumentNullException">The provided object instance is null.</exception>
+        /// <exception cref="System.ArgumentException">The specified type is not an interface.</exception>
+        public static void Register<TInterface>(TInterface objectInstance)
+        {
+            objectInstance.ThrowsArgumentNullException("objectInstance");
+
+            Type type = typeof(TInterface);
+            if (type.IsInterface == false)
+            {
+                throw new ArgumentException(string.Format("The specified type {0} is not an interface.", type));
+            }
+
+            lock (LockObj)
+            {
+                ObjectDictionary.Add(type, objectInstance);
+            }
+        }
+
+        /// <summary>
+        /// Resolves this instance.
+        /// </summary>
+        /// <typeparam name="TInterface">The type of the interface.</typeparam>
+        /// <returns>The object instance or null.</returns>
+        /// <exception cref="System.ArgumentException">The specified type is not an interface.</exception>
+        public static TInterface Resolve<TInterface>()
+        {
+            Type type = typeof(TInterface);
+            if (type.IsInterface == false)
+            {
+                throw new ArgumentException(string.Format("The specified type {0} is not an interface.", type));
+            }
+
+            lock (LockObj)
+            {
+                object instance;
+                if (ObjectDictionary.TryGetValue(type, out instance))
+                {
+                    return (TInterface)instance;
+                }
+
+                return default(TInterface);
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Core/Services/FileBackupProgressEventArgs.cs b/Main/SimpleBackup.Core/Services/FileBackupProgressEventArgs.cs
new file mode 100644 (file)
index 0000000..92643df
--- /dev/null
@@ -0,0 +1,53 @@
+//-----------------------------------------------------------------------
+// <copyright file="FileBackupProgressEventArgs.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Services
+{
+    using System;
+    using SimpleBackup.Core.Models;
+
+    /// <summary>
+    /// Event argument which represents file backup progress.
+    /// </summary>
+    public class FileBackupProgressEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="FileBackupProgressEventArgs"/> class.
+        /// </summary>
+        /// <param name="progressValue">The progress value.</param>
+        /// <param name="latestResultInfo">The latest result information.</param>
+        public FileBackupProgressEventArgs(double progressValue, IResultInfo latestResultInfo)
+        {
+            this.ProgressValue = progressValue;
+            this.LatestResultInfo = latestResultInfo;
+        }
+
+        /// <summary>
+        /// Gets the progress value.
+        /// </summary>
+        public double ProgressValue { get; private set; }
+
+        /// <summary>
+        /// Gets the latest result information.
+        /// </summary>
+        public IResultInfo LatestResultInfo { get; private set; }
+    }
+}
diff --git a/Main/SimpleBackup.Core/Services/IBackupService.cs b/Main/SimpleBackup.Core/Services/IBackupService.cs
new file mode 100644 (file)
index 0000000..8479e5a
--- /dev/null
@@ -0,0 +1,62 @@
+//-----------------------------------------------------------------------
+// <copyright file="IBackupService.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Services
+{
+    using System;
+    using System.Threading;
+    using SimpleBackup.Core.Models;
+
+    /// <summary>
+    /// Provides backup function.
+    /// </summary>
+    public interface IBackupService
+    {
+        /// <summary>
+        /// Occurs when file backup progress is updated.
+        /// </summary>
+        event EventHandler<FileBackupProgressEventArgs> NofityFileBackupProgress;
+
+        /// <summary>
+        /// Gets a value indicating whether this service is ready for backup.
+        /// </summary>
+        bool IsReadyForBackup { get; }
+
+        /// <summary>
+        /// Gets a value indicating whether this service is executing backup.
+        /// </summary>
+        bool IsExecutingBackup { get; }
+
+        /// <summary>
+        /// Backups multipul files.
+        /// </summary>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <param name="resultInfos">The array of result information.</param>
+        void BackupMultipulFiles(CancellationToken cancellationToken, out IResultInfo[] resultInfos);
+
+        /// <summary>
+        /// Backups single file.
+        /// </summary>
+        /// <param name="backupInfoId">The backup information identifier.</param>
+        /// <returns>The result information.</returns>
+        IResultInfo BackupSingleFile(Guid backupInfoId);
+    }
+}
diff --git a/Main/SimpleBackup.Core/Services/IBackupSettingService.cs b/Main/SimpleBackup.Core/Services/IBackupSettingService.cs
new file mode 100644 (file)
index 0000000..a017bdc
--- /dev/null
@@ -0,0 +1,134 @@
+//-----------------------------------------------------------------------
+// <copyright file="IBackupSettingService.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Services
+{
+    using System;
+    using SimpleBackup.Core.Models;
+
+    /// <summary>
+    /// Provides backup setting management function.
+    /// </summary>
+    public interface IBackupSettingService
+    {
+        /// <summary>
+        /// Occurs when backup setting is created.
+        /// </summary>
+        event EventHandler<SettingFileEventArgs> BackupSettingCreated;
+
+        /// <summary>
+        /// Occurs when backup setting is opened.
+        /// </summary>
+        event EventHandler<SettingFileEventArgs> BackupSettingOpened;
+
+        /// <summary>
+        /// Occurs when backup setting is modified.
+        /// </summary>
+        event EventHandler<SettingFileEventArgs> BackupSettingModified;
+
+        /// <summary>
+        /// Occurs when backup setting is saved.
+        /// </summary>
+        event EventHandler<SettingFileEventArgs> BackupSettingSaved;
+
+        /// <summary>
+        /// Occurs when backup setting is closed.
+        /// </summary>
+        event EventHandler<SettingFileEventArgs> BackupSettingClosed;
+
+        /// <summary>
+        /// Gets the current setting.
+        /// </summary>
+        IBackupSetting CurrentSetting { get; }
+
+        /// <summary>
+        /// Creates the backup setting.
+        /// </summary>
+        /// <returns><c>true</c> if the new backup setting is created; otherwise, <c>false</c>.</returns>
+        bool CreateBackupSetting();
+
+        /// <summary>
+        /// Opens the backup setting.
+        /// </summary>
+        /// <param name="resultMessage">The result message.</param>
+        /// <returns>
+        ///   <c>true</c> if backup setting is successfully loaded; otherwise, <c>false</c>.
+        /// </returns>
+        bool OpenBackupSetting(out string resultMessage);
+
+        /// <summary>
+        /// Opens the default backup setting.
+        /// </summary>
+        /// <param name="resultMessage">The result message.</param>
+        /// <returns>
+        ///   <c>true</c> if succeeded, otherwise; <c>false</c>.
+        /// </returns>
+        bool OpenDefaultBackupSetting(out string resultMessage);
+
+        /// <summary>
+        /// Closes the backup setting.
+        /// </summary>
+        void CloseBackupSetting();
+
+        /// <summary>
+        /// Overwrites the currnt backup setting.
+        /// </summary>
+        /// <returns><c>true</c> if the backup setting is saved; otherwise, <c>false</c>.</returns>
+        bool OverWriteCurrntBackupSetting();
+
+        /// <summary>
+        /// Saves the current backup setting as a new file.
+        /// </summary>
+        /// <returns><c>true</c> if the backup setting is saved; otherwise, <c>false</c>.</returns>
+        bool SaveCurrentBackupSettingAsNewFile();
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <param name="index">The index.</param>
+        /// <returns>The created backup information.</returns>
+        /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="index"/></exception>
+        IBackupInfo CreateBackupInfo(int index);
+
+        /// <summary>
+        /// Copies the backup information.
+        /// </summary>
+        /// <param name="sourceBackupInfo">The source backup information.</param>
+        /// <returns>The copied backup information.</returns>
+        /// <exception cref="System.ArgumentNullException"><paramref name="sourceBackupInfo"/></exception>
+        IBackupInfo CopyBackupInfo(IBackupInfo sourceBackupInfo);
+
+        /// <summary>
+        /// Inserts the backup information.
+        /// </summary>
+        /// <param name="index">The index.</param>
+        /// <param name="backupInfo">The backup information.</param>
+        /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="index"/></exception>
+        /// <exception cref="System.ArgumentNullException"><paramref name="backupInfo"/></exception>
+        void InsertBackupInfo(int index, IBackupInfo backupInfo);
+
+        /// <summary>
+        /// Removes the backup information.
+        /// </summary>
+        /// <param name="backupInfoId">The backup information identifier.</param>
+        void RemoveBackupInfo(Guid backupInfoId);
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/Services/IClipboardService.cs b/Main/SimpleBackup.Core/Services/IClipboardService.cs
new file mode 100644 (file)
index 0000000..4a0959d
--- /dev/null
@@ -0,0 +1,63 @@
+//-----------------------------------------------------------------------
+// <copyright file="IClipboardService.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Services
+{
+    using System;
+    using System.Windows;
+
+    /// <summary>
+    /// Provides clip board access.
+    /// </summary>
+    public interface IClipboardService
+    {
+        /// <summary>
+        /// Sets the data object.
+        /// </summary>
+        /// <param name="dataObject">The data object.</param>
+        /// <exception cref="ArgumentNullException">The data object is null.</exception>
+        void SetDataObject(IDataObject dataObject);
+
+        /// <summary>
+        /// Gets the data.
+        /// </summary>
+        /// <typeparam name="T">The type.</typeparam>
+        /// <param name="format">The format.</param>
+        /// <returns>
+        /// The data.
+        /// </returns>
+        /// <exception cref="ArgumentException">The format string is null or empty.</exception>
+        T GetData<T>(string format);
+
+        /// <summary>
+        /// Gets a boolean value indicating whether the clipboard data contains data in specified format.
+        /// </summary>
+        /// <param name="format">The format.</param>
+        /// <exception cref="ArgumentException">The format string is null or empty.</exception>
+        /// <returns>True if the specified format is contained in the Clipboard.</returns>
+        bool DoesClipboardDataContain(string format);
+
+        /// <summary>
+        /// Clears the clipbord.
+        /// </summary>
+        void ClearClipbord();
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/Services/ISettingsService.cs b/Main/SimpleBackup.Core/Services/ISettingsService.cs
new file mode 100644 (file)
index 0000000..317eb02
--- /dev/null
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="ISettingsService.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Services
+{
+    /// <summary>
+    /// Interface of a seting service.
+    /// </summary>
+    public interface ISettingsService
+    {
+        /// <summary>
+        /// Gets or sets the default name of the setting file.
+        /// </summary>
+        string DefaultSettingFileName { get; set; }
+
+        /// <summary>
+        /// Gets or sets the default zip encoding key text.
+        /// </summary>
+        string DefaultZipEncodingKeyText { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/Services/IUndoRedoService.cs b/Main/SimpleBackup.Core/Services/IUndoRedoService.cs
new file mode 100644 (file)
index 0000000..d8982d0
--- /dev/null
@@ -0,0 +1,68 @@
+//-----------------------------------------------------------------------
+// <copyright file="IUndoRedoService.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Services
+{
+    using System;
+
+    /// <summary>
+    /// Provides undo/redo function.
+    /// </summary>
+    public interface IUndoRedoService
+    {
+        /// <summary>
+        /// Commits the specified redo action with related undo action and the context information.
+        /// </summary>
+        /// <param name="redoAction">The redo action.</param>
+        /// <param name="undoAction">The undo action.</param>
+        /// <param name="context">The context.</param>
+        /// <exception cref="ArgumentNullException">The redoAction is null.</exception>
+        /// <exception cref="ArgumentNullException">The undoAction is null.</exception>
+        void Commit(Action<object> redoAction, Action<object> undoAction, object context);
+
+        /// <summary>
+        /// Executes undo action.
+        /// </summary>
+        void Undo();
+
+        /// <summary>
+        /// Determines whether the undo action is executable.
+        /// </summary>
+        /// <returns>true if the undo action can be executable; otherwise, false.</returns>
+        bool CanExecuteUndo();
+
+        /// <summary>
+        /// Executes redo action.
+        /// </summary>
+        void Redo();
+
+        /// <summary>
+        /// Determines whether the redo action is executable.
+        /// </summary>
+        /// <returns>true if the redo action can be executable; otherwise, false.</returns>
+        bool CanExecuteRedo();
+
+        /// <summary>
+        /// Clears the undo redo buffer.
+        /// </summary>
+        void ClearUndoRedoBuffer();
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/Services/SettingFileEventArgs.cs b/Main/SimpleBackup.Core/Services/SettingFileEventArgs.cs
new file mode 100644 (file)
index 0000000..5fe6f7d
--- /dev/null
@@ -0,0 +1,49 @@
+//-----------------------------------------------------------------------
+// <copyright file="SettingFileEventArgs.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Services
+{
+    using System;
+    using SimpleBackup.Core.Utilities;
+
+    /// <summary>
+    /// Setting file event argument
+    /// </summary>
+    public class SettingFileEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="SettingFileEventArgs"/> class.
+        /// </summary>
+        /// <param name="settingName">Name of the setting.</param>
+        /// <exception cref="ArgumentNullException">The provided setting name is null.</exception>
+        public SettingFileEventArgs(string settingName)
+        {
+            settingName.ThrowsArgumentNullException("settingName");
+
+            this.SettingName = settingName;
+        }
+
+        /// <summary>
+        /// Gets the name of the setting.
+        /// </summary>
+        public string SettingName { get; private set; }
+    }
+}
diff --git a/Main/SimpleBackup.Core/SimpleBackup.Core.csproj b/Main/SimpleBackup.Core/SimpleBackup.Core.csproj
new file mode 100644 (file)
index 0000000..6c0cc5f
--- /dev/null
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{33F1D454-9962-4EB6-AAD3-8D11D9A78D1F}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SimpleBackup.Core</RootNamespace>
+    <AssemblyName>SimpleBackup.Core</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>SimpleBackupKey.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="PresentationCore" />
+    <Reference Include="PresentationFramework" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xaml" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+    <Reference Include="WindowsBase" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Properties\AssemblyInfo.cs">
+      <Link>Properties\AssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="AppInfrastructure\IAppComponent.cs" />
+    <Compile Include="Models\BackupSourceType.cs" />
+    <Compile Include="Models\BackupState.cs" />
+    <Compile Include="Models\IBackupInfo.cs" />
+    <Compile Include="Models\IBackupSetting.cs" />
+    <Compile Include="Models\IDestinationPathInfo.cs" />
+    <Compile Include="Models\IModelFactory.cs" />
+    <Compile Include="Models\IResultInfo.cs" />
+    <Compile Include="Models\ItemMovingDirection.cs" />
+    <Compile Include="ObjectContainer.cs" />
+    <Compile Include="Services\FileBackupProgressEventArgs.cs" />
+    <Compile Include="Services\IBackupService.cs" />
+    <Compile Include="Services\IBackupSettingService.cs" />
+    <Compile Include="Services\IClipboardService.cs" />
+    <Compile Include="Services\ISettingsService.cs" />
+    <Compile Include="Services\IUndoRedoService.cs" />
+    <Compile Include="Services\SettingFileEventArgs.cs" />
+    <Compile Include="Utilities\Constants.cs" />
+    <Compile Include="Utilities\HelperExtensions.cs" />
+    <Compile Include="Utilities\Helpers.cs" />
+    <Compile Include="Utilities\IdIndexPair.cs" />
+    <Compile Include="Utilities\PropertyChangeNotificationBase.cs" />
+    <Compile Include="ViewModels\BackupInfoPathType.cs" />
+    <Compile Include="ViewModels\FocusOnGridRowEventArgs.cs" />
+    <Compile Include="ViewModels\IBackupInfoViewModel.cs" />
+    <Compile Include="ViewModels\IDestinationColumnHeaderViewModel.cs" />
+    <Compile Include="ViewModels\ILabelColumnHeaderViewModel.cs" />
+    <Compile Include="ViewModels\IMainWindowViewModel.cs" />
+    <Compile Include="ViewModels\ISourceColumnHeaderViewModel.cs" />
+    <Compile Include="ViewModels\IViewModelFactory.cs" />
+    <Compile Include="ViewModels\PasteType.cs" />
+    <Compile Include="Views\ExDataGridSelectedFirstCellItemChangedEventArgs.cs" />
+    <Compile Include="Views\IFileFolderDialog.cs" />
+    <Compile Include="Views\IMainWindow.cs" />
+    <Compile Include="Views\IVersionInformationWindow.cs" />
+    <Compile Include="Views\IViewFactory.cs" />
+    <Compile Include="Views\RelayCommand.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="SimpleBackupKey.snk" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\SimpleBackup.Resources\SimpleBackup.Resources.csproj">
+      <Project>{a655131e-d439-4de1-bc39-5c955306183f}</Project>
+      <Name>SimpleBackup.Resources</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/SimpleBackupKey.snk b/Main/SimpleBackup.Core/SimpleBackupKey.snk
new file mode 100644 (file)
index 0000000..def2e6d
Binary files /dev/null and b/Main/SimpleBackup.Core/SimpleBackupKey.snk differ
diff --git a/Main/SimpleBackup.Core/Utilities/Constants.cs b/Main/SimpleBackup.Core/Utilities/Constants.cs
new file mode 100644 (file)
index 0000000..0010eb8
--- /dev/null
@@ -0,0 +1,56 @@
+//-----------------------------------------------------------------------
+// <copyright file="Constants.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Utilities
+{
+    using System.Text.RegularExpressions;
+
+    /// <summary>
+    /// Defines constants
+    /// </summary>
+    public static class Constants
+    {
+        /// <summary>
+        /// The backup information clipboard format: "BackupInfoClipboardFormat"
+        /// </summary>
+        public const string BackupInfoClipboardFormat = "BackupInfoClipboardFormat";
+
+        /// <summary>
+        /// The end path segment regex: "[^\\]*$"
+        /// </summary>
+        public static readonly Regex EndPathSegmentRegex = new Regex(@"[^\\]*$", RegexOptions.Compiled);
+
+        /// <summary>
+        /// The end path separator regex: "\\$"
+        /// </summary>
+        public static readonly Regex EndPathSeparatorRegex = new Regex(@"\\$", RegexOptions.Compiled);
+
+        /// <summary>
+        /// The file name regex: "^.*(?=\.)"
+        /// </summary>
+        public static readonly Regex FileNameRegex = new Regex(@"^.*(?=\.)", RegexOptions.Compiled);
+
+        /// <summary>
+        /// The extension regex: "[^\.]*$"
+        /// </summary>
+        public static readonly Regex ExtensionRegex = new Regex(@"[^\.]*$", RegexOptions.Compiled);
+    }
+}
diff --git a/Main/SimpleBackup.Core/Utilities/HelperExtensions.cs b/Main/SimpleBackup.Core/Utilities/HelperExtensions.cs
new file mode 100644 (file)
index 0000000..52b3f21
--- /dev/null
@@ -0,0 +1,214 @@
+//-----------------------------------------------------------------------
+// <copyright file="HelperExtensions.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Utilities
+{
+    using System;
+    using System.IO;
+    using System.Windows;
+    using System.Windows.Media;
+    using SimpleBackup.Core.Models;
+    using SimpleBackup.Resources;
+
+    /// <summary>
+    /// Defines helper extension methods.
+    /// </summary>
+    public static class HelperExtensions
+    {
+        /// <summary>
+        /// Throwses the argument null exception.
+        /// </summary>
+        /// <param name="source">The source.</param>
+        /// <param name="parameterName">Name of the parameter.</param>
+        /// <exception cref="System.ArgumentNullException">The argument is null.</exception>
+        public static void ThrowsArgumentNullException(this object source, string parameterName)
+        {
+            if (source == null)
+            {
+                throw new ArgumentNullException(parameterName);
+            }
+        }
+
+        public static void ThrowsArgumentExceptionIfNullOrEmpty(this string source, string parameterName)
+        {
+            if (string.IsNullOrEmpty(source))
+            {
+                throw new ArgumentException("provided text is null or empty.", parameterName);
+            }
+        }
+
+        public static T SearchUpParentWithSelf<T>(this DependencyObject source)
+            where T : DependencyObject
+        {
+            if (source == null)
+            {
+                return null;
+            }
+
+            if (source is T)
+            {
+                return (T)source;
+            }
+
+            DependencyObject parent = VisualTreeHelper.GetParent(source);
+            while (true)
+            {
+                parent = VisualTreeHelper.GetParent(parent);
+                if ((parent == null) || (parent is Window))
+                {
+                    return null;
+                }
+
+                if (parent is T)
+                {
+                    return (T)parent;
+                }
+            }
+        }
+
+        public static T GetVisualChild<T>(this Visual source) where T : Visual
+        {
+            T targetChild = default(T);
+            int childrenCount = VisualTreeHelper.GetChildrenCount(source);
+            for (int i = 0; i < childrenCount; i++)
+            {
+                var childVisual = (Visual)VisualTreeHelper.GetChild(source, i);
+                targetChild = childVisual as T ?? GetVisualChild<T>(childVisual);
+                if (targetChild != null)
+                {
+                    break;
+                }
+            }
+
+            return targetChild;
+        }
+
+        public static object GetVisualChild(this Visual source, Type targeType)
+        {
+            object targetChild = null;
+            int childrenCount = VisualTreeHelper.GetChildrenCount(source);
+            for (int i = 0; i < childrenCount; i++)
+            {
+                var childVisual = (Visual)VisualTreeHelper.GetChild(source, i);
+                if (childVisual.GetType() == targeType)
+                {
+                    targetChild = childVisual;
+                    break;
+                }
+
+                targetChild = GetVisualChild(childVisual, targeType);
+            }
+
+            return targetChild;
+        }
+
+        public static bool IsValidFileOrDirectoryPath(this string pathText)
+        {
+            if (string.IsNullOrWhiteSpace(pathText))
+            {
+                return false;
+            }
+
+            return File.Exists(pathText) || Directory.Exists(pathText);
+        }
+
+        public static bool IsValidFilePath(this string pathText)
+        {
+            if (string.IsNullOrWhiteSpace(pathText))
+            {
+                return false;
+            }
+
+            return File.Exists(pathText);
+        }
+
+        public static bool IsValidDirectoryPath(this string pathText)
+        {
+            if (string.IsNullOrWhiteSpace(pathText))
+            {
+                return false;
+            }
+
+            return Directory.Exists(pathText);
+        }
+
+        public static bool IsExistingFileOrDirectoryPath(this string pathText)
+        {
+            if (string.IsNullOrWhiteSpace(pathText))
+            {
+                return false;
+            }
+
+            if (File.Exists(pathText))
+            {
+                return true;
+            }
+
+            if (Directory.Exists(pathText))
+            {
+                return true;
+            }
+
+            return false;
+        }
+
+        public static string AddTailPathSeparatorIfNotExist(this string text)
+        {
+            if (string.IsNullOrWhiteSpace(text))
+            {
+                return text;
+            }
+
+            if (text.EndsWith("\\") == false)
+            {
+                return text + "\\";
+            }
+
+            return text;
+        }
+
+        /// <summary>
+        /// Translates the specified backup state.
+        /// </summary>
+        /// <param name="backupState">State of the backup.</param>
+        /// <returns>The translated text.</returns>
+        public static string Translate(this BackupState backupState)
+        {
+            switch (backupState)
+            {
+                case BackupState.Todo:
+                    return Resources.BackupState_Todo;
+                case BackupState.InProgress:
+                    return Resources.BackupState_InProgress;
+                case BackupState.Success:
+                    return Resources.BackupState_Success;
+                case BackupState.Failed:
+                    return Resources.BackupState_Failed;
+                case BackupState.Cancelled:
+                    return Resources.BackupState_Cancelled;
+                case BackupState.Skipped:
+                    return Resources.BackupState_Skipped;
+                default:
+                    return string.Empty;
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Core/Utilities/Helpers.cs b/Main/SimpleBackup.Core/Utilities/Helpers.cs
new file mode 100644 (file)
index 0000000..6113b0b
--- /dev/null
@@ -0,0 +1,167 @@
+//-----------------------------------------------------------------------
+// <copyright file="Helpers.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Utilities
+{
+    using System.Diagnostics;
+    using System.Globalization;
+    using System.IO;
+    using System.Windows;
+    using System.Windows.Threading;
+
+    /// <summary>
+    /// Defines helper methods.
+    /// </summary>
+    public static class Helpers
+    {
+        #region WPF
+
+        public static void UpdateWpfGui()
+        {
+            var frame = new DispatcherFrame();
+            var callback = new DispatcherOperationCallback(obj =>
+            {
+                ((DispatcherFrame)obj).Continue = false;
+                return null;
+            });
+            Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, callback, frame);
+            Dispatcher.PushFrame(frame);
+        }
+
+        #endregion
+
+        #region Files and directories
+
+        public static bool TryExtractValidFolderPath(string sourcePath, out string extractedPath)
+        {
+            extractedPath = string.Empty;
+
+            if (string.IsNullOrEmpty(sourcePath))
+            {
+                return false;
+            }
+
+            string testPath = sourcePath;
+            while (true)
+            {
+                if (Directory.Exists(testPath))
+                {
+                    extractedPath = testPath;
+                    return true;
+                }
+
+                testPath = Path.GetDirectoryName(testPath);
+                if (string.IsNullOrEmpty(testPath))
+                {
+                    break;
+                }
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// Creates the display path text.
+        /// </summary>
+        /// <param name="fullPath">The full path.</param>
+        /// <returns>The display path text.</returns>
+        public static string CreateDisplayPathText(string fullPath)
+        {
+            if (string.IsNullOrWhiteSpace(fullPath))
+            {
+                return string.Empty;
+            }
+
+            string fileName = Path.GetFileName(fullPath);
+            string directoryName = Path.GetDirectoryName(fullPath);
+
+            return string.Format(CultureInfo.CurrentCulture, "{0} ({1})", fileName, directoryName);
+        }
+
+        public static void OpenFolder(string path)
+        {
+            if (string.IsNullOrWhiteSpace(path))
+            {
+                MessageBox.Show(
+                    string.Format(SimpleBackup.Resources.Resources.FileAccess_InvalidPathFormat, path));
+                return;
+            }
+
+            if (Directory.Exists(path))
+            {
+                Process.Start("explorer.exe", string.Format("/n, /e, {0}", path));
+            }
+            else
+            {
+                MessageBox.Show(
+                    string.Format(Resources.Resources.FileAccess_FolderPathNotExistFormat, path));
+            }
+        }
+
+        /// <summary>
+        /// Opens the parent folder and select the specified file or folder.
+        /// </summary>
+        /// <param name="path">The path.</param>
+        public static void OpenParentFolderAndSelect(string path)
+        {
+            if (path.IsExistingFileOrDirectoryPath() == false)
+            {
+                MessageBox.Show(
+                    string.Format(Resources.Resources.FileAccess_InvalidPathFormat, path));
+                return;
+            }
+
+            Process.Start("explorer.exe", string.Format("/n, /e, /select,{0}", path));
+        }
+
+        /// <summary>
+        /// Opens the file.
+        /// </summary>
+        /// <param name="fileName">Name of the file.</param>
+        public static void OpenFile(string fileName)
+        {
+            if (fileName.IsExistingFileOrDirectoryPath() == false)
+            {
+                MessageBox.Show(
+                    string.Format(Resources.Resources.FileAccess_InvalidPathFormat, fileName));
+                return;
+            }
+
+            var processStartInfo = new ProcessStartInfo
+            {
+                FileName = fileName,
+                UseShellExecute = true
+            };
+
+            try
+            {
+                Process.Start(processStartInfo);
+            }
+            catch
+            {
+                MessageBox.Show(
+                    string.Format(Resources.Resources.FileAccess_FailedToOpenFormat, fileName));
+            }
+        }
+
+        #endregion
+    }
+}
diff --git a/Main/SimpleBackup.Core/Utilities/IdIndexPair.cs b/Main/SimpleBackup.Core/Utilities/IdIndexPair.cs
new file mode 100644 (file)
index 0000000..f8c41d8
--- /dev/null
@@ -0,0 +1,64 @@
+//-----------------------------------------------------------------------
+// <copyright file="IdIndexPair.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Utilities
+{
+    using System;
+
+    /// <summary>
+    /// A pair of Guid and index.
+    /// </summary>
+    public class IdIndexPair
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="IdIndexPair"/> class.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        /// <param name="index">The index.</param>
+        /// <exception cref="ArgumentException">The provided GUID is zero.</exception>
+        /// <exception cref="ArgumentException">The provided index is a minus value.</exception>
+        public IdIndexPair(Guid id, int index)
+        {
+            if (id == default(Guid))
+            {
+                throw new ArgumentException("The provided GUID is zero.", "id");
+            }
+
+            if (index < 0)
+            {
+                throw new ArgumentException("The provided index is a minus value.", "index");
+            }
+
+            this.Id = id;
+            this.Index = index;
+        }
+
+        /// <summary>
+        /// Gets the identifier.
+        /// </summary>
+        public Guid Id { get; private set; }
+
+        /// <summary>
+        /// Gets the index.
+        /// </summary>
+        public int Index { get; private set; }
+    }
+}
diff --git a/Main/SimpleBackup.Core/Utilities/PropertyChangeNotificationBase.cs b/Main/SimpleBackup.Core/Utilities/PropertyChangeNotificationBase.cs
new file mode 100644 (file)
index 0000000..e52dba1
--- /dev/null
@@ -0,0 +1,48 @@
+//-----------------------------------------------------------------------
+// <copyright file="PropertyChangeNotificationBase.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Utilities
+{
+    using System.ComponentModel;
+
+    /// <summary>
+    /// Base class of classes which implement INotifyPropertyChanged.
+    /// </summary>
+    public abstract class PropertyChangeNotificationBase : INotifyPropertyChanged
+    {
+        /// <summary>
+        /// Occurs when a property value changes.
+        /// </summary>
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        /// <summary>
+        /// Notifies the property changed.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        protected void NotifyPropertyChanged(string propertyName)
+        {
+            if (this.PropertyChanged != null)
+            {
+                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Core/ViewModels/BackupInfoPathType.cs b/Main/SimpleBackup.Core/ViewModels/BackupInfoPathType.cs
new file mode 100644 (file)
index 0000000..6a0c229
--- /dev/null
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="BackupInfoPathType.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.ViewModels
+{
+    /// <summary>
+    /// Represents backup information path type.
+    /// </summary>
+    public enum BackupInfoPathType
+    {
+        /// <summary>
+        /// The source
+        /// </summary>
+        Source,
+
+        /// <summary>
+        /// The destination
+        /// </summary>
+        Destination
+    }
+}
diff --git a/Main/SimpleBackup.Core/ViewModels/FocusOnGridRowEventArgs.cs b/Main/SimpleBackup.Core/ViewModels/FocusOnGridRowEventArgs.cs
new file mode 100644 (file)
index 0000000..da66a8b
--- /dev/null
@@ -0,0 +1,51 @@
+//-----------------------------------------------------------------------
+// <copyright file="FocusOnGridRowEventArgs.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.ViewModels
+{
+    using System;
+
+    /// <summary>
+    /// Event argument of FocusOnGridRow event.
+    /// </summary>
+    public class FocusOnGridRowEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="FocusOnGridRowEventArgs"/> class.
+        /// </summary>
+        /// <param name="index">The index.</param>
+        /// <exception cref="System.ArgumentOutOfRangeException">The provided index is out of the range.</exception>
+        public FocusOnGridRowEventArgs(int index)
+        {
+            if (index < 0)
+            {
+                throw new ArgumentOutOfRangeException("index");
+            }
+
+            this.Index = index;
+        }
+
+        /// <summary>
+        /// Gets the index.
+        /// </summary>
+        public int Index { get; private set; }
+    }
+}
diff --git a/Main/SimpleBackup.Core/ViewModels/IBackupInfoViewModel.cs b/Main/SimpleBackup.Core/ViewModels/IBackupInfoViewModel.cs
new file mode 100644 (file)
index 0000000..bc72ce8
--- /dev/null
@@ -0,0 +1,123 @@
+//-----------------------------------------------------------------------
+// <copyright file="IBackupInfoViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.ViewModels
+{
+    using System;
+    using SimpleBackup.Core.Models;
+    using SimpleBackup.Core.Views;
+
+    /// <summary>
+    /// The interface of backup information view model.
+    /// </summary>
+    public interface IBackupInfoViewModel
+    {
+        /// <summary>
+        /// Gets the open source file relay command.
+        /// </summary>
+        RelayCommand OpenSourceFileRelayCommand { get;  }
+
+        /// <summary>
+        /// Gets the open source folder relay command.
+        /// </summary>
+        RelayCommand OpenSourceFolderRelayCommand { get; }
+
+        /// <summary>
+        /// Gets the select source relay command.
+        /// </summary>
+        RelayCommand SelectSourceRelayCommand { get; }
+
+        /// <summary>
+        /// Gets the open destination folder relay command.
+        /// </summary>
+        RelayCommand OpenDestinationFolderRelayCommand { get; }
+
+        /// <summary>
+        /// Gets the select destination relay command.
+        /// </summary>
+        RelayCommand SelectDestinationRelayCommand { get; }
+
+        /// <summary>
+        /// Gets the edit source relay command.
+        /// </summary>
+        RelayCommand EditSourceRelayCommand { get; }
+
+        /// <summary>
+        /// Gets the edit destination relay command.
+        /// </summary>
+        RelayCommand EditDestinationRelayCommand { get; }
+
+        /// <summary>
+        /// Gets the single backup with context menu relay command.
+        /// </summary>
+        RelayCommand SingleBackupRelayCommand { get; }
+
+        Guid BackupInfoId { get; }
+
+        BackupSourceType SourceType { get; }
+
+        BackupState BackupState { get; }
+
+        bool IsEnabled { get; set; }
+
+        bool IsZipArchive { get; set; }
+
+        string Label { get; set; }
+
+        string SourcePath { get; set; }
+
+        string DisplaySourcePath { get; }
+
+        string EditingSourcePath { get; set; }
+
+        string SourceToolTipText { get; }
+
+        bool IsSourceEditing { get; set; }
+
+        bool HasSourcePathError { get; }
+
+        string DestinationFolderPath { get; set; }
+
+        string DisplayDestinationFolderPath { get; }
+
+        string EditingDestinationPath { get; set; }
+
+        string DestinationToolTipText { get; }
+
+        bool IsDestinationEditing { get; set; }
+
+        bool HasDestinationFolderPathError { get; }
+
+        bool IsEditing { get; }
+
+        bool IsCutReserved { get; set; }
+
+        IBackupInfo GetBackupInfo();
+
+        void ExecuteDoubleClickAction(BackupInfoPathType pathType);
+
+        void SingleBackup();
+
+        void CommitEditingContents();
+
+        void ResetBackupState();
+    }
+}
diff --git a/Main/SimpleBackup.Core/ViewModels/IDestinationColumnHeaderViewModel.cs b/Main/SimpleBackup.Core/ViewModels/IDestinationColumnHeaderViewModel.cs
new file mode 100644 (file)
index 0000000..20b4562
--- /dev/null
@@ -0,0 +1,30 @@
+//-----------------------------------------------------------------------
+// <copyright file="IDestinationColumnHeaderViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.ViewModels
+{
+    /// <summary>
+    /// Interface of a destination column header view model.
+    /// </summary>
+    public interface IDestinationColumnHeaderViewModel
+    {
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/ViewModels/ILabelColumnHeaderViewModel.cs b/Main/SimpleBackup.Core/ViewModels/ILabelColumnHeaderViewModel.cs
new file mode 100644 (file)
index 0000000..bba6949
--- /dev/null
@@ -0,0 +1,30 @@
+//-----------------------------------------------------------------------
+// <copyright file="IDestinationColumnHeaderViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.ViewModels
+{
+    /// <summary>
+    /// Interface of a label column header view model.
+    /// </summary>
+    public interface ILabelColumnHeaderViewModel
+    {
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/ViewModels/IMainWindowViewModel.cs b/Main/SimpleBackup.Core/ViewModels/IMainWindowViewModel.cs
new file mode 100644 (file)
index 0000000..2582e60
--- /dev/null
@@ -0,0 +1,52 @@
+//-----------------------------------------------------------------------
+// <copyright file="IMainWindowViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.ViewModels
+{
+    using System;
+    using SimpleBackup.Core.Views;
+
+    /// <summary>
+    /// Interface of a main window view model.
+    /// </summary>
+    public interface IMainWindowViewModel : IDisposable
+    {
+        /// <summary>
+        /// Occurs when the focus is set on the Grid.
+        /// </summary>
+        event EventHandler<EventArgs> FocusOnGrid;
+
+        /// <summary>
+        /// Occurs when the focus is set on a Grid row.
+        /// </summary>
+        event EventHandler<FocusOnGridRowEventArgs> FocusOnGridRow;
+
+        /// <summary>
+        /// Gets the save backup setting relay command.
+        /// </summary>
+        RelayCommand SaveBackupSettingRelayCommand { get; }
+
+        /// <summary>
+        /// Called when Escape key is pressed.
+        /// </summary>
+        void OnEscKeyPressed();
+    }
+}
diff --git a/Main/SimpleBackup.Core/ViewModels/ISourceColumnHeaderViewModel.cs b/Main/SimpleBackup.Core/ViewModels/ISourceColumnHeaderViewModel.cs
new file mode 100644 (file)
index 0000000..c1315ce
--- /dev/null
@@ -0,0 +1,30 @@
+//-----------------------------------------------------------------------
+// <copyright file="ISourceColumnHeaderViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.ViewModels
+{
+    /// <summary>
+    /// Interface of a source column header view model.
+    /// </summary>
+    public interface ISourceColumnHeaderViewModel
+    {
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/ViewModels/IViewModelFactory.cs b/Main/SimpleBackup.Core/ViewModels/IViewModelFactory.cs
new file mode 100644 (file)
index 0000000..0b2d8dd
--- /dev/null
@@ -0,0 +1,35 @@
+//-----------------------------------------------------------------------
+// <copyright file="IViewModelFactory.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.ViewModels
+{
+    /// <summary>
+    /// Interface of a view model factory.
+    /// </summary>
+    public interface IViewModelFactory
+    {
+        /// <summary>
+        /// Creates the main window view model.
+        /// </summary>
+        /// <returns>The main window view model.</returns>
+        IMainWindowViewModel CreateMainWindowViewModel();
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/ViewModels/PasteType.cs b/Main/SimpleBackup.Core/ViewModels/PasteType.cs
new file mode 100644 (file)
index 0000000..c3c8ec3
--- /dev/null
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="PasteType.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.ViewModels
+{
+    /// <summary>
+    /// Paste operation type.
+    /// </summary>
+    public enum PasteType
+    {
+        /// <summary>
+        /// The copy
+        /// </summary>
+        Copy,
+
+        /// <summary>
+        /// The cut
+        /// </summary>
+        Cut
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/Views/ExDataGridSelectedFirstCellItemChangedEventArgs.cs b/Main/SimpleBackup.Core/Views/ExDataGridSelectedFirstCellItemChangedEventArgs.cs
new file mode 100644 (file)
index 0000000..3dc8ad6
--- /dev/null
@@ -0,0 +1,54 @@
+//-----------------------------------------------------------------------
+// <copyright file="ExDataGridSelectedFirstCellItemChangedEventArgs.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Views
+{
+    using System;
+
+    /// <summary>
+    /// Event argument of ExDataGrid's SelectedFirstCellItemChangedEvent event.
+    /// </summary>
+    public class ExDataGridSelectedFirstCellItemChangedEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ExDataGridSelectedFirstCellItemChangedEventArgs"/> class.
+        /// </summary>
+        /// <param name="selectedFirstCellItemIndex">Index of the selected first cell item.</param>
+        /// <param name="selectedFirstCellItem">The selected first cell item.</param>
+        public ExDataGridSelectedFirstCellItemChangedEventArgs(
+            int selectedFirstCellItemIndex,
+            object selectedFirstCellItem)
+        {
+            this.SelectedFirstCellItemIndex = selectedFirstCellItemIndex;
+            this.SelectedFirstCellItem = selectedFirstCellItem;
+        }
+
+        /// <summary>
+        /// Gets the index of the selected first cell item.
+        /// </summary>
+        public int SelectedFirstCellItemIndex { get; private set; }
+
+        /// <summary>
+        /// Gets the selected first cell item.
+        /// </summary>
+        public object SelectedFirstCellItem { get; private set; }
+    }
+}
diff --git a/Main/SimpleBackup.Core/Views/IFileFolderDialog.cs b/Main/SimpleBackup.Core/Views/IFileFolderDialog.cs
new file mode 100644 (file)
index 0000000..3709604
--- /dev/null
@@ -0,0 +1,42 @@
+//-----------------------------------------------------------------------
+// <copyright file="IFileFolderDialog.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Views
+{
+    using System.Windows.Forms;
+
+    /// <summary>
+    /// Interface of a file folder dialog.
+    /// </summary>
+    public interface IFileFolderDialog
+    {
+        /// <summary>
+        /// Gets or sets the selected path.
+        /// </summary>
+        string SelectedPath { get; set; }
+
+        /// <summary>
+        /// Shows the dialog.
+        /// </summary>
+        /// <returns>The dialog result.</returns>
+        DialogResult ShowDialog();
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/Views/IMainWindow.cs b/Main/SimpleBackup.Core/Views/IMainWindow.cs
new file mode 100644 (file)
index 0000000..70568e1
--- /dev/null
@@ -0,0 +1,39 @@
+//-----------------------------------------------------------------------
+// <copyright file="IMainWindow.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Views
+{
+    /// <summary>
+    /// Interface of a main window.
+    /// </summary>
+    public interface IMainWindow
+    {
+        /// <summary>
+        /// Gets or sets the data context.
+        /// </summary>
+        object DataContext { get; set; }
+
+        /// <summary>
+        /// Shows the window.
+        /// </summary>
+        void Show();
+    }
+}
diff --git a/Main/SimpleBackup.Core/Views/IVersionInformationWindow.cs b/Main/SimpleBackup.Core/Views/IVersionInformationWindow.cs
new file mode 100644 (file)
index 0000000..ffc9bc1
--- /dev/null
@@ -0,0 +1,35 @@
+//-----------------------------------------------------------------------
+// <copyright file="IVersionInformationWindow.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Views
+{
+    /// <summary>
+    /// Interface of a version information window.
+    /// </summary>
+    public interface IVersionInformationWindow
+    {
+        /// <summary>
+        /// Shows the dialog window.
+        /// </summary>
+        /// <returns>The result.</returns>
+        bool? ShowDialogWindow();
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/Views/IViewFactory.cs b/Main/SimpleBackup.Core/Views/IViewFactory.cs
new file mode 100644 (file)
index 0000000..d050f1d
--- /dev/null
@@ -0,0 +1,47 @@
+//-----------------------------------------------------------------------
+// <copyright file="IViewFactory.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Views
+{
+    /// <summary>
+    /// Interface of a view factory.
+    /// </summary>
+    public interface IViewFactory
+    {
+        /// <summary>
+        /// Creates the main window.
+        /// </summary>
+        /// <returns>The main window.</returns>
+        IMainWindow CreateMainWindow();
+
+        /// <summary>
+        /// Creates the version information window.
+        /// </summary>
+        /// <returns>The version information window.</returns>
+        IVersionInformationWindow CreateVersionInformationWindow();
+
+        /// <summary>
+        /// Creates the file folder dialog.
+        /// </summary>
+        /// <returns>The file folder dialog.</returns>
+        IFileFolderDialog CreateFileFolderDialog();
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Core/Views/RelayCommand.cs b/Main/SimpleBackup.Core/Views/RelayCommand.cs
new file mode 100644 (file)
index 0000000..ad29dc2
--- /dev/null
@@ -0,0 +1,105 @@
+//-----------------------------------------------------------------------
+// <copyright file="RelayCommand.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Core.Views
+{
+    using System;
+    using System.Diagnostics;
+    using System.Windows.Input;
+    using SimpleBackup.Core.Utilities;
+
+    /// <summary>
+    /// A relay command for WPF MVVM pattern.
+    /// See WPF Apps With The Model-View-ViewModel Design Pattern http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030
+    /// in MSDN Magazine > Issues and Downloads > 2009 > February.
+    /// </summary>
+    public class RelayCommand : ICommand
+    {
+        /// <summary>
+        /// The execute action
+        /// </summary>
+        private readonly Action<object> executeAction;
+
+        /// <summary>
+        /// The can execute predicate
+        /// </summary>
+        private readonly Predicate<object> canExecutePredicate;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RelayCommand"/> class.
+        /// </summary>
+        /// <param name="executeAction">The execute action.</param>
+        public RelayCommand(Action<object> executeAction)
+            : this(executeAction, null)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RelayCommand"/> class.
+        /// </summary>
+        /// <param name="executeAction">The execute action.</param>
+        /// <param name="canExecutePredicate">The can execute predicate.</param>
+        /// <exception cref="System.ArgumentNullException">executeAction is null.</exception>
+        public RelayCommand(Action<object> executeAction, Predicate<object> canExecutePredicate)
+        {
+            executeAction.ThrowsArgumentNullException("executeAction");
+
+            this.executeAction = executeAction;
+            this.canExecutePredicate = canExecutePredicate;
+        }
+
+        /// <summary>
+        /// Occurs when changes occur that affect whether or not the command should execute.
+        /// </summary>
+        public event EventHandler CanExecuteChanged
+        {
+            add
+            {
+                CommandManager.RequerySuggested += value;
+            }
+
+            remove
+            {
+                CommandManager.RequerySuggested -= value;
+            }
+        }
+
+        /// <summary>
+        /// Defines the method to be called when the command is invoked.
+        /// </summary>
+        /// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null. </param>
+        public void Execute(object parameter)
+        {
+            this.executeAction(parameter);
+        }
+
+        /// <summary>
+        /// Defines the method that determines whether the command can execute in its current state.
+        /// </summary>
+        /// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null. </param>
+        /// <returns><c>true</c> if this command can be executed; otherwise, <c>false</c>.</returns>
+        [DebuggerStepThrough]
+        public bool CanExecute(object parameter)
+        {
+            return this.canExecutePredicate == null || this.canExecutePredicate(parameter);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Main/SimpleBackup.Models/BackupInfo.cs b/Main/SimpleBackup.Models/BackupInfo.cs
new file mode 100644 (file)
index 0000000..6b85734
--- /dev/null
@@ -0,0 +1,464 @@
+//-----------------------------------------------------------------------
+// <copyright file="BackupInfo.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Models
+{
+    using System;
+    using System.IO;
+    using System.Xml.Linq;
+    using SimpleBackup.Core.Models;
+    using SimpleBackup.Core.Utilities;
+    using Resources = SimpleBackup.Resources.Resources;
+
+    /// <summary>
+    /// A model of single backup information.
+    /// </summary>
+    internal class BackupInfo : PropertyChangeNotificationBase, IBackupInfo
+    {
+        private Guid innerId = Guid.NewGuid();
+        private string innerLabel = string.Empty;
+        private BackupSourceType innerBackupSourceType = BackupSourceType.File;
+        private bool innerIsEnabled = true;
+        private bool innerIsZipArchive;
+        private string innerSourcePath = string.Empty;
+        private string innerDestinationFolderPath = string.Empty;
+        private BackupState innerBackupState = BackupState.Todo;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BackupInfo"/> class.
+        /// </summary>
+        internal BackupInfo()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BackupInfo"/> class.
+        /// </summary>
+        /// <param name="sourceBackupInfo">The source backup information.</param>
+        /// <exception cref="System.ArgumentNullException">The index is out of range.</exception>
+        internal BackupInfo(IBackupInfo sourceBackupInfo)
+        {
+            sourceBackupInfo.ThrowsArgumentNullException("sourceBackupInfo");
+
+            this.Id = Guid.NewGuid();
+            this.BackupState = BackupState.Todo;
+
+            this.Label = sourceBackupInfo.Label;
+            this.BackupSourceType = sourceBackupInfo.BackupSourceType;
+            this.IsEnabled = sourceBackupInfo.IsEnabled;
+            this.IsZipArchive = sourceBackupInfo.IsZipArchive;
+            this.SourcePath = sourceBackupInfo.SourcePath;
+            this.DestinationFolderPath = sourceBackupInfo.DestinationFolderPath;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BackupInfo"/> class.
+        /// </summary>
+        /// <param name="label">The label.</param>
+        /// <param name="backupSourceType">Type of the backup source.</param>
+        /// <param name="isEnabled">if set to <c>true</c> the backup is enabled.</param>
+        /// <param name="isZipArchive">if set to <c>true</c> zip archive switch is on.</param>
+        /// <param name="sourcePath">The source path.</param>
+        /// <param name="destinationFolderPath">The destination folder path.</param>
+        /// <exception cref="System.ArgumentNullException">The label is null.</exception>
+        /// <exception cref="System.ArgumentNullException">The source path is null.</exception>
+        /// <exception cref="System.ArgumentNullException">The destination folder path is null.</exception>
+        internal BackupInfo(
+            string label,
+            BackupSourceType backupSourceType,
+            bool isEnabled,
+            bool isZipArchive,
+            string sourcePath,
+            string destinationFolderPath)
+        {
+            label.ThrowsArgumentNullException("label");
+            sourcePath.ThrowsArgumentNullException("sourcePath");
+            destinationFolderPath.ThrowsArgumentNullException("destinationFolderPath");
+
+            this.Id = Guid.NewGuid();
+            this.BackupState = BackupState.Todo;
+
+            this.Label = label;
+            this.BackupSourceType = backupSourceType;
+            this.IsEnabled = isEnabled;
+            this.IsZipArchive = isZipArchive;
+            this.SourcePath = sourcePath;
+            this.DestinationFolderPath = destinationFolderPath;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BackupInfo" /> class.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        /// <param name="label">The label.</param>
+        /// <param name="backupSourceType">Type of the backup source.</param>
+        /// <param name="isEnabled">if set to <c>true</c> the backup is enabled.</param>
+        /// <param name="isZipArchive">if set to <c>true</c> zip archive switch is on.</param>
+        /// <param name="sourcePath">The source path.</param>
+        /// <param name="destinationFolderPath">The destination folder path.</param>
+        /// <exception cref="System.ArgumentNullException">The label is null.</exception>
+        /// <exception cref="System.ArgumentNullException">The label is null.</exception>
+        /// <exception cref="System.ArgumentNullException">The label is null.</exception>
+        internal BackupInfo(
+            Guid id,
+            string label,
+            BackupSourceType backupSourceType,
+            bool isEnabled,
+            bool isZipArchive,
+            string sourcePath,
+            string destinationFolderPath)
+        {
+            label.ThrowsArgumentNullException("label");
+            sourcePath.ThrowsArgumentNullException("sourcePath");
+            destinationFolderPath.ThrowsArgumentNullException("destinationFolderPath");
+
+            this.Id = id;
+            this.BackupState = BackupState.Todo;
+
+            this.Label = label;
+            this.BackupSourceType = backupSourceType;
+            this.IsEnabled = isEnabled;
+            this.IsZipArchive = isZipArchive;
+            this.SourcePath = sourcePath;
+            this.DestinationFolderPath = destinationFolderPath;
+        }
+
+        /// <summary>
+        /// Occurs when a property which has to be saved in setting file is changed.
+        /// </summary>
+        public event EventHandler<EventArgs> SettingFilePropertyChanged;
+
+        /// <summary>
+        /// Gets or sets the identifier.
+        /// </summary>
+        public Guid Id
+        {
+            get
+            {
+                return this.innerId;
+            }
+
+            set
+            {
+                if (this.innerId != value)
+                {
+                    this.innerId = value;
+                    this.NotifyPropertyChanged("Id");
+                    this.NotifySettingFilePropertyChanged();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the label.
+        /// </summary>
+        public string Label
+        {
+            get
+            {
+                return this.innerLabel;
+            }
+
+            set
+            {
+                if (this.innerLabel != value)
+                {
+                    this.innerLabel = value;
+                    this.NotifyPropertyChanged("Label");
+                    this.NotifySettingFilePropertyChanged();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the type of the backup source.
+        /// </summary>
+        public BackupSourceType BackupSourceType
+        {
+            get
+            {
+                return this.innerBackupSourceType;
+            }
+
+            set
+            {
+                if (this.innerBackupSourceType != value)
+                {
+                    this.innerBackupSourceType = value;
+                    this.NotifyPropertyChanged("BackupSourceType");
+                    this.NotifySettingFilePropertyChanged();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the backup is enabled.
+        /// </summary>
+        public bool IsEnabled
+        {
+            get
+            {
+                return this.innerIsEnabled;
+            }
+
+            set
+            {
+                if (this.innerIsEnabled != value)
+                {
+                    this.innerIsEnabled = value;
+                    this.NotifyPropertyChanged("IsEnabled");
+                    this.NotifySettingFilePropertyChanged();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the backup is zip archive.
+        /// </summary>
+        public bool IsZipArchive
+        {
+            get
+            {
+                return this.innerIsZipArchive;
+            }
+
+            set
+            {
+                if (this.innerIsZipArchive != value)
+                {
+                    this.innerIsZipArchive = value;
+                    this.NotifyPropertyChanged("IsZipArchive");
+                    this.NotifySettingFilePropertyChanged();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the source path.
+        /// </summary>
+        public string SourcePath
+        {
+            get
+            {
+                return this.innerSourcePath;
+            }
+
+            set
+            {
+                if (this.innerSourcePath != value)
+                {
+                    this.innerSourcePath = value;
+                    this.NotifyPropertyChanged("SourcePath");
+                    this.NotifySettingFilePropertyChanged();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the destination folder path.
+        /// </summary>
+        public string DestinationFolderPath
+        {
+            get
+            {
+                return this.innerDestinationFolderPath;
+            }
+
+            set
+            {
+                if (this.innerDestinationFolderPath != value)
+                {
+                    this.innerDestinationFolderPath = value;
+                    this.NotifyPropertyChanged("DestinationFolderPath");
+                    this.NotifySettingFilePropertyChanged();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the state of the backup.
+        /// </summary>
+        public BackupState BackupState
+        {
+            get
+            {
+                return this.innerBackupState;
+            }
+
+            set
+            {
+                if (this.innerBackupState != value)
+                {
+                    this.innerBackupState = value;
+                    this.NotifyPropertyChanged("BackupState");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the name of the latest successful backup target.
+        /// </summary>
+        public string LatestSuccessfulBackupTargetName { get; set; }
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <returns>The backup information.</returns>
+        public static IBackupInfo CreateBackupInfo()
+        {
+            return new BackupInfo();
+        }
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <param name="sourceBackupInfo">The source backup information.</param>
+        /// <returns>The backup information.</returns>
+        public static IBackupInfo CreateBackupInfo(IBackupInfo sourceBackupInfo)
+        {
+            return new BackupInfo(sourceBackupInfo);
+        }
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        /// <param name="label">The label.</param>
+        /// <param name="backupSourceType">Type of the backup source.</param>
+        /// <param name="isEnabled">if set to <c>true</c> [is enabled].</param>
+        /// <param name="isZipArchive">if set to <c>true</c> [is zip archive].</param>
+        /// <param name="sourcePath">The source path.</param>
+        /// <param name="destinationFolderPath">The destination folder path.</param>
+        /// <returns>The backup information.</returns>
+        public static IBackupInfo CreateBackupInfo(
+            Guid id,
+            string label,
+            BackupSourceType backupSourceType,
+            bool isEnabled,
+            bool isZipArchive,
+            string sourcePath,
+            string destinationFolderPath)
+        {
+            return new BackupInfo(
+                id,
+                label,
+                backupSourceType,
+                isEnabled,
+                isZipArchive,
+                sourcePath,
+                destinationFolderPath);
+        }
+
+        /// <summary>
+        /// Restores from binary.
+        /// </summary>
+        /// <param name="binaryData">The binary data.</param>
+        /// <param name="copySuffixNeeded">if set to <c>true</c> [copy suffix needed].</param>
+        /// <returns>The restored backup information.</returns>
+        public static IBackupInfo FromBinary(byte[] binaryData, bool copySuffixNeeded)
+        {
+            var memoryStream = new MemoryStream(binaryData);
+            using (var binaryReader = new BinaryReader(memoryStream))
+            {
+                string label = binaryReader.ReadString();
+                var backupSourceType = (BackupSourceType)Enum.ToObject(typeof(BackupSourceType), binaryReader.ReadInt32());
+                bool isEnabled = binaryReader.ReadBoolean();
+                bool isZipArchive = binaryReader.ReadBoolean();
+                string sourcePath = binaryReader.ReadString();
+                string destinationFolderPath = binaryReader.ReadString();
+
+                return new BackupInfo(
+                    copySuffixNeeded ? string.Format("{0} - {1}", label, Resources.Edit_CopySuffix) : label,
+                    backupSourceType,
+                    isEnabled,
+                    isZipArchive,
+                    sourcePath,
+                    destinationFolderPath);
+            }
+        }
+
+        /// <summary>
+        /// Saves this instance to a XElement.
+        /// </summary>
+        /// <returns>The generated XElement.</returns>
+        public XElement ToXml()
+        {
+            var element = new XElement("BackupInfo");
+            element.Add(new XElement("Id", this.Id));
+            element.Add(new XElement("Label", this.Label));
+            element.Add(new XElement("BackupSourceType", this.BackupSourceType));
+            element.Add(new XElement("IsEnabled", this.IsEnabled));
+            element.Add(new XElement("IsZipArchive", this.IsZipArchive));
+            element.Add(new XElement("SourcePath", this.SourcePath));
+            element.Add(new XElement("DestinationFolderPath", this.DestinationFolderPath));
+
+            return element;
+        }
+
+        /// <summary>
+        /// Gets the binary representation of this instance.
+        /// </summary>
+        /// <returns>The binary representation of this instance.</returns>
+        public byte[] ToBinary()
+        {
+            var memoryStream = new MemoryStream();
+            using (var binaryWriter = new BinaryWriter(memoryStream))
+            {
+                binaryWriter.Write(this.Label);
+                binaryWriter.Write((int)this.BackupSourceType);
+                binaryWriter.Write(this.IsEnabled);
+                binaryWriter.Write(this.IsZipArchive);
+                binaryWriter.Write(this.SourcePath);
+                binaryWriter.Write(this.DestinationFolderPath);
+
+                memoryStream.Flush();
+                return memoryStream.GetBuffer();
+            }
+        }
+
+        /// <summary>
+        /// Gets the text representation of this instance.
+        /// </summary>
+        /// <returns>The text representation of this instance.</returns>
+        public string ToFormattedText()
+        {
+            return string.Format(
+                "{0}\t{1}\t{2}\t{3}\t{4}\t{5}",
+                this.Label,
+                this.BackupSourceType,
+                this.IsEnabled,
+                this.IsZipArchive,
+                this.SourcePath,
+                this.DestinationFolderPath);
+        }
+
+        /// <summary>
+        /// Notifies the setting file property is changed.
+        /// </summary>
+        private void NotifySettingFilePropertyChanged()
+        {
+            if (this.SettingFilePropertyChanged != null)
+            {
+                this.SettingFilePropertyChanged(this, new EventArgs());
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Models/BackupSetting.cs b/Main/SimpleBackup.Models/BackupSetting.cs
new file mode 100644 (file)
index 0000000..93c7fa8
--- /dev/null
@@ -0,0 +1,246 @@
+//-----------------------------------------------------------------------
+// <copyright file="BackupSetting.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Models
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using System.Xml.Linq;
+    using SimpleBackup.Core.Models;
+
+    /// <summary>
+    /// Represents a backup setting.
+    /// </summary>
+    internal class BackupSetting : IBackupSetting
+    {
+        private readonly List<IBackupInfo> backupInfoList = new List<IBackupInfo>();
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BackupSetting"/> class.
+        /// </summary>
+        internal BackupSetting()
+        {
+            this.SettingFileName = string.Empty;
+            this.Modified = true;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BackupSetting"/> class.
+        /// </summary>
+        /// <param name="settingFileName">Name of the setting file.</param>
+        /// <param name="backupInfoCollection">The backup information collection.</param>
+        internal BackupSetting(
+            string settingFileName,
+            IEnumerable<IBackupInfo> backupInfoCollection)
+        {
+            this.SettingFileName = settingFileName;
+            this.backupInfoList.AddRange(backupInfoCollection);
+            foreach (IBackupInfo backupInfo in this.backupInfoList)
+            {
+                backupInfo.SettingFilePropertyChanged += this.OnBackupInfoSettingFilePropertyChanged;
+            }
+        }
+
+        /// <summary>
+        /// Occurs when backup setting is modified.
+        /// </summary>
+        public event EventHandler SettingModified;
+
+        /// <summary>
+        /// Gets the name of the setting.
+        /// </summary>
+        public string SettingName
+        {
+            get
+            {
+                if (string.IsNullOrEmpty(this.SettingFileName))
+                {
+                    return Resources.Resources.Views_NewBackupSettingName;
+                }
+
+                return this.SettingFileName;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the name of the setting file.
+        /// </summary>
+        public string SettingFileName { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this <see cref="BackupSetting"/> is modified.
+        /// </summary>
+        public bool Modified { get; set; }
+
+        /// <summary>
+        /// Gets the backup infos.
+        /// </summary>
+        public IReadOnlyCollection<IBackupInfo> BackupInfos
+        {
+            get
+            {
+                return this.backupInfoList.AsReadOnly();
+            }
+        }
+
+        /// <summary>
+        /// Gets the count.
+        /// </summary>
+        public int Count
+        {
+            get
+            {
+                return this.backupInfoList.Count;
+            }
+        }
+
+        /// <summary>
+        /// Creates the backup setting.
+        /// </summary>
+        /// <returns>The backup setting.</returns>
+        public static IBackupSetting CreateBackupSetting()
+        {
+            return new BackupSetting();
+        }
+
+        /// <summary>
+        /// Creates the backup setting.
+        /// </summary>
+        /// <param name="settingFileName">Name of the setting file.</param>
+        /// <param name="backupInfoCollection">The backup information collection.</param>
+        /// <returns>The backup setting.</returns>
+//        public static IBackupSetting CreateBackupSetting(
+//            string settingFileName,
+//            IEnumerable<IBackupInfo> backupInfoCollection)
+//        {
+//            return new BackupSetting(settingFileName, backupInfoCollection);
+//        }
+
+        /// <summary>
+        /// Inserts the specified index.
+        /// </summary>
+        /// <param name="index">The index.</param>
+        /// <param name="backupInfo">The backup information.</param>
+        public void Insert(int index, IBackupInfo backupInfo)
+        {
+            backupInfo.SettingFilePropertyChanged += this.OnBackupInfoSettingFilePropertyChanged;
+            this.backupInfoList.Insert(index, backupInfo);
+
+            this.MarkAsModifiedAndPublishNotification();
+        }
+
+        /// <summary>
+        /// Removes the specified removing backup information.
+        /// </summary>
+        /// <param name="removingBackupInfo">The removing backup information.</param>
+        public void Remove(IBackupInfo removingBackupInfo)
+        {
+            removingBackupInfo.SettingFilePropertyChanged -= this.OnBackupInfoSettingFilePropertyChanged;
+            this.backupInfoList.Remove(removingBackupInfo);
+
+            this.MarkAsModifiedAndPublishNotification();
+        }
+
+        public IBackupInfo FirstOrDefault(Guid id)
+        {
+            return this.backupInfoList.FirstOrDefault(p => p.Id == id);
+        }
+
+        public void MoveItem(Guid backupInfoId, ItemMovingDirection movingDirection)
+        {
+            IBackupInfo movingBackupInfo = null;
+            int currentIndex = 0;
+            for (int i = 0; i < this.backupInfoList.Count; i++)
+            {
+                if (this.backupInfoList[i].Id == backupInfoId)
+                {
+                    currentIndex = i;
+                    movingBackupInfo = this.backupInfoList[i];
+                    break;
+                }
+            }
+
+            if (movingBackupInfo != null)
+            {
+                int newIndex = -1;
+                switch (movingDirection)
+                {
+                    case ItemMovingDirection.MoveUp:
+                        if (currentIndex > 0)
+                        {
+                            newIndex = currentIndex - 1;
+                        }
+
+                        break;
+                    case ItemMovingDirection.MoveDown:
+                        if (currentIndex < this.backupInfoList.Count - 1)
+                        {
+                            newIndex = currentIndex + 1;
+                        }
+
+                        break;
+                    default:
+                        throw new InvalidOperationException("Not supported direction.");
+                }
+
+                if (newIndex != -1)
+                {
+                    IBackupInfo temp = this.backupInfoList[newIndex];
+                    this.backupInfoList[newIndex] = this.backupInfoList[currentIndex];
+                    this.backupInfoList[currentIndex] = temp;
+                }
+
+                this.MarkAsModifiedAndPublishNotification();
+            }
+        }
+
+        public XElement ToXml()
+        {
+            var backupSettingElement = new XElement("BackupSetting");
+            backupSettingElement.SetAttributeValue("Version", "1.0");
+            backupSettingElement.SetAttributeValue("RequiredToolVersion", "1.0.0.181");
+
+            var items = new XElement("Items");
+            foreach (IBackupInfo backupInfo in this.BackupInfos)
+            {
+                items.Add(backupInfo.ToXml());
+            }
+
+            backupSettingElement.Add(items);
+            return backupSettingElement;
+        }
+
+        private void OnBackupInfoSettingFilePropertyChanged(object sender, EventArgs e)
+        {
+            this.MarkAsModifiedAndPublishNotification();
+        }
+
+        private void MarkAsModifiedAndPublishNotification()
+        {
+            this.Modified = true;
+            if (this.SettingModified != null)
+            {
+                this.SettingModified(this, new EventArgs());
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Models/DestinationPathInfo.cs b/Main/SimpleBackup.Models/DestinationPathInfo.cs
new file mode 100644 (file)
index 0000000..d54f65a
--- /dev/null
@@ -0,0 +1,52 @@
+//-----------------------------------------------------------------------
+// <copyright file="DestinationPathInfo.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Models
+{
+    using SimpleBackup.Core.Models;
+
+    /// <summary>
+    /// The destination path information.
+    /// </summary>
+    internal class DestinationPathInfo : IDestinationPathInfo
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DestinationPathInfo"/> class.
+        /// </summary>
+        /// <param name="backupSourceType">Type of the backup source.</param>
+        /// <param name="path">The path.</param>
+        public DestinationPathInfo(BackupSourceType backupSourceType, string path)
+        {
+            this.BackupSourceType = backupSourceType;
+            this.Path = path;
+        }
+
+        /// <summary>
+        /// Gets the type of the backup source.
+        /// </summary>
+        public BackupSourceType BackupSourceType { get; private set; }
+
+        /// <summary>
+        /// Gets the path.
+        /// </summary>
+        public string Path { get; private set; }
+    }
+}
diff --git a/Main/SimpleBackup.Models/ModelComponent.cs b/Main/SimpleBackup.Models/ModelComponent.cs
new file mode 100644 (file)
index 0000000..df9d461
--- /dev/null
@@ -0,0 +1,41 @@
+//-----------------------------------------------------------------------
+// <copyright file="ModelComponent.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Models
+{
+    using SimpleBackup.Core;
+    using SimpleBackup.Core.AppInfrastructure;
+    using SimpleBackup.Core.Models;
+
+    /// <summary>
+    /// The model component.
+    /// </summary>
+    internal class ModelComponent : IAppComponent
+    {
+        /// <summary>
+        /// Initializes this application component.
+        /// </summary>
+        public void Initialize()
+        {
+            ObjectContainer.Register<IModelFactory>(new ModelFactory());
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Models/ModelFactory.cs b/Main/SimpleBackup.Models/ModelFactory.cs
new file mode 100644 (file)
index 0000000..0a9e1e6
--- /dev/null
@@ -0,0 +1,278 @@
+//-----------------------------------------------------------------------
+// <copyright file="ModelFactory.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Models
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Linq;
+    using System.Xml.Linq;
+    using SimpleBackup.Core.Models;
+
+    /// <summary>
+    /// Creates model objectrs.
+    /// </summary>
+    internal class ModelFactory : IModelFactory
+    {
+        /// <summary>
+        /// Creates the backup setting.
+        /// </summary>
+        /// <returns>
+        /// The backup setting.
+        /// </returns>
+        public IBackupSetting CreateBackupSetting()
+        {
+            return new BackupSetting();
+        }
+
+        /// <summary>
+        /// Creates the backup setting.
+        /// </summary>
+        /// <param name="settingFileName">Name of the setting file.</param>
+        /// <param name="backupInfoCollection">The backup information collection.</param>
+        /// <returns>
+        /// The backup setting.
+        /// </returns>
+        public IBackupSetting CreateBackupSetting(
+            string settingFileName,
+            IEnumerable<IBackupInfo> backupInfoCollection)
+        {
+            return new BackupSetting(settingFileName, backupInfoCollection);
+        }
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <returns>
+        /// The backup inforamtion.
+        /// </returns>
+        public IBackupInfo CreateBackupInfo()
+        {
+            return new BackupInfo();
+        }
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <param name="sourceBackupInfo">The source backup information.</param>
+        /// <returns>
+        /// The backup inforamtion.
+        /// </returns>
+        public IBackupInfo CreateBackupInfo(IBackupInfo sourceBackupInfo)
+        {
+            return new BackupInfo(sourceBackupInfo);
+        }
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <param name="label">The label.</param>
+        /// <param name="backupSourceType">Type of the backup source.</param>
+        /// <param name="isEnabled">if set to <c>true</c> [is enabled].</param>
+        /// <param name="isZipArchive">if set to <c>true</c> [is zip archive].</param>
+        /// <param name="sourcePath">The source path.</param>
+        /// <param name="destinationFolderPath">The destination folder path.</param>
+        /// <returns>
+        /// The backup inforamtion.
+        /// </returns>
+        public IBackupInfo CreateBackupInfo(
+            string label,
+            BackupSourceType backupSourceType,
+            bool isEnabled,
+            bool isZipArchive,
+            string sourcePath,
+            string destinationFolderPath)
+        {
+            return new BackupInfo(
+                label,
+                backupSourceType,
+                isEnabled,
+                isZipArchive,
+                sourcePath,
+                destinationFolderPath);
+        }
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        /// <param name="label">The label.</param>
+        /// <param name="backupSourceType">Type of the backup source.</param>
+        /// <param name="isEnabled">if set to <c>true</c> [is enabled].</param>
+        /// <param name="isZipArchive">if set to <c>true</c> [is zip archive].</param>
+        /// <param name="sourcePath">The source path.</param>
+        /// <param name="destinationFolderPath">The destination folder path.</param>
+        /// <returns>
+        /// The backup inforamtion.
+        /// </returns>
+        public IBackupInfo CreateBackupInfo(
+            Guid id,
+            string label,
+            BackupSourceType backupSourceType,
+            bool isEnabled,
+            bool isZipArchive,
+            string sourcePath,
+            string destinationFolderPath)
+        {
+            return new BackupInfo(
+                id,
+                label,
+                backupSourceType,
+                isEnabled,
+                isZipArchive,
+                sourcePath,
+                destinationFolderPath);
+        }
+
+        /// <summary>
+        /// Creates the backup information from binary.
+        /// </summary>
+        /// <param name="binaryData">The binary data.</param>
+        /// <param name="copySuffixNeeded">if set to <c>true</c> copy suffix is needed.</param>
+        /// <returns>
+        /// The backup inforamtion.
+        /// </returns>
+        public IBackupInfo CreateBackupInfoFromBinary(byte[] binaryData, bool copySuffixNeeded)
+        {
+            return BackupInfo.FromBinary(binaryData, copySuffixNeeded);
+        }
+
+        /// <summary>
+        /// Creates the result information.
+        /// </summary>
+        /// <param name="category">The category.</param>
+        /// <param name="description">The description.</param>
+        /// <returns>
+        /// The result inforamtion.
+        /// </returns>
+        public IResultInfo CreateResultInfo(BackupState category, string description)
+        {
+            return new ResultInfo(category, description);
+        }
+
+        /// <summary>
+        /// Creates the destination path information.
+        /// </summary>
+        /// <param name="backupSourceType">Type of the backup source.</param>
+        /// <param name="path">The path.</param>
+        /// <returns>
+        /// The destination path information.
+        /// </returns>
+        public IDestinationPathInfo CreateDestinationPathInfo(BackupSourceType backupSourceType, string path)
+        {
+            return new DestinationPathInfo(backupSourceType, path);
+        }
+
+        /// <summary>
+        /// Restores the backup setting from XML.
+        /// </summary>
+        /// <param name="xml">The XML.</param>
+        /// <param name="fileName">Name of the file.</param>
+        /// <returns>The restored backup setting.</returns>
+        public IBackupSetting RestoreBackupSettingFromXml(XElement xml, string fileName)
+        {
+            if (xml.Name != "BackupSetting")
+            {
+                return null;
+            }
+
+            XElement itemsElement = xml.Elements("Items").FirstOrDefault();
+            if (itemsElement == null)
+            {
+                return null;
+            }
+
+            var backupInfoList = new List<IBackupInfo>();
+            foreach (XElement element in itemsElement.Elements())
+            {
+                IBackupInfo backupInfo = RestoreBackupInfoFromXml(element);
+                backupInfoList.Add(backupInfo);
+            }
+
+            return new BackupSetting(fileName, backupInfoList);
+        }
+
+        /// <summary>
+        /// Restores the backup information from XML.
+        /// </summary>
+        /// <param name="xml">The XML.</param>
+        /// <returns>The restored backup information.</returns>
+        private static IBackupInfo RestoreBackupInfoFromXml(XElement xml)
+        {
+            if (xml.Name != "BackupInfo")
+            {
+                return null;
+            }
+
+            XElement idElement = xml.Elements("Id").FirstOrDefault();
+            XElement labelElement = xml.Elements("Label").FirstOrDefault();
+            XElement backupSourceTypeElement = xml.Elements("BackupSourceType").FirstOrDefault();
+            XElement enabledElement = xml.Elements("IsEnabled").FirstOrDefault();
+            XElement zipArchiveElement = xml.Elements("IsZipArchive").FirstOrDefault();
+            XElement sourcePathElement = xml.Elements("SourcePath").FirstOrDefault();
+            XElement destinationFolderPathElement = xml.Elements("DestinationFolderPath").FirstOrDefault();
+
+            if ((idElement == null) ||
+                (labelElement == null) ||
+                (backupSourceTypeElement == null) ||
+                (enabledElement == null) ||
+                (zipArchiveElement == null) ||
+                (sourcePathElement == null) ||
+                (destinationFolderPathElement == null))
+            {
+                return null;
+            }
+
+            Guid id;
+            if (Guid.TryParse(idElement.Value, out id) == false)
+            {
+                return null;
+            }
+
+            BackupSourceType backupSourceType;
+            if (Enum.TryParse(backupSourceTypeElement.Value, out backupSourceType) == false)
+            {
+                return null;
+            }
+
+            bool isEnabled;
+            if (bool.TryParse(enabledElement.Value, out isEnabled) == false)
+            {
+                return null;
+            }
+
+            bool isZipArchive;
+            if (bool.TryParse(zipArchiveElement.Value, out isZipArchive) == false)
+            {
+                return null;
+            }
+
+            return BackupInfo.CreateBackupInfo(
+                id,
+                labelElement.Value,
+                backupSourceType,
+                isEnabled,
+                isZipArchive,
+                sourcePathElement.Value,
+                destinationFolderPathElement.Value);
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Models/ResultInfo.cs b/Main/SimpleBackup.Models/ResultInfo.cs
new file mode 100644 (file)
index 0000000..49642b9
--- /dev/null
@@ -0,0 +1,52 @@
+//-----------------------------------------------------------------------
+// <copyright file="ResultInfo.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Models
+{
+    using SimpleBackup.Core.Models;
+
+    /// <summary>
+    /// Represents a backup result.
+    /// </summary>
+    internal class ResultInfo : IResultInfo
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ResultInfo"/> class.
+        /// </summary>
+        /// <param name="category">The category.</param>
+        /// <param name="description">The description.</param>
+        public ResultInfo(BackupState category, string description)
+        {
+            this.BackupState = category;
+            this.Description = description ?? string.Empty;
+        }
+
+        /// <summary>
+        /// Gets the state of the backup.
+        /// </summary>
+        public BackupState BackupState { get; private set; }
+
+        /// <summary>
+        /// Gets the description.
+        /// </summary>
+        public string Description { get; private set; }
+    }
+}
diff --git a/Main/SimpleBackup.Models/SimpleBackup.Models.csproj b/Main/SimpleBackup.Models/SimpleBackup.Models.csproj
new file mode 100644 (file)
index 0000000..1c59dad
--- /dev/null
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{7B8C68F1-8A5C-470F-9356-F0EC1268617F}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SimpleBackup.Models</RootNamespace>
+    <AssemblyName>SimpleBackup.Models</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>SimpleBackupKey.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="PresentationCore" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+    <Reference Include="WindowsBase" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Properties\AssemblyInfo.cs">
+      <Link>Properties\AssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="BackupInfo.cs" />
+    <Compile Include="BackupSetting.cs" />
+    <Compile Include="DestinationPathInfo.cs" />
+    <Compile Include="ModelComponent.cs" />
+    <Compile Include="ModelFactory.cs" />
+    <Compile Include="ResultInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="SimpleBackupKey.snk" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\SimpleBackup.Core\SimpleBackup.Core.csproj">
+      <Project>{33f1d454-9962-4eb6-aad3-8d11d9a78d1f}</Project>
+      <Name>SimpleBackup.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\SimpleBackup.Resources\SimpleBackup.Resources.csproj">
+      <Project>{a655131e-d439-4de1-bc39-5c955306183f}</Project>
+      <Name>SimpleBackup.Resources</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PostBuildEvent>set EXE_BIN_DIR=$(ProjectDir)..\bin\$(ConfigurationName)\
+xcopy "$(TargetDir)$(TargetName).dll" "%25EXE_BIN_DIR%25" /Y
+if exist "$(TargetDir)$(TargetName).pdb" xcopy "$(TargetDir)$(TargetName).pdb" "%25EXE_BIN_DIR%25" /Y</PostBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Main/SimpleBackup.Models/SimpleBackupKey.snk b/Main/SimpleBackup.Models/SimpleBackupKey.snk
new file mode 100644 (file)
index 0000000..def2e6d
Binary files /dev/null and b/Main/SimpleBackup.Models/SimpleBackupKey.snk differ
diff --git a/Main/SimpleBackup.Resources/Images/Activity_16xLG.png b/Main/SimpleBackup.Resources/Images/Activity_16xLG.png
new file mode 100644 (file)
index 0000000..9fe818e
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Activity_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/AddVariable_5541.png b/Main/SimpleBackup.Resources/Images/AddVariable_5541.png
new file mode 100644 (file)
index 0000000..7888863
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/AddVariable_5541.png differ
diff --git a/Main/SimpleBackup.Resources/Images/ApplicationIcon.ico b/Main/SimpleBackup.Resources/Images/ApplicationIcon.ico
new file mode 100644 (file)
index 0000000..393d054
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/ApplicationIcon.ico differ
diff --git a/Main/SimpleBackup.Resources/Images/Arrow_RedoRetry_16xLG.png b/Main/SimpleBackup.Resources/Images/Arrow_RedoRetry_16xLG.png
new file mode 100644 (file)
index 0000000..75b508d
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Arrow_RedoRetry_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/Arrow_UndoRevertRestore_16xLG.png b/Main/SimpleBackup.Resources/Images/Arrow_UndoRevertRestore_16xLG.png
new file mode 100644 (file)
index 0000000..d759568
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Arrow_UndoRevertRestore_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/Copy_6524.png b/Main/SimpleBackup.Resources/Images/Copy_6524.png
new file mode 100644 (file)
index 0000000..5e506e8
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Copy_6524.png differ
diff --git a/Main/SimpleBackup.Resources/Images/Cut_6523.png b/Main/SimpleBackup.Resources/Images/Cut_6523.png
new file mode 100644 (file)
index 0000000..6683ee7
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Cut_6523.png differ
diff --git a/Main/SimpleBackup.Resources/Images/Delete_black_32x32.png b/Main/SimpleBackup.Resources/Images/Delete_black_32x32.png
new file mode 100644 (file)
index 0000000..906d053
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Delete_black_32x32.png differ
diff --git a/Main/SimpleBackup.Resources/Images/FileGroup_10135_32x.png b/Main/SimpleBackup.Resources/Images/FileGroup_10135_32x.png
new file mode 100644 (file)
index 0000000..166c1ae
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/FileGroup_10135_32x.png differ
diff --git a/Main/SimpleBackup.Resources/Images/NewFile_6276.png b/Main/SimpleBackup.Resources/Images/NewFile_6276.png
new file mode 100644 (file)
index 0000000..12354ce
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/NewFile_6276.png differ
diff --git a/Main/SimpleBackup.Resources/Images/Open_6529.png b/Main/SimpleBackup.Resources/Images/Open_6529.png
new file mode 100644 (file)
index 0000000..7482286
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Open_6529.png differ
diff --git a/Main/SimpleBackup.Resources/Images/Paste_6520.png b/Main/SimpleBackup.Resources/Images/Paste_6520.png
new file mode 100644 (file)
index 0000000..656678c
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Paste_6520.png differ
diff --git a/Main/SimpleBackup.Resources/Images/Print_11009.png b/Main/SimpleBackup.Resources/Images/Print_11009.png
new file mode 100644 (file)
index 0000000..fd56bdf
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Print_11009.png differ
diff --git a/Main/SimpleBackup.Resources/Images/StatusAnnotations_Complete_and_ok_32xLG_color.png b/Main/SimpleBackup.Resources/Images/StatusAnnotations_Complete_and_ok_32xLG_color.png
new file mode 100644 (file)
index 0000000..31d44e1
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/StatusAnnotations_Complete_and_ok_32xLG_color.png differ
diff --git a/Main/SimpleBackup.Resources/Images/StatusAnnotations_Critical_32xLG_color.png b/Main/SimpleBackup.Resources/Images/StatusAnnotations_Critical_32xLG_color.png
new file mode 100644 (file)
index 0000000..7d96891
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/StatusAnnotations_Critical_32xLG_color.png differ
diff --git a/Main/SimpleBackup.Resources/Images/Symbols_Complete_and_ok_32xLG.png b/Main/SimpleBackup.Resources/Images/Symbols_Complete_and_ok_32xLG.png
new file mode 100644 (file)
index 0000000..9817b25
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Symbols_Complete_and_ok_32xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/Synchronize_16xLG.png b/Main/SimpleBackup.Resources/Images/Synchronize_16xLG.png
new file mode 100644 (file)
index 0000000..5829529
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Synchronize_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/Warning.png b/Main/SimpleBackup.Resources/Images/Warning.png
new file mode 100644 (file)
index 0000000..2167241
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/Warning.png differ
diff --git a/Main/SimpleBackup.Resources/Images/action_Cancel_16xLG.png b/Main/SimpleBackup.Resources/Images/action_Cancel_16xLG.png
new file mode 100644 (file)
index 0000000..ac08d59
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/action_Cancel_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/arrow_Down_16xLG.png b/Main/SimpleBackup.Resources/Images/arrow_Down_16xLG.png
new file mode 100644 (file)
index 0000000..efdaccd
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/arrow_Down_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/arrow_Up_16xLG.png b/Main/SimpleBackup.Resources/Images/arrow_Up_16xLG.png
new file mode 100644 (file)
index 0000000..09b45f7
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/arrow_Up_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/arrow_all_run_16xLG.png b/Main/SimpleBackup.Resources/Images/arrow_all_run_16xLG.png
new file mode 100644 (file)
index 0000000..c2cf001
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/arrow_all_run_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/arrow_run_16xLG.png b/Main/SimpleBackup.Resources/Images/arrow_run_16xLG.png
new file mode 100644 (file)
index 0000000..b88c293
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/arrow_run_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/document_32xLG.png b/Main/SimpleBackup.Resources/Images/document_32xLG.png
new file mode 100644 (file)
index 0000000..66c486d
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/document_32xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/flag_16xLG.png b/Main/SimpleBackup.Resources/Images/flag_16xLG.png
new file mode 100644 (file)
index 0000000..25c3b86
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/flag_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/refresh_16xLG.png b/Main/SimpleBackup.Resources/Images/refresh_16xLG.png
new file mode 100644 (file)
index 0000000..129f36e
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/refresh_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/Images/save_16xLG.png b/Main/SimpleBackup.Resources/Images/save_16xLG.png
new file mode 100644 (file)
index 0000000..199d45b
Binary files /dev/null and b/Main/SimpleBackup.Resources/Images/save_16xLG.png differ
diff --git a/Main/SimpleBackup.Resources/ResourceHelper.cs b/Main/SimpleBackup.Resources/ResourceHelper.cs
new file mode 100644 (file)
index 0000000..d4362b6
--- /dev/null
@@ -0,0 +1,156 @@
+//-----------------------------------------------------------------------
+// <copyright file="ResourceService.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Resources
+{
+    using System;
+    using System.Resources;
+    using System.Windows;
+
+    /// <summary>
+    /// Provides localized resources.
+    /// </summary>
+    public class ResourceHelper
+    {
+        /// <summary>
+        /// The resource identifier property
+        /// </summary>
+        public static readonly DependencyProperty ResourceIdProperty = DependencyProperty.RegisterAttached(
+            "ResourceId",
+            typeof(string),
+            typeof(ResourceHelper),
+            new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.None, OnResourceIdChanged));
+
+        /// <summary>
+        /// The resource text property
+        /// </summary>
+        public static readonly DependencyProperty ResourceTextProperty = DependencyProperty.RegisterAttached(
+            "ResourceText",
+            typeof(string),
+            typeof(ResourceHelper),
+            new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.None));
+
+        /// <summary>
+        /// The inner resource manager
+        /// </summary>
+        private static readonly ResourceManager InnerResourceManager =
+            new ResourceManager("SimpleBackup.Resources.Resources", typeof(ResourceHelper).Assembly);
+
+        /// <summary>
+        /// The synchronize root
+        /// </summary>
+        private static readonly object SyncRoot = new object();
+
+        /// <summary>
+        /// The instance of ResourceService.
+        /// </summary>
+        private static volatile ResourceHelper instance;
+
+        /// <summary>
+        /// Prevents a default instance of the <see cref="ResourceHelper"/> class from being created.
+        /// </summary>
+        private ResourceHelper()
+        {
+        }
+
+        /// <summary>
+        /// Sets the resource identifier.
+        /// </summary>
+        /// <param name="obj">The dependency object.</param>
+        /// <param name="value">The value.</param>
+        public static void SetResourceId(DependencyObject obj, string value)
+        {
+            obj.SetValue(ResourceIdProperty, value);
+        }
+
+        /// <summary>
+        /// Gets the resource identifier.
+        /// </summary>
+        /// <param name="obj">The dependency object.</param>
+        /// <returns>The resource ID.</returns>
+        public static string GetResourceId(DependencyObject obj)
+        {
+            return (string)obj.GetValue(ResourceIdProperty);
+        }
+
+        /// <summary>
+        /// Gets the resource text.
+        /// </summary>
+        /// <param name="obj">The object.</param>
+        /// <returns>The resource text.</returns>
+        public static string GetResourceText(DependencyObject obj)
+        {
+            return (string)obj.GetValue(ResourceTextProperty);
+        }
+
+        /// <summary>
+        /// Called when [resource identifier changed].
+        /// </summary>
+        /// <param name="d">The dependency object.</param>
+        /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
+        private static void OnResourceIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            var newResourceId = (string)e.NewValue;
+            string resourceText;
+            if (TryGetResourceText(newResourceId, out resourceText))
+            {
+                d.SetValue(ResourceTextProperty, resourceText);
+            }
+        }
+
+        /// <summary>
+        /// Tries the get resource text.
+        /// </summary>
+        /// <param name="resourceId">The resource identifier.</param>
+        /// <param name="resourceText">The resource text.</param>
+        /// <returns>True if succeeded to get resource text.</returns>
+        private static bool TryGetResourceText(string resourceId, out string resourceText)
+        {
+            resourceText = string.Empty;
+
+            try
+            {
+                resourceText = InnerResourceManager.GetString(resourceId);
+            }
+            catch (ArgumentNullException)
+            {
+                //// Ignore exception.
+            }
+            catch (InvalidOperationException)
+            {
+                //// Ignore exception.
+            }
+            catch (MissingManifestResourceException)
+            {
+                //// Ignore exception.
+            }
+            catch (MissingSatelliteAssemblyException)
+            {
+                //// Ignore exception.
+            }
+
+            var succeeded = resourceText != null;
+            resourceText = resourceText ?? string.Empty;
+
+            return succeeded;
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Resources/Resources.Designer.cs b/Main/SimpleBackup.Resources/Resources.Designer.cs
new file mode 100644 (file)
index 0000000..09d4ef4
--- /dev/null
@@ -0,0 +1,778 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     このコードはツールによって生成されました。
+//     ランタイム バージョン:4.0.30319.34014
+//
+//     このファイルへの変更は、以下の状況下で不正な動作の原因になったり、
+//     コードが再生成されるときに損失したりします。
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace SimpleBackup.Resources {
+    using System;
+    
+    
+    /// <summary>
+    ///   ローカライズされた文字列などを検索するための、厳密に型指定されたリソース クラスです。
+    /// </summary>
+    // このクラスは StronglyTypedResourceBuilder クラスが ResGen
+    // または Visual Studio のようなツールを使用して自動生成されました。
+    // メンバーを追加または削除するには、.ResX ファイルを編集して、/str オプションと共に
+    // ResGen を実行し直すか、または VS プロジェクトをビルドし直します。
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    public class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   このクラスで使用されているキャッシュされた ResourceManager インスタンスを返します。
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        public static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SimpleBackup.Resources.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   厳密に型指定されたこのリソース クラスを使用して、すべての検索リソースに対し、
+        ///   現在のスレッドの CurrentUICulture プロパティをオーバーライドします。
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        public static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Backup... に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Backup_ExecutingBackup {
+            get {
+                return ResourceManager.GetString("Backup_ExecutingBackup", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   The backup information has not been prepared. に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Backup_Failed_BackupInfomationNotPrepared {
+            get {
+                return ResourceManager.GetString("Backup_Failed_BackupInfomationNotPrepared", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   The destination Folder does not exist. に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Backup_Failed_DestinationNotExist {
+            get {
+                return ResourceManager.GetString("Backup_Failed_DestinationNotExist", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Failed to copy the file. に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Backup_Failed_FailedToCopy {
+            get {
+                return ResourceManager.GetString("Backup_Failed_FailedToCopy", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   The source does not exist. に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Backup_Failed_SourceNotExist {
+            get {
+                return ResourceManager.GetString("Backup_Failed_SourceNotExist", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   From に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Backup_From {
+            get {
+                return ResourceManager.GetString("Backup_From", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   The backup has been skipped. に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Backup_Skipped {
+            get {
+                return ResourceManager.GetString("Backup_Skipped", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Done! に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Backup_Succeeded {
+            get {
+                return ResourceManager.GetString("Backup_Succeeded", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   To に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Backup_To {
+            get {
+                return ResourceManager.GetString("Backup_To", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Failed to open the backup setting. The file name is empty: {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupSetting_FailedToOpenSetting_EmptyFileNameFormat {
+            get {
+                return ResourceManager.GetString("BackupSetting_FailedToOpenSetting_EmptyFileNameFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Failed to open the backup setting. Invalid major version value: {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupSetting_FailedToOpenSetting_InvalidMajorVersionFormat {
+            get {
+                return ResourceManager.GetString("BackupSetting_FailedToOpenSetting_InvalidMajorVersionFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Failed to open the backup setting. Invalid minor version value: {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupSetting_FailedToOpenSetting_InvalidMinorVersionFormat {
+            get {
+                return ResourceManager.GetString("BackupSetting_FailedToOpenSetting_InvalidMinorVersionFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Failed to open the backup setting. Invalid &quot;RequiredToolVersion&quot; value: {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupSetting_FailedToOpenSetting_InvalidRequiredToolVersionFormat {
+            get {
+                return ResourceManager.GetString("BackupSetting_FailedToOpenSetting_InvalidRequiredToolVersionFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Failed to open the backup setting. Invalid &quot;Version&quot; value: {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupSetting_FailedToOpenSetting_InvalidVersionFormat {
+            get {
+                return ResourceManager.GetString("BackupSetting_FailedToOpenSetting_InvalidVersionFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Failed to open the backup setting. There is no &quot;BackupSetting&quot; tag: {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupSetting_FailedToOpenSetting_NoBackupSettingElementFormat {
+            get {
+                return ResourceManager.GetString("BackupSetting_FailedToOpenSetting_NoBackupSettingElementFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Failed to open the backup setting. There is no &quot;Version&quot; tag: {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupSetting_FailedToOpenSetting_NoVersionElementFormat {
+            get {
+                return ResourceManager.GetString("BackupSetting_FailedToOpenSetting_NoVersionElementFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Failed to read the backup setting data because it is incomatible. To read the backup setting data, please use Simple Backup Ver.{0} or later. に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupSetting_IncompatibleMajorVersionFormat {
+            get {
+                return ResourceManager.GetString("BackupSetting_IncompatibleMajorVersionFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Failed to read some part of the backup setting data because they are incompatible. To read all the backup setting data, please use Simple Backup Ver.{0} or later. に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupSetting_IncompatibleMinorVersionFormat {
+            get {
+                return ResourceManager.GetString("BackupSetting_IncompatibleMinorVersionFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   The backup setting is opened: {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupSetting_SettingOpenedFormat {
+            get {
+                return ResourceManager.GetString("BackupSetting_SettingOpenedFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Cancelled に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupState_Cancelled {
+            get {
+                return ResourceManager.GetString("BackupState_Cancelled", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Fail に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupState_Failed {
+            get {
+                return ResourceManager.GetString("BackupState_Failed", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   In Progress に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupState_InProgress {
+            get {
+                return ResourceManager.GetString("BackupState_InProgress", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Skipped に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupState_Skipped {
+            get {
+                return ResourceManager.GetString("BackupState_Skipped", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Success に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupState_Success {
+            get {
+                return ResourceManager.GetString("BackupState_Success", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   TODO に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string BackupState_Todo {
+            get {
+                return ResourceManager.GetString("BackupState_Todo", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Copy に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Edit_CopySuffix {
+            get {
+                return ResourceManager.GetString("Edit_CopySuffix", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Failed to open the file: {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string FileAccess_FailedToOpenFormat {
+            get {
+                return ResourceManager.GetString("FileAccess_FailedToOpenFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   The folder path does not exist: {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string FileAccess_FolderPathNotExistFormat {
+            get {
+                return ResourceManager.GetString("FileAccess_FolderPathNotExistFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   The path is not valid: {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string FileAccess_InvalidPathFormat {
+            get {
+                return ResourceManager.GetString("FileAccess_InvalidPathFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Copyright© 2015 Takayoshi Matsuyama に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Version_Copyright {
+            get {
+                return ResourceManager.GetString("Version_Copyright", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+        ///
+        ///This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+        ///
+        ///You should have received a copy  [残りの文字列は切り詰められました]&quot;; に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Version_CopyrightDescription {
+            get {
+                return ResourceManager.GetString("Version_CopyrightDescription", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Add に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_AddButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_AddButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Destination に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_BackupDestinationColumnHeaderText {
+            get {
+                return ResourceManager.GetString("Views_BackupDestinationColumnHeaderText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Source に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_BackupSourceColumnHeaderText {
+            get {
+                return ResourceManager.GetString("Views_BackupSourceColumnHeaderText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Cancel Multi Backup に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_CancelMultiBackupButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_CancelMultiBackupButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Confirmation に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_ConfirmationDialogTitle {
+            get {
+                return ResourceManager.GetString("Views_ConfirmationDialogTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Backup に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_ContextMenu_Backup {
+            get {
+                return ResourceManager.GetString("Views_ContextMenu_Backup", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Edit に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_ContextMenu_Edit {
+            get {
+                return ResourceManager.GetString("Views_ContextMenu_Edit", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Open Destination に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_ContextMenu_OpenDestination {
+            get {
+                return ResourceManager.GetString("Views_ContextMenu_OpenDestination", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Open File に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_ContextMenu_OpenFile {
+            get {
+                return ResourceManager.GetString("Views_ContextMenu_OpenFile", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Open Source Folder に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_ContextMenu_OpenSourceFolder {
+            get {
+                return ResourceManager.GetString("Views_ContextMenu_OpenSourceFolder", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Select Destination に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_ContextMenu_SelectDestination {
+            get {
+                return ResourceManager.GetString("Views_ContextMenu_SelectDestination", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Select Source に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_ContextMenu_SelectSource {
+            get {
+                return ResourceManager.GetString("Views_ContextMenu_SelectSource", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Copy に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_CopyButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_CopyButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Simple Backup に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_CopyrightApplicationName {
+            get {
+                return ResourceManager.GetString("Views_CopyrightApplicationName", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Cut に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_CutButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_CutButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Simple Backup に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_DefaultWindowTitle {
+            get {
+                return ResourceManager.GetString("Views_DefaultWindowTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Label に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_LabelColumnHeaderText {
+            get {
+                return ResourceManager.GetString("Views_LabelColumnHeaderText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   _Close に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MainMenu_Close {
+            get {
+                return ResourceManager.GetString("Views_MainMenu_Close", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   E_xit に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MainMenu_Exit {
+            get {
+                return ResourceManager.GetString("Views_MainMenu_Exit", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   _File に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MainMenu_File {
+            get {
+                return ResourceManager.GetString("Views_MainMenu_File", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   _Help に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MainMenu_Help {
+            get {
+                return ResourceManager.GetString("Views_MainMenu_Help", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   _New に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MainMenu_New {
+            get {
+                return ResourceManager.GetString("Views_MainMenu_New", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   _Open に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MainMenu_Open {
+            get {
+                return ResourceManager.GetString("Views_MainMenu_Open", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Open Current Setting File Location に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MainMenu_OpenCurrentSettingFileLocation {
+            get {
+                return ResourceManager.GetString("Views_MainMenu_OpenCurrentSettingFileLocation", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   _Save に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MainMenu_Save {
+            get {
+                return ResourceManager.GetString("Views_MainMenu_Save", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Save _As に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MainMenu_SaveAs {
+            get {
+                return ResourceManager.GetString("Views_MainMenu_SaveAs", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Show Help (_V) に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MainMenu_ShowHelp {
+            get {
+                return ResourceManager.GetString("Views_MainMenu_ShowHelp", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Show Version Information (_A) に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MainMenu_ShowVersionInformation {
+            get {
+                return ResourceManager.GetString("Views_MainMenu_ShowVersionInformation", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Move down に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MoveDownButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_MoveDownButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Move up に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MoveUpButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_MoveUpButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Multiple Backup に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_MultipleBackupButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_MultipleBackupButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   New Backup に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_NewBackupSettingName {
+            get {
+                return ResourceManager.GetString("Views_NewBackupSettingName", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   New に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_NewFileButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_NewFileButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Open Backup Setting に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_OpenBackupSettingButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_OpenBackupSettingButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Open Backup Setting に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_OpenFileDialogTitle {
+            get {
+                return ResourceManager.GetString("Views_OpenFileDialogTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Clear に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_OutputWindowContextMenu_Clear {
+            get {
+                return ResourceManager.GetString("Views_OutputWindowContextMenu_Clear", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Paste に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_PasteButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_PasteButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Redo に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_RedoButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_RedoButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Refresh に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_RefreshButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_RefreshButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Remove に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_RemoveButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_RemoveButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Save Backup Setting に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_SaveBackupSettingButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_SaveBackupSettingButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Save the changes? に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_SaveConfirmationMessage {
+            get {
+                return ResourceManager.GetString("Views_SaveConfirmationMessage", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Save Backup Setting に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_SaveFileDialogTitle {
+            get {
+                return ResourceManager.GetString("Views_SaveFileDialogTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Single Backup に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_SingleBackupButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_SingleBackupButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Undo に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_UndoButtonToolTipText {
+            get {
+                return ResourceManager.GetString("Views_UndoButtonToolTipText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Version Information of Simple Backup に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_VersionWindowTitle {
+            get {
+                return ResourceManager.GetString("Views_VersionWindowTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Simple Backup - {0} に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_WindowTitleFormat {
+            get {
+                return ResourceManager.GetString("Views_WindowTitleFormat", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Zip Encoding に類似しているローカライズされた文字列を検索します。
+        /// </summary>
+        public static string Views_ZipEncodingTitleText {
+            get {
+                return ResourceManager.GetString("Views_ZipEncodingTitleText", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Resources/Resources.ja.resx b/Main/SimpleBackup.Resources/Resources.ja.resx
new file mode 100644 (file)
index 0000000..b16a2a4
--- /dev/null
@@ -0,0 +1,348 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="BackupState_Cancelled" xml:space="preserve">
+    <value>キャンセル</value>
+  </data>
+  <data name="BackupState_Failed" xml:space="preserve">
+    <value>失敗</value>
+  </data>
+  <data name="BackupState_InProgress" xml:space="preserve">
+    <value>進行中</value>
+  </data>
+  <data name="BackupState_Skipped" xml:space="preserve">
+    <value>スキップ</value>
+  </data>
+  <data name="BackupState_Success" xml:space="preserve">
+    <value>成功</value>
+  </data>
+  <data name="BackupState_Todo" xml:space="preserve">
+    <value>実行待ち</value>
+  </data>
+  <data name="Backup_ExecutingBackup" xml:space="preserve">
+    <value>バックアップ実行中...</value>
+  </data>
+  <data name="Backup_Failed_SourceNotExist" xml:space="preserve">
+    <value>バックアップ対象がありません。</value>
+  </data>
+  <data name="Backup_Failed_BackupInfomationNotPrepared" xml:space="preserve">
+    <value>バックアップ情報が準備できていません。</value>
+  </data>
+  <data name="Backup_Skipped" xml:space="preserve">
+    <value>バックアップはスキップされました。</value>
+  </data>
+  <data name="Backup_From" xml:space="preserve">
+    <value>バックアップ対象</value>
+  </data>
+  <data name="Backup_To" xml:space="preserve">
+    <value>バックアップ先</value>
+  </data>
+  <data name="Edit_CopySuffix" xml:space="preserve">
+    <value>コピー</value>
+  </data>
+  <data name="Views_AddButtonToolTipText" xml:space="preserve">
+    <value>追加</value>
+  </data>
+  <data name="Views_BackupDestinationColumnHeaderText" xml:space="preserve">
+    <value>バックアップ先</value>
+  </data>
+  <data name="Views_BackupSourceColumnHeaderText" xml:space="preserve">
+    <value>バックアップ対象</value>
+  </data>
+  <data name="Views_CancelMultiBackupButtonToolTipText" xml:space="preserve">
+    <value>マルチバックアップをキャンセル</value>
+  </data>
+  <data name="Views_ContextMenu_Backup" xml:space="preserve">
+    <value>バックアップ</value>
+  </data>
+  <data name="Views_ContextMenu_Edit" xml:space="preserve">
+    <value>編集</value>
+  </data>
+  <data name="Views_ContextMenu_OpenDestination" xml:space="preserve">
+    <value>バックアップ先の場所を開く</value>
+  </data>
+  <data name="Views_ContextMenu_OpenFile" xml:space="preserve">
+    <value>ファイルを開く</value>
+  </data>
+  <data name="Views_ContextMenu_OpenSourceFolder" xml:space="preserve">
+    <value>バックアップ対象の場所を開く</value>
+  </data>
+  <data name="Views_ContextMenu_SelectDestination" xml:space="preserve">
+    <value>バックアップ先を選ぶ</value>
+  </data>
+  <data name="Views_ContextMenu_SelectSource" xml:space="preserve">
+    <value>バックアップ対象を選ぶ</value>
+  </data>
+  <data name="Views_CopyButtonToolTipText" xml:space="preserve">
+    <value>コピー</value>
+  </data>
+  <data name="Views_CutButtonToolTipText" xml:space="preserve">
+    <value>切り取り</value>
+  </data>
+  <data name="Views_DefaultWindowTitle" xml:space="preserve">
+    <value>バックアップツール</value>
+  </data>
+  <data name="Views_LabelColumnHeaderText" xml:space="preserve">
+    <value>ラベル</value>
+  </data>
+  <data name="Views_MainMenu_Close" xml:space="preserve">
+    <value>閉じる(_C)</value>
+  </data>
+  <data name="Views_MainMenu_Exit" xml:space="preserve">
+    <value>終了(_X)</value>
+  </data>
+  <data name="Views_MainMenu_File" xml:space="preserve">
+    <value>ファイル(_F)</value>
+  </data>
+  <data name="Views_MainMenu_Help" xml:space="preserve">
+    <value>ヘルプ(_H)</value>
+  </data>
+  <data name="Views_MainMenu_New" xml:space="preserve">
+    <value>新規作成(_N)</value>
+  </data>
+  <data name="Views_MainMenu_Open" xml:space="preserve">
+    <value>開く(_O)</value>
+  </data>
+  <data name="Views_MainMenu_OpenCurrentSettingFileLocation" xml:space="preserve">
+    <value>現在の設定ファイルの場所を開く</value>
+  </data>
+  <data name="Views_MainMenu_ShowHelp" xml:space="preserve">
+    <value>ヘルプの表示(_V)</value>
+  </data>
+  <data name="Views_MainMenu_ShowVersionInformation" xml:space="preserve">
+    <value>バージョン情報(_A)</value>
+  </data>
+  <data name="Views_MoveDownButtonToolTipText" xml:space="preserve">
+    <value>下へ移動</value>
+  </data>
+  <data name="Views_MoveUpButtonToolTipText" xml:space="preserve">
+    <value>上へ移動</value>
+  </data>
+  <data name="Views_MultipleBackupButtonToolTipText" xml:space="preserve">
+    <value>マルチバックアップ</value>
+  </data>
+  <data name="Views_NewBackupSettingName" xml:space="preserve">
+    <value>新しいバックアップ</value>
+  </data>
+  <data name="Views_NewFileButtonToolTipText" xml:space="preserve">
+    <value>新規作成</value>
+  </data>
+  <data name="Views_OpenBackupSettingButtonToolTipText" xml:space="preserve">
+    <value>バックアップ設定を開く</value>
+  </data>
+  <data name="Views_OutputWindowContextMenu_Clear" xml:space="preserve">
+    <value>クリア</value>
+  </data>
+  <data name="Views_PasteButtonToolTipText" xml:space="preserve">
+    <value>貼り付け</value>
+  </data>
+  <data name="Views_RedoButtonToolTipText" xml:space="preserve">
+    <value>やり直し</value>
+  </data>
+  <data name="Views_RefreshButtonToolTipText" xml:space="preserve">
+    <value>リフレッシュ</value>
+  </data>
+  <data name="Views_RemoveButtonToolTipText" xml:space="preserve">
+    <value>削除</value>
+  </data>
+  <data name="Views_SaveBackupSettingButtonToolTipText" xml:space="preserve">
+    <value>バックアップ設定を保存する</value>
+  </data>
+  <data name="Views_SingleBackupButtonToolTipText" xml:space="preserve">
+    <value>シングルバックアップ</value>
+  </data>
+  <data name="Views_UndoButtonToolTipText" xml:space="preserve">
+    <value>元に戻す</value>
+  </data>
+  <data name="Views_VersionWindowTitle" xml:space="preserve">
+    <value>バックアップツールのバージョン情報</value>
+  </data>
+  <data name="Views_WindowTitleFormat" xml:space="preserve">
+    <value>バックアップツール - {0}</value>
+  </data>
+  <data name="Backup_Failed_DestinationNotExist" xml:space="preserve">
+    <value>バックアップ先のフォルダががありません。</value>
+  </data>
+  <data name="Backup_Failed_FailedToCopy" xml:space="preserve">
+    <value>ファイルのコピーに失敗しました。</value>
+  </data>
+  <data name="Backup_Succeeded" xml:space="preserve">
+    <value>バックアップを完了しました。</value>
+  </data>
+  <data name="Views_MainMenu_Save" xml:space="preserve">
+    <value>保存(_S)</value>
+  </data>
+  <data name="Views_MainMenu_SaveAs" xml:space="preserve">
+    <value>名前を付けて保存(_A)</value>
+  </data>
+  <data name="Views_ZipEncodingTitleText" xml:space="preserve">
+    <value>Zipエンコード</value>
+  </data>
+  <data name="Views_OpenFileDialogTitle" xml:space="preserve">
+    <value>バックアップ設定を開く</value>
+  </data>
+  <data name="Views_SaveFileDialogTitle" xml:space="preserve">
+    <value>バックアップ設定の保存</value>
+  </data>
+  <data name="BackupSetting_IncompatibleMajorVersionFormat" xml:space="preserve">
+    <value>互換性がないため、バックアップ設定データの読み込みに失敗しました。このバックアップ設定データを読み込むには、Ver.{0}以降のバックアップツールを入手してください。</value>
+  </data>
+  <data name="BackupSetting_IncompatibleMinorVersionFormat" xml:space="preserve">
+    <value>互換性がないため、一部のバックアップ設定データの読み込みに失敗しました。全てのバックアップ設定データを読み込むには、Ver.{0}以降のバックアップツールを入手してください。</value>
+  </data>
+  <data name="BackupSetting_SettingOpenedFormat" xml:space="preserve">
+    <value>バックアップ設定を開きました。{0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_EmptyFileNameFormat" xml:space="preserve">
+    <value>バックアップ設定の読み込みに失敗しました。ファイル名が空です。{0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_InvalidMajorVersionFormat" xml:space="preserve">
+    <value>バックアップ設定の読み込みに失敗しました。メジャーバージョン値が不正です。{0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_InvalidMinorVersionFormat" xml:space="preserve">
+    <value>バックアップ設定の読み込みに失敗しました。マイナーバージョン値が不正です。{0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_InvalidRequiredToolVersionFormat" xml:space="preserve">
+    <value>バックアップ設定の読み込みに失敗しました。"RequiredToolVersion"値が不正です。{0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_InvalidVersionFormat" xml:space="preserve">
+    <value>バックアップ設定の読み込みに失敗しました。"Version"値が不正です。{0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_NoBackupSettingElementFormat" xml:space="preserve">
+    <value>バックアップ設定の読み込みに失敗しました。"BackupSetting"タグが見つかりません。{0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_NoVersionElementFormat" xml:space="preserve">
+    <value>バックアップ設定の読み込みに失敗しました。"Version"タグが見つかりません。{0}</value>
+  </data>
+  <data name="FileAccess_FailedToOpenFormat" xml:space="preserve">
+    <value>ファイルオープンに失敗しました。 {0}</value>
+  </data>
+  <data name="FileAccess_FolderPathNotExistFormat" xml:space="preserve">
+    <value>存在しないフォルダです。 {0}</value>
+  </data>
+  <data name="FileAccess_InvalidPathFormat" xml:space="preserve">
+    <value>不正なパスです。 {0}</value>
+  </data>
+  <data name="Views_ConfirmationDialogTitle" xml:space="preserve">
+    <value>確認</value>
+  </data>
+  <data name="Views_SaveConfirmationMessage" xml:space="preserve">
+    <value>変更を保存しますか?</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Main/SimpleBackup.Resources/Resources.resx b/Main/SimpleBackup.Resources/Resources.resx
new file mode 100644 (file)
index 0000000..a8eb5b9
--- /dev/null
@@ -0,0 +1,361 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="BackupState_Cancelled" xml:space="preserve">
+    <value>Cancelled</value>
+  </data>
+  <data name="BackupState_Failed" xml:space="preserve">
+    <value>Fail</value>
+  </data>
+  <data name="BackupState_InProgress" xml:space="preserve">
+    <value>In Progress</value>
+  </data>
+  <data name="BackupState_Skipped" xml:space="preserve">
+    <value>Skipped</value>
+  </data>
+  <data name="BackupState_Success" xml:space="preserve">
+    <value>Success</value>
+  </data>
+  <data name="BackupState_Todo" xml:space="preserve">
+    <value>TODO</value>
+  </data>
+  <data name="Backup_ExecutingBackup" xml:space="preserve">
+    <value>Backup...</value>
+  </data>
+  <data name="Backup_Failed_SourceNotExist" xml:space="preserve">
+    <value>The source does not exist.</value>
+  </data>
+  <data name="Backup_Failed_BackupInfomationNotPrepared" xml:space="preserve">
+    <value>The backup information has not been prepared.</value>
+  </data>
+  <data name="Backup_Skipped" xml:space="preserve">
+    <value>The backup has been skipped.</value>
+  </data>
+  <data name="Backup_From" xml:space="preserve">
+    <value>From</value>
+  </data>
+  <data name="Backup_To" xml:space="preserve">
+    <value>To</value>
+  </data>
+  <data name="Edit_CopySuffix" xml:space="preserve">
+    <value>Copy</value>
+  </data>
+  <data name="Version_Copyright" xml:space="preserve">
+    <value>Copyright© 2015 Takayoshi Matsuyama</value>
+  </data>
+  <data name="Version_CopyrightDescription" xml:space="preserve">
+    <value>This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with this program.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</value>
+  </data>
+  <data name="Views_AddButtonToolTipText" xml:space="preserve">
+    <value>Add</value>
+  </data>
+  <data name="Views_BackupDestinationColumnHeaderText" xml:space="preserve">
+    <value>Destination</value>
+  </data>
+  <data name="Views_BackupSourceColumnHeaderText" xml:space="preserve">
+    <value>Source</value>
+  </data>
+  <data name="Views_CancelMultiBackupButtonToolTipText" xml:space="preserve">
+    <value>Cancel Multi Backup</value>
+  </data>
+  <data name="Views_ContextMenu_Backup" xml:space="preserve">
+    <value>Backup</value>
+  </data>
+  <data name="Views_ContextMenu_Edit" xml:space="preserve">
+    <value>Edit</value>
+  </data>
+  <data name="Views_ContextMenu_OpenDestination" xml:space="preserve">
+    <value>Open Destination</value>
+  </data>
+  <data name="Views_ContextMenu_OpenFile" xml:space="preserve">
+    <value>Open File</value>
+  </data>
+  <data name="Views_ContextMenu_OpenSourceFolder" xml:space="preserve">
+    <value>Open Source Folder</value>
+  </data>
+  <data name="Views_ContextMenu_SelectDestination" xml:space="preserve">
+    <value>Select Destination</value>
+  </data>
+  <data name="Views_ContextMenu_SelectSource" xml:space="preserve">
+    <value>Select Source</value>
+  </data>
+  <data name="Views_CopyButtonToolTipText" xml:space="preserve">
+    <value>Copy</value>
+  </data>
+  <data name="Views_CopyrightApplicationName" xml:space="preserve">
+    <value>Simple Backup</value>
+  </data>
+  <data name="Views_CutButtonToolTipText" xml:space="preserve">
+    <value>Cut</value>
+  </data>
+  <data name="Views_DefaultWindowTitle" xml:space="preserve">
+    <value>Simple Backup</value>
+  </data>
+  <data name="Views_LabelColumnHeaderText" xml:space="preserve">
+    <value>Label</value>
+  </data>
+  <data name="Views_MainMenu_Close" xml:space="preserve">
+    <value>_Close</value>
+  </data>
+  <data name="Views_MainMenu_Exit" xml:space="preserve">
+    <value>E_xit</value>
+  </data>
+  <data name="Views_MainMenu_File" xml:space="preserve">
+    <value>_File</value>
+  </data>
+  <data name="Views_MainMenu_Help" xml:space="preserve">
+    <value>_Help</value>
+  </data>
+  <data name="Views_MainMenu_New" xml:space="preserve">
+    <value>_New</value>
+  </data>
+  <data name="Views_MainMenu_Open" xml:space="preserve">
+    <value>_Open</value>
+  </data>
+  <data name="Views_MainMenu_OpenCurrentSettingFileLocation" xml:space="preserve">
+    <value>Open Current Setting File Location</value>
+  </data>
+  <data name="Views_MainMenu_ShowHelp" xml:space="preserve">
+    <value>Show Help (_V)</value>
+  </data>
+  <data name="Views_MainMenu_ShowVersionInformation" xml:space="preserve">
+    <value>Show Version Information (_A)</value>
+  </data>
+  <data name="Views_MoveDownButtonToolTipText" xml:space="preserve">
+    <value>Move down</value>
+  </data>
+  <data name="Views_MoveUpButtonToolTipText" xml:space="preserve">
+    <value>Move up</value>
+  </data>
+  <data name="Views_MultipleBackupButtonToolTipText" xml:space="preserve">
+    <value>Multiple Backup</value>
+  </data>
+  <data name="Views_NewBackupSettingName" xml:space="preserve">
+    <value>New Backup</value>
+  </data>
+  <data name="Views_NewFileButtonToolTipText" xml:space="preserve">
+    <value>New</value>
+  </data>
+  <data name="Views_OpenBackupSettingButtonToolTipText" xml:space="preserve">
+    <value>Open Backup Setting</value>
+  </data>
+  <data name="Views_OutputWindowContextMenu_Clear" xml:space="preserve">
+    <value>Clear</value>
+  </data>
+  <data name="Views_PasteButtonToolTipText" xml:space="preserve">
+    <value>Paste</value>
+  </data>
+  <data name="Views_RedoButtonToolTipText" xml:space="preserve">
+    <value>Redo</value>
+  </data>
+  <data name="Views_RefreshButtonToolTipText" xml:space="preserve">
+    <value>Refresh</value>
+  </data>
+  <data name="Views_RemoveButtonToolTipText" xml:space="preserve">
+    <value>Remove</value>
+  </data>
+  <data name="Views_SaveBackupSettingButtonToolTipText" xml:space="preserve">
+    <value>Save Backup Setting</value>
+  </data>
+  <data name="Views_SingleBackupButtonToolTipText" xml:space="preserve">
+    <value>Single Backup</value>
+  </data>
+  <data name="Views_UndoButtonToolTipText" xml:space="preserve">
+    <value>Undo</value>
+  </data>
+  <data name="Views_VersionWindowTitle" xml:space="preserve">
+    <value>Version Information of Simple Backup</value>
+  </data>
+  <data name="Views_WindowTitleFormat" xml:space="preserve">
+    <value>Simple Backup - {0}</value>
+  </data>
+  <data name="Backup_Failed_DestinationNotExist" xml:space="preserve">
+    <value>The destination Folder does not exist.</value>
+  </data>
+  <data name="Backup_Failed_FailedToCopy" xml:space="preserve">
+    <value>Failed to copy the file.</value>
+  </data>
+  <data name="Backup_Succeeded" xml:space="preserve">
+    <value>Done!</value>
+  </data>
+  <data name="Views_MainMenu_Save" xml:space="preserve">
+    <value>_Save</value>
+  </data>
+  <data name="Views_MainMenu_SaveAs" xml:space="preserve">
+    <value>Save _As</value>
+  </data>
+  <data name="Views_ZipEncodingTitleText" xml:space="preserve">
+    <value>Zip Encoding</value>
+  </data>
+  <data name="Views_OpenFileDialogTitle" xml:space="preserve">
+    <value>Open Backup Setting</value>
+  </data>
+  <data name="Views_SaveFileDialogTitle" xml:space="preserve">
+    <value>Save Backup Setting</value>
+  </data>
+  <data name="BackupSetting_IncompatibleMajorVersionFormat" xml:space="preserve">
+    <value>Failed to read the backup setting data because it is incomatible. To read the backup setting data, please use Simple Backup Ver.{0} or later.</value>
+  </data>
+  <data name="BackupSetting_IncompatibleMinorVersionFormat" xml:space="preserve">
+    <value>Failed to read some part of the backup setting data because they are incompatible. To read all the backup setting data, please use Simple Backup Ver.{0} or later.</value>
+  </data>
+  <data name="BackupSetting_SettingOpenedFormat" xml:space="preserve">
+    <value>The backup setting is opened: {0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_EmptyFileNameFormat" xml:space="preserve">
+    <value>Failed to open the backup setting. The file name is empty: {0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_InvalidMajorVersionFormat" xml:space="preserve">
+    <value>Failed to open the backup setting. Invalid major version value: {0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_InvalidMinorVersionFormat" xml:space="preserve">
+    <value>Failed to open the backup setting. Invalid minor version value: {0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_InvalidRequiredToolVersionFormat" xml:space="preserve">
+    <value>Failed to open the backup setting. Invalid "RequiredToolVersion" value: {0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_InvalidVersionFormat" xml:space="preserve">
+    <value>Failed to open the backup setting. Invalid "Version" value: {0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_NoBackupSettingElementFormat" xml:space="preserve">
+    <value>Failed to open the backup setting. There is no "BackupSetting" tag: {0}</value>
+  </data>
+  <data name="BackupSetting_FailedToOpenSetting_NoVersionElementFormat" xml:space="preserve">
+    <value>Failed to open the backup setting. There is no "Version" tag: {0}</value>
+  </data>
+  <data name="FileAccess_FailedToOpenFormat" xml:space="preserve">
+    <value>Failed to open the file: {0}</value>
+  </data>
+  <data name="FileAccess_FolderPathNotExistFormat" xml:space="preserve">
+    <value>The folder path does not exist: {0}</value>
+  </data>
+  <data name="FileAccess_InvalidPathFormat" xml:space="preserve">
+    <value>The path is not valid: {0}</value>
+  </data>
+  <data name="Views_ConfirmationDialogTitle" xml:space="preserve">
+    <value>Confirmation</value>
+  </data>
+  <data name="Views_SaveConfirmationMessage" xml:space="preserve">
+    <value>Save the changes?</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Main/SimpleBackup.Resources/SimpleBackup.Resources.csproj b/Main/SimpleBackup.Resources/SimpleBackup.Resources.csproj
new file mode 100644 (file)
index 0000000..5bdec14
--- /dev/null
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{A655131E-D439-4DE1-BC39-5C955306183F}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SimpleBackup.Resources</RootNamespace>
+    <AssemblyName>SimpleBackup.Resources</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>SimpleBackupKey.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="PresentationCore" />
+    <Reference Include="PresentationFramework" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xaml" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+    <Reference Include="WindowsBase" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Properties\AssemblyInfo.cs">
+      <Link>Properties\AssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="Resources.Designer.cs">
+      <DependentUpon>Resources.resx</DependentUpon>
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+    </Compile>
+    <Compile Include="ResourceHelper.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="SimpleBackupKey.snk" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\action_Cancel_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Activity_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\AddVariable_5541.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\ApplicationIcon.ico" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\arrow_all_run_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\arrow_Down_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Arrow_RedoRetry_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\arrow_run_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Arrow_UndoRevertRestore_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\arrow_Up_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Copy_6524.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Cut_6523.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Delete_black_32x32.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\document_32xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\FileGroup_10135_32x.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\flag_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\NewFile_6276.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Open_6529.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Paste_6520.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Print_11009.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\refresh_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\save_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\StatusAnnotations_Complete_and_ok_32xLG_color.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\StatusAnnotations_Critical_32xLG_color.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Symbols_Complete_and_ok_32xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Synchronize_16xLG.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Resource Include="Images\Warning.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Resources.ja.resx" />
+    <EmbeddedResource Include="Resources.resx">
+      <Generator>PublicResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Main/SimpleBackup.Resources/SimpleBackupKey.snk b/Main/SimpleBackup.Resources/SimpleBackupKey.snk
new file mode 100644 (file)
index 0000000..def2e6d
Binary files /dev/null and b/Main/SimpleBackup.Resources/SimpleBackupKey.snk differ
diff --git a/Main/SimpleBackup.Services/BackupService.cs b/Main/SimpleBackup.Services/BackupService.cs
new file mode 100644 (file)
index 0000000..a77dc58
--- /dev/null
@@ -0,0 +1,643 @@
+//-----------------------------------------------------------------------
+// <copyright file="BackupService.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Services
+{
+    using System;
+    using System.Collections.Generic;
+    using System.IO;
+    using System.IO.Compression;
+    using System.Linq;
+    using System.Text;
+    using System.Text.RegularExpressions;
+    using System.Threading;
+    using SimpleBackup.Core;
+    using SimpleBackup.Core.Models;
+    using SimpleBackup.Core.Services;
+    using SimpleBackup.Core.Utilities;
+    using SimpleBackup.Resources;
+
+    /// <summary>
+    /// Backup service.
+    /// </summary>
+    internal class BackupService : IBackupService
+    {
+        /// <summary>
+        /// The synchronize root
+        /// </summary>
+        private static readonly object SyncRoot = new object();
+
+        /// <summary>
+        /// The instance of BackupService.
+        /// </summary>
+        private static volatile BackupService instance;
+
+        /// <summary>
+        /// Prevents a default instance of the <see cref="BackupService"/> class from being created.
+        /// </summary>
+        private BackupService()
+        {
+            BackupSettingService.Instance.BackupSettingCreated += this.OnBackupSettingCreated;
+            BackupSettingService.Instance.BackupSettingOpened += this.OnBackupSettingOpened;
+            BackupSettingService.Instance.BackupSettingClosed += this.OnBackupSettingClosed;
+        }
+
+        /// <summary>
+        /// Occurs when file backup progress is updated.
+        /// </summary>
+        public event EventHandler<FileBackupProgressEventArgs> NofityFileBackupProgress;
+
+        /// <summary>
+        /// Gets the instance.
+        /// </summary>
+        public static IBackupService Instance
+        {
+            get
+            {
+                if (instance == null)
+                {
+                    lock (SyncRoot)
+                    {
+                        if (instance == null)
+                        {
+                            instance = new BackupService();
+                        }
+                    }
+                }
+
+                return instance;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this service is ready for backup.
+        /// </summary>
+        public bool IsReadyForBackup { get; private set; }
+
+        /// <summary>
+        /// Gets a value indicating whether this service is executing backup.
+        /// </summary>
+        public bool IsExecutingBackup { get; private set; }
+
+        /// <summary>
+        /// Backups multipul files.
+        /// </summary>
+        /// <param name="cancellationToken">The cancellation token.</param>
+        /// <param name="resultInfos">The array of result information.</param>
+        public void BackupMultipulFiles(CancellationToken cancellationToken, out IResultInfo[] resultInfos)
+        {
+            var modelFactory = ObjectContainer.Resolve<IModelFactory>();
+
+            this.IsExecutingBackup = true;
+            var resultList = new List<IResultInfo>();
+            if (this.IsReadyForBackup == false)
+            {
+                resultList.Add(modelFactory.CreateResultInfo(BackupState.Failed, Resources.Backup_Failed_BackupInfomationNotPrepared));
+                resultInfos = resultList.ToArray();
+                return;
+            }
+
+            try
+            {
+                this.NotifyBackupProgress(0, null);
+                
+                int processedCount = 0;
+
+                foreach (IBackupInfo backupInfo in BackupSettingService.Instance.CurrentSetting.BackupInfos)
+                {
+                    cancellationToken.ThrowIfCancellationRequested();
+                    backupInfo.BackupState = BackupState.InProgress;
+
+                    Thread.Sleep(100);
+
+                    IResultInfo resultInfo = null;
+                    double progressValue = 0;
+
+                    if (backupInfo.IsEnabled == false)
+                    {
+                        string description = string.Format(
+                            "{0}\r\n\t{1}: {2}",
+                            Resources.Backup_Skipped,
+                            Resources.Backup_From,
+                            backupInfo.SourcePath);
+                        resultInfo = modelFactory.CreateResultInfo(BackupState.Skipped, description);
+                        processedCount++;
+                        progressValue = processedCount * 100.0 / BackupSettingService.Instance.CurrentSetting.Count;
+                        this.NotifyBackupProgress(progressValue, resultInfo);
+                        backupInfo.BackupState = BackupState.Skipped;
+                        continue;
+                    }
+
+                    // Check the source.
+                    if (((backupInfo.BackupSourceType == BackupSourceType.File) && (File.Exists(backupInfo.SourcePath) == false)) ||
+                        ((backupInfo.BackupSourceType == BackupSourceType.Folder) && (Directory.Exists(backupInfo.SourcePath) == false)))
+                    {
+                        string description = string.Format(
+                            "{0}\r\n\t{1}: {2}\r\n\t{3}: {4}",
+                            Resources.Backup_Failed_SourceNotExist,
+                            Resources.Backup_From,
+                            backupInfo.SourcePath,
+                            Resources.Backup_To,
+                            backupInfo.DestinationFolderPath);
+                        resultInfo = modelFactory.CreateResultInfo(BackupState.Failed, description);
+                        resultList.Add(resultInfo);
+                        processedCount++;
+                        progressValue = processedCount * 100.0 / BackupSettingService.Instance.CurrentSetting.Count;
+                        this.NotifyBackupProgress(progressValue, resultInfo);
+                        backupInfo.BackupState = BackupState.Failed;
+                        continue;
+                    }
+
+                    // Check the destination.
+                    if ((backupInfo.DestinationFolderPath == "\\") ||
+                        (Directory.Exists(backupInfo.DestinationFolderPath) == false))
+                    {
+                        string description = string.Format(
+                            "{0}\r\n\t{1}: {2}\r\n\t{3}: {4}",
+                            Resources.Backup_Failed_DestinationNotExist,
+                            Resources.Backup_From,
+                            backupInfo.SourcePath,
+                            Resources.Backup_To,
+                            backupInfo.DestinationFolderPath);
+                        resultInfo = modelFactory.CreateResultInfo(BackupState.Failed, description);
+                        resultList.Add(resultInfo);
+                        processedCount++;
+                        progressValue = processedCount * 100.0 / BackupSettingService.Instance.CurrentSetting.Count;
+                        this.NotifyBackupProgress(progressValue, resultInfo);
+                        backupInfo.BackupState = BackupState.Failed;
+                        continue;
+                    }
+
+                    var destinationFileNames = new IDestinationPathInfo[0];
+                    try
+                    {
+                        if (backupInfo.IsZipArchive)
+                        {
+                            if (backupInfo.BackupSourceType == BackupSourceType.File)
+                            {
+                                BackupFileToZip(backupInfo, out destinationFileNames);
+                            }
+                            else if (backupInfo.BackupSourceType == BackupSourceType.Folder)
+                            {
+                                BackupFolerToZip(backupInfo, out destinationFileNames);
+                            }
+                        }
+                        else
+                        {
+                            if (backupInfo.BackupSourceType == BackupSourceType.File)
+                            {
+                                BackupFile(backupInfo, out destinationFileNames);
+                            }
+                            else if (backupInfo.BackupSourceType == BackupSourceType.Folder)
+                            {
+                                BackupFolder(backupInfo, out destinationFileNames);
+                            }
+                        }
+                    }
+                    catch (Exception e)
+                    {
+                        string description = string.Format(
+                            "{0}\r\n\t{1}: {2}\r\n\t{3}: {4}\r\n{5}",
+                            Resources.Backup_Failed_FailedToCopy,
+                            Resources.Backup_From,
+                            backupInfo.SourcePath,
+                            Resources.Backup_To,
+                            destinationFileNames.FirstOrDefault(),
+                            e.Message);
+                        resultInfo = modelFactory.CreateResultInfo(BackupState.Failed, description);
+                        resultList.Add(resultInfo);
+                        processedCount++;
+                        progressValue = processedCount * 100.0 / BackupSettingService.Instance.CurrentSetting.Count;
+                        this.NotifyBackupProgress(progressValue, resultInfo);
+                        backupInfo.BackupState = BackupState.Failed;
+                        continue;
+                    }
+
+                    if (CheckExistence(destinationFileNames))
+                    {
+                        string description = string.Format(
+                            "{0}\r\n\t{1}: {2}\r\n\t{3}: {4}",
+                            Resources.Backup_Succeeded,
+                            Resources.Backup_From,
+                            backupInfo.SourcePath,
+                            Resources.Backup_To,
+                            destinationFileNames.First().Path);
+                        resultInfo = modelFactory.CreateResultInfo(BackupState.Success, description);
+                        resultList.Add(resultInfo);
+                        backupInfo.BackupState = BackupState.Success;
+                        backupInfo.LatestSuccessfulBackupTargetName = destinationFileNames.First().Path;
+                    }
+
+                    processedCount++;
+                    progressValue = processedCount * 100.0 / BackupSettingService.Instance.CurrentSetting.Count;
+                    this.NotifyBackupProgress(progressValue, resultInfo);
+                }
+
+                this.NotifyBackupProgress(100.0, null);
+            }
+            catch (OperationCanceledException)
+            {
+                var resultInfo = modelFactory.CreateResultInfo(BackupState.Cancelled, Resources.BackupState_Cancelled);
+                resultList.Add(resultInfo);
+                this.NotifyBackupProgress(100.0, resultInfo);
+            }
+            finally
+            {
+                resultInfos = resultList.ToArray();
+                this.IsExecutingBackup = false;
+            }
+        }
+
+        /// <summary>
+        /// Backups single file.
+        /// </summary>
+        /// <param name="backupInfoId">The backup information identifier.</param>
+        /// <returns>The result information.</returns>
+        public IResultInfo BackupSingleFile(Guid backupInfoId)
+        {
+            var modelFactory = ObjectContainer.Resolve<IModelFactory>();
+
+            IBackupInfo backupInfo = BackupSettingService.Instance.CurrentSetting.FirstOrDefault(backupInfoId);
+            if (backupInfo == null)
+            {
+                return modelFactory.CreateResultInfo(
+                    BackupState.Failed,
+                    Resources.Backup_Failed_BackupInfomationNotPrepared);
+            }
+
+            backupInfo.BackupState = BackupState.InProgress;
+            Helpers.UpdateWpfGui();
+            
+            IResultInfo resultInfo = null;
+            string description = string.Empty;
+
+            // Check the source.
+            if (((backupInfo.BackupSourceType == BackupSourceType.File) && (File.Exists(backupInfo.SourcePath) == false)) ||
+                ((backupInfo.BackupSourceType == BackupSourceType.Folder) && (Directory.Exists(backupInfo.SourcePath) == false)))
+            {
+                description = string.Format(
+                    "{0}\r\n\t{1}: {2}\r\n\t{3}: {4}",
+                    Resources.Backup_Failed_SourceNotExist,
+                    Resources.Backup_From,
+                    backupInfo.SourcePath,
+                    Resources.Backup_To,
+                    backupInfo.DestinationFolderPath);
+                resultInfo = modelFactory.CreateResultInfo(BackupState.Failed, description);
+                backupInfo.BackupState = BackupState.Failed;
+                return resultInfo;
+            }
+
+            // Check the destination.
+            if (Directory.Exists(backupInfo.DestinationFolderPath) == false)
+            {
+                description = string.Format(
+                    "{0}\r\n\t{1}: {2}\r\n\t{3}: {4}",
+                    Resources.Backup_Failed_DestinationNotExist,
+                    Resources.Backup_From,
+                    backupInfo.SourcePath,
+                    Resources.Backup_To,
+                    backupInfo.DestinationFolderPath);
+                resultInfo = modelFactory.CreateResultInfo(BackupState.Failed, description);
+                backupInfo.BackupState = BackupState.Failed;
+                return resultInfo;
+            }
+
+            var destinationFileNames = new IDestinationPathInfo[0];
+            try
+            {
+                if (backupInfo.IsZipArchive)
+                {
+                    if (backupInfo.BackupSourceType == BackupSourceType.File)
+                    {
+                        BackupFileToZip(backupInfo, out destinationFileNames);
+                    }
+                    else if (backupInfo.BackupSourceType == BackupSourceType.Folder)
+                    {
+                        BackupFolerToZip(backupInfo, out destinationFileNames);
+                    }
+                }
+                else
+                {
+                    if (backupInfo.BackupSourceType == BackupSourceType.File)
+                    {
+                        BackupFile(backupInfo, out destinationFileNames);
+                    }
+                    else if (backupInfo.BackupSourceType == BackupSourceType.Folder)
+                    {
+                        BackupFolder(backupInfo, out destinationFileNames);
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+                description = string.Format(
+                    "{0}\r\n\t{1}: {2}\r\n\t{3}: {4}\r\n{5}",
+                    Resources.Backup_Failed_FailedToCopy,
+                    Resources.Backup_From,
+                    backupInfo.SourcePath,
+                    Resources.Backup_To,
+                    destinationFileNames.FirstOrDefault(),
+                    e.Message);
+                resultInfo = modelFactory.CreateResultInfo(BackupState.Failed, description);
+                backupInfo.BackupState = BackupState.Failed;
+                return resultInfo;
+            }
+
+            if (CheckExistence(destinationFileNames))
+            {
+                description = string.Format(
+                    "{0}\r\n\t{1}: {2}\r\n\t{3}: {4}",
+                    Resources.Backup_Succeeded,
+                    Resources.Backup_From,
+                    backupInfo.SourcePath,
+                    Resources.Backup_To,
+                    destinationFileNames.First().Path);
+                resultInfo = modelFactory.CreateResultInfo(BackupState.Success, description);
+                backupInfo.BackupState = BackupState.Success;
+                backupInfo.LatestSuccessfulBackupTargetName = destinationFileNames.First().Path;
+                return resultInfo;
+            }
+
+            description = string.Format(
+                "{0}\r\n\t{1}: {2}\r\n\t{3}: {4}",
+                Resources.Backup_Failed_FailedToCopy,
+                Resources.Backup_From,
+                backupInfo.SourcePath,
+                Resources.Backup_To,
+                destinationFileNames.FirstOrDefault());
+            return modelFactory.CreateResultInfo(BackupState.Failed, description);
+        }
+
+        private static void BackupFileToZip(IBackupInfo backupInfo, out IDestinationPathInfo[] destinationPathInfoArray)
+        {
+            var innerDestinationPathInfoList = new List<IDestinationPathInfo>();
+
+            var modelFactory = ObjectContainer.Resolve<IModelFactory>();
+
+            Match lastPathSegmentMatch = Constants.EndPathSegmentRegex.Match(backupInfo.SourcePath);
+            Match fileNameMatch = Constants.FileNameRegex.Match(lastPathSegmentMatch.Value);
+            Match extensionMatch = Constants.ExtensionRegex.Match(lastPathSegmentMatch.Value);
+
+            string destinationFolderPath = backupInfo.DestinationFolderPath.AddTailPathSeparatorIfNotExist();
+            string destinationTempFolderPath = destinationFolderPath + fileNameMatch.Value +
+                " - " + DateTime.Now.ToString("yyyyMMdd-HHmmss") + "-tmp";
+            string destinationTempFileName = destinationTempFolderPath + "\\" + fileNameMatch.Value +
+                " - " + DateTime.Now.ToString("yyyyMMdd-HHmmss") + "." + extensionMatch.Value;
+            try
+            {
+                try
+                {
+                    Directory.CreateDirectory(destinationTempFolderPath);
+                }
+                catch (Exception e)
+                {
+                    throw new InvalidOperationException(
+                        string.Format(
+                            "Failed to create the folder: {0}\r\n{1}",
+                            destinationTempFolderPath,
+                            e.Message),
+                        e);
+                }
+
+                try
+                {
+                    File.Copy(backupInfo.SourcePath, destinationTempFileName);
+                }
+                catch (Exception e)
+                {
+                    throw new InvalidOperationException(
+                        string.Format(
+                            "Failed to copy the file.\r\n\tFrom: {0}\r\n\tTo: {1}\r\n{2}",
+                            backupInfo.SourcePath,
+                            destinationTempFolderPath,
+                            e.Message),
+                        e);
+                }
+
+                var destinationFileName = destinationFolderPath + fileNameMatch.Value
+                    + " - " + DateTime.Now.ToString("yyyyMMdd-HHmmss") + ".zip";
+                innerDestinationPathInfoList.Add(modelFactory.CreateDestinationPathInfo(BackupSourceType.File, destinationFileName));
+
+                try
+                {
+                    ZipFile.CreateFromDirectory(
+                        destinationTempFolderPath,
+                        destinationFileName,
+                        CompressionLevel.Optimal,
+                        false,
+                        Encoding.GetEncoding(Properties.Settings.Default.DefaultZipEncodingKeyText));
+                }
+                catch (Exception e)
+                {
+                    backupInfo.BackupState = BackupState.Failed;
+                    throw new InvalidOperationException(
+                        string.Format(
+                            "Failed to create the zip archive.\r\n\tFrom: {0}\r\n\tTo: {1}\r\n{2}",
+                            destinationTempFolderPath,
+                            destinationFileName,
+                            e.Message),
+                        e);
+                }
+            }
+            finally
+            {
+                destinationPathInfoArray = innerDestinationPathInfoList.ToArray();
+
+                if (File.Exists(destinationTempFileName))
+                {
+                    File.Delete(destinationTempFileName);
+                }
+
+                if (Directory.Exists(destinationTempFolderPath))
+                {
+                    Directory.Delete(destinationTempFolderPath);
+                }
+            }
+        }
+
+        private static void BackupFolerToZip(IBackupInfo backupInfo, out IDestinationPathInfo[] destinationPathInfoArray)
+        {
+            var innerDestinationPathInfoList = new List<IDestinationPathInfo>();
+
+            var modelFactory = ObjectContainer.Resolve<IModelFactory>();
+
+            Match lastPathSegmentMatch = Constants.EndPathSegmentRegex.Match(backupInfo.SourcePath);
+
+            string destinationFolderPath = backupInfo.DestinationFolderPath.AddTailPathSeparatorIfNotExist();
+            var destinationFileName = destinationFolderPath
+                + lastPathSegmentMatch.Value + " - "
+                + DateTime.Now.ToString("yyyyMMdd-HHmmss")
+                + ".zip";
+            innerDestinationPathInfoList.Add(modelFactory.CreateDestinationPathInfo(BackupSourceType.File, destinationFileName));
+
+            try
+            {
+                ZipFile.CreateFromDirectory(
+                    backupInfo.SourcePath,
+                    destinationFileName,
+                    CompressionLevel.Optimal,
+                    false,
+                    Encoding.GetEncoding(Properties.Settings.Default.DefaultZipEncodingKeyText));
+            }
+            catch (Exception e)
+            {
+                backupInfo.BackupState = BackupState.Failed;
+                throw new InvalidOperationException(
+                    string.Format(
+                        "Failed to create the zip archive.\r\n\tFrom: {0}\r\n\tTo: {1}\r\n{2}",
+                        backupInfo.SourcePath,
+                        destinationFileName,
+                        e.Message),
+                    e);
+            }
+            finally
+            {
+                destinationPathInfoArray = innerDestinationPathInfoList.ToArray();
+            }
+        }
+
+        private static void BackupFile(IBackupInfo backupInfo, out IDestinationPathInfo[] destinationPathInfoArray)
+        {
+            var innerDestinationPathInfoList = new List<IDestinationPathInfo>();
+
+            var modelFactory = ObjectContainer.Resolve<IModelFactory>();
+
+            Match lastPathSegmentMatch = Constants.EndPathSegmentRegex.Match(backupInfo.SourcePath);
+            Match fileNameMatch = Constants.FileNameRegex.Match(lastPathSegmentMatch.Value);
+            Match extensionMatch = Constants.ExtensionRegex.Match(lastPathSegmentMatch.Value);
+
+            string destinationFolderPath = backupInfo.DestinationFolderPath.AddTailPathSeparatorIfNotExist();
+            var destinationFileName = destinationFolderPath + fileNameMatch.Value
+                + " - " + DateTime.Now.ToString("yyyyMMdd-HHmmss") + "." + extensionMatch.Value;
+            innerDestinationPathInfoList.Add(modelFactory.CreateDestinationPathInfo(BackupSourceType.File, destinationFileName));
+
+            try
+            {
+                File.Copy(backupInfo.SourcePath, destinationFileName);
+            }
+            finally
+            {
+                destinationPathInfoArray = innerDestinationPathInfoList.ToArray();
+            }
+        }
+
+        private static void BackupFolder(IBackupInfo backupInfo, out IDestinationPathInfo[] destinationPathInfoArray)
+        {
+            var innerDestinationPathInfoList = new List<IDestinationPathInfo>();
+
+            var modelFactory = ObjectContainer.Resolve<IModelFactory>();
+
+            Match lastPathSegmentMatch = Constants.EndPathSegmentRegex.Match(backupInfo.SourcePath);
+
+            //// 方法 : ディレクトリをコピーする
+            //// http://msdn.microsoft.com/ja-jp/library/bb762914(v=vs.110).aspx
+            string destinationFolderPath = backupInfo.DestinationFolderPath.AddTailPathSeparatorIfNotExist();
+            var destinationFolderName = destinationFolderPath
+                + lastPathSegmentMatch.Value + " - " + DateTime.Now.ToString("yyyyMMdd-HHmmss");
+            innerDestinationPathInfoList.Add(modelFactory.CreateDestinationPathInfo(BackupSourceType.Folder, destinationFolderName));
+
+            try
+            {
+                FolderCopy(backupInfo.SourcePath, destinationFolderName, true);
+            }
+            finally
+            {
+                destinationPathInfoArray = innerDestinationPathInfoList.ToArray();
+            }
+        }
+
+        private static void FolderCopy(string sourceFolderPath, string destinationFolderPath, bool copySubFolders)
+        {
+            var sourceDirectoryInfo = new DirectoryInfo(sourceFolderPath);
+            DirectoryInfo[] subDirectoryInfos = sourceDirectoryInfo.GetDirectories();
+
+            if (sourceDirectoryInfo.Exists == false)
+            {
+                throw new DirectoryNotFoundException(
+                    "Source directory does not exist or could not be found: "
+                    + sourceFolderPath);
+            }
+
+            // If the destination directory doesn't exist, create it.
+            if (Directory.Exists(destinationFolderPath) == false)
+            {
+                Directory.CreateDirectory(destinationFolderPath);
+            }
+
+            // Get the files in the directory and copy them to the new location.
+            FileInfo[] files = sourceDirectoryInfo.GetFiles();
+            foreach (FileInfo file in files)
+            {
+                string temppath = Path.Combine(destinationFolderPath, file.Name);
+                file.CopyTo(temppath, false);
+            }
+
+            // If copying subdirectories, copy them and their contents to new location.
+            if (copySubFolders)
+            {
+                foreach (DirectoryInfo subDirectoryInfo in subDirectoryInfos)
+                {
+                    string temppath = Path.Combine(destinationFolderPath, subDirectoryInfo.Name);
+                    FolderCopy(subDirectoryInfo.FullName, temppath, copySubFolders);
+                }
+            }
+        }
+
+        private static bool CheckExistence(IDestinationPathInfo[] destinationPathInfoArray)
+        {
+            return (destinationPathInfoArray != null) &&
+                (destinationPathInfoArray.Length != 0) &&
+                destinationPathInfoArray.All(
+                    destinationPathInfo =>
+                        {
+                            if (destinationPathInfo.BackupSourceType == BackupSourceType.File)
+                            {
+                                return File.Exists(destinationPathInfo.Path);
+                            }
+
+                            return Directory.Exists(destinationPathInfo.Path);
+                        });
+        }
+
+        private void OnBackupSettingCreated(object sender, SettingFileEventArgs settingFileEventArgs)
+        {
+            this.IsReadyForBackup = true;
+        }
+
+        private void OnBackupSettingOpened(object sender, SettingFileEventArgs settingFileEventArgs)
+        {
+            this.IsReadyForBackup = true;
+        }
+
+        private void OnBackupSettingClosed(object sender, SettingFileEventArgs settingFileEventArgs)
+        {
+            this.IsReadyForBackup = false;
+        }
+
+        private void NotifyBackupProgress(double progressValue, IResultInfo latestResultInfo)
+        {
+            if (this.NofityFileBackupProgress != null)
+            {
+                this.NofityFileBackupProgress(this, new FileBackupProgressEventArgs(progressValue, latestResultInfo));
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Services/BackupSettingService.cs b/Main/SimpleBackup.Services/BackupSettingService.cs
new file mode 100644 (file)
index 0000000..2827371
--- /dev/null
@@ -0,0 +1,591 @@
+//-----------------------------------------------------------------------
+// <copyright file="BackupSettingService.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Services
+{
+    using System;
+    using System.IO;
+    using System.Linq;
+    using System.Windows;
+    using System.Windows.Input;
+    using System.Xml.Linq;
+    using SimpleBackup.Core;
+    using SimpleBackup.Core.Models;
+    using SimpleBackup.Core.Services;
+    using SimpleBackup.Core.Utilities;
+    using SimpleBackup.Resources;
+    using Application = System.Windows.Application;
+    using Cursors = System.Windows.Input.Cursors;
+    using MessageBox = System.Windows.MessageBox;
+    using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
+    using SaveFileDialog = Microsoft.Win32.SaveFileDialog;
+
+    /// <summary>
+    /// Backup Setting service.
+    /// </summary>
+    internal class BackupSettingService : IBackupSettingService
+    {
+        /// <summary>
+        /// The supported major version
+        /// </summary>
+        private const int SupportedMajorVersion = 1;
+
+        /// <summary>
+        /// The supported minor version
+        /// </summary>
+        private const int SupportedMinorVersion = 0;
+
+        /// <summary>
+        /// The synchronize root
+        /// </summary>
+        private static readonly object SyncRoot = new object();
+
+        /// <summary>
+        /// The instance of SettingFileService.
+        /// </summary>
+        private static volatile BackupSettingService instance;
+
+        /// <summary>
+        /// Prevents a default instance of the <see cref="BackupSettingService"/> class from being created.
+        /// </summary>
+        private BackupSettingService()
+        {
+        }
+
+        /// <summary>
+        /// Occurs when backup setting is created.
+        /// </summary>
+        public event EventHandler<SettingFileEventArgs> BackupSettingCreated;
+
+        /// <summary>
+        /// Occurs when backup setting is opened.
+        /// </summary>
+        public event EventHandler<SettingFileEventArgs> BackupSettingOpened;
+
+        /// <summary>
+        /// Occurs when backup setting is modified.
+        /// </summary>
+        public event EventHandler<SettingFileEventArgs> BackupSettingModified;
+
+        /// <summary>
+        /// Occurs when backup setting is saved.
+        /// </summary>
+        public event EventHandler<SettingFileEventArgs> BackupSettingSaved;
+
+        /// <summary>
+        /// Occurs when backup setting is closed.
+        /// </summary>
+        public event EventHandler<SettingFileEventArgs> BackupSettingClosed;
+
+        /// <summary>
+        /// Gets the instance.
+        /// </summary>
+        public static IBackupSettingService Instance
+        {
+            get
+            {
+                if (instance == null)
+                {
+                    lock (SyncRoot)
+                    {
+                        if (instance == null)
+                        {
+                            instance = new BackupSettingService();
+                        }
+                    }
+                }
+
+                return instance;
+            }
+        }
+
+        /// <summary>
+        /// Gets the current setting.
+        /// </summary>
+        public IBackupSetting CurrentSetting { get; private set; }
+
+        /// <summary>
+        /// Creates the backup setting.
+        /// </summary>
+        /// <returns><c>true</c> if the new backup setting is created; otherwise, <c>false</c>.</returns>
+        public bool CreateBackupSetting()
+        {
+            if ((this.CurrentSetting != null) && this.CurrentSetting.Modified)
+            {
+                MessageBoxResult confirmationResult = MessageBox.Show(
+                    Application.Current.MainWindow,
+                    Resources.Views_SaveConfirmationMessage,
+                    Resources.Views_ConfirmationDialogTitle,
+                    MessageBoxButton.YesNoCancel);
+                if (confirmationResult == MessageBoxResult.Yes)
+                {
+                    this.SaveCurrentBackupSetting();
+                }
+                else if (confirmationResult == MessageBoxResult.Cancel)
+                {
+                    return false;
+                }
+            }
+
+            if (this.CurrentSetting != null)
+            {
+                this.CloseCurrentBackupSetting();
+            }
+
+            var modelFactory = ObjectContainer.Resolve<IModelFactory>();
+
+            IBackupSetting backupSetting = modelFactory.CreateBackupSetting();
+            this.CurrentSetting = backupSetting;
+            this.CurrentSetting.SettingModified += this.OnCurrentSettingModified;
+
+            if (this.BackupSettingCreated != null)
+            {
+                this.BackupSettingCreated(this, new SettingFileEventArgs(this.CurrentSetting.SettingName));
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// Opens the backup setting.
+        /// </summary>
+        /// <param name="resultMessage">The result message.</param>
+        /// <returns>
+        ///   <c>true</c> if backup setting is successfully loaded; otherwise, <c>false</c>.
+        /// </returns>
+        public bool OpenBackupSetting(out string resultMessage)
+        {
+            if ((this.CurrentSetting != null) && this.CurrentSetting.Modified)
+            {
+                MessageBoxResult confirmationResult = MessageBox.Show(
+                    Application.Current.MainWindow,
+                    Resources.Views_SaveConfirmationMessage,
+                    Resources.Views_ConfirmationDialogTitle,
+                    MessageBoxButton.YesNoCancel);
+                if (confirmationResult == MessageBoxResult.Yes)
+                {
+                    this.SaveCurrentBackupSetting();
+                }
+                else if (confirmationResult == MessageBoxResult.Cancel)
+                {
+                    resultMessage = string.Empty;
+                    return false;
+                }
+            }
+
+            string initialDirectory = AppDomain.CurrentDomain.BaseDirectory;
+            if ((this.CurrentSetting != null) &&
+                this.CurrentSetting.SettingFileName.IsValidFilePath())
+            {
+                initialDirectory = Path.GetDirectoryName(this.CurrentSetting.SettingFileName);
+                this.CloseBackupSetting();
+            }
+
+            var openFileDialog = new OpenFileDialog
+            {
+                Title = Resources.Views_OpenFileDialogTitle,
+                DefaultExt = ".xml",
+                Filter = "Backup Setting File|*.xml",
+                InitialDirectory = initialDirectory,
+                Multiselect = false
+            };
+
+            if (openFileDialog.ShowDialog(Application.Current.MainWindow) != true)
+            {
+                resultMessage = string.Empty;
+                return false;
+            }
+
+            var fileName = openFileDialog.FileName;
+            try
+            {
+                Mouse.OverrideCursor = Cursors.Wait;
+                return this.OpenBackupSetting(fileName, out resultMessage);
+            }
+            finally
+            {
+                Mouse.OverrideCursor = null;
+            }
+        }
+
+        /// <summary>
+        /// Closes the backup setting.
+        /// </summary>
+        public void CloseBackupSetting()
+        {
+            if (this.CurrentSetting == null)
+            {
+                return;
+            }
+
+            if (this.CurrentSetting.Modified)
+            {
+                MessageBoxResult confirmationResult = MessageBox.Show(
+                    Application.Current.MainWindow,
+                    Resources.Views_SaveConfirmationMessage,
+                    Resources.Views_ConfirmationDialogTitle,
+                    MessageBoxButton.YesNoCancel);
+                if (confirmationResult == MessageBoxResult.Yes)
+                {
+                    this.SaveCurrentBackupSetting();
+                }
+                else if (confirmationResult == MessageBoxResult.Cancel)
+                {
+                    return;
+                }
+            }
+
+            this.CloseCurrentBackupSetting();
+        }
+
+        /// <summary>
+        /// Overwrites the currnt backup setting.
+        /// </summary>
+        /// <returns><c>true</c> if the backup setting is saved; otherwise, <c>false</c>.</returns>
+        public bool OverWriteCurrntBackupSetting()
+        {
+            if (this.CurrentSetting == null)
+            {
+                return false;
+            }
+
+            if (string.IsNullOrEmpty(this.CurrentSetting.SettingFileName) ||
+                (File.Exists(this.CurrentSetting.SettingFileName) == false))
+            {
+                var saveFileDialog = new SaveFileDialog
+                {
+                    Title = Resources.Views_SaveFileDialogTitle,
+                    DefaultExt = ".xml",
+                    Filter = "Backup Setting File|*.xml"
+                };
+
+                if (saveFileDialog.ShowDialog(Application.Current.MainWindow) != true)
+                {
+                    return false;
+                }
+
+                this.CurrentSetting.SettingFileName = saveFileDialog.FileName;
+            }
+
+            this.SaveCurrentBackupSetting();
+            return true;
+        }
+
+        /// <summary>
+        /// Saves the current backup setting as a new file.
+        /// </summary>
+        /// <returns><c>true</c> if the backup setting is saved; otherwise, <c>false</c>.</returns>
+        public bool SaveCurrentBackupSettingAsNewFile()
+        {
+            if (this.CurrentSetting == null)
+            {
+                return false;
+            }
+
+            var saveFileDialog = new SaveFileDialog
+            {
+                Title = Resources.Views_SaveFileDialogTitle,
+                DefaultExt = ".xml",
+                Filter = "Backup Setting File|*.xml"
+            };
+
+            if (saveFileDialog.ShowDialog(Application.Current.MainWindow) != true)
+            {
+                return false;
+            }
+
+            this.CurrentSetting.SettingFileName = saveFileDialog.FileName;
+
+            this.SaveCurrentBackupSetting();
+            return true;
+        }
+
+        /// <summary>
+        /// Opens the default backup setting.
+        /// </summary>
+        /// <param name="resultMessage">The result message.</param>
+        /// <returns>
+        ///   <c>true</c> if succeeded, otherwise; <c>false</c>.
+        /// </returns>
+        public bool OpenDefaultBackupSetting(out string resultMessage)
+        {
+            return this.OpenBackupSetting(
+                Properties.Settings.Default.DefaultSettingFileName,
+                out resultMessage);
+        }
+
+        /// <summary>
+        /// Creates the backup information.
+        /// </summary>
+        /// <param name="index">The index.</param>
+        /// <returns>The created backup information.</returns>
+        /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="index"/></exception>
+        public IBackupInfo CreateBackupInfo(int index)
+        {
+            if (index < 0)
+            {
+                throw new ArgumentOutOfRangeException("index");
+            }
+
+            var modelFactory = ObjectContainer.Resolve<IModelFactory>();
+
+            IBackupInfo backupInfo = modelFactory.CreateBackupInfo();
+            this.CurrentSetting.Insert(index, backupInfo);
+            return backupInfo;
+        }
+
+        /// <summary>
+        /// Copies the backup information.
+        /// </summary>
+        /// <param name="sourceBackupInfo">The source backup information.</param>
+        /// <returns>A copied BackupInfo.</returns>
+        /// <exception cref="System.ArgumentNullException"><paramref name="sourceBackupInfo"/></exception>
+        public IBackupInfo CopyBackupInfo(IBackupInfo sourceBackupInfo)
+        {
+            sourceBackupInfo.ThrowsArgumentNullException("sourceBackupInfo");
+
+            var modelFactory = ObjectContainer.Resolve<IModelFactory>();
+            return modelFactory.CreateBackupInfo(sourceBackupInfo);
+        }
+
+        /// <summary>
+        /// Inserts the backup information.
+        /// </summary>
+        /// <param name="index">The index.</param>
+        /// <param name="backupInfo">The backup information.</param>
+        /// <exception cref="System.ArgumentOutOfRangeException"><paramref name="index"/></exception>
+        /// <exception cref="System.ArgumentNullException"><paramref name="backupInfo"/></exception>
+        public void InsertBackupInfo(int index, IBackupInfo backupInfo)
+        {
+            if (index > this.CurrentSetting.Count)
+            {
+                throw new ArgumentOutOfRangeException("index");
+            }
+
+            backupInfo.ThrowsArgumentNullException("backupInfo");
+
+            this.CurrentSetting.Insert(index, backupInfo);
+        }
+
+        /// <summary>
+        /// Removes the backup information.
+        /// </summary>
+        /// <param name="backupInfoId">The backup information identifier.</param>
+        public void RemoveBackupInfo(Guid backupInfoId)
+        {
+            IBackupInfo removingBackupInfo =
+                this.CurrentSetting.FirstOrDefault(backupInfoId);
+            if (removingBackupInfo == null)
+            {
+                return;
+            }
+
+            this.CurrentSetting.Remove(removingBackupInfo);
+        }
+
+        /// <summary>
+        /// Saves the backup setting.
+        /// </summary>
+        /// <param name="backupSetting">The backup setting.</param>
+        private static void SaveBackupSetting(IBackupSetting backupSetting)
+        {
+            var xdoc = new XDocument { Declaration = new XDeclaration("1.0", "utf-8", "yes") };
+            xdoc.Add(backupSetting.ToXml());
+
+            xdoc.Save(backupSetting.SettingFileName, SaveOptions.None);
+        }
+
+        /// <summary>
+        /// Opens the backup setting.
+        /// </summary>
+        /// <param name="fileName">Name of the file.</param>
+        /// <param name="resultMessage">The result message.</param>
+        /// <returns>
+        ///   <c>true</c> if succeeded; otherwise, <c>false</c>.
+        /// </returns>
+        private bool OpenBackupSetting(string fileName, out string resultMessage)
+        {
+            resultMessage = string.Empty;
+
+            if (string.IsNullOrEmpty(fileName))
+            {
+                resultMessage = string.Format(
+                    Resources.BackupSetting_FailedToOpenSetting_EmptyFileNameFormat,
+                    fileName);
+                return false;
+            }
+
+            XDocument xml = XDocument.Load(fileName, LoadOptions.None);
+            XElement backupSettingElement = xml.Elements("BackupSetting").FirstOrDefault();
+            if (backupSettingElement == null)
+            {
+                resultMessage = string.Format(
+                    Resources.BackupSetting_FailedToOpenSetting_NoBackupSettingElementFormat,
+                    fileName);
+                return false;
+            }
+
+            XAttribute versionAttribute = backupSettingElement.Attributes().FirstOrDefault(p => p.Name == "Version");
+            if (versionAttribute == null)
+            {
+                resultMessage = string.Format(
+                    Resources.BackupSetting_FailedToOpenSetting_NoVersionElementFormat,
+                    fileName);
+                return false;
+            }
+
+            string[] versionTextFlagments = versionAttribute.Value.Split('.');
+            if (versionTextFlagments.Length != 2)
+            {
+                resultMessage = string.Format(
+                    Resources.BackupSetting_FailedToOpenSetting_InvalidVersionFormat,
+                    fileName);
+                return false;
+            }
+
+            int majorVersion;
+            if (int.TryParse(versionTextFlagments[0], out majorVersion) == false)
+            {
+                resultMessage = string.Format(
+                    Resources.BackupSetting_FailedToOpenSetting_InvalidMajorVersionFormat,
+                    fileName);
+                return false;
+            }
+
+            int minorVersion;
+            if (int.TryParse(versionTextFlagments[1], out minorVersion) == false)
+            {
+                resultMessage = string.Format(
+                    Resources.BackupSetting_FailedToOpenSetting_InvalidMinorVersionFormat,
+                    fileName);
+                return false;
+            }
+
+            XAttribute requiredToolVersionAttribute = backupSettingElement.Attributes().FirstOrDefault(p => p.Name == "RequiredToolVersion");
+            if (requiredToolVersionAttribute == null)
+            {
+                resultMessage = string.Format(
+                    Resources.BackupSetting_FailedToOpenSetting_InvalidRequiredToolVersionFormat,
+                    fileName);
+                return false;
+            }
+
+            if (majorVersion > SupportedMajorVersion)
+            {
+                string message = string.Format(
+                    Resources.BackupSetting_IncompatibleMajorVersionFormat,
+                    requiredToolVersionAttribute.Value);
+                MessageBox.Show(
+                    Application.Current.MainWindow,
+                    message,
+                    Resources.Views_DefaultWindowTitle,
+                    MessageBoxButton.OK,
+                    MessageBoxImage.Error);
+                resultMessage = message;
+                return false;
+            }
+
+            if (minorVersion > SupportedMinorVersion)
+            {
+                string message = string.Format(
+                    Resources.BackupSetting_IncompatibleMinorVersionFormat,
+                    requiredToolVersionAttribute.Value);
+                MessageBox.Show(
+                    Application.Current.MainWindow,
+                    message,
+                    Resources.Views_DefaultWindowTitle,
+                    MessageBoxButton.OK,
+                    MessageBoxImage.Warning);
+                resultMessage = message + "\r\n";
+            }
+
+            var modelFactory = ObjectContainer.Resolve<IModelFactory>();
+            if (modelFactory != null)
+            {
+                IBackupSetting backupSetting = modelFactory.RestoreBackupSettingFromXml(backupSettingElement, fileName);
+                this.CurrentSetting = backupSetting;
+                this.CurrentSetting.SettingModified += this.OnCurrentSettingModified;
+                if (this.BackupSettingOpened != null)
+                {
+                    this.BackupSettingOpened(this, new SettingFileEventArgs(backupSetting.SettingFileName));
+                }
+
+                resultMessage += string.Format(Resources.BackupSetting_SettingOpenedFormat, fileName);
+                return true;
+            }
+
+            resultMessage = string.Format(
+                    Resources.BackupSetting_FailedToOpenSetting_EmptyFileNameFormat,
+                    fileName);
+            return false;
+        }
+
+        /// <summary>
+        /// Saves the current backup setting.
+        /// </summary>
+        private void SaveCurrentBackupSetting()
+        {
+            try
+            {
+                Mouse.OverrideCursor = Cursors.Wait;
+
+                SaveBackupSetting(this.CurrentSetting);
+
+                this.CurrentSetting.Modified = false;
+            }
+            finally
+            {
+                Mouse.OverrideCursor = null;
+            }
+
+            if (this.BackupSettingSaved != null)
+            {
+                this.BackupSettingSaved(this, new SettingFileEventArgs(this.CurrentSetting.SettingFileName));
+            }
+        }
+
+        private void CloseCurrentBackupSetting()
+        {
+            UndoRedoService.Instance.ClearUndoRedoBuffer();
+            string settingName = this.CurrentSetting.SettingFileName;
+            this.CurrentSetting.SettingModified -= this.OnCurrentSettingModified;
+            this.CurrentSetting = null;
+
+            if (this.BackupSettingClosed != null)
+            {
+                this.BackupSettingClosed(this, new SettingFileEventArgs(settingName));
+            }
+        }
+
+        /// <summary>
+        /// Called when current setting is modified.
+        /// </summary>
+        /// <param name="sender">The sender.</param>
+        /// <param name="eventArgs">The <see cref="EventArgs"/> instance containing the event data.</param>
+        private void OnCurrentSettingModified(object sender, EventArgs eventArgs)
+        {
+            if (this.BackupSettingModified != null)
+            {
+                this.BackupSettingModified(this, new SettingFileEventArgs(this.CurrentSetting.SettingName));
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Services/ClipboardService.cs b/Main/SimpleBackup.Services/ClipboardService.cs
new file mode 100644 (file)
index 0000000..2efd783
--- /dev/null
@@ -0,0 +1,139 @@
+//-----------------------------------------------------------------------
+// <copyright file="ClipboardService.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Services
+{
+    using System;
+    using System.Linq;
+    using System.Windows;
+    using SimpleBackup.Core.Services;
+    using SimpleBackup.Core.Utilities;
+
+    /// <summary>
+    /// Provides clip board access.
+    /// </summary>
+    internal class ClipboardService : IClipboardService
+    {
+        private static readonly object SyncRoot = new object();
+        private static volatile ClipboardService instance;
+
+        /// <summary>
+        /// Prevents a default instance of the <see cref="ClipboardService"/> class from being created.
+        /// </summary>
+        private ClipboardService()
+        {
+        }
+
+        /// <summary>
+        /// Gets the instance.
+        /// </summary>
+        public static IClipboardService Instance
+        {
+            get
+            {
+                if (instance == null)
+                {
+                    lock (SyncRoot)
+                    {
+                        if (instance == null)
+                        {
+                            instance = new ClipboardService();
+                        }
+                    }
+                }
+
+                return instance;
+            }
+        }
+
+        /// <summary>
+        /// Sets the data object.
+        /// </summary>
+        /// <param name="dataObject">The data object.</param>
+        /// <exception cref="ArgumentNullException">The data object is null.</exception>
+        public void SetDataObject(IDataObject dataObject)
+        {
+            dataObject.ThrowsArgumentNullException("dataObject");
+
+            Clipboard.SetDataObject(dataObject);
+        }
+
+        /// <summary>
+        /// Gets the data.
+        /// </summary>
+        /// <typeparam name="T">The type.</typeparam>
+        /// <param name="format">The format.</param>
+        /// <returns>
+        /// The data.
+        /// </returns>
+        /// <exception cref="ArgumentException">The format string is null or empty.</exception>
+        public T GetData<T>(string format)
+        {
+            format.ThrowsArgumentExceptionIfNullOrEmpty("format");
+
+            IDataObject dataObject = Clipboard.GetDataObject();
+            if (dataObject != null)
+            {
+                if (dataObject.GetDataPresent(format))
+                {
+                    try
+                    {
+                        return (T)dataObject.GetData(format);
+                    }
+                    catch
+                    {
+                        return default(T);
+                    }
+                }
+            }
+
+            return default(T);
+        }
+
+        /// <summary>
+        /// Gets a boolean value indicating whether the clipboard data contains data in specified format.
+        /// </summary>
+        /// <param name="format">The format.</param>
+        /// <exception cref="ArgumentException">The format string is null or empty.</exception>
+        /// <returns>True if the specified format is contained in the Clipboard.</returns>
+        public bool DoesClipboardDataContain(string format)
+        {
+            format.ThrowsArgumentExceptionIfNullOrEmpty("format");
+
+            IDataObject dataObject = Clipboard.GetDataObject();
+            if (dataObject != null)
+            {
+                string[] formats = dataObject.GetFormats();
+                return formats.Contains(format);
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// Clears the clipbord.
+        /// </summary>
+        public void ClearClipbord()
+        {
+            Clipboard.Clear();
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Services/Properties/Settings.Designer.cs b/Main/SimpleBackup.Services/Properties/Settings.Designer.cs
new file mode 100644 (file)
index 0000000..fdf4566
--- /dev/null
@@ -0,0 +1,50 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     このコードはツールによって生成されました。
+//     ランタイム バージョン:4.0.30319.34014
+//
+//     このファイルへの変更は、以下の状況下で不正な動作の原因になったり、
+//     コードが再生成されるときに損失したりします。
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace SimpleBackup.Services.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("")]
+        public string DefaultSettingFileName {
+            get {
+                return ((string)(this["DefaultSettingFileName"]));
+            }
+            set {
+                this["DefaultSettingFileName"] = value;
+            }
+        }
+        
+        [global::System.Configuration.UserScopedSettingAttribute()]
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+        [global::System.Configuration.DefaultSettingValueAttribute("")]
+        public string DefaultZipEncodingKeyText {
+            get {
+                return ((string)(this["DefaultZipEncodingKeyText"]));
+            }
+            set {
+                this["DefaultZipEncodingKeyText"] = value;
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Services/Properties/Settings.settings b/Main/SimpleBackup.Services/Properties/Settings.settings
new file mode 100644 (file)
index 0000000..4973a97
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="SimpleBackup.Services.Properties" GeneratedClassName="Settings">
+  <Profiles />
+  <Settings>
+    <Setting Name="DefaultSettingFileName" Type="System.String" Scope="User">
+      <Value Profile="(Default)" />
+    </Setting>
+    <Setting Name="DefaultZipEncodingKeyText" Type="System.String" Scope="User">
+      <Value Profile="(Default)" />
+    </Setting>
+  </Settings>
+</SettingsFile>
\ No newline at end of file
diff --git a/Main/SimpleBackup.Services/ServiceComponent.cs b/Main/SimpleBackup.Services/ServiceComponent.cs
new file mode 100644 (file)
index 0000000..46a15e4
--- /dev/null
@@ -0,0 +1,45 @@
+//-----------------------------------------------------------------------
+// <copyright file="ServiceComponent.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Services
+{
+    using SimpleBackup.Core;
+    using SimpleBackup.Core.AppInfrastructure;
+    using SimpleBackup.Core.Services;
+
+    /// <summary>
+    /// The service component.
+    /// </summary>
+    internal class ServiceComponent : IAppComponent
+    {
+        /// <summary>
+        /// Initializes this application component.
+        /// </summary>
+        public void Initialize()
+        {
+            ObjectContainer.Register<IBackupService>(BackupService.Instance);
+            ObjectContainer.Register<IBackupSettingService>(BackupSettingService.Instance);
+            ObjectContainer.Register<IClipboardService>(ClipboardService.Instance);
+            ObjectContainer.Register<ISettingsService>(SettingsService.Instance);
+            ObjectContainer.Register<IUndoRedoService>(UndoRedoService.Instance);
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Services/SettingsService.cs b/Main/SimpleBackup.Services/SettingsService.cs
new file mode 100644 (file)
index 0000000..98aa9b0
--- /dev/null
@@ -0,0 +1,110 @@
+//-----------------------------------------------------------------------
+// <copyright file="SettingsService.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Services
+{
+    using SimpleBackup.Core.Services;
+
+    /// <summary>
+    /// Provides application setting.
+    /// </summary>
+    internal class SettingsService : ISettingsService
+    {
+        /// <summary>
+        /// The synchronize root.
+        /// </summary>
+        private static readonly object SyncRoot = new object();
+
+        /// <summary>
+        /// The instance of SettingsService.
+        /// </summary>
+        private static volatile SettingsService instance;
+
+        /// <summary>
+        /// Prevents a default instance of the <see cref="SettingsService"/> class from being created.
+        /// </summary>
+        private SettingsService()
+        {
+        }
+
+        /// <summary>
+        /// Gets the instance.
+        /// </summary>
+        public static ISettingsService Instance
+        {
+            get
+            {
+                if (instance == null)
+                {
+                    lock (SyncRoot)
+                    {
+                        if (instance == null)
+                        {
+                            instance = new SettingsService();
+                        }
+                    }
+                }
+
+                return instance;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the default name of the setting file.
+        /// </summary>
+        public string DefaultSettingFileName
+        {
+            get
+            {
+                return Properties.Settings.Default.DefaultSettingFileName;
+            }
+
+            set
+            {
+                if (Properties.Settings.Default.DefaultSettingFileName != value)
+                {
+                    Properties.Settings.Default.DefaultSettingFileName = value;
+                    Properties.Settings.Default.Save();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the default zip encoding key text.
+        /// </summary>
+        public string DefaultZipEncodingKeyText
+        {
+            get
+            {
+                return Properties.Settings.Default.DefaultZipEncodingKeyText;
+            }
+
+            set
+            {
+                if (Properties.Settings.Default.DefaultZipEncodingKeyText != value)
+                {
+                    Properties.Settings.Default.DefaultZipEncodingKeyText = value;
+                    Properties.Settings.Default.Save();
+                }
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Services/SimpleBackup.Services.csproj b/Main/SimpleBackup.Services/SimpleBackup.Services.csproj
new file mode 100644 (file)
index 0000000..c36f0ae
--- /dev/null
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{950EE3DF-1731-49B7-94C2-F33154855782}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SimpleBackup.Services</RootNamespace>
+    <AssemblyName>SimpleBackup.Services</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>SimpleBackupKey.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="PresentationCore" />
+    <Reference Include="PresentationFramework" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.IO.Compression.FileSystem" />
+    <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Lib\Expression\Blend\.NETFramework\v4.5\Libraries\System.Windows.Interactivity.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Xaml" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+    <Reference Include="WindowsBase" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Properties\AssemblyInfo.cs">
+      <Link>Properties\AssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="BackupService.cs" />
+    <Compile Include="BackupSettingService.cs" />
+    <Compile Include="ClipboardService.cs" />
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+      <DependentUpon>Settings.settings</DependentUpon>
+    </Compile>
+    <Compile Include="ServiceComponent.cs" />
+    <Compile Include="SettingsService.cs" />
+    <Compile Include="UndoRedoActionSet.cs" />
+    <Compile Include="UndoRedoService.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="app.config" />
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <None Include="SimpleBackupKey.snk" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\SimpleBackup.Core\SimpleBackup.Core.csproj">
+      <Project>{33f1d454-9962-4eb6-aad3-8d11d9a78d1f}</Project>
+      <Name>SimpleBackup.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\SimpleBackup.Resources\SimpleBackup.Resources.csproj">
+      <Project>{a655131e-d439-4de1-bc39-5c955306183f}</Project>
+      <Name>SimpleBackup.Resources</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PostBuildEvent>set EXE_BIN_DIR=$(ProjectDir)..\bin\$(ConfigurationName)\
+xcopy "$(TargetDir)$(TargetName).dll" "%25EXE_BIN_DIR%25" /Y
+if exist "$(TargetDir)$(TargetName).pdb" xcopy "$(TargetDir)$(TargetName).pdb" "%25EXE_BIN_DIR%25" /Y</PostBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Main/SimpleBackup.Services/SimpleBackupKey.snk b/Main/SimpleBackup.Services/SimpleBackupKey.snk
new file mode 100644 (file)
index 0000000..def2e6d
Binary files /dev/null and b/Main/SimpleBackup.Services/SimpleBackupKey.snk differ
diff --git a/Main/SimpleBackup.Services/UndoRedoActionSet.cs b/Main/SimpleBackup.Services/UndoRedoActionSet.cs
new file mode 100644 (file)
index 0000000..db4bb14
--- /dev/null
@@ -0,0 +1,71 @@
+//-----------------------------------------------------------------------
+// <copyright file="UndoRedoActionSet.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Services
+{
+    using System;
+    using SimpleBackup.Core.Utilities;
+
+    /// <summary>
+    /// Provides undo/redo function.
+    /// </summary>
+    internal partial class UndoRedoService
+    {
+        /// <summary>
+        /// Represents a pair of undo/redo actions and its context information.
+        /// </summary>
+        private class UndoRedoActionSet
+        {
+            /// <summary>
+            /// Initializes a new instance of the <see cref="UndoRedoActionSet"/> class.
+            /// </summary>
+            /// <param name="redoAction">The redo action.</param>
+            /// <param name="undoAction">The undo action.</param>
+            /// <param name="context">The context.</param>
+            /// <exception cref="ArgumentNullException">The redoAction is null.</exception>
+            /// <exception cref="ArgumentNullException">The undoAction is null.</exception>
+            public UndoRedoActionSet(Action<object> redoAction, Action<object> undoAction, object context)
+            {
+                redoAction.ThrowsArgumentNullException("redoAction");
+                undoAction.ThrowsArgumentNullException("undoAction");
+
+                this.RedoAction = redoAction;
+                this.UndoAction = undoAction;
+                this.Context = context;
+            }
+
+            /// <summary>
+            /// Gets the redo action.
+            /// </summary>
+            public Action<object> RedoAction { get; private set; }
+
+            /// <summary>
+            /// Gets the undo action.
+            /// </summary>
+            public Action<object> UndoAction { get; private set; }
+
+            /// <summary>
+            /// Gets the context.
+            /// </summary>
+            public object Context { get; private set; }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Services/UndoRedoService.cs b/Main/SimpleBackup.Services/UndoRedoService.cs
new file mode 100644 (file)
index 0000000..5e221b3
--- /dev/null
@@ -0,0 +1,144 @@
+//-----------------------------------------------------------------------
+// <copyright file="UndoRedoService.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Services
+{
+    using System;
+    using System.Collections.Generic;
+    using SimpleBackup.Core.Services;
+    using SimpleBackup.Core.Utilities;
+
+    /// <summary>
+    /// Provides undo/redo function.
+    /// </summary>
+    internal partial class UndoRedoService : IUndoRedoService
+    {
+        private static readonly object SyncRoot = new object();
+        private static volatile UndoRedoService instance;
+
+        private readonly Stack<UndoRedoActionSet> actionSetsForUndo = new Stack<UndoRedoActionSet>();
+        private readonly Stack<UndoRedoActionSet> actionSetsForRedo = new Stack<UndoRedoActionSet>();
+
+        /// <summary>
+        /// Prevents a default instance of the <see cref="UndoRedoService"/> class from being created.
+        /// </summary>
+        private UndoRedoService()
+        {
+        }
+
+        /// <summary>
+        /// Gets the instance.
+        /// </summary>
+        public static IUndoRedoService Instance
+        {
+            get
+            {
+                if (instance == null)
+                {
+                    lock (SyncRoot)
+                    {
+                        if (instance == null)
+                        {
+                            instance = new UndoRedoService();
+                        }
+                    }
+                }
+
+                return instance;
+            }
+        }
+
+        /// <summary>
+        /// Commits the specified redo action with related undo action and the context information.
+        /// </summary>
+        /// <param name="redoAction">The redo action.</param>
+        /// <param name="undoAction">The undo action.</param>
+        /// <param name="context">The context.</param>
+        /// <exception cref="ArgumentNullException">The redoAction is null.</exception>
+        /// <exception cref="ArgumentNullException">The undoAction is null.</exception>
+        public void Commit(Action<object> redoAction, Action<object> undoAction, object context)
+        {
+            redoAction.ThrowsArgumentNullException("redoAction");
+            undoAction.ThrowsArgumentNullException("undoAction");
+
+            var undoRedoActionSet = new UndoRedoActionSet(redoAction, undoAction, context);
+            this.actionSetsForUndo.Push(undoRedoActionSet);
+            redoAction.Invoke(undoRedoActionSet.Context);
+        }
+
+        /// <summary>
+        /// Executes undo action.
+        /// </summary>
+        public void Undo()
+        {
+            if (this.CanExecuteUndo() == false)
+            {
+                return;
+            }
+
+            UndoRedoActionSet undoRedoActionSet = this.actionSetsForUndo.Pop();
+            undoRedoActionSet.UndoAction.Invoke(undoRedoActionSet.Context);
+            this.actionSetsForRedo.Push(undoRedoActionSet);
+        }
+
+        /// <summary>
+        /// Determines whether the undo action is executable.
+        /// </summary>
+        /// <returns>true if the undo action can be executable; otherwise, false.</returns>
+        public bool CanExecuteUndo()
+        {
+            return this.actionSetsForUndo.Count != 0;
+        }
+
+        /// <summary>
+        /// Executes redo action.
+        /// </summary>
+        public void Redo()
+        {
+            if (this.CanExecuteRedo() == false)
+            {
+                return;
+            }
+
+            UndoRedoActionSet undoRedoActionSet = this.actionSetsForRedo.Pop();
+            undoRedoActionSet.RedoAction.Invoke(undoRedoActionSet.Context);
+            this.actionSetsForUndo.Push(undoRedoActionSet);
+        }
+
+        /// <summary>
+        /// Determines whether the redo action is executable.
+        /// </summary>
+        /// <returns>true if the redo action can be executable; otherwise, false.</returns>
+        public bool CanExecuteRedo()
+        {
+            return this.actionSetsForRedo.Count != 0;
+        }
+
+        /// <summary>
+        /// Clears the undo redo buffer.
+        /// </summary>
+        public void ClearUndoRedoBuffer()
+        {
+            this.actionSetsForUndo.Clear();
+            this.actionSetsForRedo.Clear();
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Services/app.config b/Main/SimpleBackup.Services/app.config
new file mode 100644 (file)
index 0000000..632bc35
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <configSections>
+        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
+            <section name="SimpleBackup.Services.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
+        </sectionGroup>
+    </configSections>
+    <userSettings>
+        <SimpleBackup.Services.Properties.Settings>
+            <setting name="DefaultSettingFileName" serializeAs="String">
+                <value />
+            </setting>
+            <setting name="DefaultZipEncodingKeyText" serializeAs="String">
+                <value />
+            </setting>
+        </SimpleBackup.Services.Properties.Settings>
+    </userSettings>
+</configuration>
\ No newline at end of file
diff --git a/Main/SimpleBackup.ViewModels/BackupInfoPasteInfo.cs b/Main/SimpleBackup.ViewModels/BackupInfoPasteInfo.cs
new file mode 100644 (file)
index 0000000..d169528
--- /dev/null
@@ -0,0 +1,67 @@
+//-----------------------------------------------------------------------
+// <copyright file="BackupInfoPasteInfo.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using System;
+    using SimpleBackup.Core.Utilities;
+    using SimpleBackup.Core.ViewModels;
+
+    /// <summary>
+    /// Paste information of BackupInfo.
+    /// </summary>
+    [Serializable]
+    internal class BackupInfoPasteInfo
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BackupInfoPasteInfo"/> class.
+        /// </summary>
+        /// <param name="backupInfoBytes">The backup information bytes.</param>
+        /// <param name="pasteType">Type of the paste.</param>
+        /// <param name="sourceIndex">Index of the source backup information view model.</param>
+        public BackupInfoPasteInfo(
+            byte[] backupInfoBytes,
+            PasteType pasteType,
+            int sourceIndex)
+        {
+            backupInfoBytes.ThrowsArgumentNullException("backupInfoBytes");
+
+            this.BackupInfoBytes = backupInfoBytes;
+            this.PasteType = pasteType;
+            this.SourceIndex = sourceIndex;
+        }
+
+        /// <summary>
+        /// Gets the backup information bytes.
+        /// </summary>
+        public byte[] BackupInfoBytes { get; private set; }
+
+        /// <summary>
+        /// Gets the type of the paste.
+        /// </summary>
+        public PasteType PasteType { get; private set; }
+
+        /// <summary>
+        /// Gets the index of the source backup information view model.
+        /// </summary>
+        public int SourceIndex { get; private set; }
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/BackupInfoViewModel.cs b/Main/SimpleBackup.ViewModels/BackupInfoViewModel.cs
new file mode 100644 (file)
index 0000000..c4ac97f
--- /dev/null
@@ -0,0 +1,794 @@
+//-----------------------------------------------------------------------
+// <copyright file="BackupInfoViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using System;
+    using System.ComponentModel;
+    using System.IO;
+    using System.Text.RegularExpressions;
+    using System.Windows.Forms;
+    using System.Windows.Input;
+    using SimpleBackup.Core;
+    using SimpleBackup.Core.Models;
+    using SimpleBackup.Core.Services;
+    using SimpleBackup.Core.Utilities;
+    using SimpleBackup.Core.ViewModels;
+    using SimpleBackup.Core.Views;
+    using SimpleBackup.Resources;
+
+    /// <summary>
+    /// Backup information view model.
+    /// </summary>
+    internal class BackupInfoViewModel : PropertyChangeNotificationBase, IBackupInfoViewModel
+    {
+        private readonly IBackupService backupService;
+        private readonly IBackupSettingService backupSettingService;
+        private readonly IViewFactory viewFactory;
+
+        private readonly IBackupInfo backupInfoModel;
+
+        private readonly Action clearOutputMessageAction;
+
+        private readonly Action<string> addOutputMessageAction;
+
+        private bool innerHasSourcePathError;
+
+        private bool innerHasDestinationFolderPathError;
+
+        private bool innerIsSourceEditing;
+
+        private string innerEditingSourcePath = string.Empty;
+
+        private bool innerIsDestinationEditing;
+
+        private string innerEditingDestinationPath = string.Empty;
+
+        private bool innerIsCutReserved;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BackupInfoViewModel"/> class.
+        /// </summary>
+        /// <param name="backupInfoModel">The backup information model.</param>
+        /// <param name="clearOutputMessageAction">The clear output message action.</param>
+        /// <param name="addOutputMessageAction">The add output message action.</param>
+        private BackupInfoViewModel(
+            IBackupInfo backupInfoModel,
+            Action clearOutputMessageAction,
+            Action<string> addOutputMessageAction)
+        {
+            backupInfoModel.ThrowsArgumentNullException("backupInfoModel");
+            clearOutputMessageAction.ThrowsArgumentNullException("clearOutputMessageAction");
+            addOutputMessageAction.ThrowsArgumentNullException("addOutputMessageAction");
+
+            this.backupInfoModel = backupInfoModel;
+            this.backupInfoModel.PropertyChanged += this.OnBackupInfoModelPropertyChanged;
+            this.clearOutputMessageAction = clearOutputMessageAction;
+            this.addOutputMessageAction = addOutputMessageAction;
+
+            this.backupService = ObjectContainer.Resolve<IBackupService>();
+            this.backupSettingService = ObjectContainer.Resolve<IBackupSettingService>();
+            this.viewFactory = ObjectContainer.Resolve<IViewFactory>();
+
+            this.OpenSourceFileRelayCommand = new RelayCommand(this.ExecuteOpenSourceFile, this.CanExecuteOpenSourceFile);
+            this.OpenSourceFolderRelayCommand = new RelayCommand(this.ExecuteOpenSourceFolder, this.CanExecuteOpenSourceFolder);
+            this.SelectSourceRelayCommand = new RelayCommand(this.ExecuteSelectSource, this.CanExecuteSelectSource);
+            this.OpenDestinationFolderRelayCommand = new RelayCommand(this.ExecuteOpenDestinationFolder, this.CanExecuteOpenDestinationFolder);
+            this.SelectDestinationRelayCommand = new RelayCommand(this.ExecuteSelectDestination, this.CanExecuteSelectDestination);
+            this.EditSourceRelayCommand = new RelayCommand(this.ExecuteEditSource, this.CanExecuteEditSource);
+            this.EditDestinationRelayCommand = new RelayCommand(this.ExecuteEditDestination, this.CanExecuteEditDestination);
+            this.SingleBackupRelayCommand = new RelayCommand(this.ExecuteSingleBackup, this.CanExecuteSingleBackup);
+
+            this.UpdateErrorStatus();
+        }
+
+        /// <summary>
+        /// Gets the open source file relay command.
+        /// </summary>
+        public RelayCommand OpenSourceFileRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the open source folder relay command.
+        /// </summary>
+        public RelayCommand OpenSourceFolderRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the select source relay command.
+        /// </summary>
+        public RelayCommand SelectSourceRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the open destination folder relay command.
+        /// </summary>
+        public RelayCommand OpenDestinationFolderRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the select destination relay command.
+        /// </summary>
+        public RelayCommand SelectDestinationRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the edit source relay command.
+        /// </summary>
+        public RelayCommand EditSourceRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the edit destination relay command.
+        /// </summary>
+        public RelayCommand EditDestinationRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the single backup with context menu relay command.
+        /// </summary>
+        public RelayCommand SingleBackupRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the backup information identifier.
+        /// </summary>
+        public Guid BackupInfoId
+        {
+            get
+            {
+                return this.backupInfoModel.Id;
+            }
+        }
+
+        /// <summary>
+        /// Gets the type of the source.
+        /// </summary>
+        public BackupSourceType SourceType
+        {
+            get
+            {
+                return this.backupInfoModel.BackupSourceType;
+            }
+        }
+
+        /// <summary>
+        /// Gets the state of the backup.
+        /// </summary>
+        public BackupState BackupState
+        {
+            get
+            {
+                return this.backupInfoModel.BackupState;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the backup is enabled.
+        /// </summary>
+        public bool IsEnabled
+        {
+            get
+            {
+                return this.backupInfoModel.IsEnabled;
+            }
+
+            set
+            {
+                if (this.backupInfoModel.IsEnabled != value)
+                {
+                    this.backupInfoModel.IsEnabled = value;
+                    this.NotifyPropertyChanged("IsEnabled");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the backup is zip archive.
+        /// </summary>
+        public bool IsZipArchive
+        {
+            get
+            {
+                return this.backupInfoModel.IsZipArchive;
+            }
+
+            set
+            {
+                if (this.backupInfoModel.IsZipArchive != value)
+                {
+                    this.backupInfoModel.IsZipArchive = value;
+                    this.NotifyPropertyChanged("IsZipArchive");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the label.
+        /// </summary>
+        public string Label
+        {
+            get
+            {
+                return this.backupInfoModel.Label;
+            }
+
+            set
+            {
+                if (this.backupInfoModel.Label != value)
+                {
+                    this.backupInfoModel.Label = value;
+                    this.NotifyPropertyChanged("Label");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the source path.
+        /// </summary>
+        public string SourcePath
+        {
+            get
+            {
+                return this.backupInfoModel.SourcePath;
+            }
+
+            set
+            {
+                if ((this.backupInfoModel.SourcePath != value) &&
+                    value.IsValidFileOrDirectoryPath())
+                {
+                    this.backupInfoModel.SourcePath = value;
+                    this.UpdateErrorStatus();
+                    this.NotifyPropertyChanged("SourcePath");
+                    this.NotifyPropertyChanged("DisplaySourcePath");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the display source path.
+        /// </summary>
+        public string DisplaySourcePath
+        {
+            get
+            {
+                return Helpers.CreateDisplayPathText(this.backupInfoModel.SourcePath);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the editing source path.
+        /// </summary>
+        public string EditingSourcePath
+        {
+            get
+            {
+                return this.innerEditingSourcePath;
+            }
+
+            set
+            {
+                if (this.innerEditingSourcePath != value)
+                {
+                    this.innerEditingSourcePath = value;
+                    this.NotifyPropertyChanged("EditingSourcePath");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the source tool tip text.
+        /// </summary>
+        public string SourceToolTipText
+        {
+            get
+            {
+                Match match = Constants.EndPathSegmentRegex.Match(this.backupInfoModel.SourcePath);
+                return match.Success ? match.Value : string.Empty;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this instance is source editing.
+        /// </summary>
+        public bool IsSourceEditing
+        {
+            get
+            {
+                return this.innerIsSourceEditing;
+            }
+
+            set
+            {
+                if (this.innerIsSourceEditing != value)
+                {
+                    this.innerIsSourceEditing = value;
+                    this.NotifyPropertyChanged("IsSourceEditing");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance has source path error.
+        /// </summary>
+        public bool HasSourcePathError
+        {
+            get
+            {
+                return this.innerHasSourcePathError;
+            }
+
+            private set
+            {
+                if (this.innerHasSourcePathError != value)
+                {
+                    this.innerHasSourcePathError = value;
+                    this.NotifyPropertyChanged("HasSourcePathError");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the destination folder path.
+        /// </summary>
+        public string DestinationFolderPath
+        {
+            get
+            {
+                return this.backupInfoModel.DestinationFolderPath;
+            }
+
+            set
+            {
+                if ((this.backupInfoModel.DestinationFolderPath != value) &&
+                    value.IsValidFileOrDirectoryPath())
+                {
+                    this.backupInfoModel.DestinationFolderPath = value;
+                    this.UpdateErrorStatus();
+                    this.NotifyPropertyChanged("DestinationFolderPath");
+                    this.NotifyPropertyChanged("DisplayDestinationFolderPath");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the display destination folder path.
+        /// </summary>
+        public string DisplayDestinationFolderPath
+        {
+            get
+            {
+                return Helpers.CreateDisplayPathText(
+                    Regex.Replace(this.backupInfoModel.DestinationFolderPath, @"\\$", string.Empty));
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the editing destination path.
+        /// </summary>
+        public string EditingDestinationPath
+        {
+            get
+            {
+                return this.innerEditingDestinationPath;
+            }
+
+            set
+            {
+                if (this.innerEditingDestinationPath != value)
+                {
+                    this.innerEditingDestinationPath = value;
+                    this.NotifyPropertyChanged("EditingDestinationPath");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the destination tool tip text.
+        /// </summary>
+        public string DestinationToolTipText
+        {
+            get
+            {
+                string endSeparatorRemovedPath = Constants.EndPathSeparatorRegex.Replace(this.backupInfoModel.DestinationFolderPath, string.Empty);
+                Match match = Constants.EndPathSegmentRegex.Match(endSeparatorRemovedPath);
+                return match.Success ? match.Value : string.Empty;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this instance is destination editing.
+        /// </summary>
+        public bool IsDestinationEditing
+        {
+            get
+            {
+                return this.innerIsDestinationEditing;
+            }
+
+            set
+            {
+                if (this.innerIsDestinationEditing != value)
+                {
+                    this.innerIsDestinationEditing = value;
+                    this.NotifyPropertyChanged("IsDestinationEditing");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance has destination folder path error.
+        /// </summary>
+        public bool HasDestinationFolderPathError
+        {
+            get
+            {
+                return this.innerHasDestinationFolderPathError;
+            }
+
+            private set
+            {
+                if (this.innerHasDestinationFolderPathError != value)
+                {
+                    this.innerHasDestinationFolderPathError = value;
+                    this.NotifyPropertyChanged("HasDestinationFolderPathError");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is editing.
+        /// </summary>
+        public bool IsEditing
+        {
+            get
+            {
+                return this.IsSourceEditing || this.IsDestinationEditing;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this instance is cut reserved.
+        /// </summary>
+        public bool IsCutReserved
+        {
+            get
+            {
+                return this.innerIsCutReserved;
+            }
+
+            set
+            {
+                if (this.innerIsCutReserved != value)
+                {
+                    this.innerIsCutReserved = value;
+                    this.NotifyPropertyChanged("IsCutReserved");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Creates the backup information view mode.
+        /// </summary>
+        /// <param name="backupInfoModel">The backup information model.</param>
+        /// <param name="clearOutputMessageAction">The clear output message action.</param>
+        /// <param name="addOutputMessageAction">The add output message action.</param>
+        /// <returns>The backup information view model.</returns>
+        public static IBackupInfoViewModel CreateBackupInfoViewMode(
+            IBackupInfo backupInfoModel,
+            Action clearOutputMessageAction,
+            Action<string> addOutputMessageAction)
+        {
+            return new BackupInfoViewModel(
+                backupInfoModel,
+                clearOutputMessageAction,
+                addOutputMessageAction);
+        }
+
+        /// <summary>
+        /// Gets the backup information.
+        /// </summary>
+        /// <returns>The backup information.</returns>
+        public IBackupInfo GetBackupInfo()
+        {
+            return this.backupInfoModel;
+        }
+
+        /// <summary>
+        /// Executes the double click action.
+        /// </summary>
+        /// <param name="pathType">Type of the path.</param>
+        public void ExecuteDoubleClickAction(BackupInfoPathType pathType)
+        {
+            switch (pathType)
+            {
+                case BackupInfoPathType.Source:
+                    if (this.SourcePath.IsValidFileOrDirectoryPath())
+                    {
+                        this.SingleBackup();
+                    }
+                    else
+                    {
+                        string extractedPath;
+                        this.SelectSource(
+                            Helpers.TryExtractValidFolderPath(this.SourcePath, out extractedPath)
+                                ? extractedPath
+                                : string.Empty);
+                    }
+
+                    break;
+                case BackupInfoPathType.Destination:
+                    if (this.DestinationFolderPath.IsValidFileOrDirectoryPath())
+                    {
+                        this.ExecuteOpenDestinationFolder(null);
+                    }
+                    else
+                    {
+                        string extractedPath;
+                        this.SelectDestination(
+                            Helpers.TryExtractValidFolderPath(this.DestinationFolderPath, out extractedPath)
+                                ? extractedPath
+                                : string.Empty);
+                    }
+
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// Executes single backup.
+        /// </summary>
+        public void SingleBackup()
+        {
+            try
+            {
+                Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
+
+                this.clearOutputMessageAction();
+                Helpers.UpdateWpfGui();
+                this.addOutputMessageAction(Resources.Backup_ExecutingBackup);
+                Helpers.UpdateWpfGui();
+            
+                IResultInfo resultInfo = this.backupService.BackupSingleFile(this.BackupInfoId);
+                this.addOutputMessageAction(string.Format("{0}: {1}", resultInfo.BackupState.Translate(), resultInfo.Description));
+            }
+            finally
+            {
+                Mouse.OverrideCursor = null;
+            }
+        }
+
+        /// <summary>
+        /// Commits the editing contents.
+        /// </summary>
+        public void CommitEditingContents()
+        {
+            if (this.IsSourceEditing)
+            {
+                // Path validation is executed in SourcePath setter.
+                this.SourcePath = this.EditingSourcePath;
+                this.EditingSourcePath = string.Empty;
+                this.IsSourceEditing = false;
+            }
+
+            if (this.IsDestinationEditing)
+            {
+                // Path validation is executed in DestinationFolderPath setter.
+                this.DestinationFolderPath = this.EditingDestinationPath;
+                this.EditingDestinationPath = string.Empty;
+                this.IsDestinationEditing = false;
+            }
+        }
+
+        /// <summary>
+        /// Resets the state of the backup.
+        /// </summary>
+        public void ResetBackupState()
+        {
+            this.backupInfoModel.BackupState = BackupState.Todo;
+            this.UpdateErrorStatus();
+        }
+
+        private void OnBackupInfoModelPropertyChanged(
+            object sender,
+            PropertyChangedEventArgs propertyChangedEventArgs)
+        {
+            if (propertyChangedEventArgs.PropertyName == "BackupState")
+            {
+                this.NotifyPropertyChanged("BackupState");
+            }
+        }
+
+        private void ExecuteOpenSourceFile(object obj)
+        {
+            if (this.CanExecuteOpenSourceFile(obj) == false)
+            {
+                return;
+            }
+
+            Helpers.OpenFile(this.SourcePath);
+        }
+
+        private bool CanExecuteOpenSourceFile(object obj)
+        {
+            return (this.backupService.IsExecutingBackup == false) &&
+                (this.backupInfoModel.BackupSourceType == BackupSourceType.File);
+        }
+
+        private void ExecuteOpenSourceFolder(object obj)
+        {
+            Helpers.OpenParentFolderAndSelect(this.SourcePath);
+        }
+
+        private bool CanExecuteOpenSourceFolder(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void ExecuteSelectSource(object obj)
+        {
+            this.SelectSource(string.Empty);
+        }
+
+        private void SelectSource(string initialDirectoryPath)
+        {
+            string newSourcePath = string.Empty;
+
+            IFileFolderDialog fileFolderDialog = this.viewFactory.CreateFileFolderDialog();
+            if ((string.IsNullOrEmpty(initialDirectoryPath) == false) && Directory.Exists(initialDirectoryPath))
+            {
+                fileFolderDialog.SelectedPath = initialDirectoryPath;
+            }
+            else
+            {
+                fileFolderDialog.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+            }
+
+            if (fileFolderDialog.ShowDialog() == DialogResult.OK)
+            {
+                if (File.Exists(fileFolderDialog.SelectedPath))
+                {
+                    this.backupInfoModel.BackupSourceType = BackupSourceType.File;
+                    newSourcePath = fileFolderDialog.SelectedPath;
+                }
+                else if (Directory.Exists(fileFolderDialog.SelectedPath))
+                {
+                    this.backupInfoModel.BackupSourceType = BackupSourceType.Folder;
+                    newSourcePath = fileFolderDialog.SelectedPath;
+                }
+            }
+
+            if (string.IsNullOrEmpty(newSourcePath) == false)
+            {
+                this.backupInfoModel.SourcePath = newSourcePath;
+                this.NotifyPropertyChanged("SourceType");
+                this.NotifyPropertyChanged("SourcePath");
+                this.NotifyPropertyChanged("DisplaySourcePath");
+            }
+
+            this.UpdateErrorStatus();
+        }
+
+        private bool CanExecuteSelectSource(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void ExecuteOpenDestinationFolder(object obj)
+        {
+            IBackupInfo backupInfo = this.GetBackupInfo();
+            if (((backupInfo.BackupSourceType == BackupSourceType.File) &&
+                File.Exists(backupInfo.LatestSuccessfulBackupTargetName)) ||
+                ((backupInfo.BackupSourceType == BackupSourceType.Folder) &&
+                Directory.Exists(backupInfo.LatestSuccessfulBackupTargetName)))
+            {
+                Helpers.OpenParentFolderAndSelect(backupInfo.LatestSuccessfulBackupTargetName);
+            }
+            else
+            {
+                Helpers.OpenFolder(this.DestinationFolderPath);
+            }
+        }
+
+        private bool CanExecuteOpenDestinationFolder(object obj)
+        {
+            return this.backupSettingService.CurrentSetting != null;
+        }
+
+        private void ExecuteSelectDestination(object obj)
+        {
+            this.SelectDestination(string.Empty);
+        }
+
+        private void SelectDestination(string initialDirectoryPath)
+        {
+            IFileFolderDialog fileFolderDialog = this.viewFactory.CreateFileFolderDialog();
+            if ((string.IsNullOrEmpty(initialDirectoryPath) == false) && Directory.Exists(initialDirectoryPath))
+            {
+                fileFolderDialog.SelectedPath = initialDirectoryPath;
+            }
+            else
+            {
+                fileFolderDialog.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+            }
+
+            if (fileFolderDialog.ShowDialog() == DialogResult.OK)
+            {
+                string destinationPath =
+                    Directory.Exists(fileFolderDialog.SelectedPath)
+                        ? fileFolderDialog.SelectedPath
+                        : Path.GetDirectoryName(fileFolderDialog.SelectedPath);
+                this.backupInfoModel.DestinationFolderPath = destinationPath;
+                this.NotifyPropertyChanged("DestinationFolderPath");
+                this.NotifyPropertyChanged("DisplayDestinationFolderPath");
+            }
+
+            this.UpdateErrorStatus();
+        }
+
+        private bool CanExecuteSelectDestination(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void ExecuteEditSource(object obj)
+        {
+            this.EditingSourcePath = this.SourcePath;
+            this.IsSourceEditing = true;
+        }
+
+        private bool CanExecuteEditSource(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void ExecuteEditDestination(object obj)
+        {
+            this.EditingDestinationPath = this.DestinationFolderPath;
+            this.IsDestinationEditing = true;
+        }
+
+        private bool CanExecuteEditDestination(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void ExecuteSingleBackup(object obj)
+        {
+            this.SingleBackup();
+        }
+
+        private bool CanExecuteSingleBackup(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void UpdateErrorStatus()
+        {
+            switch (this.backupInfoModel.BackupSourceType)
+            {
+                case BackupSourceType.File:
+                    this.HasSourcePathError = File.Exists(this.backupInfoModel.SourcePath) == false;
+                    break;
+                case BackupSourceType.Folder:
+                    this.HasSourcePathError = Directory.Exists(this.backupInfoModel.SourcePath) == false;
+                    break;
+                default:
+                    throw new InvalidOperationException("Unexpected backup source type.");
+            }
+
+            this.HasDestinationFolderPathError = Directory.Exists(this.backupInfoModel.DestinationFolderPath) == false;
+        }
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/DataGridColumnHeaderBaseViewModel.cs b/Main/SimpleBackup.ViewModels/DataGridColumnHeaderBaseViewModel.cs
new file mode 100644 (file)
index 0000000..8fd7cee
--- /dev/null
@@ -0,0 +1,56 @@
+//-----------------------------------------------------------------------
+// <copyright file="DataGridColumnHeaderBaseViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using SimpleBackup.Core.Utilities;
+
+    /// <summary>
+    /// A base class of a DataGridColumn view models.
+    /// </summary>
+    internal abstract class DataGridColumnHeaderBaseViewModel : PropertyChangeNotificationBase
+    {
+        /// <summary>
+        /// The inner header
+        /// </summary>
+        private object innerHeader = new object();
+
+        /// <summary>
+        /// Gets or sets the header.
+        /// </summary>
+        public object Header
+        {
+            get
+            {
+                return this.innerHeader;
+            }
+
+            set
+            {
+                if (this.innerHeader != value)
+                {
+                    this.innerHeader = value;
+                    this.NotifyPropertyChanged("Header");
+                }
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/DestinationColumnHeaderViewModel.cs b/Main/SimpleBackup.ViewModels/DestinationColumnHeaderViewModel.cs
new file mode 100644 (file)
index 0000000..7c7df46
--- /dev/null
@@ -0,0 +1,32 @@
+//-----------------------------------------------------------------------
+// <copyright file="DestinationColumnHeaderViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using SimpleBackup.Core.ViewModels;
+
+    /// <summary>
+    /// The view model of destination column header.
+    /// </summary>
+    internal class DestinationColumnHeaderViewModel : DataGridColumnHeaderBaseViewModel, IDestinationColumnHeaderViewModel
+    {
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/EncodingInfoItemViewModel.cs b/Main/SimpleBackup.ViewModels/EncodingInfoItemViewModel.cs
new file mode 100644 (file)
index 0000000..3fda81d
--- /dev/null
@@ -0,0 +1,55 @@
+//-----------------------------------------------------------------------
+// <copyright file="EncodingInfoItemViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using SimpleBackup.Core.Utilities;
+
+    /// <summary>
+    /// A view model for single encoding information item.
+    /// </summary>
+    internal class EncodingInfoItemViewModel
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="EncodingInfoItemViewModel"/> class.
+        /// </summary>
+        /// <param name="encodingKeyName">Name of the encoding key.</param>
+        /// <param name="encodingDisplayName">Display name of the encoding.</param>
+        public EncodingInfoItemViewModel(string encodingKeyName, string encodingDisplayName)
+        {
+            encodingKeyName.ThrowsArgumentExceptionIfNullOrEmpty("encodingKeyName");
+            encodingDisplayName.ThrowsArgumentExceptionIfNullOrEmpty("encodingDisplayName");
+
+            this.EncodingKeyName = encodingKeyName;
+            this.EncodingDisplayName = encodingDisplayName;
+        }
+
+        /// <summary>
+        /// Gets the name of the encoding key.
+        /// </summary>
+        public string EncodingKeyName { get; private set; }
+
+        /// <summary>
+        /// Gets the display name of the encoding.
+        /// </summary>
+        public string EncodingDisplayName { get; private set; }
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/IndexBackupInfoViewModelPair.cs b/Main/SimpleBackup.ViewModels/IndexBackupInfoViewModelPair.cs
new file mode 100644 (file)
index 0000000..471fc83
--- /dev/null
@@ -0,0 +1,63 @@
+//-----------------------------------------------------------------------
+// <copyright file="IndexBackupInfoViewModelPair.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using System;
+    using SimpleBackup.Core.Utilities;
+    using SimpleBackup.Core.ViewModels;
+
+    /// <summary>
+    /// A pair of index and backup information view model.
+    /// </summary>
+    internal class IndexBackupInfoViewModelPair
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="IndexBackupInfoViewModelPair"/> class.
+        /// </summary>
+        /// <param name="index">The index.</param>
+        /// <param name="backupInfoViewModel">The backup information view model.</param>
+        /// <exception cref="System.ArgumentOutOfRangeException">The provided index is out of the range.</exception>
+        /// <exception cref="System.ArgumentNullException">The provided backupInfoViewModel is null.</exception>
+        public IndexBackupInfoViewModelPair(int index, IBackupInfoViewModel backupInfoViewModel)
+        {
+            if (index < 0)
+            {
+                throw new ArgumentOutOfRangeException("index");
+            }
+
+            backupInfoViewModel.ThrowsArgumentNullException("backupInfoViewModel");
+
+            this.Index = index;
+            this.BackupInfoViewModel = backupInfoViewModel;
+        }
+
+        /// <summary>
+        /// Gets the index.
+        /// </summary>
+        public int Index { get; private set; }
+
+        /// <summary>
+        /// Gets the backup information view model.
+        /// </summary>
+        public IBackupInfoViewModel BackupInfoViewModel { get; private set; }
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/IsZipArchiveColumnHeaderViewModel.cs b/Main/SimpleBackup.ViewModels/IsZipArchiveColumnHeaderViewModel.cs
new file mode 100644 (file)
index 0000000..262f9a4
--- /dev/null
@@ -0,0 +1,30 @@
+//-----------------------------------------------------------------------
+// <copyright file="IsZipArchiveColumnHeaderViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    /// <summary>
+    /// The view model of IsZipArchive column header.
+    /// </summary>
+    internal class IsZipArchiveColumnHeaderViewModel : DataGridColumnHeaderBaseViewModel
+    {
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/LabelColumnHeaderViewModel.cs b/Main/SimpleBackup.ViewModels/LabelColumnHeaderViewModel.cs
new file mode 100644 (file)
index 0000000..cc19cfa
--- /dev/null
@@ -0,0 +1,32 @@
+//-----------------------------------------------------------------------
+// <copyright file="LabelColumnHeaderViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using SimpleBackup.Core.ViewModels;
+
+    /// <summary>
+    /// The view model of label column header.
+    /// </summary>
+    internal class LabelColumnHeaderViewModel : DataGridColumnHeaderBaseViewModel, ILabelColumnHeaderViewModel
+    {
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/MainWindowViewModel.cs b/Main/SimpleBackup.ViewModels/MainWindowViewModel.cs
new file mode 100644 (file)
index 0000000..ad617f5
--- /dev/null
@@ -0,0 +1,1223 @@
+//-----------------------------------------------------------------------
+// <copyright file="MainWindowViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using System;
+    using System.Collections.Generic;
+    using System.Collections.ObjectModel;
+    using System.Globalization;
+    using System.IO;
+    using System.Linq;
+    using System.Reflection;
+    using System.Threading;
+    using System.Threading.Tasks;
+    using System.Windows;
+    using System.Windows.Input;
+    using SimpleBackup.Core;
+    using SimpleBackup.Core.Models;
+    using SimpleBackup.Core.Services;
+    using SimpleBackup.Core.Utilities;
+    using SimpleBackup.Core.ViewModels;
+    using SimpleBackup.Core.Views;
+
+    /// <summary>
+    /// The view model of the main window.
+    /// </summary>
+    internal class MainWindowViewModel : PropertyChangeNotificationBase, IMainWindowViewModel
+    {
+        private readonly string defaultWindowTitleFormat = Resources.Resources.Views_DefaultWindowTitle;
+        private readonly string windowTitleFormat = Resources.Resources.Views_WindowTitleFormat;
+        private readonly List<EncodingInfoItemViewModel> innerZipEncodings = new List<EncodingInfoItemViewModel>();
+        private readonly IBackupService backupService;
+        private readonly IBackupSettingService backupSettingService;
+        private readonly IClipboardService clipboardService;
+        private readonly IUndoRedoService undoRedoService;
+        private readonly IModelFactory modelFactory;
+        private readonly IViewFactory viewFactory;
+        private string innerWindowTitle;
+        private string innerOutputMessage;
+        private EncodingInfoItemViewModel innerSelectedEncodingInfoItem;
+        private CancellationTokenSource cancellationTokenSource;
+        private IBackupInfoViewModel innerSelectedBackupInfoViewModel;
+        private int innerSelectedFirstCellItemIndex;
+
+        /// <summary>
+        /// Prevents a default instance of the <see cref="MainWindowViewModel"/> class from being created.
+        /// </summary>
+        private MainWindowViewModel()
+        {
+            this.CreateNewBackupSettingRelayCommand = new RelayCommand(this.ExecuteCreateNewBackupSetting, this.CanExecuteCreateNewBackupSetting);
+            this.OpenBackupSettingRelayCommand = new RelayCommand(this.ExecuteOpenBackupSetting, this.CanExecuteOpenBackupSetting);
+            this.SaveBackupSettingRelayCommand = new RelayCommand(this.ExecuteSaveBackupSetting, this.CanExecuteSaveBackupSetting);
+            this.SaveAsBackupSettingRelayCommand = new RelayCommand(this.ExecuteSaveAsBackupSetting, this.CanExecuteSaveAsBackupSetting);
+            this.CloseBackupSettingRelayCommand = new RelayCommand(this.ExecuteCloseBackupSetting, this.CanExecuteCloseBackupSetting);
+            this.OpenCurrentSettingFileLocationRelayCommand = new RelayCommand(this.ExecuteOpenCurrentSettingFileLocation, this.CanExecuteOpenCurrentSettingFileLocation);
+            this.ExitRelayCommand = new RelayCommand(this.ExecuteExit, this.CanExecuteExit);
+
+            this.ShowHelpRelayCommand = new RelayCommand(this.ExecuteShowHelp);
+            this.ShowVersionInformationRelayCommand = new RelayCommand(this.ExecuteShowVersionInformation);
+
+            this.BackUpRelayCommand = new RelayCommand(this.ExecuteBackup, this.CanExecuteBackup);
+            this.BackupCancelRelayCommand = new RelayCommand(this.ExecuteBackupCancel, this.CanExecuteBackupCancel);
+            this.SingleBackupRelayCommand = new RelayCommand(this.ExecuteSingleBackup, this.CanExecuteSingleBackup);
+            this.AddItemRelayCommand = new RelayCommand(this.ExecuteAddItem, this.CanExecuteAddItem);
+            this.RemoveItemRelayCommand = new RelayCommand(this.ExecuteRemoveItem, this.CanExecuteRemoveItem);
+            this.MoveUpItemRelayCommand = new RelayCommand(this.ExecuteMoveUpItem, this.CanExecuteMoveUpItem);
+            this.MoveDownItemRelayCommand = new RelayCommand(this.ExecuteMoveDownItem, this.CanExecuteMoveDownItem);
+            this.CopyRelayCommand = new RelayCommand(this.ExecuteCopy, this.CanExecuteCopy);
+            this.CutRelayCommand = new RelayCommand(this.ExecuteCut, this.CanExecuteCut);
+            this.PasteRelayCommand = new RelayCommand(this.ExecutePaste, this.CanExecutePaste);
+            this.UndoRelayCommand = new RelayCommand(this.ExecuteUndo, this.CanExecuteUndo);
+            this.RedoRelayCommand = new RelayCommand(this.ExecuteRedo, this.CanExecuteRedo);
+            this.RefreshRelayCommand = new RelayCommand(this.ExecuteRefresh, this.CanExecuteRefresh);
+            this.ClearOutputWindowRelayCommand = new RelayCommand(this.ExecuteClearOutputWindow, this.CanExecuteClearOutputWindow);
+
+            this.WindowTitle = this.defaultWindowTitleFormat;
+            this.BackupInfoViewModels = new ObservableCollection<IBackupInfoViewModel>();
+
+            this.IsZipArchiveColumnHeaderViewModel = new IsZipArchiveColumnHeaderViewModel { Header = "Zip" };
+            this.LabelColumnHeaderViewModel = new LabelColumnHeaderViewModel { Header = Resources.Resources.Views_LabelColumnHeaderText };
+            this.SourceColumnHeaderViewModel = new SourceColumnHeaderViewModel { Header = Resources.Resources.Views_BackupSourceColumnHeaderText };
+            this.DestinationColumnHeaderViewModel = new DestinationColumnHeaderViewModel { Header = Resources.Resources.Views_BackupDestinationColumnHeaderText };
+            this.ProgressViewModel = new ProgressViewModel();
+
+            this.innerOutputMessage = string.Empty;
+            this.SetupZipEncodingItems();
+
+            this.backupService = ObjectContainer.Resolve<IBackupService>();
+            this.backupSettingService = ObjectContainer.Resolve<IBackupSettingService>();
+            this.clipboardService = ObjectContainer.Resolve<IClipboardService>();
+            this.undoRedoService = ObjectContainer.Resolve<IUndoRedoService>();
+            this.modelFactory = ObjectContainer.Resolve<IModelFactory>();
+            this.viewFactory = ObjectContainer.Resolve<IViewFactory>();
+
+            this.backupSettingService.BackupSettingOpened += this.OnBackupSettingOpened;
+            this.backupSettingService.BackupSettingModified += this.OnBackupSettingModified;
+            this.backupSettingService.BackupSettingSaved += this.OnBackupSettingSaved;
+            this.backupSettingService.BackupSettingClosed += this.OnBackupSettingClosed;
+            this.backupService.NofityFileBackupProgress += this.OnBackupServiceNofityFileBackupProgress;
+
+            string resultMessage;
+            if (this.backupSettingService.OpenDefaultBackupSetting(out resultMessage))
+            {
+                foreach (IBackupInfo backupInfo in this.backupSettingService.CurrentSetting.BackupInfos)
+                {
+                    IBackupInfoViewModel backupInfoViewModel = BackupInfoViewModel.CreateBackupInfoViewMode(
+                        backupInfo,
+                        this.ClearOutputMessage,
+                        this.AddOutputMessage);
+                    this.BackupInfoViewModels.Add(backupInfoViewModel);
+                }
+            }
+
+            if (string.IsNullOrEmpty(resultMessage) == false)
+            {
+                this.OutputMessage = resultMessage;
+            }
+        }
+
+        /// <summary>
+        /// Occurs when focusing on grid is required.
+        /// </summary>
+        public event EventHandler<EventArgs> FocusOnGrid;
+
+        /// <summary>
+        /// Occurs when focusing on grid row is required.
+        /// </summary>
+        public event EventHandler<FocusOnGridRowEventArgs> FocusOnGridRow;
+
+        /// <summary>
+        /// Gets the create new backup settings relay command.
+        /// </summary>
+        public RelayCommand CreateNewBackupSettingRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the open backup settings relay command.
+        /// </summary>
+        public RelayCommand OpenBackupSettingRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the save backup settings relay command.
+        /// </summary>
+        public RelayCommand SaveBackupSettingRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the save as backup settings relay command.
+        /// </summary>
+        public RelayCommand SaveAsBackupSettingRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the close backup settings relay command.
+        /// </summary>
+        public RelayCommand CloseBackupSettingRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the open current setting file location relay command.
+        /// </summary>
+        public RelayCommand OpenCurrentSettingFileLocationRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the exit relay command.
+        /// </summary>
+        public RelayCommand ExitRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the show help relay command.
+        /// </summary>
+        public RelayCommand ShowHelpRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the show version information relay command.
+        /// </summary>
+        public RelayCommand ShowVersionInformationRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the back up relay command.
+        /// </summary>
+        public RelayCommand BackUpRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the backup cancel relay command.
+        /// </summary>
+        public RelayCommand BackupCancelRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the single backup relay command.
+        /// </summary>
+        public RelayCommand SingleBackupRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the add item relay command.
+        /// </summary>
+        public RelayCommand AddItemRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the remove item relay command.
+        /// </summary>
+        public RelayCommand RemoveItemRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the move up item relay command.
+        /// </summary>
+        public RelayCommand MoveUpItemRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the move down item relay command.
+        /// </summary>
+        public RelayCommand MoveDownItemRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the copy relay command.
+        /// </summary>
+        public RelayCommand CopyRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the cut relay command.
+        /// </summary>
+        public RelayCommand CutRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the paste relay command.
+        /// </summary>
+        public RelayCommand PasteRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the undo relay command.
+        /// </summary>
+        public RelayCommand UndoRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the redo relay command.
+        /// </summary>
+        public RelayCommand RedoRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the refresh relay command.
+        /// </summary>
+        public RelayCommand RefreshRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the clear output window relay command.
+        /// </summary>
+        public RelayCommand ClearOutputWindowRelayCommand { get; private set; }
+
+        /// <summary>
+        /// Gets the backup information view models.
+        /// </summary>
+        public ObservableCollection<IBackupInfoViewModel> BackupInfoViewModels { get; private set; }
+
+        /// <summary>
+        /// Gets the progress view model.
+        /// </summary>
+        public ProgressViewModel ProgressViewModel { get; private set; }
+
+        /// <summary>
+        /// Gets the is zip archive column header view model.
+        /// </summary>
+        public IsZipArchiveColumnHeaderViewModel IsZipArchiveColumnHeaderViewModel { get; private set; }
+
+        /// <summary>
+        /// Gets the label column header view model.
+        /// </summary>
+        public LabelColumnHeaderViewModel LabelColumnHeaderViewModel { get; private set; }
+
+        /// <summary>
+        /// Gets the source column header view model.
+        /// </summary>
+        public SourceColumnHeaderViewModel SourceColumnHeaderViewModel { get; private set; }
+
+        /// <summary>
+        /// Gets the destination column header view model.
+        /// </summary>
+        public DestinationColumnHeaderViewModel DestinationColumnHeaderViewModel { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the window title.
+        /// </summary>
+        public string WindowTitle
+        {
+            get
+            {
+                return this.innerWindowTitle;
+            }
+
+            set
+            {
+                if (this.innerWindowTitle != value)
+                {
+                    this.innerWindowTitle = value;
+                    this.NotifyPropertyChanged("WindowTitle");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the zip encodings.
+        /// </summary>
+        public IEnumerable<EncodingInfoItemViewModel> ZipEncodings
+        {
+            get
+            {
+                return this.innerZipEncodings;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the selected encoding information item.
+        /// </summary>
+        public EncodingInfoItemViewModel SelectedEncodingInfoItem
+        {
+            get
+            {
+                return this.innerSelectedEncodingInfoItem;
+            }
+
+            set
+            {
+                if (this.innerSelectedEncodingInfoItem != value)
+                {
+                    this.innerSelectedEncodingInfoItem = value;
+                    var settingsService = ObjectContainer.Resolve<ISettingsService>();
+                    settingsService.DefaultZipEncodingKeyText = value.EncodingKeyName;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the selected backup information view model.
+        /// </summary>
+        public IBackupInfoViewModel SelectedBackupInfoViewModel
+        {
+            get
+            {
+                return this.innerSelectedBackupInfoViewModel;
+            }
+
+            set
+            {
+                if (this.innerSelectedBackupInfoViewModel != value)
+                {
+                    this.innerSelectedBackupInfoViewModel = value;
+                    this.NotifyPropertyChanged("SelectedBackupInfoViewModel");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the output message.
+        /// </summary>
+        public string OutputMessage
+        {
+            get
+            {
+                return this.innerOutputMessage;
+            }
+
+            set
+            {
+                if (this.innerOutputMessage != value)
+                {
+                    this.innerOutputMessage = value;
+                    this.NotifyPropertyChanged("OutputMessage");
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the index of the selected first cell item.
+        /// </summary>
+        public int SelectedFirstCellItemIndex
+        {
+            get
+            {
+                return this.innerSelectedFirstCellItemIndex;
+            }
+
+            set
+            {
+                this.innerSelectedFirstCellItemIndex = value;
+                this.CommitEditingContents();
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the selected first cell item.
+        /// </summary>
+        public BackupInfoViewModel SelectedFirstCellItem { get; set; }
+
+        /// <summary>
+        /// Creates the main window view model.
+        /// </summary>
+        /// <returns>The main window view model.</returns>
+        public static IMainWindowViewModel CreateMainWindowViewModel()
+        {
+            return new MainWindowViewModel();
+        }
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            this.Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Called when ESC key is pressed.
+        /// </summary>
+        public void OnEscKeyPressed()
+        {
+            this.CancelCutOperation();
+            this.CancelCellEditOperation();
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                // dispose managed resources
+                this.cancellationTokenSource.Dispose();
+            }
+
+            //// free native resources - Nothing to dispose.
+        }
+
+        /// <summary>
+        /// Cancels the cut operation.
+        /// </summary>
+        private void CancelCutOperation()
+        {
+            var cutReservedBackupInfoViewModels = this.BackupInfoViewModels.Where(p => p.IsCutReserved).ToArray();
+            foreach (IBackupInfoViewModel infoViewModel in cutReservedBackupInfoViewModels)
+            {
+                infoViewModel.IsCutReserved = false;
+                this.clipboardService.ClearClipbord();
+            }
+        }
+
+        /// <summary>
+        /// Cancels the cell edit operation.
+        /// </summary>
+        private void CancelCellEditOperation()
+        {
+            var editingInfoViewModels = this.BackupInfoViewModels.Where(p => p.IsEditing).ToArray();
+            foreach (IBackupInfoViewModel infoViewModel in editingInfoViewModels)
+            {
+                infoViewModel.IsSourceEditing = false;
+                infoViewModel.IsDestinationEditing = false;
+            }
+        }
+
+        private void OnBackupSettingOpened(object sender, SettingFileEventArgs args)
+        {
+            this.WindowTitle = string.Format(CultureInfo.InvariantCulture, this.windowTitleFormat, args.SettingName);
+        }
+
+        private void OnBackupSettingModified(object sender, SettingFileEventArgs args)
+        {
+            this.UpdateWindowTitleAsModified(args.SettingName);
+        }
+
+        private void OnBackupSettingSaved(object sender, SettingFileEventArgs args)
+        {
+            this.WindowTitle = string.Format(CultureInfo.InvariantCulture, this.windowTitleFormat, args.SettingName);
+        }
+
+        private void OnBackupSettingClosed(object sender, SettingFileEventArgs args)
+        {
+            this.WindowTitle = this.defaultWindowTitleFormat;
+            this.BackupInfoViewModels.Clear();
+        }
+
+        private void ExecuteCreateNewBackupSetting(object obj)
+        {
+            this.backupSettingService.CreateBackupSetting();
+            this.ExecuteAddItem(null);
+            this.UpdateWindowTitleAsModified(this.backupSettingService.CurrentSetting.SettingName);
+        }
+
+        private bool CanExecuteCreateNewBackupSetting(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void ExecuteBackup(object obj)
+        {
+            if (this.cancellationTokenSource != null)
+            {
+                this.cancellationTokenSource.Dispose();
+            }
+
+            this.cancellationTokenSource = new CancellationTokenSource();
+            Action backupAction = () =>
+                {
+                    try
+                    {
+                        Application.Current.Dispatcher.Invoke(
+                            () =>
+                                {
+                                    this.OutputMessage = Resources.Resources.Backup_ExecutingBackup;
+                                    Mouse.OverrideCursor = Cursors.Wait;
+                                });
+                        
+                        IResultInfo[] resultInfos;
+                        this.backupService.BackupMultipulFiles(this.cancellationTokenSource.Token, out resultInfos);
+                    }
+                    finally
+                    {
+                        Application.Current.Dispatcher.Invoke(
+                            () =>
+                            {
+                                Mouse.OverrideCursor = null;
+                            });
+                    }
+                };
+            Action<Task> postBackupAction = previousTask =>
+                {
+                    if (previousTask.Exception != null)
+                    {
+                        this.OutputMessage = this.OutputMessage + "\r\n" + previousTask.Exception.ToString();
+                    }
+
+                    if (this.FocusOnGrid != null)
+                    {
+                        Application.Current.Dispatcher.Invoke(
+                            () => this.FocusOnGrid(this, new EventArgs()));
+                    }
+                };
+
+            Task.Factory.StartNew(backupAction, this.cancellationTokenSource.Token)
+                .ContinueWith(postBackupAction);
+        }
+
+        private bool CanExecuteBackup(object obj)
+        {
+            return (this.backupSettingService.CurrentSetting != null) &&
+                this.backupService.IsReadyForBackup && (this.backupService.IsExecutingBackup == false);
+        }
+
+        private void ExecuteBackupCancel(object obj)
+        {
+            if (this.cancellationTokenSource != null)
+            {
+                this.cancellationTokenSource.Cancel();
+            }
+        }
+
+        private bool CanExecuteBackupCancel(object obj)
+        {
+            return this.backupService.IsReadyForBackup && this.backupService.IsExecutingBackup;
+        }
+
+        private void ExecuteOpenBackupSetting(object obj)
+        {
+            if (this.CanExecuteOpenBackupSetting(obj) == false)
+            {
+                return;
+            }
+
+            string resultMessage;
+            if (this.backupSettingService.OpenBackupSetting(out resultMessage))
+            {
+                foreach (IBackupInfo backupInfo in this.backupSettingService.CurrentSetting.BackupInfos)
+                {
+                    IBackupInfoViewModel backupInfoViewModel = BackupInfoViewModel.CreateBackupInfoViewMode(
+                        backupInfo,
+                        this.ClearOutputMessage,
+                        this.AddOutputMessage);
+                    this.BackupInfoViewModels.Add(backupInfoViewModel);
+                }
+            }
+
+            if (string.IsNullOrEmpty(resultMessage) == false)
+            {
+                this.OutputMessage = resultMessage;
+            }
+        }
+
+        private bool CanExecuteOpenBackupSetting(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void ExecuteSaveBackupSetting(object obj)
+        {
+            this.backupSettingService.OverWriteCurrntBackupSetting();
+        }
+
+        private bool CanExecuteSaveBackupSetting(object obj)
+        {
+            return (this.backupSettingService.CurrentSetting != null) &&
+                (this.backupService.IsExecutingBackup == false);
+        }
+
+        private void ExecuteSaveAsBackupSetting(object obj)
+        {
+            this.backupSettingService.SaveCurrentBackupSettingAsNewFile();
+        }
+
+        private bool CanExecuteSaveAsBackupSetting(object obj)
+        {
+            return (this.backupSettingService.CurrentSetting != null) &&
+                (this.backupService.IsExecutingBackup == false);
+        }
+
+        private void ExecuteCloseBackupSetting(object obj)
+        {
+            this.backupSettingService.CloseBackupSetting();
+        }
+
+        private bool CanExecuteCloseBackupSetting(object obj)
+        {
+            return (this.backupSettingService.CurrentSetting != null) &&
+                (this.backupService.IsExecutingBackup == false);
+        }
+
+        private void ExecuteOpenCurrentSettingFileLocation(object obj)
+        {
+            Helpers.OpenParentFolderAndSelect(this.backupSettingService.CurrentSetting.SettingFileName);
+        }
+
+        private bool CanExecuteOpenCurrentSettingFileLocation(object obj)
+        {
+            return (this.backupSettingService.CurrentSetting != null) &&
+                (this.backupService.IsExecutingBackup == false);
+        }
+
+        private void ExecuteExit(object obj)
+        {
+            Application.Current.Shutdown(0);
+        }
+
+        private bool CanExecuteExit(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void ExecuteShowHelp(object obj)
+        {
+            string helpFilePath = string.Format(
+                @"{0}\Documents\HelpDocument.pdf",
+                Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
+            Helpers.OpenFile(helpFilePath);
+        }
+
+        private void ExecuteShowVersionInformation(object obj)
+        {
+            IVersionInformationWindow versionInformationWindow = this.viewFactory.CreateVersionInformationWindow();
+            
+            versionInformationWindow.ShowDialogWindow();
+        }
+
+        private void ExecuteSingleBackup(object obj)
+        {
+            if (this.SelectedFirstCellItem != null)
+            {
+                this.SelectedFirstCellItem.SingleBackup();
+            }
+        }
+
+        private bool CanExecuteSingleBackup(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void ExecuteAddItem(object obj)
+        {
+            if (this.CanExecuteAddItem(obj) == false)
+            {
+                return;
+            }
+
+            int currentIndex = -1;
+            if (this.SelectedBackupInfoViewModel != null)
+            {
+                currentIndex = this.BackupInfoViewModels.IndexOf(this.SelectedBackupInfoViewModel);
+            }
+
+            int targetIndex = (currentIndex != -1) ? currentIndex + 1 : this.BackupInfoViewModels.Count;
+
+            var action = new Action<object>(
+                context =>
+                {
+                    var index = (int)context;
+                    IBackupInfo backupInfo = this.backupSettingService.CreateBackupInfo(index);
+                    IBackupInfoViewModel backupInfoViewModel = BackupInfoViewModel.CreateBackupInfoViewMode(
+                        backupInfo,
+                        this.ClearOutputMessage,
+                        this.AddOutputMessage);
+                    this.BackupInfoViewModels.Insert(index, backupInfoViewModel);
+
+                    if (this.FocusOnGridRow != null)
+                    {
+                        this.FocusOnGridRow(this, new FocusOnGridRowEventArgs(index));
+                    }
+
+                    this.SelectedBackupInfoViewModel = backupInfoViewModel;
+                });
+
+            var undoAction = new Action<object>(
+                context =>
+                {
+                    var index = (int)context;
+                    if (index < this.BackupInfoViewModels.Count)
+                    {
+                        var removingBackupInfoViewModel = this.BackupInfoViewModels[index];
+                        this.backupSettingService.RemoveBackupInfo(removingBackupInfoViewModel.BackupInfoId);
+                        this.BackupInfoViewModels.Remove(removingBackupInfoViewModel);
+
+                        if (index < this.BackupInfoViewModels.Count)
+                        {
+                            if (this.FocusOnGridRow != null)
+                            {
+                                this.FocusOnGridRow(this, new FocusOnGridRowEventArgs(index));
+                            }
+
+                            this.SelectedBackupInfoViewModel = this.BackupInfoViewModels[index];
+                        }
+                        else if (this.BackupInfoViewModels.Count != 0)
+                        {
+                            if (this.FocusOnGridRow != null)
+                            {
+                                this.FocusOnGridRow(this, new FocusOnGridRowEventArgs(index - 1));
+                            }
+
+                            this.SelectedBackupInfoViewModel = this.BackupInfoViewModels[index - 1];
+                        }
+                    }
+                });
+
+            this.undoRedoService.Commit(action, undoAction, targetIndex);
+        }
+
+        private bool CanExecuteAddItem(object obj)
+        {
+            return (this.backupSettingService.CurrentSetting != null) &&
+                (this.backupService.IsExecutingBackup == false);
+        }
+
+        private void ExecuteRemoveItem(object obj)
+        {
+            if (this.CanExecuteRemoveItem(obj) == false)
+            {
+                return;
+            }
+
+            var targetIndexViewModelPair = new IndexBackupInfoViewModelPair(
+                    this.BackupInfoViewModels.IndexOf(this.SelectedBackupInfoViewModel),
+                    this.SelectedBackupInfoViewModel);
+
+            this.RemoveItem(targetIndexViewModelPair);
+        }
+
+        private void RemoveItem(IndexBackupInfoViewModelPair targetIndexViewModelPair)
+        {
+            var action = new Action<object>(
+                context =>
+                {
+                    var indexViewModelPair = (IndexBackupInfoViewModelPair)context;
+                    if (indexViewModelPair.Index < this.BackupInfoViewModels.Count)
+                    {
+                        var removingBackupInfoViewModel = this.BackupInfoViewModels[indexViewModelPair.Index];
+                        this.backupSettingService.RemoveBackupInfo(removingBackupInfoViewModel.BackupInfoId);
+                        this.BackupInfoViewModels.Remove(removingBackupInfoViewModel);
+
+                        if (indexViewModelPair.Index < this.BackupInfoViewModels.Count)
+                        {
+                            if (this.FocusOnGridRow != null)
+                            {
+                                this.FocusOnGridRow(this, new FocusOnGridRowEventArgs(indexViewModelPair.Index));
+                            }
+
+                            this.SelectedBackupInfoViewModel = this.BackupInfoViewModels[indexViewModelPair.Index];
+                        }
+                        else if (this.BackupInfoViewModels.Count != 0)
+                        {
+                            if (this.FocusOnGridRow != null)
+                            {
+                                this.FocusOnGridRow(this, new FocusOnGridRowEventArgs(indexViewModelPair.Index - 1));
+                            }
+
+                            this.SelectedBackupInfoViewModel = this.BackupInfoViewModels[indexViewModelPair.Index - 1];
+                        }
+                    }
+                });
+
+            var undoAction = new Action<object>(
+                context =>
+                {
+                    var indexViewModelPair = (IndexBackupInfoViewModelPair)context;
+
+                    this.backupSettingService.InsertBackupInfo(
+                        indexViewModelPair.Index,
+                        indexViewModelPair.BackupInfoViewModel.GetBackupInfo());
+                    this.BackupInfoViewModels.Insert(
+                        indexViewModelPair.Index,
+                        indexViewModelPair.BackupInfoViewModel);
+
+                    if (this.FocusOnGridRow != null)
+                    {
+                        this.FocusOnGridRow(this, new FocusOnGridRowEventArgs(indexViewModelPair.Index));
+                    }
+
+                    this.SelectedBackupInfoViewModel = indexViewModelPair.BackupInfoViewModel;
+                });
+
+            this.undoRedoService.Commit(action, undoAction, targetIndexViewModelPair);
+        }
+
+        private bool CanExecuteRemoveItem(object obj)
+        {
+            return (this.backupSettingService.CurrentSetting != null) &&
+                (this.backupService.IsExecutingBackup == false) &&
+                (this.SelectedBackupInfoViewModel != null);
+        }
+
+        private void ExecuteMoveUpItem(object obj)
+        {
+            if (this.CanExecuteMoveUpItem(obj) == false)
+            {
+                return;
+            }
+
+            var selectedIdIndexPair = new IdIndexPair(
+                this.SelectedBackupInfoViewModel.BackupInfoId,
+                this.BackupInfoViewModels.IndexOf(this.SelectedBackupInfoViewModel));
+            var action = new Action<object>(context =>
+            {
+                var idIndexPair = (IdIndexPair)context;
+                if (idIndexPair.Index > 0)
+                {
+                    this.backupSettingService.CurrentSetting.MoveItem(idIndexPair.Id, ItemMovingDirection.MoveUp);
+                    this.BackupInfoViewModels.Move(idIndexPair.Index, idIndexPair.Index - 1);
+                }
+            });
+
+            var undoAction = new Action<object>(context =>
+            {
+                var idIndexPair = (IdIndexPair)context;
+                var index = idIndexPair.Index - 1;
+                if (index < this.BackupInfoViewModels.Count - 1)
+                {
+                    this.backupSettingService.CurrentSetting.MoveItem(idIndexPair.Id, ItemMovingDirection.MoveDown);
+                    this.BackupInfoViewModels.Move(index, index + 1);
+                }
+            });
+
+            this.undoRedoService.Commit(action, undoAction, selectedIdIndexPair);
+        }
+
+        private bool CanExecuteMoveUpItem(object obj)
+        {
+            return (this.backupSettingService.CurrentSetting != null) &&
+                (this.backupService.IsExecutingBackup == false) &&
+                (this.SelectedBackupInfoViewModel != null) &&
+                this.BackupInfoViewModels.IndexOf(this.SelectedBackupInfoViewModel) > 0;
+        }
+
+        private void ExecuteMoveDownItem(object obj)
+        {
+            if (this.CanExecuteMoveDownItem(obj) == false)
+            {
+                return;
+            }
+
+            var selectedIdIndexPair = new IdIndexPair(
+                this.SelectedBackupInfoViewModel.BackupInfoId,
+                this.BackupInfoViewModels.IndexOf(this.SelectedBackupInfoViewModel));
+            var action = new Action<object>(context =>
+            {
+                var idIndexPair = (IdIndexPair)context;
+                if (idIndexPair.Index < this.BackupInfoViewModels.Count - 1)
+                {
+                    this.backupSettingService.CurrentSetting.MoveItem(idIndexPair.Id, ItemMovingDirection.MoveDown);
+                    this.BackupInfoViewModels.Move(idIndexPair.Index, idIndexPair.Index + 1);
+                }
+            });
+
+            var undoAction = new Action<object>(context =>
+            {
+                var idIndexPair = (IdIndexPair)context;
+                var index = idIndexPair.Index + 1;
+                if (index > 0)
+                {
+                    this.backupSettingService.CurrentSetting.MoveItem(idIndexPair.Id, ItemMovingDirection.MoveUp);
+                    this.BackupInfoViewModels.Move(index, index - 1);
+                }
+            });
+
+            this.undoRedoService.Commit(action, undoAction, selectedIdIndexPair);
+        }
+
+        private bool CanExecuteMoveDownItem(object obj)
+        {
+            return (this.backupSettingService.CurrentSetting != null) &&
+                (this.backupService.IsExecutingBackup == false) &&
+                (this.SelectedBackupInfoViewModel != null) &&
+                this.BackupInfoViewModels.IndexOf(this.SelectedBackupInfoViewModel) < this.BackupInfoViewModels.Count - 1;
+        }
+
+        private void ExecuteCopy(object obj)
+        {
+            if (this.CanExecuteCopy(obj))
+            {
+                IBackupInfo copiedBackupInfo = this.backupSettingService.CopyBackupInfo(
+                    this.SelectedBackupInfoViewModel.GetBackupInfo());
+                byte[] backupInfoBytes = copiedBackupInfo.ToBinary();
+                var info = new BackupInfoPasteInfo(
+                    backupInfoBytes,
+                    PasteType.Copy,
+                    this.BackupInfoViewModels.IndexOf(this.SelectedBackupInfoViewModel));
+                IDataObject dataObject = new DataObject();
+                dataObject.SetData(Constants.BackupInfoClipboardFormat, info);
+                dataObject.SetData(DataFormats.Text, copiedBackupInfo.ToFormattedText());
+                this.clipboardService.SetDataObject(dataObject);
+            }
+        }
+
+        private bool CanExecuteCopy(object obj)
+        {
+            return this.SelectedBackupInfoViewModel != null;
+        }
+
+        private void ExecuteCut(object obj)
+        {
+            if (this.CanExecuteCut(obj))
+            {
+                IBackupInfo copiedBackupInfo = this.backupSettingService.CopyBackupInfo(
+                    this.SelectedBackupInfoViewModel.GetBackupInfo());
+                byte[] backupInfoBytes = copiedBackupInfo.ToBinary();
+                var info = new BackupInfoPasteInfo(
+                    backupInfoBytes,
+                    PasteType.Cut,
+                    this.BackupInfoViewModels.IndexOf(this.SelectedBackupInfoViewModel));
+                IDataObject dataObject = new DataObject();
+                dataObject.SetData(Constants.BackupInfoClipboardFormat, info);
+                this.clipboardService.SetDataObject(dataObject);
+                dataObject.SetData(DataFormats.Text, copiedBackupInfo.ToFormattedText());
+                this.SelectedBackupInfoViewModel.IsCutReserved = true;
+            }
+        }
+
+        private bool CanExecuteCut(object obj)
+        {
+            return this.SelectedBackupInfoViewModel != null;
+        }
+
+        private void ExecutePaste(object obj)
+        {
+            if (this.CanExecutePaste(obj))
+            {
+                if (this.clipboardService.DoesClipboardDataContain(Constants.BackupInfoClipboardFormat))
+                {
+                    var pasteInfo =
+                        this.clipboardService.GetData<BackupInfoPasteInfo>(Constants.BackupInfoClipboardFormat);
+                    if (pasteInfo != null)
+                    {
+                        IBackupInfo backupInfo = this.modelFactory.CreateBackupInfoFromBinary(
+                            pasteInfo.BackupInfoBytes,
+                            pasteInfo.PasteType == PasteType.Copy);
+
+                        if ((pasteInfo.PasteType == PasteType.Cut) &&
+                            (pasteInfo.SourceIndex < this.BackupInfoViewModels.Count))
+                        {
+                            IBackupInfoViewModel source = this.BackupInfoViewModels[pasteInfo.SourceIndex];
+                            if (source.IsCutReserved)
+                            {
+                                var targetIndexViewModelPair = new IndexBackupInfoViewModelPair(
+                                    pasteInfo.SourceIndex,
+                                    source);
+                                this.RemoveItem(targetIndexViewModelPair);
+                            }
+                        }
+
+                        int targetIndex = this.GetTargetItemIndex();
+                        this.InsertBackupInfo(backupInfo, targetIndex);
+                    }
+                }
+            }
+        }
+
+        private bool CanExecutePaste(object obj)
+        {
+            var supportedClipboardFormats = new string[] { Constants.BackupInfoClipboardFormat };
+
+            return supportedClipboardFormats.Any(p => this.clipboardService.DoesClipboardDataContain(p));
+        }
+
+        private void InsertBackupInfo(IBackupInfo backupInfo, int targetIndex)
+        {
+            if ((backupInfo == null) || (targetIndex < 0) || (targetIndex > this.BackupInfoViewModels.Count))
+            {
+                return;
+            }
+
+            IBackupInfoViewModel backupInfoViewModel = BackupInfoViewModel.CreateBackupInfoViewMode(
+                backupInfo,
+                this.ClearOutputMessage,
+                this.AddOutputMessage);
+            var targetIndexViewModelPair = new IndexBackupInfoViewModelPair(
+                    targetIndex,
+                    backupInfoViewModel);
+
+            var action = new Action<object>(context => this.InsertBackupInfo(context));
+            var undoAction = new Action<object>(context => this.RemoveInsertedBackupInfo(context));
+            this.undoRedoService.Commit(action, undoAction, targetIndexViewModelPair);
+        }
+
+        private void InsertBackupInfo(object context)
+        {
+            var indexViewModelPair = (IndexBackupInfoViewModelPair)context;
+            this.backupSettingService.InsertBackupInfo(
+                indexViewModelPair.Index,
+                indexViewModelPair.BackupInfoViewModel.GetBackupInfo());
+            this.BackupInfoViewModels.Insert(indexViewModelPair.Index, indexViewModelPair.BackupInfoViewModel);
+            if (this.FocusOnGridRow != null)
+            {
+                this.FocusOnGridRow(this, new FocusOnGridRowEventArgs(indexViewModelPair.Index));
+            }
+
+            this.SelectedBackupInfoViewModel = indexViewModelPair.BackupInfoViewModel;
+        }
+
+        private void RemoveInsertedBackupInfo(object context)
+        {
+            var indexViewModelPair = (IndexBackupInfoViewModelPair)context;
+            if (indexViewModelPair.Index < this.BackupInfoViewModels.Count)
+            {
+                var removingBackupInfoViewModel = this.BackupInfoViewModels[indexViewModelPair.Index];
+                this.backupSettingService.RemoveBackupInfo(removingBackupInfoViewModel.BackupInfoId);
+                this.BackupInfoViewModels.Remove(removingBackupInfoViewModel);
+
+                if (indexViewModelPair.Index < this.BackupInfoViewModels.Count)
+                {
+                    if (this.FocusOnGridRow != null)
+                    {
+                        this.FocusOnGridRow(this, new FocusOnGridRowEventArgs(indexViewModelPair.Index));
+                    }
+
+                    this.SelectedBackupInfoViewModel = this.BackupInfoViewModels[indexViewModelPair.Index];
+                }
+                else if (this.BackupInfoViewModels.Count != 0)
+                {
+                    if (this.FocusOnGridRow != null)
+                    {
+                        this.FocusOnGridRow(this, new FocusOnGridRowEventArgs(indexViewModelPair.Index - 1));
+                    }
+
+                    this.SelectedBackupInfoViewModel = this.BackupInfoViewModels[indexViewModelPair.Index - 1];
+                }
+            }
+        }
+
+        private void ExecuteUndo(object obj)
+        {
+            if (this.undoRedoService.CanExecuteUndo())
+            {
+                this.undoRedoService.Undo();
+            }
+        }
+
+        private bool CanExecuteUndo(object obj)
+        {
+            return (this.backupSettingService.CurrentSetting != null) &&
+                this.undoRedoService.CanExecuteUndo();
+        }
+
+        private void ExecuteRedo(object obj)
+        {
+            if (this.undoRedoService.CanExecuteRedo())
+            {
+                this.undoRedoService.Redo();
+            }
+        }
+
+        private bool CanExecuteRedo(object obj)
+        {
+            return (this.backupSettingService.CurrentSetting != null) && 
+                this.undoRedoService.CanExecuteRedo();
+        }
+
+        private void ExecuteRefresh(object obj)
+        {
+            this.ResetAllBackItemStates();
+            this.RestProgressBar();
+        }
+
+        private bool CanExecuteRefresh(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void ExecuteClearOutputWindow(object obj)
+        {
+            this.OutputMessage = string.Empty;
+        }
+
+        private bool CanExecuteClearOutputWindow(object obj)
+        {
+            return this.backupService.IsExecutingBackup == false;
+        }
+
+        private void OnBackupServiceNofityFileBackupProgress(object sender, FileBackupProgressEventArgs args)
+        {
+            this.ProgressViewModel.ProgressValue = args.ProgressValue;
+            if (args.LatestResultInfo != null)
+            {
+                this.OutputMessage = this.OutputMessage + "\r\n"
+                                     + string.Format(
+                                         "{0}: {1}",
+                                         args.LatestResultInfo.BackupState.Translate(),
+                                         args.LatestResultInfo.Description);
+            }
+        }
+
+        private void CommitEditingContents()
+        {
+            IBackupInfoViewModel[] editingViewModels =
+                    this.BackupInfoViewModels.Where(p => p.IsEditing).ToArray();
+
+            foreach (IBackupInfoViewModel backupInfoViewModel in editingViewModels)
+            {
+                backupInfoViewModel.CommitEditingContents();
+            }
+        }
+
+        private void UpdateWindowTitleAsModified(string backupSettingName)
+        {
+            this.WindowTitle = string.Format(
+                CultureInfo.InvariantCulture,
+                this.windowTitleFormat,
+                backupSettingName + "*");
+        }
+
+        private void ResetAllBackItemStates()
+        {
+            foreach (IBackupInfoViewModel backupInfoViewModel in this.BackupInfoViewModels)
+            {
+                backupInfoViewModel.ResetBackupState();
+            }
+        }
+
+        private void RestProgressBar()
+        {
+            this.ProgressViewModel.ProgressValue = 0;
+        }
+
+        private void ClearOutputMessage()
+        {
+            this.OutputMessage = string.Empty;
+        }
+
+        private void AddOutputMessage(string additionalMessage)
+        {
+            this.OutputMessage = this.OutputMessage + (additionalMessage ?? string.Empty) + "\r\n";
+        }
+
+        private int GetTargetItemIndex()
+        {
+            int currentIndex = -1;
+            if (this.SelectedBackupInfoViewModel != null)
+            {
+                currentIndex = this.BackupInfoViewModels.IndexOf(this.SelectedBackupInfoViewModel);
+            }
+            else
+            {
+                currentIndex = this.SelectedFirstCellItemIndex;
+            }
+
+            int targetIndex = (currentIndex != -1) ? currentIndex + 1 : this.BackupInfoViewModels.Count;
+
+            return targetIndex;
+        }
+
+        private void SetupZipEncodingItems()
+        {
+            var settingsService = ObjectContainer.Resolve<ISettingsService>();
+            if (string.IsNullOrEmpty(settingsService.DefaultZipEncodingKeyText))
+            {
+                settingsService.DefaultZipEncodingKeyText = "utf-8";
+            }
+
+            this.innerZipEncodings.Add(new EncodingInfoItemViewModel("shift_jis", "Japanese (Shift-JIS)"));
+            this.innerZipEncodings.Add(new EncodingInfoItemViewModel("utf-16", "Unicode"));
+            this.innerZipEncodings.Add(new EncodingInfoItemViewModel("utf-8", "Unicode (UTF-8)"));
+
+            EncodingInfoItemViewModel defaultEncodingItem =
+                this.innerZipEncodings.FirstOrDefault(
+                    p =>
+                    string.Equals(
+                        p.EncodingKeyName,
+                        settingsService.DefaultZipEncodingKeyText,
+                        StringComparison.OrdinalIgnoreCase));
+            if (defaultEncodingItem != null)
+            {
+                this.SelectedEncodingInfoItem = defaultEncodingItem;
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/ProgressViewModel.cs b/Main/SimpleBackup.ViewModels/ProgressViewModel.cs
new file mode 100644 (file)
index 0000000..8313e26
--- /dev/null
@@ -0,0 +1,56 @@
+//-----------------------------------------------------------------------
+// <copyright file="ProgressViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using SimpleBackup.Core.Utilities;
+
+    /// <summary>
+    /// The view model for reporting progress.
+    /// </summary>
+    internal class ProgressViewModel : PropertyChangeNotificationBase
+    {
+        /// <summary>
+        /// The progress value
+        /// </summary>
+        private double progressValue;
+
+        /// <summary>
+        /// Gets or sets the progress value.
+        /// </summary>
+        public double ProgressValue
+        {
+            get
+            {
+                return this.progressValue;
+            }
+
+            set
+            {
+                if (this.progressValue.Equals(value) == false)
+                {
+                    this.progressValue = value;
+                    this.NotifyPropertyChanged("ProgressValue");
+                }
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/SimpleBackup.ViewModels.csproj b/Main/SimpleBackup.ViewModels/SimpleBackup.ViewModels.csproj
new file mode 100644 (file)
index 0000000..8ffd7ca
--- /dev/null
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{70BC6544-A4C9-4325-9CE1-CC3F79787693}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SimpleBackup.ViewModels</RootNamespace>
+    <AssemblyName>SimpleBackup.ViewModels</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>SimpleBackupKey.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="PresentationCore" />
+    <Reference Include="PresentationFramework" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xaml" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+    <Reference Include="WindowsBase" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Properties\AssemblyInfo.cs">
+      <Link>Properties\AssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="BackupInfoPasteInfo.cs" />
+    <Compile Include="BackupInfoViewModel.cs" />
+    <Compile Include="DataGridColumnHeaderBaseViewModel.cs" />
+    <Compile Include="DestinationColumnHeaderViewModel.cs" />
+    <Compile Include="EncodingInfoItemViewModel.cs" />
+    <Compile Include="IndexBackupInfoViewModelPair.cs" />
+    <Compile Include="IsZipArchiveColumnHeaderViewModel.cs" />
+    <Compile Include="LabelColumnHeaderViewModel.cs" />
+    <Compile Include="MainWindowViewModel.cs" />
+    <Compile Include="ProgressViewModel.cs" />
+    <Compile Include="SourceColumnHeaderViewModel.cs" />
+    <Compile Include="ViewModelComponent.cs" />
+    <Compile Include="ViewModelFactory.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="SimpleBackupKey.snk" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\SimpleBackup.Core\SimpleBackup.Core.csproj">
+      <Project>{33f1d454-9962-4eb6-aad3-8d11d9a78d1f}</Project>
+      <Name>SimpleBackup.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\SimpleBackup.Resources\SimpleBackup.Resources.csproj">
+      <Project>{a655131e-d439-4de1-bc39-5c955306183f}</Project>
+      <Name>SimpleBackup.Resources</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PostBuildEvent>set EXE_BIN_DIR=$(ProjectDir)..\bin\$(ConfigurationName)\
+xcopy "$(TargetDir)$(TargetName).dll" "%25EXE_BIN_DIR%25" /Y
+if exist "$(TargetDir)$(TargetName).pdb" xcopy "$(TargetDir)$(TargetName).pdb" "%25EXE_BIN_DIR%25" /Y</PostBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Main/SimpleBackup.ViewModels/SimpleBackupKey.snk b/Main/SimpleBackup.ViewModels/SimpleBackupKey.snk
new file mode 100644 (file)
index 0000000..def2e6d
Binary files /dev/null and b/Main/SimpleBackup.ViewModels/SimpleBackupKey.snk differ
diff --git a/Main/SimpleBackup.ViewModels/SourceColumnHeaderViewModel.cs b/Main/SimpleBackup.ViewModels/SourceColumnHeaderViewModel.cs
new file mode 100644 (file)
index 0000000..cca8b35
--- /dev/null
@@ -0,0 +1,32 @@
+//-----------------------------------------------------------------------
+// <copyright file="SourceColumnHeaderViewModel.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using SimpleBackup.Core.ViewModels;
+
+    /// <summary>
+    /// The view model of source column header.
+    /// </summary>
+    internal class SourceColumnHeaderViewModel : DataGridColumnHeaderBaseViewModel, ISourceColumnHeaderViewModel
+    {
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/ViewModelComponent.cs b/Main/SimpleBackup.ViewModels/ViewModelComponent.cs
new file mode 100644 (file)
index 0000000..f2547b1
--- /dev/null
@@ -0,0 +1,41 @@
+//-----------------------------------------------------------------------
+// <copyright file="ViewModelComponent.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using SimpleBackup.Core;
+    using SimpleBackup.Core.AppInfrastructure;
+    using SimpleBackup.Core.ViewModels;
+
+    /// <summary>
+    /// The view model component.
+    /// </summary>
+    internal class ViewModelComponent : IAppComponent
+    {
+        /// <summary>
+        /// Initializes this application component.
+        /// </summary>
+        public void Initialize()
+        {
+            ObjectContainer.Register<IViewModelFactory>(new ViewModelFactory());
+        }
+    }
+}
diff --git a/Main/SimpleBackup.ViewModels/ViewModelFactory.cs b/Main/SimpleBackup.ViewModels/ViewModelFactory.cs
new file mode 100644 (file)
index 0000000..a54e0b3
--- /dev/null
@@ -0,0 +1,40 @@
+//-----------------------------------------------------------------------
+// <copyright file="ViewModelFactory.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.ViewModels
+{
+    using SimpleBackup.Core.ViewModels;
+
+    /// <summary>
+    /// The view model factory.
+    /// </summary>
+    internal class ViewModelFactory : IViewModelFactory
+    {
+        /// <summary>
+        /// Creates the main window view model.
+        /// </summary>
+        /// <returns>The main window view model.</returns>
+        public IMainWindowViewModel CreateMainWindowViewModel()
+        {
+            return MainWindowViewModel.CreateMainWindowViewModel();
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Views/BackupSourceTypeToImageConverter.cs b/Main/SimpleBackup.Views/BackupSourceTypeToImageConverter.cs
new file mode 100644 (file)
index 0000000..25bed54
--- /dev/null
@@ -0,0 +1,87 @@
+//-----------------------------------------------------------------------
+// <copyright file="BackupSourceTypeToImageConverter.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Views
+{
+    using System;
+    using System.Diagnostics;
+    using System.Windows.Controls;
+    using System.Windows.Data;
+    using System.Windows.Media.Imaging;
+    using SimpleBackup.Core.Models;
+
+    /// <summary>
+    /// A converter which converts BackupSourceType to Image.
+    /// </summary>
+    internal class BackupSourceTypeToImageConverter : IValueConverter
+    {
+        /// <summary>
+        /// Converts a value.
+        /// </summary>
+        /// <param name="value">The value produced by the binding source.</param>
+        /// <param name="targetType">The type of the binding target property.</param>
+        /// <param name="parameter">The converter parameter to use.</param>
+        /// <param name="culture">The culture to use in the converter.</param>
+        /// <returns>
+        /// A converted value. If the method returns null, the valid null value is used. 
+        /// </returns>
+        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        {
+            Uri imageSourceUri;
+            var backupState = (BackupSourceType)value;
+            switch (backupState)
+            {
+                case BackupSourceType.File:
+                    imageSourceUri = new Uri("pack://application:,,,/SimpleBackup.Resources;component/Images/document_32xLG.png", UriKind.Absolute);
+                    break;
+                case BackupSourceType.Folder:
+                    imageSourceUri = new Uri("pack://application:,,,/SimpleBackup.Resources;component/Images/FileGroup_10135_32x.png", UriKind.Absolute);
+                    break;
+                default:
+                    imageSourceUri = new Uri("pack://application:,,,/SimpleBackup.Resources;component/Images/document_32xLG.png", UriKind.Absolute);
+                    break;
+            }
+
+            var bitmapImage = new BitmapImage();
+            bitmapImage.BeginInit();
+            bitmapImage.UriSource = imageSourceUri;
+            bitmapImage.EndInit();
+
+            return new Image { Source = bitmapImage };
+        }
+
+        /// <summary>
+        /// Converts a value.
+        /// </summary>
+        /// <param name="value">The value that is produced by the binding target.</param>
+        /// <param name="targetType">The type to convert to.</param>
+        /// <param name="parameter">The converter parameter to use.</param>
+        /// <param name="culture">The culture to use in the converter.</param>
+        /// <returns>
+        /// A converted value. If the method returns null, the valid null value is used. 
+        /// </returns>
+        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        {
+            Debug.Assert(true, "ConvertBack is called.");
+            return new object();
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Views/BackupStateToImageConverter.cs b/Main/SimpleBackup.Views/BackupStateToImageConverter.cs
new file mode 100644 (file)
index 0000000..63c1f48
--- /dev/null
@@ -0,0 +1,99 @@
+//-----------------------------------------------------------------------
+// <copyright file="BackupStateToImageConverter.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Views
+{
+    using System;
+    using System.Diagnostics;
+    using System.Windows.Controls;
+    using System.Windows.Data;
+    using System.Windows.Media.Imaging;
+    using SimpleBackup.Core.Models;
+
+    /// <summary>
+    /// A converter which converts BackupState to Image.
+    /// </summary>
+    internal class BackupStateToImageConverter : IValueConverter
+    {
+        /// <summary>
+        /// Converts a value.
+        /// </summary>
+        /// <param name="value">The value produced by the binding source.</param>
+        /// <param name="targetType">The type of the binding target property.</param>
+        /// <param name="parameter">The converter parameter to use.</param>
+        /// <param name="culture">The culture to use in the converter.</param>
+        /// <returns>
+        /// A converted value. If the method returns null, the valid null value is used. 
+        /// </returns>
+        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        {
+            Uri imageSourceUri;
+            var backupState = (BackupState)value;
+            switch (backupState)
+            {
+                case BackupState.Todo:
+                    imageSourceUri = new Uri("pack://application:,,,/SimpleBackup.Resources;component/Images/flag_16xLG.png", UriKind.Absolute);
+                    break;
+                case BackupState.InProgress:
+                    imageSourceUri = new Uri("pack://application:,,,/SimpleBackup.Resources;component/Images/Activity_16xLG.png", UriKind.Absolute);
+                    break;
+                case BackupState.Success:
+                    imageSourceUri = new Uri("pack://application:,,,/SimpleBackup.Resources;component/Images/StatusAnnotations_Complete_and_ok_32xLG_color.png", UriKind.Absolute);
+                    break;
+                case BackupState.Failed:
+                    imageSourceUri = new Uri("pack://application:,,,/SimpleBackup.Resources;component/Images/StatusAnnotations_Critical_32xLG_color.png", UriKind.Absolute);
+                    break;
+                case BackupState.Cancelled:
+                    imageSourceUri = new Uri("pack://application:,,,/SimpleBackup.Resources;component/Images/Warning.png", UriKind.Absolute);
+                    break;
+                case BackupState.Skipped:
+                    imageSourceUri = new Uri("pack://application:,,,/SimpleBackup.Resources;component/Images/Warning.png", UriKind.Absolute);
+                    break;
+                default:
+                    imageSourceUri = new Uri("pack://application:,,,/SimpleBackup.Resources;component/Images/Remove_16xLG.png", UriKind.Absolute);
+                    break;
+            }
+
+            var bitmapImage = new BitmapImage();
+            bitmapImage.BeginInit();
+            bitmapImage.UriSource = imageSourceUri;
+            bitmapImage.EndInit();
+
+            return new Image { Source = bitmapImage };
+        }
+
+        /// <summary>
+        /// Converts a value.
+        /// </summary>
+        /// <param name="value">The value that is produced by the binding target.</param>
+        /// <param name="targetType">The type to convert to.</param>
+        /// <param name="parameter">The converter parameter to use.</param>
+        /// <param name="culture">The culture to use in the converter.</param>
+        /// <returns>
+        /// A converted value. If the method returns null, the valid null value is used. 
+        /// </returns>
+        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+        {
+            Debug.Assert(true, "ConvertBack is called.");
+            return new object();
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Views/ExDataGrid.cs b/Main/SimpleBackup.Views/ExDataGrid.cs
new file mode 100644 (file)
index 0000000..f998a76
--- /dev/null
@@ -0,0 +1,148 @@
+//-----------------------------------------------------------------------
+// <copyright file="ExDataGrid.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Views
+{
+    using System;
+    using System.Linq;
+    using System.Windows;
+    using System.Windows.Controls;
+    using SimpleBackup.Core.Views;
+
+    /// <summary>
+    /// An extended data grid control.
+    /// </summary>
+    internal class ExDataGrid : DataGrid
+    {
+        /// <summary>
+        /// The selected first cell item index property key
+        /// Read-Only Dependency Properties
+        /// http://msdn.microsoft.com/en-us/library/ms754044(v=vs.110).aspx
+        /// </summary>
+        public static readonly DependencyPropertyKey SelectedFirstCellItemIndexPropertyKey =
+            DependencyProperty.RegisterReadOnly(
+            "SelectedFirstCellItemIndex",
+            typeof(int),
+            typeof(ExDataGrid),
+            new PropertyMetadata(default(int)));
+
+        /// <summary>
+        /// The selected first cell item index property
+        /// </summary>
+        public static readonly DependencyProperty SelectedFirstCellItemIndexProperty =
+            SelectedFirstCellItemIndexPropertyKey.DependencyProperty;
+
+        /// <summary>
+        /// The selected first cell item property key
+        /// </summary>
+        public static readonly DependencyPropertyKey SelectedFirstCellItemPropertyKey =
+            DependencyProperty.RegisterReadOnly(
+            "SelectedFirstCellItem",
+            typeof(object),
+            typeof(ExDataGrid),
+            new PropertyMetadata(default(object)));
+
+        /// <summary>
+        /// The selected first cell item property
+        /// </summary>
+        public static readonly DependencyProperty SelectedFirstCellItemProperty =
+            SelectedFirstCellItemPropertyKey.DependencyProperty;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ExDataGrid"/> class.
+        /// </summary>
+        public ExDataGrid()
+        {
+            this.Loaded += (sender, args) =>
+                {
+                    if (this.SelectedFirstCellItemChanged != null)
+                    {
+                        if (this.Items.Count != 0)
+                        {
+                            this.SelectedFirstCellItemChanged(
+                                this,
+                                new ExDataGridSelectedFirstCellItemChangedEventArgs(
+                                    0,
+                                    this.Items[0]));
+                        }
+                    }
+                };
+        }
+
+        public event EventHandler<ExDataGridSelectedFirstCellItemChangedEventArgs> SelectedFirstCellItemChanged;
+
+        /// <summary>
+        /// Gets the index of the selected first cell item.
+        /// </summary>
+        public int SelectedFirstCellItemIndex
+        {
+            get
+            {
+                return (int)this.GetValue(SelectedFirstCellItemIndexProperty);
+            }
+        }
+
+        /// <summary>
+        /// Gets the selected first cell item.
+        /// </summary>
+        public object SelectedFirstCellItem
+        {
+            get
+            {
+                return (object)this.GetValue(SelectedFirstCellItemProperty);
+            }
+        }
+
+        protected override void OnSelectedCellsChanged(SelectedCellsChangedEventArgs e)
+        {
+            base.OnSelectedCellsChanged(e);
+
+            int firstIndex = int.MaxValue;
+            object firstIndexItem = null;
+
+            DataGridCellInfo[] validCellInfos = this.SelectedCells.Where(p => p.IsValid).ToArray();
+            foreach (DataGridCellInfo cellInfo in validCellInfos)
+            {
+                int index = this.Items.IndexOf(cellInfo.Item);
+                if (index < firstIndex)
+                {
+                    firstIndex = index;
+                    firstIndexItem = cellInfo.Item;
+                }                
+            }
+
+            if (this.SelectedFirstCellItemIndex != firstIndex)
+            {
+                this.SetValue(SelectedFirstCellItemIndexPropertyKey, firstIndex);
+                this.SetValue(SelectedFirstCellItemPropertyKey, firstIndexItem);
+
+                if (this.SelectedFirstCellItemChanged != null)
+                {
+                    this.SelectedFirstCellItemChanged(
+                        this,
+                        new ExDataGridSelectedFirstCellItemChangedEventArgs(
+                            firstIndex,
+                            firstIndexItem));
+                }
+            }
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Views/ExDataGridSelectedFirstCellItemBehavior.cs b/Main/SimpleBackup.Views/ExDataGridSelectedFirstCellItemBehavior.cs
new file mode 100644 (file)
index 0000000..b1a6b79
--- /dev/null
@@ -0,0 +1,102 @@
+//-----------------------------------------------------------------------
+// <copyright file="ExDataGridSelectedFirstCellItemBehavior.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Views
+{
+    using System.Windows;
+    using System.Windows.Interactivity;
+    using SimpleBackup.Core.Views;
+
+    /// <summary>
+    /// Behavior for ExDataGrid's SelectedFirstCellItemIndex and SelectedFirstCellItem read-only dependency properties.
+    /// </summary>
+    internal class ExDataGridSelectedFirstCellItemBehavior : Behavior<ExDataGrid>
+    {
+        /// <summary>
+        /// The selected first cell item index property.
+        /// This wraps ExDataGrid's SelectedFirstCellItemIndex read-only dependency property.
+        /// </summary>
+        public static readonly DependencyProperty SelectedFirstCellItemIndexProperty =
+            DependencyProperty.Register(
+            "SelectedFirstCellItemIndex",
+            typeof(int),
+            typeof(ExDataGridSelectedFirstCellItemBehavior),
+            new PropertyMetadata(default(int)));
+
+        /// <summary>
+        /// The selected first cell item property.
+        /// This wraps ExDataGrid's SelectedFirstCellItem read-only dependency property.
+        /// </summary>
+        public static readonly DependencyProperty SelectedFirstCellItemProperty =
+            DependencyProperty.Register(
+            "SelectedFirstCellItem",
+            typeof(object),
+            typeof(ExDataGridSelectedFirstCellItemBehavior),
+            new PropertyMetadata(default(object)));
+
+        /// <summary>
+        /// Gets or sets the index of the selected first cell item.
+        /// </summary>
+        public int SelectedFirstCellItemIndex
+        {
+            get { return (int)this.GetValue(SelectedFirstCellItemIndexProperty); }
+            set { this.SetValue(SelectedFirstCellItemIndexProperty, value); }
+        }
+
+        /// <summary>
+        /// Gets or sets the selected first cell item.
+        /// </summary>
+        public object SelectedFirstCellItem
+        {
+            get { return (object)this.GetValue(SelectedFirstCellItemProperty); }
+            set { this.SetValue(SelectedFirstCellItemProperty, value); }
+        }
+
+        /// <summary>
+        /// Called after the behavior is attached to an AssociatedObject.
+        /// </summary>
+        protected override void OnAttached()
+        {
+            base.OnAttached();
+            this.AssociatedObject.SelectedFirstCellItemChanged += this.OnExDataGridSelectedFirstCellItemChanged;
+        }
+
+        /// <summary>
+        /// Called when the behavior is being detached from its AssociatedObject, but before it has actually occurred.
+        /// </summary>
+        protected override void OnDetaching()
+        {
+            base.OnDetaching();
+            this.AssociatedObject.SelectedFirstCellItemChanged -= this.OnExDataGridSelectedFirstCellItemChanged;
+        }
+
+        /// <summary>
+        /// Called when ExDataGrid's SelectedFirstCellItemChanged event is published.
+        /// </summary>
+        /// <param name="sender">The sender.</param>
+        /// <param name="e">The <see cref="ExDataGridSelectedFirstCellItemChangedEventArgs"/> instance containing the event data.</param>
+        private void OnExDataGridSelectedFirstCellItemChanged(object sender, ExDataGridSelectedFirstCellItemChangedEventArgs e)
+        {
+            this.SelectedFirstCellItemIndex = e.SelectedFirstCellItemIndex;
+            this.SelectedFirstCellItem = e.SelectedFirstCellItem;
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Views/FileFolderDialog.cs b/Main/SimpleBackup.Views/FileFolderDialog.cs
new file mode 100644 (file)
index 0000000..c605a9b
--- /dev/null
@@ -0,0 +1,157 @@
+//-----------------------------------------------------------------------
+// <copyright file="FileFolderDialog.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Views
+{
+    using System;
+    using System.IO;
+    using System.Text;
+    using System.Windows.Forms;
+    using SimpleBackup.Core.Views;
+
+    /// <summary>
+    /// File folder dialog.
+    /// </summary>
+    internal class FileFolderDialog : CommonDialog, IFileFolderDialog
+    {
+        /// <summary>
+        /// The inner open file dialog
+        /// </summary>
+        private readonly OpenFileDialog innerOpenFileDialog = new OpenFileDialog();
+
+        /// <summary>
+        /// Gets or sets the selected path.
+        /// </summary>
+        public string SelectedPath
+        {
+            get
+            {
+                if ((string.IsNullOrEmpty(this.innerOpenFileDialog.FileName) == false) &&
+                    (this.innerOpenFileDialog.FileName.EndsWith("Folder Selection.") || (File.Exists(this.innerOpenFileDialog.FileName) == false)) &&
+                    (Directory.Exists(this.innerOpenFileDialog.FileName) == false))
+                {
+                    return Path.GetDirectoryName(this.innerOpenFileDialog.FileName);
+                }
+
+                return this.innerOpenFileDialog.FileName;
+            }
+
+            set
+            {
+                if (string.IsNullOrEmpty(value) == false)
+                {
+                    this.innerOpenFileDialog.FileName = value;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets the selected paths as semi-colon seprated string.
+        /// </summary>
+        public string SelectedPaths
+        {
+            get
+            {
+                if ((this.innerOpenFileDialog.FileNames != null) && (this.innerOpenFileDialog.FileNames.Length > 1))
+                {
+                    var sb = new StringBuilder();
+                    foreach (string fileName in this.innerOpenFileDialog.FileNames)
+                    {
+                        if (File.Exists(fileName))
+                        {
+                            sb.Append(fileName + ";");
+                        }
+                    }
+
+                    return sb.ToString();
+                }
+
+                return null;
+            }
+        }
+
+        /// <summary>
+        /// Runs a common dialog box with a default owner.
+        /// </summary>
+        /// <returns>
+        /// <see cref="F:System.Windows.Forms.DialogResult.OK" /> if the user clicks OK in the dialog box; otherwise, <see cref="F:System.Windows.Forms.DialogResult.Cancel" />.
+        /// </returns>
+        /// <PermissionSet>
+        ///   <IPermission class="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
+        ///   <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
+        ///   <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="UnmanagedCode, ControlEvidence" />
+        ///   <IPermission class="System.Diagnostics.PerformanceCounterPermission, System, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true" />
+        /// </PermissionSet>
+        public new DialogResult ShowDialog()
+        {
+            return this.ShowDialog(null);
+        }
+
+        /// <summary>
+        /// Runs a common dialog box with the specified owner.
+        /// </summary>
+        /// <param name="owner">Any object that implements <see cref="T:System.Windows.Forms.IWin32Window" /> that represents the top-level window that will own the modal dialog box.</param>
+        /// <returns>
+        /// <see cref="F:System.Windows.Forms.DialogResult.OK" /> if the user clicks OK in the dialog box; otherwise, <see cref="F:System.Windows.Forms.DialogResult.Cancel" />.
+        /// </returns>
+        public new DialogResult ShowDialog(IWin32Window owner)
+        {
+            this.innerOpenFileDialog.ValidateNames = false;
+            this.innerOpenFileDialog.CheckFileExists = false;
+            this.innerOpenFileDialog.CheckPathExists = true;
+
+            // Set initial directory (used when dialog.FileName is set from outside)
+            if (string.IsNullOrEmpty(this.innerOpenFileDialog.FileName) == false)
+            {
+                this.innerOpenFileDialog.InitialDirectory = Directory.Exists(this.innerOpenFileDialog.FileName)
+                    ? this.innerOpenFileDialog.FileName
+                    : Path.GetDirectoryName(this.innerOpenFileDialog.FileName);
+            }
+
+            // Always default to Folder Selection.
+            this.innerOpenFileDialog.FileName = "Folder Selection.";
+
+            return (owner == null)
+                ? this.innerOpenFileDialog.ShowDialog()
+                : this.innerOpenFileDialog.ShowDialog(owner);
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, resets the properties of a common dialog box to their default values.
+        /// </summary>
+        public override void Reset()
+        {
+            this.innerOpenFileDialog.Reset();
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, specifies a common dialog box.
+        /// </summary>
+        /// <param name="hwndOwner">A value that represents the window handle of the owner window for the common dialog box. </param>
+        /// <returns>
+        /// <c>true</c> if the dialog box was successfully run; otherwise, <c>false</c>.
+        /// </returns>
+        protected override bool RunDialog(IntPtr hwndOwner)
+        {
+            return true;
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Views/MainWindow.xaml b/Main/SimpleBackup.Views/MainWindow.xaml
new file mode 100644 (file)
index 0000000..2f4922c
--- /dev/null
@@ -0,0 +1,553 @@
+<!--
+This file is part of Simple Backup.
+
+Simple Backup is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Simple Backup is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<Window x:Class="SimpleBackup.Views.MainWindow"
+        x:ClassModifier="internal"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
+        xmlns:resources="clr-namespace:SimpleBackup.Resources;assembly=SimpleBackup.Resources"
+        xmlns:views1="clr-namespace:SimpleBackup.Views"
+        x:Name="RootWindow"
+        Title="{Binding WindowTitle}" Height="400" Width="800" MinHeight="200" MinWidth="400"
+        PreviewKeyDown="OnMainWindowPreviewKeyDown"
+        Icon="pack://application:,,,/SimpleBackup.Resources;component/Images/ApplicationIcon.ico">
+    <Window.Resources>
+        <views1:BackupStateToImageConverter x:Key="BackupStateToImageConverter"/>
+        <views1:BackupSourceTypeToImageConverter x:Key="BackupSourceTypeToImageConverter"/>
+        <Style x:Key="ToolBarButtonStyle" TargetType="{x:Type Button}">
+            <Setter Property="FocusVisualStyle">
+                <Setter.Value>
+                    <Style>
+                        <Setter Property="Control.Template">
+                            <Setter.Value>
+                                <ControlTemplate>
+                                    <Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="1" StrokeDashArray="1 2"/>
+                                </ControlTemplate>
+                            </Setter.Value>
+                        </Setter>
+                    </Style>
+                </Setter.Value>
+            </Setter>
+            <Setter Property="Background" Value="#FFDDDDDD"/>
+            <Setter Property="BorderBrush" Value="#FF707070"/>
+            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
+            <Setter Property="BorderThickness" Value="1"/>
+            <Setter Property="HorizontalContentAlignment" Value="Center"/>
+            <Setter Property="VerticalContentAlignment" Value="Center"/>
+            <Setter Property="Padding" Value="1"/>
+            <Setter Property="Height" Value="20"/>
+            <Setter Property="Width" Value="20"/>
+            <Setter Property="ToolTipService.ShowOnDisabled" Value="True"/>
+            <Setter Property="Template">
+                <Setter.Value>
+                    <ControlTemplate TargetType="{x:Type Button}">
+                        <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
+                            <Grid>
+                                <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
+                                <Rectangle x:Name="disablingRectangle" Visibility="Collapsed">
+                                    <Rectangle.Fill>
+                                        <SolidColorBrush Color="White" Opacity="0.5"/>
+                                    </Rectangle.Fill>
+                                </Rectangle>
+                            </Grid>
+                        </Border>
+                        <ControlTemplate.Triggers>
+                            <Trigger Property="IsDefaulted" Value="True">
+                                <Setter Property="BorderBrush" TargetName="border" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
+                            </Trigger>
+                            <Trigger Property="IsMouseOver" Value="True">
+                                <Setter Property="Background" TargetName="border" Value="#FFBEE6FD"/>
+                                <Setter Property="BorderBrush" TargetName="border" Value="#FF3C7FB1"/>
+                            </Trigger>
+                            <Trigger Property="IsPressed" Value="True">
+                                <Setter Property="Background" TargetName="border" Value="#FFC4E5F6"/>
+                                <Setter Property="BorderBrush" TargetName="border" Value="#FF2C628B"/>
+                            </Trigger>
+                            <Trigger Property="ToggleButton.IsChecked" Value="True">
+                                <Setter Property="Background" TargetName="border" Value="#FFBCDDEE"/>
+                                <Setter Property="BorderBrush" TargetName="border" Value="#FF245A83"/>
+                            </Trigger>
+                            <Trigger Property="IsEnabled" Value="False">
+                                <Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
+                                <Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
+                                <Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
+                                <Setter Property="Visibility" TargetName="disablingRectangle" Value="Visible"/>
+                            </Trigger>
+                        </ControlTemplate.Triggers>
+                    </ControlTemplate>
+                </Setter.Value>
+            </Setter>
+        </Style>
+    </Window.Resources>
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="20"/>
+            <RowDefinition Height="3*" MinHeight="60"/>
+            <RowDefinition Height="5"/>
+            <RowDefinition Height="*" MinHeight="20"/>
+            <RowDefinition Height="20"/>
+        </Grid.RowDefinitions>
+        <Menu Grid.Row="0">
+            <MenuItem resources:ResourceHelper.ResourceId="Views_MainMenu_File"
+                      Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}">
+                <MenuItem Command="{Binding CreateNewBackupSettingRelayCommand}"
+                          resources:ResourceHelper.ResourceId="Views_MainMenu_New"
+                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                <MenuItem Command="{Binding OpenBackupSettingRelayCommand}"
+                          resources:ResourceHelper.ResourceId="Views_MainMenu_Open"
+                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                <MenuItem Command="{Binding SaveBackupSettingRelayCommand}"
+                          resources:ResourceHelper.ResourceId="Views_MainMenu_Save"
+                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                          InputGestureText="Ctrl+S"/>
+                <MenuItem Command="{Binding SaveAsBackupSettingRelayCommand}"
+                          resources:ResourceHelper.ResourceId="Views_MainMenu_SaveAs"
+                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                <MenuItem Command="{Binding CloseBackupSettingRelayCommand}"
+                          resources:ResourceHelper.ResourceId="Views_MainMenu_Close"
+                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                <Separator/>
+                <MenuItem Command="{Binding OpenCurrentSettingFileLocationRelayCommand}"
+                          resources:ResourceHelper.ResourceId="Views_MainMenu_OpenCurrentSettingFileLocation"
+                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                <Separator/>
+                <MenuItem Command="{Binding ExitRelayCommand}"
+                          resources:ResourceHelper.ResourceId="Views_MainMenu_Exit"
+                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+            </MenuItem>
+            <MenuItem resources:ResourceHelper.ResourceId="Views_MainMenu_Help"
+                      Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}">
+                <MenuItem Command="{Binding ShowHelpRelayCommand}"
+                          resources:ResourceHelper.ResourceId="Views_MainMenu_ShowHelp"
+                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                <Separator/>
+                <MenuItem Command="{Binding ShowVersionInformationRelayCommand}"
+                          resources:ResourceHelper.ResourceId="Views_MainMenu_ShowVersionInformation"
+                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+            </MenuItem>
+        </Menu>
+        <Grid Grid.Row="1">
+            <Grid.RowDefinitions>
+                <RowDefinition Height="23"/>
+                <RowDefinition Height="*"/>
+            </Grid.RowDefinitions>
+            <StackPanel Orientation="Horizontal">
+                <ToolBarTray>
+                    <ToolBar>
+                        <!-- Icon images are from VS203 Image Library http://www.microsoft.com/en-us/download/confirmation.aspx?id=35825 -->
+                        <Button Command="{Binding CreateNewBackupSettingRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_NewFileButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/NewFile_6276.png"/>
+                        </Button>
+                        <Button Command="{Binding OpenBackupSettingRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_OpenBackupSettingButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/Open_6529.png"/>
+                        </Button>
+                        <Button Command="{Binding SaveBackupSettingRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_SaveBackupSettingButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/save_16xLG.png"/>
+                        </Button>
+                        <Separator/>
+                        <Button Command="{Binding BackUpRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_MultipleBackupButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/arrow_all_run_16xLG.png"/>
+                        </Button>
+                        <Button Command="{Binding BackupCancelRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_CancelMultiBackupButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/action_Cancel_16xLG.png"/>
+                        </Button>
+                        <Separator/>
+                        <Button Command="{Binding SingleBackupRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_SingleBackupButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/arrow_run_16xLG.png"/>
+                        </Button>
+                        <Separator/>
+                        <Button Command="{Binding AddItemRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_AddButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/AddVariable_5541.png"/>
+                        </Button>
+                        <Button Command="{Binding RemoveItemRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_RemoveButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/Delete_black_32x32.png" Width="16" Height="16"/>
+                        </Button>
+                        <Separator/>
+                        <Button Command="{Binding MoveUpItemRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_MoveUpButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/arrow_Up_16xLG.png"/>
+                        </Button>
+                        <Button Command="{Binding MoveDownItemRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_MoveDownButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/arrow_Down_16xLG.png"/>
+                        </Button>
+                        <Separator/>
+                        <Button Command="{Binding CopyRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_CopyButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/Copy_6524.png"/>
+                        </Button>
+                        <Button Command="{Binding CutRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_CutButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/Cut_6523.png"/>
+                        </Button>
+                        <Button Command="{Binding PasteRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_PasteButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/Paste_6520.png"/>
+                        </Button>
+                        <Button Command="{Binding UndoRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_UndoButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/Arrow_UndoRevertRestore_16xLG.png"/>
+                        </Button>
+                        <Button Command="{Binding RedoRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_RedoButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/Arrow_RedoRetry_16xLG.png"/>
+                        </Button>
+                        <Separator/>
+                        <Button Command="{Binding RefreshRelayCommand}"
+                                resources:ResourceHelper.ResourceId="Views_RefreshButtonToolTipText"
+                                ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"
+                                Style="{DynamicResource ToolBarButtonStyle}">
+                            <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/refresh_16xLG.png"/>
+                        </Button>
+                        <Separator/>
+                        <TextBlock resources:ResourceHelper.ResourceId="Views_ZipEncodingTitleText"
+                                   Text="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                        <ComboBox IsEditable="False" MinWidth="80" Margin="5,0,0,0"
+                                  ItemsSource="{Binding ZipEncodings}" SelectionChanged="OnZipEncodingSelectionChanged"
+                                  SelectedItem="{Binding SelectedEncodingInfoItem}"
+                                  DisplayMemberPath="EncodingDisplayName"/>
+                    </ToolBar>
+                </ToolBarTray>
+            </StackPanel>
+            <views1:ExDataGrid x:Name="BackupInfoDataGrid"
+                      Grid.Row="1" ItemsSource="{Binding BackupInfoViewModels}" AlternatingRowBackground="AliceBlue" AlternationCount="2" AutoGenerateColumns="False"
+                      MouseDoubleClick="OnDataGridMouseDoubleClick"
+                      SelectedItem="{Binding SelectedBackupInfoViewModel, Mode=TwoWay}"
+                      SelectionMode="Extended"
+                      SelectionUnit="CellOrRowHeader"
+                      RowHeaderWidth="20">
+                <views1:ExDataGrid.Resources>
+                    <Style TargetType="{x:Type DataGridRow}">
+                        <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
+                        <Setter Property="SnapsToDevicePixels" Value="True"/>
+                        <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
+                        <Setter Property="ValidationErrorTemplate">
+                            <Setter.Value>
+                                <ControlTemplate>
+                                    <TextBlock Foreground="Red" Margin="2,0,0,0" Text="!" VerticalAlignment="Center"><Run Text="!"/></TextBlock>
+                                </ControlTemplate>
+                            </Setter.Value>
+                        </Setter>
+                        <Setter Property="Template">
+                            <Setter.Value>
+                                <ControlTemplate TargetType="{x:Type DataGridRow}">
+                                    <Grid>
+                                        <Border x:Name="DGR_Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
+                                            <SelectiveScrollingGrid>
+                                                <SelectiveScrollingGrid.ColumnDefinitions>
+                                                    <ColumnDefinition Width="Auto"/>
+                                                    <ColumnDefinition Width="*"/>
+                                                </SelectiveScrollingGrid.ColumnDefinitions>
+                                                <SelectiveScrollingGrid.RowDefinitions>
+                                                    <RowDefinition Height="*"/>
+                                                    <RowDefinition Height="Auto"/>
+                                                </SelectiveScrollingGrid.RowDefinitions>
+                                                <DataGridCellsPresenter Grid.Column="1" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
+                                                <DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" Visibility="{TemplateBinding DetailsVisibility}">
+                                                    <SelectiveScrollingGrid.SelectiveScrollingOrientation>
+                                                        <Binding Path="AreRowDetailsFrozen" RelativeSource="{RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}">
+                                                            <Binding.ConverterParameter>
+                                                                <SelectiveScrollingOrientation>Vertical</SelectiveScrollingOrientation>
+                                                            </Binding.ConverterParameter>
+                                                        </Binding>
+                                                    </SelectiveScrollingGrid.SelectiveScrollingOrientation>
+                                                </DataGridDetailsPresenter>
+                                                <DataGridRowHeader Grid.RowSpan="2" SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical">
+                                                    <DataGridRowHeader.Visibility>
+                                                        <Binding Path="HeadersVisibility" RelativeSource="{RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}">
+                                                            <Binding.ConverterParameter>
+                                                                <DataGridHeadersVisibility>Row</DataGridHeadersVisibility>
+                                                            </Binding.ConverterParameter>
+                                                        </Binding>
+                                                    </DataGridRowHeader.Visibility>
+                                                </DataGridRowHeader>
+                                            </SelectiveScrollingGrid>
+                                        </Border>
+                                        <Rectangle x:Name="CutReservingRectangle" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" Fill="Transparent"
+                                                   Stroke="Coral" StrokeThickness="2" StrokeDashArray="2 2" Visibility="Collapsed"
+                                                   IsHitTestVisible="False"/>
+                                    </Grid>
+                                    <ControlTemplate.Triggers>
+                                        <DataTrigger Binding="{Binding IsCutReserved}" Value="True">
+                                            <Setter TargetName="CutReservingRectangle" Property="Visibility" Value="Visible"/>
+                                        </DataTrigger>
+                                    </ControlTemplate.Triggers>
+                                </ControlTemplate>
+                            </Setter.Value>
+                        </Setter>
+                        <Style.Triggers>
+                            <Trigger Property="IsNewItem" Value="True">
+                                <Setter Property="Margin" Value="{Binding NewItemMargin, RelativeSource={RelativeSource FindAncestor, AncestorLevel=1, AncestorType={x:Type DataGrid}}}"/>
+                            </Trigger>
+                        </Style.Triggers>
+                    </Style>
+                </views1:ExDataGrid.Resources>
+                <!-- Using behaviours to bind to read-only properties in MVVM -->
+                <!-- http://blog.magnusmontin.net/2014/01/30/wpf-using-behaviours-to-bind-to-readonly-properties-in-mvvm/ -->
+                <i:Interaction.Behaviors>
+                    <views1:ExDataGridSelectedFirstCellItemBehavior
+                        SelectedFirstCellItemIndex="{Binding SelectedFirstCellItemIndex, Mode=OneWayToSource}"
+                        SelectedFirstCellItem="{Binding SelectedFirstCellItem, Mode=OneWayToSource}"/>
+                </i:Interaction.Behaviors>
+                <DataGrid.Columns>
+                    <!-- Backup State Column -->
+                    <DataGridTemplateColumn>
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <ContentControl Width="16" Height="16" Content="{Binding BackupState, Mode=OneWay, Converter={StaticResource BackupStateToImageConverter}}"/>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                    </DataGridTemplateColumn>
+                    <!-- IsEnabled Column -->
+                    <DataGridTemplateColumn>
+                        <DataGridTemplateColumn.HeaderTemplate>
+                            <DataTemplate>
+                                <Image Source="pack://application:,,,/SimpleBackup.Resources;component/Images/arrow_all_run_16xLG.png"/>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.HeaderTemplate>
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <CheckBox IsChecked="{Binding IsEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+                                            HorizontalAlignment="Center"
+                                            PreviewKeyDown="OnCellContentPreviewKeyDown"/>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                    </DataGridTemplateColumn>
+                    <!-- IsZipArchive Column -->
+                    <DataGridTemplateColumn>
+                        <DataGridTemplateColumn.Header>
+                            <ContentPresenter Content="{Binding DataContext.IsZipArchiveColumnHeaderViewModel,
+                                                                RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
+                        </DataGridTemplateColumn.Header>
+                        <DataGridTemplateColumn.HeaderTemplate>
+                            <DataTemplate>
+                                <TextBlock Text="{Binding Content.Header}"/>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.HeaderTemplate>
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <CheckBox IsChecked="{Binding IsZipArchive, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+                                          HorizontalAlignment="Center"
+                                          PreviewKeyDown="OnCellContentPreviewKeyDown"/>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                    </DataGridTemplateColumn>
+                    <!-- Label Column -->
+                    <DataGridTemplateColumn>
+                        <!-- Binding of DataGrid Column Header -->
+                        <!-- http://social.technet.microsoft.com/wiki/contents/articles/22012.binding-of-datagrid-column-header.aspx -->
+                        <DataGridTemplateColumn.Header>
+                            <ContentPresenter Content="{Binding DataContext.LabelColumnHeaderViewModel,
+                                                                RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
+                        </DataGridTemplateColumn.Header>
+                        <DataGridTemplateColumn.HeaderTemplate>
+                            <DataTemplate>
+                                <TextBlock Text="{Binding Content.Header}"/>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.HeaderTemplate>
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <TextBox Text="{Binding Label, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
+                                            PreviewKeyDown="OnCellContentPreviewKeyDown"/>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                    </DataGridTemplateColumn>
+                    <!-- Backup Source Type Column -->
+                    <DataGridTemplateColumn>
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <ContentControl Width="16" Height="16" Content="{Binding SourceType, Mode=OneWay, Converter={StaticResource BackupSourceTypeToImageConverter}}"/>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                    </DataGridTemplateColumn>
+                    <!-- SourcePath Column -->
+                    <DataGridTemplateColumn Width="300">
+                        <!-- Binding of DataGrid Column Header -->
+                        <!-- http://social.technet.microsoft.com/wiki/contents/articles/22012.binding-of-datagrid-column-header.aspx -->
+                        <DataGridTemplateColumn.Header>
+                            <ContentPresenter Content="{Binding DataContext.SourceColumnHeaderViewModel,
+                                                                RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
+                        </DataGridTemplateColumn.Header>
+                        <DataGridTemplateColumn.HeaderTemplate>
+                            <DataTemplate>
+                                <TextBlock Text="{Binding Content.Header}"/>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.HeaderTemplate>
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <Grid>
+                                    <TextBlock x:Name="SourceTextBlock" Text="{Binding DisplaySourcePath, Mode=OneWay}" ToolTip="{Binding SourceToolTipText}">
+                                        <TextBlock.ContextMenu>
+                                            <ContextMenu>
+                                                <MenuItem Command="{Binding SingleBackupRelayCommand}"
+                                                          resources:ResourceHelper.ResourceId="Views_ContextMenu_Backup"
+                                                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                                                <Separator/>
+                                                <MenuItem Command="{Binding OpenSourceFileRelayCommand}"
+                                                          resources:ResourceHelper.ResourceId="Views_ContextMenu_OpenFile"
+                                                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                                                <MenuItem Command="{Binding OpenSourceFolderRelayCommand}"
+                                                          resources:ResourceHelper.ResourceId="Views_ContextMenu_OpenSourceFolder"
+                                                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                                                <Separator/>
+                                                <MenuItem Command="{Binding SelectSourceRelayCommand}"
+                                                          resources:ResourceHelper.ResourceId="Views_ContextMenu_SelectSource"
+                                                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                                                <MenuItem Command="{Binding EditSourceRelayCommand}"
+                                                          resources:ResourceHelper.ResourceId="Views_ContextMenu_Edit"
+                                                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                                            </ContextMenu>
+                                        </TextBlock.ContextMenu>
+                                        <TextBlock.Style>
+                                            <Style TargetType="TextBlock">
+                                                <Style.Triggers>
+                                                    <DataTrigger Binding="{Binding HasSourcePathError}" Value="true">
+                                                        <Setter Property="Foreground" Value="Red"/>
+                                                    </DataTrigger>
+                                                </Style.Triggers>
+                                            </Style>
+                                        </TextBlock.Style>
+                                    </TextBlock>
+                                    <TextBox x:Name="SourceTextBox" Text="{Binding EditingSourcePath, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
+                                             Visibility="Collapsed" PreviewKeyDown="OnCellContentPreviewKeyDown"/>
+                                </Grid>
+
+                                <!-- DataTemplate.Triggers-->
+                                <!-- http://msdn.microsoft.com/ja-jp/library/system.windows.datatemplate.triggers%28v=vs.110%29.aspx -->
+                                <DataTemplate.Triggers>
+                                    <DataTrigger Binding="{Binding IsSourceEditing}" Value="True">
+                                        <Setter TargetName="SourceTextBlock" Property="Visibility" Value="Collapsed"/>
+                                        <Setter TargetName="SourceTextBox" Property="Visibility" Value="Visible"/>
+                                    </DataTrigger>
+                                </DataTemplate.Triggers>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                    </DataGridTemplateColumn>
+                    <!-- DestinationFolderPath Column -->
+                    <DataGridTemplateColumn Width="300">
+                        <DataGridTemplateColumn.Header>
+                            <ContentPresenter Content="{Binding DataContext.DestinationColumnHeaderViewModel,
+                                                                RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
+                        </DataGridTemplateColumn.Header>
+                        <DataGridTemplateColumn.HeaderTemplate>
+                            <DataTemplate>
+                                <TextBlock Text="{Binding Content.Header}"/>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.HeaderTemplate>
+                        <DataGridTemplateColumn.CellTemplate>
+                            <DataTemplate>
+                                <Grid>
+                                    <TextBlock x:Name="DestinationTextBlock" Text="{Binding DisplayDestinationFolderPath, Mode=OneWay}" ToolTip="{Binding DestinationToolTipText}">
+                                        <TextBlock.ContextMenu>
+                                            <ContextMenu>
+                                                <MenuItem Command="{Binding SingleBackupRelayCommand}"
+                                                          resources:ResourceHelper.ResourceId="Views_ContextMenu_Backup"
+                                                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                                                <Separator/>
+                                                <MenuItem Command="{Binding OpenDestinationFolderRelayCommand}"
+                                                          resources:ResourceHelper.ResourceId="Views_ContextMenu_OpenDestination"
+                                                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                                                <Separator/>
+                                                <MenuItem Command="{Binding SelectDestinationRelayCommand}"
+                                                          resources:ResourceHelper.ResourceId="Views_ContextMenu_SelectDestination"
+                                                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                                                <MenuItem Command="{Binding EditDestinationRelayCommand}"
+                                                          resources:ResourceHelper.ResourceId="Views_ContextMenu_Edit"
+                                                          Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                                            </ContextMenu>
+                                        </TextBlock.ContextMenu>
+                                        <TextBlock.Style>
+                                            <Style TargetType="TextBlock">
+                                                <Style.Triggers>
+                                                    <DataTrigger Binding="{Binding HasDestinationFolderPathError}" Value="true">
+                                                        <Setter Property="Foreground" Value="Red"/>
+                                                    </DataTrigger>
+                                                </Style.Triggers>
+                                            </Style>
+                                        </TextBlock.Style>
+                                    </TextBlock>
+                                    <TextBox x:Name="DestinationTextBox" Text="{Binding EditingDestinationPath, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"
+                                             Visibility="Collapsed" PreviewKeyDown="OnCellContentPreviewKeyDown"/>
+                                </Grid>
+                                <DataTemplate.Triggers>
+                                    <DataTrigger Binding="{Binding IsDestinationEditing}" Value="True">
+                                        <Setter TargetName="DestinationTextBlock" Property="Visibility" Value="Collapsed"/>
+                                        <Setter TargetName="DestinationTextBox" Property="Visibility" Value="Visible"/>
+                                    </DataTrigger>
+                                </DataTemplate.Triggers>
+                            </DataTemplate>
+                        </DataGridTemplateColumn.CellTemplate>
+                    </DataGridTemplateColumn>
+                </DataGrid.Columns>
+            </views1:ExDataGrid>
+        </Grid>
+        <GridSplitter Grid.Row="2" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
+        <ScrollViewer Grid.Row="3" HorizontalScrollBarVisibility="Auto">
+            <TextBox IsReadOnly="True" Text="{Binding OutputMessage}">
+                <TextBox.ContextMenu>
+                    <ContextMenu>
+                        <MenuItem Command="{Binding ClearOutputWindowRelayCommand}"
+                                  resources:ResourceHelper.ResourceId="Views_OutputWindowContextMenu_Clear"
+                                  Header="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}"/>
+                    </ContextMenu>
+                </TextBox.ContextMenu>
+            </TextBox>
+        </ScrollViewer>
+        <ToolBar Grid.Row="4">
+            <ProgressBar Width="100" Value="{Binding ProgressViewModel.ProgressValue}"/>
+        </ToolBar>
+    </Grid>
+</Window>
diff --git a/Main/SimpleBackup.Views/MainWindow.xaml.cs b/Main/SimpleBackup.Views/MainWindow.xaml.cs
new file mode 100644 (file)
index 0000000..8519569
--- /dev/null
@@ -0,0 +1,356 @@
+//-----------------------------------------------------------------------
+// <copyright file="MainWindow.xaml.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Views
+{
+    using System;
+    using System.ComponentModel;
+    using System.Linq;
+    using System.Windows;
+    using System.Windows.Controls;
+    using System.Windows.Controls.Primitives;
+    using System.Windows.Input;
+    using SimpleBackup.Core;
+    using SimpleBackup.Core.Services;
+    using SimpleBackup.Core.Utilities;
+    using SimpleBackup.Core.ViewModels;
+    using SimpleBackup.Core.Views;
+    using Application = System.Windows.Application;
+    using DataGrid = System.Windows.Controls.DataGrid;
+    using DataGridCell = System.Windows.Controls.DataGridCell;
+    using KeyEventArgs = System.Windows.Input.KeyEventArgs;
+    using MessageBox = System.Windows.MessageBox;
+    using TextBox = System.Windows.Controls.TextBox;
+
+    /// <summary>
+    /// The Code-Behind of MainWindow.xaml.
+    /// </summary>
+    internal partial class MainWindow : Window, IMainWindow
+    {
+        private IBackupSettingService backupSettingService;
+
+        /// <summary>
+        /// Prevents a default instance of the <see cref="MainWindow"/> class from being created.
+        /// </summary>
+        private MainWindow()
+        {
+            this.InitializeComponent();
+
+            this.backupSettingService = ObjectContainer.Resolve<IBackupSettingService>();
+
+            this.DataContextChanged += (sender, args) =>
+                {
+                    var viewModel = this.DataContext as IMainWindowViewModel;
+                    if (viewModel != null)
+                    {
+                        viewModel.FocusOnGrid += this.OnFocusOnGridRequired;
+                        viewModel.FocusOnGridRow += this.OnFocusOnGridRowRequired;
+                    }
+                    else
+                    {
+                        throw new InvalidOperationException("The data context is not an IMainWindowViewModel object.");
+                    }
+                };
+
+            this.BackupInfoDataGrid.Loaded += (sender, args) =>
+                {
+                    if (this.BackupInfoDataGrid.Items.Count != 0)
+                    {
+                        this.FocusOnGridRow(0);
+                    }
+                };
+        }
+
+        /// <summary>
+        /// Creates the main window.
+        /// </summary>
+        /// <returns>The main window.</returns>
+        public static IMainWindow CreateMainWindow()
+        {
+            return new MainWindow();
+        }
+
+        /// <summary>
+        /// Raises the Closing event.
+        /// </summary>
+        /// <param name="e">A <see cref="T:System.ComponentModel.CancelEventArgs" /> that contains the event data.</param>
+        protected override void OnClosing(CancelEventArgs e)
+        {
+            if ((this.backupSettingService.CurrentSetting != null) &&
+                this.backupSettingService.CurrentSetting.Modified)
+            {
+                MessageBoxResult confirmationResult = MessageBox.Show(
+                    Application.Current.MainWindow,
+                    SimpleBackup.Resources.Resources.Views_SaveConfirmationMessage,
+                    SimpleBackup.Resources.Resources.Views_ConfirmationDialogTitle,
+                    MessageBoxButton.YesNoCancel);
+                if (confirmationResult == MessageBoxResult.Yes)
+                {
+                    if (this.backupSettingService.OverWriteCurrntBackupSetting() == false)
+                    {
+                        e.Cancel = true;
+                    }
+                }
+                else if (confirmationResult == MessageBoxResult.Cancel)
+                {
+                    e.Cancel = true;
+                }
+            }
+        }
+
+        private void OnFocusOnGridRequired(object sender, EventArgs eventArgs)
+        {
+            this.BackupInfoDataGrid.Focus();
+        }
+
+        private void OnFocusOnGridRowRequired(object sender, FocusOnGridRowEventArgs args)
+        {
+            this.FocusOnGridRow(args.Index);
+        }
+
+        private void FocusOnGridRow(int index)
+        {
+            this.BackupInfoDataGrid.Focus();
+            var dataGridRow = this.BackupInfoDataGrid.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;
+            if (dataGridRow != null)
+            {
+                dataGridRow.Focus();
+                this.SelectBackupInfoDataGridItem(index);
+
+                var dataGridCellsPanel = dataGridRow.GetVisualChild<DataGridCellsPanel>();
+                if (dataGridCellsPanel != null)
+                {
+                    if (dataGridCellsPanel.Children.Count != 0)
+                    {
+                        var dataGridCell = dataGridCellsPanel.Children[0] as DataGridCell;
+                        if (dataGridCell != null)
+                        {
+                            dataGridCell.Focus();
+                        }
+                    }
+                }
+            }
+        }
+
+        private void SelectBackupInfoDataGridItem(int index)
+        {
+            this.BackupInfoDataGrid.SelectedIndex = index;
+        }
+
+        private void OnDataGridMouseDoubleClick(object sender, MouseButtonEventArgs e)
+        {
+            var dataGrid = (DataGrid)sender;
+            var currentItemviewModel = dataGrid.CurrentItem as IBackupInfoViewModel;
+            if (currentItemviewModel == null)
+            {
+                return;
+            }
+
+            DataGridCellInfo currentCellInfo = dataGrid.CurrentCell;
+            var currentColumnHeaderContentPresenter = currentCellInfo.Column.Header as ContentPresenter;
+            if (currentColumnHeaderContentPresenter != null)
+            {
+                var sourceColumnHeaderViewModel =
+                    currentColumnHeaderContentPresenter.Content as ISourceColumnHeaderViewModel;
+                if (sourceColumnHeaderViewModel != null)
+                {
+                    currentItemviewModel.ExecuteDoubleClickAction(BackupInfoPathType.Source);
+                }
+                else
+                {
+                    var destinationColumnHeaderViewModel =
+                        currentColumnHeaderContentPresenter.Content as IDestinationColumnHeaderViewModel;
+                    if (destinationColumnHeaderViewModel != null)
+                    {
+                        currentItemviewModel.ExecuteDoubleClickAction(BackupInfoPathType.Destination);
+                    }
+                }
+            }
+        }
+
+        private void OnCellContentPreviewKeyDown(object sender, KeyEventArgs e)
+        {
+            Type sourceType = sender.GetType();
+
+            var sourceDataGridCell = ((DependencyObject)sender).SearchUpParentWithSelf<DataGridCell>();
+            if (sourceDataGridCell == null)
+            {
+                return;
+            }
+
+            var sourceDataGridRow = sourceDataGridCell.SearchUpParentWithSelf<DataGridRow>();
+            if (sourceDataGridRow == null)
+            {
+                return;
+            }
+
+            var dataGrid = sourceDataGridRow.SearchUpParentWithSelf<DataGrid>();
+            if (dataGrid == null)
+            {
+                return;
+            }
+
+            int sourceRowIndex = dataGrid.Items.IndexOf(sourceDataGridRow.Item);
+            int targetRowIndex = -1;
+            switch (e.Key)
+            {
+                case Key.Up:
+                    if (sourceRowIndex != 0)
+                    {
+                        targetRowIndex = sourceRowIndex - 1;
+                    }
+
+                    break;
+                case Key.Down:
+                    if (sourceRowIndex < dataGrid.Items.Count - 1)
+                    {
+                        targetRowIndex = sourceRowIndex + 1;
+                    }
+
+                    break;
+                case Key.PageUp:
+                    break;
+                case Key.PageDown:
+                    break;
+            }
+
+            if (targetRowIndex < 0)
+            {
+                return;
+            }
+
+            var targetDataGridRow = dataGrid.ItemContainerGenerator.ContainerFromIndex(targetRowIndex) as DataGridRow;
+            if (targetDataGridRow == null)
+            {
+                return;
+            }
+
+            var targetCellsPresenter = targetDataGridRow.GetVisualChild<DataGridCellsPresenter>();
+            if (targetCellsPresenter == null)
+            {
+                return;
+            }
+
+            var targetDataGridCell =
+                (DataGridCell)targetCellsPresenter.ItemContainerGenerator.ContainerFromIndex(sourceDataGridCell.Column.DisplayIndex);
+            if (targetDataGridCell == null)
+            {
+                return;
+            }
+
+            var targetElement = targetDataGridCell.GetVisualChild(sourceType) as UIElement;
+            if (targetElement == null)
+            {
+                return;
+            }
+
+            sourceDataGridRow.IsSelected = false;
+            targetDataGridRow.IsSelected = true;
+            targetElement.Focus();
+
+            e.Handled = true;
+        }
+
+        private void OnMainWindowPreviewKeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.Key == Key.F2)
+            {
+                this.StartEditCurrentCell();
+                e.Handled = true;
+            }
+            else if (e.Key == Key.Escape)
+            {
+                var viewModel = this.DataContext as IMainWindowViewModel;
+                if (viewModel != null)
+                {
+                    viewModel.OnEscKeyPressed();
+                }
+
+                e.Handled = true;
+            }
+            else if ((Keyboard.Modifiers & ModifierKeys.Control) > 0)
+            {
+                if (e.Key == Key.S)
+                {
+                    var viewModel = this.DataContext as IMainWindowViewModel;
+                    if (viewModel != null)
+                    {
+                        if (viewModel.SaveBackupSettingRelayCommand.CanExecute(this))
+                        {
+                            viewModel.SaveBackupSettingRelayCommand.Execute(this);
+                            e.Handled = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        private void StartEditCurrentCell()
+        {
+            var currentItemviewModel = this.BackupInfoDataGrid.CurrentItem as IBackupInfoViewModel;
+            if (currentItemviewModel == null)
+            {
+                return;
+            }
+
+            DataGridCellInfo currentCellInfo = this.BackupInfoDataGrid.CurrentCell;
+            var currentColumnHeaderContentPresenter = currentCellInfo.Column.Header as ContentPresenter;
+            if (currentColumnHeaderContentPresenter != null)
+            {
+                if (currentColumnHeaderContentPresenter.Content is ISourceColumnHeaderViewModel)
+                {
+                    currentItemviewModel.EditSourceRelayCommand.Execute(null);
+                    this.FocusOnTextBoxInSelectedDataGridCell();
+                }
+                else if (currentColumnHeaderContentPresenter.Content is IDestinationColumnHeaderViewModel)
+                {
+                    currentItemviewModel.EditDestinationRelayCommand.Execute(null);
+                    this.FocusOnTextBoxInSelectedDataGridCell();
+                }
+                else if (currentColumnHeaderContentPresenter.Content is ILabelColumnHeaderViewModel)
+                {
+                    this.FocusOnTextBoxInSelectedDataGridCell();
+                }
+            }
+        }
+
+        private void FocusOnTextBoxInSelectedDataGridCell()
+        {
+            DataGridCellInfo cellInfo = this.BackupInfoDataGrid.SelectedCells.FirstOrDefault();
+            var cellContentPresenter = cellInfo.Column.GetCellContent(cellInfo.Item) as ContentPresenter;
+            if (cellContentPresenter != null)
+            {
+                var textBox = cellContentPresenter.GetVisualChild<TextBox>();
+                if (textBox != null)
+                {
+                    textBox.Focus();
+                    textBox.Select(textBox.Text.Length, 0);
+                }
+            }
+        }
+
+        private void OnZipEncodingSelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            // Move focus setting from the ComboBox by setting focus to the main window.
+            this.Focus();
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Views/SimpleBackup.Views.csproj b/Main/SimpleBackup.Views/SimpleBackup.Views.csproj
new file mode 100644 (file)
index 0000000..7fce336
--- /dev/null
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{C42B720C-323E-4E0C-ACBF-7FA9CFE228BE}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SimpleBackup.Views</RootNamespace>
+    <AssemblyName>SimpleBackup.Views</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SccProjectName>SAK</SccProjectName>
+    <SccLocalPath>SAK</SccLocalPath>
+    <SccAuxPath>SAK</SccAuxPath>
+    <SccProvider>SAK</SccProvider>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <SignAssembly>true</SignAssembly>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>SimpleBackupKey.snk</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="PresentationCore" />
+    <Reference Include="PresentationFramework" />
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\Lib\Expression\Blend\.NETFramework\v4.5\Libraries\System.Windows.Interactivity.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Xaml" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+    <Reference Include="WindowsBase" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="..\Properties\AssemblyInfo.cs">
+      <Link>Properties\AssemblyInfo.cs</Link>
+    </Compile>
+    <Compile Include="BackupSourceTypeToImageConverter.cs" />
+    <Compile Include="BackupStateToImageConverter.cs" />
+    <Compile Include="ExDataGrid.cs" />
+    <Compile Include="ExDataGridSelectedFirstCellItemBehavior.cs" />
+    <Compile Include="FileFolderDialog.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="MainWindow.xaml.cs">
+      <DependentUpon>MainWindow.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="VersionInformationWindow.xaml.cs">
+      <DependentUpon>VersionInformationWindow.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="ViewComponent.cs" />
+    <Compile Include="ViewFactory.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="SimpleBackupKey.snk" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\SimpleBackup.Core\SimpleBackup.Core.csproj">
+      <Project>{33f1d454-9962-4eb6-aad3-8d11d9a78d1f}</Project>
+      <Name>SimpleBackup.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\SimpleBackup.Resources\SimpleBackup.Resources.csproj">
+      <Project>{a655131e-d439-4de1-bc39-5c955306183f}</Project>
+      <Name>SimpleBackup.Resources</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Page Include="MainWindow.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
+  </ItemGroup>
+  <ItemGroup>
+    <Page Include="VersionInformationWindow.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <PropertyGroup>
+    <PostBuildEvent>set EXE_BIN_DIR=$(ProjectDir)..\bin\$(ConfigurationName)\
+xcopy "$(TargetDir)$(TargetName).dll" "%25EXE_BIN_DIR%25" /Y
+if exist "$(TargetDir)$(TargetName).pdb" xcopy "$(TargetDir)$(TargetName).pdb" "%25EXE_BIN_DIR%25" /Y</PostBuildEvent>
+  </PropertyGroup>
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Main/SimpleBackup.Views/SimpleBackupKey.snk b/Main/SimpleBackup.Views/SimpleBackupKey.snk
new file mode 100644 (file)
index 0000000..def2e6d
Binary files /dev/null and b/Main/SimpleBackup.Views/SimpleBackupKey.snk differ
diff --git a/Main/SimpleBackup.Views/VersionInformationWindow.xaml b/Main/SimpleBackup.Views/VersionInformationWindow.xaml
new file mode 100644 (file)
index 0000000..0e0d9aa
--- /dev/null
@@ -0,0 +1,66 @@
+<!--
+This file is part of Simple Backup.
+
+Simple Backup is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Simple Backup is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+-->
+    
+<Window x:Class="SimpleBackup.Views.VersionInformationWindow"
+        x:ClassModifier="internal"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:resources="clr-namespace:SimpleBackup.Resources;assembly=SimpleBackup.Resources"
+        Height="200" Width="350" ResizeMode="NoResize"
+        Icon="pack://application:,,,/SimpleBackup.Resources;component/Images/ApplicationIcon.ico"
+        resources:ResourceHelper.ResourceId="Views_VersionWindowTitle"
+        Title="{Binding RelativeSource={RelativeSource Self}, Path=(resources:ResourceHelper.ResourceText)}">
+    <Window.Resources>
+        <Style x:Key="VersionInfoTextBoxStyle" TargetType="{x:Type TextBox}">
+            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
+            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
+            <Setter Property="BorderThickness" Value="1"/>
+            <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
+            <Setter Property="HorizontalContentAlignment" Value="Left"/>
+            <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
+            <Setter Property="AllowDrop" Value="True"/>
+            <Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
+            <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
+            <Setter Property="Template">
+                <Setter.Value>
+                    <ControlTemplate TargetType="{x:Type TextBox}">
+                        <ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
+                    </ControlTemplate>
+                </Setter.Value>
+            </Setter>
+            <Style.Triggers>
+                <MultiTrigger>
+                    <MultiTrigger.Conditions>
+                        <Condition Property="IsInactiveSelectionHighlightEnabled" Value="True"/>
+                        <Condition Property="IsSelectionActive" Value="False"/>
+                    </MultiTrigger.Conditions>
+                    <Setter Property="SelectionBrush" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
+                </MultiTrigger>
+            </Style.Triggers>
+        </Style>
+    </Window.Resources>
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="Auto"/>
+            <RowDefinition/>
+        </Grid.RowDefinitions>
+        <TextBox Grid.Row="0" x:Name="VersionInfoTextBox" IsReadOnly="True" Style="{DynamicResource VersionInfoTextBoxStyle}" Margin="5,15,5,10" TextWrapping="Wrap"/>
+        <ScrollViewer Grid.Row="1" Margin="5">
+            <TextBox x:Name="CopyrightTextBox" IsReadOnly="True" Style="{DynamicResource VersionInfoTextBoxStyle}" TextWrapping="Wrap"/>
+        </ScrollViewer>
+    </Grid>
+</Window>
diff --git a/Main/SimpleBackup.Views/VersionInformationWindow.xaml.cs b/Main/SimpleBackup.Views/VersionInformationWindow.xaml.cs
new file mode 100644 (file)
index 0000000..2fe79f0
--- /dev/null
@@ -0,0 +1,59 @@
+//-----------------------------------------------------------------------
+// <copyright file="VersionInformationWindow.xaml.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Views
+{
+    using System.Reflection;
+    using System.Windows;
+    using SimpleBackup.Core.Views;
+
+    /// <summary>
+    /// The Code-Behind of VersionInformationWindow.xaml.
+    /// </summary>
+    internal partial class VersionInformationWindow : Window, IVersionInformationWindow
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="VersionInformationWindow"/> class.
+        /// </summary>
+        public VersionInformationWindow()
+        {
+            this.InitializeComponent();
+
+            this.VersionInfoTextBox.Text = string.Format(
+                "{0} Ver.{1}\r\n{2}",
+                SimpleBackup.Resources.Resources.Views_CopyrightApplicationName,
+                Assembly.GetExecutingAssembly().GetName().Version,
+                SimpleBackup.Resources.Resources.Version_Copyright);
+            this.CopyrightTextBox.Text = SimpleBackup.Resources.Resources.Version_CopyrightDescription;
+        }
+
+        /// <summary>
+        /// Shows the dialog window.
+        /// </summary>
+        /// <returns>
+        /// The result.
+        /// </returns>
+        public bool? ShowDialogWindow()
+        {
+            return this.ShowDialog();
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Views/ViewComponent.cs b/Main/SimpleBackup.Views/ViewComponent.cs
new file mode 100644 (file)
index 0000000..6c881ea
--- /dev/null
@@ -0,0 +1,41 @@
+//-----------------------------------------------------------------------
+// <copyright file="ViewComponent.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Views
+{
+    using SimpleBackup.Core;
+    using SimpleBackup.Core.AppInfrastructure;
+    using SimpleBackup.Core.Views;
+
+    /// <summary>
+    /// The view component.
+    /// </summary>
+    internal class ViewComponent : IAppComponent
+    {
+        /// <summary>
+        /// Initializes this application component.
+        /// </summary>
+        public void Initialize()
+        {
+            ObjectContainer.Register<IViewFactory>(new ViewFactory());
+        }
+    }
+}
diff --git a/Main/SimpleBackup.Views/ViewFactory.cs b/Main/SimpleBackup.Views/ViewFactory.cs
new file mode 100644 (file)
index 0000000..ea89c16
--- /dev/null
@@ -0,0 +1,69 @@
+//-----------------------------------------------------------------------
+// <copyright file="ViewFactory.cs" company="Takayoshi Matsuyama">
+//     Copyright (c) Takayoshi Matsuyama. All rights reserved.
+// </copyright>
+//-----------------------------------------------------------------------
+
+// This file is part of Simple Backup.
+//
+// Simple Backup is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Simple Backup is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Simple Backup.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace SimpleBackup.Views
+{
+    using System.Windows;
+    using SimpleBackup.Core.Views;
+
+    /// <summary>
+    /// Creates view objects.
+    /// </summary>
+    internal class ViewFactory : IViewFactory
+    {
+        /// <summary>
+        /// Creates the main window.
+        /// </summary>
+        /// <returns>
+        /// The main window.
+        /// </returns>
+        public IMainWindow CreateMainWindow()
+        {
+            return MainWindow.CreateMainWindow();
+        }
+
+        /// <summary>
+        /// Creates the version information window.
+        /// </summary>
+        /// <returns>
+        /// The version information window.
+        /// </returns>
+        public IVersionInformationWindow CreateVersionInformationWindow()
+        {
+            return new VersionInformationWindow
+            {
+                Owner = Application.Current.MainWindow,
+                WindowStartupLocation = WindowStartupLocation.CenterOwner
+            };
+        }
+
+        /// <summary>
+        /// Creates the file folder dialog.
+        /// </summary>
+        /// <returns>
+        /// The file folder dialog.
+        /// </returns>
+        public IFileFolderDialog CreateFileFolderDialog()
+        {
+            return new FileFolderDialog();
+        }
+    }
+}
index 2aaad22..05dd942 100644 (file)
     <AssemblyOriginatorKeyFile>SimpleBackupKey.snk</AssemblyOriginatorKeyFile>
   </PropertyGroup>
   <PropertyGroup>
-    <ApplicationIcon>Resources\Images\ApplicationIcon.ico</ApplicationIcon>
+    <ApplicationIcon>
+    </ApplicationIcon>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Data" />
-    <Reference Include="System.IO.Compression.FileSystem" />
-    <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <SpecificVersion>False</SpecificVersion>
       <HintPath>Lib\Expression\Blend\.NETFramework\v4.5\Libraries\System.Windows.Interactivity.dll</HintPath>
     </Reference>
+    <Reference Include="System.Xaml" />
     <Reference Include="System.Xml" />
     <Reference Include="Microsoft.CSharp" />
     <Reference Include="System.Core" />
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="System.Xaml">
-      <RequiredTargetFramework>4.0</RequiredTargetFramework>
-    </Reference>
     <Reference Include="WindowsBase" />
     <Reference Include="PresentationCore" />
     <Reference Include="PresentationFramework" />
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
     </ApplicationDefinition>
-    <Compile Include="Core\Models\IBackupInfo.cs" />
-    <Compile Include="Core\Models\IBackupSetting.cs" />
-    <Compile Include="Core\Models\IResultInfo.cs" />
-    <Compile Include="Core\Models\BackupState.cs" />
-    <Compile Include="Core\Services\FileBackupProgressEventArgs.cs" />
-    <Compile Include="Core\Services\IBackupService.cs" />
-    <Compile Include="Core\Services\IBackupSettingService.cs" />
-    <Compile Include="Core\Services\IClipboardService.cs" />
-    <Compile Include="Core\Models\ItemMovingDirection.cs" />
-    <Compile Include="Core\Services\IUndoRedoService.cs" />
-    <Compile Include="Core\Services\SettingFileEventArgs.cs" />
-    <Compile Include="Core\Utilities\Constants.cs" />
-    <Compile Include="Core\Utilities\HelperExtensions.cs" />
-    <Compile Include="Core\Utilities\Helpers.cs" />
-    <Compile Include="Core\Utilities\IdIndexPair.cs" />
-    <Compile Include="Core\ViewModels\BackupInfoPathType.cs" />
-    <Compile Include="Core\ViewModels\FocusOnGridRowEventArgs.cs" />
-    <Compile Include="Core\ViewModels\IMainWindowViewModel.cs" />
-    <Compile Include="Core\Views\ExDataGridSelectedFirstCellItemChangedEventArgs.cs" />
-    <Compile Include="Core\Views\IMainWindow.cs" />
-    <Compile Include="Core\Views\RelayCommand.cs" />
-    <Compile Include="Models\BackupSourceType.cs" />
-    <Compile Include="Models\ModelHelper.cs" />
-    <Compile Include="Models\ResultInfo.cs" />
-    <Compile Include="Models\BackupSetting.cs" />
-    <Compile Include="Services\ClipboardService.cs" />
-    <Compile Include="Services\BackupSettingService.cs" />
-    <Compile Include="ViewModels\BackupInfoPasteInfo.cs" />
-    <Compile Include="ViewModels\EncodingInfoItemViewModel.cs" />
-    <Compile Include="ViewModels\PasteType.cs" />
-    <Compile Include="Views\BackupSourceTypeToImageConverter.cs" />
-    <Compile Include="Views\VersionInformationWindow.xaml.cs">
-      <DependentUpon>VersionInformationWindow.xaml</DependentUpon>
-    </Compile>
-    <Page Include="Views\MainWindow.xaml">
-      <Generator>MSBuild:Compile</Generator>
-      <SubType>Designer</SubType>
-    </Page>
+    <Compile Include="Bootstrapper.cs" />
     <Compile Include="App.xaml.cs">
       <DependentUpon>App.xaml</DependentUpon>
       <SubType>Code</SubType>
     </Compile>
-    <Compile Include="Models\BackupInfo.cs" />
-    <Compile Include="Resources\Resources.Designer.cs">
-      <AutoGen>True</AutoGen>
-      <DesignTime>True</DesignTime>
-      <DependentUpon>Resources.resx</DependentUpon>
-    </Compile>
-    <Compile Include="Services\ResourceService.cs" />
-    <Compile Include="Services\BackupService.cs" />
-    <Compile Include="Models\DestinationPathInfo.cs" />
-    <Compile Include="Services\UndoRedoActionSet.cs" />
-    <Compile Include="Services\UndoRedoService.cs" />
-    <Compile Include="ViewModels\BackupInfoViewModel.cs" />
-    <Compile Include="Core\Utilities\PropertyChangeNotificationBase.cs" />
-    <Compile Include="ViewModels\DataGridColumnHeaderBaseViewModel.cs" />
-    <Compile Include="ViewModels\DestinationColumnHeaderViewModel.cs" />
-    <Compile Include="ViewModels\IndexBackupInfoViewModelPair.cs" />
-    <Compile Include="ViewModels\IsZipArchiveColumnHeaderViewModel.cs" />
-    <Compile Include="ViewModels\MainWindowViewModel.cs" />
-    <Compile Include="ViewModels\ProgressViewModel.cs" />
-    <Compile Include="ViewModels\SourceColumnHeaderViewModel.cs" />
-    <Compile Include="ViewModels\LabelColumnHeaderViewModel.cs" />
-    <Compile Include="Views\BackupStateToImageConverter.cs" />
-    <Compile Include="Views\ExDataGrid.cs" />
-    <Compile Include="Views\ExDataGridSelectedFirstCellItemBehavior.cs" />
-    <Compile Include="Views\FileFolderDialog.cs">
-      <SubType>Component</SubType>
-    </Compile>
-    <Compile Include="Views\MainWindow.xaml.cs">
-      <DependentUpon>MainWindow.xaml</DependentUpon>
-      <SubType>Code</SubType>
-    </Compile>
-    <Page Include="Views\VersionInformationWindow.xaml">
-      <SubType>Designer</SubType>
-      <Generator>MSBuild:Compile</Generator>
-    </Page>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Properties\AssemblyInfo.cs">
       <Generator>ResXFileCodeGenerator</Generator>
       <LastGenOutput>Resources.Designer.cs</LastGenOutput>
     </EmbeddedResource>
-    <EmbeddedResource Include="Resources\Resources.ja.resx" />
-    <EmbeddedResource Include="Resources\Resources.resx">
-      <Generator>ResXFileCodeGenerator</Generator>
-      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
-    </EmbeddedResource>
     <None Include="Documents\HelpDocument.docx" />
     <None Include="Documents\HelpDocument.pdf">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
   </ItemGroup>
   <ItemGroup>
-    <Resource Include="Resources\Images\Activity_16xLG.png" />
-  </ItemGroup>
-  <ItemGroup>
     <BootstrapperPackage Include=".NETFramework,Version=v4.5">
       <Visible>False</Visible>
       <ProductName>Microsoft .NET Framework 4.5 %28x86 および x64%29</ProductName>
     </BootstrapperPackage>
   </ItemGroup>
   <ItemGroup>
-    <Resource Include="Resources\Images\AddVariable_5541.png" />
-    <Resource Include="Resources\Images\Arrow_RedoRetry_16xLG.png" />
-    <Resource Include="Resources\Images\Arrow_UndoRevertRestore_16xLG.png" />
-    <Resource Include="Resources\Images\Copy_6524.png" />
-    <Resource Include="Resources\Images\Cut_6523.png" />
-    <Resource Include="Resources\Images\Delete_black_32x32.png" />
-    <Resource Include="Resources\Images\Open_6529.png" />
-    <Resource Include="Resources\Images\Paste_6520.png" />
-    <Resource Include="Resources\Images\Print_11009.png" />
-    <Resource Include="Resources\Images\save_16xLG.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\arrow_Down_16xLG.png" />
-    <Resource Include="Resources\Images\arrow_Up_16xLG.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\Symbols_Complete_and_ok_32xLG.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\StatusAnnotations_Critical_32xLG_color.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\Warning.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\StatusAnnotations_Complete_and_ok_32xLG_color.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\Synchronize_16xLG.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\flag_16xLG.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\arrow_run_16xLG.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\document_32xLG.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\FileGroup_10135_32x.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\ApplicationIcon.ico" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\arrow_all_run_16xLG.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\action_Cancel_16xLG.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\NewFile_6276.png" />
-  </ItemGroup>
-  <ItemGroup>
-    <Resource Include="Resources\Images\refresh_16xLG.png" />
+    <ProjectReference Include="SimpleBackup.Core\SimpleBackup.Core.csproj">
+      <Project>{33f1d454-9962-4eb6-aad3-8d11d9a78d1f}</Project>
+      <Name>SimpleBackup.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="SimpleBackup.Resources\SimpleBackup.Resources.csproj">
+      <Project>{a655131e-d439-4de1-bc39-5c955306183f}</Project>
+      <Name>SimpleBackup.Resources</Name>
+    </ProjectReference>
   </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/Main/SimpleBackup.psess b/Main/SimpleBackup.psess
new file mode 100644 (file)
index 0000000..1066eef
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VSPerformanceSession Version="1.00">
+  <Options>
+    <Solution>SimpleBackup.sln</Solution>
+    <CollectionMethod>Sampling</CollectionMethod>
+    <AllocationMethod>None</AllocationMethod>
+    <AddReport>true</AddReport>
+    <ResourceBasedAnalysisSelected>true</ResourceBasedAnalysisSelected>
+    <UniqueReport>Timestamp</UniqueReport>
+    <SamplingMethod>Cycles</SamplingMethod>
+    <CycleCount>10000000</CycleCount>
+    <PageFaultCount>10</PageFaultCount>
+    <SysCallCount>10</SysCallCount>
+    <SamplingCounter Name="" ReloadValue="00000000000f4240" DisplayName="" />
+    <RelocateBinaries>false</RelocateBinaries>
+    <HardwareCounters EnableHWCounters="false" />
+    <EtwSettings />
+    <PdhSettings>
+      <PdhCountersEnabled>false</PdhCountersEnabled>
+      <PdhCountersRate>500</PdhCountersRate>
+      <PdhCounters>
+        <PdhCounter>\Memory\Pages/sec</PdhCounter>
+        <PdhCounter>\PhysicalDisk(_Total)\Avg. Disk Queue Length</PdhCounter>
+        <PdhCounter>\Processor(_Total)\% Processor Time</PdhCounter>
+      </PdhCounters>
+    </PdhSettings>
+  </Options>
+  <ExcludeSmallFuncs>true</ExcludeSmallFuncs>
+  <InteractionProfilingEnabled>false</InteractionProfilingEnabled>
+  <JScriptProfilingEnabled>false</JScriptProfilingEnabled>
+  <PreinstrumentEvent>
+    <InstrEventExclude>false</InstrEventExclude>
+  </PreinstrumentEvent>
+  <PostinstrumentEvent>
+    <InstrEventExclude>false</InstrEventExclude>
+  </PostinstrumentEvent>
+  <Binaries>
+    <ProjBinary>
+      <Path>obj\Debug\SimpleBackup.exe</Path>
+      <ArgumentTimestamp>01/01/0001 00:00:00</ArgumentTimestamp>
+      <Instrument>true</Instrument>
+      <Sample>true</Sample>
+      <ExternalWebsite>false</ExternalWebsite>
+      <InteractionProfilingEnabled>false</InteractionProfilingEnabled>
+      <IsLocalJavascript>false</IsLocalJavascript>
+      <IsWindowsStoreApp>false</IsWindowsStoreApp>
+      <IsWWA>false</IsWWA>
+      <LaunchProject>true</LaunchProject>
+      <OverrideProjectSettings>false</OverrideProjectSettings>
+      <LaunchMethod>Executable</LaunchMethod>
+      <ExecutablePath>bin\Debug\SimpleBackup.exe</ExecutablePath>
+      <StartupDirectory>bin\Debug\</StartupDirectory>
+      <Arguments>
+      </Arguments>
+      <NetAppHost>IIS</NetAppHost>
+      <NetBrowser>InternetExplorer</NetBrowser>
+      <ExcludeSmallFuncs>true</ExcludeSmallFuncs>
+      <JScriptProfilingEnabled>false</JScriptProfilingEnabled>
+      <PreinstrumentEvent>
+        <InstrEventExclude>false</InstrEventExclude>
+      </PreinstrumentEvent>
+      <PostinstrumentEvent>
+        <InstrEventExclude>false</InstrEventExclude>
+      </PostinstrumentEvent>
+      <ProjRef>{447D8832-4AAA-4621-8FC9-4BBE5977731C}|SimpleBackup.csproj</ProjRef>
+      <ProjPath>SimpleBackup.csproj</ProjPath>
+      <ProjName>SimpleBackup</ProjName>
+    </ProjBinary>
+  </Binaries>
+  <Reports>
+    <Report>
+      <Path>SimpleBackup150329.vspx</Path>
+    </Report>
+  </Reports>
+  <Launches>
+    <ProjBinary>
+      <Path>:PB:{447D8832-4AAA-4621-8FC9-4BBE5977731C}|SimpleBackup.csproj</Path>
+    </ProjBinary>
+  </Launches>
+</VSPerformanceSession>
\ No newline at end of file
index e4f89af..b4a47eb 100644 (file)
@@ -3,14 +3,44 @@ Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 2012
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleBackup", "SimpleBackup.csproj", "{447D8832-4AAA-4621-8FC9-4BBE5977731C}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleBackup.Core", "SimpleBackup.Core\SimpleBackup.Core.csproj", "{33F1D454-9962-4EB6-AAD3-8D11D9A78D1F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleBackup.Models", "SimpleBackup.Models\SimpleBackup.Models.csproj", "{7B8C68F1-8A5C-470F-9356-F0EC1268617F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleBackup.Services", "SimpleBackup.Services\SimpleBackup.Services.csproj", "{950EE3DF-1731-49B7-94C2-F33154855782}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleBackup.ViewModels", "SimpleBackup.ViewModels\SimpleBackup.ViewModels.csproj", "{70BC6544-A4C9-4325-9CE1-CC3F79787693}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleBackup.Views", "SimpleBackup.Views\SimpleBackup.Views.csproj", "{C42B720C-323E-4E0C-ACBF-7FA9CFE228BE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleBackup.Resources", "SimpleBackup.Resources\SimpleBackup.Resources.csproj", "{A655131E-D439-4DE1-BC39-5C955306183F}"
+EndProject
 Global
        GlobalSection(TeamFoundationVersionControl) = preSolution
-               SccNumberOfProjects = 2
+               SccNumberOfProjects = 8
                SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
                SccTeamFoundationServer = https://tkys0515.visualstudio.com/defaultcollection
-               SccProjectUniqueName0 = SimpleBackup.csproj
                SccLocalPath0 = .
+               SccProjectUniqueName1 = SimpleBackup.csproj
                SccLocalPath1 = .
+               SccProjectUniqueName2 = SimpleBackup.Core\\SimpleBackup.Core.csproj
+               SccProjectName2 = SimpleBackup.Core
+               SccLocalPath2 = SimpleBackup.Core
+               SccProjectUniqueName3 = SimpleBackup.Models\\SimpleBackup.Models.csproj
+               SccProjectName3 = SimpleBackup.Models
+               SccLocalPath3 = SimpleBackup.Models
+               SccProjectUniqueName4 = SimpleBackup.Services\\SimpleBackup.Services.csproj
+               SccProjectName4 = SimpleBackup.Services
+               SccLocalPath4 = SimpleBackup.Services
+               SccProjectUniqueName5 = SimpleBackup.ViewModels\\SimpleBackup.ViewModels.csproj
+               SccProjectName5 = SimpleBackup.ViewModels
+               SccLocalPath5 = SimpleBackup.ViewModels
+               SccProjectUniqueName6 = SimpleBackup.Views\\SimpleBackup.Views.csproj
+               SccProjectName6 = SimpleBackup.Views
+               SccLocalPath6 = SimpleBackup.Views
+               SccProjectUniqueName7 = SimpleBackup.Resources\\SimpleBackup.Resources.csproj
+               SccProjectName7 = SimpleBackup.Resources
+               SccLocalPath7 = SimpleBackup.Resources
        EndGlobalSection
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
@@ -21,8 +51,35 @@ Global
                {447D8832-4AAA-4621-8FC9-4BBE5977731C}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {447D8832-4AAA-4621-8FC9-4BBE5977731C}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {447D8832-4AAA-4621-8FC9-4BBE5977731C}.Release|Any CPU.Build.0 = Release|Any CPU
+               {33F1D454-9962-4EB6-AAD3-8D11D9A78D1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {33F1D454-9962-4EB6-AAD3-8D11D9A78D1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {33F1D454-9962-4EB6-AAD3-8D11D9A78D1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {33F1D454-9962-4EB6-AAD3-8D11D9A78D1F}.Release|Any CPU.Build.0 = Release|Any CPU
+               {7B8C68F1-8A5C-470F-9356-F0EC1268617F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {7B8C68F1-8A5C-470F-9356-F0EC1268617F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {7B8C68F1-8A5C-470F-9356-F0EC1268617F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {7B8C68F1-8A5C-470F-9356-F0EC1268617F}.Release|Any CPU.Build.0 = Release|Any CPU
+               {950EE3DF-1731-49B7-94C2-F33154855782}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {950EE3DF-1731-49B7-94C2-F33154855782}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {950EE3DF-1731-49B7-94C2-F33154855782}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {950EE3DF-1731-49B7-94C2-F33154855782}.Release|Any CPU.Build.0 = Release|Any CPU
+               {70BC6544-A4C9-4325-9CE1-CC3F79787693}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {70BC6544-A4C9-4325-9CE1-CC3F79787693}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {70BC6544-A4C9-4325-9CE1-CC3F79787693}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {70BC6544-A4C9-4325-9CE1-CC3F79787693}.Release|Any CPU.Build.0 = Release|Any CPU
+               {C42B720C-323E-4E0C-ACBF-7FA9CFE228BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {C42B720C-323E-4E0C-ACBF-7FA9CFE228BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {C42B720C-323E-4E0C-ACBF-7FA9CFE228BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {C42B720C-323E-4E0C-ACBF-7FA9CFE228BE}.Release|Any CPU.Build.0 = Release|Any CPU
+               {A655131E-D439-4DE1-BC39-5C955306183F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {A655131E-D439-4DE1-BC39-5C955306183F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {A655131E-D439-4DE1-BC39-5C955306183F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {A655131E-D439-4DE1-BC39-5C955306183F}.Release|Any CPU.Build.0 = Release|Any CPU
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
        EndGlobalSection
+       GlobalSection(Performance) = preSolution
+               HasPerformanceSessions = true
+       EndGlobalSection
 EndGlobal