Browse Source

Added close confirmation dialog

flabbet 5 years ago
parent
commit
6f8b7ad82a

+ 24 - 0
PixiEditor/Models/Dialogs/ConfirmationDialog.cs

@@ -0,0 +1,24 @@
+using PixiEditor.Models.Enums;
+using PixiEditor.Views;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PixiEditor.Models.Dialogs
+{
+    public static class ConfirmationDialog
+    {
+        public static ConfirmationType Show(string message)
+        {
+            ConfirmationPopup popup = new ConfirmationPopup()
+            {
+                Body = message
+            };
+            if ((bool)popup.ShowDialog())
+            {
+                return popup.Result ? ConfirmationType.Yes : ConfirmationType.No;
+            }
+            return ConfirmationType.Canceled;
+        }
+    }
+}

+ 11 - 0
PixiEditor/Models/Enums/ConfirmationType.cs

@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace PixiEditor.Models.Enums
+{
+    public enum ConfirmationType
+    {
+        Yes, No, Canceled
+    }
+}

+ 37 - 4
PixiEditor/ViewModels/ViewModelMain.cs

@@ -3,8 +3,7 @@ using PixiEditor.Helpers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.Dialogs;
-using PixiEditor.Models.Enums;
-using PixiEditor.Models.Images;
+using PixiEditor.Models.Enums;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Position;
@@ -13,9 +12,9 @@ using PixiEditor.Models.Tools.Tools;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Collections.ObjectModel;
+using System.ComponentModel;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
-using System.Security.Cryptography.X509Certificates;
 using System.Windows;
 using System.Windows;
 using System.Windows.Input;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media;
@@ -25,6 +24,8 @@ namespace PixiEditor.ViewModels
 {
 {
     class ViewModelMain : ViewModelBase
     class ViewModelMain : ViewModelBase
     {
     {
+        public Action CloseAction { get; set; }
+
         public static ViewModelMain Current { get; set; } = null;
         public static ViewModelMain Current { get; set; } = null;
         public RelayCommand SelectToolCommand { get; set; } //Command that handles tool switching 
         public RelayCommand SelectToolCommand { get; set; } //Command that handles tool switching 
         public RelayCommand OpenNewFilePopupCommand { get; set; } //Command that generates draw area
         public RelayCommand OpenNewFilePopupCommand { get; set; } //Command that generates draw area
@@ -57,6 +58,7 @@ namespace PixiEditor.ViewModels
         public RelayCommand RemoveSwatchCommand { get; set; }
         public RelayCommand RemoveSwatchCommand { get; set; }
         public RelayCommand SaveDocumentCommand { get; set; }
         public RelayCommand SaveDocumentCommand { get; set; }
         public RelayCommand OnStartupCommand { get; set; }
         public RelayCommand OnStartupCommand { get; set; }
+        public RelayCommand CloseWindowCommand { get; set; }
 
 
 
 
         private double _mouseXonCanvas;
         private double _mouseXonCanvas;
@@ -170,6 +172,8 @@ namespace PixiEditor.ViewModels
             }
             }
         }
         }
 
 
+        private bool _unsavedDocumentModified = false;
+
         public ClipboardController ClipboardController { get; set; }
         public ClipboardController ClipboardController { get; set; }
 
 
         public ViewModelMain()
         public ViewModelMain()
@@ -210,6 +214,7 @@ namespace PixiEditor.ViewModels
             RemoveSwatchCommand = new RelayCommand(RemoveSwatch);
             RemoveSwatchCommand = new RelayCommand(RemoveSwatch);
             SaveDocumentCommand = new RelayCommand(SaveDocument, DocumentIsNotNull);
             SaveDocumentCommand = new RelayCommand(SaveDocument, DocumentIsNotNull);
             OnStartupCommand = new RelayCommand(OnStartup);
             OnStartupCommand = new RelayCommand(OnStartup);
+            CloseWindowCommand = new RelayCommand(CloseWindow);
             ToolSet = new ObservableCollection<Tool> {new MoveTool(), new PenTool(), new SelectTool(), new FloodFill(), new LineTool(),
             ToolSet = new ObservableCollection<Tool> {new MoveTool(), new PenTool(), new SelectTool(), new FloodFill(), new LineTool(),
             new CircleTool(), new RectangleTool(), new EarserTool(), new ColorPickerTool(), new BrightnessTool()};            
             new CircleTool(), new RectangleTool(), new EarserTool(), new ColorPickerTool(), new BrightnessTool()};            
             ShortcutController = new ShortcutController
             ShortcutController = new ShortcutController
