1379 lines
52 KiB
C#
1379 lines
52 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using System.Drawing;
|
|
using System.Windows.Forms.Layout;
|
|
using System.ComponentModel;
|
|
|
|
namespace DevComponents.DotNetBar.Layout
|
|
{
|
|
[ToolboxItem(true)]
|
|
[Designer("DevComponents.DotNetBar.Layout.Design.LayoutControlDesigner, DevComponents.DotNetBar.Layout.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=7eb7c3a35b91de04")]
|
|
[ToolboxBitmap(typeof(LayoutControl), "LayoutControl.ico")]
|
|
public class LayoutControl : ContainerControl
|
|
{
|
|
/// <summary>
|
|
/// Initializes a new instance of the LayoutControl class.
|
|
/// </summary>
|
|
public LayoutControl()
|
|
{
|
|
this.SetStyle(ControlStyles.UserPaint | ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer
|
|
| ControlStyles.SupportsTransparentBackColor | ControlStyles.Opaque, true);
|
|
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
|
//this.SetStyle(ControlStyles.Opaque, true);
|
|
|
|
_RootGroup.IsRootGroup = true;
|
|
|
|
_HScrollBar = new DevComponents.DotNetBar.ScrollBar.HScrollBarAdv();
|
|
_HScrollBar.Height = SystemInformation.HorizontalScrollBarHeight;
|
|
_HScrollBar.Visible = false;
|
|
_HScrollBar.Scroll += new ScrollEventHandler(HScrollBarScroll);
|
|
this.Controls.Add(_HScrollBar);
|
|
|
|
_VScrollBar = new VScrollBarAdv();
|
|
_VScrollBar.Width = SystemInformation.VerticalScrollBarWidth;
|
|
_VScrollBar.Visible = false;
|
|
_VScrollBar.Scroll += VScrollBarScroll;
|
|
this.Controls.Add(_VScrollBar);
|
|
|
|
_Thumb = new Control();
|
|
_Thumb.Width = SystemInformation.VerticalScrollBarWidth;
|
|
_Thumb.Height = SystemInformation.HorizontalScrollBarHeight;
|
|
_Thumb.Visible = false;
|
|
this.Controls.Add(_Thumb);
|
|
|
|
_InsertMarker = new InsertMarker();
|
|
_InsertMarker.Visible = false;
|
|
this.Controls.Add(_InsertMarker);
|
|
|
|
_RootGroup.LayoutControl = this;
|
|
|
|
this.FocusStyle = new SimpleStyle();
|
|
|
|
if (BarFunctions.IsWindows7 && DevComponents.DotNetBar.Touch.TouchHandler.IsTouchEnabled)
|
|
{
|
|
_TouchHandler = new DevComponents.DotNetBar.Touch.TouchHandler(this, DevComponents.DotNetBar.Touch.eTouchHandlerType.Gesture);
|
|
_TouchHandler.PanBegin += new EventHandler<DevComponents.DotNetBar.Touch.GestureEventArgs>(TouchHandlerPanBegin);
|
|
_TouchHandler.Pan += new EventHandler<DevComponents.DotNetBar.Touch.GestureEventArgs>(TouchHandlerPan);
|
|
_TouchHandler.PanEnd += new EventHandler<DevComponents.DotNetBar.Touch.GestureEventArgs>(TouchHandlerPanEnd);
|
|
}
|
|
|
|
StyleManager.Register(this);
|
|
}
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing) StyleManager.Unregister(this);
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
private Color _CurrentBackColor = Color.Empty;
|
|
private void UpdateBackColor()
|
|
{
|
|
DevComponents.DotNetBar.Rendering.Office2007ColorTable table = ((DevComponents.DotNetBar.Rendering.Office2007Renderer)DevComponents.DotNetBar.Rendering.GlobalManager.Renderer).ColorTable;
|
|
_CurrentBackColor = table.Form.BackColor;
|
|
}
|
|
/// <summary>
|
|
/// Called by StyleManager to notify control that style on manager has changed and that control should refresh its appearance if
|
|
/// its style is controlled by StyleManager.
|
|
/// </summary>
|
|
/// <param name="newStyle">New active style.</param>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void StyleManagerStyleChanged(eDotNetBarStyle newStyle)
|
|
{
|
|
UpdateBackColor();
|
|
this.Invalidate(true);
|
|
}
|
|
void HScrollBarScroll(object sender, ScrollEventArgs e)
|
|
{
|
|
if (e.NewValue != e.OldValue)
|
|
ScrollControls(-e.NewValue, 0);
|
|
}
|
|
|
|
void VScrollBarScroll(object sender, ScrollEventArgs e)
|
|
{
|
|
if (e.NewValue != e.OldValue)
|
|
ScrollControls(0, -e.NewValue);
|
|
//Console.WriteLine("{0} {1} {2}", e.Type, e.NewValue, _RootGroup.ActualBounds.Height);
|
|
}
|
|
|
|
private Control _Thumb = null;
|
|
private DevComponents.DotNetBar.ScrollBar.HScrollBarAdv _HScrollBar = null;
|
|
private VScrollBarAdv _VScrollBar = null;
|
|
private InsertMarker _InsertMarker = null;
|
|
protected override void OnPaint(PaintEventArgs e)
|
|
{
|
|
#if TRIAL
|
|
if(WinApi.ColorExpAlt())
|
|
{
|
|
StringFormat format=new StringFormat(StringFormat.GenericDefault);
|
|
format.Alignment=StringAlignment.Center;
|
|
format.FormatFlags=format.FormatFlags & ~(format.FormatFlags & StringFormatFlags.NoWrap);
|
|
e.Graphics.DrawString("Thank you very much for trying DotNetBar. Unfortunately your trial period is over. To continue using DotNetBar you should purchase license at http://www.devcomponents.com",new Font(this.Font.FontFamily,12),SystemBrushes.Highlight,this.ClientRectangle,format);
|
|
format.Dispose();
|
|
return;
|
|
}
|
|
#endif
|
|
if ((this.BackColor.IsEmpty || this.BackColor == Color.Transparent))
|
|
{
|
|
base.OnPaintBackground(e);
|
|
}
|
|
else if(this.BackColor == SystemColors.Control && !_CurrentBackColor.IsEmpty)
|
|
{
|
|
using (SolidBrush brush = new SolidBrush(_CurrentBackColor))
|
|
e.Graphics.FillRectangle(brush, this.ClientRectangle);
|
|
}
|
|
else
|
|
{
|
|
using (SolidBrush brush = new SolidBrush(this.BackColor))
|
|
e.Graphics.FillRectangle(brush, this.ClientRectangle);
|
|
}
|
|
using (PaintContext context = new PaintContext(this, e.Graphics, _HotkeyPrefix))
|
|
{
|
|
_RootGroup.Paint(context);
|
|
}
|
|
//if (!string.IsNullOrEmpty(this.Text))
|
|
// e.Graphics.DrawString(this.Text, this.Font, Brushes.Black, new PointF(0, this.Height - 32));
|
|
base.OnPaint(e);
|
|
}
|
|
protected override void OnHandleCreated(EventArgs e)
|
|
{
|
|
UpdateBackColor();
|
|
_RootGroup.SetBounds(GetLayoutBounds());
|
|
//LayoutGroup();
|
|
base.OnHandleCreated(e);
|
|
}
|
|
private void LayoutGroup()
|
|
{
|
|
if (this.IsHandleCreated)
|
|
{
|
|
using (Graphics g = this.CreateGraphics())
|
|
{
|
|
LayoutContext context = new LayoutContext(this, g, _LabelFont ?? this.Font);
|
|
_RootGroup.Layout(context);
|
|
}
|
|
}
|
|
}
|
|
private Rectangle GetLayoutBounds()
|
|
{
|
|
Rectangle r = this.ClientRectangle;
|
|
return r;
|
|
}
|
|
protected override void OnLayout(LayoutEventArgs levent)
|
|
{
|
|
if (_VScrollBar == null || _HScrollBar == null || !this.IsHandleCreated) return;
|
|
|
|
Rectangle r = GetLayoutBounds();
|
|
if (r.Width <= 0 || r.Height <= 0) return;
|
|
|
|
WinApi.SendMessage(this.Handle, WinApi.WM_SETREDRAW, 0, 0);
|
|
|
|
r.Offset(_ScrollPosition);
|
|
_RootGroup.SetBounds(r);
|
|
LayoutGroup();
|
|
|
|
bool hScrollBarVisible = false, vScrollBarVisible = false;
|
|
|
|
if (_RootGroup.ActualBounds.Height > r.Height + 1)
|
|
{
|
|
vScrollBarVisible = true;
|
|
|
|
r.Width -= _VScrollBar.Width;
|
|
_RootGroup.SetBounds(r);
|
|
LayoutGroup();
|
|
|
|
if (_RootGroup.ActualBounds.Width > r.Width + 1)
|
|
{
|
|
hScrollBarVisible = true;
|
|
r.Height -= _HScrollBar.Height;
|
|
_RootGroup.SetBounds(r);
|
|
LayoutGroup();
|
|
}
|
|
|
|
}
|
|
else if (_RootGroup.ActualBounds.Width > r.Width + 1)
|
|
{
|
|
hScrollBarVisible = true;
|
|
|
|
r.Height -= _HScrollBar.Height;
|
|
|
|
_RootGroup.SetBounds(r);
|
|
LayoutGroup();
|
|
|
|
if (_RootGroup.ActualBounds.Height > r.Height + 1)
|
|
{
|
|
vScrollBarVisible = true;
|
|
r.Width -= _VScrollBar.Width;
|
|
_RootGroup.SetBounds(r);
|
|
LayoutGroup();
|
|
}
|
|
|
|
}
|
|
|
|
bool performLayout = false;
|
|
if (vScrollBarVisible && r.Height > 0)
|
|
{
|
|
_VScrollBar.Location = new Point(this.ClientRectangle.Right - _VScrollBar.Width, this.ClientRectangle.Y);
|
|
_VScrollBar.Height = this.ClientRectangle.Height - (hScrollBarVisible ? _HScrollBar.Height : 0);
|
|
if (_VScrollBar.Visible != vScrollBarVisible)
|
|
{
|
|
_VScrollBar.Value = 0;
|
|
_VScrollBar.Visible = true;
|
|
_VScrollBar.BringToFront();
|
|
}
|
|
_VScrollBar.Minimum = 0;
|
|
_VScrollBar.Maximum = _RootGroup.ActualBounds.Height - 1;
|
|
_VScrollBar.LargeChange = r.Height;
|
|
_VScrollBar.SmallChange = 16;
|
|
}
|
|
else if (_VScrollBar.Visible)
|
|
{
|
|
_VScrollBar.Visible = false;
|
|
if (_ScrollPosition.Y != 0)
|
|
{
|
|
_ScrollPosition.Y = 0;
|
|
performLayout = true;
|
|
}
|
|
}
|
|
|
|
if (hScrollBarVisible && r.Width > 0)
|
|
{
|
|
_HScrollBar.Location = new Point(this.ClientRectangle.X, this.ClientRectangle.Bottom - _HScrollBar.Height);
|
|
_HScrollBar.Width = this.ClientRectangle.Width - (vScrollBarVisible ? _VScrollBar.Width : 0);
|
|
if (_HScrollBar.Visible != hScrollBarVisible)
|
|
{
|
|
_HScrollBar.Value = 0;
|
|
_HScrollBar.Visible = true;
|
|
_HScrollBar.BringToFront();
|
|
}
|
|
_HScrollBar.Minimum = 0;
|
|
_HScrollBar.Maximum = _RootGroup.ActualBounds.Width - 1;
|
|
_HScrollBar.LargeChange = r.Width;
|
|
_HScrollBar.SmallChange = 16;
|
|
}
|
|
else if (_HScrollBar.Visible)
|
|
{
|
|
_HScrollBar.Visible = false;
|
|
if (_ScrollPosition.X != 0)
|
|
{
|
|
_ScrollPosition.X = 0;
|
|
performLayout = true;
|
|
}
|
|
}
|
|
|
|
if (vScrollBarVisible && hScrollBarVisible && r.Height > 0 && r.Width > 0)
|
|
{
|
|
_Thumb.Bounds = new Rectangle(this.ClientRectangle.Right - _VScrollBar.Width, this.ClientRectangle.Bottom - _HScrollBar.Height, _VScrollBar.Width, _HScrollBar.Height);
|
|
_Thumb.Visible = true;
|
|
_Thumb.BringToFront();
|
|
}
|
|
else if (_Thumb.Visible)
|
|
_Thumb.Visible = false;
|
|
|
|
if (performLayout)
|
|
{
|
|
r = GetLayoutBounds();
|
|
r.Offset(_ScrollPosition);
|
|
_RootGroup.SetBounds(r);
|
|
LayoutGroup();
|
|
}
|
|
|
|
WinApi.SendMessage(this.Handle, WinApi.WM_SETREDRAW, 1, 0);
|
|
this.Refresh();
|
|
base.OnLayout(levent);
|
|
}
|
|
|
|
protected override void OnMouseWheel(MouseEventArgs e)
|
|
{
|
|
if (_VScrollBar.Visible)
|
|
{
|
|
int y = -_VScrollBar.Value + Math.Sign(e.Delta) * _VScrollBar.SmallChange;
|
|
if (-y < 0) y = 0;
|
|
ScrollControls(0, y);
|
|
_VScrollBar.Value = Math.Min(_VScrollBar.Maximum - _VScrollBar.LargeChange, -y);
|
|
|
|
}
|
|
base.OnMouseWheel(e);
|
|
}
|
|
|
|
public new void ScrollControlIntoView(Control control)
|
|
{
|
|
LayoutItemBase item = FindControlItem(control);
|
|
if (item == null) return;
|
|
ScrollItemIntoView(item);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Brings specified item that belongs to this LayoutControl into view by scrolling control if necessary.
|
|
/// </summary>
|
|
/// <param name="item">Item to bring into view.</param>
|
|
public void ScrollItemIntoView(LayoutItemBase item)
|
|
{
|
|
if (item.GetLayoutControl() != this)
|
|
throw new ArgumentException("item does not belong to this control");
|
|
if (!_HScrollBar.Visible && !_VScrollBar.Visible) return;
|
|
|
|
Rectangle clientRect = this.ClientRectangle;
|
|
Rectangle itemBounds = item.Bounds;
|
|
//itemBounds.Offset(-_ScrollPosition.X,-_ScrollPosition.Y);
|
|
if (clientRect.Contains(itemBounds)) return;
|
|
|
|
Point scroll = new Point();
|
|
if (item.Bounds.Y < clientRect.Y)
|
|
{
|
|
scroll.Y = clientRect.Y - itemBounds.Y;
|
|
}
|
|
else if (item.Bounds.Bottom > clientRect.Bottom)
|
|
{
|
|
scroll.Y = Math.Max(-(_VScrollBar.Maximum - _VScrollBar.LargeChange), clientRect.Bottom - itemBounds.Bottom);
|
|
}
|
|
|
|
if (item.Bounds.X < clientRect.X)
|
|
{
|
|
scroll.X = clientRect.X - itemBounds.X;
|
|
}
|
|
else if (item.Bounds.Right > clientRect.Right)
|
|
{
|
|
scroll.X = clientRect.Right - itemBounds.Right;
|
|
}
|
|
|
|
if (!scroll.IsEmpty)
|
|
{
|
|
ScrollControls(_ScrollPosition.X + scroll.X, _ScrollPosition.Y + scroll.Y);
|
|
_VScrollBar.Value = Math.Max(0, Math.Min(Math.Abs(_ScrollPosition.Y), _VScrollBar.Maximum));
|
|
}
|
|
|
|
}
|
|
|
|
private LayoutGroup _RootGroup = new LayoutGroup();
|
|
/// <summary>
|
|
/// Gets the LayoutGroup for the control. LayoutGroup should not be changed.
|
|
/// </summary>
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Browsable(false)]
|
|
public LayoutGroup RootGroup
|
|
{
|
|
get { return _RootGroup; }
|
|
set
|
|
{
|
|
if (value != _RootGroup)
|
|
{
|
|
LayoutGroup oldValue = _RootGroup;
|
|
_RootGroup = value;
|
|
OnRootGroupChanged(oldValue, value);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when RootGroup property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnRootGroupChanged(LayoutGroup oldValue, LayoutGroup newValue)
|
|
{
|
|
if (oldValue != null)
|
|
{
|
|
oldValue.LayoutControl = null;
|
|
oldValue.IsRootGroup = false;
|
|
}
|
|
if (newValue != null)
|
|
{
|
|
newValue.LayoutControl = this;
|
|
newValue.IsRootGroup = true;
|
|
}
|
|
//OnPropertyChanged(new PropertyChangedEventArgs("RootGroup"));
|
|
|
|
}
|
|
|
|
private Font _LabelFont = null;
|
|
/// <summary>
|
|
/// Indicates font used for the item labels.
|
|
/// </summary>
|
|
[DefaultValue(null), Category("Appearance"), Description("Indicates font used for the item labels.")]
|
|
public Font LabelFont
|
|
{
|
|
get { return _LabelFont; }
|
|
set
|
|
{
|
|
if (value != _LabelFont)
|
|
{
|
|
Font oldValue = _LabelFont;
|
|
_LabelFont = value;
|
|
OnLabelFontChanged(oldValue, value);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when LabelFont property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnLabelFontChanged(Font oldValue, Font newValue)
|
|
{
|
|
//OnPropertyChanged(new PropertyChangedEventArgs("LabelFont"));
|
|
this.PerformLayout();
|
|
this.Invalidate();
|
|
}
|
|
|
|
private Color _LabelTextColor = Color.Empty;
|
|
/// <summary>
|
|
/// Gets or sets the color of the label text.
|
|
/// </summary>
|
|
[Category("Appearance"), Description("Indicates color of label text.")]
|
|
public Color LabelTextColor
|
|
{
|
|
get { return _LabelTextColor; }
|
|
set { _LabelTextColor = value; /*OnPropertyChanged("LabelTextColor");*/ this.Invalidate(); }
|
|
}
|
|
/// <summary>
|
|
/// Gets whether property should be serialized.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public bool ShouldSerializeLabelTextColor()
|
|
{
|
|
return !_LabelTextColor.IsEmpty;
|
|
}
|
|
/// <summary>
|
|
/// Resets property to its default value.
|
|
/// </summary>
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
public void ResetLabelTextColor()
|
|
{
|
|
this.LabelTextColor = Color.Empty;
|
|
}
|
|
|
|
private eTextAlignment _LabelTextAlignment = eTextAlignment.Default;
|
|
/// <summary>
|
|
/// Indicates the label text alignment within the text bounds.
|
|
/// </summary>
|
|
[DefaultValue(eTextAlignment.Default), Category("Appearance"), Description("Indicates the label text alignment within the text bounds.")]
|
|
public eTextAlignment LabelTextAlignment
|
|
{
|
|
get { return _LabelTextAlignment; }
|
|
set
|
|
{
|
|
if (value != _LabelTextAlignment)
|
|
{
|
|
eTextAlignment oldValue = _LabelTextAlignment;
|
|
_LabelTextAlignment = value;
|
|
OnLabelTextAlignmentChanged(oldValue, value);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when LabelTextAlignment property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnLabelTextAlignmentChanged(eTextAlignment oldValue, eTextAlignment newValue)
|
|
{
|
|
//OnPropertyChanged(new PropertyChangedEventArgs("LabelTextAlignment"));
|
|
this.Invalidate();
|
|
}
|
|
|
|
private EmptyLayoutManager _EmptyLayout = new EmptyLayoutManager();
|
|
public override LayoutEngine LayoutEngine
|
|
{
|
|
get
|
|
{
|
|
return _EmptyLayout;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sets default property values for LayoutControlItem given the control assigned to it.
|
|
/// </summary>
|
|
/// <param name="item">Reference to LayoutControlItem</param>
|
|
public void SetupControlItem(DevComponents.DotNetBar.Layout.LayoutControlItem item)
|
|
{
|
|
if (item == null || item.Control == null) return;
|
|
|
|
Control c = item.Control;
|
|
|
|
c.Margin = new System.Windows.Forms.Padding();
|
|
|
|
if (c is TextBoxBase)
|
|
{
|
|
item.Width = 100;
|
|
item.WidthType = eLayoutSizeType.Percent;
|
|
item.Height = c.Height + item.Padding.Vertical;
|
|
item.Text = "Label:";
|
|
item.MinSize = new Size(120, 0);
|
|
}
|
|
else if (c is ButtonBase || c is IButtonControl)
|
|
{
|
|
//item.ControlSize = c.Size;
|
|
item.Width = c.Width + item.Padding.Horizontal;
|
|
item.Height = c.Height + item.Padding.Vertical;
|
|
item.Text = "";
|
|
item.MinSize = new Size(32, 20);
|
|
}
|
|
else if(c is DevComponents.DotNetBar.Controls.RatingStar)
|
|
{
|
|
c.Text = "";
|
|
item.Width = c.Width + item.Padding.Horizontal;
|
|
item.Height = c.Height + item.Padding.Vertical;
|
|
item.Text = "Rating:";
|
|
item.MinSize = new Size(85, 23);
|
|
}
|
|
else
|
|
{
|
|
item.Width = c.Width + item.Padding.Horizontal;
|
|
item.Height = c.Height + item.Padding.Vertical;
|
|
item.Text = "Label:";
|
|
item.MinSize = new Size(64, 18);
|
|
}
|
|
}
|
|
|
|
private LayoutItemBase FindItemForMnemonic(LayoutGroup group, char charCode)
|
|
{
|
|
foreach (LayoutItemBase item in group.Items)
|
|
{
|
|
LayoutGroup childGroup = item as LayoutGroup;
|
|
if (childGroup != null)
|
|
{
|
|
LayoutItemBase item2 = FindItemForMnemonic(childGroup, charCode);
|
|
if (item2 != null) return item2;
|
|
}
|
|
else if (item.TextVisible && !string.IsNullOrEmpty(item.Text) && IsMnemonic(charCode, item.Text))
|
|
{
|
|
return item;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
private bool IsMnemonicProcessed(char charCode)
|
|
{
|
|
LayoutItemBase item = FindItemForMnemonic(_RootGroup, charCode);
|
|
if (item != null)
|
|
return item.ProcessMnemonic(charCode);
|
|
|
|
return false;
|
|
}
|
|
protected override bool ProcessMnemonic(char charCode)
|
|
{
|
|
if (this.Visible && _MnemonicsEnabled && IsMnemonicProcessed(charCode))
|
|
return true;
|
|
return base.ProcessMnemonic(charCode);
|
|
}
|
|
|
|
private bool _MnemonicsEnabled = true;
|
|
/// <summary>
|
|
/// Indicates whether accelerator keys assigned to item Text property are processed by items which respond to them.
|
|
/// </summary>
|
|
[DefaultValue(true), Category("Behavior"), Description("Indicates whether accelerator keys assigned to item Text property are processed by items which respond to them.")]
|
|
public bool MnemonicsEnabled
|
|
{
|
|
get { return _MnemonicsEnabled; }
|
|
set
|
|
{
|
|
if (value != _MnemonicsEnabled)
|
|
{
|
|
bool oldValue = _MnemonicsEnabled;
|
|
_MnemonicsEnabled = value;
|
|
OnMnemonicsEnabledChanged(oldValue, value);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when MnemonicsEnabled property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnMnemonicsEnabledChanged(bool oldValue, bool newValue)
|
|
{
|
|
//OnPropertyChanged(new PropertyChangedEventArgs("MnemonicsEnabled"));
|
|
}
|
|
|
|
private System.Drawing.Text.HotkeyPrefix _HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show;
|
|
/// <summary>
|
|
/// Indicates visibility of the hot-key prefixes, accelerator keys, that are set using ampersand in item Text.
|
|
/// </summary>
|
|
[DefaultValue(System.Drawing.Text.HotkeyPrefix.Show), Category("Behavior"), Description("Indicates visibility of the hot-key prefixes, accelerator keys, that are set using ampersand in item Text.")]
|
|
public System.Drawing.Text.HotkeyPrefix HotkeyPrefix
|
|
{
|
|
get { return _HotkeyPrefix; }
|
|
set
|
|
{
|
|
if (value != _HotkeyPrefix)
|
|
{
|
|
System.Drawing.Text.HotkeyPrefix oldValue = _HotkeyPrefix;
|
|
_HotkeyPrefix = value;
|
|
OnHotkeyPrefixChanged(oldValue, value);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when HotkeyPrefix property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnHotkeyPrefixChanged(System.Drawing.Text.HotkeyPrefix oldValue, System.Drawing.Text.HotkeyPrefix newValue)
|
|
{
|
|
this.Invalidate();
|
|
//OnPropertyChanged(new PropertyChangedEventArgs("HotkeyPrefix"));
|
|
|
|
}
|
|
private Size GetAutoScrollMinSize()
|
|
{
|
|
Rectangle clientRectangle = GetLayoutBounds();
|
|
Rectangle displayRect = _RootGroup.ActualBounds;
|
|
return new Size(Math.Abs(Math.Min(clientRectangle.Width - displayRect.Width, 0)),
|
|
Math.Abs(Math.Min(clientRectangle.Height - displayRect.Height, 0)));
|
|
}
|
|
private Point _ScrollPosition = new Point();
|
|
private void ScrollControls(Point scrollPosition)
|
|
{
|
|
ScrollControls(scrollPosition.X, scrollPosition.Y);
|
|
}
|
|
private void ScrollControls(int x, int y)
|
|
{
|
|
int xScroll = 0;
|
|
int yScroll = 0;
|
|
Rectangle clientRectangle = GetLayoutBounds();
|
|
if (_VScrollBar.Visible)
|
|
clientRectangle.Width -= _VScrollBar.Width;
|
|
if (_HScrollBar.Visible)
|
|
clientRectangle.Height -= _HScrollBar.Height;
|
|
|
|
Rectangle displayRect = _RootGroup.ActualBounds;
|
|
int maxXScroll = Math.Min(clientRectangle.Width - displayRect.Width, 0);
|
|
int maxYScroll = Math.Min(clientRectangle.Height - displayRect.Height, 0);
|
|
if (x > 0)
|
|
x = 0;
|
|
if (y > 0)
|
|
y = 0;
|
|
if (x < maxXScroll)
|
|
x = maxXScroll;
|
|
if (y < maxYScroll)
|
|
y = maxYScroll;
|
|
if (_ScrollPosition.X != x)
|
|
xScroll = x - displayRect.X;
|
|
if (_ScrollPosition.Y != y)
|
|
yScroll = y - displayRect.Y;
|
|
_ScrollPosition.X = x;
|
|
_ScrollPosition.Y = y;
|
|
|
|
bool useScrollWindowEx = !(_VScrollBar.Visible && _HScrollBar.Visible);
|
|
|
|
if ((xScroll != 0) || ((yScroll != 0) && this.IsHandleCreated))
|
|
{
|
|
DateTime start = DateTime.Now;
|
|
|
|
if (useScrollWindowEx)
|
|
{
|
|
_RootGroup.UpdateScrollBounds(xScroll, yScroll, false); // Move Items but not controls
|
|
Rectangle clipBounds = clientRectangle;
|
|
WinApi.RECT rectClip = WinApi.RECT.FromXYWH(clipBounds.X, clipBounds.Y, clipBounds.Width, clipBounds.Height);
|
|
WinApi.RECT prcUpdate = WinApi.RECT.FromXYWH(clipBounds.X, clipBounds.Y, clipBounds.Width, clipBounds.Height);
|
|
WinApi.RECT rectScroll = WinApi.RECT.FromXYWH(displayRect.X, displayRect.Y, displayRect.Width, displayRect.Height);
|
|
WinApi.ScrollWindowEx(new System.Runtime.InteropServices.HandleRef(this, this.Handle),
|
|
xScroll,
|
|
yScroll,
|
|
ref rectScroll,
|
|
ref rectClip,
|
|
IntPtr.Zero,
|
|
ref prcUpdate,
|
|
7);
|
|
if (_HScrollBar.Visible)
|
|
{
|
|
_HScrollBar.Location = new Point(this.ClientRectangle.X, this.ClientRectangle.Bottom - _HScrollBar.Height);
|
|
_HScrollBar.BringToFront();
|
|
_HScrollBar.Refresh();
|
|
}
|
|
if (_VScrollBar.Visible)
|
|
{
|
|
_VScrollBar.Location = new Point(this.ClientRectangle.Right - _VScrollBar.Width, this.ClientRectangle.Y);
|
|
_VScrollBar.BringToFront();
|
|
_VScrollBar.Refresh();
|
|
}
|
|
|
|
Type t = typeof(Control);
|
|
System.Reflection.MethodInfo mi = t.GetMethod("UpdateBounds", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, System.Type.DefaultBinder, new Type[0], new System.Reflection.ParameterModifier[0]);
|
|
if (mi != null)
|
|
{
|
|
for (int i = 0; i < base.Controls.Count; i++)
|
|
{
|
|
Control control = base.Controls[i];
|
|
if ((control != null) && control.IsHandleCreated && control != _VScrollBar && control != _HScrollBar)
|
|
{
|
|
mi.Invoke(control, null); //control.UpdateBounds();
|
|
}
|
|
}
|
|
}
|
|
this.Refresh();
|
|
}
|
|
else
|
|
{
|
|
WinApi.SendMessage(this.Handle, WinApi.WM_SETREDRAW, 0, 0);
|
|
_RootGroup.UpdateScrollBounds(xScroll, yScroll, true);
|
|
WinApi.SendMessage(this.Handle, WinApi.WM_SETREDRAW, 1, 0);
|
|
this.Refresh();
|
|
}
|
|
|
|
DateTime end = DateTime.Now;
|
|
//Console.WriteLine("ScrollTime:{0}", end.Subtract(start).TotalMilliseconds);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Padding property is not supported by LayoutControl.
|
|
/// </summary>
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)]
|
|
public new System.Windows.Forms.Padding Padding
|
|
{
|
|
get
|
|
{
|
|
return base.Padding;
|
|
}
|
|
set
|
|
{
|
|
}
|
|
}
|
|
|
|
private bool _AutoScaleLayout = true;
|
|
/// <summary>
|
|
/// Indicates whether layout control automatically scales the items if the parent Form performs scaling due to AutoScale settings.
|
|
/// </summary>
|
|
[DefaultValue(true), Category("Behavior"), Description("Indicates whether layout control automatically scales the items if the parent Form performs scaling due to AutoScale settings.")]
|
|
public bool AutoScaleLayout
|
|
{
|
|
get { return _AutoScaleLayout; }
|
|
set
|
|
{
|
|
_AutoScaleLayout = value;
|
|
}
|
|
}
|
|
|
|
|
|
protected virtual void ScaleItems(LayoutGroup group, SizeF factor)
|
|
{
|
|
foreach (LayoutItemBase item in group.Items)
|
|
{
|
|
item.ScaleItem(factor);
|
|
if (item is LayoutGroup)
|
|
ScaleItems((LayoutGroup)item, factor);
|
|
}
|
|
}
|
|
protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
|
|
{
|
|
//Console.WriteLine("ScaleControl factor={0} boundsSpecified={1}", factor, specified);
|
|
if (_AutoScaleLayout && (factor.Width != 1f || factor.Height != 1f))
|
|
{
|
|
this.SuspendLayout();
|
|
try
|
|
{
|
|
ScaleItems(_RootGroup, factor);
|
|
}
|
|
finally
|
|
{
|
|
ResumeLayout();
|
|
}
|
|
}
|
|
base.ScaleControl(factor, specified);
|
|
}
|
|
protected override void ScaleCore(float dx, float dy)
|
|
{
|
|
//Console.WriteLine("ScaleCore dx={0} dy={1}", dx, dy);
|
|
base.ScaleCore(dx, dy);
|
|
}
|
|
|
|
private SimpleStyle _FocusStyle = null;
|
|
/// <summary>
|
|
/// Indicates the focus style applied to the item which hosts an Control when that control contains input focus.
|
|
/// </summary>
|
|
[Category("Appearance"), Description("Indicates the focus style applied to the item which hosts an Control when that control contains input focus."), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
public SimpleStyle FocusStyle
|
|
{
|
|
get { return _FocusStyle; }
|
|
internal set
|
|
{
|
|
if (value != _FocusStyle)
|
|
{
|
|
SimpleStyle oldValue = _FocusStyle;
|
|
_FocusStyle = value;
|
|
OnFocusStyleChanged(oldValue, value);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when FocusStyle property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnFocusStyleChanged(SimpleStyle oldValue, SimpleStyle newValue)
|
|
{
|
|
if (oldValue != null)
|
|
oldValue.PropertyChanged -= FocusStylePropertyChanged;
|
|
if (newValue != null)
|
|
newValue.PropertyChanged += FocusStylePropertyChanged;
|
|
//OnPropertyChanged(new PropertyChangedEventArgs("FocusStyle"));
|
|
|
|
}
|
|
private void FocusStylePropertyChanged(object sender, PropertyChangedEventArgs e)
|
|
{
|
|
this.Invalidate();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the vertical scrollbar used by control.
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
public VScrollBarAdv VScrollBar
|
|
{
|
|
get
|
|
{
|
|
return _VScrollBar;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Gets the horizontal scrollbar used by the control.
|
|
/// </summary>
|
|
[Browsable(false)]
|
|
public DevComponents.DotNetBar.ScrollBar.HScrollBarAdv HScrollBar
|
|
{
|
|
get
|
|
{
|
|
return _HScrollBar;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Finds the item which is responsible for the control or returns null if there is no item that represents the control or control is not
|
|
/// contained by the layout control.
|
|
/// </summary>
|
|
/// <param name="c"></param>
|
|
/// <returns></returns>
|
|
public LayoutItemBase FindControlItem(Control c)
|
|
{
|
|
if (c == null || c.Parent != this) return null;
|
|
|
|
return FindControlItem(_RootGroup, c);
|
|
}
|
|
private LayoutItemBase FindControlItem(LayoutGroup group, Control c)
|
|
{
|
|
foreach (LayoutItemBase item in group.Items)
|
|
{
|
|
if (item is LayoutControlItem && ((LayoutControlItem)item).Control == c)
|
|
return item;
|
|
LayoutGroup childGroup = item as LayoutGroup;
|
|
if (childGroup != null)
|
|
{
|
|
LayoutItemBase childItem = FindControlItem(childGroup, c);
|
|
if (childItem != null) return childItem;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Finds the layout items which have controls assigned but controls are not parented by the layout control or one of its child controls.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public List<LayoutItemBase> FindOrphanedControlItems()
|
|
{
|
|
List<LayoutItemBase> list = new List<LayoutItemBase>();
|
|
FindOrphanedControlItems(list, _RootGroup);
|
|
return list;
|
|
}
|
|
|
|
private void FindOrphanedControlItems(List<LayoutItemBase> list, LayoutGroup group)
|
|
{
|
|
foreach (LayoutItemBase item in group.Items)
|
|
{
|
|
if (item is LayoutControlItem && !IsChildControl(((LayoutControlItem)item).Control))
|
|
list.Add(item);
|
|
else
|
|
{
|
|
LayoutGroup childGroup = item as LayoutGroup;
|
|
if (childGroup != null)
|
|
FindOrphanedControlItems(list, childGroup);
|
|
}
|
|
}
|
|
}
|
|
private bool IsChildControl(Control control)
|
|
{
|
|
if (control == null) return true;
|
|
do
|
|
{
|
|
if (control.Parent == this) return true;
|
|
control = control.Parent;
|
|
} while (control != null && control.Parent != null);
|
|
return false;
|
|
}
|
|
/// <summary>
|
|
/// Returns whether control is an system control used internally by LayoutControl.
|
|
/// </summary>
|
|
/// <param name="c"></param>
|
|
/// <returns></returns>
|
|
public bool IsSystemControl(Control c)
|
|
{
|
|
return c == _VScrollBar || c == _HScrollBar || c == _InsertMarker || c == _Thumb;
|
|
}
|
|
|
|
private bool _DisposeControlsOnRootGroupClear = true;
|
|
/// <summary>
|
|
/// Indicates whether controls associated with layout items are automatically disposed when RootGroup.Clear method is called. Default value is true.
|
|
/// </summary>
|
|
[DefaultValue(true), Category("Behavior"), Description("Indicates whether controls are automatically disposed when RootGroup.Clear method is called.")]
|
|
public bool DisposeControlsOnRootGroupClear
|
|
{
|
|
get { return _DisposeControlsOnRootGroupClear; }
|
|
set
|
|
{
|
|
_DisposeControlsOnRootGroupClear = value;
|
|
}
|
|
}
|
|
|
|
|
|
private LayoutItemBase _MouseOverItem = null;
|
|
protected override void OnMouseMove(MouseEventArgs e)
|
|
{
|
|
if (_MouseOverItem != null && _MouseOverItem.Bounds.Contains(e.Location))
|
|
{
|
|
_MouseOverItem.OnMouseMove(this, e);
|
|
}
|
|
else
|
|
{
|
|
LayoutItemBase item = HitTest(e.Location);
|
|
if (item != _MouseOverItem)
|
|
{
|
|
if (_MouseOverItem != null)
|
|
_MouseOverItem.OnMouseLeave(this, e);
|
|
_MouseOverItem = item;
|
|
|
|
if (_MouseOverItem != null)
|
|
{
|
|
_MouseOverItem.OnMouseEnter(this, e);
|
|
_MouseOverItem.OnMouseMove(this, e);
|
|
}
|
|
}
|
|
}
|
|
|
|
base.OnMouseMove(e);
|
|
}
|
|
protected override void OnMouseLeave(EventArgs e)
|
|
{
|
|
if (_MouseOverItem != null)
|
|
{
|
|
_MouseOverItem.OnMouseLeave(this, e);
|
|
_MouseOverItem = null;
|
|
}
|
|
base.OnMouseLeave(e);
|
|
}
|
|
protected override void OnMouseDown(MouseEventArgs e)
|
|
{
|
|
if (_MouseOverItem != null)
|
|
_MouseOverItem.OnMouseDown(this, e);
|
|
base.OnMouseDown(e);
|
|
}
|
|
protected override void OnMouseUp(MouseEventArgs e)
|
|
{
|
|
if (_MouseOverItem != null)
|
|
_MouseOverItem.OnMouseUp(this, e);
|
|
base.OnMouseUp(e);
|
|
}
|
|
protected override void OnClick(EventArgs e)
|
|
{
|
|
if (_MouseOverItem != null)
|
|
_MouseOverItem.OnClick(this, e);
|
|
base.OnClick(e);
|
|
}
|
|
protected override void OnMouseHover(EventArgs e)
|
|
{
|
|
if (_MouseOverItem != null)
|
|
_MouseOverItem.OnMouseHover(this, e);
|
|
base.OnMouseHover(e);
|
|
}
|
|
private bool _ShowToolTips = true;
|
|
/// <summary>
|
|
/// Gets or sets whether tooltips are shown when mouse is over the item when Tooltip property is set.
|
|
/// </summary>
|
|
[DefaultValue(true), Category("Behavior"), Description("Indicates whether tooltips are shown when mouse is over the item when Tooltip property is set.")]
|
|
public bool ShowToolTips
|
|
{
|
|
get { return _ShowToolTips; }
|
|
set
|
|
{
|
|
_ShowToolTips = value;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Gets the layout item at specified location.
|
|
/// </summary>
|
|
/// <param name="clientLoc">LayoutControl client coordinates to test.</param>
|
|
/// <returns>Layout item or null.</returns>
|
|
public LayoutItemBase HitTest(Point clientLoc)
|
|
{
|
|
return HitTest(_RootGroup, clientLoc);
|
|
}
|
|
|
|
private LayoutItemBase HitTest(LayoutGroup group, Point clientLoc)
|
|
{
|
|
foreach (LayoutItemBase item in group.Items)
|
|
{
|
|
LayoutGroup childGroup = item as LayoutGroup;
|
|
if (childGroup != null)
|
|
{
|
|
LayoutItemBase childItem = HitTest(childGroup, clientLoc);
|
|
if (childItem != null) return childItem;
|
|
}
|
|
if (item.Bounds.Contains(clientLoc))
|
|
return item;
|
|
}
|
|
return null;
|
|
}
|
|
private bool IsContainedBy(LayoutItemBase item, LayoutItemBase parent)
|
|
{
|
|
if (parent == null || item == null) return false;
|
|
do
|
|
{
|
|
if (item.Parent == parent)
|
|
return true;
|
|
item = item.Parent;
|
|
} while (item != null);
|
|
return false;
|
|
}
|
|
/// <summary>
|
|
/// Gets the HitTestInsertInfo structure that provides information on insertion point for an item based on the
|
|
/// specified client coordinates.
|
|
/// </summary>
|
|
/// <param name="clientLoc">Client coordinates to determine insert location for.</param>
|
|
/// <returns>Instance of HitTestInsertInfo or null if item cannot be placed.</returns>
|
|
public HitTestInsertInfo GetHitTestInsertInfo(LayoutItemBase insertItem, Point clientLoc)
|
|
{
|
|
HitTestInsertInfo insertInfo = new HitTestInsertInfo();
|
|
insertInfo.Parent = _RootGroup;
|
|
LayoutItemBase item = HitTestInsert(_RootGroup, clientLoc);
|
|
if (item != null)
|
|
{
|
|
if (IsContainedBy(item, insertItem) || insertItem.IsChildItem(item))
|
|
return new HitTestInsertInfo();
|
|
else if (item is LayoutGroup && item != _RootGroup && item != insertItem)
|
|
{
|
|
insertInfo.Parent = (LayoutGroup)item;
|
|
if (insertInfo.Parent.Items.Count == 0)
|
|
{
|
|
insertInfo.InsertIndex = 0;
|
|
insertInfo.InsertMarkerBounds = new Rectangle(item.Bounds.X, item.Bounds.Y, 1, item.Bounds.Height);
|
|
}
|
|
else
|
|
{
|
|
LayoutItemBase lastItem = insertInfo.Parent.Items[insertInfo.Parent.Items.Count - 1];
|
|
insertInfo.InsertIndex = insertInfo.Parent.Items.Count;
|
|
insertInfo.InsertMarkerBounds = new Rectangle(lastItem.Bounds.Right, lastItem.Bounds.Y, 1, lastItem.Bounds.Height);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
insertInfo.Parent = (LayoutGroup)item.Parent;
|
|
if (clientLoc.X < item.Bounds.X + item.Bounds.Width / 2)
|
|
{
|
|
insertInfo.InsertIndex = insertInfo.Parent.Items.IndexOf(item);
|
|
insertInfo.InsertMarkerBounds = new Rectangle(item.Bounds.X, item.Bounds.Y, 1, item.Bounds.Height);
|
|
}
|
|
else
|
|
{
|
|
insertInfo.InsertIndex = insertInfo.Parent.Items.IndexOf(item) + 1;
|
|
insertInfo.InsertMarkerBounds = new Rectangle(item.Bounds.Right, item.Bounds.Y, 1, item.Bounds.Height);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_RootGroup.Items.Count == 0)
|
|
insertInfo.InsertMarkerBounds = new Rectangle(_RootGroup.Bounds.X, _RootGroup.Bounds.Y, 1, insertItem.Bounds.Height);
|
|
else
|
|
{
|
|
insertInfo.InsertIndex = _RootGroup.Items.Count;
|
|
LayoutItemBase lastItem = _RootGroup.Items[_RootGroup.Items.Count - 1];
|
|
insertInfo.InsertMarkerBounds = new Rectangle(lastItem.Bounds.Right, lastItem.Bounds.Y, 1, lastItem.Bounds.Height);
|
|
}
|
|
}
|
|
|
|
return insertInfo;
|
|
}
|
|
/// <summary>
|
|
/// Returns item which contains specified client point or null.
|
|
/// </summary>
|
|
/// <param name="clientLoc">Client location to test.</param>
|
|
/// <returns></returns>
|
|
private LayoutItemBase HitTestInsert(LayoutGroup group, Point clientLoc)
|
|
{
|
|
LayoutItemBase relItem = null;
|
|
foreach (LayoutItemBase item in group.Items)
|
|
{
|
|
LayoutGroup childGroup = item as LayoutGroup;
|
|
|
|
if (childGroup != null)
|
|
{
|
|
relItem = HitTestInsert(childGroup, clientLoc);
|
|
if (relItem != null)
|
|
return relItem;
|
|
}
|
|
|
|
if (item.Bounds.Contains(clientLoc))
|
|
return item;
|
|
|
|
if (group.IsRootGroup && clientLoc.Y >= item.Bounds.Y && clientLoc.Y <= item.Bounds.Bottom)
|
|
{
|
|
if (item.Bounds.X < clientLoc.X || clientLoc.X > item.Bounds.Right)
|
|
relItem = item;
|
|
}
|
|
}
|
|
return relItem;
|
|
}
|
|
|
|
public void HideInsertMarker()
|
|
{
|
|
_InsertMarker.Visible = false;
|
|
}
|
|
public void ShowInsertMarker(Rectangle r)
|
|
{
|
|
if (r.Width < 6) r.Width = 6;
|
|
_InsertMarker.Bounds = r;
|
|
if (!_InsertMarker.Visible)
|
|
_InsertMarker.Visible = true;
|
|
_InsertMarker.BringToFront();
|
|
}
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public new Size AutoScrollMargin
|
|
{
|
|
get
|
|
{
|
|
return base.AutoScrollMargin;
|
|
}
|
|
set
|
|
{
|
|
}
|
|
}
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public new Size AutoScrollMinSize
|
|
{
|
|
get
|
|
{
|
|
return base.AutoScrollMinSize;
|
|
}
|
|
set { }
|
|
}
|
|
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public override bool AutoScroll
|
|
{
|
|
get
|
|
{
|
|
return base.AutoScroll;
|
|
}
|
|
set
|
|
{
|
|
//base.AutoScroll = value;
|
|
}
|
|
}
|
|
[Browsable(false)]
|
|
public override string Text
|
|
{
|
|
get
|
|
{
|
|
return base.Text;
|
|
}
|
|
set
|
|
{
|
|
base.Text = value;
|
|
}
|
|
}
|
|
|
|
protected override Size DefaultSize
|
|
{
|
|
get
|
|
{
|
|
return new Size(200, 200);
|
|
}
|
|
}
|
|
|
|
#region Touch Handling
|
|
private DevComponents.DotNetBar.Touch.TouchHandler _TouchHandler = null;
|
|
private bool _TouchEnabled = true;
|
|
/// <summary>
|
|
/// Indicates whether touch support for scrolling is enabled.
|
|
/// </summary>
|
|
[DefaultValue(true), Category("Behavior"), Description("Indicates whether touch support for scrolling is enabled.")]
|
|
public bool TouchEnabled
|
|
{
|
|
get { return _TouchEnabled; }
|
|
set
|
|
{
|
|
if (value != _TouchEnabled)
|
|
{
|
|
bool oldValue = _TouchEnabled;
|
|
_TouchEnabled = value;
|
|
OnTouchEnabledChanged(oldValue, value);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Called when TouchEnabled property has changed.
|
|
/// </summary>
|
|
/// <param name="oldValue">Old property value</param>
|
|
/// <param name="newValue">New property value</param>
|
|
protected virtual void OnTouchEnabledChanged(bool oldValue, bool newValue)
|
|
{
|
|
//OnPropertyChanged(new PropertyChangedEventArgs("TouchEnabled"));
|
|
}
|
|
private int TriggerPageChangeOffset
|
|
{
|
|
get
|
|
{
|
|
return 32;
|
|
}
|
|
}
|
|
private int MaximumReversePageOffset
|
|
{
|
|
get
|
|
{
|
|
return 0; //Math.Min(32, this.Width / 6);
|
|
}
|
|
}
|
|
private bool _TouchDrag = false;
|
|
private Point _TouchStartLocation = Point.Empty;
|
|
private Point _TouchStartScrollPosition = Point.Empty;
|
|
private Rectangle _TouchInnerBounds = Rectangle.Empty;
|
|
private void TouchHandlerPanBegin(object sender, DevComponents.DotNetBar.Touch.GestureEventArgs e)
|
|
{
|
|
if (_TouchEnabled)
|
|
{
|
|
_TouchInnerBounds = GetLayoutBounds();
|
|
_TouchStartLocation = e.Location;
|
|
_TouchStartScrollPosition = _ScrollPosition;
|
|
_TouchDrag = true;
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void TouchHandlerPanEnd(object sender, DevComponents.DotNetBar.Touch.GestureEventArgs e)
|
|
{
|
|
if (_TouchDrag)
|
|
{
|
|
EndTouchPan();
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void EndTouchPan()
|
|
{
|
|
_TouchDrag = false;
|
|
Point autoScrollPosition = _ScrollPosition;
|
|
Size autoScrollMinSize = GetAutoScrollMinSize();
|
|
if (autoScrollMinSize.Width > 0)
|
|
{
|
|
if (autoScrollMinSize.Width < -autoScrollPosition.X)
|
|
autoScrollPosition = new Point(autoScrollMinSize.Width, autoScrollPosition.Y);
|
|
else if (-autoScrollPosition.X < 0)
|
|
autoScrollPosition = new Point(0, autoScrollPosition.Y);
|
|
}
|
|
|
|
if (autoScrollMinSize.Height > 0)
|
|
{
|
|
if (autoScrollMinSize.Height < -autoScrollPosition.Y)
|
|
autoScrollPosition = new Point(autoScrollPosition.X, autoScrollMinSize.Height);
|
|
else if (-autoScrollPosition.Y < 0)
|
|
autoScrollPosition = new Point(autoScrollPosition.X, 0);
|
|
}
|
|
|
|
ScrollControls(autoScrollPosition);
|
|
UpdateScrollbarsFromScrollPosition();
|
|
}
|
|
|
|
private void TouchHandlerPan(object sender, DevComponents.DotNetBar.Touch.GestureEventArgs e)
|
|
{
|
|
if (_TouchDrag)
|
|
{
|
|
Point autoScrollPosition = _ScrollPosition;
|
|
Size autoScrollMinSize = GetAutoScrollMinSize();
|
|
int offset = (e.Location.X - _TouchStartLocation.X);
|
|
int offsetChange = offset + _TouchStartScrollPosition.X;
|
|
|
|
bool overflowH = false;
|
|
|
|
if (autoScrollMinSize.Width > 0)
|
|
{
|
|
if (-offsetChange + MaximumReversePageOffset > autoScrollMinSize.Width)
|
|
{
|
|
autoScrollPosition.X = -(autoScrollMinSize.Width + MaximumReversePageOffset);
|
|
overflowH = true;
|
|
}
|
|
else if (offsetChange > MaximumReversePageOffset)
|
|
{
|
|
autoScrollPosition.X = MaximumReversePageOffset;
|
|
overflowH = true;
|
|
}
|
|
else
|
|
autoScrollPosition.X = offsetChange;
|
|
}
|
|
|
|
// Y Scroll
|
|
bool overflowV = false;
|
|
if (autoScrollMinSize.Height > 0)
|
|
{
|
|
offset = (e.Location.Y - _TouchStartLocation.Y);
|
|
offsetChange = offset + _TouchStartScrollPosition.Y;
|
|
|
|
if (-offsetChange + MaximumReversePageOffset > autoScrollMinSize.Height)
|
|
{
|
|
autoScrollPosition.Y = -(autoScrollMinSize.Height + MaximumReversePageOffset);
|
|
overflowV = true;
|
|
}
|
|
else if (offsetChange > MaximumReversePageOffset)
|
|
{
|
|
autoScrollPosition.Y = MaximumReversePageOffset;
|
|
overflowV = true;
|
|
}
|
|
else
|
|
autoScrollPosition.Y = offsetChange;
|
|
}
|
|
|
|
if (_ScrollPosition != autoScrollPosition)
|
|
{
|
|
ScrollControls(autoScrollPosition);
|
|
Update();
|
|
}
|
|
if (overflowH && overflowV && e.IsInertia) EndTouchPan();
|
|
|
|
|
|
UpdateScrollbarsFromScrollPosition();
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void UpdateScrollbarsFromScrollPosition()
|
|
{
|
|
if (_VScrollBar != null && _VScrollBar.Visible && _VScrollBar.Value != -_ScrollPosition.Y)
|
|
_VScrollBar.Value = Math.Min(_VScrollBar.Maximum, Math.Max(0, -_ScrollPosition.Y));
|
|
if (_HScrollBar != null && _HScrollBar.Visible && _HScrollBar.Value != -_ScrollPosition.X)
|
|
_HScrollBar.Value = Math.Min(_HScrollBar.Maximum, Math.Max(0, -_ScrollPosition.X));
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
#region HitTestInsertInfo
|
|
public class HitTestInsertInfo
|
|
{
|
|
public LayoutGroup Parent = null;
|
|
public int InsertIndex = -1;
|
|
public Rectangle InsertMarkerBounds = Rectangle.Empty;
|
|
}
|
|
#endregion
|
|
|
|
#region EmptyLayoutManager
|
|
internal class EmptyLayoutManager : LayoutEngine
|
|
{
|
|
public override void InitLayout(object child, BoundsSpecified specified)
|
|
{
|
|
|
|
}
|
|
|
|
public override bool Layout(object container, LayoutEventArgs layoutEventArgs)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
#endregion
|
|
}
|