/*
* Overlays - Images, text or other things that can be rendered over the top of a ListView
*
* Author: Phillip Piper
* Date: 14/04/2009 4:36 PM
*
* Change log:
* v2.3
* 2009-08-17 JPP - Overlays now use Adornments
* - Added ITransparentOverlay interface. Overlays can now have separate transparency levels
* 2009-08-10 JPP - Moved decoration related code to new file
* v2.2.1
* 200-07-24 JPP - TintedColumnDecoration now works when last item is a member of a collapsed
* group (well, it no longer crashes).
* v2.2
* 2009-06-01 JPP - Make sure that TintedColumnDecoration reaches to the last item in group view
* 2009-05-05 JPP - Unified BillboardOverlay text rendering with that of TextOverlay
* 2009-04-30 JPP - Added TintedColumnDecoration
* 2009-04-14 JPP - Initial version
*
* To do:
*
* Copyright (C) 2009-2014 Phillip Piper
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
* If you wish to use this code in a closed source application, please contact phillip_piper@bigfoot.com.
*/
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace BrightIdeasSoftware
{
///
/// The interface for an object which can draw itself over the top of
/// an ObjectListView.
///
public interface IOverlay
{
///
/// Draw this overlay
///
/// The ObjectListView that is being overlaid
/// The Graphics onto the given OLV
/// The content area of the OLV
void Draw(ObjectListView olv, Graphics g, Rectangle r);
}
///
/// An interface for an overlay that supports variable levels of transparency
///
public interface ITransparentOverlay : IOverlay
{
///
/// Gets or sets the transparency of the overlay.
/// 0 is completely transparent, 255 is completely opaque.
///
int Transparency { get; set; }
}
///
/// A null implementation of the IOverlay interface
///
public class AbstractOverlay : ITransparentOverlay
{
#region IOverlay Members
///
/// Draw this overlay
///
/// The ObjectListView that is being overlaid
/// The Graphics onto the given OLV
/// The content area of the OLV
public virtual void Draw(ObjectListView olv, Graphics g, Rectangle r) {
}
#endregion
#region ITransparentOverlay Members
///
/// How transparent should this overlay be?
///
[Category("ObjectListView"),
Description("How transparent should this overlay be"),
DefaultValue(128),
NotifyParentProperty(true)]
public int Transparency {
get { return this.transparency; }
set { this.transparency = Math.Min(255, Math.Max(0, value)); }
}
private int transparency = 128;
#endregion
}
///
/// An overlay that will draw an image over the top of the ObjectListView
///
[TypeConverter("BrightIdeasSoftware.Design.OverlayConverter")]
public class ImageOverlay : ImageAdornment, ITransparentOverlay
{
///
/// Create an ImageOverlay
///
public ImageOverlay() {
this.Alignment = System.Drawing.ContentAlignment.BottomRight;
}
#region Public properties
///
/// Gets or sets the horizontal inset by which the position of the overlay will be adjusted
///
[Category("ObjectListView"),
Description("The horizontal inset by which the position of the overlay will be adjusted"),
DefaultValue(20),
NotifyParentProperty(true)]
public int InsetX {
get { return this.insetX; }
set { this.insetX = Math.Max(0, value); }
}
private int insetX = 20;
///
/// Gets or sets the vertical inset by which the position of the overlay will be adjusted
///
[Category("ObjectListView"),
Description("Gets or sets the vertical inset by which the position of the overlay will be adjusted"),
DefaultValue(20),
NotifyParentProperty(true)]
public int InsetY {
get { return this.insetY; }
set { this.insetY = Math.Max(0, value); }
}
private int insetY = 20;
#endregion
#region Commands
///
/// Draw this overlay
///
/// The ObjectListView being decorated
/// The Graphics used for drawing
/// The bounds of the rendering
public virtual void Draw(ObjectListView olv, Graphics g, Rectangle r) {
Rectangle insetRect = r;
insetRect.Inflate(-this.InsetX, -this.InsetY);
// We hard code a transparency of 255 here since transparency is handled by the glass panel
this.DrawImage(g, insetRect, this.Image, 255);
}
#endregion
}
///
/// An overlay that will draw text over the top of the ObjectListView
///
[TypeConverter("BrightIdeasSoftware.Design.OverlayConverter")]
public class TextOverlay : TextAdornment, ITransparentOverlay
{
///
/// Create a TextOverlay
///
public TextOverlay() {
this.Alignment = System.Drawing.ContentAlignment.BottomRight;
}
#region Public properties
///
/// Gets or sets the horizontal inset by which the position of the overlay will be adjusted
///
[Category("ObjectListView"),
Description("The horizontal inset by which the position of the overlay will be adjusted"),
DefaultValue(20),
NotifyParentProperty(true)]
public int InsetX {
get { return this.insetX; }
set { this.insetX = Math.Max(0, value); }
}
private int insetX = 20;
///
/// Gets or sets the vertical inset by which the position of the overlay will be adjusted
///
[Category("ObjectListView"),
Description("Gets or sets the vertical inset by which the position of the overlay will be adjusted"),
DefaultValue(20),
NotifyParentProperty(true)]
public int InsetY {
get { return this.insetY; }
set { this.insetY = Math.Max(0, value); }
}
private int insetY = 20;
///
/// Gets or sets whether the border will be drawn with rounded corners
///
[Browsable(false),
Obsolete("Use CornerRounding instead", false),
DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public bool RoundCorneredBorder {
get { return this.CornerRounding > 0; }
set {
if (value)
this.CornerRounding = 16.0f;
else
this.CornerRounding = 0.0f;
}
}
#endregion
#region Commands
///
/// Draw this overlay
///
/// The ObjectListView being decorated
/// The Graphics used for drawing
/// The bounds of the rendering
public virtual void Draw(ObjectListView olv, Graphics g, Rectangle r) {
if (String.IsNullOrEmpty(this.Text))
return;
Rectangle insetRect = r;
insetRect.Inflate(-this.InsetX, -this.InsetY);
// We hard code a transparency of 255 here since transparency is handled by the glass panel
this.DrawText(g, insetRect, this.Text, 255);
}
#endregion
}
///
/// A Billboard overlay is a TextOverlay positioned at an absolute point
///
public class BillboardOverlay : TextOverlay
{
///
/// Create a BillboardOverlay
///
public BillboardOverlay() {
this.Transparency = 255;
this.BackColor = Color.PeachPuff;
this.TextColor = Color.Black;
this.BorderColor = Color.Empty;
this.Font = new Font("Tahoma", 10);
}
///
/// Gets or sets where should the top left of the billboard be placed
///
public Point Location {
get { return this.location; }
set { this.location = value; }
}
private Point location;
///
/// Draw this overlay
///
/// The ObjectListView being decorated
/// The Graphics used for drawing
/// The bounds of the rendering
public override void Draw(ObjectListView olv, Graphics g, Rectangle r) {
if (String.IsNullOrEmpty(this.Text))
return;
// Calculate the bounds of the text, and then move it to where it should be
Rectangle textRect = this.CalculateTextBounds(g, r, this.Text);
textRect.Location = this.Location;
// Make sure the billboard is within the bounds of the List, as far as is possible
if (textRect.Right > r.Width)
textRect.X = Math.Max(r.Left, r.Width - textRect.Width);
if (textRect.Bottom > r.Height)
textRect.Y = Math.Max(r.Top, r.Height - textRect.Height);
this.DrawBorderedText(g, textRect, this.Text, 255);
}
}
}