@@ -251,6 +256,28 @@ namespace PixiEditor.ViewModels
             Current = this;
             Current = this;
         }
         }
 
 
+        private void CloseWindow(object property)
+        {
+            if (!(property is CancelEventArgs)) throw new ArgumentException();
+
+            (property as CancelEventArgs).Cancel = true;
+
+            ConfirmationType result = ConfirmationType.No;
+            if (_unsavedDocumentModified)
+            {
+                result = ConfirmationDialog.Show("Document was modified. Do you want to save changes?");
+                if(result == ConfirmationType.Yes)
+                {
+                    SaveDocument(null);
+                }
+            }
+            if (result != ConfirmationType.Canceled)
+            {
+                (property as CancelEventArgs).Cancel = false;
+            }
+
+        }
+
         private void OnStartup(object parameter)
         private void OnStartup(object parameter)
         {
         {
             var lastArg = Environment.GetCommandLineArgs().Last();
             var lastArg = Environment.GetCommandLineArgs().Last();
@@ -307,6 +334,7 @@ namespace PixiEditor.ViewModels
         {
         {
             BitmapManager.ActiveDocument = Importer.ImportDocument(path);
             BitmapManager.ActiveDocument = Importer.ImportDocument(path);
             Exporter.SaveDocumentPath = path;
             Exporter.SaveDocumentPath = path;
+            _unsavedDocumentModified = false;
         }
         }
 
 
         private void SaveDocument(object parameter)
         private void SaveDocument(object parameter)
@@ -320,6 +348,7 @@ namespace PixiEditor.ViewModels
             {
             {
                 Exporter.SaveAsEditableFile(BitmapManager.ActiveDocument, Exporter.SaveDocumentPath);
                 Exporter.SaveAsEditableFile(BitmapManager.ActiveDocument, Exporter.SaveDocumentPath);
             }
             }
+            _unsavedDocumentModified = false;
         }
         }
 
 
         private void RemoveSwatch(object parameter)
         private void RemoveSwatch(object parameter)
@@ -348,6 +377,7 @@ namespace PixiEditor.ViewModels
         {
         {
             ActiveSelection = new Selection(Array.Empty<Coordinates>());
             ActiveSelection = new Selection(Array.Empty<Coordinates>());
             RecenterZoombox = true;
             RecenterZoombox = true;
+            _unsavedDocumentModified = true;
         }
         }
 
 
         public void AddSwatch(Color color)
         public void AddSwatch(Color color)
@@ -482,6 +512,7 @@ namespace PixiEditor.ViewModels
         {
         {
             ChangesController.AddChanges(new LayerChange(e.PixelsChanged, e.ChangedLayerIndex),
             ChangesController.AddChanges(new LayerChange(e.PixelsChanged, e.ChangedLayerIndex),
                 new LayerChange(e.OldPixelsValues, e.ChangedLayerIndex));
                 new LayerChange(e.OldPixelsValues, e.ChangedLayerIndex));
+            _unsavedDocumentModified = true;
         }
         }
 
 
         public void SwapColors(object parameter)
         public void SwapColors(object parameter)
@@ -689,7 +720,7 @@ namespace PixiEditor.ViewModels
             if (dialog.ShowDialog())
             if (dialog.ShowDialog())
             {
             {
                 NewDocument(dialog.FileWidth, dialog.FileHeight);
                 NewDocument(dialog.FileWidth, dialog.FileHeight);
-                BitmapManager.ActiveDocument.ActiveLayer.LayerBitmap = Importer.ImportImage(dialog.FilePath, dialog.FileWidth, dialog.FileHeight);
+                BitmapManager.ActiveDocument.ActiveLayer.LayerBitmap = Importer.ImportImage(dialog.FilePath, dialog.FileWidth, dialog.FileHeight);
             }
             }
         }
         }
 
 
@@ -702,6 +733,8 @@ namespace PixiEditor.ViewModels
             UndoManager.RedoStack.Clear();
             UndoManager.RedoStack.Clear();
             ActiveSelection = new Selection(Array.Empty<Coordinates>());
             ActiveSelection = new Selection(Array.Empty<Coordinates>());
             RecenterZoombox = !RecenterZoombox;
             RecenterZoombox = !RecenterZoombox;
