Skip to content

Commit

Permalink
Store picture markers against a range, rather than an address to bene…
Browse files Browse the repository at this point in the history
…fit from range repository notifications
  • Loading branch information
igitur committed Jun 29, 2018
1 parent b448bcc commit 19f5468
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 116 deletions.
10 changes: 0 additions & 10 deletions ClosedXML/Excel/Drawings/IXLMarker.cs

This file was deleted.

43 changes: 22 additions & 21 deletions ClosedXML/Excel/Drawings/IXLPicture.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Keep this file CodeMaid organised and cleaned
using System;
using System.Drawing;
using System.IO;
Expand All @@ -6,20 +7,7 @@ namespace ClosedXML.Excel.Drawings
{
public interface IXLPicture : IDisposable
{
IXLAddress BottomRightCellAddress { get; }

/// <summary>
/// Create a copy of the picture on a different worksheet.
/// </summary>
/// <param name="targetSheet">The worksheet to which the picture will be copied.</param>
/// <returns>A created copy of the picture.</returns>
IXLPicture CopyTo(IXLWorksheet targetSheet);

/// <summary>
/// Create a copy of the picture on the same worksheet.
/// </summary>
/// <returns>A created copy of the picture.</returns>
IXLPicture Duplicate();
IXLCell BottomRightCell { get; }

/// <summary>
/// Type of image. The supported formats are defined by OpenXML's ImagePartType.
Expand All @@ -45,32 +33,45 @@ public interface IXLPicture : IDisposable

Int32 Top { get; set; }

IXLAddress TopLeftCellAddress { get; }
IXLCell TopLeftCell { get; }

Int32 Width { get; set; }

IXLWorksheet Worksheet { get; }

/// <summary>
/// Create a copy of the picture on a different worksheet.
/// </summary>
/// <param name="targetSheet">The worksheet to which the picture will be copied.</param>
/// <returns>A created copy of the picture.</returns>
IXLPicture CopyTo(IXLWorksheet targetSheet);

/// <summary>
/// Deletes this picture.
/// </summary>
void Delete();

/// <summary>
/// Create a copy of the picture on the same worksheet.
/// </summary>
/// <returns>A created copy of the picture.</returns>
IXLPicture Duplicate();

Point GetOffset(XLMarkerPosition position);

IXLPicture MoveTo(Int32 left, Int32 top);

IXLPicture MoveTo(IXLAddress cell);
IXLPicture MoveTo(IXLCell cell);

IXLPicture MoveTo(IXLAddress cell, Int32 xOffset, Int32 yOffset);
IXLPicture MoveTo(IXLCell cell, Int32 xOffset, Int32 yOffset);

IXLPicture MoveTo(IXLAddress cell, Point offset);
IXLPicture MoveTo(IXLCell cell, Point offset);

IXLPicture MoveTo(IXLAddress fromCell, IXLAddress toCell);
IXLPicture MoveTo(IXLCell fromCell, IXLCell toCell);

IXLPicture MoveTo(IXLAddress fromCell, Int32 fromCellXOffset, Int32 fromCellYOffset, IXLAddress toCell, Int32 toCellXOffset, Int32 toCellYOffset);
IXLPicture MoveTo(IXLCell fromCell, Int32 fromCellXOffset, Int32 fromCellYOffset, IXLCell toCell, Int32 toCellXOffset, Int32 toCellYOffset);

IXLPicture MoveTo(IXLAddress fromCell, Point fromOffset, IXLAddress toCell, Point toOffset);
IXLPicture MoveTo(IXLCell fromCell, Point fromOffset, IXLCell toCell, Point toOffset);

IXLPicture Scale(Double factor, Boolean relativeToOriginal = false);

Expand Down
28 changes: 21 additions & 7 deletions ClosedXML/Excel/Drawings/XLMarker.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,37 @@
// Keep this file CodeMaid organised and cleaned
using System;
using System.Diagnostics;
using System.Drawing;

namespace ClosedXML.Excel.Drawings
{
[DebuggerDisplay("{Address} {Offset}")]
internal class XLMarker : IXLMarker
internal class XLMarker
{
internal XLMarker(IXLAddress address)
: this(address, new Point(0, 0))
// Using a range to store the location so that it gets added to the range repository
// and hence will be adjusted when there are insertions / deletions
private readonly IXLRange rangeCell;

internal XLMarker(IXLCell cell)
: this(cell.AsRange(), new Point(0, 0))
{ }

internal XLMarker(IXLCell cell, Point offset)
: this(cell.AsRange(), offset)
{ }

internal XLMarker(IXLAddress address, Point offset)
private XLMarker(IXLRange rangeCell, Point offset)
{
this.Address = address;
if (rangeCell.RowCount() != 1 || rangeCell.ColumnCount() != 1)
throw new ArgumentException("Range should contain only one cell.", nameof(rangeCell));

this.rangeCell = rangeCell;
this.Offset = offset;
}

public IXLAddress Address { get; set; }

public IXLCell Cell { get => rangeCell.FirstCell(); }
public Int32 ColumnNumber { get => rangeCell.RangeAddress.FirstAddress.ColumnNumber; }
public Point Offset { get; set; }
public Int32 RowNumber { get => rangeCell.RangeAddress.FirstAddress.RowNumber; }
}
}
89 changes: 42 additions & 47 deletions ClosedXML/Excel/Drawings/XLPicture.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Keep this file CodeMaid organised and cleaned
using System;
using System.Collections.Generic;
using System.Diagnostics;
Expand Down Expand Up @@ -96,7 +97,7 @@ private XLPicture(IXLWorksheet worksheet)
{
this.Worksheet = worksheet ?? throw new ArgumentNullException(nameof(worksheet));
this.Placement = XLPicturePlacement.MoveAndSize;
this.Markers = new Dictionary<XLMarkerPosition, IXLMarker>()
this.Markers = new Dictionary<XLMarkerPosition, XLMarker>()
{
[XLMarkerPosition.TopLeft] = null,
[XLMarkerPosition.BottomRight] = null
Expand All @@ -110,17 +111,18 @@ private XLPicture(IXLWorksheet worksheet)
this.id = 1;
}

public IXLAddress BottomRightCellAddress
public IXLCell BottomRightCell
{
get
{
return Markers[XLMarkerPosition.BottomRight].Address;
return Markers[XLMarkerPosition.BottomRight].Cell;
}

private set
{
if (!value.Worksheet.Equals(this.Worksheet))
throw new ArgumentOutOfRangeException(nameof(value.Worksheet));
throw new InvalidOperationException("A picture and its anchor cells must be on the same worksheet");

this.Markers[XLMarkerPosition.BottomRight] = new XLMarker(value);
}
}
Expand Down Expand Up @@ -160,7 +162,7 @@ public Int32 Left
if (this.Placement != XLPicturePlacement.FreeFloating)
throw new ArgumentException("To set the left-hand offset, the placement should be FreeFloating");

Markers[XLMarkerPosition.TopLeft] = new XLMarker(Worksheet.Cell(1, 1).Address, new Point(value, this.Top));
Markers[XLMarkerPosition.TopLeft] = new XLMarker(Worksheet.Cell(1, 1), new Point(value, this.Top));
}
}

Expand Down Expand Up @@ -192,21 +194,21 @@ public Int32 Top
if (this.Placement != XLPicturePlacement.FreeFloating)
throw new ArgumentException("To set the top offset, the placement should be FreeFloating");

Markers[XLMarkerPosition.TopLeft] = new XLMarker(Worksheet.Cell(1, 1).Address, new Point(this.Left, value));
Markers[XLMarkerPosition.TopLeft] = new XLMarker(Worksheet.Cell(1, 1), new Point(this.Left, value));
}
}

