/// <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); }
/// <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(); } } }
/// <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); } }
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; }
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); }
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); }
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; }
/// <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}"); }
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)); }
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)); }
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)); }
/// <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; } } }
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); } } }
/// <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}"); }
/// <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 }; } }
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; } } }
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; }
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)); }