+            Exporter.SaveDocumentPath = null;
+            _unsavedDocumentModified = false;
         }
         }
 
 
         public void NewLayer(object parameter)
         public void NewLayer(object parameter)

+ 40 - 0
PixiEditor/Views/ConfirmationPopup.xaml

@@ -0,0 +1,40 @@
+<Window x:Class="PixiEditor.Views.ConfirmationPopup"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:system="clr-namespace:System;assembly=System.Runtime"
+        mc:Ignorable="d"
+        Title="ConfirmationPopup" Name="popup" WindowStartupLocation="CenterScreen" Height="200" Width="500" WindowStyle="None">
+
+    <WindowChrome.WindowChrome>
+        <WindowChrome CaptionHeight="32" ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
+    </WindowChrome.WindowChrome>
+
+    <Grid Background="{StaticResource AccentColor}">
+        <Grid.RowDefinitions>
+            <RowDefinition Height="35"/>
+            <RowDefinition Height="34*"/>
+            <RowDefinition Height="21*"/>
+        </Grid.RowDefinitions>
+        <TextBlock Grid.Row="1" Text="{Binding Body, ElementName=popup}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="18" Foreground="White"/>
+        <DockPanel Grid.Row="0" Background="{StaticResource MainColor}">
+            <Button DockPanel.Dock="Right" HorizontalAlignment="Right" Style="{StaticResource CloseButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Close"
+                            Command="{Binding DataContext.CancelCommand, ElementName=popup}"/>
+        </DockPanel>
+        <StackPanel Grid.Row="2" Orientation="Horizontal" VerticalAlignment="Bottom" HorizontalAlignment="Center"  Margin="0,0,10,10">
+            <Button Margin="10,0,10,0" Height="30" Width="60" Command="{Binding Path=DataContext.SetResultAndCloseCommand, ElementName=popup}" 
+                Style="{StaticResource DarkRoundButton}" Content="Yes">
+                <Button.CommandParameter>
+                    <system:Boolean>True</system:Boolean>
+                </Button.CommandParameter>
+            </Button>
+            <Button Height="30" Width="60" Command="{Binding Path=DataContext.SetResultAndCloseCommand, ElementName=popup}" Style="{StaticResource DarkRoundButton}" Content="No">
+                <Button.CommandParameter>
+                    <system:Boolean>False</system:Boolean>
+                </Button.CommandParameter>
+            </Button>
+            <Button Margin="10,0,10,0" Height="30" Width="80" Style="{StaticResource DarkRoundButton}" Content="Cancel"
+                    Command="{Binding DataContext.CancelCommand, ElementName=popup}"/>
+        </StackPanel>
+    </Grid>
+</Window>

+ 61 - 0
PixiEditor/Views/ConfirmationPopup.xaml.cs

