Example #1
0
        /// <summary>
        ///     Called when the value of the SeriesHost property changes.
        /// </summary>
        /// <param name="oldValue">The value to be replaced.</param>
        /// <param name="newValue">The new series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            if (null != oldValue)
            {
                oldValue.ResourceDictionariesChanged -= SeriesHostResourceDictionariesChanged;
            }

            if (null != newValue)
            {
                newValue.ResourceDictionariesChanged += SeriesHostResourceDictionariesChanged;
            }
            else
            {
                // Dispose of the enumerator.
                if (null != _resourceDictionaryEnumerator)
                {
                    _resourceDictionaryEnumerator.Dispose();
                    _resourceDictionaryEnumerator = null;
                }
            }

            ResourceDictionaryDispenser.Parent = newValue;
        }
 /// <summary>
 /// Called when the value of the SeriesHost property changes.
 /// </summary>
 /// <param name="oldValue">The value to be replaced.</param>
 /// <param name="newValue">The new series host value.</param>
 protected virtual void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
 {
     if (newValue != null && oldValue != null)
     {
         throw new InvalidOperationException(ModernUI.Toolkit.Data.Charting.Resources.Series_SeriesHost_SeriesHostPropertyNotNull);
     }
 }
Example #3
0
 /// <summary>
 /// Called when the value of the SeriesHost property changes.
 /// </summary>
 /// <param name="oldValue">The value to be replaced.</param>
 /// <param name="newValue">The new series host value.</param>
 protected virtual void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
 {
     if ((oldValue != null) && (newValue != null))
     {
         throw new InvalidOperationException(Properties.Resources.Series_SeriesHost_SeriesHostPropertyNotNull);
     }
 }
        /// <summary>
        /// Called when the ObservableCollection.CollectionChanged property
        /// changes.
        /// </summary>
        /// <param name="sender">The object that raised the event.</param>
        /// <param name="e">The event data.</param>
        private void OnSeriesCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            // Clear ISeriesHost property of old Series
            if (null != e.OldItems)
            {
                foreach (Series series in e.OldItems)
                {
                    ISeriesHost host = series as ISeriesHost;
                    if (host != null)
                    {
                        foreach (IRequireGlobalSeriesIndex tracksGlobalIndex in host.GetDescendentSeries().OfType <IRequireGlobalSeriesIndex>())
                        {
                            tracksGlobalIndex.GlobalSeriesIndexChanged(-1);
                        }
                    }

                    RemoveSeriesFromPlotArea(series);
                }
            }

            // Set ISeriesHost property of new Series
            if (null != e.NewItems)
            {
                foreach (Series series in e.NewItems)
                {
                    AddSeriesToPlotArea(series);
                }
            }

            if (e.Action != NotifyCollectionChangedAction.Replace)
            {
                OnGlobalSeriesIndexesInvalidated(this, new RoutedEventArgs());
            }
        }
 protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
 {
     if (oldValue != null && ForegroundGridLines != null)
         oldValue.ForegroundElements.Remove(ForegroundGridLines);
     if (newValue != null && ForegroundGridLines != null)
         newValue.ForegroundElements.Add(ForegroundGridLines);
 }
 /// <summary>
 /// Instantiates a new instance of the SeriesHostAxesCollection class.
 /// </summary>
 /// <param name="seriesHost">The series host.</param>
 /// <param name="persistentAxes">A collection of axes that can never be
 /// removed from the chart.</param>
 internal SeriesHostAxesCollection(ISeriesHost seriesHost, UniqueObservableCollection <IAxis> persistentAxes)
     : this(seriesHost)
 {
     Debug.Assert(persistentAxes != null, "Persistent axes collection cannot be null.");
     this.SeriesHost     = seriesHost;
     this.PersistentAxes = persistentAxes;
     this.PersistentAxes.CollectionChanged += PersistentAxesCollectionChanged;
 }
 /// <summary>
 /// Redraws other column series to assure they allocate the right amount
 /// of space for their columns.
 /// </summary>
 /// <param name="seriesHost">The series host to update.</param>
 private void RedrawOtherColumnSeries(ISeriesHost seriesHost)
 {
     // redraw all other column series to ensure they make space for new one
     foreach (ColumnSeries series in seriesHost.Series.OfType <ColumnSeries>().Where(series => series != this))
     {
         series.UpdateAllDataPoints();
     }
 }
        /// <summary>
        /// When the series host property is set retrieves a style to use for all the
        /// data points.
        /// </summary>
        /// <param name="oldValue">The old series host value.</param>
        /// <param name="newValue">The new series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            if (newValue != null)
            {
                ActualDataPointStyle = DataPointStyle ?? GetDataPointStyleFromHost();
                CreateLegendItemDataPoint();
            }
        }
Example #9
0
        /// <summary>
        /// Redraws other column series to assure they allocate the right amount
        /// of space for their columns.
        /// </summary>
        /// <param name="seriesHost">The series host to update.</param>
        protected void RedrawOtherSeries(ISeriesHost seriesHost)
        {
            Type thisType = typeof(ColumnBarBaseSeries <T>);

            // redraw all other column series to ensure they make space for new one
            foreach (ColumnBarBaseSeries <T> series in seriesHost.Series.Where(series => thisType.GetTypeInfo().IsAssignableFrom(series.GetType().GetTypeInfo())).OfType <ColumnBarBaseSeries <T> >().Where(series => series != this))
            {
                series.UpdateDataPoints(series.ActiveDataPoints);
            }
        }
        /// <summary>
        /// Handles changes to the SeriesHost property.
        /// </summary>
        /// <param name="oldValue">Old value.</param>
        /// <param name="newValue">New value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            if (null == newValue)
            {
                // Reset flag to prepare for next addition to a series host
                _needRefreshWhenSizeChanged = true;
            }
        }
        /// <summary>
        /// Redraw other column series when removed from a series host.
        /// </summary>
        /// <param name="oldValue">The old value of the series host property.</param>
        /// <param name="newValue">The new value of the series host property.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            // If being removed from series host, redraw all column series.
            if (newValue == null || oldValue != null)
            {
                RedrawOtherColumnSeries(oldValue);
            }
        }
