/// <summary>
        /// Handles the mouse move event
        /// </summary>
        /// <param name="e"></param>
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (_isDragging)
            {
                Region    rg = new Region();
                Rectangle gb = _graph.GetGraphBounds();
                if (_selectedSlider != null)
                {
                    rg.Union(_selectedSlider.Bounds);
                    int x     = e.X;
                    int index = _breaks.IndexOf(_selectedSlider);
                    if (x > gb.Right)
                    {
                        x = gb.Right;
                    }
                    if (x < gb.Left)
                    {
                        x = gb.Left;
                    }
                    if (index > 0)
                    {
                        if (x < _breaks[index - 1].Position + 2)
                        {
                            x = (int)_breaks[index - 1].Position + 2;
                        }
                    }
                    if (index < _breaks.Count - 1)
                    {
                        if (x > _breaks[index + 1].Position - 2)
                        {
                            x = (int)_breaks[index + 1].Position - 2;
                        }
                    }
                    _selectedSlider.Position = x;
                    rg.Union(_selectedSlider.Bounds);
                    Invalidate(rg);
                }
                return;
            }
            bool overSlider = false;

            foreach (BreakSlider slider in _breaks)
            {
                if (slider.Bounds.Contains(e.Location) || slider.HandleBounds.Contains(e.Location))
                {
                    overSlider = true;
                }
            }
            if (_dragCursor && !overSlider)
            {
                Cursor      = Cursors.Arrow;
                _dragCursor = false;
            }
            if (!_dragCursor && overSlider)
            {
                _dragCursor = true;
                Cursor      = Cursors.SizeWE;
            }

            base.OnMouseMove(e);
        }
        /// <summary>
        /// Given a scheme, this will build the break list to match approximately. This does not
        /// force the interval method to build a new scheme.
        /// </summary>
        public void UpdateBreaks()
        {
            if (_isRaster)
            {
                UpdateRasterBreaks();
                return;
            }

            if (_scheme == null)
            {
                return;
            }
            IFeatureCategory selectedCat = null;

            if (_selectedSlider != null)
            {
                selectedCat = _selectedSlider.Category as IFeatureCategory;
            }
            Breaks.Clear();
            Statistics stats = _scheme.Statistics;
            Rectangle  gb    = _graph.GetGraphBounds();

            _graph.ColorRanges.Clear();
            foreach (IFeatureCategory category in _scheme.GetCategories())
            {
                ColorRange cr = new ColorRange(category.GetColor(), category.Range);
                _graph.ColorRanges.Add(cr);
                BreakSlider bs = new BreakSlider(gb, _graph.Minimum, _graph.Maximum, cr)
                {
                    Color       = _breakColor,
                    SelectColor = _selectedBreakColor
                };
                if (selectedCat != null && category == selectedCat)
                {
                    bs.Selected          = true;
                    _selectedSlider      = bs;
                    _graph.SelectedRange = cr;
                }

                bs.Value = category.Maximum != null?double.Parse(category.Maximum.ToString()) : stats.Maximum;

                bs.Category = category;
                Breaks.Add(bs);
            }

            Breaks.Sort();

            // Moving a break generally affects both a maximum and a minimum.
            // Point to the next category to actuate that.
            for (int i = 0; i < Breaks.Count - 1; i++)
            {
                Breaks[i].NextCategory = Breaks[i + 1].Category;

                // We use the maximums to set up breaks. Minimums should simply
                // be set to work with the maximums of the previous category.
                Breaks[i + 1].Category.Minimum = Breaks[i].Value;
            }

            if (Breaks.Count == 0)
            {
                return;
            }
            int         breakIndex = 0;
            BreakSlider nextSlider = Breaks[breakIndex];
            int         count      = 0;

            if (_graph?.Bins == null)
            {
                return;
            }
            foreach (double value in _values)
            {
                if (value < nextSlider.Value)
                {
                    count++;
                    continue;
                }

                nextSlider.Count = count;
                while (value > nextSlider.Value)
                {
                    breakIndex++;
                    if (breakIndex >= Breaks.Count)
                    {
                        break;
                    }

                    nextSlider = Breaks[breakIndex];
                }

                count = 0;
            }
        }