/// <summary>
        /// rule coordinates (x:[0..1], y:axis)
        /// </summary>
        /// <param name="icrc">The context.</param>
        void IRequireTransforms.Transforms(IChartRenderContext icrc)
        {
            if (ValueAxis == null)
            {
                return;
            }
            var matx = MatrixSupport.TransformFor(icrc.SeriesArea, ValueAxis);

            _trace.Verbose($"transforms sy:{matx.M22:F3} matx:{matx} sa:{icrc.SeriesArea}");
            if (ClipToDataRegion)
            {
                Path.Clip = new RectangleGeometry()
                {
                    Rect = icrc.SeriesArea
                };
            }
            var vx     = ValueAxis.For(Value);
            var offset = matx.Transform(new Point(0, vx));

            Rule.SetValue(Canvas.TopProperty, offset.Y);
            matx.OffsetY   = 0;
            Rule.Transform = new MatrixTransform()
            {
                Matrix = matx
            };
        }
        void IRequireDataSourceUpdates.Add(IChartRenderContext icrc, int startAt, IList items)
        {
            if (CategoryAxis == null || ValueAxis == null)
            {
                return;
            }
            if (BindPaths == null || !BindPaths.IsValid)
            {
                return;
            }
            var recycler = new Recycler <Path, ItemState <Path> >(CreatePath);
            var reproc   = IncrementalAdd <ItemState <Path> >(startAt, items, ItemState, (ix, item) => {
                var valuey = BindPaths.ValueFor(item);
                // short-circuit if it's NaN
                if (double.IsNaN(valuey))
                {
                    return(null);
                }
                var valuex = BindPaths.CategoryFor(item, ix);
                // add requested item
                var istate = ElementPipeline(ix, valuex, valuey, item, recycler, BindPaths);
                return(istate);
            }, (rpc, istate) => {
                istate.Shift(rpc, BindPaths, CategoryAxis, null);
                // NO geometry update; done in later stages of render pipeline
            });

            ReconfigureLimits();
            // finish up
            Layer.Add(recycler.Created);
            Dirty = false;
            RaiseItemsUpdated(ItemUpdates, icrc, NotifyCollectionChangedAction.Add, startAt, reproc);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// X-coordinates	axis
        /// Y-coordinates	"px"
        /// Grid-coordinates (x:axis, y:[0..1])
        /// </summary>
        /// <param name="icrc"></param>
        void IRequireTransforms.Transforms(IChartRenderContext icrc)
        {
            var scale = Orientation == AxisOrientation.Horizontal ? icrc.Area.Width / Range : icrc.Area.Height / Range;
            var matx  = ProjectionForAxis(icrc.Area, scale);

            AxisGeometry.Transform = new MatrixTransform()
            {
                Matrix = matx
            };
            var matxv = ProjectionFor(icrc.Area);

            _trace.Verbose($"{Name}:{Orientation}:{Side} transforms sx:{scale:F3} matx:{matx} matxv:{matxv} a:{icrc.Area}");
            foreach (var state in AxisLabels)
            {
                if (state.element == null)
                {
                    continue;
                }
                var mapt = Orientation == AxisOrientation.Horizontal ? new Point(0, 1) : new Point(1, 0);
                var ptv  = matxv.Transform(mapt);
                _trace.Verbose($"{Name} mapped mapt:{mapt} ptv:{ptv}");
                state.scale   = scale;
                state.xorigin = ptv.X;
                state.yorigin = ptv.Y;
                var loc = state.UpdateLocation();
                _trace.Verbose($"{Name} el {state.element.ActualWidth}x{state.element.ActualHeight} v:{state.value} @:({loc.X},{loc.Y})");
                if (icrc.Type != RenderType.TransformsOnly)
                {
                    // doing render so (try to) trigger the SizeChanged handler
                    state.element.InvalidateMeasure();
                    state.element.InvalidateArrange();
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Grid-coordinates (x:[0..1], y:axis)
        /// </summary>
        /// <param name="icrc"></param>
        void IRequireTransforms.Transforms(IChartRenderContext icrc)
        {
            if (ValueAxis == null)
            {
                return;
            }
            var scalex = icrc.SeriesArea.Width;
            var scaley = icrc.SeriesArea.Height / ValueAxis.Range;
            var gmatx  = new Matrix(scalex, 0, 0, -scaley, 0, 0);
            var gmt    = new MatrixTransform()
            {
                Matrix = gmatx
            };

            _trace.Verbose($"transforms sx:{scalex:F3} sy:{scaley:F3} matx:{gmatx} a:{icrc.Area} sa:{icrc.SeriesArea}");
            foreach (var state in GridLines)
            {
                var adj = state.Element.ActualHeight / 2;
                var top = icrc.Area.Bottom - (state.Tick.Value - ValueAxis.Minimum) * scaley - adj;
                _trace.Verbose($"transforms tick:{state.Tick.Index} adj:{adj} top:{top}");
                state.Element.Data.Transform = gmt;
                state.SetLocation(icrc.SeriesArea.Left, top);
            }
            foreach (var state in MinorGridLines)
            {
                var adj = state.Element.ActualHeight / 2;
                var top = icrc.Area.Bottom - (state.Tick.Value - ValueAxis.Minimum) * scaley - adj;
                _trace.Verbose($"transforms subtick:{state.Tick.Index} adj:{adj} top:{top}");
                state.Element.Data.Transform = gmt;
                state.SetLocation(icrc.SeriesArea.Left, top);
            }
        }
Ejemplo n.º 5
0
        void IRequireDataSourceUpdates.Remove(IChartRenderContext icrc, int startAt, IList items)
        {
            var remove = new List <FrameworkElement>();

            for (int ix = 0; ix < items.Count; ix++)
            {
                // remove requested item
                if (AxisLabels[startAt].element != null)
                {
                    remove.Add(AxisLabels[startAt].element);
                }
                AxisLabels.RemoveAt(startAt);
            }
            // re-sequence remaining items
            for (int ix = startAt; ix < AxisLabels.Count; ix++)
            {
                AxisLabels[ix].index = ix;
                AxisLabels[ix].value = ix;
            }
            // configure axis limits; just based on count-of-elements
            UpdateLimits(0);
            UpdateLimits(AxisLabels.Count);
            // finish up
            Layer.Remove(remove);
            RebuildAxisGeometry();
            Dirty = false;
        }
Ejemplo n.º 6
0
        void IRequireDataSourceUpdates.Add(IChartRenderContext icrc, int startAt, IList items)
        {
            if (CategoryAxis == null || ValueAxis == null)
            {
                return;
            }
            if (BindPaths == null || !BindPaths.IsValid)
            {
                return;
            }
            var recycler = new Recycler <Path, SeriesItemState>(new List <Path>(), CreatePath);
            var reproc   = IncrementalAdd <SeriesItemState>(startAt, items, ItemState, (ix, item) => {
                var valuex = BindPaths.CategoryFor(item, ix);
                // add requested item
                var istate = ElementPipeline(ix, valuex, item, recycler, BindPaths);
                return(istate);
            }, (rpc, istate) => {
                istate.Shift(rpc, BindPaths, CategoryAxis, UpdateGeometry);
            });

            ReconfigureLimits();
            // finish up
            Layer.Add(recycler.Created);
            Dirty = false;
            RaiseItemsUpdated(ItemUpdates, icrc, NotifyCollectionChangedAction.Add, startAt, reproc);
        }
Ejemplo n.º 7
0
        ItemState CreateSubtick(IChartRenderContext icrc, Recycler <Path, ItemState> recycler, SubtickState tick)
        {
            if (tick.Value <= ValueAxis.Minimum || tick.Value >= ValueAxis.Maximum)
            {
                return(null);
            }
            var state = new ItemState()
            {
                Tick = tick
            };
            var current = recycler.Next(state);

            if (!current.Item1)
            {
                // restore binding
                if (MinorGridPathStyle != null)
                {
                    BindTo(this, nameof(MinorGridPathStyle), current.Item2, FrameworkElement.StyleProperty);
                    TransferFromStyle(current.Item2, MinorGridPathStyle);
                }
                else if (PathStyle != null)
                {
                    BindTo(this, nameof(PathStyle), current.Item2, FrameworkElement.StyleProperty);
                    TransferFromStyle(current.Item2, PathStyle);
                }
            }
            state.Element = current.Item2;
            ApplyBinding(this, nameof(Visibility), state.Element, UIElement.VisibilityProperty);
            state.SetLocation(icrc.Area.Left, tick.Value);
            return(state);
        }
Ejemplo n.º 8
0
        void IRequireDataSourceUpdates.Add(IChartRenderContext icrc, int startAt, IList items)
        {
            if (CategoryAxis == null || ValueAxis == null)
            {
                return;
            }
            if (BindPaths == null || !BindPaths.IsValid)
            {
                return;
            }
            var recycler = new Recycler <Path, ItemState <Path> >(new List <Path>(), CreatePath);
            var reproc   = IncrementalAdd <ItemState <Path> >(startAt, items, ItemState, (ix, item) => {
                var valueO = BindPaths.OpenFor(item);
                var valueH = BindPaths.HighFor(item);
                var valueL = BindPaths.LowFor(item);
                var valueC = BindPaths.CloseFor(item);
                // short-circuit if it's NaN
                if (double.IsNaN(valueO) || double.IsNaN(valueH) || double.IsNaN(valueL) || double.IsNaN(valueC))
                {
                    return(null);
                }
                var valuex = BindPaths.CategoryFor(item, ix);
                // add requested item
                var istate = ElementPipeline(ix, valuex, valueO, valueH, valueL, valueC, item, recycler, BindPaths.bvl);
                return(istate);
            }, (rpc, istate) => {
                istate.Shift(rpc, BindPaths, CategoryAxis, UpdateGeometry);
            });

            ReconfigureLimits();
            // finish up
            Layer.Add(recycler.Created);
            Dirty = false;
            RaiseItemsUpdated(ItemUpdates, icrc, NotifyCollectionChangedAction.Add, startAt, reproc);
        }
 /// <summary>
 /// Rule coordinates:
 ///		x: "normalized" [0..1] and scaled to the area-width
 ///		y: "axis" scale
 /// </summary>
 /// <param name="icrc">The context.</param>
 void IRequireRender.Render(IChartRenderContext icrc)
 {
     if (ValueAxis == null)
     {
         return;
     }
     _trace.Verbose($"{Name} val:{Value}");
     Dirty = false;
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Scale the NDC rectangle to the dimensions given.
        /// </summary>
        /// <param name="icrc">Context.</param>
        void IRequireTransforms.Transforms(IChartRenderContext icrc)
        {
            var matx = MatrixSupport.ProjectForQuadrant(4, icrc.SeriesArea);

            Rectangle.Transform = new MatrixTransform()
            {
                Matrix = matx
            };
        }
 /// <summary>
 /// Get the transform from <see cref="IProvideCustomTransform"/>, or based on axes, whichever hits first.
 /// If there's no <see cref="ValueAxis"/> return Identity matrix.
 /// </summary>
 /// <param name="icrc">Use for the area.</param>
 /// <returns>Matrix or DEFAULT.</returns>
 protected Matrix ObtainMatrix(IChartRenderContext icrc)
 {
     if (Source is IProvideCustomTransform ipct)
     {
         return(ipct.TransformFor(icrc.Area));
     }
     if (ValueAxis == null)
     {
         return(default);
        /// <summary>
        /// Adjust transforms for the various components.
        /// Geometry: scaled to actual values in cartesian coordinates as indicated by axes.
        /// </summary>
        /// <param name="icrc"></param>
        void IRequireTransforms.Transforms(IChartRenderContext icrc)
        {
            if (CategoryAxis == null || ValueAxis == null)
            {
                return;
            }
            if (ItemState.Count == 0)
            {
                return;
            }
            var mp = MatrixSupport.DataArea(CategoryAxis, ValueAxis, icrc.Area, 1);
            // cancel x-offset
            var proj2 = mp.Item2;

            proj2.OffsetX = 0;
            // get the local marker matrix
            var marker = MatrixSupport.LocalFor(mp.Item1, MarkerWidth, icrc.Area, -MarkerOrigin.X, -MarkerOrigin.Y);
            // get the offset matrix
            var mato = MatrixSupport.Multiply(mp.Item1, proj2);

            foreach (var state in ItemState)
            {
                // assemble Mk * M * P transform for this path
                var iworld = (state as IItemStateMatrix).World;
                var model  = MatrixSupport.Multiply(marker, iworld);
                var matx   = MatrixSupport.Multiply(model, proj2);
                var mt     = new MatrixTransform()
                {
                    Matrix = matx
                };
                if (state.Element.DataContext is GeometryWithOffsetShim <Geometry> gs)
                {
                    gs.GeometryTransform = mt;
                    var output = mato.Transform(new Point(state.XValue, 0));
                    gs.Offset = icrc.Area.Left + output.X;
                }
                else
                {
                    state.Element.Data.Transform = mt;
                }
                if (ClipToDataRegion)
                {
                    state.Element.Clip = new RectangleGeometry()
                    {
                        Rect = icrc.SeriesArea
                    };
                }
            }
            _trace.Verbose($"{Name} mat:{mp.Item1} clip:{icrc.SeriesArea}");
        }
Ejemplo n.º 13
0
        object IDataSourceRenderer.Preamble(IChartRenderContext icrc)
        {
            if (ValueAxis == null || CategoryAxis == null)
            {
                return(null);
            }
            if (BindPaths == null || !BindPaths.IsValid)
            {
                return(null);
            }
            ResetLimits();
            var paths    = ItemState.Select(ms => ms.Elements).SelectMany(el => el).Select(el => el.Item2);
            var recycler = new Recycler <Path, SeriesItemState>(paths, CreatePath);

            return(new State(new List <SeriesItemState>(), recycler, BindPaths));
        }
Ejemplo n.º 14
0
 object IDataSourceRenderer.Preamble(IChartRenderContext icrc)
 {
     if (ValueAxis == null || CategoryAxis == null)
     {
         return(null);
     }
     if (BindPaths == null || !BindPaths.IsValid)
     {
         return(null);
     }
     ResetLimits();
     return(new State()
     {
         evs = BindPaths
     });
 }
        object IDataSourceRenderer.Preamble(IChartRenderContext icrc)
        {
            if (CategoryAxis1 == null || CategoryAxis2 == null)
            {
                return(null);
            }
            if (BindPaths == null || !BindPaths.IsValid)
            {
                return(null);
            }
            ResetLimits();
            var paths    = ItemState.Select(ms => ms.Element).Where(el => el != null);
            var recycler = new Recycler <Path, ItemState <Path> >(paths, CreatePath);

            return(new RenderState_Heatmap <ItemState <Path>, Path>(new List <ItemState <Path> >(), recycler, BindPaths));
        }
Ejemplo n.º 16
0
        object IDataSourceRenderer.Preamble(IChartRenderContext icrc)
        {
            if (ValueAxis == null || CategoryAxis == null)
            {
                return(null);
            }
            if (BindPaths == null || !BindPaths.IsValid)
            {
                return(null);
            }
            ResetLimits();
            var paths    = ItemState.Select(ms => ms.Element);
            var recycler = new Recycler <Image, ItemState <Image> >(paths, CreateElement);

            return(new RenderState_ValueAndLabel <ItemState <Image>, Image>(new List <ItemState <Image> >(), recycler, BindPaths));
        }
Ejemplo n.º 17
0
        /// <summary>
        /// X-coordinates	"px"
        /// Y-coordinates	[0..1]
        /// </summary>
        /// <param name="icrc"></param>
        void IRequireTransforms.Transforms(IChartRenderContext icrc)
        {
            var scaley = icrc.Area.Height / Range;
            var matx   = new Matrix(1, 0, 0, -scaley, icrc.Area.Left + AxisMargin * (Side == Side.Right ? 1 : -1), icrc.Area.Top + Maximum * scaley);

            AxisGeometry.Transform = new MatrixTransform()
            {
                Matrix = matx
            };
            _trace.Verbose($"transforms sy:{scaley:F3} matx:{matx} a:{icrc.Area} sa:{icrc.SeriesArea}");
            foreach (var state in TickLabels)
            {
                var adj = state.tb.ActualHeight / 2;
                var top = icrc.Area.Bottom - (state.tick.Value - Minimum) * scaley - adj;
                state.SetLocation(icrc.Area.Left, top);
            }
        }
        void IRequireAfterAxesFinalized.AxesFinalized(IChartRenderContext icrc)
        {
            if (icrc.Type == RenderType.TransformsOnly)
            {
                return;
            }
            var mat   = MatrixSupport.DataArea(CategoryAxis1, CategoryAxis2, icrc.SeriesArea, 4);
            var matmp = MatrixSupport.Multiply(mat.Item1, mat.Item2);

            _trace.Verbose($"{Name} matmp:{matmp} clip:{icrc.SeriesArea}");
            var mt = new MatrixTransform()
            {
                Matrix = matmp
            };

            StyleGenerator?.Reset();
            foreach (var istate in ItemState)
            {
                if (istate.Element.DataContext is GeometryWith2OffsetShim <RectangleGeometry> gs)
                {
                    gs.GeometryTransform = mt;
                }
                else
                {
                    istate.Element.Data.Transform = mt;
                }
                if (StyleGenerator != null)
                {
                    var style = StyleGenerator.For(new Category2StyleContext(CategoryAxis1, CategoryAxis2, this, new double[3] {
                        istate.Value, istate.XValue, (istate as IProvideYValue).YValue
                    }));
                    if (style != null)
                    {
                        istate.Element.Style = style;
                    }
                    else
                    {
                        if (PathStyle != null)
                        {
                            BindTo(this, nameof(PathStyle), istate.Element, FrameworkElement.StyleProperty);
                        }
                    }
                }
            }
            StyleGenerator?.UpdateLegend(new Category2StyleContext(CategoryAxis1, CategoryAxis2, this, new double[0]));
        }
        object IDataSourceRenderer.Preamble(IChartRenderContext icrc)
        {
            if (String.IsNullOrEmpty(ValuePath))
            {
                return(null);
            }
            var by       = new BindingEvaluator(ValuePath);
            var paths    = ItemState.Select(ms => ms.Element);
            var recycler = new Recycler <Path, ItemState <Path> >(paths, CreatePath);

            Generator.Reset();
            return(new State(new List <ItemState <Path> >(), recycler,
                             null,
                             !String.IsNullOrEmpty(ValueLabelPath) ? new BindingEvaluator(ValueLabelPath) : null,
                             by,
                             !String.IsNullOrEmpty(ValueLabelPath) ? new BindingEvaluator(ValueLabelPath) : null
                             ));
        }
        void IRequireTransforms.Transforms(IChartRenderContext icrc)
        {
            if (ItemState.Count == 0)
            {
                return;
            }
            var matx = (this as IProvideCustomTransform).TransformFor(icrc.Area);

            foreach (var sis in ItemState)
            {
                if (sis.Element.DataContext is GeometryShim <PathGeometry> gs)
                {
                    gs.GeometryTransform = new MatrixTransform()
                    {
                        Matrix = matx
                    };
                }
            }
        }
        /// <summary>
        /// Adjust transforms for the various components.
        /// Geometry: scaled to actual values in cartesian coordinates as indicated by axes.
        /// </summary>
        /// <param name="icrc"></param>
        void IRequireTransforms.Transforms(IChartRenderContext icrc)
        {
            if (CategoryAxis1 == null || CategoryAxis2 == null)
            {
                return;
            }
            if (ItemState.Count == 0)
            {
                return;
            }
            // TODO quad depends on orientations of both axes this is assuming default orientations
            var mat   = MatrixSupport.DataArea(CategoryAxis1, CategoryAxis2, icrc.SeriesArea, 4);
            var matmp = MatrixSupport.Multiply(mat.Item1, mat.Item2);

            _trace.Verbose($"{Name} matmp:{matmp} clip:{icrc.SeriesArea}");
            var mt = new MatrixTransform()
            {
                Matrix = matmp
            };

            foreach (var state in ItemState)
            {
                if (state.Element.DataContext is GeometryWith2OffsetShim <RectangleGeometry> gs)
                {
                    gs.GeometryTransform = mt;
                    var output = matmp.Transform(new Point(state.XValue, (state as IProvideYValue).YValue));
                    gs.Offset  = output.X - icrc.SeriesArea.Left;
                    gs.Offset2 = output.Y - icrc.SeriesArea.Top;
                }
                else
                {
                    state.Element.Data.Transform = mt;
                }
                if (ClipToDataRegion)
                {
                    var cg = new RectangleGeometry()
                    {
                        Rect = icrc.SeriesArea
                    };
                    state.Element.Clip = cg;
                }
            }
        }
Ejemplo n.º 22
0
        void IRequireDataSourceUpdates.Remove(IChartRenderContext icrc, int startAt, IList items)
        {
            if (CategoryAxis == null || ValueAxis == null)
            {
                return;
            }
            if (BindPaths == null || !BindPaths.IsValid)
            {
                return;
            }
            var reproc = IncrementalRemove <ItemState <Path> >(startAt, items, ItemState, istate => istate.Element != null, (rpc, istate) => {
                istate.Shift(-rpc, BindPaths, CategoryAxis, UpdateGeometry);
            });

            ReconfigureLimits();
            // finish up
            Layer.Remove(reproc.Select(xx => xx.Element));
            Dirty = false;
            RaiseItemsUpdated(ItemUpdates, icrc, NotifyCollectionChangedAction.Remove, startAt, reproc);
        }
        void IRequireAfterAxesFinalized.AxesFinalized(IChartRenderContext icrc)
        {
            if (CategoryAxis == null || ValueAxis == null)
            {
                return;
            }
            if (ItemState.Count == 0)
            {
                return;
            }
            var world = MatrixSupport.ModelFor(CategoryAxis, ValueAxis);

            foreach (var state in ItemState)
            {
                if (state is IItemStateMatrix ism)
                {
                    ism.World = MatrixSupport.Translate(world, state.XOffset, state.Value);
                }
            }
        }
Ejemplo n.º 24
0
        /// <summary>
        /// Adjust transforms for the various components.
        /// Geometry: scaled to actual values in cartesian coordinates as indicated by axes.
        /// </summary>
        /// <param name="icrc"></param>
        void IRequireTransforms.Transforms(IChartRenderContext icrc)
        {
            if (CategoryAxis == null || ValueAxis == null)
            {
                return;
            }
            if (ItemState.Count == 0)
            {
                return;
            }
            var mp = MatrixSupport.DataArea(CategoryAxis, ValueAxis, icrc.Area, 1);
            // get the offset matrix
            var mato = MatrixSupport.Multiply(mp.Item1, mp.Item2);
            // TODO preserve aspect ratio of image; will require ImageOpened evh
            var dimx = MarkerWidth * mato.M11;

            _trace.Verbose($"dimx {dimx}");
            foreach (var state in ItemState)
            {
                if (state.Element.DataContext is ImageSourceShim iss)
                {
                    var output = mato.Transform(new Point(state.XValue + MarkerOffset, state.Value));
                    _trace.Verbose($"output {output.X:F1},{output.Y:F1}  value {state.XValue},{state.Value}  image {state.Element.ActualWidth:F1}x{state.Element.ActualHeight:F1}");
                    var hw = dimx * MarkerOrigin.X;
                    var hh = dimx * MarkerOrigin.Y;
                    // these have bindings so effect is immediate
                    iss.OffsetX = output.X - hw;
                    iss.OffsetY = output.Y - hh;
                    iss.Width   = dimx;
                    iss.Height  = dimx;
                }
                if (ClipToDataRegion)
                {
                    state.Element.Clip = new RectangleGeometry()
                    {
                        Rect = icrc.SeriesArea
                    };
                }
            }
            _trace.Verbose($"{Name} mat:{mp.Item1} clip:{icrc.SeriesArea}");
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Adjust transforms for the various components.
        /// Geometry: scaled to actual values in cartesian coordinates as indicated by axes.
        /// </summary>
        /// <param name="icrc"></param>
        void IRequireTransforms.Transforms(IChartRenderContext icrc)
        {
            if (CategoryAxis == null || ValueAxis == null)
            {
                return;
            }
            var matx = MatrixSupport.TransformFor(icrc.Area, CategoryAxis, ValueAxis);

            _trace.Verbose($"{Name} mat:{matx} clip:{icrc.SeriesArea}");
            Geometry.Transform = new MatrixTransform()
            {
                Matrix = matx
            };
            if (ClipToDataRegion)
            {
                Segments.Clip = new RectangleGeometry()
                {
                    Rect = icrc.SeriesArea
                };
            }
        }
Ejemplo n.º 26
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>
        /// Adjust transforms for the various components.
        /// Geometry: scaled to actual values in cartesian coordinates as indicated by axes.
        /// </summary>
        /// <param name="icrc"></param>
        void IRequireTransforms.Transforms(IChartRenderContext icrc)
        {
            if (CategoryAxis == null || ValueAxis == null)
            {
                return;
            }
            if (ItemState.Count == 0)
            {
                return;
            }
            var matx = MatrixSupport.TransformForOffsetX(icrc.Area, CategoryAxis, ValueAxis);

            _trace.Verbose($"{Name} mat:{matx} clip:{icrc.SeriesArea}");
            var mt = new MatrixTransform()
            {
                Matrix = matx
            };

            foreach (var state in ItemState)
            {
                if (state.Element.DataContext is GeometryWithOffsetShim <RectangleGeometry> gs)
                {
                    gs.GeometryTransform = mt;
                    var output = matx.Transform(new Point(state.XValue, 0));
                    gs.Offset = icrc.Area.Left + output.X;
                }
                else
                {
                    state.Element.Data.Transform = mt;
                }
                if (ClipToDataRegion)
                {
                    var cg = new RectangleGeometry()
                    {
                        Rect = icrc.SeriesArea
                    };
                    state.Element.Clip = cg;
                }
            }
        }
Ejemplo n.º 28
0
        void IRequireDataSourceUpdates.Remove(IChartRenderContext icrc, int startAt, IList items)
        {
            if (CategoryAxis == null || ValueAxis == null)
            {
                return;
            }
            if (BindPaths == null || !BindPaths.IsValid)
            {
                return;
            }
            var reproc = IncrementalRemove <SeriesItemState>(startAt, items, ItemState, null, (rpc, istate) => {
                istate.Shift(-rpc, BindPaths, CategoryAxis, UpdateGeometry);
            });

            ReconfigureLimits();
            // finish up
            var paths = reproc.Select(ms => ms.Elements).SelectMany(el => el).Select(el => el.Item2);

            Layer.Remove(paths);
            Dirty = false;
            RaiseItemsUpdated(ItemUpdates, icrc, NotifyCollectionChangedAction.Remove, startAt, reproc);
        }
        /// <summary>
        /// Rule coordinates:
        ///		x: "normalized" [0..1] and scaled to the area-width
        ///		y: "axis" scale
        /// </summary>
        /// <param name="icrc">The context.</param>
        void IRequireRender.Render(IChartRenderContext icrc)
        {
            if (ValueAxis == null)
            {
                return;
            }
            _trace.Verbose($"{Name} max:{Value1} min:{Value2}");
            var vmin = ValueAxis.For(Value2);
            var vmax = ValueAxis.For(Value1);
            var mmin = DoMinMax ? Math.Min(vmin, vmax) : vmin;
            var mmax = DoMinMax ? Math.Max(vmin, vmax) : vmax;

#if false
            Value1Rule.StartPoint = new Point(0, mmin);
            Value1Rule.EndPoint   = new Point(1, mmin);
            Value2Rule.StartPoint = new Point(0, mmax);
            Value2Rule.EndPoint   = new Point(1, mmax);
            Band.Rect             = new Rect(Value1Rule.StartPoint, Value2Rule.EndPoint);
#else
            Band.Rect = new Rect(new Point(0, 0), new Point(1, mmax - mmin));
#endif
            Dirty = false;
        }
Ejemplo n.º 30
0
        object IDataSourceRenderer.Preamble(IChartRenderContext icrc)
        {
            if (Theme?.TextBlockTemplate == null)
            {
                // already reported an error so this should be no surprise
                return(null);
            }
            if (String.IsNullOrEmpty(LabelPath))
            {
                return(null);
            }
            var bl = new BindingEvaluator(LabelPath);

            if (bl == null)
            {
                return(null);
            }
            var recycler = new Recycler <FrameworkElement, ItemState>(AxisLabels.Where(tl => tl.element != null).Select(tl => tl.element), CreateElement);

            ResetLimits();
            var widx = LabelStyle?.Find(FrameworkElement.WidthProperty);

            return(new State(new List <ItemState>(), recycler, icrc, widx == null, bl));
        }