/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace XenAdmin.Controls
{
public partial class SectionHeaderLabel : UserControl
{
///
/// Vertical Alignment enumeration. This doesn;t appear in .NET until 4.0
///
public enum VerticalAlignment
{
///
/// Align to the Top of the control
///
Top,
///
/// Align to the vertical center of the control
///
Middle,
///
/// Align to the Bottom of the control
///
Bottom
}
///
/// Horizontal alignment of the control text
///
[Localizable(true)]
public HorizontalAlignment LabelHorizontalAlignment { get; set; }
///
/// Text to display
///
[Localizable(true)]
public string LabelText { get; set; }
///
/// Padding around the text
///
[Localizable(true)]
public Padding LabelPadding { get; set; }
///
/// Vertical alignment of the header line
///
public VerticalAlignment LineLocation { get; set; }
///
/// Color of the header line
///
public Color LineColor { get; set; }
///
/// Padding around the header line
///
[Localizable(true)]
public Padding LinePadding { get; set; }
///
/// Use mnemonic for setting focus on a control
///
[Localizable(true)]
public bool UseMnemonic { get; set; }
///
/// The control on which to set focus when mnemonic key is pressed
///
[Localizable(true)]
public Control FocusControl { get; set; }
///
/// Public constructor
///
public SectionHeaderLabel()
{
InitializeComponent();
this.LineColor = Color.Black;
SetStyle(ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw, true);
}
///
/// Custom OnPoint method
///
/// PaintEventArgs object
protected override void OnPaint(PaintEventArgs e)
{
DrawLine(e.Graphics);
DrawLabel(e.Graphics);
Size baseHeight = new Size(0, this.Padding.Vertical +
(this.LinePadding.Vertical + 1) +
this.LabelPadding.Vertical +
(int)e.Graphics.MeasureString(this.LabelText, this.Font).Height);
this.MinimumSize = baseHeight;
base.OnPaint(e);
}
///
/// Handle mnemonic events to set focus to the FocusControl
///
///
///
protected override bool ProcessMnemonic(char charCode)
{
if (this.UseMnemonic && Control.IsMnemonic(charCode, this.LabelText) && (Control.ModifierKeys == Keys.Alt) && null != this.FocusControl)
{
this.FocusControl.Focus();
return true;
}
else
{
return false;
}
}
///
/// Draws the text label of the control
///
/// Current graphics drawing object
private void DrawLabel(Graphics graphics)
{
StringFormat sf = new StringFormat();
if (this.UseMnemonic)
{
sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show;
if (!this.ShowKeyboardCues)
sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Hide;
}
else
sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.None;
sf.FormatFlags = StringFormatFlags.NoWrap;
//Make sure our brush is disposed
using (SolidBrush brush = new SolidBrush(this.ForeColor))
{
PointF pointF = GetTextPointF(graphics);
//Draw the actual text
graphics.DrawString(this.LabelText, this.Font, brush, pointF, sf);
}
}
///
/// Draw the header line
///
/// Current graphics drawing object
private void DrawLine(Graphics graphics)
{
//These are used a lot in here...
SizeF textSizeF = graphics.MeasureString(this.LabelText, this.Font);
float lineY = GetLineVerticalLocation();
//Make sure our pen is disposed
using (Pen pen = new Pen(this.LineColor))
{
if (LineLocation == VerticalAlignment.Middle)
{
switch (LabelHorizontalAlignment)
{
case HorizontalAlignment.Left:
{
//Draw a line from the right end of the text to the right end of the control
DrawLeftLine(graphics, textSizeF, lineY, pen);
break;
}
case HorizontalAlignment.Right:
{
//Draw a line from the left end of the control to the left end of the text
DrawRightLine(graphics, textSizeF, lineY, pen);
break;
}
case HorizontalAlignment.Center:
{
//Draw a line from the left of the control, to the left of the label,
// then from the right of the label to the right of the control
DrawLeftLine(graphics, textSizeF, lineY, pen);
DrawRightLine(graphics, textSizeF, lineY, pen);
break;
}
}
}
else
{
float startX = (float)this.Padding.Left + //Control left padding
(float)LinePadding.Left; //Line left padding
float endX = (float)this.Width - //Control width
(float)this.Padding.Right - //Control right padding
(float)this.LinePadding.Right; //Line right padding
graphics.DrawLine(pen, startX, lineY, endX, lineY);
}
}
}
private void DrawRightLine(Graphics graphics, SizeF textSizeF, float lineY, Pen pen)
{
float startX = (float)this.Padding.Left + //Control left padding
(float)LinePadding.Left; //Line left padding
float endX = (float)this.Width - //Control width
(float)this.Padding.Right - //Control right padding
(float)this.LinePadding.Right - //Line right padding
(float)this.LabelPadding.Horizontal - //Label horizontal padding
textSizeF.Width; //Width of the label text
graphics.DrawLine(pen, startX, lineY, endX, lineY);
}
private void DrawLeftLine(Graphics graphics, SizeF textSizeF, float lineY, Pen pen)
{
float startX = (float)this.Padding.Left + //Control left padding
(float)LabelPadding.Horizontal + //Label left+right padding
(float)LinePadding.Left + //Line left padding
textSizeF.Width; //Width of the label text
float endX = (float)this.Width - //Control width
(float)this.Padding.Right - //Control right padding
(float)this.LinePadding.Right; //Line right padding
graphics.DrawLine(pen, startX, lineY, endX, lineY);
}
///
/// Determines the left point of the line
///
/// Current graphics drawing object
/// Returns the left PointF
private PointF GetLeftLinePoint(Graphics graphics)
{
PointF pointF = new PointF();
pointF.X = this.Padding.Left + this.LinePadding.Left;
pointF.Y = GetLineVerticalLocation();
return pointF;
}
///
/// Determines the right point of the line
///
/// Current graphics drawing object
/// Returns the right PointF
private PointF GetRightLinePoint(Graphics graphics)
{
PointF pointF = new PointF();
pointF.X = this.Width - this.Padding.Right - this.LinePadding.Right;
pointF.Y = GetLineVerticalLocation();
return pointF;
}
///
/// Determines the vertical location of the line
///
/// the float location for the line Y
private float GetLineVerticalLocation()
{
float Y = 0f;
switch (this.LineLocation)
{
case VerticalAlignment.Top:
{
Y = this.Padding.Top + this.LinePadding.Top + 1;
break;
}
case VerticalAlignment.Middle:
{
Y = (this.Height - this.Padding.Vertical) / 2;
break;
}
case VerticalAlignment.Bottom:
{
Y = (this.Height - this.Padding.Bottom - this.LinePadding.Bottom - 1);
break;
}
}
return Y;
}
///
/// Determines the point location for the label text
///
/// Current graphics drawing object
/// The PointF location of the label text
private PointF GetTextPointF(Graphics graphics)
{
SizeF textSize = graphics.MeasureString(this.LabelText, this.Font);
PointF pointF = new PointF();
pointF.Y = this.Padding.Top + this.LabelPadding.Top + 1;
//If both the line and the label are top aligned,
// bump the text down, including the line's padding
if (LineLocation == VerticalAlignment.Top)
{
pointF.Y += this.LinePadding.Vertical + 1;
}
switch (this.LabelHorizontalAlignment)
{
case HorizontalAlignment.Left:
{
pointF.X = this.Padding.Left + this.LabelPadding.Left;
break;
}
case HorizontalAlignment.Center:
{
pointF.X = (this.Width - this.Padding.Horizontal) / 2 - (int)textSize.Width / 2;
break;
}
case HorizontalAlignment.Right:
{
pointF.X = (this.Width - this.Padding.Right - this.LabelPadding.Right) - (int)textSize.Width;
break;
}
}
return pointF;
}
}
}