using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Design; using System.Drawing.Drawing2D; using System.Windows.Forms; using DevComponents.Charts.TextMarkup; using DevComponents.DotNetBar.Charts.Style; namespace DevComponents.DotNetBar.Charts { /// /// Represents the collection of ChartContainer objects. /// [Editor("DevComponents.Charts.Design.ChartContainerCollectionEditor, DevComponents.Charts.Design, " + "Version=14.1.0.37, Culture=neutral, PublicKeyToken=90f470f34c89ccaf", typeof(UITypeEditor))] public class ChartContainerCollection : CustomNamedCollection { public ChartContainerCollection() { } #region GetUniqueName public string GetUniqueName() { return (GetUniqueName("ChartCont")); } #endregion } /// /// ChartContainer /// public class ChartContainer : ChartVisualElement, ILegendData, IScrollable, IComparable { #region Private variables private States _States; private string _EmptyText; private BodyElement _EmptyTextMarkup; private ChartLegend _Legend; private ChartTitleCollection _Titles; private ScrollBarLite _VScrollBar; private ScrollBarLite _HScrollBar; private int _VScrollBarWidth = 9; private int _HScrollBarHeight = 9; private Rectangle _FrameBounds; // Margin private Rectangle _ContentBounds; // Content - chart container(s) private Rectangle _ContentBoundsEx; // Content - extended content bounds private int _FillWeight = 100; private AutoSizeMode _AutoSizeMode = AutoSizeMode.NotSet; private Size _MinContentSize = new Size(100, 100); private Timer _AutoScrollTimer; private AutoScrollEnable _AutoScrollEnable; private Rectangle _ScrollRect; private bool _Panning; private int _HPanOffset; private int _VPanOffset; private ItemHitArea _HitArea; private ItemHitArea _MouseDownHitArea; private ContainerVisualStyles _ContainerVisualStyles; private EffectiveStyles _EffectiveContainerStyles; private int _MatrixDisplayOrder; private Rectangle _MatrixDisplayBounds; private int _SelectionUpdateCount = -1; #endregion public ChartContainer() { InitDefaultStates(); SetupScrollBars(); _EffectiveContainerStyles = new EffectiveStyles(this); } #region InitDefaultStates private void InitDefaultStates() { SetState(States.AutoGenSeriesCollection, true); SetState(States.EnablePanning, true); SetState(States.HScrollBarVisible, true); SetState(States.VScrollBarVisible, true); } #endregion #region Public properties #region AutoSizeMode /// /// Gets or sets the mode used to size the container (by FillWeight, etc). /// [DefaultValue(AutoSizeMode.NotSet), Category("Layout")] [Description("Indicates the mode used to size the container (by FillWeight, etc).")] public AutoSizeMode AutoSizeMode { get { return (_AutoSizeMode); } set { if (value != _AutoSizeMode) { _AutoSizeMode = value; OnPropertyChangedEx("AutoSizeMode", VisualChangeType.Layout); } } } #endregion #region ContainerVisualStyles /// /// Gets or sets the visual styles for the container. /// [Category("Style")] [Description("Indicates the visual styles for the container.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public ContainerVisualStyles ContainerVisualStyles { get { if (_ContainerVisualStyles == null) { _ContainerVisualStyles = new ContainerVisualStyles(); StyleVisualChangeHandler(null, _ContainerVisualStyles); } return (_ContainerVisualStyles); } set { if (_ContainerVisualStyles != value) { ContainerVisualStyles oldValue = _ContainerVisualStyles; _ContainerVisualStyles = value; OnStyleChanged("ContainerVisualStyles", oldValue, value); if (oldValue != null) oldValue.Dispose(); } } } #endregion #region ContentBounds /// /// Gets the Content area bounding rectangle. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Rectangle ContentBounds { get { return (_ContentBounds); } internal set { _ContentBounds = value; } } #endregion #region EffectiveContainerStyle /// /// Gets a reference to the container's effective (cached, composite) styles. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public EffectiveStyles EffectiveContainerStyles { get { return (_EffectiveContainerStyles); } } #endregion #region EmptyText /// /// Gets or sets the Text to display when the container is empty. /// [Browsable(true), Category("Appearance"), DefaultValue(null)] [Description("Indicates the Text to display when the container is empty.")] public string EmptyText { get { return (_EmptyText); } set { if (_EmptyText != value) { _EmptyText = value; EmptyTextMarkupChanged(); OnPropertyChangedEx("EmptyText", VisualChangeType.Render); } } } #endregion #region EnableEmptyTextMarkup /// /// Gets or sets whether EmptyText markup support is enabled. /// [DefaultValue(false), Category("Appearance")] [Description("Indicates whether EmptyText markup support is enabled.")] public bool EnableEmptyTextMarkup { get { return (TestState(States.EnableEmptyTextMarkup)); } set { if (EnableEmptyTextMarkup != value) { SetState(States.EnableEmptyTextMarkup, value); EmptyTextMarkupChanged(); OnPropertyChangedEx("EnableEmptyTextMarkup", VisualChangeType.Layout); } } } #region Markup support private void EmptyTextMarkupChanged() { _EmptyTextMarkup = null; if (EnableEmptyTextMarkup == true) { if (MarkupParser.IsMarkup(_EmptyText) == true) { _EmptyTextMarkup = MarkupParser.Parse(_EmptyText); if (_EmptyTextMarkup != null) _EmptyTextMarkup.HyperLinkClick += EmptyTextMarkupLinkClick; } } } /// /// Occurs when a text markup link is clicked /// protected virtual void EmptyTextMarkupLinkClick(object sender, EventArgs e) { HyperLink link = sender as HyperLink; ChartControl.DoEmptyTextMarkupLinkClickEvent(this, link); } /// /// Gets plain text without text-markup (if text-markup is used in EmptyText) /// [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public string EmptyTextPlainText { get { return (_EmptyTextMarkup != null ? _EmptyTextMarkup.PlainText : _EmptyText); } } #endregion #endregion #region EnablePanning /// /// Gets or sets whether the container can be panned with the mouse. /// [DefaultValue(true), Category("Behavior")] [Description("Indicates whether the container can be panned with the mouse.")] public bool EnablePanning { get { return (TestState(States.EnablePanning)); } set { if (value != EnablePanning) { SetState(States.EnablePanning, value); OnPropertyChanged("EnablePanning"); } } } #endregion #region EnableSelection /// /// Gets or sets whether the CONTAINER can be "selected" with the mouse. /// [DefaultValue(false), Category("Behavior")] [Description("Indicates whether the CONTAINER can be \"selected\" with the mouse.")] public bool EnableSelection { get { return (TestState(States.EnableSelection)); } set { if (value != EnableSelection) { SetState(States.EnableSelection, value); OnPropertyChanged("EnableSelection"); } } } #endregion #region FillWeight /// /// Gets or sets a value which, when AutoSizeMode is Fill, /// represents the width of the container relative to the widths /// of other fill-mode containers (default value is 100). /// [DefaultValue(100), Category("Layout")] [Description("Indicates a value which, when AutoSizeMode is Fill, represents the width of the containers relative to the widths of other fill-mode containers (default value is 100).")] public int FillWeight { get { return (_FillWeight); } set { if (value != _FillWeight) { _FillWeight = value; OnPropertyChangedEx("FillWeight", VisualChangeType.Layout); } } } #endregion #region FrameBounds /// /// Gets the Frame area bounding rectangle. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Rectangle FrameBounds { get { return (_FrameBounds); } internal set { _FrameBounds = value; } } #endregion #region HScrollBar /// /// Gets a reference to the containers’s horizontal scrollbar /// [Category("ScrollBar")] [Description("Indicates the container’s horizontal scrollbar.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public ScrollBarLite HScrollBar { get { return (_HScrollBar); } internal set { _HScrollBar = value; } } #endregion #region HScrollBarHeight /// /// Gets or sets the horizontal scrollBar height. /// [DefaultValue(9), Category("ScrollBar")] [Description("Indicates the horizontal scrollBar height")] public int HScrollBarHeight { get { return (_HScrollBarHeight); } set { if (value != _HScrollBarHeight) { if (value > 0) { _HScrollBarHeight = value; OnPropertyChangedEx("HScrollBarHeight", VisualChangeType.Layout); } } } } #endregion #region HScrollOffset /// /// Gets or sets the horizontal scrollbar offset. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int HScrollOffset { get { if (_HScrollBar != null && _HScrollBar.Visible == true) return (_HScrollBar.Value); return (0); } set { SetHScrollValue(value); } } #endregion #region HScrollBarVisible /// /// Gets or sets whether Horizontal Scrollbar is shown if needed (due to content of the control exceeding available width). /// [DefaultValue(true), Category("ScrollBar")] [Description("Indicates whether Horizontal Scrollbar is shown if needed (due to content of the control exceeding available width).")] public bool HScrollBarVisible { get { return (TestState(States.HScrollBarVisible)); } set { if (value != HScrollBarVisible) { SetState(States.HScrollBarVisible, value); InvalidateLayout(); } } } #endregion #region IsSelected /// /// Gets or sets whether the container is selected. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool IsSelected { get { ChartControl chartControl = ChartControl; if (chartControl != null) { if (_SelectionUpdateCount == chartControl.SelectionUpdateCount) return (TestState(States.IsSelected)); bool selected = chartControl.GetSelected(this); SetState(States.IsSelected, selected); _SelectionUpdateCount = chartControl.SelectionUpdateCount; } return (TestState(States.IsSelected)); } set { if (value != IsSelected) { SetState(States.IsSelected, value); ChartControl chartControl = ChartControl; if (chartControl != null) { chartControl.SetSelected(this, value); InvalidateRender(); } } } } #endregion #region Legend /// /// Gets or Sets the element Legend. /// [Category("Legend")] [Description("Indicates the element Legend.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public ChartLegend Legend { get { if (_Legend == null) Legend = new ChartLegend(); return (_Legend); } set { if (value != _Legend) { if (_Legend != null) { _Legend.Parent = null; _Legend.PropertyChanged -= LegendPropertyChanged; } _Legend = value; if (_Legend != null) { _Legend.Parent = this; _Legend.PropertyChanged += LegendPropertyChanged; } } } } void LegendPropertyChanged(object sender, PropertyChangedEventArgs e) { InvalidateLayout(); } #endregion #region MatrixAlignEndColumn /// /// Gets or sets whether the container's content ending X-offset is aligned /// with other containers ending in the same ChartMatrix column. /// [DefaultValue(false), Category("Matrix")] [Description("Indicates whether the container's content ending X-offset is aligned with other containers ending in the same ChartMatrix column.")] public bool MatrixAlignEndColumn { get { return (TestState(States.MatrixAlignEndColumn)); } set { if (value != MatrixAlignEndColumn) { SetState(States.MatrixAlignEndColumn, value); OnPropertyChangedEx("MatrixAlignEndColumn", VisualChangeType.Layout); } } } #endregion #region MatrixAlignEndRow /// /// Gets or sets whether the container's content ending Y-offset is aligned /// with other containers ending in the same ChartMatrix row. /// [DefaultValue(false), Category("Matrix")] [Description("Indicates whether the container's content ending Y-offset is aligned with other containers ending in the same ChartMatrix row.")] public bool MatrixAlignEndRow { get { return (TestState(States.MatrixAlignEndRow)); } set { if (value != MatrixAlignEndRow) { SetState(States.MatrixAlignEndRow, value); OnPropertyChangedEx("MatrixAlignEndRow", VisualChangeType.Layout); } } } #endregion #region MatrixAlignStartColumn /// /// Gets or sets whether the container's content starting X-offset is aligned /// with other containers starting in the same ChartMatrix column. /// [DefaultValue(false), Category("Matrix")] [Description("Indicates whether the container's content starting X-offset is aligned with other containers starting in the same ChartMatrix column.")] public bool MatrixAlignStartColumn { get { return (TestState(States.MatrixAlignStartColumn)); } set { if (value != MatrixAlignStartColumn) { SetState(States.MatrixAlignStartColumn, value); OnPropertyChangedEx("MatrixAlignStartColumn", VisualChangeType.Layout); } } } #endregion #region MatrixAlignStartRow /// /// Gets or sets whether the container's content starting Y-offset is aligned /// with other containers starting in the same ChartMatrix row. /// [DefaultValue(false), Category("Matrix")] [Description("Indicates whether the container's content starting Y-offset is aligned with other containers starting in the same ChartMatrix row.")] public bool MatrixAlignStartRow { get { return (TestState(States.MatrixAlignStartRow)); } set { if (value != MatrixAlignStartRow) { SetState(States.MatrixAlignStartRow, value); OnPropertyChangedEx("MatrixAlignStartRow", VisualChangeType.Layout); } } } #endregion #region MatrixDisplayBounds /// /// Gets or sets the containers matrix display bounds (in relative units of the matrix). /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Rectangle MatrixDisplayBounds { get { return (_MatrixDisplayBounds); } set { if (value != _MatrixDisplayBounds) { _MatrixDisplayBounds = value; OnPropertyChangedEx("MatrixDisplayBounds", VisualChangeType.Layout); } } } #endregion #region MatrixDisplayOrder /// /// Gets or sets the containers display order in the parent matrix layout /// (higher values are placed on top of lower values). /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int MatrixDisplayOrder { get { return (_MatrixDisplayOrder); } set { if (value != _MatrixDisplayOrder) { _MatrixDisplayOrder = value; OnPropertyChangedEx("MatrixDisplayOrder", VisualChangeType.Layout); } } } #endregion #region MinContentSize /// /// Gets or sets the minimum size of the content area of the chart. /// [Category("Layout")] [Description("Indicates the minimum size of the content area of the chart.")] public Size MinContentSize { get { return (_MinContentSize); } set { if (value != _MinContentSize) { _MinContentSize = value; OnPropertyChangedEx("MinContentSize", VisualChangeType.Layout); } } } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal virtual bool ShouldSerializeMinContentSize() { return (_MinContentSize.Width != 100 || _MinContentSize.Height != 100); } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] internal virtual void ResetMinContentSize() { MinContentSize = new Size(100, 100); } #endregion #region ScrollBounds /// /// Gets the Scrollable bounds. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual Rectangle ScrollBounds { get { return (_ContentBounds); } } #endregion #region ScrollBoundsEx /// /// Gets the extended Scrollable bounds. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual Rectangle ScrollBoundsEx { get { return (_ContentBoundsEx); } } #endregion #region ScrollBoundsOffset /// /// Gets the current scrollbar offset /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Point ScrollBoundsOffset { get { return (new Point(HScrollOffset, VScrollOffset)); } } #endregion #region Titles /// /// Gets or Sets a reference to the collection of Titles /// [Category("Appearance")] [Description("Indicates the collection of Titles.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public ChartTitleCollection Titles { get { if (_Titles == null) { _Titles = new ChartTitleCollection(); _Titles.CollectionChanged += TitlesCollectionChanged; } return (_Titles); } internal set { if (_Titles != null) _Titles.CollectionChanged -= TitlesCollectionChanged; _Titles = value; if (_Titles != null) _Titles.CollectionChanged += TitlesCollectionChanged; } } #region TitlesCollectionChanged void TitlesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { switch (e.Action) { case NotifyCollectionChangedAction.Add: foreach (ChartTitle title in e.NewItems) title.Parent = this; break; case NotifyCollectionChangedAction.Replace: foreach (ChartTitle title in e.OldItems) title.Parent = null; foreach (ChartTitle title in e.NewItems) title.Parent = this; break; case NotifyCollectionChangedAction.Remove: foreach (ChartTitle title in e.OldItems) title.Parent = null; break; } InvalidateLayout(); } #endregion #endregion #region VScrollBar /// /// Gets a reference to the container’s vertical scrollbar /// [Category("ScrollBar")] [Description("Indicates the container’s vertical scrollbar.")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public ScrollBarLite VScrollBar { get { return (_VScrollBar); } } #endregion #region VScrollBarWidth /// /// Gets or sets the vertical scrollBar width. /// [DefaultValue(9), Category("ScrollBar")] [Description("Indicates the vertical scrollBar width")] public int VScrollBarWidth { get { return (_VScrollBarWidth); } set { if (value != _VScrollBarWidth) { if (value > 0) { _VScrollBarWidth = value; OnPropertyChangedEx("VScrollBarWidth", VisualChangeType.Layout); } } } } #endregion #region VScrollOffset /// /// Gets the vertical scrollbar offset /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int VScrollOffset { get { if (_VScrollBar != null && _VScrollBar.Visible == true) return (_VScrollBar.Value); return (0); } set { SetVScrollValue(value); } } #endregion #region VScrollBarVisible /// /// Gets or sets whether Vertical Scrollbar is shown when needed (due to the content area exceeding available height). /// [DefaultValue(true), Category("ScrollBar")] [Description("Indicates whether Vertical Scrollbar is shown when needed (due to the content area exceeding available height)")] public bool VScrollBarVisible { get { return (TestState(States.VScrollBarVisible)); } set { if (value != VScrollBarVisible) { SetState(States.VScrollBarVisible, value); InvalidateLayout(); } } } #endregion #endregion #region Internal properties #region ContentBoundsEx internal Rectangle ContentBoundsEx { get { return (_ContentBoundsEx); } set { _ContentBoundsEx = value; } } #endregion #region EmptyTextMarkup internal BodyElement EmptyTextMarkup { get { return (_EmptyTextMarkup); } set { _EmptyTextMarkup = value; } } #endregion #region HitArea internal ItemHitArea HitArea { get { return (_HitArea); } set { _HitArea = value; } } #endregion #region IsSubPanel /// /// Gets whether the ChartPanel is a subordinate / nested panel. /// internal bool IsSubPanel { get { return (Parent != null); } } #endregion #region MatrixColumnAligned /// /// Gets whether the ChartContainer column was MatrixAligned. /// internal bool MatrixColumnAligned { get { return (TestState(States.MatrixColumnAligned)); } set { SetState(States.MatrixColumnAligned, value); } } #endregion #region MatrixRowAligned /// /// Gets whether the ChartContainer row was MatrixAligned. /// internal bool MatrixRowAligned { get { return (TestState(States.MatrixRowAligned)); } set { SetState(States.MatrixRowAligned, value); } } #endregion #region MouseDownHitArea internal ItemHitArea MouseDownHitArea { get { return (_MouseDownHitArea); } set { _MouseDownHitArea = value; } } #endregion #endregion #region MeasureOverride protected override void MeasureOverride(ChartLayoutInfo layoutInfo) { if (Legend.Visible == true) Legend.Measure(layoutInfo); foreach (ChartTitle title in Titles) { if (title.Visible == true) title.Measure(layoutInfo); } } #endregion #region ArrangeOverride protected override void ArrangeOverride(ChartLayoutInfo layoutInfo) { if (Legend.Visible == true) Legend.Arrange(layoutInfo); foreach (ChartTitle title in Titles) { if (title.Visible == true) title.Arrange(layoutInfo); } UpdateScrollBars(layoutInfo); } #endregion #region RenderOverride protected override void RenderOverride(ChartRenderInfo renderInfo) { Graphics g = renderInfo.Graphics; // Render Titles foreach (ChartTitle title in Titles) { if (title.Visible == true) title.Render(renderInfo); } // Render the Legend if (Legend.Visible == true) Legend.Render(renderInfo); } #endregion #region RenderTextMarkup internal void RenderTextMarkup(Graphics g, Font font, Color textColor, Alignment alignment, Rectangle r) { if (textColor.IsEmpty) textColor = Color.Black; MarkupDrawContext d = new MarkupDrawContext(g, font, textColor, false); _EmptyTextMarkup.Arrange(new Rectangle(Point.Empty, r.Size), d); Size size = _EmptyTextMarkup.Bounds.Size; switch (alignment) { case Alignment.NotSet: case Alignment.MiddleLeft: case Alignment.MiddleCenter: case Alignment.MiddleRight: if (r.Height > size.Height) r.Y += (r.Height - size.Height) / 2; break; case Alignment.BottomLeft: case Alignment.BottomCenter: case Alignment.BottomRight: if (r.Height > size.Height) r.Y = r.Bottom - size.Height; break; } _EmptyTextMarkup.Bounds = new Rectangle(r.Location, size); Region oldClip = g.Clip; try { g.SetClip(r, CombineMode.Intersect); _EmptyTextMarkup.Render(d); } finally { g.Clip = oldClip; } } #endregion #region RenderEmptyText protected void RenderEmptyText( Graphics g, ContainerVisualStyle style, Rectangle bounds) { if (String.IsNullOrEmpty(EmptyText) == false) { if (EmptyTextMarkup != null) { RenderTextMarkup(g, style.Font, style.TextColor, style.Alignment, bounds); } else { eTextFormat tf = style.GetTextFormatFlags(); TextDrawing.DrawString(g, EmptyText, style.Font, style.TextColor, bounds, tf); } } } #endregion #region RenderScrollbars protected void RenderScrollbars(ChartRenderInfo renderInfo) { Graphics g = renderInfo.Graphics; if (HScrollBar.Visible == true && VScrollBar.Visible == true) { ScrollBarVisualStyle style = VScrollBar.GetEffectiveStyle(); Rectangle r = HScrollBar.Bounds; r.X = VScrollBar.Bounds.X; r.Width = VScrollBar.Width; using (Brush br = style.TrackBackground.GetBrush(r)) g.FillRectangle(br, r); using (Pen pen = new Pen(style.BorderColor)) g.DrawRectangle(pen, r); } if (HScrollBar.Visible == true) HScrollBar.Render(renderInfo); if (VScrollBar.Visible == true) VScrollBar.Render(renderInfo); } #endregion #region Mouse handling #region OnMouseEnter protected override bool OnMouseEnter(EventArgs e) { base.OnMouseEnter(e); InvalidateRender(); return (true); } #endregion #region OnMouseLeave protected override bool OnMouseLeave(EventArgs e) { base.OnMouseLeave(e); InvalidateRender(); return (true); } #endregion #region OnMouseMove protected override bool OnMouseMove(MouseEventArgs e) { _HitArea = GetHitArea(e.Location); if (IsMouseDown == true) return (OnMouseDownMove(e)); if (_HitArea == ItemHitArea.InContent) { if (EmptyTextMarkup != null) { ChartControl.SetChartCursor = true; EmptyTextMarkup.MouseMove(ChartControl, e); ChartControl.SetChartCursor = false; if (EmptyTextMarkup.MouseOverElement != null) { if (EmptyTextMarkup.MouseOverElement is HyperLink) return (true); } } if (EnablePanning == true && (HScrollBar.Enabled == true || VScrollBar.Enabled == true)) { ChartCursor = OpenHandCursor; return (true); } } ChartCursor = Cursors.Default; return (false); } #region OnMouseDownMove private bool OnMouseDownMove(MouseEventArgs e) { if (_Panning == true) { ChartCursor = ClosedHandCursor; if (HScrollBar.Enabled == true) HScrollOffset = _HPanOffset + (MouseDownPoint.X - e.Location.X); if (VScrollBar.Enabled == true) { int n = (MouseDownPoint.Y - e.Location.Y); if (VScrollBar.Inverted == true) VScrollOffset = _VPanOffset - n; else VScrollOffset = _VPanOffset + n; } } return (true); } #endregion #endregion #region OnMouseDown protected override bool OnMouseDown(MouseEventArgs e) { ChartControl.Focus(); UpdateSelection(e); return (OnMouseDownEx(e)); } protected override bool OnMouseDownEx(MouseEventArgs e) { base.OnMouseDown(e); MouseDownHitArea = _HitArea; if (EmptyTextMarkup != null) { if (EmptyTextMarkup.MouseOverElement != null) { EmptyTextMarkup.MouseDown(ChartControl, e); return (true); } } if (_HitArea == ItemHitArea.InContent) { if (EnablePanning == true && (HScrollBar.Visible == true || VScrollBar.Visible == true)) { _HPanOffset = HScrollOffset; _VPanOffset = VScrollOffset; _Panning = true; ChartCursor = ClosedHandCursor; ChartControl.PostInternalMouseMove(); ChartControl.CapturedItem = this; return (true); } } return (false); } #region UpdateSelection private void UpdateSelection(MouseEventArgs e) { ChartContainer parent = Parent as ChartContainer; if (parent != null && parent.EnableSelection == true) { if (IsSelected == false || ((e.Button & MouseButtons.Left) == MouseButtons.Left)) { ChartControl chartControl = ChartControl; if (chartControl != null) { bool ctrlKey = ((Control.ModifierKeys & Keys.Control) == Keys.Control); if (ctrlKey == true) { chartControl.SetSelected(this, !IsSelected); } else { chartControl.ClearAllSelected(); chartControl.SetSelected(this, true); } } } } } #endregion #endregion #region OnMouseUp protected override bool OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (EmptyTextMarkup != null) { if (EmptyTextMarkup.MouseOverElement != null) EmptyTextMarkup.Click(ChartControl); } if (_Panning == true) { _Panning = false; ChartControl.CapturedItem = null; } return (true); } #endregion #region OnMouseWheel protected override bool OnMouseWheel(MouseEventArgs e) { if ((Control.ModifierKeys & Keys.Shift) == Keys.Shift) return (OnHorizontalMouseWheel(e)); return (OnVerticalMouseWheel(e)); } #region OnHorizontalMouseWheel private bool OnHorizontalMouseWheel(MouseEventArgs e) { if (HScrollBar.Enabled == true) { if ((e.Delta < 0 && HScrollBar.IsAtMaxumum == false) || (e.Delta > 0 && HScrollBar.IsAtMinumum == false)) { SetHWheelValue(-e.Delta); return (true); } } return (false); } #region SetHWheelValue private void SetHWheelValue(int delta) { int value = delta * SystemInformation.MouseWheelScrollLines / 120; value *= HScrollBar.SmallChange; value += HScrollBar.Value; SetHScrollValue(value); } #endregion #endregion #region OnVerticalMouseWheel private bool OnVerticalMouseWheel(MouseEventArgs e) { if (VScrollBar.Enabled == true) { if (VScrollBar.Inverted == true) { if ((e.Delta < 0 && VScrollBar.IsAtMinumum == false) || (e.Delta > 0 && VScrollBar.IsAtMaxumum == false)) { SetVWheelValue(e.Delta); return (true); } } else { if ((e.Delta < 0 && VScrollBar.IsAtMaxumum == false) || (e.Delta > 0 && VScrollBar.IsAtMinumum == false)) { SetVWheelValue(-e.Delta); return (true); } } } return (false); } #region SetVWheelValue private void SetVWheelValue(int delta) { int value = delta * SystemInformation.MouseWheelScrollLines / 120; value *= VScrollBar.SmallChange; value += VScrollBar.Value; SetVScrollValue(value); } #endregion #endregion #endregion #endregion #region Scrollbar support #region SetupScrollBars private void SetupScrollBars() { _VScrollBar = new VScrollBarLite(); _VScrollBar.Parent = this; _VScrollBar.Width = Dpi.Width(VScrollBarWidth); _HScrollBar = new HScrollBarLite(); _HScrollBar.Parent = this; _HScrollBar.Height = Dpi.Height(HScrollBarHeight); _HScrollBar.Visible = false; _VScrollBar.Visible = false; } #endregion #region UpdateScrollBars private void UpdateScrollBars(ChartLayoutInfo layoutInfo) { Rectangle cbounds = ScrollBounds; Rectangle cboundsEx = ScrollBoundsEx; EnableHScrollBar(cbounds, cboundsEx); EnableVScrollBar(cbounds, cboundsEx); if (_HScrollBar.Enabled == true) { int widthEx = cboundsEx.Width; _HScrollBar.SmallChange = cbounds.Width / 20; _HScrollBar.Maximum = Math.Max(0, widthEx); _HScrollBar.LargeChange = Math.Min(cbounds.Width, _HScrollBar.Maximum); if (_HScrollBar.Value + _HScrollBar.LargeChange > _HScrollBar.Maximum) _HScrollBar.Value = _HScrollBar.Maximum - _HScrollBar.LargeChange; _HScrollBar.Arrange(layoutInfo); } if (_VScrollBar.Enabled == true) { int heightEx = cboundsEx.Height; _VScrollBar.SmallChange = cbounds.Height / 20; _VScrollBar.Maximum = Math.Max(0, heightEx); _VScrollBar.LargeChange = Math.Min(cbounds.Height, _VScrollBar.Maximum); if (_VScrollBar.Value + _VScrollBar.LargeChange > _VScrollBar.Maximum) _VScrollBar.Value = _VScrollBar.Maximum - _VScrollBar.LargeChange; _VScrollBar.Arrange(layoutInfo); } } #region EnableHScrollBar private void EnableHScrollBar(Rectangle cbounds, Rectangle cboundsEx) { bool enable = (HScrollBarVisible == true) && (cboundsEx.Width > cbounds.Width); if ((cbounds.Height < _HScrollBar.Height + 4) || cbounds.Width <= 0) enable = false; if (enable == true) { _HScrollBar.Location = new Point(cbounds.Left, cbounds.Bottom - _HScrollBar.Height - 1); int n = cbounds.Width - 1; if (_VScrollBar.Visible == true) n -= _VScrollBar.Width; _HScrollBar.Width = n; _HScrollBar.Height = Dpi.Height(HScrollBarHeight); } else { _HScrollBar.Value = 0; } _HScrollBar.Enabled = enable; _HScrollBar.Visible = enable; } #endregion #region EnableVScrollBar private void EnableVScrollBar(Rectangle cbounds, Rectangle cboundsEx) { bool enable = (VScrollBarVisible == true) && (cboundsEx.Height > cbounds.Height); if (cbounds.Height <= 0 || (cbounds.Width < _VScrollBar.Width + 4)) enable = false; if (enable == true) { _VScrollBar.Location = new Point(cbounds.Right - _VScrollBar.Width - 1, cbounds.Top); _VScrollBar.Height = cbounds.Height - 1; if (_HScrollBar.Visible == true) _VScrollBar.Height -= _HScrollBar.Height; _VScrollBar.Width = Dpi.Width(VScrollBarWidth); } else { _VScrollBar.Value = 0; } _VScrollBar.Enabled = enable; _VScrollBar.Visible = enable; } #endregion #endregion #region SetVScrollValue internal void SetVScrollValue(int value) { if (_VScrollBar.Visible == true) { int oldValue = _VScrollBar.Value; value = Math.Max(value, 0); value = Math.Min(value, _VScrollBar.Maximum); _VScrollBar.Value = value; } } #endregion #region SetHScrollValue internal void SetHScrollValue(int value) { if (_HScrollBar.Visible == true) { int oldValue = _HScrollBar.Value; value = Math.Max(value, 0); value = Math.Min(value, _HScrollBar.Maximum); _HScrollBar.Value = value; } } #endregion #region AutoScrolling support #region EnableAutoScrolling internal void EnableAutoScrolling( AutoScrollEnable enable, Rectangle scrollRect) { if (ChartControl.Focused == true) { _AutoScrollEnable = enable; if ((_HScrollBar != null && _HScrollBar.Visible == true) || (_VScrollBar != null && _VScrollBar.Visible == true)) { _ScrollRect = scrollRect; if (_AutoScrollTimer == null) { _AutoScrollTimer = new Timer(); _AutoScrollTimer.Interval = 10; _AutoScrollTimer.Tick += AutoScrollTimerTick; _AutoScrollTimer.Start(); } } } } #endregion #region DisableAutoScrolling internal void DisableAutoScrolling() { if (_AutoScrollTimer != null) { _AutoScrollTimer.Stop(); _AutoScrollTimer.Tick -= AutoScrollTimerTick; _AutoScrollTimer = null; } } #endregion #region AutoScrollTimerTick private void AutoScrollTimerTick(object sender, EventArgs e) { Point pt = ChartControl.PointToClient(Cursor.Position); Rectangle t = _ScrollRect; if ((_AutoScrollEnable & AutoScrollEnable.Horizontal) == AutoScrollEnable.Horizontal && (_HScrollBar != null && _HScrollBar.Visible == true)) { int dx = (pt.X < t.X) ? ScrollAmount(pt.X - t.X) : (pt.X >= t.Right) ? ScrollAmount(pt.X - t.Right) : 0; SetHScrollValue(_HScrollBar.Value + dx); } if ((_AutoScrollEnable & AutoScrollEnable.Vertical) == AutoScrollEnable.Vertical && (_VScrollBar != null && _VScrollBar.Visible == true)) { int dy = (pt.Y < t.Top) ? ScrollAmount(pt.Y - t.Top) : (pt.Y >= t.Bottom) ? ScrollAmount(pt.Y - t.Bottom) : 0; SetVScrollValue(_VScrollBar.Value + dy); } } #endregion #region ScrollAmount private int ScrollAmount(int delta) { int n = Math.Abs(delta); int amt = 1 << ((n / 16) + 1); return (delta < 0 ? -amt : amt); } #endregion #endregion #endregion #region EnsureVisible /// /// Ensures the container is visible on screen, and optionally /// centered (if possible). /// /// public virtual void EnsureVisible(bool center) { ChartContainer parent = Parent as ChartContainer; if (parent != null) parent.EnsureVisible(this, center); } /// /// Ensures that the given container "item" is visible /// on screen, and optionally centered (if possible). /// /// public virtual void EnsureVisible(ChartContainer item, bool center) { Rectangle bounds = ContentBounds; bounds.X += HScrollOffset; if (VScrollBar.Inverted == true) bounds.Y -= VScrollOffset; else bounds.Y += VScrollOffset; if (HScrollBar.Enabled == true) bounds.Width -= VScrollBar.Width; if (VScrollBar.Enabled == true) bounds.Height -= HScrollBar.Height; bounds.Width -= Dpi.Width4; bounds.Height -= Dpi.Height4; Rectangle ibounds = item.FrameBounds; if (bounds.Contains(ibounds) == false) { if (HScrollBar.Enabled == true) { if (center == true) { int x = (bounds.X + bounds.Right) / 2 - (ibounds.Width / 2); SetHScrollValue(ibounds.X - x); } else { int x = ibounds.X; if (ibounds.Right > bounds.Right) x -= (ibounds.Right - bounds.Right); if (x < bounds.X) x = bounds.X; SetHScrollValue(HScrollOffset + (ibounds.X - x)); } } if (VScrollBar.Enabled == true) { if (center == true) { int y = (bounds.Y + bounds.Bottom) / 2; y -= (ibounds.Height / 2); SetVScrollValue(ibounds.Y - y); } else { int y = ibounds.Y; if (ibounds.Bottom > bounds.Bottom) y -= (ibounds.Bottom - bounds.Bottom); if (y < bounds.Y) y = bounds.Y; SetVScrollValue(VScrollOffset + (ibounds.Y - y)); } } } ChartContainer parent = Parent as ChartContainer; if (parent != null) parent.EnsureVisible(this, center); } #endregion #region GetDisplayBounds /// /// Gets the "displayBounds" of the given rectangle (scroll /// adjusted bounds). /// /// /// public Rectangle GetDisplayBounds(Rectangle bounds) { bounds.X -= HScrollOffset; if (VScrollBar.Inverted == true) bounds.Y += VScrollOffset; else bounds.Y -= VScrollOffset; return (bounds); } #endregion #region GetElementAt /// /// Gets the element at the given Point. /// /// /// public override ChartVisualElement GetElementAt(Point pt) { if (InScrollBar(HScrollBar, pt)) return (HScrollBar); if (InScrollBar(VScrollBar, pt)) return (VScrollBar); foreach (ChartTitle title in Titles) { if (title.Visible == true) { if (title.Bounds.Contains(pt)) return (title); } } if (Legend.Visible == true) { if (Legend.FrameBounds.Contains(pt)) { ChartVisualElement item = Legend.GetElementAt(pt); return (item ?? Legend); } } return (null); } #region InScrollBar private bool InScrollBar(ScrollBarLite scrollBar, Point pt) { if (scrollBar != null && scrollBar.Visible == true) { if (scrollBar.Bounds.Contains(pt)) return (true); } return (false); } #endregion #endregion #region GetHitArea /// /// Gets the HitArea for the given Point. /// /// /// public override ItemHitArea GetHitArea(Point pt) { Rectangle contentBounds = GetScrollBounds(ContentBounds); if (contentBounds.Contains(pt)) return (ItemHitArea.InContent); Rectangle frameBounds = GetScrollBounds(FrameBounds); if (frameBounds.Contains(pt)) return (ItemHitArea.InFrame); return (ItemHitArea.None); } #endregion #region GetTitleByName /// /// Gets the defined Title with the given name. /// /// /// ChartTitle or null public ChartTitle GetTitleByName(string name) { return (Titles[name]); } #endregion #region Style Support #region GetEffectiveContainerStyle internal ContainerVisualStyle GetEffectiveContainerStyle() { StyleState state = GetStyleState(); return (EffectiveContainerStyles[state]); } #endregion #region GetStyleState private StyleState GetStyleState() { StyleState state = StyleState.Default; if (IsMouseOver == true) state |= StyleState.MouseOver; if (IsSelected == true) state |= StyleState.Selected; return (state); } #endregion #region ApplyStyles public override void ApplyStyles(BaseVisualStyle style, StyleType cs) { base.ApplyStyles(style); ContainerVisualStyle cstyle = style as ContainerVisualStyle; if (cstyle != null) { ApplyParentStyles(cstyle, Parent as ChartContainer, cs); cstyle.ApplyStyle(ContainerVisualStyles[cs]); } } #region ApplyParentStyles (ChartContainerVisualStyles) private void ApplyParentStyles( ContainerVisualStyle cstyle, ChartContainer item, StyleType cs) { if (item != null) { ApplyParentStyles(cstyle, item.Parent as ChartContainer, cs); ChartPanel panel = item as ChartPanel; if (panel != null) { if (panel.DefaultVisualStyles.ContainerVisualStyles != null) cstyle.ApplyStyle(panel.DefaultVisualStyles.ContainerVisualStyles[cs]); } } else { ChartControl chartControl = ChartControl; if (chartControl.BaseVisualStyles.ContainerVisualStyles != null) cstyle.ApplyStyle(chartControl.BaseVisualStyles.ContainerVisualStyles[cs]); if (chartControl.DefaultVisualStyles.ContainerVisualStyles != null) cstyle.ApplyStyle(chartControl.DefaultVisualStyles.ContainerVisualStyles[cs]); } } #endregion #endregion #region ApplyDefaults public override void ApplyDefaults(BaseVisualStyle style, StyleType cs) { ContainerVisualStyle cstyle = style as ContainerVisualStyle; if (cstyle != null) { if (cstyle.BorderPattern == null) cstyle.BorderPattern = new BorderPattern(LinePattern.Solid); if (cstyle.DropShadow.Enabled == Tbool.NotSet) cstyle.DropShadow.Enabled = Tbool.False; } base.ApplyDefaults(style, cs); } #endregion #region InvalidateStyle /// ///Invalidate the cached Style /// public void InvalidateStyle() { ClearEffectiveStyles(); } #endregion #region ClearEffectiveStyles protected override void ClearEffectiveStyles() { _EffectiveContainerStyles.InvalidateStyles(); if (_VScrollBar != null) _VScrollBar.InvalidateStyle(); if (_HScrollBar != null) _HScrollBar.InvalidateStyle(); } #endregion #endregion #region ILegendData #region GetLegendItems public virtual List GetLegendData() { return (null); } #endregion #endregion #region CompareTo public int CompareTo(object obj) { ChartContainer cobj = obj as ChartContainer; if (cobj != null) { if (this.Equals(cobj) == true) return (0); } return (-1); } #endregion #region Copy/CopyTo public override ChartVisualElement Copy() { ChartContainer copy = new ChartContainer(); CopyTo(copy); return (copy); } public override void CopyTo(ChartVisualElement copy) { ChartContainer c = copy as ChartContainer; if (c != null) { base.CopyTo(c); c.AutoSizeMode = AutoSizeMode; c.ContainerVisualStyles = (_ContainerVisualStyles != null) ? ContainerVisualStyles.Copy() : null; c.EmptyText = EmptyText; c.EnableEmptyTextMarkup = EnableEmptyTextMarkup; c.EnablePanning = EnablePanning; c.EnableSelection = EnableSelection; c.FillWeight = FillWeight; c.HScrollBarHeight = HScrollBarHeight; c.HScrollBarVisible = HScrollBarVisible; c.Legend = (_Legend != null) ? (ChartLegend)Legend.Copy() : null; c.MatrixAlignEndColumn = MatrixAlignEndColumn; c.MatrixAlignEndRow = MatrixAlignEndRow; c.MatrixAlignStartColumn = MatrixAlignStartColumn; c.MatrixAlignStartRow = MatrixAlignStartRow; c.MatrixDisplayBounds = MatrixDisplayBounds; c.MatrixDisplayOrder = MatrixDisplayOrder; c.MinContentSize = MinContentSize; c.Titles.Clear(); foreach (ChartTitle title in Titles) c.Titles.Add((ChartTitle)title.Copy()); c.VScrollBarWidth = VScrollBarWidth; c.VScrollBarVisible = VScrollBarVisible; } } #endregion #region GetSerialData internal override SerialElementCollection GetSerialData(string serialName) { SerialElementCollection sec = new SerialElementCollection(); if (serialName != null) { if (serialName.Equals("") == true) serialName = "ChartContainer"; sec.AddStartElement(serialName); } sec.AddValue("AutoSizeMode", AutoSizeMode, AutoSizeMode.NotSet); if (_ContainerVisualStyles != null && _ContainerVisualStyles.IsEmpty == false) sec.AddElement(_ContainerVisualStyles.GetSerialData("ContainerVisualStyles")); sec.AddValue("EmptyText", EmptyText, null); sec.AddValue("EnableEmptyTextMarkup", EnableEmptyTextMarkup, false); sec.AddValue("EnablePanning", EnablePanning, true); sec.AddValue("EnableSelection", EnableSelection, false); sec.AddValue("FillWeight", FillWeight, 100); sec.AddValue("HScrollBarHeight", HScrollBarHeight, 9); sec.AddValue("HScrollBarVisible", HScrollBarVisible, true); if (_HScrollBar != null) sec.AddElement(_HScrollBar.GetSerialData("HScrollBar")); if (_Legend != null) sec.AddElement(_Legend.GetSerialData("Legend")); sec.AddValue("MatrixAlignEndColumn", MatrixAlignEndColumn, false); sec.AddValue("MatrixAlignEndRow", MatrixAlignEndRow, false); sec.AddValue("MatrixAlignStartColumn", MatrixAlignStartColumn, false); sec.AddValue("MatrixAlignStartRow", MatrixAlignStartRow, false); ChartPanel panel = Parent as ChartPanel; if (panel == null || panel.AutoFillChartMatrix == false) { if (_MatrixDisplayBounds.IsEmpty == false) sec.AddValue("MatrixDisplayBounds", MatrixDisplayBounds); } sec.AddValue("MatrixDisplayOrder", MatrixDisplayOrder, 0); sec.AddValue("MinContentSize", MinContentSize, new Size(100,100)); if (_Titles != null && _Titles.Count > 0) { sec.AddStartElement("Titles count=\"" + _Titles.Count + "\""); foreach (ChartTitle title in _Titles) sec.AddElement(title.GetSerialData("")); sec.AddEndElement("Titles"); } if (_VScrollBar != null) sec.AddElement(_VScrollBar.GetSerialData("VScrollBar")); sec.AddValue("VScrollBarWidth", VScrollBarWidth, 9); sec.AddValue("VScrollBarVisible", VScrollBarVisible, true); sec.AddElement(base.GetSerialData(null)); if (serialName != null) sec.AddEndElement("ChartContainer"); return (sec); } #endregion #region PutSerialData #region ProcessValue internal override void ProcessValue(SerialElement se) { switch (se.Name) { case "AutoSizeMode": AutoSizeMode = (AutoSizeMode)se.GetValueEnum(typeof(AutoSizeMode)); break; case "EmptyText": EmptyText = se.StringValue; break; case "EnableEmptyTextMarkup": EnableEmptyTextMarkup = bool.Parse(se.StringValue); break; case "EnablePanning": EnablePanning = bool.Parse(se.StringValue); break; case "EnableSelection": EnableSelection = bool.Parse(se.StringValue); break; case "FillWeight": FillWeight = int.Parse(se.StringValue); break; case "HScrollBarHeight": HScrollBarHeight = int.Parse(se.StringValue); break; case "HScrollBarVisible": HScrollBarVisible = bool.Parse(se.StringValue); break; case "MatrixAlignEndColumn": MatrixAlignEndColumn = bool.Parse(se.StringValue); break; case "MatrixAlignEndRow": MatrixAlignEndRow = bool.Parse(se.StringValue); break; case "MatrixAlignStartColumn": MatrixAlignStartColumn = bool.Parse(se.StringValue); break; case "MatrixAlignStartRow": MatrixAlignStartRow = bool.Parse(se.StringValue); break; case "MatrixDisplayBounds": ChartPanel panel = Parent as ChartPanel; if (panel == null || panel.AutoFillChartMatrix == false) MatrixDisplayBounds = se.GetValueRect(); break; case "MatrixDisplayOrder": MatrixDisplayOrder = int.Parse(se.StringValue); break; case "MinContentSize": MinContentSize = se.GetValueSize(); break; case "VScrollBarWidth": VScrollBarWidth = int.Parse(se.StringValue); break; case "VScrollBarVisible": VScrollBarVisible = bool.Parse(se.StringValue); break; default: base.ProcessValue(se); break; } } #endregion #region ProcessCollection internal override void ProcessCollection(SerialElement se) { SerialElementCollection sec = se.Sec; switch (se.Name) { case "ChartTitle": string name = sec.GetItemValue("Name"); ChartTitle title = GetTitleByName(name); if (title != null) Titles.Remove(title); title = new ChartTitle(name); sec.PutSerialData(title); Titles.Add(title); break; case "ContainerVisualStyles": sec.PutSerialData(ContainerVisualStyles); break; case "HScrollBar": sec.PutSerialData(HScrollBar); break; case "Legend": sec.PutSerialData(Legend); break; case "Titles": sec.PutSerialData(this); break; case "VScrollBar": sec.PutSerialData(VScrollBar); break; default: base.ProcessCollection(se); break; } } #endregion #endregion #region States [Flags] private enum States : uint { AutoGenSeriesCollection = (1U << 0), EnableEmptyTextMarkup = (1U << 1), EnablePanning = (1U << 2), ShowPointsToolTips = (1U << 3), ShowSeriesToolTips = (1U << 4), HScrollBarEnabled = (1U << 5), VScrollBarEnabled = (1U << 6), HScrollBarVisible = (1U << 7), VScrollBarVisible = (1U << 8), LayoutBoundsValid = (1U << 9), IsSelected = (1U << 10), MatrixAlignStartColumn = (1U << 11), MatrixAlignEndColumn = (1U << 12), MatrixAlignStartRow = (1U << 13), MatrixAlignEndRow = (1U << 14), MatrixColumnAligned = (1U << 15), MatrixRowAligned = (1U << 16), EnableSelection = (1U << 17), } #region TestState private bool TestState(States state) { return ((_States & state) == state); } #endregion #region SetState private void SetState(States state, bool value) { if (value == true) _States |= state; else _States &= ~state; } #endregion #endregion #region IDisposable public override void Dispose() { ContainerVisualStyles = null; Titles = null; base.Dispose(); } #endregion } #region enums #region AutoSizeMode /// /// Defines auto-sizing mode. /// public enum AutoSizeMode { /// /// NotSet (None is default) /// NotSet = -1, /// /// No Auto-sizing will take place. /// None, /// /// Size will be determined by the fill weight. /// Fill, } #endregion #endregion }