Example #12
0
 protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
 {
     if (oldValue != null && ForegroundGridLines != null)
     {
         oldValue.ForegroundElements.Remove(ForegroundGridLines);
     }
     if (newValue != null && ForegroundGridLines != null)
     {
         newValue.ForegroundElements.Add(ForegroundGridLines);
     }
 }
Example #13
0
        /// <summary>
        /// This method is run when the series host property is changed.
        /// </summary>
        /// <param name="oldValue">The old series host.</param>
        /// <param name="newValue">The new series host.</param>
        protected virtual void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            if (oldValue != null && this.GridLines != null)
            {
                oldValue.BackgroundElements.Remove(this.GridLines);
            }

            if (newValue != null && this.GridLines != null)
            {
                newValue.BackgroundElements.Add(this.GridLines);
            }
        }
Example #14
0
        /// <summary>
        /// Sets the new series host to be the parent style dispenser of the
        /// local style dispenser object.
        /// </summary>
        /// <param name="oldValue">The new series host value.</param>
        /// <param name="newValue">The old series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            // Disposing of the style enumerator.
            if ((newValue == null) && (null != _styleEnumerator))
            {
                _styleEnumerator.Dispose();
                _styleEnumerator = null;
            }

            this.StyleDispenser.Parent = newValue;
        }
        /// <summary>
        /// Removes a series from the plot area.
        /// </summary>
        /// <param name="series">The series to remove from the plot area.
        /// </param>
        private void RemoveSeriesFromPlotArea(Series series)
        {
            AggregatedObservableCollection <UIElement> legendItemsList = LegendItems as AggregatedObservableCollection <UIElement>;

            legendItemsList.ChildCollections.Remove(series.LegendItems);

            ISeriesHost host = series as ISeriesHost;

            if (host != null)
            {
                host.GlobalSeriesIndexesInvalidated -= OnChildSeriesGlobalSeriesIndexesInvalidated;
            }
            series.SeriesHost = null;
        }
        /// <summary>
        /// Adds a series to the plot area and injects chart services.
        /// </summary>
        /// <param name="series">The series to add to the plot area.</param>
        private void AddSeriesToPlotArea(Series series)
        {
            series.SeriesHost = this;
            AggregatedObservableCollection <UIElement> chartLegendItems = this.LegendItems as AggregatedObservableCollection <UIElement>;

            int indexOfSeries = this.Series.IndexOf(series);

            chartLegendItems.ChildCollections.Insert(indexOfSeries, series.LegendItems);

            ISeriesHost host = series as ISeriesHost;

            if (host != null)
            {
                host.GlobalSeriesIndexesInvalidated += OnChildSeriesGlobalSeriesIndexesInvalidated;
            }
        }
        /// <summary>
        /// When the series host property is set retrieves a style to use for all the
        /// data points.
        /// </summary>
        /// <param name="oldValue">The old series host value.</param>
        /// <param name="newValue">The new series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            if (oldValue != null)
            {
                oldValue.ResourceDictionariesChanged -= new EventHandler(SeriesHostResourceDictionariesChanged);
            }

            if (newValue != null)
            {
                newValue.ResourceDictionariesChanged += new EventHandler(SeriesHostResourceDictionariesChanged);

                DispensedResourcesChanging();
            }
        }
        /// <summary>
        /// When the series host property is set retrieves a style to use for all the
        /// data points.
        /// </summary>
        /// <param name="oldValue">The old series host value.</param>
        /// <param name="newValue">The new series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            if (newValue != null)
            {
                using (IEnumerator <Style> styleEnumerator = GetStyleEnumeratorFromHost())
                {
                    if (styleEnumerator.MoveNext())
                    {
                        ActualDataPointStyle = DataPointStyle ?? styleEnumerator.Current;
                    }
                }

                CreateLegendItemDataPoint();
            }
        }
        /// <summary>
        /// Called when the value of the SeriesHost property changes.
        /// </summary>
        /// <param name="oldValue">The value to be replaced.</param>
        /// <param name="newValue">The new series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            if (oldValue != null)
            {
                if (InternalActualIndependentAxis != null)
                {
                    InternalActualIndependentAxis.RegisteredListeners.Remove(this);
                    InternalActualIndependentAxis = null;
                }
                if (InternalActualDependentAxis != null)
                {
                    InternalActualDependentAxis.RegisteredListeners.Remove(this);
                    InternalActualDependentAxis = null;
                }
            }

            base.OnSeriesHostPropertyChanged(oldValue, newValue);
        }
Example #20
0
        /// <summary>
        ///     Gets all series that track their global indexes recursively.
        /// </summary>
        /// <param name="rootSeriesHost">The root series host.</param>
        /// <returns>A sequence of series.</returns>
        public static IEnumerable <ISeries> GetDescendentSeries(this ISeriesHost rootSeriesHost)
        {
            var series = new Queue <ISeries>(rootSeriesHost.Series);

            while (series.Count != 0)
            {
                ISeries currentSeries = series.Dequeue();
                yield return(currentSeries);

                var seriesHost = currentSeries as ISeriesHost;
                if (seriesHost != null)
                {
                    foreach (ISeries childSeries in seriesHost.Series)
                    {
                        series.Enqueue(childSeries);
                    }
                }
            }
        }
