Browse Source

Added saving to clipboard using bitmap and PNG format

flabbet 5 years ago
parent
commit
ad937747cc

+ 68 - 0
PixiEditor/Models/Controllers/ClipboardController.cs

@@ -0,0 +1,68 @@
+using PixiEditor.Models.Layers;
+using PixiEditor.Models.Position;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Media.Imaging;
+
+namespace PixiEditor.Models.Controllers
+{
+    public class ClipboardController
+    {
+        public void CopyToClipboard(WriteableBitmap bitmap, Coordinates[] selection)
+        {
+            Clipboard.Clear();
+            using (var pngStream = new MemoryStream())
+            {
+                DataObject data = new DataObject();
+                var croppedBmp = BitmapSelectionToBmpSource(bitmap.Clone(), selection);
+                data.SetData(DataFormats.Bitmap, croppedBmp, true); //Bitmap, no transparency support
+
+                PngBitmapEncoder encoder = new PngBitmapEncoder();
+                encoder.Frames.Add(BitmapFrame.Create(croppedBmp));
+                encoder.Save(pngStream);
+                data.SetData("PNG", pngStream, false); //PNG, supports transparency
+
+                Clipboard.SetDataObject(data, true);
+            }
+        }
+
+        public BitmapSource BitmapSelectionToBmpSource(WriteableBitmap bitmap, Coordinates[] selection)
+        {
+            int offsetX = selection.Min(x => x.X);
+            int offsetY = selection.Min(x => x.Y);
+            int width = selection.Max(x => x.X) - offsetX + 1;
+            int height = selection.Max(x => x.Y) - offsetY + 1;
+            return bitmap.Crop(offsetX, offsetY, width, height);
+        }
+
+        private Bitmap BitmapFromBitmapSource(BitmapSource bitmap)
+        {
+            Bitmap bmp;
+            using (MemoryStream outStream = new MemoryStream())
+            {
+                BitmapEncoder enc = new BmpBitmapEncoder();
+                enc.Frames.Add(BitmapFrame.Create(bitmap));
+                enc.Save(outStream);
+                bmp = new Bitmap(outStream);
+            }
+            return bmp;
+        }
+
+        private Stream StreamFromBitmapSource(BitmapSource writeBmp)
+        {
+            Stream bmp = new MemoryStream();
+
+            BitmapEncoder enc = new BmpBitmapEncoder();
+            enc.Frames.Add(BitmapFrame.Create(writeBmp));
+            enc.Save(bmp);
+
+            return bmp;
+        }
+    }
+}

+ 19 - 0
PixiEditor/Styles/MenuButtonStyle.xaml

@@ -1,6 +1,25 @@
 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
 
+    <Style x:Key="{x:Static MenuItem.SeparatorStyleKey}"
+       TargetType="{x:Type Separator}">
+        <Setter Property="Height"
+          Value="1" />
+        <Setter Property="Margin"
+          Value="0,4,0,4" />
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type Separator}">
+                    <Border BorderThickness="1">
+                        <Border.BorderBrush>
+                            <SolidColorBrush Color="#FF4D4D4D" />
+                        </Border.BorderBrush>
+                    </Border>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+
     <Style x:Key="menuItemStyle" TargetType="{x:Type MenuItem}">
         <Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}"/>
         <Setter Property="FontSize" Value="12"/>

+ 11 - 2
PixiEditor/ViewModels/ViewModelMain.cs

@@ -42,6 +42,7 @@ namespace PixiEditor.ViewModels
         public RelayCommand SwapColorsCommand { get; set; }
         public RelayCommand DeselectCommand { get; set; }
         public RelayCommand SelectAllCommand { get; set; }
+        public RelayCommand CopyCommand { get; set; }
 
 
         private double _mouseXonCanvas;
@@ -140,6 +141,7 @@ namespace PixiEditor.ViewModels
             }
         }
 
+        public ClipboardController ClipboardController { get; set; }
 
         public ViewModelMain()
         {
@@ -166,8 +168,9 @@ namespace PixiEditor.ViewModels
             SwapColorsCommand = new RelayCommand(SwapColors);
             KeyDownCommand = new RelayCommand(KeyDown);
             RenameLayerCommand = new RelayCommand(RenameLayer);
-            DeselectCommand = new RelayCommand(Deselect, CanDeselect);
+            DeselectCommand = new RelayCommand(Deselect, SelectionIsNotEmpty);
             SelectAllCommand = new RelayCommand(SelectAll, CanSelectAll);
+            CopyCommand = new RelayCommand(Copy, SelectionIsNotEmpty);
             ToolSet = new ObservableCollection<Tool> {new MoveTool(), new PenTool(), new SelectTool(), new FloodFill(), new LineTool(),
             new CircleTool(), new RectangleTool(), new EarserTool(), new ColorPickerTool(), new BrightnessTool()};
             ShortcutController = new ShortcutController
@@ -193,11 +196,17 @@ namespace PixiEditor.ViewModels
                 }
             };
             UndoManager.SetMainRoot(this);
