/// <summary>
 /// Retrieves the value for a given access from a data point.
 /// </summary>
 /// <param name="dataPoint">The data point to retrieve the value from.</param>
 /// <param name="axis">The axis to retrieve the value for.</param>
 /// <returns>A function that returns a value appropriate for the axis
 /// when provided a DataPoint.</returns>
 protected virtual object GetActualDataPointAxisValue(DataPoint dataPoint, IAxis axis)
 {
     if (axis == InternalActualIndependentAxis)
     {
         return dataPoint.ActualIndependentValue;
     }
     else if (axis == InternalActualDependentAxis)
     {
         return dataPoint.ActualDependentValue;
     }
     return null;
 }
 /// <summary>
 /// Detaches size change and actual size change event handlers from the
 /// data point.
 /// </summary>
 /// <param name="dataPoint">The data point.</param>
 protected override void DetachEventHandlersFromDataPoint(DataPoint dataPoint)
 {
     BubbleDataPoint bubbleDataPoint = (BubbleDataPoint)dataPoint;
     bubbleDataPoint.SizePropertyChanged -= BubbleDataPointSizePropertyChanged;
     bubbleDataPoint.ActualSizePropertyChanged -= BubbleDataPointActualSizePropertyChanged;
     base.DetachEventHandlersFromDataPoint(dataPoint);
 }
        /// <summary>
        /// Prepares a bubble data point by binding the size value binding to
        /// the size property.
        /// </summary>
        /// <param name="dataPoint">The data point to prepare.</param>
        /// <param name="dataContext">The data context of the data point.
        /// </param>
        protected override void PrepareDataPoint(DataPoint dataPoint, object dataContext)
        {
            base.PrepareDataPoint(dataPoint, dataContext);

            BubbleDataPoint bubbleDataPoint = (BubbleDataPoint)dataPoint;
            bubbleDataPoint.SetBinding(BubbleDataPoint.SizeProperty, SizeValueBinding ?? DependentValueBinding ?? IndependentValueBinding);
        }
        /// <summary>
        /// Removes a data point from the plot area.
        /// </summary>
        /// <param name="dataPoint">The data point to remove.</param>
        protected virtual void RemoveDataPoint(DataPoint dataPoint)
        {
            if (dataPoint.IsSelected)
            {
                Unselect(dataPoint);
            }

            ActiveDataPointCount--;

            dataPoint.State = DataPointState.PendingRemoval;
        }
        /// <summary>
        /// Adds a data point to the plot area.
        /// </summary>
        /// <param name="dataPoint">The data point to add to the plot area.
        /// </param>
        protected virtual void AddDataPoint(DataPoint dataPoint)
        {
            if (dataPoint.IsSelected)
            {
                Select(dataPoint);
            }

            if (PlotArea != null)
            {
                // Positioning data point outside the visible area.
                Canvas.SetLeft(dataPoint, float.MinValue);
                Canvas.SetTop(dataPoint, float.MinValue);
                dataPoint.IsSelectionEnabled = IsSelectionEnabled;
                AttachEventHandlersToDataPoint(dataPoint);
                PlotArea.Children.Insert(GetInsertionIndex(dataPoint), dataPoint);
                ActiveDataPointCount++;
            }
        }
 /// <summary>
 /// Method called to get series to acquire the axes it needs.  Acquires
 /// no axes by default.
 /// </summary>
 /// <param name="firstDataPoint">The first data point.</param>
 protected abstract void GetAxes(DataPoint firstDataPoint);
        /// <summary>
        /// This method updates a single data point.
        /// </summary>
        /// <param name="dataPoint">The data point to update.</param>
        protected override void UpdateDataPoint(DataPoint dataPoint)
        {
            double PlotAreaHeight = ActualDependentRangeAxis.GetPlotAreaCoordinate(ActualDependentRangeAxis.Range.Maximum).Value;
            double dataPointX = ActualIndependentAxis.GetPlotAreaCoordinate(dataPoint.ActualIndependentValue).Value;
            double dataPointY = ActualDependentRangeAxis.GetPlotAreaCoordinate(dataPoint.ActualDependentValue).Value;

            if (ValueHelper.CanGraph(dataPointX) && ValueHelper.CanGraph(dataPointY))
            {
                dataPoint.Visibility = Visibility.Visible;

                // Set the Position
                Canvas.SetLeft(
                    dataPoint,
                    Math.Round(dataPointX - (dataPoint.ActualWidth / 2)));
                Canvas.SetTop(
                    dataPoint,
                    Math.Round(PlotAreaHeight - (dataPointY + (dataPoint.ActualHeight / 2))));
            }
            else
            {
                dataPoint.Visibility = Visibility.Collapsed;
            }
        }
 /// <summary>
 /// Returns the DataItem corresponding to the specified DataPoint.
 /// </summary>
 /// <param name="dataPoint">Specified DataPoint.</param>
 /// <returns>Corresponding DataItem.</returns>
 protected DataItem DataItemFromDataPoint(DataPoint dataPoint)
 {
     return DataItems.Where(di => di.DataPoint == dataPoint).Single();
 }
 /// <summary>
 /// Updates the visual representation of a single data point in the plot
 /// area.
 /// </summary>
 /// <param name="dataPoint">The data point to update.</param>
 protected abstract void UpdateDataPoint(DataPoint dataPoint);
 /// <summary>
 /// Detaches event handlers from a data point.
 /// </summary>
 /// <param name="dataPoint">The data point.</param>
 protected virtual void DetachEventHandlersFromDataPoint(DataPoint dataPoint)
 {
     
     dataPoint.IsSelectedChanged -= OnDataPointIsSelectedChanged;
     dataPoint.ActualDependentValueChanged -= OnDataPointActualDependentValueChanged;
     dataPoint.ActualIndependentValueChanged -= OnDataPointActualIndependentValueChanged;
     dataPoint.DependentValueChanged -= OnDataPointDependentValueChanged;
     dataPoint.IndependentValueChanged -= OnDataPointIndependentValueChanged;
 }
 /// <summary>
 /// Selects a data point.
 /// </summary>
 /// <param name="dataPoint">The data point to select.</param>
 private void Select(DataPoint dataPoint)
 {
     SelectedItem = dataPoint.DataContext;
 }
 /// <summary>
 /// Unselects a data point.
 /// </summary>
 /// <param name="dataPoint">The data point to unselect.</param>
 private void Unselect(DataPoint dataPoint)
 {
     if (dataPoint.DataContext.Equals(SelectedItem))
     {
         SelectedItem = null;
     }
 }
 /// <summary>
 /// Attaches event handlers to a data point.
 /// </summary>
 /// <param name="dataPoint">The data point.</param>
 protected virtual void AttachEventHandlersToDataPoint(DataPoint dataPoint)
 {
     dataPoint.IsSelectedChanged += OnDataPointIsSelectedChanged;
     dataPoint.ActualDependentValueChanged += OnDataPointActualDependentValueChanged;
     dataPoint.ActualIndependentValueChanged += OnDataPointActualIndependentValueChanged;
     dataPoint.DependentValueChanged += OnDataPointDependentValueChanged;
     dataPoint.IndependentValueChanged += OnDataPointIndependentValueChanged;
     dataPoint.StateChanged += OnDataPointStateChanged;
 }
        /// <summary>
        /// Method called to get the axes that the series needs.
        /// </summary>
        /// <param name="firstDataPoint">The first data point.</param>
        /// <param name="independentAxisPredicate">A predicate that returns
        /// a value indicating whether an axis is an acceptable candidate for
        /// the series independent axis.</param>
        /// <param name="independentAxisFactory">A function that creates an
        /// acceptable independent axis.</param>
        /// <param name="dependentAxisPredicate">A predicate that returns
        /// a value indicating whether an axis is an acceptable candidate for
        /// the series dependent axis.</param>
        /// <param name="dependentAxisFactory">A function that creates an
        /// acceptable dependent axis.</param>
        protected virtual void GetAxes(DataPoint firstDataPoint, Func<IAxis, bool> independentAxisPredicate, Func<IAxis> independentAxisFactory, Func<IAxis, bool> dependentAxisPredicate, Func<IAxis> dependentAxisFactory)
        {
            Func<IAxis, bool> actualIndependentAxisPredicate = (axis) => independentAxisPredicate(axis) && axis.CanPlot(firstDataPoint.IndependentValue);
            IAxis workingIndependentAxis = null;
            if (this.InternalActualIndependentAxis == null)
            {
                if (this.InternalIndependentAxis != null)
                {
                    if (actualIndependentAxisPredicate(this.InternalIndependentAxis))
                    {
                        workingIndependentAxis = this.InternalIndependentAxis;
                    }
                    else
                    {
                        throw new InvalidOperationException(ModernUI.Toolkit.Data.Charting.Resources.DataPointSeriesWithAxes_GetAxes_AssignedIndependentAxisCannotBeUsed);
                    }
                }

                if (workingIndependentAxis == null)
                {
                    workingIndependentAxis = this.SeriesHost.Axes.FirstOrDefault(actualIndependentAxisPredicate);
                }

                if (workingIndependentAxis == null)
                {
                    workingIndependentAxis = independentAxisFactory();
                }

                this.InternalActualIndependentAxis = workingIndependentAxis;

                if (!workingIndependentAxis.RegisteredListeners.Contains(this))
                {
                    workingIndependentAxis.RegisteredListeners.Add(this);
                }
                if (!this.SeriesHost.Axes.Contains(workingIndependentAxis))
                {
                    this.SeriesHost.Axes.Add(workingIndependentAxis);
                }
            }

            Func<IAxis, bool> actualDependentAxisPredicate = (axis) => dependentAxisPredicate(axis) && axis.CanPlot(firstDataPoint.DependentValue);
            IAxis workingDependentAxis = null;
            if (this.InternalActualDependentAxis == null)
            {
                if (this.InternalDependentAxis != null)
                {
                    if (actualDependentAxisPredicate(this.InternalDependentAxis))
                    {
                        workingDependentAxis = this.InternalDependentAxis;
                    }
                    else
                    {
                        throw new InvalidOperationException(ModernUI.Toolkit.Data.Charting.Resources.DataPointSeriesWithAxes_GetAxes_AssignedDependentAxisCannotBeUsed);
                    }
                }

                if (workingDependentAxis == null)
                {
                    workingDependentAxis = InternalActualIndependentAxis.DependentAxes.Concat(this.SeriesHost.Axes).FirstOrDefault(actualDependentAxisPredicate);
                }

                if (workingDependentAxis == null)
                {
                    workingDependentAxis = dependentAxisFactory();
                }

                this.InternalActualDependentAxis = workingDependentAxis;

                if (!workingDependentAxis.RegisteredListeners.Contains(this))
                {
                    workingDependentAxis.RegisteredListeners.Add(this);
                }

                // Only add axis to the axes collection of the series host if 
                // it is not a dependent axis belonging to the acquired 
                // independent axis.
                if (!this.SeriesHost.Axes.Contains(workingDependentAxis) && !InternalActualIndependentAxis.DependentAxes.Contains(workingDependentAxis))
                {
                    this.SeriesHost.Axes.Add(workingDependentAxis);
                }
            }
        }
        /// <summary>
        /// Updates the data point's visual representation.
        /// </summary>
        /// <param name="dataPoint">The data point.</param>
        protected override void UpdateDataPoint(DataPoint dataPoint)
        {
            double maximumDiameter = Math.Min(PlotAreaSize.Width, PlotAreaSize.Height) * MaximumBubbleSizeAsRatioOfSmallestDimension;

            BubbleDataPoint bubbleDataPoint = (BubbleDataPoint)dataPoint;

            double ratioOfLargestBubble =
                (_rangeOfActualSizeValues.HasData && _rangeOfActualSizeValues.Maximum != 0.0 && bubbleDataPoint.ActualSize >= 0.0) ? Math.Abs(bubbleDataPoint.ActualSize) / _rangeOfActualSizeValues.Maximum : 0.0;

            bubbleDataPoint.Width = ratioOfLargestBubble * maximumDiameter;
            bubbleDataPoint.Height = ratioOfLargestBubble * maximumDiameter;

            double left =
                (ActualIndependentAxis.GetPlotAreaCoordinate(bubbleDataPoint.ActualIndependentValue)).Value
                    - (bubbleDataPoint.Width / 2.0);

            double top =
                (PlotAreaSize.Height
                    - (bubbleDataPoint.Height / 2.0))
                    - ActualDependentRangeAxis.GetPlotAreaCoordinate(bubbleDataPoint.ActualDependentValue).Value;

            if (ValueHelper.CanGraph(left) && ValueHelper.CanGraph(top))
            {
                dataPoint.Visibility = Visibility.Visible;

                Canvas.SetLeft(bubbleDataPoint, left);
                Canvas.SetTop(bubbleDataPoint, top);
            }
            else
            {
                dataPoint.Visibility = Visibility.Collapsed;
            }
        }
        /// <summary>
        /// Prepares a data point by extracting binding it to a data context
        /// object.
        /// </summary>
        /// <param name="dataPoint">A data point.</param>
        /// <param name="dataContext">A data context object.</param>
        protected virtual void PrepareDataPoint(DataPoint dataPoint, object dataContext)
        {
            // Create a Control with DataContext set to the data source
            dataPoint.DataContext = dataContext;

            // Set bindings for IndependentValue/DependentValue
            if (IndependentValueBinding != null)
            {
                dataPoint.SetBinding(DataPoint.IndependentValueProperty, IndependentValueBinding);
            }

            if (DependentValueBinding == null)
            {
                dataPoint.SetBinding(DataPoint.DependentValueProperty, new Binding());
            }
            else
            {
                dataPoint.SetBinding(DataPoint.DependentValueProperty, DependentValueBinding);
            }
        }
 /// <summary>
 /// Prepares a DataPoint for use.
 /// </summary>
 /// <param name="dataPoint">DataPoint instance.</param>
 protected virtual void PrepareDataPoint(DataPoint dataPoint) { }
 /// <summary>
 /// Handles data point state property change.
 /// </summary>
 /// <param name="dataPoint">The data point.</param>
 /// <param name="oldValue">The old value.</param>
 /// <param name="newValue">The new value.</param>
 protected virtual void OnDataPointStateChanged(DataPoint dataPoint, DataPointState oldValue, DataPointState newValue)
 {
    
 }
 /// <summary>
 /// Acquire a horizontal linear axis and a vertical linear axis.
 /// </summary>
 /// <param name="firstDataPoint">The first data point.</param>
 protected override void GetAxes(DataPoint firstDataPoint)
 {
     GetAxes(
         firstDataPoint,
         (axis) => axis.Orientation == AxisOrientation.X,
         () =>
         {
             IAxis axis = CreateRangeAxisFromData(firstDataPoint.IndependentValue);
             if (axis == null)
             {
                 axis = new CategoryAxis();
             }
             axis.Orientation = AxisOrientation.X;
             return axis;
         },
         (axis) => axis.Orientation == AxisOrientation.Y && axis is IRangeAxis,
         () =>
         {
             DisplayAxis axis = (DisplayAxis)CreateRangeAxisFromData(firstDataPoint.DependentValue);
             if (axis == null)
             {
                 throw new InvalidOperationException(ModernUI.Toolkit.Data.Charting.Resources.DataPointSeriesWithAxes_NoSuitableAxisAvailableForPlottingDependentValue);
             }
             axis.ShowGridLines = true;
             axis.Orientation = AxisOrientation.Y;
             return axis;
         });
 }
 /// <summary>
 /// Returns the index at which to insert data point in the plot area
 /// child collection.
 /// </summary>
 /// <param name="dataPoint">The data point to retrieve the insertion
 /// index for.</param>
 /// <returns>The insertion index.</returns>
 protected virtual int GetInsertionIndex(DataPoint dataPoint)
 {
     return PlotArea.Children.Count;
 }
 /// <summary>
 /// Prepares a DataPoint for use.
 /// </summary>
 /// <param name="dataPoint">DataPoint instance.</param>
 protected override void PrepareDataPoint(DataPoint dataPoint)
 {
     base.PrepareDataPoint(dataPoint);
     dataPoint.SizeChanged += new SizeChangedEventHandler(DataPointSizeChanged);
 }
 /// <summary>
 /// Sets the style of the data point to the single style used for all
 /// data points.
 /// </summary>
 /// <param name="dataPoint">The data point to apply the style to.
 /// </param>
 /// <param name="dataContext">The object associated with the data point.
 /// </param>
 protected override void PrepareDataPoint(DataPoint dataPoint, object dataContext)
 {
     dataPoint.SetBinding(DataPoint.StyleProperty, new Binding() { Path = new PropertyPath(ActualDataPointStyleName), Source = this });
     base.PrepareDataPoint(dataPoint, dataContext);
 }