Example #21
0
        /// <summary>
        /// Called when the value of the SeriesHost property changes.
        /// </summary>
        /// <param name="oldValue">The value to be replaced.</param>
        /// <param name="newValue">The new series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            if (oldValue != null)
            {
                if (InternalActualIndependentAxis != null)
                {
                    oldValue.UnregisterWithAxis(this, InternalActualIndependentAxis);
                    InternalActualIndependentAxis.Invalidated -= OnAxisInvalidated;
                    InternalActualIndependentAxis              = null;
                }
                if (InternalActualDependentAxis != null)
                {
                    oldValue.UnregisterWithAxis(this, InternalActualDependentAxis);
                    InternalActualDependentAxis.Invalidated -= OnAxisInvalidated;
                    InternalActualDependentAxis              = null;
                }
            }

            base.OnSeriesHostPropertyChanged(oldValue, newValue);
        }
        /// <summary>
        /// Ensures that chart and series are kept in a consistent state when a
        /// series is added or removed from a chart.
        /// </summary>
        /// <param name="oldValue">Old chart.</param>
        /// <param name="newValue">New chart.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            IRangeAxis axis = null;

            // Unregister the axes from the old chart
            if (oldValue != null)
            {
                axis = IndependentAxis;
                if (axis != null)
                {
                    axis.RegisteredListeners.Remove(this);
                    IndependentAxis = null;
                }

                axis = DependentAxis;
                if (axis != null)
                {
                    axis.RegisteredListeners.Remove(this);
                    DependentAxis = null;
                }
            }

            // Register the axes with new chart
            if (newValue != null)
            {
                axis = IndependentAxis;
                if (axis != null)
                {
                    axis.RegisteredListeners.Add(this);
                }

                axis = DependentAxis;
                if (axis != null)
                {
                    axis.RegisteredListeners.Add(this);
                }
            }

            base.OnSeriesHostPropertyChanged(oldValue, newValue);
        }
Example #23
0
        /// <summary>
        /// Initializes a new instance of the Chart class.
        /// </summary>
        public Chart()
        {
#if SILVERLIGHT
            DefaultStyleKey = typeof(Chart);
#endif
            // Create the backing collection for Series
            UniqueObservableCollection <Series> series = new UniqueObservableCollection <Series>();
            series.CollectionChanged += new NotifyCollectionChangedEventHandler(OnSeriesCollectionChanged);
            _series = series;

            // Create the backing collection for Axes
            UniqueObservableCollection <IAxis> axes = new UniqueObservableCollection <IAxis>();
            _axes = axes;

            ObservableCollection <IAxis> actualAxes = new SeriesHostAxesCollection(this, axes);
            actualAxes.CollectionChanged += ActualAxesCollectionChanged;
            this.InternalActualAxes       = actualAxes;
            this.ActualAxes = new ReadOnlyCollection <IAxis>(InternalActualAxes);

            // Create collection for LegendItems
            NoResetObservableCollection <UIElement> chartLegendItems = new AggregatedObservableCollection <UIElement>();
            _legendChildrenLegendAdapter.Collection = chartLegendItems;
            LegendItems = chartLegendItems;

            ISeriesHost host = this as ISeriesHost;
            host.GlobalSeriesIndexesInvalidated += OnGlobalSeriesIndexesInvalidated;

            ChartAreaChildren = new AggregatedObservableCollection <UIElement>();
            ChartAreaChildren.ChildCollections.Add(_edgeAxes);
            ChartAreaChildren.ChildCollections.Add(_backgroundElements);
            ChartAreaChildren.ChildCollections.Add(Series);
            ChartAreaChildren.ChildCollections.Add(_foregroundElements);

            _chartAreaChildrenListAdapter.Collection = ChartAreaChildren;

            // Create style dispenser
            StyleDispenser = new StyleDispenser();
        }
        /// <summary>
        /// Initializes a new instance of the ISeriesHost class.
        /// </summary>
        public Chart()
        {
            DefaultStyleKey = typeof(Chart);

            // Create the backing collection for Series
            ObservableCollection <Series> series = new NoResetObservableCollection <Series>();

            series.CollectionChanged += new NotifyCollectionChangedEventHandler(OnSeriesCollectionChanged);
            _series = series;
            _seriesCollectionSeriesContainerAdapter.Collection = series;

            // Create the backing collection for Axes
            ObservableCollection <IAxis> axes = new NoResetObservableCollection <IAxis>();

            axes.CollectionChanged += new NotifyCollectionChangedEventHandler(OnAxesCollectionChanged);
            _axes = axes;

            ObservableCollection <IAxis> actualAxes = new ObservableCollection <IAxis>();

            actualAxes.CollectionChanged += new NotifyCollectionChangedEventHandler(ActualAxesCollectionChanged);
            this.InternalActualAxes       = actualAxes;
            this.ActualAxes = new ReadOnlyCollection <IAxis>(InternalActualAxes);

            _gridLinesContainerChildrenChartAreaAdapter.Collection = _gridLinesContainerChildren;

            // Create collection for LegendItems
            AggregatedObservableCollection <UIElement> chartLegendItems = new AggregatedObservableCollection <UIElement>();

            _legendChildrenLegendAdapter.Collection = chartLegendItems;
            LegendItems = chartLegendItems;

            ISeriesHost host = this as ISeriesHost;

            host.GlobalSeriesIndexesInvalidated += OnGlobalSeriesIndexesInvalidated;

            // Create style dispenser
            StyleDispenser = new StyleDispenser();
        }
