flabbet 4 years ago
parent
commit
19cc6ba6eb

+ 12 - 69
PixiEditor/Models/Controllers/BitmapManager.cs

@@ -1,5 +1,6 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.Linq;
 using System.Linq;
 using System.Windows;
 using System.Windows;
 using System.Windows.Input;
 using System.Windows.Input;
@@ -7,7 +8,6 @@ using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Media.Imaging;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DataHolders;
-using PixiEditor.Models.Enums;
 using PixiEditor.Models.Events;
 using PixiEditor.Models.Events;
 using PixiEditor.Models.ImageManipulation;
 using PixiEditor.Models.ImageManipulation;
 using PixiEditor.Models.Layers;
 using PixiEditor.Models.Layers;
@@ -34,9 +34,7 @@ namespace PixiEditor.Models.Controllers
             MouseController.OnMouseUp += MouseController_OnMouseUp;
             MouseController.OnMouseUp += MouseController_OnMouseUp;
             BitmapOperations = new BitmapOperationsUtility(this);
             BitmapOperations = new BitmapOperationsUtility(this);
             ReadonlyToolUtility = new ReadonlyToolUtility();
             ReadonlyToolUtility = new ReadonlyToolUtility();
-        }
-
-        public event EventHandler<LayersChangedEventArgs> LayersChanged;
+        }
 
 
         public event EventHandler<DocumentChangedEventArgs> DocumentChanged;
         public event EventHandler<DocumentChangedEventArgs> DocumentChanged;
 
 
@@ -96,6 +94,8 @@ namespace PixiEditor.Models.Controllers
             }
             }
         }
         }
 
 
+        public ObservableCollection<Document> Documents { get; set; } = new ObservableCollection<Document>();
+
         /// <summary>
         /// <summary>
         ///     Returns if tool is BitmapOperationTool.
         ///     Returns if tool is BitmapOperationTool.
         /// </summary>
         /// </summary>
@@ -104,71 +104,6 @@ namespace PixiEditor.Models.Controllers
             return tool is BitmapOperationTool;
             return tool is BitmapOperationTool;
         }
         }
 
 
-        public void SetActiveTool(Tool tool)
-        {
-            PreviewLayer = null;
-            SelectedTool?.Toolbar.SaveToolbarSettings();
-            SelectedTool = tool;
-            SelectedTool.Toolbar.LoadSharedSettings();
-        }
-
-        public void SetActiveLayer(int index)
-        {
-            if (ActiveDocument.ActiveLayerIndex <= ActiveDocument.Layers.Count - 1)
-            {
-                ActiveDocument.ActiveLayer.IsActive = false;
-            }
-
-            ActiveDocument.ActiveLayerIndex = index;
-            ActiveDocument.ActiveLayer.IsActive = true;
-            LayersChanged?.Invoke(this, new LayersChangedEventArgs(index, LayerAction.SetActive));
-        }
-
-        public void AddNewLayer(string name, WriteableBitmap bitmap, bool setAsActive = true)
-        {
-            AddNewLayer(name, bitmap.PixelWidth, bitmap.PixelHeight, setAsActive);
-            ActiveDocument.Layers.Last().LayerBitmap = bitmap;
-        }
-
-        public void AddNewLayer(string name, bool setAsActive = true)
-        {
-            AddNewLayer(name, 0, 0, setAsActive);
-        }
-
-        public void AddNewLayer(string name, int width, int height, bool setAsActive = true)
-        {
-            ActiveDocument.Layers.Add(new Layer(name, width, height)
-            {
-                MaxHeight = ActiveDocument.Height,
-                MaxWidth = ActiveDocument.Width
-            });
-            if (setAsActive)
-            {
-                SetActiveLayer(ActiveDocument.Layers.Count - 1);
-            }
-
-            LayersChanged?.Invoke(this, new LayersChangedEventArgs(0, LayerAction.Add));
-        }
-
-        public void RemoveLayer(int layerIndex)
-        {
-            if (ActiveDocument.Layers.Count == 0)
-            {
-                return;
-            }
-
-            bool wasActive = ActiveDocument.Layers[layerIndex].IsActive;
-            ActiveDocument.Layers.RemoveAt(layerIndex);
-            if (wasActive)
-            {
-                SetActiveLayer(0);
-            }
-            else if (ActiveDocument.ActiveLayerIndex > ActiveDocument.Layers.Count - 1)
-            {
-                SetActiveLayer(ActiveDocument.Layers.Count - 1);
-            }
-        }
-
         public void ExecuteTool(Coordinates newPosition, bool clickedOnCanvas)
         public void ExecuteTool(Coordinates newPosition, bool clickedOnCanvas)
         {
         {
             if (SelectedTool.CanStartOutsideCanvas || clickedOnCanvas)
             if (SelectedTool.CanStartOutsideCanvas || clickedOnCanvas)
@@ -207,6 +142,14 @@ namespace PixiEditor.Models.Controllers
         public bool IsOperationTool()
         public bool IsOperationTool()
         {
         {
             return IsOperationTool(SelectedTool);
             return IsOperationTool(SelectedTool);
+        }
+
+        public void SetActiveTool(Tool tool)
+        {
+            PreviewLayer = null;
+            SelectedTool?.Toolbar.SaveToolbarSettings();
+            SelectedTool = tool;
+            SelectedTool.Toolbar.LoadSharedSettings();
         }
         }
 
 
         private void Controller_MousePositionChanged(object sender, MouseMovementEventArgs e)
         private void Controller_MousePositionChanged(object sender, MouseMovementEventArgs e)

+ 2 - 2
PixiEditor/Models/Controllers/ClipboardController.cs

@@ -58,7 +58,7 @@ namespace PixiEditor.Models.Controllers
                 return;
                 return;
             }
             }
 
 
