OnTopReplica/src/OnTopReplica/ThumbnailRegion.cs
Lorenz Cuno Klopfenstein a7774b6677 Code re-org
2018-04-10 18:52:40 +02:00

223 lines
7.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace OnTopReplica {
/// <summary>
/// Represents a thumbnail region.
/// </summary>
/// <remarks>
/// A ThumbnailRegion can work in absolute or in relative mode.
/// In absolute mode, the region is expressed in absolute pixel values, as expressed by the value of the
/// <see cref="Bounds"/> property.
/// In relative mode, the region is expressed in padding pixels from the borders of the source. Internally this
/// is still represented by the <see cref="Bounds"/> property. Properties of the Rectangle value are mapped as follows:
/// Rectangle.X = Padding.Left
/// Rectangle.Y = Padding.Top
/// Rectangle.Width = Padding.Right
/// Rectangle.Height = Padding.Bottom
/// </remarks>
public class ThumbnailRegion {
/// <summary>
/// Creates a ThumbnailRegion from a padding value relative to the thumbnail borders.
/// </summary>
public ThumbnailRegion(Padding padding) {
_bounds = new Rectangle {
X = padding.Left,
Y = padding.Top,
Width = padding.Right,
Height = padding.Bottom
};
Relative = true;
}
/// <summary>
/// Creates a ThumbnailRegion from a bounds rectangle (in absolute terms).
/// </summary>
public ThumbnailRegion(Rectangle rectangle) {
_bounds = rectangle;
Relative = false;
}
/// <summary>
/// Creates a ThumbnailRegion from a rectangle, either expressing values in relative or in absolute terms.
/// </summary>
public ThumbnailRegion(Rectangle paddingOrBounds, bool relative) {
_bounds = paddingOrBounds;
Relative = relative;
}
private Rectangle _bounds;
/// <summary>
/// Gets or sets the bounds of the thumbnail region.
/// </summary>
public Rectangle Bounds {
get {
#if DEBUG
if (Relative)
throw new InvalidOperationException("Not allowed to use ThumbnailRegion Bounds as Rectangle value (in relative mode).");
#endif
return _bounds;
}
set {
_bounds = value;
Relative = false;
}
}
/// <summary>
/// Gets or sets whether the bounds are expressed relative to the thumbnail borders.
/// </summary>
public bool Relative {
get;
set;
}
/// <summary>
/// Sets the relative bounds of the region. Switches to relative mode.
/// </summary>
/// <param name="padding">Padding in relative terms from the borders.</param>
public void SetRelativeBounds(Padding padding) {
Bounds = new Rectangle {
X = padding.Left,
Y = padding.Top,
Width = padding.Right,
Height = padding.Bottom
};
Relative = true;
}
/// <summary>
/// Gets the bounds of the thumbnail region as relative padding from the thumbnail borders.
/// </summary>
/// <remarks>Makes sense only in relative mode.</remarks>
public Padding BoundsAsPadding {
get {
#if DEBUG
if (!Relative)
throw new InvalidOperationException("Not allowed to use ThumbnailRegion Bounds as Padding value (not in relative mode).");
#endif
return new Padding {
Left = _bounds.X,
Top = _bounds.Y,
Right = _bounds.Width,
Bottom = _bounds.Height
};
}
}
/// <summary>
/// Gets the offset of the region.
/// </summary>
/// <remarks>
/// The offset is expressed as a point of displacement from the up-right corner (0,0) of the original source.
/// </remarks>
public Point Offset {
get {
//This is equal in both absolute and relative mode
return _bounds.Location;
}
}
const int MinimumRegionSize = 8;
/// <summary>
/// Computes the effective region representing the bounds inside a source thumbnail of a certain size.
/// </summary>
/// <param name="sourceSize">Size of the full thumbnail source.</param>
/// <returns>Bounds inside the thumbnail.</returns>
protected Rectangle ComputeRegion(Size sourceSize) {
Rectangle ret;
//Compute
if (Relative) {
ret = new Rectangle {
X = _bounds.X,
Y = _bounds.Y,
Width = sourceSize.Width - _bounds.X - _bounds.Width,
Height = sourceSize.Height - _bounds.Y - _bounds.Height
};
}
else {
ret = _bounds;
}
//Constrain to bounds
if (ret.X + ret.Width > sourceSize.Width)
ret.Width = sourceSize.Width - ret.X;
if (ret.Y + ret.Height > sourceSize.Height)
ret.Height = sourceSize.Height - ret.Y;
return ret;
}
/// <summary>
/// Computes a rectangle representing the bounds of the region inside a source thumbnail of a certain size.
/// </summary>
/// <param name="sourceSize">Size of the full thumbnail source.</param>
/// <returns>Bounds inside the thumbnail.</returns>
public Rectangle ComputeRegionRectangle(Size sourceSize) {
return ComputeRegion(sourceSize);
}
/// <summary>
/// Computes a value representing the size of the region inside a source thumbnail of a certain size.
/// </summary>
/// <param name="sourceSize">Size of the full thumbnail source.</param>
/// <returns>Size of the bounds inside the thumbnail.</returns>
public Size ComputeRegionSize(Size sourceSize) {
return ComputeRegion(sourceSize).Size;
}
/// <summary>
/// Switches the region to relative mode, according to a source thumbnail of a given size.
/// </summary>
/// <param name="sourceSize">Size of the full thumbnail source.</param>
public void SwitchToRelative(Size sourceSize) {
if (Relative)
return;
var relativeBounds = new Padding {
Left = _bounds.X,
Top = _bounds.Y,
Right = sourceSize.Width - (_bounds.X + _bounds.Width),
Bottom = sourceSize.Height - (_bounds.Y + _bounds.Height)
};
this.SetRelativeBounds(relativeBounds);
}
/// <summary>
/// Switches the region to absolute mode, according to a source thumbnail of a given size.
/// </summary>
/// <param name="sourceSize">Size of the full thumbnail source.</param>
public void SwitchToAbsolute(Size sourceSize) {
if (!Relative)
return;
var absoluteBounds = new Rectangle {
X = _bounds.X,
Y = _bounds.Y,
Width = (sourceSize.Width - _bounds.Width) - _bounds.X,
Height = (sourceSize.Height - _bounds.Height) - _bounds.Y
};
Bounds = absoluteBounds;
}
public override string ToString() {
return string.Format("({0}, {1})", _bounds, (Relative) ? "relative" : "absolute");
}
}
}