using DevComponents.DotNetBar.Rendering;
using DevComponents.DotNetBar.TextMarkup;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using DevComponents.DotNetBar.Metro.Helpers;
namespace DevComponents.DotNetBar.Controls
{
public class DesktopAlertWindow : Form
{
#region Constructor
public DesktopAlertWindow()
{
this.SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque |
ControlStyles.ResizeRedraw | ControlStyles.DoubleBuffer, true);
this.AccessibleRole = System.Windows.Forms.AccessibleRole.Alert;
this.ClientSize = DefaultAlertSizeValue;
this.AutoScaleDimensions = new SizeF(96f, 96f);
this.AutoScaleMode = AutoScaleMode.Dpi;
this.ControlBox = false;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.ShowInTaskbar = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = FormStartPosition.Manual;
this.Padding = new System.Windows.Forms.Padding(8);
this.Font = new Font("Segoe UI", 10.125F);
}
protected override void Dispose(bool disposing)
{
DestroyAutoCloseTimer();
base.Dispose(disposing);
}
#endregion
#region Implementation
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Color backColor = this.BackColor;
Color foreColor = this.ForeColor;
using (SolidBrush brush = new SolidBrush(backColor))
g.FillRectangle(brush, this.ClientRectangle);
if (_CloseButtonVisible)
{
Font symFont = Symbols.GetFont(12f, eSymbolSet.Material);
TextDrawing.DrawStringLegacy(g, "\uE14C", symFont,
(_CloseButtonMouseOver ? ColorHelpers.GetShadeColor(foreColor) : foreColor),
_CloseButtonBounds,
eTextFormat.Default | eTextFormat.NoClipping);
}
if (!string.IsNullOrEmpty(_SymbolRealized))
{
Font symFont = Symbols.GetFont(_SymbolSize, _SymbolSet);
TextDrawing.DrawStringLegacy(g, _SymbolRealized, symFont, _SymbolColor.IsEmpty ? foreColor : _SymbolColor,
_ImageBounds,
eTextFormat.Default | eTextFormat.NoClipping | eTextFormat.VerticalCenter);
}
else if (_Image != null)
{
g.DrawImage(_Image, _ImageBounds);
}
Rectangle r = _TextBounds;
if (r.Bottom > this.ClientRectangle.Bottom - this.Padding.Bottom)
r.Height -= (r.Bottom - (this.ClientRectangle.Bottom - this.Padding.Bottom));
eTextFormat format = TextFormat;
if (_TextMarkup == null)
{
if (this.RightToLeft == RightToLeft.Yes) format |= eTextFormat.RightToLeft;
if (UseTextRenderer)
{
TextRenderer.DrawText(g, Text, Font, r, foreColor, backColor,
TextDrawing.GetTextFormatFlags(format));
}
else
TextDrawing.DrawString(g, Text, this.Font, foreColor, r, format);
}
else
{
TextMarkup.MarkupDrawContext d = new TextMarkup.MarkupDrawContext(g, this.Font, foreColor,
(this.RightToLeft == RightToLeft.Yes), r, true);
Size markupSize = _TextMarkup.Bounds.Size;
if (!markupSize.IsEmpty && (format & eTextFormat.VerticalCenter) == eTextFormat.VerticalCenter && r.Height>markupSize.Height)
{
r.Y += (r.Height - markupSize.Height) / 2;
r.Height = markupSize.Height;
}
_TextMarkup.Arrange(r, d);
_TextMarkup.Render(d);
}
base.OnPaint(e);
}
private eTextFormat TextFormat
{
get
{
return eTextFormat.Default | eTextFormat.WordBreak | eTextFormat.VerticalCenter | eTextFormat.EndEllipsis;
}
}
protected override void OnMouseEnter(EventArgs e)
{
if (_AutoClose && _AutoCloseTimer != null)
_AutoCloseTimer.Enabled = false;
base.OnMouseEnter(e);
}
protected override void OnMouseLeave(EventArgs e)
{
if (_TextMarkup != null)
_TextMarkup.MouseLeave(this);
if (_AutoClose && _AutoCloseTimer != null)
_AutoCloseTimer.Enabled = true;
base.OnMouseLeave(e);
}
private bool _CloseButtonMouseOver = false;
protected override void OnMouseMove(MouseEventArgs e)
{
if (_CloseButtonVisible && _CloseButtonBounds.Contains(e.Location))
{
_CloseButtonMouseOver = true;
Invalidate(_CloseButtonBounds);
}
else if (_CloseButtonMouseOver)
{
_CloseButtonMouseOver = false;
Invalidate(_CloseButtonBounds);
}
if (_TextMarkup != null)
_TextMarkup.MouseMove(this, e);
base.OnMouseMove(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (_TextMarkup != null)
_TextMarkup.MouseDown(this, e);
base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)
{
if (_TextMarkup != null)
_TextMarkup.MouseUp(this, e);
if (_CloseButtonMouseOver && e.Button == MouseButtons.Left)
this.HideAlert(eAlertClosureSource.CloseButton);
base.OnMouseUp(e);
}
private bool _AutoSize = true;
[DefaultValue(true)]
public override bool AutoSize
{
get
{
return _AutoSize;
}
set
{
_AutoSize = value;
}
}
private Rectangle _ImageBounds = Rectangle.Empty;
private Rectangle _TextBounds = Rectangle.Empty;
private Rectangle _CloseButtonBounds = Rectangle.Empty;
///
/// Sets alert size based on its content, it respects MinimumSize and MaximumSize property settings.
///
public void PerformAutoSize()
{
Size size = Dpi.Size(_DefaultAlertSize);
if (!this.MinimumSize.IsEmpty)
size = Dpi.Size(this.MinimumSize);
if (!this.IsHandleCreated)
this.CreateHandle();
size = LayoutAlert(size);
Size maximumSize = this.MaximumSize;
if (!maximumSize.IsEmpty)
{
if (maximumSize.Width > 0 && size.Width > maximumSize.Width)
size.Width = maximumSize.Width;
if (maximumSize.Height > 0 && size.Height > maximumSize.Height)
size.Height = maximumSize.Height;
size = LayoutAlert(size);
}
this.Size = size;
}
private Size LayoutAlert(Size size)
{
Rectangle r = new Rectangle(Point.Empty, size);
r.X += Dpi.Width(this.Padding.Left);
r.Width -= Dpi.Width(this.Padding.Horizontal);
r.Y += Dpi.Height(this.Padding.Top);
r.Height -= Dpi.Height(this.Padding.Vertical);
if (!string.IsNullOrEmpty(Text) || !string.IsNullOrEmpty(_SymbolRealized) || _Image != null)
{
using (Graphics g = BarFunctions.CreateGraphics(this))
{
if (_CloseButtonVisible)
{
Font symFont = Symbols.GetFont(12f, eSymbolSet.Material);
Size closeSize = TextDrawing.MeasureString(g, "\uE14C", symFont); // Need to do this to get consistent size for the symbol since they are not all the same width we pick widest
_CloseButtonBounds = new Rectangle(r.Right - closeSize.Width - Dpi.Width4, r.Y + Dpi.Height4, closeSize.Width, closeSize.Height);
r.Width -= closeSize.Width + Dpi.Width8;
}
_ImageBounds = Rectangle.Empty;
if (!string.IsNullOrEmpty(_SymbolRealized))
{
Size symSize = GetSymbolSize(g);
symSize.Width += Dpi.Width2;
_ImageBounds = new Rectangle(r.X, r.Y, symSize.Width, symSize.Height);
r.X += symSize.Width + _ImageTextPadding;
r.Width -= symSize.Width + _ImageTextPadding;
if (symSize.Height > r.Height)
{
size.Height += (symSize.Height - r.Height);
r.Height = symSize.Height;
}
else
{
_ImageBounds.Height = r.Height;
}
}
else if (_Image != null)
{
_ImageBounds = new Rectangle(r.X, r.Y, _Image.Width, _Image.Height);
r.X += _Image.Width + _ImageTextPadding;
r.Width -= _Image.Width + _ImageTextPadding;
if (_Image.Height > r.Height)
{
size.Height += (_Image.Height - r.Height);
r.Height = _Image.Height;
}
}
_TextBounds = Rectangle.Empty;
if (_TextMarkup != null)
{
MarkupDrawContext dc = GetMarkupDrawContext(g);
_TextMarkup.Measure(r.Size, dc);
Size sz = _TextMarkup.Bounds.Size;
_TextMarkup.Arrange(new Rectangle(r.Location, sz), dc);
if (sz.Width > r.Width)
{
size.Width += (sz.Width - r.Width);
r.Width = size.Width;
}
if (sz.Height > r.Height)
{
size.Height += (sz.Height - r.Height);
r.Height = size.Height;
}
_TextBounds = r;
}
else if (!string.IsNullOrEmpty(this.Text))
{
Size sz = (UseTextRenderer ? TextRenderer.MeasureText(g, this.Text, this.Font, r.Size, TextDrawing.GetTextFormatFlags(TextFormat)) : TextDrawing.MeasureString(g, this.Text, this.Font, size, TextFormat));
if (sz.Width > r.Width)
{
size.Width += (sz.Width - r.Width);
r.Width = size.Width;
}
if (sz.Height > r.Height)
{
size.Height += (sz.Height - r.Height);
r.Height = size.Height;
}
_TextBounds = r;
}
}
}
return size;
}
private MarkupDrawContext GetMarkupDrawContext(Graphics g)
{
return new MarkupDrawContext(g, this.Font, this.ForeColor, this.RightToLeft == RightToLeft.Yes);
}
private Size GetSymbolSize(Graphics g)
{
Size symbolSize = Size.Empty;
if (g == null || string.IsNullOrEmpty(_Symbol)) return symbolSize;
Font symFont = Symbols.GetFont(this.SymbolSize, this.SymbolSet);
symbolSize = TextDrawing.MeasureString(g, "\uF00A", symFont); // Need to do this to get consistent size for the symbol since they are not all the same width we pick widest
//int descent = (int)Math.Ceiling((symFont.FontFamily.GetCellDescent(symFont.Style) *
// symFont.Size / symFont.FontFamily.GetEmHeight(symFont.Style)));
//symbolSize.Height -= descent;
return symbolSize;
}
//private Color[] _BackColors = null;
/////
///// Indicates the array of colors that when set are used to draw the background of the alert.
/////
//[DefaultValue(null), Category("Appearance"), Description("Indicates the array of colors that when set are used to draw the background of the alert."), TypeConverter(typeof(ArrayConverter))]
//public Color[] BackColors
//{
// get
// {
// return _BackColors;
// }
// set
// {
// if (_BackColors != value)
// {
// _BackColors = value;
// this.Invalidate();
// }
// }
//}
//private Color[] _BorderColors = null;
/////
///// Indicates the array of colors that when set are used to draw the border of the alert.
/////
//[DefaultValue(null), Category("Appearance"), Description("Indicates the array of colors that when set are used to draw the border of the alert."), TypeConverter(typeof(ArrayConverter))]
//public Color[] BorderColors
//{
// get
// {
// return _BorderColors;
// }
// set
// {
// if (_BorderColors != value)
// {
// _BorderColors = value;
// //OnPropertyChanged(new PropertyChangedEventArgs("Colors"));
// this.Invalidate();
// }
// }
//}
private Color _SymbolColor = Color.Empty;
///
/// Gets or sets the color of the Symbol.
///
[Category("Appearance"), Description("Indicates color of the Symbol.")]
public Color SymbolColor
{
get { return _SymbolColor; }
set { _SymbolColor = value; this.Invalidate(); }
}
///
/// Gets whether property should be serialized.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeSymbolColor()
{
return !_SymbolColor.IsEmpty;
}
///
/// Resets property to its default value.
///
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetSymbolColor()
{
this.SymbolColor = Color.Empty;
}
///
/// Gets the realized symbol string.
///
[Browsable(false)]
public string SymbolRealized
{
get { return _SymbolRealized; }
}
private string _Symbol = "", _SymbolRealized = "";
///
/// Indicates the symbol displayed on face of the button instead of the image. Setting the symbol overrides the image setting.
///
[DefaultValue(""), Category("Appearance"), Description("Indicates the symbol displayed on face of the button instead of the image. Setting the symbol overrides the image setting.")]
[Editor("DevComponents.DotNetBar.Design.SymbolTypeEditor, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(System.Drawing.Design.UITypeEditor))]
public string Symbol
{
get { return _Symbol; }
set
{
if (value != _Symbol)
{
string oldValue = _Symbol;
_Symbol = value;
OnSymbolChanged(oldValue, value);
}
}
}
///
/// Called when Symbol property has changed.
///
/// Old property value
/// New property value
protected virtual void OnSymbolChanged(string oldValue, string newValue)
{
if (string.IsNullOrEmpty(newValue))
_SymbolRealized = "";
else
_SymbolRealized = Symbols.GetSymbol(newValue);
this.Invalidate();
}
private eSymbolSet _SymbolSet = eSymbolSet.Awesome;
///
/// Gets or sets the symbol set used to represent the Symbol.
///
[Browsable(false), DefaultValue(eSymbolSet.Awesome)]
public eSymbolSet SymbolSet
{
get { return _SymbolSet; }
set
{
if (_SymbolSet != value)
{
eSymbolSet oldValue = _SymbolSet;
_SymbolSet = value;
OnSymbolSetChanged(oldValue, value);
}
}
}
///
/// Called when SymbolSet property value changes.
///
/// Indciates old value
/// Indicates new value
protected virtual void OnSymbolSetChanged(eSymbolSet oldValue, eSymbolSet newValue)
{
this.Invalidate();
this.Refresh();
}
private float _SymbolSize = 22f;
///
/// Indicates the size of the symbol in points.
///
[DefaultValue(22f), Category("Appearance"), Description("Indicates the size of the symbol in points.")]
public float SymbolSize
{
get { return _SymbolSize; }
set
{
if (value != _SymbolSize)
{
float oldValue = _SymbolSize;
_SymbolSize = value;
OnSymbolSizeChanged(oldValue, value);
}
}
}
///
/// Called when SymbolSize property has changed.
///
/// Old property value
/// New property value
protected virtual void OnSymbolSizeChanged(float oldValue, float newValue)
{
this.Invalidate();
}
private Image _Image = null;
///
/// Indicates image displayed on alert.
///
[DefaultValue(null), Category("Appearance"), Description("Indicates image displayed on alert.")]
public Image Image
{
get { return _Image; }
set
{
_Image = value;
this.Invalidate();
}
}
protected override void OnTextChanged(EventArgs e)
{
// Markup support
MarkupTextChanged();
base.OnTextChanged(e);
}
//private string _TitleText = "";
/////
///// Gets or sets the tile title text displayed by default in lower left corner.
/////
//[DefaultValue(""), Category("Appearance"), Description("Indicates tile title text displayed by default in lower left corner"), Editor("DevComponents.DotNetBar.Design.TextMarkupUIEditor, DevComponents.DotNetBar.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(System.Drawing.Design.UITypeEditor))]
//public string TitleText
//{
// get { return _TitleText; }
// set
// {
// if (value != _TitleText)
// {
// string oldValue = _TitleText;
// _TitleText = value;
// OnTitleTextChanged(oldValue, value);
// }
// }
//}
/////
///// Called when TitleText property has changed.
/////
///// Old property value
///// New property value
//protected virtual void OnTitleTextChanged(string oldValue, string newValue)
//{
// TitleTextMarkupUpdate();
// this.Invalidate();
// //OnPropertyChanged(new PropertyChangedEventArgs("TitleText"));
//}
/////
///// Gets reference to parsed markup body element if text was markup otherwise returns null.
/////
//internal TextMarkup.BodyElement TitleTextMarkupBody
//{
// get { return _TitleTextMarkup; }
//}
//private TextMarkup.BodyElement _TitleTextMarkup = null;
//private void TitleTextMarkupUpdate()
//{
// if (_TitleTextMarkup != null)
// _TitleTextMarkup.HyperLinkClick -= TitleTextMarkupLinkClicked;
// _TitleTextMarkup = null;
// if (!_TextMarkupEnabled)
// return;
// if (!TextMarkup.MarkupParser.IsMarkup(ref _TitleText))
// return;
// _TitleTextMarkup = TextMarkup.MarkupParser.Parse(_TitleText);
// if (_TitleTextMarkup != null)
// _TitleTextMarkup.HyperLinkClick += TitleTextMarkupLinkClicked;
//}
//private void TitleTextMarkupLinkClicked(object sender, EventArgs e)
//{
// DevComponents.DotNetBar.TextMarkup.HyperLink link = sender as DevComponents.DotNetBar.TextMarkup.HyperLink;
// if (link != null)
// OnTitleTextMarkupLinkClick(new MarkupLinkClickEventArgs(link.Name, link.HRef));
// else
// OnTitleTextMarkupLinkClick(e);
//}
/////
///// Occurs when an hyperlink in title text markup is clicked.
/////
//public event EventHandler TitleTextMarkupLinkClick;
/////
///// Raises TitleTextMarkupLinkClick event.
/////
///// Provides event arguments.
//protected virtual void OnTitleTextMarkupLinkClick(EventArgs e)
//{
// EventHandler handler = TitleTextMarkupLinkClick;
// if (handler != null)
// handler(this, e);
//}
//private Font _TitleTextFont = null;
/////
///// Gets or sets the title text font.
/////
//[DefaultValue(null), Category("Appearance"), Description("Gets or sets the title text font.")]
//public Font TitleTextFont
//{
// get { return _TitleTextFont; }
// set
// {
// if (value != _TitleTextFont)
// {
// Font oldValue = _TitleTextFont;
// _TitleTextFont = value;
// OnTitleTextFontChanged(oldValue, value);
// }
// }
//}
/////
///// Called when TitleTextFont property has changed.
/////
///// Old property value
///// New property value
//protected virtual void OnTitleTextFontChanged(Font oldValue, Font newValue)
//{
// this.Invalidate();
// //OnPropertyChanged(new PropertyChangedEventArgs("TitleTextFont"));
//}
//private Rectangle _TitleTextBounds = Rectangle.Empty;
//internal Rectangle TitleTextBounds
//{
// get
// {
// return _TitleTextBounds;
// }
// set
// {
// _TitleTextBounds = value;
// }
//}
//private Color _TitleTextColor = Color.Empty;
/////
///// Gets or sets the color of the title text.
/////
//[Category("Columns"), Description("Indicates color of title text.")]
//public Color TitleTextColor
//{
// get { return _TitleTextColor; }
// set
// {
// if (_TitleTextColor != value)
// {
// Color oldValue = _TitleTextColor;
// _TitleTextColor = value;
// OnTitleTextColorChanged(oldValue, value);
// }
// }
//}
/////
///// Called when TitleTextColor property has changed.
/////
///// Old property value
///// New property value
//protected virtual void OnTitleTextColorChanged(Color oldValue, Color newValue)
//{
// this.Invalidate();
// //OnPropertyChanged(new PropertyChangedEventArgs("TitleTextColor"));
//}
/////
///// Gets whether property should be serialized.
/////
//[EditorBrowsable(EditorBrowsableState.Never)]
//public bool ShouldSerializeTitleTextColor()
//{
// return !_TitleTextColor.IsEmpty;
//}
/////
///// Resets property to its default value.
/////
//[EditorBrowsable(EditorBrowsableState.Never)]
//public void ResetTitleTextColor()
//{
// this.TitleTextColor = Color.Empty;
//}
//private ContentAlignment _TitleTextAlignment = ContentAlignment.BottomLeft;
/////
///// Gets or sets title text alignment.
/////
//[DefaultValue(ContentAlignment.BottomLeft), Category("Appearance"), Description("Indicates title text alignment.")]
//public ContentAlignment TitleTextAlignment
//{
// get { return _TitleTextAlignment; }
// set
// {
// if (value != _TitleTextAlignment)
// {
// ContentAlignment oldValue = _TitleTextAlignment;
// _TitleTextAlignment = value;
// OnTitleTextAlignmentChanged(oldValue, value);
// }
// }
//}
/////
///// Called when TitleTextAlignment property has changed.
/////
///// Old property value
///// New property value
//protected virtual void OnTitleTextAlignmentChanged(ContentAlignment oldValue, ContentAlignment newValue)
//{
// //OnPropertyChanged(new PropertyChangedEventArgs("TitleTextAlignment"));
// this.Invalidate();
//}
protected override void OnClick(EventArgs e)
{
if (_TextMarkup != null && _TextMarkup.MouseOverElement is HyperLink)
{
_TextMarkup.Click(this);
base.OnClick(e);
return;
}
else if (_CloseButtonMouseOver)
{
base.OnClick(e);
return;
}
if (_ClickAction != null)
{
_ClickAction.Invoke(_AlertId);
this.HideAlert(eAlertClosureSource.AlertClicked);
}
base.OnClick(e);
}
private long _AlertId = 0;
///
/// Indicates optional Alert Id.
///
[Browsable(false), DefaultValue(0)]
public long AlertId {
get { return _AlertId; }
set { _AlertId = value; }
}
private Action _ClickAction = null;
///
/// Indicates the method that will be invoked if user clicks the alert.
///
[Browsable(false), DefaultValue(null)]
public Action ClickAction
{
get { return _ClickAction; }
set { _ClickAction = value; }
}
private bool _TextMarkupEnabled = true;
///
/// Gets or sets whether text-markup can be used in Text property.
///
[DefaultValue(true), Category("Appearance"), Description("Indicates whether text-markup can be used in Text property.")]
public bool TextMarkupEnabled
{
get { return _TextMarkupEnabled; }
set
{
if (value != _TextMarkupEnabled)
{
bool oldValue = _TextMarkupEnabled;
_TextMarkupEnabled = value;
OnTextMarkupEnabledChanged(oldValue, value);
}
}
}
///
/// Called when TextMarkupEnabled property has changed.
///
/// Old property value
/// New property value
protected virtual void OnTextMarkupEnabledChanged(bool oldValue, bool newValue)
{
//OnPropertyChanged(new PropertyChangedEventArgs("TextMarkupEnabled"));
this.Invalidate();
}
#endregion
#region Markup Implementation
private TextMarkup.BodyElement _TextMarkup = null;
private void MarkupTextChanged()
{
if (_TextMarkup != null)
_TextMarkup.HyperLinkClick -= TextMarkupLinkClick;
_TextMarkup = null;
if (!_TextMarkupEnabled)
return;
string text = this.Text;
if (!TextMarkup.MarkupParser.IsMarkup(ref text))
return;
_TextMarkup = TextMarkup.MarkupParser.Parse(text);
if (_TextMarkup != null)
_TextMarkup.HyperLinkClick += TextMarkupLinkClick;
}
///
/// Occurs when text markup link is clicked.
///
protected virtual void TextMarkupLinkClick(object sender, EventArgs e)
{
TextMarkup.HyperLink link = sender as TextMarkup.HyperLink;
if (link != null)
OnMarkupLinkClick(new MarkupLinkClickEventArgs(link.Name, link.HRef));
}
///
/// Occurs when text markup link is clicked. Markup links can be created using "a" tag, for example:
/// Markup link
///
[Description("Occurs when text markup link is clicked. Markup links can be created using a tag.")]
public event MarkupLinkClickEventHandler MarkupLinkClick;
///
/// Raises MarkupLinkClick event.
///
/// Provides event arguments.
protected virtual void OnMarkupLinkClick(MarkupLinkClickEventArgs e)
{
MarkupLinkClickEventHandler handler = MarkupLinkClick;
if (handler != null)
handler(this, e);
}
///
/// Gets reference to parsed markup body element if text was markup otherwise returns null.
///
internal TextMarkup.BodyElement TextMarkupBody
{
get { return _TextMarkup; }
}
internal static Size MeasureText(DesktopAlertWindow item, Graphics g, int containerWidth, Font font, eTextFormat stringFormat, bool rightToLeft)
{
if (item.Text == "" && item.TextMarkupBody == null) return Size.Empty;
Size textSize = Size.Empty;
if (item.TextMarkupBody == null)
{
textSize = TextDrawing.MeasureString(g, ButtonItemPainter.GetDrawText(item.Text), font, containerWidth, stringFormat);
}
else
{
Size availSize = new Size(containerWidth, 1);
if (containerWidth == 0)
availSize.Width = 1600;
TextMarkup.MarkupDrawContext d = new TextMarkup.MarkupDrawContext(g, font, Color.Empty, false);
item.TextMarkupBody.Measure(availSize, d);
availSize = item.TextMarkupBody.Bounds.Size;
if (containerWidth != 0)
availSize.Width = containerWidth;
d.RightToLeft = rightToLeft;
item.TextMarkupBody.Arrange(new Rectangle(0, 0, availSize.Width, availSize.Height), d);
textSize = item.TextMarkupBody.Bounds.Size;
}
return textSize;
}
private static readonly Size DefaultAlertSizeValue = new Size(360, 64);
private Size _DefaultAlertSize = DefaultAlertSizeValue;
///
/// Gets or sets the default alert size.
///
[Category("Appearance"), Description("Indicates default alert size.")]
public Size DefaultAlertSize
{
get { return _DefaultAlertSize; }
set
{
if (value != _DefaultAlertSize)
{
Size oldValue = _DefaultAlertSize;
_DefaultAlertSize = value;
OnDefaultAlertSizeChanged(oldValue, value);
}
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeDefaultAlertSize()
{
return _DefaultAlertSize.Width != DefaultAlertSizeValue.Width || _DefaultAlertSize.Height != DefaultAlertSizeValue.Height;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetDefaultAlertSize()
{
DefaultAlertSize = DefaultAlertSizeValue;
}
private void OnDefaultAlertSizeChanged(Size oldValue, Size newValue)
{
if (_AutoSize && this.IsHandleCreated)
PerformAutoSize();
}
//private eAlertAnimation _AlertAnimation = eAlertAnimation.RightToLeft;
/////
///// Gets or sets the animation type used to display Alert.
/////
//[Browsable(true), Description("Gets or sets the animation type used to display Alert."), Category("Behavior"), DefaultValue(eAlertAnimation.RightToLeft)]
//public eAlertAnimation AlertAnimation
//{
// get { return _AlertAnimation; }
// set { _AlertAnimation = value; }
//}
private int _AlertAnimationDuration = 200;
///
/// Gets or sets the total time in milliseconds alert animation takes.
/// Default value is 200.
///
[Browsable(true), Description("Gets or sets the total time in milliseconds alert animation takes."), Category("Behavior"), DefaultValue(200)]
public int AlertAnimationDuration
{
get { return _AlertAnimationDuration; }
set { _AlertAnimationDuration = value; }
}
private bool _AutoClose = true;
///
/// Gets or sets whether balloon will close automatically when user click the close button.
///
[Description("Indicates whether balloon will close automatically when user click the close button."), Category("Behavior"), DefaultValue(true)]
public bool AutoClose
{
get { return _AutoClose; }
set { _AutoClose = value; }
}
private int _AutoCloseTimeOut = 6;
///
/// Gets or sets time period in seconds after alert closes automatically.
///
[Description("Indicates time period in seconds after balloon closes automatically."), Category("Behavior"), DefaultValue(6)]
public int AutoCloseTimeOut
{
get { return _AutoCloseTimeOut; }
set
{
_AutoCloseTimeOut = value;
OnAutoCloseTimeOutChanged();
}
}
private System.Windows.Forms.Timer _AutoCloseTimer = null;
protected void OnAutoCloseTimeOutChanged()
{
if (_AutoCloseTimeOut > 0 && !this.DesignMode)
{
StartAutoCloseTimer();
}
else
{
DestroyAutoCloseTimer();
}
}
private void StartAutoCloseTimer()
{
if (_AutoCloseTimer == null)
{
_AutoCloseTimer = new System.Windows.Forms.Timer();
_AutoCloseTimer.Enabled = false;
_AutoCloseTimer.Tick += new EventHandler(this.AutoCloseTimeOutEllapsed);
}
_AutoCloseTimer.Interval = _AutoCloseTimeOut * 1000;
if (this.Visible)
{
_AutoCloseTimer.Enabled = true;
_AutoCloseTimer.Start();
}
}
protected virtual void AutoCloseTimeOutEllapsed(object sender, EventArgs e)
{
if (this.IsDisposed)
return;
DestroyAutoCloseTimer();
this.HideAlert(eAlertClosureSource.Timeout);
this.Close();
}
private void DestroyAutoCloseTimer()
{
if (_AutoCloseTimer != null)
{
_AutoCloseTimer.Enabled = false;
_AutoCloseTimer.Tick -= new EventHandler(this.AutoCloseTimeOutEllapsed);
_AutoCloseTimer.Dispose();
_AutoCloseTimer = null;
}
}
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (this.Visible)
{
if (_AutoCloseTimeOut > 0)
StartAutoCloseTimer();
if (_AutoCloseTimer != null && !_AutoCloseTimer.Enabled)
{
_AutoCloseTimer.Enabled = true;
_AutoCloseTimer.Start();
}
}
else
{
if (_AutoCloseTimer != null && _AutoCloseTimer.Enabled)
{
_AutoCloseTimer.Stop();
_AutoCloseTimer.Enabled = false;
}
}
}
private Control _ReferenceControl = null;
///
/// Specifies the reference control which is used to find which screen the alert is displayed on. If not specified alert is displayed on primary screen.
///
[DefaultValue(null), Browsable(false)]
public Control ReferenceControl
{
get { return _ReferenceControl; }
set { _ReferenceControl = value; }
}
private static Semaphore _DisplayPositionsSemaphore = new Semaphore(1, 1);
private static List _DisplayPositions = new List();
private Rectangle GetAlertBounds()
{
Rectangle r = this.Bounds;
ScreenInformation si = null;
if (_ReferenceControl == null)
si = BarFunctions.PrimaryScreen;
else
si = BarFunctions.ScreenFromControl(_ReferenceControl);
if (_AlertPosition == eAlertPosition.BottomRight)
{
r = new Rectangle(si.WorkingArea.Right - this.Width, si.WorkingArea.Bottom - this.Height - Dpi.Height12, this.Width, this.Height);
}
else if (_AlertPosition == eAlertPosition.BottomLeft)
{
r = new Rectangle(si.WorkingArea.Left, si.WorkingArea.Bottom - this.Height - Dpi.Height12, this.Width, this.Height);
}
else if (_AlertPosition == eAlertPosition.TopRight)
{
r = new Rectangle(si.WorkingArea.Right - this.Width, si.WorkingArea.Top + Dpi.Height12, this.Width, this.Height);
}
else if (_AlertPosition == eAlertPosition.TopLeft)
{
r = new Rectangle(si.WorkingArea.Left, si.WorkingArea.Top + Dpi.Height12, this.Width, this.Height);
}
// Now adjust display position
if (_DisplayPositions.Count > 0)
{
if(_AlertPosition == eAlertPosition.TopLeft || _AlertPosition == eAlertPosition.TopRight)
_DisplayPositions.Sort(_RectangleComparer);
else
_DisplayPositions.Sort(_RectangleReverseComparer);
Rectangle originalBounds = r;
for (int i = 0; i < _DisplayPositions.Count; i++)
{
if (_DisplayPositions[i].IntersectsWith(r))
{
if (_AlertPosition == eAlertPosition.BottomLeft || _AlertPosition == eAlertPosition.BottomRight)
r.Y -= _DisplayPositions[i].Height + _AlertsSpacing;
else
r.Y += _DisplayPositions[i].Height + _AlertsSpacing;
}
else
break;
if (!si.WorkingArea.Contains(r))
{
r = originalBounds;
break;
}
if (i == _DisplayPositions.Count - 1)
break;
}
}
_DisplayPositionsSemaphore.WaitOne();
try
{
_DisplayPositions.Add(r);
}
finally
{
_DisplayPositionsSemaphore.Release();
}
return r;
}
private static readonly RectangleComparer _RectangleComparer = new RectangleComparer();
private static readonly RectangleReverseComparer _RectangleReverseComparer = new RectangleReverseComparer();
private class RectangleComparer : IComparer
{
public int Compare(Rectangle x, Rectangle y)
{
return x.Y - y.Y;
}
}
private class RectangleReverseComparer : IComparer
{
public int Compare(Rectangle x, Rectangle y)
{
return y.Y - x.Y;
}
}
protected override void OnClosed(EventArgs e)
{
_DisplayPositionsSemaphore.WaitOne();
try
{
for (int i = _DisplayPositions.Count - 1; i >= 0; i--)
{
if (_DisplayPositions[i] == this.Bounds)
{
_DisplayPositions.RemoveAt(i);
break;
}
}
}
finally
{
_DisplayPositionsSemaphore.Release();
}
base.OnClosed(e);
}
///
/// Display balloon.
///
/// Indicates whether alert receives input focus upon showing.
public void Show(bool focusAlert)
{
PerformAutoSize();
this.Bounds = GetAlertBounds();
Rectangle rEnd = this.Bounds;
DesktopAlert.OnBeforeAlertDisplayed(this, EventArgs.Empty);
if(this.IsDisposed)
return;
if (ShouldAnimate())
{
try
{
_AnimationInProgress = true;
eAlertAnimation alertAnimation = GetAlertAnimation();
if (alertAnimation == eAlertAnimation.RightToLeft)
NativeFunctions.AnimateWindow(this.Handle, _AlertAnimationDuration, (NativeFunctions.AW_SLIDE | NativeFunctions.AW_HOR_NEGATIVE));
else if (alertAnimation == eAlertAnimation.LeftToRight)
NativeFunctions.AnimateWindow(this.Handle, _AlertAnimationDuration, (NativeFunctions.AW_SLIDE | NativeFunctions.AW_HOR_POSITIVE));
else if (alertAnimation == eAlertAnimation.BottomToTop)
NativeFunctions.AnimateWindow(this.Handle, _AlertAnimationDuration, (NativeFunctions.AW_SLIDE | NativeFunctions.AW_VER_NEGATIVE));
else if (alertAnimation == eAlertAnimation.TopToBottom)
NativeFunctions.AnimateWindow(this.Handle, _AlertAnimationDuration, (NativeFunctions.AW_SLIDE | NativeFunctions.AW_VER_POSITIVE));
}
finally
{
_AnimationInProgress = false;
}
}
base.Show();
if (_TopMost)
NativeFunctions.SetWindowPos(this.Handle,
new IntPtr(NativeFunctions.HWND_TOPMOST), 0, 0, 0, 0,
NativeFunctions.SWP_NOACTIVATE | NativeFunctions.SWP_NOMOVE | NativeFunctions.SWP_NOSIZE);
//this.Visible = true;
if (_PlaySound)
System.Media.SystemSounds.Beep.Play();
}
protected override bool ShowWithoutActivation
{
get
{
return true;
}
}
private eAlertAnimation GetAlertAnimation()
{
if (_AlertPosition == eAlertPosition.TopLeft || _AlertPosition == eAlertPosition.BottomLeft)
return eAlertAnimation.LeftToRight;
else
return eAlertAnimation.RightToLeft;
}
///
/// Displays balloon.
///
public new void Show()
{
this.Show(false);
}
private bool _AnimationInProgress = false;
///
/// Called when alert needs to be hidden.
///
protected virtual void HideAlert(eAlertClosureSource source)
{
DestroyAutoCloseTimer();
if (ShouldAnimate())
{
Rectangle rStart = this.Bounds;
//Rectangle rEnd = GetAnimationRectangle();
try
{
_AnimationInProgress = true;
eAlertAnimation alertAnimation = GetAlertAnimation();
if (alertAnimation == eAlertAnimation.RightToLeft)
NativeFunctions.AnimateWindow(this.Handle, _AlertAnimationDuration, (NativeFunctions.AW_SLIDE | NativeFunctions.AW_HOR_POSITIVE | NativeFunctions.AW_HIDE));
else if (alertAnimation == eAlertAnimation.LeftToRight)
NativeFunctions.AnimateWindow(this.Handle, _AlertAnimationDuration, (NativeFunctions.AW_SLIDE | NativeFunctions.AW_HOR_NEGATIVE | NativeFunctions.AW_HIDE));
else if (alertAnimation == eAlertAnimation.BottomToTop)
NativeFunctions.AnimateWindow(this.Handle, _AlertAnimationDuration, (NativeFunctions.AW_SLIDE | NativeFunctions.AW_VER_POSITIVE | NativeFunctions.AW_HIDE));
else if (alertAnimation == eAlertAnimation.TopToBottom)
NativeFunctions.AnimateWindow(this.Handle, _AlertAnimationDuration, (NativeFunctions.AW_SLIDE | NativeFunctions.AW_VER_NEGATIVE | NativeFunctions.AW_HIDE));
}
finally
{
_AnimationInProgress = false;
}
}
else
base.Hide();
this.Close();
DesktopAlert.OnAlertClosed(this, new AlertClosedEventArgs(source));
_ClickAction = null;
this.Dispose();
}
///
/// Hides balloon.
///
public new void Hide()
{
HideAlert(eAlertClosureSource.Timeout);
}
private bool ShouldAnimate()
{
if (_AlertAnimationDuration > 0 && !this.DesignMode && !this.IsDisposed)
return true;
return false;
}
private int _AlertsSpacing = 8;
///
/// Indicates spacing between alerts on the screen
///
[DefaultValue(8), Category("Behavior"), Description("Indicates spacing between alerts on the screen")]
public int AlertsSpacing
{
get { return _AlertsSpacing; }
set
{
if (_AlertsSpacing != value)
{
int oldValue = _AlertsSpacing;
_AlertsSpacing = value;
OnAlertsSpacingChanged(value, oldValue);
}
}
}
protected virtual void OnAlertsSpacingChanged(int newValue, int oldValue)
{
throw new NotImplementedException();
}
//private Rectangle GetAnimationRectangle()
//{
// Rectangle r = new Rectangle(this.Location, this.Size);
// if (_AlertAnimation == eAlertAnimation.BottomToTop)
// {
// r.Y = r.Bottom - 1;
// r.Height = 1;
// }
// else if (_AlertAnimation == eAlertAnimation.TopToBottom)
// {
// r.Height = 1;
// }
// else if (_AlertAnimation == eAlertAnimation.LeftToRight)
// {
// r.Width = 2;
// }
// else if (_AlertAnimation == eAlertAnimation.RightToLeft)
// {
// r.X = r.Right - 1;
// r.Width = 1;
// }
// return r;
//}
private eAlertPosition _AlertPosition = eAlertPosition.BottomRight;
///
/// Indicates the request screen position for the alert
///
[DefaultValue(eAlertPosition.BottomRight), Category("Behavior"), Description("Indicates the request screen position for the alert")]
public eAlertPosition AlertPosition
{
get { return _AlertPosition; }
set
{
if (_AlertPosition != value)
{
eAlertPosition oldValue = _AlertPosition;
_AlertPosition = value;
OnAlertPositionChanged(value, oldValue);
}
}
}
protected virtual void OnAlertPositionChanged(eAlertPosition newValue, eAlertPosition oldValue)
{
//throw new NotImplementedException();
}
private bool _TopMost = true;
[DefaultValue(true)]
public new bool TopMost
{
get { return _TopMost; }
set
{
if (_TopMost != value)
{
bool oldValue = _TopMost;
_TopMost = value;
OnTopMostChanged(value, oldValue);
}
}
}
protected virtual void OnTopMostChanged(bool newValue, bool oldValue)
{
if (IsHandleCreated && Visible)
NativeFunctions.SetWindowPos(this.Handle,
new IntPtr(newValue ? NativeFunctions.HWND_TOPMOST : NativeFunctions.HWND_NOTOPMOST), 0, 0, 0, 0,
NativeFunctions.SWP_NOACTIVATE | NativeFunctions.SWP_NOMOVE | NativeFunctions.SWP_NOSIZE);
}
private int _ImageTextPadding = 11;
///
/// Indicates spacing in pixels between image and text
///
[DefaultValue(11), Category("Appearance"), Description("Indicates spacing in pixels between image and text")]
public int ImageTextPadding
{
get { return _ImageTextPadding; }
set
{
if (_ImageTextPadding != value)
{
int oldValue = _ImageTextPadding;
_ImageTextPadding = value;
OnImageTextPaddingChanged(value, oldValue);
}
}
}
protected virtual void OnImageTextPaddingChanged(int newValue, int oldValue)
{
}
private bool UseTextRenderer
{
get { return true; /*_BackColors == null || _BackColors.Length < 2;*/ }
}
private bool _PlaySound = true;
///
/// Indicates whether alert plays exclamation sound when shown.
///
[DefaultValue(true), Category("Behavior"), Description("Indicates whether alert plays exclamation sound when shown.")]
public bool PlaySound
{
get { return _PlaySound; }
set
{
if (_PlaySound != value)
{
bool oldValue = _PlaySound;
_PlaySound = value;
OnPlaySoundChanged(value, oldValue);
}
}
}
protected virtual void OnPlaySoundChanged(bool newValue, bool oldValue)
{
//throw new NotImplementedException();
}
private bool _CloseButtonVisible = true;
///
/// Indicates whether close button on alert is visible
///
[DefaultValue(true), Category("Appearance"), Description("Indicates whether close button on alert is visible")]
public bool CloseButtonVisible
{
get { return _CloseButtonVisible; }
set
{
if (_CloseButtonVisible != value)
{
bool oldValue = _CloseButtonVisible;
_CloseButtonVisible = value;
OnCloseButtonVisibleChanged(value, oldValue);
}
}
}
protected virtual void OnCloseButtonVisibleChanged(bool newValue, bool oldValue)
{
//throw new NotImplementedException();
}
#endregion
}
///
/// Defines the alert positions.
///
public enum eAlertPosition
{
///
/// Top-left screen position.
///
TopLeft,
///
/// Top-right screen position.
///
TopRight,
///
/// Bottom-right screen position.
///
BottomRight,
///
/// Bottom left screen position.
///
BottomLeft
}
///
/// Defines closure sources for the alert.
///
public enum eAlertClosureSource
{
///
/// Alert is closed becouse of timeout
///
Timeout,
///
/// Alert is closed becouse user clicked close button.
///
CloseButton,
///
/// Alert is closed becouse user clicked on the alert.
///
AlertClicked
}
}