/// <summary> /// Main flow of the render pipeline. /// </summary> /// <param name="sc"></param> /// <param name="ist"></param> /// <param name="recycler"></param> void ElementPipeline(SelectorContext sc, ItemState ist, Recycler <FrameworkElement, ItemState> recycler) { sc.SetTick(ist.index); var createit = true; if (LabelSelector != null) { var ox = LabelSelector.Convert(sc, typeof(bool), null, System.Globalization.CultureInfo.CurrentUICulture.Name); if (ox is bool bx) { createit = bx; } else { createit = ox != null; } } if (!createit) { return; } var current = recycler.Next(ist); if (current == null) { return; } if (!current.Item1) { // recycled: restore binding if we are using a LabelFormatter if (LabelFormatter != null && LabelStyle != null) { BindTo(this, nameof(LabelStyle), current.Item2, FrameworkElement.StyleProperty); } } // default text var text = ist.label == null ? String.Empty : (String.IsNullOrEmpty(LabelFormatString) ? ist.label.ToString() : String.Format(LabelFormatString, ist.label) ); if (LabelFormatter != null) { // call for Style, String override var format = LabelFormatter.Convert(sc, typeof(Tuple <Style, String>), null, System.Globalization.CultureInfo.CurrentUICulture.Name); if (format is Tuple <Style, String> ovx) { if (ovx.Item1 != null) { current.Item2.Style = ovx.Item1; } if (ovx.Item2 != null) { text = ovx.Item2; } } } // back-fill values var shim = new TextShim() { Text = text }; current.Item2.DataContext = shim; BindTo(shim, nameof(Visibility), current.Item2, UIElement.VisibilityProperty); ist.element = current.Item2; sc.Generated(ist); }
void DoTickLabels(IChartRenderContext icrc) { var tc = new TickCalculator(Minimum, Maximum); _trace.Verbose($"grid range:{tc.Range} tintv:{tc.TickInterval}"); // TODO may want to include the LabelStyle's padding if defined var padding = AxisLineThickness + 2 * AxisMargin; var tbr = new Recycler <FrameworkElement, ItemState>(TickLabels.Select(tl => tl.tb), (ist) => { var fe = CreateElement(ist); fe.Width = icrc.Area.Width - padding; if (fe is TextBlock tbb) { tbb.Padding = Side == Side.Right ? new Thickness(padding, 0, 0, 0) : new Thickness(0, 0, padding, 0); } return(fe); }); var itemstate = new List <ItemState>(); // materialize the ticks var lx = tc.GetTicks().ToArray(); var sc = new ValueAxisSelectorContext(this, icrc.Area, lx, tc.TickInterval); for (int ix = 0; ix < lx.Length; ix++) { //_trace.Verbose($"grid vx:{tick}"); sc.SetTick(ix); var createit = true; if (LabelSelector != null) { // ask the label selector var ox = LabelSelector.Convert(sc, typeof(bool), null, System.Globalization.CultureInfo.CurrentUICulture.Name); if (ox is bool bx) { createit = bx; } else { createit = ox != null; } } if (!createit) { continue; } var current = tbr.Next(null); var tick = lx[ix]; if (!current.Item1) { // restore binding if we are using a LabelFormatter if (LabelFormatter != null && LabelStyle != null) { BindTo(this, nameof(LabelStyle), current.Item2, FrameworkElement.StyleProperty); } } // default text var text = tick.Value.ToString(String.IsNullOrEmpty(LabelFormatString) ? "G" : LabelFormatString); if (LabelFormatter != null) { // call for Style, String override var format = LabelFormatter.Convert(sc, typeof(Tuple <Style, String>), null, System.Globalization.CultureInfo.CurrentUICulture.Name); if (format is Tuple <Style, String> ovx) { if (ovx.Item1 != null) { current.Item2.Style = ovx.Item1; } if (ovx.Item2 != null) { text = ovx.Item2; } } } var shim = new TextShim() { Text = text }; current.Item2.DataContext = shim; BindTo(shim, nameof(Visibility), current.Item2, UIElement.VisibilityProperty); var state = new ItemState() { tb = current.Item2, tick = tick }; state.SetLocation(icrc.Area.Left, tick.Value); sc.Generated(tick); itemstate.Add(state); } // VT and internal bookkeeping TickLabels = itemstate; Layer.Remove(tbr.Unused); Layer.Add(tbr.Created); foreach (var xx in TickLabels) { // force it to measure; needed for Transforms xx.tb.Measure(icrc.Dimensions); } }