Contains useful methods to apply to a chart
Ejemplo n.º 1
0
        //Lets define some default configurations, all charts should be able to detect any of these types and plot
        //them correclty

        static Charting()
        {
            Configurations = new Dictionary <Type, ConfigWrapper>();

            // Live.Charts can plot any type, yes even any class defined by yourself.
            // you just need to tell the charts how to plot it.
            // for example the Xy Mapper expouses an X and Y method,
            // for example .X( "mapper" ) asks for the function to get the value of a point in X, same with Y
            // live charts will inject a value and an index
            // the value will be of type <T> and the index is only the value of the point in the array.

            //the SeriesMappers class is just a reminder of the configurators that we have, it actually just
            //returns a new instance of the related configurator
            //a configurator is only a holder for the mappers.

            //lets configure <int>

            For <int>(Mappers.Xy <int>()
                      .X((value, index) => index)                               //use the index of the item in the array as X
                      .Y(value => value), SeriesOrientation.Horizontal);        //use the value (of type int int this case) as Y
            For <int>(Mappers.Xy <int>()
                      .X(value => value)                                        //use the value (int) as X
                      .Y((value, index) => index), SeriesOrientation.Vertical); //use the index of the item in the array as Y

            //ok now lets configure a class I defined, the ObservablePoint class, it only has 2 properties, X and Y

            For <ObservablePoint>(Mappers.Xy <ObservablePoint>() //in this case value is of type <ObservablePoint>
                                  .X(value => value.X)           //use the X property as X
                                  .Y(value => value.Y));         //use the Y property as Y

            //easy, now live charts know how to plot an ObservablePoint class and integers.

            //ok, now lets use another mapper, in this case we are going to configre a class for a PolarChart
            //polar chart requieres a Radius and an Angle instead of X and Y
            //so we will just pull the Mappers.Polar configurator
            //and specify which property to use as Radius and which one as Angle
            //in this case the PolarPoint class that I defined only contains these 2 properties.
            //so it is realy easy, now value is of type Polar point, becaus we said so when: SeriesMappers.Polar<PolarPoint>()

            For <PolarPoint>(Mappers.Polar <PolarPoint>()
                             .Radius(value => value.Radius) //use the radius property as radius for the plotting
                             .Angle(value => value.Angle)); //use the angle property as angle for the plotting

            //now a more complex situation
            //the OhclPoint is ready to plot financial points,
            //the financial series requires a Open, High, Low, and Close values at least
            //that is just by definition of a CandleStick series
            //so I created a OhclPoint class, and used the Financial mapper:
            //and again the OhclPoint class only contains those 4 properties
            //we just mapped them correctly and LiveCharts will know how to handle this class.

            //the DateTime for now its tricky....
            //I will explain better later if i do not find a better solution...

            For <OhlcPoint>(Mappers.Financial <OhlcPoint>()
                            .X((value, index) => index)
                            .Open(value => value.Open)
                            .High(value => value.High)
                            .Low(value => value.Low)
                            .Close(value => value.Close), SeriesOrientation.Horizontal);

            For <double>(Mappers.Xy <double>()
                         .X((value, index) => index)
                         .Y(value => value), SeriesOrientation.Horizontal);
            For <double>(Mappers.Xy <double>()
                         .X(value => value)
                         .Y((value, index) => index), SeriesOrientation.Vertical);

            For <decimal>(Mappers.Xy <decimal>()
                          .X((value, index) => index)
                          .Y(value => (double)value), SeriesOrientation.Horizontal);
            For <decimal>(Mappers.Xy <decimal>()
                          .X(value => (double)value)
                          .Y((value, index) => index), SeriesOrientation.Vertical);

            For <short>(Mappers.Xy <short>()
                        .X((value, index) => index)
                        .Y(value => value), SeriesOrientation.Horizontal);
            For <short>(Mappers.Xy <short>()
                        .X(value => value)
                        .Y((value, index) => index), SeriesOrientation.Vertical);

            For <float>(Mappers.Xy <float>()
                        .X((value, index) => index)
                        .Y(value => value), SeriesOrientation.Horizontal);
            For <float>(Mappers.Xy <float>()
                        .X(value => value)
                        .Y((value, index) => index), SeriesOrientation.Vertical);

            For <long>(Mappers.Xy <long>()
                       .X((value, index) => index)
                       .Y(value => value), SeriesOrientation.Horizontal);
            For <long>(Mappers.Xy <long>()
                       .X(value => value)
                       .Y((value, index) => index), SeriesOrientation.Vertical);

            For <BubblePoint>(Mappers.Bubble <BubblePoint>()
                              .X(value => value.X)
                              .Y(value => value.Y)
                              .Weight(value => value.Weight));

            For <ObservableValue>(Mappers.Xy <ObservableValue>()
                                  .X((value, index) => index)
                                  .Y(value => value.Value),
                                  SeriesOrientation.Horizontal);
            For <ObservableValue>(Mappers.Xy <ObservableValue>()
                                  .X(value => value.Value)
                                  .Y((value, index) => index),
                                  SeriesOrientation.Vertical);

            For <DatePoint>(Mappers.Xy <DatePoint>()
                            .X(x => ChartFunctions.ToChartDay(x.DateTime))
                            .Y(x => x.Value), SeriesOrientation.Horizontal);
            For <DatePoint>(Mappers.Xy <DatePoint>()
                            .Y(x => ChartFunctions.ToChartDay(x.DateTime))
                            .X(x => x.Value), SeriesOrientation.Vertical);
        }