-            ViewModelMain.Current.BitmapManager.RemoveLayer((int)parameters[0]);
+            ViewModelMain.Current.BitmapManager.ActiveDocument.RemoveLayer((int)parameters[0]);
         }
         }
 
 
         private static void AddLayerProcess(object[] parameters)
         private static void AddLayerProcess(object[] parameters)
@@ -125,7 +125,7 @@ namespace PixiEditor.Models.Controllers
 
 
         private static void AddImageToLayers(WriteableBitmap image)
         private static void AddImageToLayers(WriteableBitmap image)
         {
         {
-            ViewModelMain.Current.BitmapManager.AddNewLayer("Image", image);
+            ViewModelMain.Current.BitmapManager.ActiveDocument.AddNewLayer("Image", image);
         }
         }
     }
     }
 }
 }

+ 72 - 0
PixiEditor/Models/DataHolders/Document.cs

@@ -3,6 +3,7 @@ using System.Collections.ObjectModel;
 using System.Linq;
 using System.Linq;
 using System.Windows;
 using System.Windows;
 using System.Windows.Media;
 using System.Windows.Media;
+using System.Windows.Media.Imaging;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Enums;
 using PixiEditor.Models.Enums;
@@ -25,6 +26,20 @@ namespace PixiEditor.Models.DataHolders
 
 
         public event EventHandler<DocumentSizeChangedEventArgs> DocumentSizeChanged;
         public event EventHandler<DocumentSizeChangedEventArgs> DocumentSizeChanged;
 
 
+        public event EventHandler<LayersChangedEventArgs> LayersChanged;
+
+        private string name = "Untitled";
+
+        public string Name
+        {
+            get => name;
+            set
+            {
+                name = value;
+                RaisePropertyChanged(nameof(Name));
+            }
+        }
+
         public int Width
         public int Width
         {
         {
             get => width;
             get => width;
@@ -96,6 +111,63 @@ namespace PixiEditor.Models.DataHolders
             DocumentSizeChanged?.Invoke(this, new DocumentSizeChangedEventArgs(oldWidth, oldHeight, width, height));
             DocumentSizeChanged?.Invoke(this, new DocumentSizeChangedEventArgs(oldWidth, oldHeight, width, height));
         }
         }
 
 
