feat: rotate and wrap long axis tick labels - #141
Merged
Conversation
Axis tick labels were always drawn single-line and unrotated: an angle set on axis.text.x/y was silently ignored, and a long discrete label just overran its neighbour. - Honour el@angle on axis.text.x/y. `.draw_axis` reads the element's rotation, passes rot= to the label grob, and anchors it: an explicit hjust/vjust wins, otherwise the end of the run is pinned at the tick so the slant clears the panel. The gutter/row is measured from the rotated extent (the .track_w/.track_h rot path). - Wrap long x tick labels to their per-tick width. At layout time, when the page width is known and the panel is a plain null track, compute each tick's mm budget (panel width / break count) and pass it to the drawer as an absolute wrap width; the label row is measured through the same grob so the reserved height matches. Wrapping only engages when the widest label actually overruns its budget, so every plot whose labels already fit stays byte-identical. Rotated, aspect-locked, faceted-free-x, and composition paths fall back to single line. - .el_rot is now blank-safe (element_blank() carries no angle). Docs: NEWS, an effects-and-themes section, inst/examples/32-axis-labels.R, and tests in test-axis-text.R. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Closes the last WI-4 residual: wrapping/auto-fit for long axis tick labels (title/subtitle/caption already wrap). Two mechanisms, both driven from the theme.
Rotation
axis.text.x/axis.text.ynow honour anangle— previously a silent no-op..draw_axisreads the element's rotation, passesrot=to the label grob, and anchors it: an explicithjust/vjustwins, otherwise the end of the run is pinned at the tick so the slant clears the panel. The gutter/row is sized from the rotated extent (the existing.track_w/.track_hrotpath).Wrapping
Left horizontal, a long discrete label that would overrun its tick spacing wraps onto multiple lines and the label row grows to fit. At layout time — when the page width is known and the panel is a plain
nulltrack — each tick's mm budget (panel width ÷ break count) is computed viavellum::vl_convert()and handed to the drawer as an absolute wrap width; the row is measured through the same grob (.axis_text_grob) so the reserved height matches the drawn text.Byte-identical guarantee: wrapping only engages when the widest label actually overruns its budget, so every plot whose labels already fit is unchanged (all existing snapshots pass untouched). Rotated, aspect-locked (
coord_fixed/coord_sf/polar), faceted-free-x, marginal, and aligned-composition paths fall back to single line.Also:
.el_rot()is now blank-safe (element_blank()carries noangleproperty).Verification (WI-0)
Rendered and looked at 45°, 90°, and wrapped bar charts (labels rotate/wrap, clear the panel, row height reserved, no overlap); confirmed a rotated axis renders through
vellumwidget::as_widget();inst/examples/32-axis-labels.Rruns end to end.Tests:
test-axis-text.R(13). Full suite[ FAIL 0 | WARN 1 pre-existing | SKIP 0 | PASS 2873 ].🤖 Generated with Claude Code