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 { /// /// Initializes a new instance of the LayoutControl class. /// 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(TouchHandlerPanBegin); _TouchHandler.Pan += new EventHandler(TouchHandlerPan); _TouchHandler.PanEnd += new EventHandler(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; } /// /// 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. /// /// New active style. [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); } /// /// Brings specified item that belongs to this LayoutControl into view by scrolling control if necessary. /// /// Item to bring into view. 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(); /// /// Gets the LayoutGroup for the control. LayoutGroup should not be changed. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Browsable(false)] public LayoutGroup RootGroup { get { return _RootGroup; } set { if (value != _RootGroup) { LayoutGroup oldValue = _RootGroup; _RootGroup = value; OnRootGroupChanged(oldValue, value); } } } /// /// Called when RootGroup property has changed. /// /// Old property value /// New property value 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; /// /// Indicates font used for the item labels. /// [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); } } } /// /// Called when LabelFont property has changed. /// /// Old property value /// New property value protected virtual void OnLabelFontChanged(Font oldValue, Font newValue) { //OnPropertyChanged(new PropertyChangedEventArgs("LabelFont")); this.PerformLayout(); this.Invalidate(); } private Color _LabelTextColor = Color.Empty; /// /// Gets or sets the color of the label text. /// [Category("Appearance"), Description("Indicates color of label text.")] public Color LabelTextColor { get { return _LabelTextColor; } set { _LabelTextColor = value; /*OnPropertyChanged("LabelTextColor");*/ this.Invalidate(); } } /// /// Gets whether property should be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeLabelTextColor() { return !_LabelTextColor.IsEmpty; } /// /// Resets property to its default value. /// [EditorBrowsable(EditorBrowsableState.Never)] public void ResetLabelTextColor() { this.LabelTextColor = Color.Empty; } private eTextAlignment _LabelTextAlignment = eTextAlignment.Default; /// /// Indicates the label text alignment within the text bounds. /// [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); } } } /// /// Called when LabelTextAlignment property has changed. /// /// Old property value /// New property value 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; } } /// /// Sets default property values for LayoutControlItem given the control assigned to it. /// /// Reference to LayoutControlItem 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; /// /// Indicates whether accelerator keys assigned to item Text property are processed by items which respond to them. /// [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); } } } /// /// Called when MnemonicsEnabled property has changed. /// /// Old property value /// New property value protected virtual void OnMnemonicsEnabledChanged(bool oldValue, bool newValue) { //OnPropertyChanged(new PropertyChangedEventArgs("MnemonicsEnabled")); } private System.Drawing.Text.HotkeyPrefix _HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.Show; /// /// Indicates visibility of the hot-key prefixes, accelerator keys, that are set using ampersand in item Text. /// [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); } } } /// /// Called when HotkeyPrefix property has changed. /// /// Old property value /// New property value 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); } } /// /// Padding property is not supported by LayoutControl. /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)] public new System.Windows.Forms.Padding Padding { get { return base.Padding; } set { } } private bool _AutoScaleLayout = true; /// /// Indicates whether layout control automatically scales the items if the parent Form performs scaling due to AutoScale settings. /// [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; /// /// Indicates the focus style applied to the item which hosts an Control when that control contains input focus. /// [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); } } } /// /// Called when FocusStyle property has changed. /// /// Old property value /// New property value 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(); } /// /// Gets the vertical scrollbar used by control. /// [Browsable(false)] public VScrollBarAdv VScrollBar { get { return _VScrollBar; } } /// /// Gets the horizontal scrollbar used by the control. /// [Browsable(false)] public DevComponents.DotNetBar.ScrollBar.HScrollBarAdv HScrollBar { get { return _HScrollBar; } } /// /// 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. /// /// /// 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; } /// /// Finds the layout items which have controls assigned but controls are not parented by the layout control or one of its child controls. /// /// public List FindOrphanedControlItems() { List list = new List(); FindOrphanedControlItems(list, _RootGroup); return list; } private void FindOrphanedControlItems(List 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; } /// /// Returns whether control is an system control used internally by LayoutControl. /// /// /// public bool IsSystemControl(Control c) { return c == _VScrollBar || c == _HScrollBar || c == _InsertMarker || c == _Thumb; } private bool _DisposeControlsOnRootGroupClear = true; /// /// Indicates whether controls associated with layout items are automatically disposed when RootGroup.Clear method is called. Default value is true. /// [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; /// /// Gets or sets whether tooltips are shown when mouse is over the item when Tooltip property is set. /// [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; } } /// /// Gets the layout item at specified location. /// /// LayoutControl client coordinates to test. /// Layout item or null. 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; } /// /// Gets the HitTestInsertInfo structure that provides information on insertion point for an item based on the /// specified client coordinates. /// /// Client coordinates to determine insert location for. /// Instance of HitTestInsertInfo or null if item cannot be placed. 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; } /// /// Returns item which contains specified client point or null. /// /// Client location to test. /// 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; /// /// Indicates whether touch support for scrolling is enabled. /// [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); } } } /// /// Called when TouchEnabled property has changed. /// /// Old property value /// New property value 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 }