+        public void SetActiveLayer(int index)
+        {
+            if (ActiveLayerIndex <= Layers.Count - 1)
+            {
+                ActiveLayer.IsActive = false;
+            }
+
+            ActiveLayerIndex = index;
+            ActiveLayer.IsActive = true;
+            LayersChanged?.Invoke(this, new LayersChangedEventArgs(index, LayerAction.SetActive));
+        }
+
+        public void AddNewLayer(string name, WriteableBitmap bitmap, bool setAsActive = true)
+        {
+            AddNewLayer(name, bitmap.PixelWidth, bitmap.PixelHeight, setAsActive);
+            Layers.Last().LayerBitmap = bitmap;
+        }
+
+        public void AddNewLayer(string name, bool setAsActive = true)
+        {
+            AddNewLayer(name, 0, 0, setAsActive);
+        }
+
+        public void AddNewLayer(string name, int width, int height, bool setAsActive = true)
+        {
+            Layers.Add(new Layer(name, width, height)
+            {
+                MaxHeight = Height,
+                MaxWidth = Width
+            });
+            if (setAsActive)
+            {
+                SetActiveLayer(Layers.Count - 1);
+            }
+
+            LayersChanged?.Invoke(this, new LayersChangedEventArgs(0, LayerAction.Add));
+        }
+
+        public void RemoveLayer(int layerIndex)
+        {
+            if (Layers.Count == 0)
+            {
+                return;
+            }
+
+            bool wasActive = Layers[layerIndex].IsActive;
+            Layers.RemoveAt(layerIndex);
+            if (wasActive)
+            {
+                SetActiveLayer(0);
+            }
+            else if (ActiveLayerIndex > Layers.Count - 1)
+            {
+                SetActiveLayer(Layers.Count - 1);
+            }
+        }
+
         /// <summary>
         /// <summary>
         ///     Resizes all document layers using NearestNeighbor interpolation.
         ///     Resizes all document layers using NearestNeighbor interpolation.
         /// </summary>
         /// </summary>

+ 7 - 3
PixiEditor/ViewModels/SubViewModels/Main/FileViewModel.cs

@@ -6,6 +6,7 @@ using System.Windows.Media.Imaging;
 using Microsoft.Win32;
 using Microsoft.Win32;
 using PixiEditor.Exceptions;
 using PixiEditor.Exceptions;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
+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.Enums;
@@ -49,10 +50,11 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
 
 
         public void NewDocument(int width, int height, bool addBaseLayer = true)
         public void NewDocument(int width, int height, bool addBaseLayer = true)
         {
         {
-            Owner.BitmapManager.ActiveDocument = new Document(width, height);
+            Owner.BitmapManager.Documents.Add(new Document(width, height));
+            Owner.BitmapManager.ActiveDocument = Owner.BitmapManager.Documents[^1];
             if (addBaseLayer)
             if (addBaseLayer)
             {
             {
-                Owner.BitmapManager.AddNewLayer("Base Layer");
+                Owner.BitmapManager.ActiveDocument.AddNewLayer("Base Layer");
             }
             }
 
 
             Owner.ResetProgramStateValues();
             Owner.ResetProgramStateValues();
@@ -74,7 +76,9 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             if (dialog.ShowDialog())
             if (dialog.ShowDialog())
             {
             {
                 NewDocument(dialog.FileWidth, dialog.FileHeight, false);
                 NewDocument(dialog.FileWidth, dialog.FileHeight, false);
-                Owner.BitmapManager.AddNewLayer("Image", Importer.ImportImage(dialog.FilePath, dialog.FileWidth, dialog.FileHeight));
+                Owner.BitmapManager.ActiveDocument.AddNewLayer(
+                    "Image",
+                    Importer.ImportImage(dialog.FilePath, dialog.FileWidth, dialog.FileHeight));
             }
             }
         }
         }
 
 

+ 6 - 5
PixiEditor/ViewModels/SubViewModels/Main/LayersViewModel.cs

