Skip to content

Commit

Permalink
Replace with clipboard: exception #1545 (#1546)
Browse files Browse the repository at this point in the history
* Update gitignore for VS2017

* Fix exception for pasting objects copied from desktop

* Refactor ClipboardUtil
  • Loading branch information
initialshl authored and IanTeo committed Sep 4, 2017
1 parent 8540685 commit 7fa8625
Show file tree
Hide file tree
Showing 16 changed files with 87 additions and 53 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Expand Up @@ -32,4 +32,5 @@ cov-report.xml
.hubturboconfig/

# StyleCop
PowerPointLabs/PowerPointLabs/StyleCop.Cache
PowerPointLabs/PowerPointLabs/StyleCop.Cache
PowerPointLabs/.vs/PowerPointLabs/v15/sqlite3/storage.ide
Expand Up @@ -5,6 +5,7 @@
using PowerPointLabs.Models;
using PowerPointLabs.PasteLab;
using PowerPointLabs.TextCollection;
using PowerPointLabs.Utils;

using PPExtraEventHelper;

Expand All @@ -30,7 +31,7 @@ class PasteAtCursorPositionActionHandler : PasteLabActionHandler
positionY = ((coordinates.Y - activeWindow.PointsToScreenPixelsY(0)) / yref) * 100;
}

ShapeRange pastingShapes = PasteShapesFromClipboard(slide);
ShapeRange pastingShapes = ClipboardUtil.PasteShapesFromClipboard(slide);
if (pastingShapes == null)
{
return null;
Expand Down
Expand Up @@ -10,7 +10,7 @@ class PasteAtCursorPositionEnabledHandler : EnabledHandler
{
protected override bool GetEnabled(string ribbonId)
{
return !GraphicsUtil.IsClipboardEmpty();
return !ClipboardUtil.IsClipboardEmpty();
}
}
}
Expand Up @@ -3,6 +3,7 @@
using PowerPointLabs.ActionFramework.Common.Attribute;
using PowerPointLabs.Models;
using PowerPointLabs.TextCollection;
using PowerPointLabs.Utils;

namespace PowerPointLabs.ActionFramework.PasteLab
{
Expand All @@ -13,11 +14,11 @@ class PasteAtOriginalPositionActionHandler : PasteLabActionHandler
ShapeRange selectedShapes, ShapeRange selectedChildShapes)
{
PowerPointSlide tempSlide = presentation.AddSlide(index: slide.Index);
ShapeRange tempPastingShapes = PasteShapesFromClipboard(tempSlide);
ShapeRange tempPastingShapes = ClipboardUtil.PasteShapesFromClipboard(tempSlide);
if (tempPastingShapes == null)
{
tempSlide.Delete();
return PasteShapesFromClipboard(slide);
return ClipboardUtil.PasteShapesFromClipboard(slide);
}

ShapeRange pastingShapes = slide.CopyShapesToSlide(tempPastingShapes);
Expand Down
Expand Up @@ -10,7 +10,7 @@ class PasteAtOriginalPositionEnabledHandler : EnabledHandler
{
protected override bool GetEnabled(string ribbonId)
{
return !GraphicsUtil.IsClipboardEmpty();
return !ClipboardUtil.IsClipboardEmpty();
}
}
}
Expand Up @@ -27,7 +27,7 @@ class PasteIntoGroupActionHandler : PasteLabActionHandler
return null;
}

