-
Notifications
You must be signed in to change notification settings - Fork 20
Issue #303 margin adjustment for multi-line labels and titles #549
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,9 @@ draw_title = function(main, sub, xlab, ylab, legend, legend_args, opar) { | |
| if (is.null(line_main)) line_main = par("mgp")[3] + 1.7 - .1 | ||
| line_main = line_main + 1.2 | ||
| } | ||
| } | ||
|
|
||
| if (!is.null(sub)) { | ||
| if (isTRUE(get_tpar("side.sub", 1) == 3)) { | ||
| line_sub = get_tpar("line.sub", 1.7) | ||
| } else { | ||
|
|
@@ -49,13 +52,33 @@ draw_title = function(main, sub, xlab, ylab, legend, legend_args, opar) { | |
| } | ||
|
|
||
| if (!is.null(main)) { | ||
| main_lines = text_line_count(main) | ||
| if (main_lines > 1L) { | ||
| # Keep line 1 aligned with single-line titles by shifting the centered | ||
| # multi-line block downward by half its extra line height. | ||
| if (is.null(line_main)) line_main = par("mgp")[3] + 1.1 | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we be using get_tpar() here to get theme-specific settings instead of par()? |
||
| line_main = line_main - (main_lines - 1) / 2 | ||
| } | ||
| adj_main = get_tpar(c("adj.main", "adj"), 3) | ||
| ylab_lines = text_line_count(ylab) | ||
| # dynmar can expand left margin for multi-line ylab after title draw; apply | ||
| # a compensating right shift so main stays aligned with the plot box. | ||
| if (ylab_lines > 1L && isTRUE(get_tpar("dynmar", FALSE))) { | ||
| delta_in = (ylab_lines - 1) * par("csi") * par("cex.lab") | ||
| if (is.finite(par("pin")[1]) && par("pin")[1] > 0) { | ||
| multi_panel = prod(par("mfrow")) > 1 || prod(par("mfcol")) > 1 | ||
| panel_boost = if (isTRUE(multi_panel)) 2 else 1 | ||
| adj_main = adj_main + panel_boost * (delta_in / par("pin")[1]) | ||
| } | ||
| adj_main = min(1, max(0, adj_main)) | ||
| } | ||
| args = list( | ||
| main = main, | ||
| line = line_main, | ||
| cex.main = get_tpar("cex.main", 1.4), | ||
| col.main = get_tpar("col.main", "black"), | ||
| font.main = get_tpar("font.main", 2), | ||
| adj = get_tpar(c("adj.main", "adj"), 3)) | ||
| adj = adj_main) | ||
| args = Filter(function(x) !is.null(x), args) | ||
| do.call(title, args) | ||
| } | ||
|
|
@@ -65,7 +88,23 @@ draw_title = function(main, sub, xlab, ylab, legend, legend_args, opar) { | |
| args = list(xlab = xlab) | ||
| args[["adj"]] = get_tpar(c("adj.xlab", "adj")) | ||
| do.call(title, args) | ||
|
|
||
| args = list(ylab = ylab) | ||
| ylab_lines = text_line_count(ylab) | ||
| if (ylab_lines > 1L) { | ||
| # Keep multi-line ylab centered around the default label line so outer | ||
| # lines do not get pushed off-device in tighter layouts (e.g., mfrow 2x2). | ||
| line_ylab = par("mgp")[1] - (ylab_lines - 1) | ||
| cex_ylab = get_tpar(c("cex.ylab", "cex.lab"), 1) | ||
| csi = par("csi") | ||
| left_margin_in = par("mai")[2] | ||
| # Keep roughly one glyph-width of room from the left device edge to avoid | ||
| # clipping of the outermost ylab line on compact multi-panel layouts. | ||
| edge_pad_in = 0.75 * csi * cex_ylab | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be misunderstanding, but why calculate in inches (csi) instead of user coords (cxy)? Where does 0.75 come from? Is it borrowed from one of the (hard-coded) based plot scaling factors? Or, just eye-balling? |
||
| max_line = (left_margin_in - edge_pad_in) / csi | ||
| line_ylab = min(line_ylab, max_line) | ||
| args[["line"]] = max(0, line_ylab) | ||
| } | ||
| args[["adj"]] = get_tpar(c("adj.ylab", "adj")) | ||
| do.call(title, args) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these par() cases be get_tpar() instead?