@@ -29,7 +29,8 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
 
 
         public void NewLayer(object parameter)
         public void NewLayer(object parameter)
         {
         {
-            Owner.BitmapManager.AddNewLayer($"New Layer {Owner.BitmapManager.ActiveDocument.Layers.Count}");
+            //TODO: Implement AddNewLayer to Document, not BitmapManager
+            Owner.BitmapManager.ActiveDocument.AddNewLayer($"New Layer {Owner.BitmapManager.ActiveDocument.Layers.Count}");
         }
         }
 
 
         public bool CanCreateNewLayer(object parameter)
         public bool CanCreateNewLayer(object parameter)
@@ -39,12 +40,12 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
 
 
         public void SetActiveLayer(object parameter)
         public void SetActiveLayer(object parameter)
         {
         {
-            Owner.BitmapManager.SetActiveLayer((int)parameter);
+            Owner.BitmapManager.ActiveDocument.SetActiveLayer((int)parameter);
         }
         }
 
 
         public void DeleteLayer(object parameter)
         public void DeleteLayer(object parameter)
         {
         {
-            Owner.BitmapManager.RemoveLayer((int)parameter);
+            Owner.BitmapManager.ActiveDocument.RemoveLayer((int)parameter);
         }
         }
 
 
         public bool CanDeleteLayer(object property)
         public bool CanDeleteLayer(object property)
@@ -63,7 +64,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             Owner.BitmapManager.ActiveDocument.Layers.Move(oldIndex, oldIndex + 1);
             Owner.BitmapManager.ActiveDocument.Layers.Move(oldIndex, oldIndex + 1);
             if (Owner.BitmapManager.ActiveDocument.ActiveLayerIndex == oldIndex)
             if (Owner.BitmapManager.ActiveDocument.ActiveLayerIndex == oldIndex)
             {
             {
-                Owner.BitmapManager.SetActiveLayer(oldIndex + 1);
+                Owner.BitmapManager.ActiveDocument.SetActiveLayer(oldIndex + 1);
             }
             }
         }
         }
 
 
@@ -73,7 +74,7 @@ namespace PixiEditor.ViewModels.SubViewModels.Main
             Owner.BitmapManager.ActiveDocument.Layers.Move(oldIndex, oldIndex - 1);
             Owner.BitmapManager.ActiveDocument.Layers.Move(oldIndex, oldIndex - 1);
             if (Owner.BitmapManager.ActiveDocument.ActiveLayerIndex == oldIndex)
             if (Owner.BitmapManager.ActiveDocument.ActiveLayerIndex == oldIndex)
             {
             {
-                Owner.BitmapManager.SetActiveLayer(oldIndex - 1);
+                Owner.BitmapManager.ActiveDocument.SetActiveLayer(oldIndex - 1);
             }
             }
         }
         }
 
 

+ 29 - 57
PixiEditor/Views/MainWindow.xaml

@@ -12,7 +12,7 @@
         xmlns:ui="clr-namespace:PixiEditor.Helpers.UI"
         xmlns:ui="clr-namespace:PixiEditor.Helpers.UI"
         xmlns:cmd="http://www.galasoft.ch/mvvmlight" 
         xmlns:cmd="http://www.galasoft.ch/mvvmlight" 
         xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
         xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
-        xmlns:colorpicker="clr-namespace:ColorPicker;assembly=ColorPicker"
+        xmlns:colorpicker="clr-namespace:ColorPicker;assembly=ColorPicker" xmlns:usercontrols="clr-namespace:PixiEditor.Views.UserControls"
         mc:Ignorable="d" WindowStyle="None" Initialized="MainWindow_Initialized"
         mc:Ignorable="d" WindowStyle="None" Initialized="MainWindow_Initialized"
         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}">
@@ -164,61 +164,33 @@
         </StackPanel>
         </StackPanel>
         <Grid Grid.Column="1" Grid.Row="2" Background="#303030" Margin="0,7,5,0">
         <Grid Grid.Column="1" Grid.Row="2" Background="#303030" Margin="0,7,5,0">
             <Grid>
             <Grid>
