fix(charts): grouped bars emanate from the zero baseline#200
Merged
Conversation
Grouped (non-stacked) bars measured their height from the axis nice-floor, so on an axis that crossed zero a negative value rendered as a short upward column anchored at the floor — visually indistinguishable from a small positive — and positive bars overshot below zero. BarChartLayout now anchors both orientations to the zero baseline (clamped into the visible range via the new baselineValue helper): positive bars grow away from zero, negatives hang back across it, and value labels sit past the bar's far end. When zero is off-scale — an explicit non-zero valueAxis().min() or baselineAtZero(false) over a range that excludes zero — the baseline clamps to the nearest visible bound, so a deliberately zoomed axis still anchors its bars at the plot floor. Charts with positive data on a zero-based axis are byte-identical. Tests: ChartLayoutResolverTest rewrites the negative grouped case to assert the positive and negative bars meet at zero with heights proportional to |value|, and adds horizontal and positive-min-clamp cases; ChartShowcaseExample gains a mixed +/- net-cash-flow card. ./mvnw test -pl . green (1382).
The grouped-bar value-label arms had no test pairing ValueLabelMode.OUTSIDE with a negative value, so a label rendered on the wrong side of a negative bar would still pass. Add a vertical case (positive label above the top, negative below the bottom) and a horizontal case (positive past the right end, negative past the left end). Both fail if either negative arm is collapsed into its positive counterpart.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Grouped (non-stacked) bar charts measured each bar's height from the axis
nice-floor rather than zero. On an axis that crosses zero this rendered a
negative value as a short upward column anchored at the floor — visually
indistinguishable from a small positive — and let positive bars overshoot
below zero. Stacked bars were already pinned to zero, so the two groupings
disagreed.
What changed
BarChartLayoutnow anchors both orientations to the zero baseline, clampedinto the visible range by the new
baselineValue(NiceScale)helper(
max(niceMin, min(0, niceMax))):meet exactly at the zero line (heights proportional to
|value|).valueAxis().min(...)orbaselineAtZero(false)over a range that excludes zero — the baseline clampsto the nearest visible bound, so a deliberately zoomed axis still anchors its
bars at the plot floor (
explicitAxisBoundsAreHonoredkeeps passing).for negative.
are byte-identical.
ChartShowcaseExamplegains a mixed +/- net-cash-flow card; the committedassets/readme/chart-showcase.{pdf,png}previews are regenerated.Verification
./mvnw test -pl .→ BUILD SUCCESS, 1384 tests, 0 failures.ChartLayoutResolverTest: rewrote the negative-grouped case to assert barsmeet at zero with heights proportional to
|value|; added horizontal,positive-min-clamp, and OUTSIDE-label-side cases. Mutation-checked — copying
either negative value-label arm into its positive counterpart turns the new
label tests red.
Lane: canonical (
document.chart). No public API change (baselineValueispackage-private); japicmp unaffected.