Example #25
0
        /// <summary>
        /// Called when the value of the SeriesHost property changes.
        /// </summary>
        /// <param name="oldValue">The value to be replaced.</param>
        /// <param name="newValue">The new series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            if (null != oldValue)
            {
                oldValue.ResourceDictionariesChanged -= new EventHandler(SeriesHostResourceDictionariesChanged);
            }

            if (null != newValue)
            {
                newValue.ResourceDictionariesChanged += new EventHandler(SeriesHostResourceDictionariesChanged);
            }
            else
            {
                // Dispose of the enumerator.
                if (null != _resourceDictionaryEnumerator)
                {
                    _resourceDictionaryEnumerator.Dispose();
                    _resourceDictionaryEnumerator = null;
                }
            }

            this.ResourceDictionaryDispenser.Parent = newValue;
        }
        /// <summary>
        /// Rebuilds the chart area.
        /// </summary>
        private void RebuildChartArea()
        {
            if (ChartArea != null && PlotArea != null)
            {
                ISeriesHost        seriesHost = this as ISeriesHost;
                IEnumerable <Axis> axes       = seriesHost.Axes.OfType <Axis>();
                ChartArea.Children.Clear();
                ChartArea.RowDefinitions.Clear();
                ChartArea.ColumnDefinitions.Clear();

                IEnumerable <Axis> leftAxes   = axes.Where(axis => axis.Location == AxisLocation.Left);
                IEnumerable <Axis> topAxes    = axes.Where(axis => axis.Location == AxisLocation.Top);
                IEnumerable <Axis> rightAxes  = axes.Where(axis => axis.Location == AxisLocation.Right);
                IEnumerable <Axis> bottomAxes = axes.Where(axis => axis.Location == AxisLocation.Bottom);

                // Choosing appropriate actual axis location values for Auto
                int leftAxesCount   = leftAxes.Count();
                int topAxesCount    = topAxes.Count();
                int rightAxesCount  = rightAxes.Count();
                int bottomAxesCount = bottomAxes.Count();

                IEnumerable <Axis> autoAxes = axes.Where(axis => axis.Location == AxisLocation.Auto);
                Axis autoAxis = autoAxes.FirstOrDefault();
                while (autoAxis != null)
                {
                    autoAxis.LocationChanged -= AxisLocationChanged;
                    if (autoAxis.Orientation == AxisOrientation.Horizontal)
                    {
                        if (bottomAxesCount <= topAxesCount)
                        {
                            autoAxis.Location = AxisLocation.Bottom;
                            bottomAxesCount++;
                        }
                        else
                        {
                            autoAxis.Location = AxisLocation.Top;
                            topAxesCount++;
                        }
                    }
                    else if (autoAxis.Orientation == AxisOrientation.Vertical)
                    {
                        if (leftAxesCount <= rightAxesCount)
                        {
                            autoAxis.Location = AxisLocation.Left;
                            leftAxesCount++;
                        }
                        else
                        {
                            autoAxis.Location = AxisLocation.Right;
                            rightAxesCount++;
                        }
                    }
                    autoAxis.LocationChanged += AxisLocationChanged;
                    autoAxis = autoAxes.FirstOrDefault();
                }

                // building grid
                int numTopAxes  = topAxes.Count();
                int numLeftAxes = leftAxes.Count();

                topAxes.Reverse().ForEachWithIndex((axis, index) =>
                {
                    axis.HorizontalAlignment = HorizontalAlignment.Stretch;
                    axis.VerticalAlignment   = VerticalAlignment.Bottom;
                    ChartArea.RowDefinitions.Add(new RowDefinition {
                        Height = GridLength.Auto
                    });
                    Grid.SetColumn(axis, numLeftAxes);
                    Grid.SetRow(axis, index);
                });

                leftAxes.Reverse().ForEachWithIndex((axis, index) =>
                {
                    axis.VerticalAlignment   = VerticalAlignment.Stretch;
                    axis.HorizontalAlignment = HorizontalAlignment.Right;
                    ChartArea.ColumnDefinitions.Add(new ColumnDefinition {
                        Width = GridLength.Auto
                    });
                    Grid.SetRow(axis, numTopAxes);
                    Grid.SetColumn(axis, index);
                });

                ChartArea.RowDefinitions.Add(new RowDefinition());
                ChartArea.ColumnDefinitions.Add(new ColumnDefinition());

                Grid.SetRow(PlotArea, numTopAxes);
                Grid.SetColumn(PlotArea, numLeftAxes);

                bottomAxes.ForEachWithIndex((axis, index) =>
                {
                    axis.HorizontalAlignment = HorizontalAlignment.Stretch;
                    axis.VerticalAlignment   = VerticalAlignment.Top;
                    ChartArea.RowDefinitions.Add(new RowDefinition {
                        Height = GridLength.Auto
                    });
                    Grid.SetColumn(axis, numLeftAxes);
                    Grid.SetRow(axis, numTopAxes + index + 1);
                });

                rightAxes.ForEachWithIndex((axis, index) =>
                {
                    axis.VerticalAlignment   = VerticalAlignment.Stretch;
                    axis.HorizontalAlignment = HorizontalAlignment.Left;
                    ChartArea.ColumnDefinitions.Add(new ColumnDefinition {
                        Width = GridLength.Auto
                    });
                    Grid.SetRow(axis, numTopAxes);
                    Grid.SetColumn(axis, numLeftAxes + index + 1);
                });

                foreach (Axis axis in seriesHost.Axes)
                {
                    ChartArea.Children.Add(axis);
                }

                ChartArea.Children.Add(PlotArea);
            }
        }
        /// <summary>
        /// When the series host property is set retrieves a style to use for all the
        /// data points.
        /// </summary>
        /// <param name="oldValue">The old series host value.</param>
        /// <param name="newValue">The new series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            if (newValue != null)
            {
                ActualDataPointStyle = DataPointStyle ?? GetDataPointStyleFromHost();
                CreateLegendItemDataPoint();
            }
        }
        /// <summary>
        /// Ensures that chart and series are kept in a consistent state when a
        /// series is added or removed from a chart. 
        /// </summary>
        /// <param name="oldValue">Old chart.</param>
        /// <param name="newValue">New chart.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            IRangeAxis axis = null;

            // Unregister the axes from the old chart
            if (oldValue != null)
            {
                axis = IndependentAxis;
                if (axis != null)
                {
                    axis.RegisteredListeners.Remove(this);
                    IndependentAxis = null;
                }

                axis = DependentAxis;
                if (axis != null)
                {
                    axis.RegisteredListeners.Remove(this);
                    DependentAxis = null;
                }
            }

            // Register the axes with new chart
            if (newValue != null)
            {
                axis = IndependentAxis;
                if (axis != null)
                {
                    axis.RegisteredListeners.Add(this);
                }

                axis = DependentAxis;
                if (axis != null)
                {
                    axis.RegisteredListeners.Add(this);
                }
            }

            base.OnSeriesHostPropertyChanged(oldValue, newValue);
        }