-                <vws:MainDrawingPanel ZoomPercentage="{Binding ViewportSubViewModel.ZoomPercentage, Mode=TwoWay}" Center="{Binding ViewportSubViewModel.RecenterZoombox, Mode=TwoWay}" x:Name="DrawingPanel"
-                                      CenterOnStart="True" Cursor="{Binding ToolsSubViewModel.ToolCursor}" 
-                                      MiddleMouseClickedCommand="{Binding ToolsSubViewModel.SelectToolCommand}" 
-                                      MiddleMouseClickedCommandParameter="{x:Static tools:ToolType.MoveViewport}"
-                                      ViewportPosition="{Binding ViewportSubViewModel.ViewportPosition, Mode=TwoWay}">
-                    <i:Interaction.Triggers>
-                        <i:EventTrigger EventName="MouseMove">
-                            <i:InvokeCommandAction Command="{Binding IoSubViewModel.MouseMoveCommand}" />
-                        </i:EventTrigger>
-                        <i:EventTrigger EventName="MouseDown">
-                            <i:InvokeCommandAction Command="{Binding IoSubViewModel.MouseDownCommand}"/>
-                        </i:EventTrigger>
-                    </i:Interaction.Triggers>
-                    <i:Interaction.Behaviors>
-                        <behaviors:MouseBehaviour RelativeTo="{Binding ElementName=DrawingPanel, Path=Item}"
-                                                  MouseX="{Binding IoSubViewModel.MouseXOnCanvas, Mode=OneWayToSource}"
-                                                  MouseY="{Binding IoSubViewModel.MouseYOnCanvas, Mode=OneWayToSource}" />
-                    </i:Interaction.Behaviors>
-                    <vws:MainDrawingPanel.Item>
-                        <Canvas Width="{Binding BitmapManager.ActiveDocument.Width}"
-                                Height="{Binding BitmapManager.ActiveDocument.Height}" VerticalAlignment="Center"
-                                HorizontalAlignment="Center">
-                            <Image Source="/Images/transparentbg.png"
-                                   Height="{Binding BitmapManager.ActiveDocument.Height}"
-                                   Width="{Binding BitmapManager.ActiveDocument.Width}" Opacity="0.9"
-                                   Stretch="UniformToFill" />
-                            <Image Source="{Binding BitmapManager.PreviewLayer.LayerBitmap}" Panel.ZIndex="2"
-                                   RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"
-                                   Width="{Binding BitmapManager.PreviewLayer.Width}"
-                                   Height="{Binding BitmapManager.PreviewLayer.Height}" 
-                                   Margin="{Binding BitmapManager.PreviewLayer.Offset}"/>
-                            <ItemsControl ItemsSource="{Binding BitmapManager.ActiveDocument.Layers}">
-                                <ItemsControl.ItemsPanel>
-                                    <ItemsPanelTemplate>
-                                        <Grid />
-                                    </ItemsPanelTemplate>
-                                </ItemsControl.ItemsPanel>
-                                <ItemsControl.ItemTemplate>
-                                    <DataTemplate>
-                                        <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding LayerBitmap}"
-                                               Visibility="{Binding IsVisible, Converter={StaticResource BoolToVisibilityConverter}}"
-                                               RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"
-                                               Opacity="{Binding Opacity}"
-                                               Width="{Binding Width}" Height="{Binding Height}" Margin="{Binding Offset}" />
-                                    </DataTemplate>
-                                </ItemsControl.ItemTemplate>
-                            </ItemsControl>
-                            <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding SelectionSubViewModel.ActiveSelection.SelectionLayer.LayerBitmap}"
-                                   RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"
-                                   Width="{Binding SelectionSubViewModel.ActiveSelection.SelectionLayer.Width}"
-                                   Height="{Binding SelectionSubViewModel.ActiveSelection.SelectionLayer.Height}" 
-                                   Margin="{Binding SelectionSubViewModel.ActiveSelection.SelectionLayer.Offset}" />
-                        </Canvas>
-                    </vws:MainDrawingPanel.Item>
-                </vws:MainDrawingPanel>
+                <avalondock:DockingManager ActiveContent="{Binding BitmapManager.ActiveDocument, Mode=TwoWay}" DocumentsSource="{Binding BitmapManager.Documents}">
+                    <avalondock:DockingManager.Theme>
+                        <avalondock:Vs2013DarkTheme/>
+                    </avalondock:DockingManager.Theme>
+                    <avalondock:DockingManager.LayoutItemContainerStyle>
+                        <Style TargetType="{x:Type avalondock:LayoutItem}">
+                            <Setter Property="Title" Value="{Binding Model.Name}" />
+                            <Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}" />
+                            <Setter Property="CanClose" Value="{Binding Model.CanClose}" />
+                        </Style>
+                    </avalondock:DockingManager.LayoutItemContainerStyle>
+                    <avalondock:DockingManager.LayoutItemTemplate>
+                        <DataTemplate DataType="{x:Type vm:ViewModelMain}">
+                            <usercontrols:DrawingViewPort DataContext="{Binding Path=DataContext, 
+                                RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
+                                        ZoomPercentage="{Binding ViewportSubViewModel.ZoomPercentage}"
+                                        RecenterZoombox="{Binding ViewportSubViewModel.RecenterZoombox}"
+                                        Cursor="{Binding ToolsSubViewModel.ToolCursor}"
+                                        MiddleMouseClickedCommand="{Binding ToolsSubViewModel.SelectToolCommand}"
+                                        ViewportPosition="{Binding ViewportSubViewModel.ViewportPosition}"
+                                        MouseMoveCommand="{Binding IoSubViewModel.MouseMoveCommand}"
+                                        MouseDownCommand="{Binding IoSubViewModel.MouseDownCommand}"
+                                        MouseXOnCanvas="{Binding IoSubViewModel.MouseXOnCanvas, Mode=TwoWay}"
+                                        MouseYOnCanvas="{Binding IoSubViewModel.MouseYOnCanvas, Mode=TwoWay}"/>
+                        </DataTemplate>
+                    </avalondock:DockingManager.LayoutItemTemplate>
+                </avalondock:DockingManager>
             </Grid>
             </Grid>
         </Grid>
         </Grid>
 
 
