Пример #1
0
        /// <summary>
        /// Use the <see cref="bx"/> evaluator to return the x-axis value, or index if it is NULL.
        /// </summary>
        /// <param name="ox">Object to evaluate.</param>
        /// <param name="index">Index value if <see cref="bx"/> is NULL.</param>
        /// <returns></returns>
        public double CategoryFor(object ox, int index)
        {
            // TODO this is coming back int from model object
            var valuex = bx != null ? (double)bx.For(ox) : index;

            return(valuex);
        }
        /// <summary>
        /// Core element processing.
        /// The <see cref="RectangleGeometry"/> inside the <see cref="Path"/> is now location-invariant wrt x-axis.
        /// This means that during incremental updates, no re-calculation is required, only adjusting the <see cref="Canvas.LeftProperty"/>.
        /// </summary>
        /// <param name="index">Data index.</param>
        /// <param name="valuec1">C1 (x-axis) index.</param>
        /// <param name="valuec2">C2 (y-axis) index.</param>
        /// <param name="value">Cell value.</param>
        /// <param name="item"></param>
        /// <param name="recycler"></param>
        /// <param name="byl"></param>
        /// <returns></returns>
        ItemState <Path> ElementPipeline(int index, int valuec1, int valuec2, double value, object item, Recycler <Path, ItemState <Path> > recycler, BindingEvaluator byl)
        {
            var path = recycler.Next(null);

            if (path == null)
            {
                return(null);
            }
            var shim = new GeometryWith2OffsetShim <RectangleGeometry>()
            {
                // MUST use invariant geometry here so it can translate.
                PathData = new RectangleGeometry()
                {
                    Rect = new Rect(new Point(0, 0), new Point(1, 1))
                }
            };

            path.Item2.DataContext = shim;
            // connect the shim to template root element's Visibility
            BindTo(shim, nameof(shim.Visibility), path.Item2, UIElement.VisibilityProperty);
            BindTo(shim, nameof(shim.Offset), path.Item2, Canvas.LeftProperty);
            BindTo(shim, nameof(shim.Offset2), path.Item2, Canvas.TopProperty);
            if (byl == null)
            {
                return(new SeriesItemState_Double(index, valuec1, 0, valuec2, value, path.Item2));
            }
            else
            {
                var cs = byl.For(item);
                return(new SeriesItemState_Custom(index, valuec1, 0, valuec2, value, cs, path.Item2));
            }
        }
Пример #3
0
        /// <summary>
        /// Take the actual value from the source and coerce it to the double type, until we get full polymorphism on the y-value.
        /// <para/>
        /// Currently handles <see cref="double"/>, <see cref="int"/>, <see cref="short"/>,and Nullable{double,int,short} types.
        /// </summary>
        /// <param name="item">Source instance.</param>
        /// <param name="be">Evaluator or NULL.  If NULL returns <see cref="Double.NaN"/>.</param>
        /// <returns>Coerced value or THROWs.</returns>
        public static double CoerceValue(object item, BindingEvaluator be)
        {
            if (be == null)
            {
                return(double.NaN);
            }
            var ox = be.For(item);

            if (ox is short sx)
            {
                return((double)sx);
            }
            if (ox is int ix)
            {
                return((double)ix);
            }
            if (ox is long lx)
            {
                return((double)lx);
            }
            if (ox is DateTime dt)
            {
                return(dt == default(DateTime) ? double.NaN : (double)dt.Ticks);
            }
            // now nullable types
            if (ox is double?)
            {
                double?ddx = (double?)ox;
                return(ddx ?? double.NaN);
            }
            if (ox is int?)
            {
                int?ddx = (int?)ox;
                return(ddx ?? double.NaN);
            }
            if (ox is short?)
            {
                short?ddx = (short?)ox;
                return(ddx ?? double.NaN);
            }
            return((double)ox);
        }
