Fix stacked category charts stacking Line/Scatter series and mixing axis groups (#906)#994
Merged
Merged
Conversation
…xis groups (#906) When a CategoryChart had setStacked(true) with a Line (or Scatter) series on a secondary Y-axis group, the line was stacked on top of the bars and both axis groups were ranged from the combined stack of every series. - Add CategorySeriesRenderStyle.isStackable() (false for Line/Scatter). - PlotContent_Category: only stackable render styles accumulate into the per-category stack offsets. - AxisPair: recompute stacked min/max per Y-axis group, summing only stackable series in that group, and only override when the group has stackable series (so a line-only group keeps its raw range). - Add BarChart13 demo reproducing the issue scenario. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes stacked CategoryChart behavior so stacking applies only to stackable category render styles and stacked-axis ranging is computed per Y-axis group, preventing secondary-axis Line/Scatter series from inflating or participating in the bar stack.
Changes:
- Add
CategorySeriesRenderStyle.isStackable()to distinguish stackable (Bar/Area/Stick/SteppedBar) vs non-stackable (Line/Scatter) styles. - Update
PlotContent_Categoryto apply stack offsets only when the series is both stacked and stackable. - Update
AxisPair.overrideMinMaxForYAxisto compute stacked min/max per Y-axis group using only stackable series in that group; add a demo reproducer.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| xchart/src/main/java/org/knowm/xchart/internal/chartpart/PlotContent_Category.java | Gates stacking offsets so Line/Scatter render at their own values. |
| xchart/src/main/java/org/knowm/xchart/internal/chartpart/AxisPair.java | Recomputes stacked Y-range per axis group using only stackable series for that group. |
| xchart/src/main/java/org/knowm/xchart/CategorySeries.java | Introduces CategorySeriesRenderStyle.isStackable() to formalize stacking participation. |
| xchart-demo/src/main/java/org/knowm/xchart/demo/charts/bar/BarChart13.java | Adds a demo for stacked bars + secondary-axis line scenario. |
Comment on lines
+51
to
+53
| chart.getStyler().setYAxisGroupPosition(1, YAxisPosition.Right); // secondary axis on the right | ||
| chart.getStyler().setYAxisMax(0, 200.0); // primary (bars) axis | ||
| chart.getStyler().setYAxisMax(1, 200.0); // secondary (line) axis |
Comment on lines
+307
to
313
| // If stacked, recalculate min and max from the per-category stack sums. Only series belonging | ||
| // to this Y-axis group are summed, and only stackable render styles (bar, stick, stepped bar, | ||
| // area) contribute — Line and Scatter series are drawn at their own values, so they neither | ||
| // stack nor inflate another axis group's range. Stacking otherwise sums the series values the | ||
| // same way regardless of style, and covers charts where individual series override the default | ||
| // render style. | ||
| if (categoryStyler.isStacked() && !chart.getSeriesMap().isEmpty()) { |
Comment on lines
+14
to
+18
| /** | ||
| * Stacked Bars with a Line on a secondary Y-Axis | ||
| * | ||
| * <p>Demonstrates the following: | ||
| * |
Comment on lines
+137
to
+140
| public boolean isStackable() { | ||
|
|
||
| return this != Line && this != Scatter; | ||
| } |
- CategorySeriesRenderStyle.isStackable() now enumerates the stackable styles (Bar/Area/Stick/SteppedBar) so any future render style defaults to non-stackable until intentionally opted in, instead of a Line/Scatter deny-list. - Add StackedSecondaryAxisTest covering the #906 scenario: stacked bars on group 0 + Line on group 1. Asserts each group's computed Y-axis range (primary 0..55 stack sums, secondary max 180 not inflated to 235), a line-only stacked group, and the single-group-bars baseline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Member
Author
|
Thanks for the review. Addressed in cdfa8b4:
Not changed, by maintainer decision:
|
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.
Fixes #906.
Problem
With
CategoryChart+setStacked(true), aLineseries assigned to a secondary Y-axis group was (1) drawn stacked on top of the bars, and (2) caused both axis groups to be ranged from the combined stack of all series (bars + line), so neither axis reflected only its own data.Two root causes:
PlotContent_Categoryapplied the stack offset to every series regardless of render style, soLine/Scatterparticipated in the bar stack.AxisPair.overrideMinMaxForYAxisrecomputed the stacked min/max by summing every series in the chart, ignoring bothgetYAxisGroup()and render style — even though it is called once per axis group.Fix
CategorySeriesRenderStyle.isStackable()—falseforLine/Scatter,trueforBar/Area/Stick/SteppedBar.PlotContent_Category: only stackable render styles accumulate into the per-category stack offsets (singleseriesStackedflag gates all stacking branches).AxisPair: recompute the stacked range per axis group, summing only stackable series belonging to that group; skip the override entirely when a group has no stackable series (a line-only group keeps its raw range), and keep any non-stacked series on the same group in view viaMath.max/Math.min.BarChart13demo reproducing the reporter's exact scenario.Behavior for single-group stacked charts is unchanged (verified: full
xchartsuite, 122 tests green).Result
Left axis ranges to the stacked bar sums (0–55), right axis to the line values (0–180), and the line is drawn at its own values instead of on top of the bars — matching the "Expected behavior" in the issue.
🤖 Generated with Claude Code