Ejemplo n.º 2
0
        internal void UpdateSeparators(AxisOrientation source, ChartCore chart, int axisIndex)
        {
            foreach (var element in Cache.Values.ToArray())
            {
                if (element.GarbageCollectorIndex < GarbageCollectorIndex)
                {
                    element.State = SeparationState.Remove;
                    Cache.Remove(element.Key);
                }

                var toLine = ChartFunctions.ToPlotArea(element.Value, source, chart, axisIndex);

                var direction = source == AxisOrientation.X ? 1 : -1;

                toLine += EvaluatesUnitWidth ? direction * ChartFunctions.GetUnitWidth(source, chart, this) / 2 : 0;
                var toLabel = toLine + element.View.LabelModel.GetOffsetBySource(source);

                if (IsMerged)
                {
                    const double padding = 4;

                    if (source == AxisOrientation.Y)
                    {
                        if (toLabel + element.View.LabelModel.ActualHeight >
                            chart.DrawMargin.Top + chart.DrawMargin.Height)
                        {
                            toLabel -= element.View.LabelModel.ActualHeight + padding;
                        }
                    }
                    else
                    {
                        if (toLabel + element.View.LabelModel.ActualWidth >
                            chart.DrawMargin.Left + chart.DrawMargin.Width)
                        {
                            toLabel -= element.View.LabelModel.ActualWidth + padding;
                        }
                    }
                }

                var labelTab = Tab;
                labelTab += element.View.LabelModel.GetOffsetBySource(source.Invert());

                switch (element.State)
                {
                case SeparationState.Remove:
                    if (!chart.View.DisableAnimations && !View.DisableAnimations)
                    {
                        element.View.Move(chart, this, source, axisIndex, toLabel, toLine, labelTab);
                        element.View.FadeOutAndRemove(chart);
                    }
                    else
                    {
                        element.View.Remove(chart);
                    }
                    break;

                case SeparationState.Keep:
                    if (!chart.View.DisableAnimations && !View.DisableAnimations)
                    {
                        if (element.IsNew)
                        {
                            var toLinePrevious = FromPreviousState(element.Value, source, chart);
                            toLinePrevious += EvaluatesUnitWidth ? ChartFunctions.GetUnitWidth(source, chart, this) / 2 : 0;
                            var toLabelPrevious = toLinePrevious + element.View.LabelModel.GetOffsetBySource(source);
                            element.View.Place(chart, this, source, axisIndex, toLabelPrevious,
                                               toLinePrevious, labelTab);
                            element.View.FadeIn(this, chart);
                        }
                        element.View.Move(chart, this, source, axisIndex, toLabel, toLine, labelTab);
                    }
                    else
                    {
                        element.View.Place(chart, this, source, axisIndex, toLabel, toLine, labelTab);
                    }
                    break;

                case SeparationState.InitialAdd:
                    element.View.Place(chart, this, source, axisIndex, toLabel, toLine, labelTab);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            LastAxisMax  = TopLimit;
            LastAxisMin  = BotLimit;
            LastPlotArea = new CoreRectangle(chart.DrawMargin.Left, chart.DrawMargin.Top,
                                             chart.DrawMargin.Width, chart.DrawMargin.Height);
        }