Пример #4
0
        void IRequireDataSourceUpdates.Add(IChartRenderContext icrc, int startAt, IList items)
        {
            // mimic the DSRP sequence
            var widx = LabelStyle?.Find(FrameworkElement.WidthProperty);
            var bl   = new BindingEvaluator(LabelPath);
            // keep a separate list; easier at the end
            var reproc = new List <ItemState>();

            for (int ix = 0; ix < items.Count; ix++)
            {
                // add requested item
                var label  = bl.For(items[ix]);
                var istate = makeit(startAt + ix, label, widx == null);
                AxisLabels.Insert(startAt + ix, istate);
                reproc.Add(istate);
            }
            // re-sequence remaining items
            for (int ix = startAt + reproc.Count; ix < AxisLabels.Count; ix++)
            {
                AxisLabels[ix].index = ix;
                AxisLabels[ix].value = ix;
            }
            // render new items
            // run the element pipeline on the added items
            var recycler = new Recycler <FrameworkElement, ItemState>(CreateElement);
            var labels   = new List <ICategoryLabelState>(AxisLabels);
            var sc       = new SelectorContext(this, icrc.SeriesArea, labels);

            foreach (var istate in reproc)
            {
                ElementPipeline(sc, istate, recycler);
            }
            // configure axis limits; just based on count-of-elements
            UpdateLimits(0);
            UpdateLimits(AxisLabels.Count);
            // finish up
            Layer.Add(recycler.Created);
            RebuildAxisGeometry();
            Dirty = false;
        }
        /// <summary>
        /// Core element processing.
        /// The <see cref="RectangleGeometry"/> inside the <see cref="Path"/> is now location-invariant wrt x-axis.
        /// This means that during incremental updates, no re-calculation is required, only adjusting the <see cref="Canvas.LeftProperty"/>.
        /// </summary>
        /// <param name="index"></param>
        /// <param name="valuex"></param>
        /// <param name="valuey"></param>
        /// <param name="item"></param>
        /// <param name="recycler"></param>
        /// <param name="byl"></param>
        /// <returns></returns>
        ItemState <Path> ElementPipeline(int index, double valuex, double valuey, object item, Recycler <Path, ItemState <Path> > recycler, BindingEvaluator byl)
        {
            var y1      = ValueAxis.For(valuey);
            var y2      = ValueAxis.For(0);
            var topy    = Math.Max(y1, y2);
            var bottomy = Math.Min(y1, y2);
            var leftx   = CategoryAxis.For(valuex);
            var barx    = BarOffset;
            var rightx  = barx + BarWidth;

            _trace.Verbose($"{Name}[{index}] {valuey} ({barx},{topy}) ({rightx},{bottomy})");
            var path = recycler.Next(null);

            if (path == null)
            {
                return(null);
            }
            var shim = new GeometryWithOffsetShim <RectangleGeometry>()
            {
                PathData = new RectangleGeometry()
                {
                    Rect = new Rect(new Point(barx, topy), new Point(rightx, bottomy))
                }
            };

            path.Item2.DataContext = shim;
            // connect the shim to template root element's Visibility
            BindTo(shim, nameof(shim.Visibility), path.Item2, UIElement.VisibilityProperty);
            BindTo(shim, nameof(shim.Offset), path.Item2, Canvas.LeftProperty);
            if (byl == null)
            {
                return(new SeriesItemState_Double(index, leftx, BarOffset, y1, path.Item2));
            }
            else
            {
                var cs = byl.For(item);
                return(new SeriesItemState_Custom(index, leftx, BarOffset, y1, cs, path.Item2));
            }
        }
Пример #6
0
 /// <summary>
 /// Force (non-NULL) results to be a <see cref="String"/>.
 /// <para/>
 /// If <see cref="String.Empty"/>, <see cref="byl"/> was NULL. If NULL, the evaluation result was NULL.
 /// </summary>
 /// <param name="item">Source instance.</param>
 /// <returns>Evaluated string, NULL, or <see cref="String.Empty"/>.</returns>
 public String LabelStringFor(object item)
 {
     return(byl != null?byl.For(item)?.ToString() : String.Empty);
 }