@@ -386,7 +358,7 @@
             </avalondock:DockingManager>
             </avalondock:DockingManager>
         </Grid>
         </Grid>
         <DockPanel Grid.Row="3" Grid.Column="1">
         <DockPanel Grid.Row="3" Grid.Column="1">
-            <TextBlock Text="{Binding BitmapManager.SelectedTool.ActionDisplay}" Foreground="White" FontSize="16"  VerticalAlignment="Center"/>
+            <TextBlock Text="{Binding BitmapManager.SelectedTool.ActionDisplay}" Foreground="White" FontSize="15"  VerticalAlignment="Center"/>
             <StackPanel DockPanel.Dock="Right" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
             <StackPanel DockPanel.Dock="Right" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
                 <TextBlock Text="X:" Foreground="White" FontSize="16"/>
                 <TextBlock Text="X:" Foreground="White" FontSize="16"/>
                 <TextBlock Margin="4,0,10,0" Text="{Binding IoSubViewModel.MouseXOnCanvas, Converter={StaticResource DoubleToIntConverter}}" Foreground="White" FontSize="16"/>
                 <TextBlock Margin="4,0,10,0" Text="{Binding IoSubViewModel.MouseXOnCanvas, Converter={StaticResource DoubleToIntConverter}}" Foreground="White" FontSize="16"/>

+ 74 - 0
PixiEditor/Views/UserControls/DrawingViewPort.xaml

