using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Windows.Forms; namespace OnTopReplica { /// /// Represents a thumbnail region. /// /// /// 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 /// property. /// In relative mode, the region is expressed in padding pixels from the borders of the source. Internally this /// is still represented by the 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 /// public class ThumbnailRegion { /// /// Creates a ThumbnailRegion from a padding value relative to the thumbnail borders. /// public ThumbnailRegion(Padding padding) { _bounds = new Rectangle { X = padding.Left, Y = padding.Top, Width = padding.Right, Height = padding.Bottom }; Relative = true; } /// /// Creates a ThumbnailRegion from a bounds rectangle (in absolute terms). /// public ThumbnailRegion(Rectangle rectangle) { _bounds = rectangle; Relative = false; } /// /// Creates a ThumbnailRegion from a rectangle, either expressing values in relative or in absolute terms. /// public ThumbnailRegion(Rectangle paddingOrBounds, bool relative) { _bounds = paddingOrBounds; Relative = relative; } private Rectangle _bounds; /// /// Gets or sets the bounds of the thumbnail region. /// 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; } } /// /// Gets or sets whether the bounds are expressed relative to the thumbnail borders. /// public bool Relative { get; set; } /// /// Sets the relative bounds of the region. Switches to relative mode. /// /// Padding in relative terms from the borders. public void SetRelativeBounds(Padding padding) { Bounds = new Rectangle { X = padding.Left, Y = padding.Top, Width = padding.Right, Height = padding.Bottom }; Relative = true; } /// /// Gets the bounds of the thumbnail region as relative padding from the thumbnail borders. /// /// Makes sense only in relative mode. 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 }; } } /// /// Gets the offset of the region. /// /// /// The offset is expressed as a point of displacement from the up-right corner (0,0) of the original source. /// public Point Offset { get { //This is equal in both absolute and relative mode return _bounds.Location; } } const int MinimumRegionSize = 8; /// /// Computes the effective region representing the bounds inside a source thumbnail of a certain size. /// /// Size of the full thumbnail source. /// Bounds inside the thumbnail. 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; } /// /// Computes a rectangle representing the bounds of the region inside a source thumbnail of a certain size. /// /// Size of the full thumbnail source. /// Bounds inside the thumbnail. public Rectangle ComputeRegionRectangle(Size sourceSize) { return ComputeRegion(sourceSize); } /// /// Computes a value representing the size of the region inside a source thumbnail of a certain size. /// /// Size of the full thumbnail source. /// Size of the bounds inside the thumbnail. public Size ComputeRegionSize(Size sourceSize) { return ComputeRegion(sourceSize).Size; } /// /// Switches the region to relative mode, according to a source thumbnail of a given size. /// /// Size of the full thumbnail source. 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); } /// /// Switches the region to absolute mode, according to a source thumbnail of a given size. /// /// Size of the full thumbnail source. 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"); } } }