485 lines
20 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;
namespace DevComponents.DotNetBar.Layout
{
/// <summary>
/// Represents layout item which hosts a Windows Forms Control.
/// </summary>
[Designer("DevComponents.DotNetBar.Layout.Design.LayoutControlItemDesigner, DevComponents.DotNetBar.Layout.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=7eb7c3a35b91de04")]
public class LayoutControlItem : LayoutItemBase
{
#region Constructor
protected override void OnDispose()
{
UnhookControlEventHandlers(_Control);
base.OnDispose();
}
#endregion
#region Implementation
protected override void OnUpdateLayout()
{
base.OnUpdateLayout();
if (_Control != null)
{
Rectangle bounds = Helpers.Deflate(this.Bounds, this.Padding);
Rectangle r = bounds;
if (this.TextVisible && !string.IsNullOrEmpty(this.Text))
{
Rectangle actualTextBounds = this.ActualTextBounds;
if (IsImageVisible)
actualTextBounds = Rectangle.Union(actualTextBounds, this.ActualImageBounds);
if (this.TextPosition == eLayoutPosition.Default || this.TextPosition == eLayoutPosition.Left)
{
r.X = actualTextBounds.Right + _TextControlSpacing;
r.Width = bounds.Right - r.X;
}
else if (this.TextPosition == eLayoutPosition.Top)
{
r.Y = actualTextBounds.Bottom + _TextControlSpacing;
r.Height = bounds.Bottom - r.Y;
}
else if (this.TextPosition == eLayoutPosition.Bottom)
{
r.Height = actualTextBounds.Y - bounds.Y - _TextControlSpacing;
}
else if (this.TextPosition == eLayoutPosition.Right)
{
r.Width = actualTextBounds.X - r.X - _TextControlSpacing;
}
}
if (_Control.Margin.Horizontal > 0 || _Control.Margin.Vertical > 0)
{
r.X += _Control.Margin.Left;
r.Width -= _Control.Margin.Horizontal;
r.Y += _Control.Margin.Top;
r.Height -= _Control.Margin.Vertical;
}
if (!_ControlSize.IsEmpty && _Control.Dock != DockStyle.Fill && (_ControlSize.Width > 0 && r.Width > _ControlSize.Width) || (_ControlSize.Height > 0 && r.Height > _ControlSize.Height))
{
Size controlSize = new Size(_ControlSize.Width > 0 ? Math.Min(r.Width, _ControlSize.Width) : r.Width,
_ControlSize.Height > 0 ? Math.Min(r.Height, _ControlSize.Height) : r.Height);
if (_Control.Dock != DockStyle.None)
{
if (_Control.Dock == DockStyle.Left)
r = new Rectangle(r.X, r.Y, controlSize.Width, r.Height);
else if (_Control.Dock == DockStyle.Right)
r = new Rectangle(r.Right - controlSize.Width, r.Y, controlSize.Width, r.Height);
else if (_Control.Dock == DockStyle.Top)
r = new Rectangle(r.X, r.Y, r.Width, controlSize.Height);
else if (_Control.Dock == DockStyle.Bottom)
r = new Rectangle(r.X, r.Bottom - controlSize.Height, r.Width, controlSize.Height);
}
else
{
if (_Control.Anchor == (AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom))
{
// Center into the bounding box
r.X += (r.Width - controlSize.Width) / 2;
r.Y += (r.Height - controlSize.Height) / 2;
r.Size = controlSize;
}
else if (_Control.Anchor == (AnchorStyles.Left | AnchorStyles.Top))
{
r.Size = controlSize;
}
else if (_Control.Anchor == (AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Right))
{
r.X += (r.Width - controlSize.Width) / 2;
r.Size = controlSize;
}
else if (_Control.Anchor == (AnchorStyles.Left | AnchorStyles.Top | AnchorStyles.Bottom))
{
r.Y += (r.Height - controlSize.Height) / 2;
r.Size = controlSize;
}
else if (_Control.Anchor == (AnchorStyles.Left | AnchorStyles.Bottom))
{
r.Y = r.Bottom - controlSize.Height;
r.Size = controlSize;
}
else if (_Control.Anchor == (AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right))
{
r.Y = r.Bottom - controlSize.Height;
r.X += (r.Width - controlSize.Width) / 2;
r.Size = controlSize;
}
else if (_Control.Anchor == (AnchorStyles.Right | AnchorStyles.Top))
{
r.X = r.Right - controlSize.Width;
r.Size = controlSize;
}
else if (_Control.Anchor == (AnchorStyles.Right | AnchorStyles.Bottom))
{
r.X = r.Right - controlSize.Width;
r.Y = r.Bottom - controlSize.Height;
r.Size = controlSize;
}
else if (_Control.Anchor == (AnchorStyles.Right | AnchorStyles.Bottom | AnchorStyles.Top))
{
r.X = r.Right - controlSize.Width;
r.Y += (r.Height - controlSize.Height) / 2;
r.Size = controlSize;
}
else
r.Size = controlSize;
}
}
_Control.Bounds = r;
}
}
protected override void OnPaintBackground(PaintContext context)
{
base.OnPaintBackground(context);
if (IsKeyboardFocusWithin && context.FocusStyle != null)
{
DrawingHelpers.PaintStyle(context.Graphics, context.FocusStyle, this.Bounds);
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override void ScaleItem(SizeF factor)
{
base.ScaleItem(factor);
bool widthChanged = factor.Width != 1f;
bool heightChanged = factor.Height != 1f;
if (!_ControlSize.IsEmpty && (widthChanged || heightChanged))
{
Size newSize = new Size();
if (widthChanged)
newSize.Width = (int)(_ControlSize.Width * factor.Width);
else
newSize.Width = _ControlSize.Width;
if (heightChanged)
newSize.Height = (int)(_ControlSize.Height * factor.Height);
else
newSize.Height = _ControlSize.Height;
ControlSize = newSize;
}
}
internal override void UpdateScrollBounds(int xScroll, int yScroll, bool moveControls)
{
base.UpdateScrollBounds(xScroll, yScroll, moveControls);
if (moveControls && _Control != null)
_Control.Location = new Point(_Control.Location.X + xScroll, _Control.Location.Y + yScroll);
}
protected override Size OnMeasureText(LayoutContext c)
{
if (_Control is TextBoxBase && this.TextPosition == eLayoutPosition.Default)
{
TextBoxBase textBox = (TextBoxBase)_Control;
int textBaseLine = Helpers.GetTextBaseline(_Control, ContentAlignment.TopLeft);
if (textBox is DevComponents.DotNetBar.Controls.TextBoxX)
textBaseLine += 3;
else if (textBox.BorderStyle == BorderStyle.FixedSingle || textBox.BorderStyle == BorderStyle.None)
textBaseLine += 2;
else if (textBox.BorderStyle == BorderStyle.Fixed3D)
textBaseLine += 3;
_ControlTextBaseline = textBaseLine;
}
else
_ControlTextBaseline = 0;
return base.OnMeasureText(c);
}
internal override int TextBaseline
{
get
{
if (_ControlTextBaseline > 0 && _ControlTextBaseline > base.TextBaseline)
return _ControlTextBaseline;
return base.TextBaseline;
}
set
{
base.TextBaseline = value;
}
}
private int _ControlTextBaseline = 0;
private Control _Control = null;
/// <summary>
/// Gets or sets the control managed by layout item.
/// </summary>
[DefaultValue(null), Category("Data"), Description("Indicates control managed by layout item.")]
public Control Control
{
get { return _Control; }
set
{
if (value != _Control)
{
Control oldValue = _Control;
_Control = value;
OnControlChanged(oldValue, value);
}
}
}
private void UnhookControlEventHandlers(Control control)
{
if (control == null) return;
control.Enter -= ControlEnter;
control.Leave -= ControlLeave;
control.MouseHover -= ControlMouseHover;
control.MouseDown -= ControlMouseDown;
control.MouseMove -= ControlMouseMove;
control.MouseLeave -= ControlMouseLeave;
}
/// <summary>
/// Called when Control property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnControlChanged(Control oldValue, Control newValue)
{
if (oldValue != null)
{
UnhookControlEventHandlers(oldValue);
}
OnPropertyChanged(new PropertyChangedEventArgs("Control"));
if (_Control != null)
{
_Control.Enter += ControlEnter;
_Control.Leave += ControlLeave;
_Control.MouseHover += ControlMouseHover;
_Control.MouseDown += ControlMouseDown;
_Control.MouseMove += ControlMouseMove;
_Control.MouseLeave += ControlMouseLeave;
if (_Control.Visible != this.Visible)
_Control.Visible = this.Visible;
}
InvalidateLayout();
}
private Point _MouseTooltipLocation = Point.Empty;
void ControlMouseLeave(object sender, EventArgs e)
{
_MouseTooltipLocation = Point.Empty;
if (ToolTipVisible)
HideToolTip();
}
void ControlMouseMove(object sender, MouseEventArgs e)
{
if (!_MouseTooltipLocation.IsEmpty && ToolTipVisible && (Math.Abs(_MouseTooltipLocation.X - e.X) > 1 || Math.Abs(_MouseTooltipLocation.Y - e.Y) > 1))
HideToolTip();
}
void ControlMouseDown(object sender, MouseEventArgs e)
{
if (ToolTipVisible)
HideToolTip();
}
void ControlMouseHover(object sender, EventArgs e)
{
if (_EnableControlTooltip)
{
ShowToolTip();
_MouseTooltipLocation = _Control.PointToClient(Control.MousePosition);
}
}
private void ControlLeave(object sender, EventArgs e)
{
IsKeyboardFocusWithin = false;
}
private void ControlEnter(object sender, EventArgs e)
{
IsKeyboardFocusWithin = true;
}
private bool _EnableControlTooltip = true;
/// <summary>
/// Indicates whether Tooltip for the item is shown when mouse is over the control.
/// </summary>
[DefaultValue(true), Category("Behavior"), Description("Indicates whether Tooltip for the item is shown when mouse is over the control.")]
public bool EnableControlTooltip
{
get { return _EnableControlTooltip; }
set
{
if (value != _EnableControlTooltip)
{
bool oldValue = _EnableControlTooltip;
_EnableControlTooltip = value;
OnEnableControlTooltipChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when EnableControlTooltip property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnEnableControlTooltipChanged(bool oldValue, bool newValue)
{
OnPropertyChanged(new PropertyChangedEventArgs("EnableControlTooltip"));
}
private int _TextControlSpacing = 3;
/// <summary>
/// Indicates spacing between text and the control.
/// </summary>
[DefaultValue(3), Category("Appearance"), Description("Indicates spacing between text and the control."), RefreshProperties(RefreshProperties.All)]
public int TextControlSpacing
{
get { return _TextControlSpacing; }
set
{
if (value != _TextControlSpacing)
{
int oldValue = _TextControlSpacing;
_TextControlSpacing = value;
OnTextControlSpacingChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when TextControlSpacing property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnTextControlSpacingChanged(int oldValue, int newValue)
{
OnPropertyChanged(new PropertyChangedEventArgs("TextControlSpacing"));
InvalidateLayout();
}
/// <summary>
/// Processes accelerator key for the item.
/// </summary>
/// <param name="charCode"></param>
internal override bool ProcessMnemonic(char charCode)
{
if (MnemonicsEnabled && _Control != null && _Control.CanSelect)
{
_Control.Select();
return true;
}
return false;
}
private Size _ControlSize = Size.Empty;
/// <summary>
/// Indicates suggested control size which is used only if calculated layout size for the control exceeds the size specified here. Either width or height may be set or both.
/// ControlSize property can be used in conjuction with Dock and Anchor properties on the Control. When available space for the Control
/// exceeds ControlSize the Dock and Anchor properties will indicate the control position inside of the control box.
/// </summary>
[Category("Appearance"), Description("Indicates suggested control size which is used only if calculated layout size for the control exceeds the size specified here. Either width or height may be set or both.")]
public Size ControlSize
{
get { return _ControlSize; }
set
{
if (value != _ControlSize)
{
Size oldValue = _ControlSize;
_ControlSize = value;
OnControlSizeChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when ControlSize property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnControlSizeChanged(Size oldValue, Size newValue)
{
OnPropertyChanged(new PropertyChangedEventArgs("ControlSize"));
InvalidateLayout();
}
[EditorBrowsable(EditorBrowsableState.Never)]
public bool ShouldSerializeControlSize()
{
return !_ControlSize.IsEmpty;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public void ResetControlSize()
{
ControlSize = Size.Empty;
}
private bool _AutoSetTabIndex = true;
/// <summary>
/// Indicates whether Control TabIndex is automatically set based on the position of the item inside of the layout.
/// </summary>
[DefaultValue(true), Category("Behavior"), Description("Indicates whether Control TabIndex is automatically set based on the position of the item inside of the layout.")]
public bool AutoSetTabIndex
{
get { return _AutoSetTabIndex; }
set
{
if (value != _AutoSetTabIndex)
{
bool oldValue = _AutoSetTabIndex;
_AutoSetTabIndex = value;
OnAutoSetTabIndexChanged(oldValue, value);
}
}
}
/// <summary>
/// Called when AutoSetTabIndex property has changed.
/// </summary>
/// <param name="oldValue">Old property value</param>
/// <param name="newValue">New property value</param>
protected virtual void OnAutoSetTabIndexChanged(bool oldValue, bool newValue)
{
OnPropertyChanged(new PropertyChangedEventArgs("AutoSetTabIndex"));
}
protected override void OnAbsoluteIndexChanged(int oldValue, int newValue)
{
if (_Control != null && _AutoSetTabIndex) _Control.TabIndex = newValue;
base.OnAbsoluteIndexChanged(oldValue, newValue);
}
private bool _FocusVisualStyleEnabled = true;
/// <summary>
/// Indicates whether LayoutControl.FocusStyle is used to paint background of item when control has input focus.
/// </summary>
[DefaultValue(true), Category("Behavior"), Description("Indicates whether LayoutControl.FocusStyle is used to paint background of item when control has input focus.")]
public bool FocusVisualStyleEnabled
{
get { return _FocusVisualStyleEnabled; }
set
{
if (_FocusVisualStyleEnabled == value)
return;
_FocusVisualStyleEnabled = value;
if (this.IsKeyboardFocusWithin)
this.Invalidate();
OnPropertyChanged(new PropertyChangedEventArgs("FocusVisualStyleEnabled"));
}
}
protected override void OnVisibleChanged(bool oldValue, bool newValue)
{
if (_Control != null)
_Control.Visible = newValue;
base.OnVisibleChanged(oldValue, newValue);
}
#endregion
}
}