@@ -0,0 +1,74 @@
+<UserControl x:Class="PixiEditor.Views.UserControls.DrawingViewPort"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:PixiEditor.Views.UserControls" 
+             xmlns:tools="clr-namespace:PixiEditor.Models.Tools"
+             xmlns:vws="clr-namespace:PixiEditor.Views" 
+             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
+             xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours" xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="800" Name="uc">
+    <UserControl.Resources>
+        <converters:BoolToIntConverter x:Key="BoolToIntConverter" />
+        <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
+    </UserControl.Resources>
+    <vws:MainDrawingPanel ZoomPercentage="{Binding ZoomPercentage, Mode=TwoWay, ElementName=uc}"
+                          Center="{Binding RecenterZoombox, Mode=TwoWay, ElementName=uc}" 
+                          x:Name="DrawingPanel"
+                          CenterOnStart="True" Cursor="{Binding Cursor, ElementName=uc}" 
+                          MiddleMouseClickedCommand="{Binding MiddleMouseClickedCommand, ElementName=uc}" 
+                          MiddleMouseClickedCommandParameter="{x:Static tools:ToolType.MoveViewport}"
+                          ViewportPosition="{Binding ViewportPosition, ElementName=uc, Mode=TwoWay}">
+            <i:Interaction.Triggers>
+                <i:EventTrigger EventName="MouseMove">
+                    <i:InvokeCommandAction Command="{Binding MouseMoveCommand, ElementName=uc}" />
+                </i:EventTrigger>
+                <i:EventTrigger EventName="MouseDown">
+                    <i:InvokeCommandAction Command="{Binding MouseDownCommand, ElementName=uc}"/>
+                </i:EventTrigger>
+            </i:Interaction.Triggers>
+            <i:Interaction.Behaviors>
+                <behaviors:MouseBehaviour RelativeTo="{Binding ElementName=DrawingPanel, Path=Item}"
+                                                  MouseX="{Binding MouseXOnCanvas, Mode=TwoWay, ElementName=uc}"
+                                                  MouseY="{Binding MouseYOnCanvas, Mode=TwoWay, ElementName=uc}" />
+            </i:Interaction.Behaviors>
+            <vws:MainDrawingPanel.Item>
+                <Canvas Width="{Binding BitmapManager.ActiveDocument.Width}"
+                                Height="{Binding BitmapManager.ActiveDocument.Height}" VerticalAlignment="Center"
+                                HorizontalAlignment="Center">
+                    <Image Source="/Images/transparentbg.png"
+                                   Height="{Binding BitmapManager.ActiveDocument.Height}"
+                                   Width="{Binding BitmapManager.ActiveDocument.Width}" Opacity="0.9"
+                                   Stretch="UniformToFill" />
+                <Image Source="{Binding BitmapManager.PreviewLayer.LayerBitmap}" Panel.ZIndex="2"
+                                   RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"
+                                   Width="{Binding BitmapManager.PreviewLayer.Width}"
+                                   Height="{Binding BitmapManager.PreviewLayer.Height}" 
+                                   Margin="{Binding BitmapManager.PreviewLayer.Offset}"/>
+                <ItemsControl ItemsSource="{Binding BitmapManager.ActiveDocument.Layers}">
+                        <ItemsControl.ItemsPanel>
+                            <ItemsPanelTemplate>
+                                <Grid />
+                            </ItemsPanelTemplate>
+                        </ItemsControl.ItemsPanel>
+                        <ItemsControl.ItemTemplate>
+                            <DataTemplate>
+                                <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding LayerBitmap}"
+                                               Visibility="{Binding IsVisible, Converter={StaticResource BoolToVisibilityConverter}}"
+                                               RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"
+                                               Opacity="{Binding Opacity}"
+                                               Width="{Binding Width}" Height="{Binding Height}" Margin="{Binding Offset}" />
+                            </DataTemplate>
+                        </ItemsControl.ItemTemplate>
+                    </ItemsControl>
+                    <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding SelectionSubViewModel.ActiveSelection.SelectionLayer.LayerBitmap}"
+                                   RenderOptions.BitmapScalingMode="NearestNeighbor" Stretch="Uniform"
+                                   Width="{Binding SelectionSubViewModel.ActiveSelection.SelectionLayer.Width}"
+                                   Height="{Binding SelectionSubViewModel.ActiveSelection.SelectionLayer.Height}" 
+                                   Margin="{Binding SelectionSubViewModel.ActiveSelection.SelectionLayer.Offset}" />
+                </Canvas>
+            </vws:MainDrawingPanel.Item>
+        </vws:MainDrawingPanel>
+</UserControl>