@@ -0,0 +1,61 @@
+using PixiEditor.Helpers;
+using System;
+using System.Windows;
+using System.Windows.Input;
+
+namespace PixiEditor.Views
+{
+    /// <summary>
+    /// Interaction logic for ConfirmationPopup.xaml
+    /// </summary>
+    public partial class ConfirmationPopup : Window
+    {
+        public RelayCommand CancelCommand { get; set; }
+        public RelayCommand SetResultAndCloseCommand { get; set; }
+
+        public ConfirmationPopup()
+        {
+            InitializeComponent();
+            CancelCommand = new RelayCommand(Cancel);
+            SetResultAndCloseCommand = new RelayCommand(SetResultAndClose);
+            DataContext = this;
+        }
+
+        private void SetResultAndClose(object property)
+        {
+            bool result = (bool)property;
+            Result = result;
+            DialogResult = true;
+            Close();
+        }
+
+        private void Cancel(object property)
+        {
+            DialogResult = false;
+            Close();
+        }
+
+        public bool Result
+        {
+            get { return (bool)GetValue(SaveChangesProperty); }
+            set { SetValue(SaveChangesProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for SaveChanges.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty SaveChangesProperty =
+            DependencyProperty.Register("SaveChanges", typeof(bool), typeof(ConfirmationPopup), new PropertyMetadata(true));
+
+
+
+        public string Body
+        {
+            get { return (string)GetValue(BodyProperty); }
+            set { SetValue(BodyProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for Body.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty BodyProperty =
+            DependencyProperty.Register("Body", typeof(string), typeof(ConfirmationPopup), new PropertyMetadata(""));
+
+    }
+}

+ 5 - 3
PixiEditor/Views/MainWindow.xaml

@@ -9,9 +9,8 @@
         xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
         xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
         xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
         xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
         xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
         xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
-        xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock"
         xmlns:ui="clr-namespace:PixiEditor.Helpers.UI"
         xmlns:ui="clr-namespace:PixiEditor.Helpers.UI"
-        xmlns:cmd="http://www.galasoft.ch/mvvmlight" xmlns:shell="clr-namespace:Microsoft.Windows.Shell;assembly=Xceed.Wpf.AvalonDock" xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
+        xmlns:cmd="http://www.galasoft.ch/mvvmlight" xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
         mc:Ignorable="d" WindowStyle="None" 
         mc:Ignorable="d" WindowStyle="None" 
         Title="PixiEditor" Name="mainWindow" Height="1000" Width="1600" Background="{StaticResource MainColor}" 
         Title="PixiEditor" Name="mainWindow" Height="1000" Width="1600" Background="{StaticResource MainColor}" 
         WindowStartupLocation="CenterScreen" WindowState="Maximized" DataContext="{DynamicResource ViewModelMain}">
         WindowStartupLocation="CenterScreen" WindowState="Maximized" DataContext="{DynamicResource ViewModelMain}">
@@ -28,7 +27,7 @@
     </Window.Resources>
     </Window.Resources>
 
 
     <Window.CommandBindings>
     <Window.CommandBindings>
-        <CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Close" />
+        <CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Close"/>
         <CommandBinding Command="{x:Static SystemCommands.MaximizeWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Maximize" />
         <CommandBinding Command="{x:Static SystemCommands.MaximizeWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Maximize" />
         <CommandBinding Command="{x:Static SystemCommands.MinimizeWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Minimize" />
         <CommandBinding Command="{x:Static SystemCommands.MinimizeWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Minimize" />
         <CommandBinding Command="{x:Static SystemCommands.RestoreWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Restore" />
         <CommandBinding Command="{x:Static SystemCommands.RestoreWindowCommand}" CanExecute="CommandBinding_CanExecute" Executed="CommandBinding_Executed_Restore" />
@@ -41,6 +40,9 @@
         <i:EventTrigger EventName="ContentRendered">
         <i:EventTrigger EventName="ContentRendered">
             <i:InvokeCommandAction Command="{Binding OnStartupCommand}"/>
             <i:InvokeCommandAction Command="{Binding OnStartupCommand}"/>
         </i:EventTrigger>
         </i:EventTrigger>
+        <i:EventTrigger EventName="Closing">
+            <cmd:EventToCommand Command="{Binding CloseWindowCommand}" PassEventArgsToCommand="True"/>
+        </i:EventTrigger>
     </i:Interaction.Triggers>
     </i:Interaction.Triggers>
     <Grid Name="mainGrid" Margin="5">
     <Grid Name="mainGrid" Margin="5">
         <Grid.ColumnDefinitions>
         <Grid.ColumnDefinitions>

+ 5 - 2
PixiEditor/Views/MainWindow.xaml.cs

@@ -1,4 +1,5 @@
-using System;
+using PixiEditor.ViewModels;
+using System;
 using System.Windows;
 using System.Windows;
 using System.Windows.Input;
 using System.Windows.Input;
 
 
@@ -14,6 +15,9 @@ namespace PixiEditor
             InitializeComponent();
             InitializeComponent();
             StateChanged += MainWindowStateChangeRaised;
             StateChanged += MainWindowStateChangeRaised;
             MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
             MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
+            ViewModelMain vm = new ViewModelMain();
+            vm.CloseAction = new Action(Close);
+            DataContext = vm;
         }
         }
 
 
         private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
         private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
@@ -39,7 +43,6 @@ namespace PixiEditor
             SystemCommands.RestoreWindow(this);
             SystemCommands.RestoreWindow(this);
         }
         }
 
 
-
         private void CommandBinding_Executed_Close(object sender, ExecutedRoutedEventArgs e)
         private void CommandBinding_Executed_Close(object sender, ExecutedRoutedEventArgs e)
         {
         {
             SystemCommands.CloseWindow(this);
             SystemCommands.CloseWindow(this);