ShapeRange pastingShapes = PasteShapesFromClipboard(slide);
ShapeRange pastingShapes = ClipboardUtil.PasteShapesFromClipboard(slide);
if (pastingShapes == null)
{
return null;
Expand Down
Expand Up @@ -14,7 +14,7 @@ class PasteIntoGroupEnabledHandler : EnabledHandler
protected override bool GetEnabled(string ribbonId)
{
Selection currentSelection = this.GetCurrentSelection();
return !GraphicsUtil.IsClipboardEmpty() &&
return !ClipboardUtil.IsClipboardEmpty() &&
ShapeUtil.IsSelectionMultipleOrGroup(currentSelection) &&
!ShapeUtil.HasPlaceholderInSelection(currentSelection);
}
Expand Down
@@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.Runtime.InteropServices;

using Microsoft.Office.Interop.PowerPoint;

Expand All @@ -25,7 +24,7 @@ protected sealed override void ExecuteAction(string ribbonId)
PowerPointSlide slide = this.GetCurrentSlide();
Selection selection = this.GetCurrentSelection();

if (GraphicsUtil.IsClipboardEmpty())
if (ClipboardUtil.IsClipboardEmpty())
{
Logger.Log(ribbonId + " failed. Clipboard is empty.");
return;
Expand All @@ -36,9 +35,13 @@ protected sealed override void ExecuteAction(string ribbonId)

if (ShapeUtil.IsSelectionShape(selection) && !IsSelectionIgnored(ribbonId))
{
// When pasting some objects, the selection may change to the pasted object (e.g. jpg from desktop).
// Therefore we must capture the selection first.
ShapeRange selectedShapes = selection.ShapeRange;

// Save clipboard onto a temp slide, because CorruptionCorrrection uses Copy-Paste
PowerPointSlide tempClipboardSlide = presentation.AddSlide(index: slide.Index);
ShapeRange tempClipboardShapes = PasteShapesFromClipboard(tempClipboardSlide);
ShapeRange tempClipboardShapes = ClipboardUtil.PasteShapesFromClipboard(tempClipboardSlide);

// Nothing is pasted, stop now
if (tempClipboardShapes == null)
Expand All @@ -47,8 +50,7 @@ protected sealed override void ExecuteAction(string ribbonId)
return;
}

// Preserve selection using tags
ShapeRange selectedShapes = selection.ShapeRange;
// Preserve selection by tagging them
for (int i = 1; i <= selectedShapes.Count; i++)
{
selectedShapes[i].Tags.Add(SelectOrderTagName, i.ToString());
Expand Down Expand Up @@ -80,7 +82,7 @@ protected sealed override void ExecuteAction(string ribbonId)
passedSelectedShapes = slide.ToShapeRange(correctedShapeList);
passedSelectedChildShapes = slide.ToShapeRange(correctedChildShapeList);

// Remove the tags after they have been used
// Remove shape tags after they have been used
ShapeUtil.DeleteTagFromShapes(passedSelectedShapes, SelectOrderTagName);
ShapeUtil.DeleteTagFromShapes(passedSelectedChildShapes, SelectChildOrderTagName);

Expand All @@ -99,20 +101,6 @@ protected sealed override void ExecuteAction(string ribbonId)
protected abstract ShapeRange ExecutePasteAction(string ribbonId, PowerPointPresentation presentation, PowerPointSlide slide,
ShapeRange selectedShapes, ShapeRange selectedChildShapes);

protected ShapeRange PasteShapesFromClipboard(PowerPointSlide slide)
{
try
{
return slide.Shapes.Paste();
}
catch (COMException e)
{
// May be thrown if there is placeholder shape in clipboard
Logger.LogException(e, "PasteShapeFromClipboard");
return null;
}
}

private bool IsSelectionIgnored(string ribbonId)
{
return ribbonId.StartsWith("PasteAtCursorPosition") ||
Expand Down
Expand Up @@ -4,6 +4,7 @@
using PowerPointLabs.Models;
using PowerPointLabs.PasteLab;
using PowerPointLabs.TextCollection;
using PowerPointLabs.Utils;

namespace PowerPointLabs.ActionFramework.PasteLab
{
Expand All @@ -13,7 +14,7 @@ class PasteToFillSlideActionHandler : PasteLabActionHandler
protected override ShapeRange ExecutePasteAction(string ribbonId, PowerPointPresentation presentation, PowerPointSlide slide,
ShapeRange selectedShapes, ShapeRange selectedChildShapes)
{
ShapeRange pastingShapes = PasteShapesFromClipboard(slide);
ShapeRange pastingShapes = ClipboardUtil.PasteShapesFromClipboard(slide);
if (pastingShapes == null)
{
return null;
Expand Down
Expand Up @@ -10,7 +10,7 @@ class PasteToFillSlideEnabledHandler : EnabledHandler
{
protected override bool GetEnabled(string ribbonId)
{
return !GraphicsUtil.IsClipboardEmpty();
return !ClipboardUtil.IsClipboardEmpty();
}
}
}
Expand Up @@ -6,6 +6,7 @@
using PowerPointLabs.Models;
using PowerPointLabs.PasteLab;
using PowerPointLabs.TextCollection;
using PowerPointLabs.Utils;

namespace PowerPointLabs.ActionFramework.PasteLab
{
Expand All @@ -21,7 +22,7 @@ class ReplaceWithClipboardActionHandler : PasteLabActionHandler
return null;
}

ShapeRange pastingShapes = PasteShapesFromClipboard(slide);
ShapeRange pastingShapes = ClipboardUtil.PasteShapesFromClipboard(slide);
if (pastingShapes == null)
{
return null;
Expand Down
Expand Up @@ -14,7 +14,7 @@ class ReplaceWithClipboardEnabledHandler : EnabledHandler
protected override bool GetEnabled(string ribbonId)
{
Selection currentSelection = this.GetCurrentSelection();
return !GraphicsUtil.IsClipboardEmpty() &&
return !ClipboardUtil.IsClipboardEmpty() &&
ShapeUtil.IsSelectionSingleShape(currentSelection) &&
!ShapeUtil.HasPlaceholderInSelection(currentSelection);
}
Expand Down
1 change: 1 addition & 0 deletions PowerPointLabs/PowerPointLabs/PowerPointLabs.csproj
Expand Up @@ -641,6 +641,7 @@
<Compile Include="TextCollection\ZoomLabText.cs" />
<Compile Include="TextCollection\SyncLabText.cs" />
<Compile Include="TextCollection\CropLabText.cs" />
<Compile Include="Utils\ClipboardUtil.cs" />
<Compile Include="Utils\ShapeUtil.cs" />
<Compile Include="Utils\SlideUtil.cs" />
<Compile Include="Views\ErrorDialogBox.xaml.cs">
Expand Down
Expand Up @@ -5,7 +5,7 @@

using Microsoft.Office.Interop.PowerPoint;

using static PowerPointLabs.ActionFramework.Common.Extension.ContentControlExtensions;
using PowerPointLabs.ActionFramework.Common.Extension;
using PowerPointLabs.TextCollection;
using PowerPointLabs.Utils;

Expand Down
50 changes: 50 additions & 0 deletions PowerPointLabs/PowerPointLabs/Utils/ClipboardUtil.cs
@@ -0,0 +1,50 @@
using System.Runtime.InteropServices;
using System.Windows.Forms;

using Microsoft.Office.Interop.PowerPoint;

using PowerPointLabs.ActionFramework.Common.Log;
using PowerPointLabs.Models;

namespace PowerPointLabs.Utils
{
internal static class ClipboardUtil
{
#region API

public static bool IsClipboardEmpty()
{
IDataObject clipboardData = Clipboard.GetDataObject();
return clipboardData == null || clipboardData.GetFormats().Length == 0;
}

public static ShapeRange PasteShapesFromClipboard(PowerPointSlide slide)
{
try
{
// Note: Some copied objects are pasted on currentSlide rather than the desired slide (e.g. jpg from desktop),
// so we must check whether it is pasted correctly, else we cut-and-paste it into the correct slide.

int initialSlideShapesCount = slide.Shapes.Count;
ShapeRange pastedShapes = slide.Shapes.Paste();

int finalSlideShapesCount = slide.Shapes.Count;
if (pastedShapes.Count >= 1 && finalSlideShapesCount == initialSlideShapesCount)
{
pastedShapes.Cut();
pastedShapes = slide.Shapes.Paste();
}

return pastedShapes;
}
catch (COMException e)
{
// May be thrown if there is placeholder shape in clipboard
Logger.LogException(e, "PasteShapeFromClipboard");
return null;
}
}

#endregion
}
}
30 changes: 10 additions & 20 deletions PowerPointLabs/PowerPointLabs/Utils/GraphicsUtil.cs
Expand Up @@ -40,20 +40,10 @@ static GraphicsUtil()
dpiScale = g.DpiX / TargetDpi;
}
}
# endregion

# region API

# region Clipboard

public static bool IsClipboardEmpty()
{
IDataObject clipboardData = Clipboard.GetDataObject();
return clipboardData == null || clipboardData.GetFormats().Length == 0;
}

#endregion

#region API

#region Shape

public static void ExportShape(Shape shape, string exportPath)
Expand Down Expand Up @@ -109,7 +99,7 @@ public static Bitmap ShapeToBitmap(Shape shape)

#endregion

# region Slide
#region Slide
public static void ExportSlide(Slide slide, string exportPath, float magnifyRatio = 1.0f)
{
slide.Export(exportPath,
Expand All @@ -123,9 +113,9 @@ public static void ExportSlide(PowerPointSlide slide, string exportPath, float m
ExportSlide(slide.GetNativeSlide(), exportPath, magnifyRatio);
}

# endregion
#endregion

# region Bitmap
#region Bitmap
public static Bitmap CreateThumbnailImage(Image oriImage, int width, int height)
{
var scalingRatio = CalculateScalingRatio(oriImage.Size, new Size(width, height));
Expand Down Expand Up @@ -153,9 +143,9 @@ public static Bitmap CreateThumbnailImage(Image oriImage, int width, int height)

return thumbnail;
}
# endregion
#endregion

# region GDI+
#region GDI+
public static void SuspendDrawing(Control control)
{
Native.SendMessage(control.Handle, (uint) Native.Message.WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero);
Expand All @@ -166,9 +156,9 @@ public static void ResumeDrawing(Control control)
Native.SendMessage(control.Handle, (uint) Native.Message.WM_SETREDRAW, new IntPtr(1), IntPtr.Zero);
control.Refresh();
}
# endregion
#endregion

# region Color
#region Color
public static int ConvertColorToRgb(Drawing.Color argb)
{
return (argb.B << 16) | (argb.G << 8) | argb.R;
Expand Down Expand Up @@ -282,6 +272,6 @@ public static float GetDpiScale()
{
return dpiScale;
}
# endregion
#endregion
}
}

0 comments on commit 7fa8625

Please sign in to comment.