+ 105 - 0
PixiEditor/Views/UserControls/DrawingViewPort.xaml.cs

@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using PixiEditor.Models.Controllers;
+using PixiEditor.Models.DataHolders;
+using PixiEditor.Models.Position;
+
+namespace PixiEditor.Views.UserControls
+{
+    /// <summary>
+    /// Interaction logic for DrawingViewPort.xaml.
+    /// </summary>
+    public partial class DrawingViewPort : UserControl
+    {
+        public DrawingViewPort()
+        {
+            InitializeComponent();
+        }
+
+        public float ZoomPercentage
+        {
+            get { return (float)GetValue(ZoomPercentageProperty); }
+            set { SetValue(ZoomPercentageProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for ZoomPercentage.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty ZoomPercentageProperty =
+            DependencyProperty.Register("ZoomPercentage", typeof(float), typeof(DrawingViewPort), new PropertyMetadata(100f));
+
+        public bool RecenterZoombox
+        {
+            get { return (bool)GetValue(RecenterZoomboxProperty); }
+            set { SetValue(RecenterZoomboxProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for RecenterZoombox.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty RecenterZoomboxProperty =
+            DependencyProperty.Register("RecenterZoombox", typeof(bool), typeof(DrawingViewPort), new PropertyMetadata(false));
+
+        public ICommand MiddleMouseClickedCommand
+        {
+            get { return (ICommand)GetValue(MiddleMouseClickedCommandProperty); }
+            set { SetValue(MiddleMouseClickedCommandProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for MiddleMouseClickedCommand.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty MiddleMouseClickedCommandProperty =
+            DependencyProperty.Register("MiddleMouseClickedCommand", typeof(ICommand), typeof(DrawingViewPort), new PropertyMetadata(default(ICommand)));
+
+        public Point ViewportPosition
+        {
+            get { return (Point)GetValue(ViewportPositionProperty); }
+            set { SetValue(ViewportPositionProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for ViewportPosition.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty ViewportPositionProperty =
+            DependencyProperty.Register("ViewportPosition", typeof(Point), typeof(DrawingViewPort), new PropertyMetadata(default(Point)));
+
+        public ICommand MouseMoveCommand
+        {
+            get { return (ICommand)GetValue(MouseMoveCommandProperty); }
+            set { SetValue(MouseMoveCommandProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for MouseMoveCommand.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty MouseMoveCommandProperty =
+            DependencyProperty.Register("MouseMoveCommand", typeof(ICommand), typeof(DrawingViewPort), new PropertyMetadata(default(ICommand)));
+
+        public ICommand MouseDownCommand
+        {
+            get { return (ICommand)GetValue(MouseDownCommandProperty); }
+            set { SetValue(MouseDownCommandProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for MouseDownCommand.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty MouseDownCommandProperty =
+            DependencyProperty.Register("MouseDownCommand", typeof(ICommand), typeof(DrawingViewPort), new PropertyMetadata(default(ICommand)));
+
+        public double MouseXOnCanvas
+        {
+            get { return (double)GetValue(MouseXOnCanvasProperty); }
+            set { SetValue(MouseXOnCanvasProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for MouseXOnCanvas.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty MouseXOnCanvasProperty =
+            DependencyProperty.Register("MouseXOnCanvas", typeof(double), typeof(DrawingViewPort), new PropertyMetadata(0.0));
+
+        public double MouseYOnCanvas
+        {
+            get { return (double)GetValue(MouseYOnCanvasProperty); }
+            set { SetValue(MouseYOnCanvasProperty, value); }
+        }
+
+        // Using a DependencyProperty as the backing store for MouseXOnCanvas.  This enables animation, styling, binding, etc...
+        public static readonly DependencyProperty MouseYOnCanvasProperty =
+            DependencyProperty.Register("MouseYOnCanvas", typeof(double), typeof(DrawingViewPort), new PropertyMetadata(0.0));
+    }
+}