Пример #7
0
 /// <summary>
 /// Evaluate the label or NULL.
 /// <para/>
 /// If NULL, either <see cref="byl"/> was NULL, OR the evaluation result was NULL.
 /// </summary>
 /// <param name="item">Source instance.</param>
 /// <returns>Evaluated value or NULL.</returns>
 public object LabelFor(object item)
 {
     return(byl?.For(item));
 }
        public int Category2For(object ox)
        {
            var valuex = (int)bc2.For(ox);

            return(valuex);
        }
Пример #9
0
        ItemState <Path> ElementPipeline(
            int index, double valuex, double valueO, double valueH, double valueL, double valueC,
            object item, Recycler <Path, ItemState <Path> > recycler, BindingEvaluator bvl
            )
        {
            // map through axes
            var y1      = ValueAxis.For(valueO);
            var y2      = ValueAxis.For(valueC);
            var y3      = ValueAxis.For(valueH);
            var y4      = ValueAxis.For(valueL);
            var leftx   = CategoryAxis.For(valuex);
            var offsetx = BarOffset;
            var rightx  = offsetx + BarWidth;
            // force them to be a min/max
            var topy    = Math.Max(y1, y2);
            var bottomy = Math.Min(y1, y2);
            var highy   = Math.Max(y3, y4);
            var lowy    = Math.Min(y3, y4);

            _trace.Verbose($"{Name}[{index}] {valueO}/{valueH}/{valueL}/{valueC} ({offsetx},{topy}) ({rightx},{bottomy})");
            // create geometry
            var path = recycler.Next(null);

            if (path == null)
            {
                return(null);
            }
            var pg = new PathGeometry();
            // body (open/close)
            var body = PathHelper.Rectangle(offsetx, topy, rightx, bottomy);

            pg.Figures.Add(body);
            // upper shadow (high)
            var centerx = offsetx + (rightx - offsetx) / 2;
            var upper   = PathHelper.Line(centerx, topy, centerx, highy);

            pg.Figures.Add(upper);
            // lower shadow (low)
            var lower = PathHelper.Line(centerx, bottomy, centerx, lowy);

            pg.Figures.Add(lower);
            var shim = new GeometryWithOffsetShim <PathGeometry>()
            {
                PathData = pg
            };

            path.Item2.DataContext = shim;
            // establish the style for "forward" or "reverse" polarity
            BindTo(this, valueO < valueC ? nameof(PathStyle) : nameof(ReversePathStyle), path.Item2, Path.StyleProperty);
            // bind offset
            BindTo(shim, nameof(shim.Offset), path.Item2, Canvas.LeftProperty);
            var figs = new Tuple <double, PathFigure> [4];

            figs[0] = new Tuple <double, PathFigure>(y1, body);
            figs[1] = new Tuple <double, PathFigure>(y2, body);
            figs[2] = new Tuple <double, PathFigure>(y3, upper);
            figs[3] = new Tuple <double, PathFigure>(y4, lower);
            if (bvl == null)
            {
                return(new SeriesItemState(index, leftx, BarOffset, y1, path.Item2, figs));
            }
            else
            {
                var cs = bvl.For(item);
                return(new SeriesItemState_Custom(index, leftx, BarOffset, y1, cs, path.Item2, figs));
            }
        }
Пример #10
0
            /// <summary>
            /// Use the <see cref="bx"/> evaluator to return the x-axis value, or index if it is NULL.
            /// </summary>
            /// <param name="ox">Object to evaluate.</param>
            /// <param name="index">Index value if <see cref="bx"/> is NULL.</param>
            /// <returns></returns>
            public double CategoryFor(object ox, int index)
            {
                var valuex = bx != null ? (double)bx.For(ox) : index;

                return(valuex);
            }