Example #29
0
        /// <summary>
        /// Redraw other column series when removed from a series host.
        /// </summary>
        /// <param name="oldValue">The old value of the series host property.</param>
        /// <param name="newValue">The new value of the series host property.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            // If being removed from series host, redraw all column series.
            if (newValue == null || oldValue != null)
            {
                RedrawOtherColumnSeries(oldValue);
            }
        }
Example #30
0
 /// <summary>
 /// Redraws other column series to assure they allocate the right amount
 /// of space for their columns.
 /// </summary>
 /// <param name="seriesHost">The series host to update.</param>
 private void RedrawOtherColumnSeries(ISeriesHost seriesHost)
 {
     // redraw all other column series to ensure they make space for new one
     foreach (ColumnSeries series in seriesHost.Series.OfType<ColumnSeries>().Where(series => series != this))
     {
         series.UpdateAllDataPoints();
     }
 }
        /// <summary>
        /// When the series host property is set retrieves a style to use for all the
        /// data points.
        /// </summary>
        /// <param name="oldValue">The old series host value.</param>
        /// <param name="newValue">The new series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            if (newValue != null)
            {
                using (IEnumerator<Style> styleEnumerator = GetStyleEnumeratorFromHost())
                {
                    if (styleEnumerator.MoveNext())
                    {
                        ActualDataPointStyle = DataPointStyle ?? styleEnumerator.Current;
                    }
                }

                CreateLegendItemDataPoint();
            }
        }
 /// <summary>
 /// Instantiates a new instance of the SeriesHostAxesCollection class.
 /// </summary>
 /// <param name="seriesHost">The series host.</param>
 internal SeriesHostAxesCollection(ISeriesHost seriesHost)
 {
     this.SeriesHost         = seriesHost;
     this.PersistentAxes     = new UniqueObservableCollection <IAxis>();
     this.CollectionChanged += ThisCollectionChanged;
 }
Example #33
0
        /// <summary>
        /// Sets the new series host to be the parent style dispenser of the
        /// local style dispenser object.
        /// </summary>
        /// <param name="oldValue">The new series host value.</param>
        /// <param name="newValue">The old series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            // Disposing of the style enumerator.
            if (newValue == null)
            {
                _styleEnumerator.Dispose();
                _styleEnumerator = null;
            }

            this.StyleDispenser.Parent = newValue;
        }
        /// <summary>
        /// Called when the value of the SeriesHost property changes.
        /// </summary>
        /// <param name="oldValue">The value to be replaced.</param>
        /// <param name="newValue">The new series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            if (oldValue != null)
            {
                if (InternalActualIndependentAxis != null)
                {
                    InternalActualIndependentAxis.RegisteredListeners.Remove(this);
                    InternalActualIndependentAxis = null;
                }
                if (InternalActualDependentAxis != null)
                {
                    InternalActualDependentAxis.RegisteredListeners.Remove(this);
                    InternalActualDependentAxis = null;
                }
            }

            base.OnSeriesHostPropertyChanged(oldValue, newValue);
        }
        /// <summary>
        /// This method is run when the series host property is changed.
        /// </summary>
        /// <param name="oldValue">The old series host.</param>
        /// <param name="newValue">The new series host.</param>
        protected virtual void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            if (oldValue != null && this.GridLines != null)
            {
                oldValue.BackgroundElements.Remove(this.GridLines);
            }

            if (newValue != null && this.GridLines != null)
            {
                newValue.BackgroundElements.Add(this.GridLines);
            }
        }
Example #36
0
 /// <summary>
 /// Called when the value of the SeriesHost property changes.
 /// </summary>
 /// <param name="oldValue">The value to be replaced.</param>
 /// <param name="newValue">The new series host value.</param>
 protected virtual void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
 {
     if ((oldValue != null) && (newValue != null))
     {
         throw new InvalidOperationException(Properties.Resources.Series_SeriesHost_SeriesHostPropertyNotNull);
     }
 }
Example #37
0
        /// <summary>
        /// Handles changes to the SeriesHost property.
        /// </summary>
        /// <param name="oldValue">Old value.</param>
        /// <param name="newValue">New value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            if (null == newValue)
            {
                // Reset flag to prepare for next addition to a series host
                _needRefreshWhenSizeChanged = true;
            }
        }
Example #38
0
 /// <summary>
 ///     Gets a value indicating whether an axis is in use by the series
 ///     host.
 /// </summary>
 /// <param name="that">The series host.</param>
 /// <param name="axis">
 ///     The axis that may or may not be used by a
 ///     series.
 /// </param>
 /// <returns>
 ///     A value indicating whether an axis is in use by the series
 ///     host.
 /// </returns>
 public static bool IsUsedByASeries(this ISeriesHost that, IAxis axis)
 {
     return(axis.RegisteredListeners.OfType <ISeries>().Intersect(that.Series).Any());
 }
        /// <summary>
        /// When the series host property is set retrieves a style to use for all the
        /// data points.
        /// </summary>
        /// <param name="oldValue">The old series host value.</param>
        /// <param name="newValue">The new series host value.</param>
        protected override void OnSeriesHostPropertyChanged(ISeriesHost oldValue, ISeriesHost newValue)
        {
            base.OnSeriesHostPropertyChanged(oldValue, newValue);

            if (oldValue != null)
            {
                oldValue.ResourceDictionariesChanged -= new EventHandler(SeriesHostResourceDictionariesChanged);
            }

            if (newValue != null)
            {
                newValue.ResourceDictionariesChanged += new EventHandler(SeriesHostResourceDictionariesChanged);

                DispensedResourcesChanging();
            }
        }