+            ClipboardController = new ClipboardController();
             SetActiveTool(ToolType.Move);
             BitmapManager.PrimaryColor = PrimaryColor;
             Current = this;
         }
 
+        private void Copy(object parameter)
+        {
+            ClipboardController.CopyToClipboard(BitmapManager.ActiveLayer.LayerBitmap, ActiveSelection.SelectedPoints);
+        }
+
         public void SelectAll(object parameter)
         {
             SelectTool select = new SelectTool();
@@ -215,7 +224,7 @@ namespace PixiEditor.ViewModels
             ActiveSelection = new Selection();
         }
 
-        private bool CanDeselect(object property)
+        private bool SelectionIsNotEmpty(object property)
         {
             return ActiveSelection.SelectedPoints != null;
         }

+ 16 - 13
PixiEditor/Views/MainWindow.xaml

@@ -49,8 +49,8 @@
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
             <RowDefinition Height="35*"/>
-            <RowDefinition Height="29*"/>
-            <RowDefinition Height="895*"/>
+            <RowDefinition Height="17*"/>
+            <RowDefinition Height="908*"/>
             <RowDefinition Height="30*"/>
         </Grid.RowDefinitions>
 
@@ -61,20 +61,23 @@
                     <Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource menuItemStyle}"/>
                 </Menu.Resources>
                 <MenuItem Header="_File">
-                <MenuItem InputGestureText="CTRL+N" Header="_New" Command="{Binding GenerateDrawAreaCommand}"/>
-                <MenuItem Header="_Open" InputGestureText="Ctrl+O" Command="{Binding OpenFileCommand}"/>
-                <MenuItem Header="_Export" InputGestureText="Ctrl+S" Command="{Binding SaveFileCommand}"/>
-                <MenuItem Header="_Export As..." InputGestureText="Ctrl+Shift+S" Command="{Binding SaveFileCommand}" CommandParameter="AsNew"/>
-            </MenuItem>
+                    <MenuItem InputGestureText="CTRL+N" Header="_New" Command="{Binding GenerateDrawAreaCommand}"/>
+                    <MenuItem Header="_Open" InputGestureText="Ctrl+O" Command="{Binding OpenFileCommand}"/>
+                    <MenuItem Header="_Export" InputGestureText="Ctrl+S" Command="{Binding SaveFileCommand}"/>
+                    <MenuItem Header="_Export As..." InputGestureText="Ctrl+Shift+S" Command="{Binding SaveFileCommand}" CommandParameter="AsNew"/>
+                </MenuItem>
                 <MenuItem Header="_Edit">
-                <MenuItem Header="_Undo" InputGestureText="Ctrl+Z" Command="{Binding UndoCommand}"/>
-                <MenuItem Header="_Redo" InputGestureText="Ctrl+Y" Command="{Binding RedoCommand}"/>
-            </MenuItem>
+                    <MenuItem Header="_Undo" InputGestureText="Ctrl+Z" Command="{Binding UndoCommand}"/>
+                    <MenuItem Header="_Redo" InputGestureText="Ctrl+Y" Command="{Binding RedoCommand}"/>
+                    <Separator/>
+                    <MenuItem Header="_Copy" Command="{Binding CopyCommand}"/>
+                    <MenuItem Header="_Paste"/>
+                </MenuItem>
                 <MenuItem Header="_Select">
                     <MenuItem Header="_Select All" Command="{Binding SelectAllCommand}" InputGestureText="Ctrl+A"/>
                     <MenuItem Header="_Deselect" Command="{Binding DeselectCommand}" InputGestureText="Ctrl+D"/>
                 </MenuItem>
-        </Menu>
+            </Menu>
             <StackPanel DockPanel.Dock="Right" VerticalAlignment="Top" Orientation="Horizontal" HorizontalAlignment="Right" WindowChrome.IsHitTestVisibleInChrome="True">
                 <Button Style="{StaticResource MinimizeButtonStyle}" WindowChrome.IsHitTestVisibleInChrome="True" ToolTip="Minimize"
                             Command="{x:Static SystemCommands.MinimizeWindowCommand}"/>
@@ -86,7 +89,7 @@
                             Command="{x:Static SystemCommands.CloseWindowCommand}"/>
             </StackPanel>
         </DockPanel>
-        <StackPanel Background="#404040" Orientation="Horizontal" Grid.ColumnSpan="2" Margin="0,30,0,0" Grid.RowSpan="2">
+        <StackPanel Background="#404040" Orientation="Horizontal" Grid.ColumnSpan="3" Margin="0,30,146,0" Grid.RowSpan="2">
             <ItemsControl ItemsSource="{Binding BitmapManager.SelectedTool.Toolbar.Settings}">
                 <ItemsControl.ItemsPanel>
                     <ItemsPanelTemplate>
@@ -148,7 +151,7 @@
         </Grid>
 
         <StackPanel Orientation="Vertical" Cursor="Arrow" Grid.Row="2" Grid.Column="0" Margin="0,7,5,0" Background="#404040" Grid.RowSpan="2">
-            
+
             <ItemsControl ItemsSource="{Binding ToolSet}">
                 <ItemsControl.ItemTemplate>
                     <DataTemplate>