public IXLAddress TopLeftCellAddress
public IXLCell TopLeftCell
{
get
{
return Markers[XLMarkerPosition.TopLeft].Address;
return Markers[XLMarkerPosition.TopLeft].Cell;
}

private set
{
if (!value.Worksheet.Equals(this.Worksheet))
throw new ArgumentOutOfRangeException(nameof(value.Worksheet));
throw new InvalidOperationException("A picture and its anchor cells must be on the same worksheet");

this.Markers[XLMarkerPosition.TopLeft] = new XLMarker(value);
}
Expand All @@ -225,10 +227,20 @@ public Int32 Width

public IXLWorksheet Worksheet { get; }

internal IDictionary<XLMarkerPosition, IXLMarker> Markers { get; private set; }
internal IDictionary<XLMarkerPosition, XLMarker> Markers { get; private set; }

internal String RelId { get; set; }

/// <summary>
/// Create a copy of the picture on a different worksheet.
/// </summary>
/// <param name="targetSheet">The worksheet to which the picture will be copied.</param>
/// <returns>A created copy of the picture.</returns>
public IXLPicture CopyTo(IXLWorksheet targetSheet)
{
return CopyTo((XLWorksheet)targetSheet);
}

public void Delete()
{
Worksheet.Pictures.Delete(this.Name);
Expand All @@ -239,6 +251,15 @@ public void Dispose()
this.ImageStream.Dispose();
}

/// <summary>
/// Create a copy of the picture on the same worksheet.
/// </summary>
/// <returns>A created copy of the picture.</returns>
public IXLPicture Duplicate()
{
return CopyTo(Worksheet);
}

public Point GetOffset(XLMarkerPosition position)
{
return Markers[position].Offset;
Expand All @@ -252,45 +273,45 @@ public IXLPicture MoveTo(Int32 left, Int32 top)
return this;
}

public IXLPicture MoveTo(IXLAddress cell)
public IXLPicture MoveTo(IXLCell cell)
{
return MoveTo(cell, 0, 0);
}

public IXLPicture MoveTo(IXLAddress cell, Int32 xOffset, Int32 yOffset)
public IXLPicture MoveTo(IXLCell cell, Int32 xOffset, Int32 yOffset)
{
return MoveTo(cell, new Point(xOffset, yOffset));
}

public IXLPicture MoveTo(IXLAddress cell, Point offset)
public IXLPicture MoveTo(IXLCell cell, Point offset)
{
if (cell == null) throw new ArgumentNullException(nameof(cell));
this.Placement = XLPicturePlacement.Move;
this.TopLeftCellAddress = cell;
this.TopLeftCell = cell;
this.Markers[XLMarkerPosition.TopLeft].Offset = offset;
return this;
}

public IXLPicture MoveTo(IXLAddress fromCell, IXLAddress toCell)
public IXLPicture MoveTo(IXLCell fromCell, IXLCell toCell)
{
return MoveTo(fromCell, 0, 0, toCell, 0, 0);
}

public IXLPicture MoveTo(IXLAddress fromCell, Int32 fromCellXOffset, Int32 fromCellYOffset, IXLAddress toCell, Int32 toCellXOffset, Int32 toCellYOffset)
public IXLPicture MoveTo(IXLCell fromCell, Int32 fromCellXOffset, Int32 fromCellYOffset, IXLCell toCell, Int32 toCellXOffset, Int32 toCellYOffset)
{
return MoveTo(fromCell, new Point(fromCellXOffset, fromCellYOffset), toCell, new Point(toCellXOffset, toCellYOffset));
}

public IXLPicture MoveTo(IXLAddress fromCell, Point fromOffset, IXLAddress toCell, Point toOffset)
public IXLPicture MoveTo(IXLCell fromCell, Point fromOffset, IXLCell toCell, Point toOffset)
{
if (fromCell == null) throw new ArgumentNullException(nameof(fromCell));
if (toCell == null) throw new ArgumentNullException(nameof(toCell));
this.Placement = XLPicturePlacement.MoveAndSize;

this.TopLeftCellAddress = fromCell;
this.TopLeftCell = fromCell;
this.Markers[XLMarkerPosition.TopLeft].Offset = fromOffset;

this.BottomRightCellAddress = toCell;
this.BottomRightCell = toCell;
this.Markers[XLMarkerPosition.BottomRight].Offset = toOffset;

return this;
Expand Down Expand Up @@ -326,25 +347,6 @@ public IXLPicture WithSize(Int32 width, Int32 height)
return this;
}

/// <summary>
/// Create a copy of the picture on a different worksheet.
/// </summary>
/// <param name="targetSheet">The worksheet to which the picture will be copied.</param>
/// <returns>A created copy of the picture.</returns>
public IXLPicture CopyTo(IXLWorksheet targetSheet)
{
return CopyTo((XLWorksheet) targetSheet);
}

/// <summary>
/// Create a copy of the picture on the same worksheet.
/// </summary>
/// <returns>A created copy of the picture.</returns>
public IXLPicture Duplicate()
{
return CopyTo(Worksheet);
}

internal IXLPicture CopyTo(XLWorksheet targetSheet)
{
if (targetSheet == null)
Expand All @@ -368,18 +370,11 @@ internal IXLPicture CopyTo(XLWorksheet targetSheet)
break;

case XLPicturePlacement.Move:
var newAddress = new XLAddress(targetSheet, TopLeftCellAddress.RowNumber,
TopLeftCellAddress.ColumnNumber, false, false);
newPicture.MoveTo(newAddress, GetOffset(XLMarkerPosition.TopLeft));
newPicture.MoveTo(targetSheet.Cell(TopLeftCell.Address), GetOffset(XLMarkerPosition.TopLeft));
break;

case XLPicturePlacement.MoveAndSize:
var newFromAddress = new XLAddress(targetSheet, TopLeftCellAddress.RowNumber,
TopLeftCellAddress.ColumnNumber, false, false);
var newToAddress = new XLAddress(targetSheet, BottomRightCellAddress.RowNumber,
BottomRightCellAddress.ColumnNumber, false, false);

newPicture.MoveTo(newFromAddress, GetOffset(XLMarkerPosition.TopLeft), newToAddress,
newPicture.MoveTo(targetSheet.Cell(TopLeftCell.Address), GetOffset(XLMarkerPosition.TopLeft), targetSheet.Cell(BottomRightCell.Address),
GetOffset(XLMarkerPosition.BottomRight));
break;
}
Expand Down
10 changes: 5 additions & 5 deletions ClosedXML/Excel/XLWorkbook_Load.cs
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,7 @@ private void LoadDrawings(WorksheetPart wsPart, IXLWorksheet ws)
{
var oneCellAnchor = anchor as Xdr.OneCellAnchor;
var from = LoadMarker(ws, oneCellAnchor.FromMarker);
picture.MoveTo(from.Address, from.Offset);
picture.MoveTo(from.Cell, from.Offset);
}
else if (anchor is Xdr.TwoCellAnchor)
{
Expand All @@ -917,7 +917,7 @@ private void LoadDrawings(WorksheetPart wsPart, IXLWorksheet ws)

if (twoCellAnchor.EditAs == null || !twoCellAnchor.EditAs.HasValue || twoCellAnchor.EditAs.Value == Xdr.EditAsValues.TwoCell)
{
picture.MoveTo(from.Address, from.Offset, to.Address, to.Offset);
picture.MoveTo(from.Cell, from.Offset, to.Cell, to.Offset);
}
else if (twoCellAnchor.EditAs.Value == Xdr.EditAsValues.Absolute)
{
Expand All @@ -932,7 +932,7 @@ private void LoadDrawings(WorksheetPart wsPart, IXLWorksheet ws)
}
else if (twoCellAnchor.EditAs.Value == Xdr.EditAsValues.OneCell)
{
picture.MoveTo(from.Address, from.Offset);
picture.MoveTo(from.Cell, from.Offset);
}
}
}
Expand All @@ -945,12 +945,12 @@ private static Int32 ConvertFromEnglishMetricUnits(long emu, float resolution)
return Convert.ToInt32(emu * resolution / 914400);
}

private static IXLMarker LoadMarker(IXLWorksheet ws, Xdr.MarkerType marker)
private static XLMarker LoadMarker(IXLWorksheet ws, Xdr.MarkerType marker)
{
var row = Math.Min(XLHelper.MaxRowNumber, Math.Max(1, Convert.ToInt32(marker.RowId.InnerText) + 1));
var column = Math.Min(XLHelper.MaxColumnNumber, Math.Max(1, Convert.ToInt32(marker.ColumnId.InnerText) + 1));
return new XLMarker(
ws.Cell(row, column).Address,
ws.Cell(row, column),
new Point(
ConvertFromEnglishMetricUnits(Convert.ToInt32(marker.ColumnOffset.InnerText), GraphicsUtils.Graphics.DpiX),
ConvertFromEnglishMetricUnits(Convert.ToInt32(marker.RowOffset.InnerText), GraphicsUtils.Graphics.DpiY)
Expand Down

0 comments on commit 19f5468

Please sign in to comment.