Example #40
0
        public void UpdateGraph(CalculationOptionsMage calculationOptions)
        {
            DisplayCalculations calculations = calculationOptions.Calculations;

            Chart.Series.Clear();
            Chart.Axes.Clear();

            Chart.Text = null;

            if (calculationOptions.SequenceReconstruction == null)
            {
                Chart.Text = "Sequence reconstruction data is not available.";
            }
            else
            {
                List <EffectCooldown> cooldownList = calculationOptions.Calculations.CooldownList;

                /*brushSubPoints = new Brush[cooldownList.Count];
                 * colorSubPointsA = new Color[cooldownList.Count];
                 * colorSubPointsB = new Color[cooldownList.Count];
                 * for (int i = 0; i < cooldownList.Count; i++)
                 * {
                 *  Color baseColor = cooldownList[i].Color;
                 *  brushSubPoints[i] = new SolidBrush(Color.FromArgb(baseColor.R / 2, baseColor.G / 2, baseColor.B / 2));
                 *  colorSubPointsA[i] = Color.FromArgb(baseColor.A / 2, baseColor.R / 2, baseColor.G / 2, baseColor.B / 2);
                 *  colorSubPointsB[i] = Color.FromArgb(baseColor.A / 2, baseColor);
                 * }
                 * StringFormat formatSubPoint = new StringFormat();
                 * formatSubPoint.Alignment = StringAlignment.Center;
                 * formatSubPoint.LineAlignment = StringAlignment.Center;
                 *
                 * int maxWidth = 1;
                 * for (int i = 0; i < cooldownList.Count; i++)
                 * {
                 *  string subPointName = cooldownList[i].Name;
                 *  int widthSubPoint = (int)Math.Ceiling(g.MeasureString(subPointName, fontLegend).Width + 2f);
                 *  if (widthSubPoint > maxWidth) maxWidth = widthSubPoint;
                 * }
                 * for (int i = 0; i < cooldownList.Count; i++)
                 * {
                 *  string cooldownName = cooldownList[i].Name;
                 *  rectSubPoint = new Rectangle(2, legendY, maxWidth, 16);
                 *  blendSubPoint = new System.Drawing.Drawing2D.ColorBlend(3);
                 *  blendSubPoint.Colors = new Color[] { colorSubPointsA[i], colorSubPointsB[i], colorSubPointsA[i] };
                 *  blendSubPoint.Positions = new float[] { 0f, 0.5f, 1f };
                 *  brushSubPointFill = new System.Drawing.Drawing2D.LinearGradientBrush(rectSubPoint, colorSubPointsA[i], colorSubPointsB[i], 67f);
                 *  brushSubPointFill.InterpolationColors = blendSubPoint;
                 *
                 *  g.FillRectangle(brushSubPointFill, rectSubPoint);
                 *  g.DrawRectangle(new Pen(brushSubPointFill), rectSubPoint);
                 *  g.DrawRectangle(new Pen(brushSubPointFill), rectSubPoint);
                 *  g.DrawRectangle(new Pen(brushSubPointFill), rectSubPoint);
                 *
                 *  g.DrawString(cooldownName, fontLegend, brushSubPoints[i], rectSubPoint, formatSubPoint);
                 *  legendY += 16;
                 * }*/

                if (calculationOptions.AdviseAdvancedSolver)
                {
                    Chart.Text = "Sequence Reconstruction was not fully successful, it is recommended that you enable more options in advanced solver (segment cooldowns, integral mana consumables, advanced constraints options)!";
                }

                /*g.DrawLine(Pens.Aqua, new Point(maxWidth + 40, 10), new Point(maxWidth + 80, 10));
                 * g.DrawString("Mana", fontLegend, Brushes.Black, new Point(maxWidth + 90, 2));
                 * g.DrawLine(Pens.Red, new Point(maxWidth + 40, 26), new Point(maxWidth + 80, 26));
                 * g.DrawString("Dps", fontLegend, Brushes.Black, new Point(maxWidth + 90, 18));*/

                List <SequenceItem> sequence = calculationOptions.SequenceReconstruction.sequence;

                List <TimeData> manaList = new List <TimeData>();

                float    mana     = calculations.StartingMana;
                int      gemCount = 0;
                float    time     = 0;
                Color    manaFill = Color.FromArgb(50, 0, 0, 255);
                float    maxMana  = calculations.BaseStats.Mana;
                float    maxDps   = 100;
                DateTime baseTime = new DateTime(2000, 1, 1, 0, 0, 0);
                manaList.Add(new TimeData()
                {
                    Time = baseTime, Value = mana
                });
                for (int i = 0; i < sequence.Count; i++)
                {
                    int          index    = sequence[i].Index;
                    VariableType type     = sequence[i].VariableType;
                    float        duration = (float)sequence[i].Duration;
                    Cycle        cycle    = sequence[i].Cycle;
                    CastingState state    = sequence[i].CastingState;
                    if (cycle != null)
                    {
                        float dps = (float)cycle.GetDamagePerSecond(state.ManaAdeptBonus, 1);
                        if (dps > maxDps)
                        {
                            maxDps = dps;
                        }
                    }
                    float mps = (float)sequence[i].Mps;
                    if (sequence[i].IsManaPotionOrGem)
                    {
                        float value = duration;
                        duration = 0;
                        if (sequence[i].VariableType == VariableType.ManaGem)
                        {
                            mana += (float)((1 + calculations.BaseStats.BonusManaGem) * calculations.ManaGemValue * value);
                            gemCount++;
                        }
                        else if (sequence[i].VariableType == VariableType.ManaPotion)
                        {
                            mana += (float)((1 + calculations.BaseStats.BonusManaPotionEffectMultiplier) * calculations.ManaPotionValue * value);
                        }
                        if (mana < 0)
                        {
                            mana = 0;
                        }
                        if (mana > maxMana)
                        {
                            mana = maxMana;
                        }
                        manaList.Add(new TimeData()
                        {
                            Time = baseTime + TimeSpan.FromSeconds(time) + TimeSpan.FromTicks(1), Value = mana
                        });
                    }
                    else
                    {
                        /*if (sequence[i].IsEvocation)
                         * {
                         *  switch (sequence[i].VariableType)
                         *  {
                         *      case VariableType.Evocation:
                         *          mps = -(float)calculationOptions.Calculations.EvocationRegen;
                         *          break;
                         *      case VariableType.EvocationIV:
                         *          mps = -(float)calculationOptions.Calculations.EvocationRegenIV;
                         *          break;
                         *      case VariableType.EvocationHero:
                         *          mps = -(float)calculationOptions.Calculations.EvocationRegenHero;
                         *          break;
                         *      case VariableType.EvocationIVHero:
                         *          mps = -(float)calculationOptions.Calculations.EvocationRegenIVHero;
                         *          break;
                         *  }
                         * }*/
                        float partTime = duration;
                        if (mana - mps * duration < 0)
                        {
                            partTime = mana / mps;
                        }
                        else if (mana - mps * duration > maxMana)
                        {
                            partTime = (mana - maxMana) / mps;
                        }
                        mana -= mps * duration;
                        if (mana < 0)
                        {
                            mana = 0;
                        }
                        if (mana > maxMana)
                        {
                            mana = maxMana;
                        }
                        manaList.Add(new TimeData()
                        {
                            Time = baseTime + TimeSpan.FromSeconds(time + partTime), Value = mana
                        });
                        if (partTime < duration)
                        {
                            manaList.Add(new TimeData()
                            {
                                Time = baseTime + TimeSpan.FromSeconds(time + duration), Value = mana
                            });
                        }
                    }
                    time += duration;
                }

                Style dateTimeAxisLabelStyle = new Style(typeof(DateTimeAxisLabel));
                dateTimeAxisLabelStyle.Setters.Add(new Setter(DateTimeAxisLabel.MinutesIntervalStringFormatProperty, "{0:m:ss}"));
                dateTimeAxisLabelStyle.Setters.Add(new Setter(DateTimeAxisLabel.SecondsIntervalStringFormatProperty, "{0:m:ss}"));
                DateTimeAxis timeAxis = new DateTimeAxis()
                {
                    //Title = "Time",
                    Minimum        = baseTime,
                    Maximum        = baseTime + TimeSpan.FromSeconds(calculationOptions.FightDuration),
                    IntervalType   = DateTimeIntervalType.Seconds,
                    AxisLabelStyle = dateTimeAxisLabelStyle,
                    Orientation    = AxisOrientation.X,
                    ShowGridLines  = true,
                    Location       = AxisLocation.Top,
                };

                Style hiddenCategoryLabelStyle = new Style(typeof(AxisLabel));
                hiddenCategoryLabelStyle.Setters.Add(new Setter(NumericAxisLabel.VisibilityProperty, Visibility.Collapsed));

                CategoryAxis categoryAxis = new CategoryAxis()
                {
                    AxisLabelStyle     = hiddenCategoryLabelStyle,
                    Orientation        = AxisOrientation.Y,
                    MajorTickMarkStyle = null,
                };

                int barCount = 0;
                for (int cooldown = 0; cooldown < cooldownList.Count; cooldown++)
                {
                    List <TimeIntervalData> data = new List <TimeIntervalData>();
                    //blendSubPoint = new System.Drawing.Drawing2D.ColorBlend(3);
                    //blendSubPoint.Colors = new Color[] { colorSubPointsA[cooldown], colorSubPointsB[cooldown], colorSubPointsA[cooldown] };
                    //blendSubPoint.Positions = new float[] { 0f, 0.5f, 1f };
                    bool  on     = false;
                    float timeOn = 0.0f;
                    time = 0;
                    for (int i = 0; i < sequence.Count; i++)
                    {
                        float duration = (float)sequence[i].Duration;
                        if (sequence[i].IsManaPotionOrGem)
                        {
                            duration = 0;
                        }
                        if (on && !sequence[i].CastingState.EffectsActive(cooldownList[cooldown]) && !sequence[i].IsManaPotionOrGem)
                        {
                            on = false;
                            if (time > timeOn)
                            {
                                data.Add(new TimeIntervalData()
                                {
                                    Start = baseTime + TimeSpan.FromSeconds(timeOn), End = baseTime + TimeSpan.FromSeconds(time), Category = cooldownList[cooldown].Name
                                });
                            }
                        }
                        else if (!on && sequence[i].CastingState.EffectsActive(cooldownList[cooldown]))
                        {
                            on     = true;
                            timeOn = time;
                        }
                        time += duration;
                    }
                    if (on)
                    {
                        if (time - timeOn > 0)
                        {
                            data.Add(new TimeIntervalData()
                            {
                                Start = baseTime + TimeSpan.FromSeconds(timeOn), End = baseTime + TimeSpan.FromSeconds(time), Category = cooldownList[cooldown].Name
                            });
                        }
                    }
                    if (data.Count > 0)
                    {
                        barCount++;
                        Style timeIntervalStyle = new Style(typeof(TimeIntervalDataPoint));
                        timeIntervalStyle.Setters.Add(new Setter(TimeIntervalDataPoint.BackgroundProperty, new SolidColorBrush(cooldownList[cooldown].Color)));
                        Chart.Series.Add(new TimeIntervalSeries()
                        {
                            Title                = cooldownList[cooldown].Name,
                            ItemsSource          = data,
                            IndependentValuePath = "Category",
                            DependentValuePath   = "End",
                            StartTimePath        = "Start",
                            EndTimePath          = "End",
                            DataPointStyle       = timeIntervalStyle,
                            DependentRangeAxis   = timeAxis,
                            IndependentAxis      = categoryAxis
                        });
                    }
                }

                if (calculationOptions.DisplaySegmentCooldowns && calculationOptions.BossHandler)
                {
                    foreach (var buffState in calculationOptions.Character.BossOptions.BuffStates)
                    {
                        if (buffState.Chance > 0 && buffState.Stats.BonusDamageMultiplier > 0)
                        {
                            List <TimeIntervalData> data = new List <TimeIntervalData>();

                            foreach (var phase in buffState.PhaseTimes)
                            {
                                data.Add(new TimeIntervalData()
                                {
                                    Start = baseTime + TimeSpan.FromSeconds(phase.Value[0]), End = baseTime + TimeSpan.FromSeconds(phase.Value[1]), Category = buffState.Name
                                });
                            }
                            if (data.Count > 0)
                            {
                                barCount++;
                                Style timeIntervalStyle = new Style(typeof(TimeIntervalDataPoint));
                                timeIntervalStyle.Setters.Add(new Setter(TimeIntervalDataPoint.BackgroundProperty, new SolidColorBrush(Color.FromArgb(255, 0, 0, 0))));
                                Chart.Series.Add(new TimeIntervalSeries()
                                {
                                    Title                = buffState.Name,
                                    ItemsSource          = data,
                                    IndependentValuePath = "Category",
                                    DependentValuePath   = "End",
                                    StartTimePath        = "Start",
                                    EndTimePath          = "End",
                                    DataPointStyle       = timeIntervalStyle,
                                    DependentRangeAxis   = timeAxis,
                                    IndependentAxis      = categoryAxis
                                });
                            }
                        }
                    }
                }

                Style hiddenNumericLabelStyle = new Style(typeof(NumericAxisLabel));
                hiddenNumericLabelStyle.Setters.Add(new Setter(NumericAxisLabel.VisibilityProperty, Visibility.Collapsed));

                Chart.Series.Add(new AreaSeries()
                {
                    Title                = "Mana",
                    ItemsSource          = manaList,
                    IndependentValuePath = "Time",
                    DependentValuePath   = "Value",
                    DataPointStyle       = (Style)Resources["ManaStyle"],
                    Background           = new SolidColorBrush(Color.FromArgb(0xFF, 0x00, 0xFF, 0xFF)),
                    DependentRangeAxis   = new OffsetLinearAxis()
                    {
                        Minimum            = 0,
                        Offset             = barCount * 10.0,
                        Orientation        = AxisOrientation.Y,
                        AxisLabelStyle     = hiddenNumericLabelStyle,
                        MajorTickMarkStyle = null,
                        MinorTickMarkStyle = null,
                    },
                    IndependentAxis = timeAxis,
                    LegendItemStyle = null,
                });

                maxDps *= 1.1f;
                List <TimeData> list = new List <TimeData>();
                time = 0.0f;
                for (int i = 0; i < sequence.Count; i++)
                {
                    int          index    = sequence[i].Index;
                    VariableType type     = sequence[i].VariableType;
                    float        duration = (float)sequence[i].Duration;
                    Cycle        cycle    = sequence[i].Cycle;
                    CastingState state    = sequence[i].CastingState;
                    float        mps      = (float)sequence[i].Mps;
                    if (sequence[i].IsManaPotionOrGem)
                    {
                        duration = 0;
                    }
                    float dps = 0;
                    if (cycle != null)
                    {
                        dps = (float)cycle.DamagePerSecond;
                    }
                    if (duration > 0)
                    {
                        if (calculations.ManaAdeptBonus > 0)
                        {
                            for (int t = 1; t < 10; t++)
                            {
                                DateTime timet = baseTime + TimeSpan.FromSeconds(time + 0.1f * t * duration);
                                if (cycle != null)
                                {
                                    dps = (float)cycle.GetDamagePerSecond(calculations.ManaAdeptBonus, GetManaAtTime(manaList, timet) / maxMana);
                                }
                                // apply state multipliers
                                if (calculationOptions.DisplaySegmentCooldowns)
                                {
                                    dps *= calculationOptions.GetDamageMultiplier(time, time + duration);
                                }
                                list.Add(new TimeData()
                                {
                                    Time = timet, Value = dps
                                });
                            }
                        }
                        else
                        {
                            // apply state multipliers
                            if (calculationOptions.DisplaySegmentCooldowns)
                            {
                                dps *= calculationOptions.GetDamageMultiplier(time, time + duration);
                            }
                            list.Add(new TimeData()
                            {
                                Time = baseTime + TimeSpan.FromSeconds(time + 0.1f * duration), Value = dps
                            });
                            list.Add(new TimeData()
                            {
                                Time = baseTime + TimeSpan.FromSeconds(time + 0.9f * duration), Value = dps
                            });
                        }
                    }
                    time += duration;
                }

                Chart.Series.Add(new LineSeries()
                {
                    Title                = "Dps",
                    ItemsSource          = list,
                    IndependentValuePath = "Time",
                    DependentValuePath   = "Value",
                    DataPointStyle       = (Style)Resources["DpsStyle"],
                    DependentRangeAxis   = new OffsetLinearAxis()
                    {
                        Offset             = barCount * 10.0,
                        Minimum            = 0,
                        Orientation        = AxisOrientation.Y,
                        AxisLabelStyle     = hiddenNumericLabelStyle,
                        MajorTickMarkStyle = null,
                        MinorTickMarkStyle = null,
                    },
                    IndependentAxis = timeAxis,
                });

                if (zeroLineCanvas == null)
                {
                    zeroLineCanvas          = new ZeroLineCanvas(categoryAxis);
                    zeroLineCanvas.BarCount = barCount;
                }
                else
                {
                    zeroLineCanvas.BarCount = barCount;
                    zeroLineCanvas.Axis     = categoryAxis;
                }

                ISeriesHost host = (ISeriesHost)Chart;
                if (!host.BackgroundElements.Contains(zeroLineCanvas))
                {
                    host.BackgroundElements.Add(zeroLineCanvas);
                }
            }
        }