diff --git a/R/misc_v3_comp.R b/R/misc_v3_comp.R deleted file mode 100644 index 711dd708..00000000 --- a/R/misc_v3_comp.R +++ /dev/null @@ -1,53 +0,0 @@ -v3_only = function(fun) { - setdiff(funs_v3[[fun]], funs_v4[[fun]]) -} - -v3_start_message = function() { - if (!.TMAP$v3) { - message("tmap v3 code detected. Specific changes listed below.") - .TMAP$v3 = TRUE - } - invisible(NULL) -} - -v3_reset_flag = function() { - .TMAP$v3 = FALSE - invisible(NULL) -} - - -v3_instead = function(args_called, old, new, fun, extra_called = character()) { - args = args_called$args - called = args_called$called - - if (old %in% called) { - args[[new]] = args[[old]] - args[[old]] = NULL - - # may be needed to trigger something (e.g. "shape" to use symbols instead of dots) - if (length(extra_called)) { - called = unique(c(called, extra_called)) - } - message(paste0(fun, " (v3->v4): use '", new, "' instead of '", old, "'")) - } - list(args = args, called = called) -} - -v3_instead_value = function(args_called, old, new, fun, value_old, value_new) { - args = args_called$args - called = args_called$called - - if (old %in% called) { - if (identical(args[[old]], value_old)) { - args[[old]] = NULL - args[[new]] = value_new - if (is.null(value_old)) value_old = "NULL" - message(paste0(fun, " (v3->v4): use '", new, " = ", value_new, "' instead of '", old, " = ", value_old, "'")) - list(args = args, called = called) - } else { - v3_instead(args_called, old, new, fun) - } - } else { - list(args = args, called = called) - } -} diff --git a/R/step1_rearrange.R b/R/step1_rearrange.R index fdc94db3..e5b4914a 100644 --- a/R/step1_rearrange.R +++ b/R/step1_rearrange.R @@ -49,7 +49,9 @@ step1_rearrange = function(tmel) { if (any(is_opt)) for (id in which(is_opt)) { o2 = oth[[id]] - if ("v3" %in% o2$calls) message("v3 code detected: as of tmap v4, the legend should be specified for each visual variable\n(e.g. with `fill.legend = tm_legend()` inside tm_polygons to control the legend of fill for polygons.", call. = FALSE) + cls = class(o2)[1] + if (substr(cls, nchar(cls)-2,nchar(cls)) == "_v3") cls = substr(cls, 1, nchar(cls) - 3) + if ("v3_tm_legend" %in% o2$calls) v3_tm_legend_general(fun = cls) # special case: position, in case c("left", "top") is used pids = grep(".position", names(o2), fixed = TRUE) diff --git a/R/step4_helper_legends.R b/R/step4_helper_legends.R index 508a341b..c88b91f9 100644 --- a/R/step4_helper_legends.R +++ b/R/step4_helper_legends.R @@ -44,11 +44,21 @@ step4_plot_collect_legends = function(tmx) { legs2 = lapply(legs, function(legs_aes) { legs_aes$vneutral = unlist(lapply(legs_aes$legend, function(l) l$vneutral), use.names = FALSE, recursive = FALSE) + if ("icon_scale" %in% names(legs_aes$legend[[1]])) { + legs_aes$icon_scale = legs_aes$legend[[1]]$icon_scale + } else { + legs_aes$icon_scale = 1 + } legs_aes }) # find shared legends + icon_scales = vapply(legs2, function(l) { + as.numeric(l$icon_scale) + }, FUN.VALUE = numeric(1)) + icon_scale = if (any(icon_scales != 1)) icon_scales[which(icon_scales != 1)[1]] else 1 + clones = vapply(legs2, function(l) { a = l$legend[[1]]$aes if (!is.null(a)) a else "" @@ -120,9 +130,10 @@ step4_plot_collect_legends = function(tmx) { } - leleg = legs_aes$legend[[k]] + + # get gp values from shared legends (slave) if ("clones" %in% names(leleg)) { clist = leleg$clones @@ -132,6 +143,11 @@ step4_plot_collect_legends = function(tmx) { } } + # in case the size legend consists of symbols shapes that represented icons + if (icon_scale > 1 && legnm == "size") { + gp$size = gp$size * icon_scale + } + leleg$gp = gp leleg$vneutral = NULL leleg$vvalues = NULL diff --git a/R/tm_add_legend.R b/R/tm_add_legend.R index 52dcbd8f..551c2d19 100644 --- a/R/tm_add_legend.R +++ b/R/tm_add_legend.R @@ -35,6 +35,17 @@ tm_add_legend = function(..., #args = lapply(as.list(match.call()[-1]), eval, envir = parent.frame()) if (missing(labels)) stop("tm_add_legend: labels required", call. = FALSE) args = c(as.list(environment()), list(...)) + if (type %in% c("fill", "symbol", "line")) { + v3_add_legend(type, names(args)) + if ("col" %in% names(args) && !c("fill" %in% names(args))) { + args$fill = args$col + args$col = NULL + } + if ("border.col" %in% names(args)) { + args$col = args$border.col + args$border.col = NULL + } + } tm_element_list(do.call(tm_element, c(args, list(subclass = c("tm_add_legend", "tm_component"))))) } diff --git a/R/tm_element.R b/R/tm_element.R index dfbd9064..a5442869 100644 --- a/R/tm_element.R +++ b/R/tm_element.R @@ -32,7 +32,7 @@ tm_element_list_sel = function(tml, subclass) { if (inherits(e2, "tm_legend")) { names(e2) = paste0("legend.", names(e2)) - e2 = tm_element_list(do.call(tm_element, c(e2, list(calls = "v3", subclass = "tm_options")))) + e2 = tm_element_list(do.call(tm_element, c(e2, list(calls = "v3_tm_legend", subclass = c("tm_legend_v3", "tm_options"))))) } structure(c(e1, e2), class = "tmap") } diff --git a/R/tm_layers_polygons.R b/R/tm_layers_polygons.R index 12bc67b2..bd518f00 100644 --- a/R/tm_layers_polygons.R +++ b/R/tm_layers_polygons.R @@ -128,6 +128,13 @@ tm_polygons = function(fill = tm_const(), args_called = as.list(match.call()[-1]) #lapply(as.list(match.call()[-1]), eval, envir = parent.frame()) if (any(v3_only("tm_polygons") %in% names(args))) { + + layer_fun = paste0("tm", {if ("called_from" %in% names(args)) { + args$called_from + } else { + "polygons" + }}) + v3_start_message() if (!("style" %in% names(args))) { if (!"breaks" %in% names(args)) { @@ -139,29 +146,27 @@ tm_polygons = function(fill = tm_const(), style = args$style } - imp = function(name, value) { - if (name %in% names(args)) args[[name]] else value - } - - fill.scale.args = list(n = imp("n", 5), + + fill.scale.args = list(n = v3_impute(args, "n", 5), style = style, - style.args = imp("style.args", list()), - breaks = imp("breaks", NULL), - interval.closure = imp("interval.closure", "left"), - drop.levels = imp("drop.levels", FALSE), - midpoint = imp("midpoint", NULL), - as.count = imp("as.count", NA), - values = imp("palette", NA), - values.repeat = !imp("stretch.palette", TRUE), - values.range = imp("contrast", NA), + style.args = v3_impute(args, "style.args", list()), + breaks = v3_impute(args, "breaks", NULL), + interval.closure = v3_impute(args, "interval.closure", "left"), + drop.levels = v3_impute(args, "drop.levels", FALSE), + midpoint = v3_impute(args, "midpoint", NULL), + as.count = v3_impute(args, "as.count", NA), + values = v3_impute(args, "palette", NA, "values"), + values.repeat = !v3_impute(args, "stretch.palette", TRUE, "values.repeat"), + values.range = v3_impute(args, "contrast", NA, "values.range"), values.scale = 1, - value.na = imp("colorNA", NA), - value.null = imp("colorNULL", NA), + value.na = v3_impute(args, "colorNA", NA, "value.na"), + value.null = v3_impute(args, "colorNULL", NA, "value.null"), value.neutral = NA, - labels = imp("labels", NULL), - label.na = imp("textNA", NA), + labels = v3_impute(args, "labels", NULL), + label.na = v3_impute(args, "textNA", "Missing", "label.na"), label.null = NA, - label.format = imp("legend.format", list())) + label.format = v3_impute(args, "legend.format", list(), "label.format")) + fill.scale.args$fun_pref = if (style == "cat") { "categorical" } else if (style %in% c("fixed", "sd", "equal", "pretty", "quantile", "kmeans", "hclust", "bclust", "fisher", "jenks", "dpih", "headtails", "log10_pretty")) { @@ -176,6 +181,8 @@ tm_polygons = function(fill = tm_const(), stop("unknown style") } + if ("style" %in% names(args)) v3_tm_scale_instead_of_style(style, scale_fun = fill.scale.args$fun_pref, vv = "fill", layer_fun = layer_fun, arg_list = v3_list_get()) + fill.scale = do.call("tm_scale", args = fill.scale.args) if ("convert2density" %in% names(args) && args$convert2density) { @@ -197,17 +204,19 @@ tm_polygons = function(fill = tm_const(), fill_alpha = args$alpha } - fill.legend.args = alist(title = imp("title", NA), - show = imp("legend.show", NULL), - na.show = imp("na.show", NA), - format = imp("legend.format", list()), - orientation = ifelse(imp("legend.is.portrait", TRUE), "portrait", "landscape"), - reverse = imp("legend.reverse", FALSE)) + fill.legend.args = list(title = v3_impute(args, "title", NA), + show = v3_impute(args, "legend.show", NULL), + na.show = v3_impute(args, "na.show", NA), + format = v3_impute(args, "legend.format", list()), + orientation = ifelse(v3_impute(args, "legend.is.portrait", TRUE), "portrait", "landscape"), + reverse = v3_impute(args, "legend.reverse", FALSE)) fill.legend = do.call("tm_legend", fill.legend.args) if ("legend.hist" %in% names(args) && args$legend.hist) { fill.chart = tm_chart_histogram() + v3_tm_chart_hist(layer_fun = layer_fun, vv = "fill", arg = "legend.hist") + # to do: histogram title } diff --git a/R/tm_layers_symbols.R b/R/tm_layers_symbols.R index 051a7b9f..e36d1eae 100644 --- a/R/tm_layers_symbols.R +++ b/R/tm_layers_symbols.R @@ -167,6 +167,7 @@ tm_symbols = function(size = tm_const(), if (!is.null(res)) { fill = res$fill col = res$col + col_alpha = res$col_alpha fill_alpha = res$fill_alpha fill.scale = res$fill.scale fill.legend = res$fill.legend @@ -176,7 +177,6 @@ tm_symbols = function(size = tm_const(), shape.legend = res$shape.legend fill.chart = res$fill.chart } - tm_element_list(tm_element( layer = "symbols", @@ -263,6 +263,12 @@ v3_symbols = function(args, args_called) { v3 = v3_only("tm_symbols") if (any(v3 %in% names(args))) { + layer_fun = paste0("tm_", {if ("called_from" %in% names(args)) { + args$called_from + } else { + "symbols" + }}) + v3_start_message() if (!("style" %in% names(args))) { if (!"breaks" %in% names(args)) { @@ -274,30 +280,27 @@ v3_symbols = function(args, args_called) { style = args$style } - imp = function(name, value) { - if (name %in% names(args)) args[[name]] else value - } - + v3_list_init() # v3 visual variable: fill - fill.scale.args = list(n = imp("n", 5), + fill.scale.args = list(n = v3_impute(args, "n", 5), style = style, - style.args = imp("style.args", list()), - breaks = imp("breaks", NULL), - interval.closure = imp("interval.closure", "left"), - drop.levels = imp("drop.levels", FALSE), - midpoint = imp("midpoint", NULL), - as.count = imp("as.count", NA), - values = imp("palette", NA), - values.repeat = !imp("stretch.palette", TRUE), - values.range = imp("contrast", NA), + style.args = v3_impute(args, "style.args", list()), + breaks = v3_impute(args, "breaks", NULL), + interval.closure = v3_impute(args, "interval.closure", "left"), + drop.levels = v3_impute(args, "drop.levels", FALSE), + midpoint = v3_impute(args, "midpoint", NULL), + as.count = v3_impute(args, "as.count", NA), + values = v3_impute(args, "palette", NA, "values"), + values.repeat = !v3_impute(args, "stretch.palette", TRUE, "values.repeat"), + values.range = v3_impute(args, "contrast", NA, "values.range"), values.scale = 1, - value.na = imp("colorNA", NA), - value.null = imp("colorNULL", NA), + value.na = v3_impute(args, "colorNA", NA, "value.na"), + value.null = v3_impute(args, "colorNULL", NA, "value.null"), value.neutral = NA, - labels = imp("labels", NULL), - label.na = imp("textNA", NA), + labels = v3_impute(args, "labels", NULL), + label.na = v3_impute(args, "textNA", NA, "label.na"), label.null = NA, - label.format = imp("legend.format", list())) + label.format = v3_impute(args, "legend.format", list(), "label.format")) fill.scale.args$fun_pref = if (style == "cat") { "categorical" } else if (style %in% c("fixed", "sd", "equal", "pretty", "quantile", @@ -314,61 +317,81 @@ v3_symbols = function(args, args_called) { stop("unknown style") } - if ("style" %in% names(args)) { - message("tm_symbols (v3->v4): instead of 'style = \"", style, "\"', pleaase use 'fill.scale = tm_scale_", fill.scale.args$fun_pref, "()'") - } - - + if ("style" %in% names(args)) v3_tm_scale_instead_of_style(style, scale_fun = fill.scale.args$fun_pref, vv = "fill", layer_fun = layer_fun, arg_list = v3_list_get()) fill.scale = do.call("tm_scale", args = fill.scale.args) if ("col" %in% names(args_called)) { fill = args_called$col + isn_fill = is.null(fill) + v3_message_col_fill(layer_fun = layer_fun) + if (isn_fill) { + v3_message_vv_null(layer_fun = layer_fun) + fill = NA + } col = tm_const() } else { fill = tm_const() col = tm_const() + isn_fill = FALSE } + if ("border.col" %in% names(args)) { col = args$border.col + isn_col = is.null(col) + if (!("col" %in% names(args_called))) v3_message_col_fill(layer_fun = layer_fun) + if (isn_col) { + if (!isn_fill) v3_message_vv_null(layer_fun = layer_fun) + col = NA + } } if ("alpha" %in% names(args)) { + v3_message_fill_alpha(layer_fun = layer_fun) fill_alpha = args$alpha } else { fill_alpha = tm_const() } - fill.legend.args = alist(title = imp("title.col", NA), - show = imp("legend.show", NULL), - na.show = imp("na.show", NA), - format = imp("legend.format", list()), - orientation = ifelse(imp("legend.is.portrait", TRUE), "portrait", "landscape"), - reverse = imp("legend.reverse", FALSE)) + if ("border.alpha" %in% names(args)) { + v3_message_col_alpha(layer_fun = layer_fun) + col_alpha = args$border.alpha + } else { + col_alpha = tm_const() + } + v3_list_init() + fill.legend.args = list(title = v3_impute(args, "title.col", NA, "title"), + show = v3_impute(args, "legend.show", NULL, "show"), + na.show = v3_impute(args, "na.show", NA), + format = v3_impute(args, "legend.format", list(), "format"), + orientation = ifelse(v3_impute(args, "legend.is.portrait", TRUE, "orientation"), "portrait", "landscape"), + reverse = v3_impute(args, "legend.reverse", FALSE, "reverse")) fill.legend = do.call("tm_legend", fill.legend.args) + v3_tm_legend(fun = layer_fun, vv = "col", arg_list = v3_list_get()) # v3 visual variable: size - size.scale.args = list(ticks = imp("sizes.legend", NULL), + v3_list_init() + size.scale.args = list(ticks = v3_impute(args, "sizes.legend", NULL, "ticks"), value.range = {if ("size.lim" %in% names(args)) { c(args[["size.lim"]][1] / args[["size.lim"]][2], 1) }}, - limits = imp("size.lim", NULL), + limits = v3_impute(args, "size.lim", NULL, "limits"), outliers.trunc = c(TRUE, FALSE), - labels = imp("sizes.legend.labels", NULL), + labels = v3_impute(args, "sizes.legend.labels", NULL, "labels"), fun_pref = "continuous") - + if ("size" %in% names(args_called)) v3_tm_scale(scale_fun = "continuous", vv = "size", layer_fun = layer_fun, arg_list = v3_list_get()) size.scale = do.call("tm_scale", args = size.scale.args) - - size.legend.args = alist(title = imp("title.size", NA), - show = imp("legend.size.show", NULL), - na.show = imp("showNA", NA), - format = imp("legend.format", list()), - orientation = ifelse(imp("legend.size.is.portrait", FALSE), "portrait", "landscape"), - reverse = imp("legend.size.reverse", FALSE)) - + v3_list_init() + size.legend.args = list(title = v3_impute(args, "title.size", NA, "title"), + show = v3_impute(args, "legend.size.show", NULL), + na.show = v3_impute(args, "showNA", NA), + format = v3_impute(args, "legend.format", list(), "format"), + orientation = ifelse(v3_impute(args, "legend.size.is.portrait", FALSE), "portrait", "landscape"), + reverse = v3_impute(args, "legend.size.reverse", FALSE)) + if ("size" %in% names(args_called)) v3_tm_legend(fun = layer_fun, vv = "size", arg_list = v3_list_get()) size.legend = do.call("tm_legend", size.legend.args) # v3 visual variable: shape @@ -382,35 +405,45 @@ v3_symbols = function(args, args_called) { shapes.style = args$shapes.style } - shape.scale.args = list(n = imp("shapes.n", 5), + v3_list_init() + shape.scale.args = list(n = v3_impute(args, "shapes.n", 5, "n"), style = shapes.style, - style.args = imp("shapes.style.args", list()), - breaks = imp("shapes.breaks", NULL), - interval.closure = imp("shapes.interval.closure", "left"), - drop.levels = imp("drop.levels", FALSE), - midpoint = imp("midpoint", NULL), - as.count = imp("as.count", NA), - values = imp("shapes", 21:25), - labels = imp("shapes.labels", NULL), - label.na = imp("shape.textNA", NA), + style.args = v3_impute(args, "shapes.style.args", list(), "style.args"), + breaks = v3_impute(args, "shapes.breaks", NULL, "breaks"), + interval.closure = v3_impute(args, "shapes.interval.closure", "left", "interval.closure"), + drop.levels = v3_impute(args, "drop.levels", FALSE), + midpoint = v3_impute(args, "midpoint", NULL), + as.count = v3_impute(args, "as.count", NA), + value.neutral = v3_impute(args, "shapes.legend", NA, "value.neutral"), + values = v3_impute(args, "shapes", 21:25, "values"), + labels = v3_impute(args, "shapes.labels", NULL, "labels"), + label.na = v3_impute(args, "shape.textNA", NA, "label.na"), label.null = NA, - label.format = imp("legend.format", list()), + label.format = v3_impute(args, "legend.format", list(), "label.format"), fun_pref = "intervals") - shape.scale = do.call("tm_scale", args = shape.scale.args) + if ("shape" %in% names(args_called)) { + if ("shapes.style" %in% names(args)) { + v3_tm_scale_instead_of_style(shapes.style, scale_fun = shape.scale.args$fun_pref, vv = "shape", layer_fun = layer_fun, arg_list = v3_list_get()) + } else { + v3_tm_scale(scale_fun = shape.scale.args$fun_pref, vv = "shape", layer_fun = layer_fun, arg_list = v3_list_get()) + } + } - - shape.legend.args = alist(title = imp("title.shape", NA), - show = imp("legend.shape.show", NULL), - na.show = imp("shape.showNA ", NA), - format = imp("legend.format", list()), - orientation = ifelse(imp("legend.shape.is.portrait", TRUE), "portrait", "landscape"), - reverse = imp("legend.shape.reverse", FALSE)) - + v3_list_init() + shape.legend.args = list(title = v3_impute(args, "title.shape", NA), + show = v3_impute(args, "legend.shape.show", NULL), + na.show = v3_impute(args, "shape.showNA ", NA), + format = v3_impute(args, "legend.format", list(), "format"), + orientation = ifelse(v3_impute(args, "legend.shape.is.portrait", TRUE), "portrait", "landscape"), + reverse = v3_impute(args, "legend.shape.reverse", FALSE)) + if ("shape" %in% names(args_called))v3_tm_legend(fun = layer_fun, vv = "shape", arg_list = v3_list_get()) shape.legend = do.call("tm_legend", shape.legend.args) if ("legend.hist" %in% names(args) && args$legend.hist) { fill.chart = tm_chart_histogram() + v3_tm_chart_hist(layer_fun = layer_fun, vv = "fill", arg = "legend.hist") + # to do: histogram title } else { fill.chart = tm_chart_none() @@ -418,6 +451,7 @@ v3_symbols = function(args, args_called) { list(fill = fill, col = col, + col_alpha = col_alpha, fill_alpha = fill_alpha, fill.scale = fill.scale, fill.legend = fill.legend, @@ -464,6 +498,8 @@ tm_dots = function(fill = tm_const(), ...) { args = c(as.list(environment()), list(...)) + args$called_from = "dots" + tm = do.call(tm_symbols, args) tm[[1]]$layer = c("dots", "symbols") tm @@ -511,6 +547,8 @@ tm_bubbles = function(size = tm_const(), ...) { args = c(as.list(environment()), list(...)) + args$called_from = "bubbles" + tm = do.call(tm_symbols, args) tm[[1]]$layer = c("bubbles", "symbols") tm @@ -556,6 +594,7 @@ tm_squares = function(size = tm_const(), ...) { args = c(as.list(environment()), list(...)) + args$called_from = "squares" tm = do.call(tm_symbols, args) tm[[1]]$layer = c("squares", "symbols") tm diff --git a/R/tm_layers_text.R b/R/tm_layers_text.R index 51eb82ab..5c46f3ee 100644 --- a/R/tm_layers_text.R +++ b/R/tm_layers_text.R @@ -238,24 +238,9 @@ tm_text = function(text = tm_const(), #if (FALSE) { args = list(...) - # dput(names(formals("tm_text"))) - v3 = c("root", "clustering", "size.lim", "sizes.legend", - "sizes.legend.labels", "sizes.legend.text", "n", "style", "style.args", - "as.count", "breaks", "interval.closure", "palette", "labels", - "drop.levels", "labels.text", "midpoint", "stretch.palette", - "contrast", "colorNA", "textNA", "showNA", "colorNULL", "fontface", - "fontfamily", "alpha", "case", "bg.alpha", - "size.lowerbound", "print.tiny", "scale", "auto.placement", - "along.lines", "overwrite.lines", "xmod", "ymod", "title.size", - "title.col", "legend.size.show", "legend.col.show", "legend.format", - "legend.size.is.portrait", "legend.col.is.portrait", "legend.size.reverse", - "legend.col.reverse", "legend.hist", "legend.hist.title", "legend.size.z", - "legend.col.z", "legend.hist.z", "id", "auto.palette.mapping", "shadow", - "max.categories") - - - if (any(v3 %in% names(args))) { - message("tm_text: Deprecated tmap v3 code detected. Code translated to v4") + + if (any(v3_only("tm_text") %in% names(args))) { + v3_start_message() if (!("style" %in% names(args))) { if (!"breaks" %in% names(args)) { style = "pretty" @@ -266,29 +251,26 @@ tm_text = function(text = tm_const(), style = args$style } - imp = function(name, value) { - if (name %in% names(args)) args[[name]] else value - } - - col.scale.args = list(n = imp("n", 5), + v3_list_init() + col.scale.args = list(n = v3_impute(args, "n", 5), style = style, - style.args = imp("style.args", list()), - breaks = imp("breaks", NULL), - interval.closure = imp("interval.closure", "left"), - drop.levels = imp("drop.levels", FALSE), - midpoint = imp("midpoint", NULL), - as.count = imp("as.count", NA), - values = imp("palette", NA), - values.repeat = !imp("stretch.palette", TRUE), - values.range = imp("contrast", NA), + style.args = v3_impute(args, "style.args", list()), + breaks = v3_impute(args, "breaks", NULL), + interval.closure = v3_impute(args, "interval.closure", "left"), + drop.levels = v3_impute(args, "drop.levels", FALSE), + midpoint = v3_impute(args, "midpoint", NULL), + as.count = v3_impute(args, "as.count", NA), + values = v3_impute(args, "palette", NA, "values"), + values.repeat = !v3_impute(args, "stretch.palette", TRUE, "values.repeat"), + values.range = v3_impute(args, "contrast", NA, "values.range"), values.scale = 1, - value.na = imp("colorNA", NA), - value.null = imp("colorNULL", NA), + value.na = v3_impute(args, "colorNA", NA, "value.na"), + value.null = v3_impute(args, "colorNULL", NA, "value.null"), value.neutral = NA, - labels = imp("labels", NULL), - label.na = imp("textNA", "Missing"), + labels = v3_impute(args, "labels", NULL), + label.na = v3_impute(args, "textNA", "Missing", "label.na"), label.null = NA, - label.format = imp("legend.format", list())) + label.format = v3_impute(args, "legend.format", list(), "label.format")) col.scale.args$fun_pref = if (style == "cat") { "categorical" } else if (style %in% c("fixed", "sd", "equal", "pretty", "quantile", "kmeans", "hclust", "bclust", "fisher", "jenks", "dpih", "headtails", "log10_pretty")) { @@ -301,39 +283,61 @@ tm_text = function(text = tm_const(), stop("unknown style") } - col.scale = do.call("tm_scale", args = col.scale.args) + if ("style" %in% names(args)) v3_tm_scale_instead_of_style(style, scale_fun = col.scale.args$fun_pref, vv = "col", layer_fun = "tm_text", arg_list = v3_list_get()) - col.legend.args = list(title = imp("title.col", NA), - show = imp("legend.col.show", NULL), - na.show = imp("na.show", NA), - format = imp("legend.format", list()), - orientation = ifelse(imp("legend.col.is.portrait", TRUE), "portrait", "landscape"), - reverse = imp("legend.col.reverse", FALSE)) + col.scale = do.call("tm_scale", args = col.scale.args) + v3_list_init() + col.legend.args = list(title = v3_impute(args, "title.col", NA, "title"), + show = v3_impute(args, "legend.col.show", NULL, "show"), + na.show = v3_impute(args, "na.show", NA), + format = v3_impute(args, "legend.format", list(), "format"), + orientation = ifelse(v3_impute(args, "legend.col.is.portrait", TRUE, "orientation"), "portrait", "landscape"), + reverse = v3_impute(args, "legend.col.reverse", FALSE, "reverse")) + + v3_tm_legend(fun = "tm_text", vv = "col", arg_list = v3_list_get()) col.legend = do.call("tm_legend", col.legend.args) - text.scale = tm_scale_asis(value.neutral = imp("sizes.legend.text", NA)) + v3_list_init() + text.scale = tm_scale_asis(value.neutral = v3_impute(args, "sizes.legend.text", NA, "value.neutral")) + v3_tm_scale(scale_fun = "asis", vv = "text", layer_fun = "tm_text", arg_list = v3_list_get()) - size.scale.args = list(values = tmap_seq(0, 1, power = 1/imp("root", 3)), - limits = imp("size.lim", NULL), - outliers.trunc = c(imp("print.tiny", FALSE), TRUE), - ticks = imp("breaks", NULL), - midpoint = imp("midpoint", NULL), - labels = imp("sizes.legend.labels", NULL)) - size.scale = do.call("tm_scale_continuous", size.scale.args) - - size.legend.args = list(title = imp("title.size", NA), - show = imp("legend.size.show", NULL), - na.show = imp("na.show", NA), - format = imp("legend.format", list()), - orientation = ifelse(imp("legend.size.is.portrait", TRUE), "portrait", "landscape"), - reverse = imp("legend.size.reverse", FALSE)) - if ("legend.hist" %in% names(args) && args$legend.hist) { col.chart = tm_chart_histogram() + v3_tm_chart_hist(layer_fun = "tm_text", vv = "col", arg = "legend.hist") # to do: histogram title - } + } + + v3_list_init() + size.scale.args = list(values = tmap_seq(0, 1, power = 1/v3_impute(args, "root", 3, "values = tmap_seq(0, 1, power = 1/)")), + values.scale = v3_impute(args, "scale", 1, "values.scale"), + limits = v3_impute(args, "size.lim", NULL), + outliers.trunc = c(v3_impute(args, "print.tiny", FALSE), TRUE), + ticks = v3_impute(args, "breaks", NULL), + midpoint = v3_impute(args, "midpoint", NULL), + labels = v3_impute(args, "sizes.legend.labels", NULL)) + v3_tm_scale(scale_fun = "continuous", vv = "size", layer_fun = "tm_text", arg_list = v3_list_get()) + size.scale = do.call("tm_scale_continuous", size.scale.args) + + + v3_list_init() + size.legend.args = list(title = v3_impute(args, "title.size", NA, "title"), + show = v3_impute(args, "legend.size.show", NULL, "show"), + na.show = v3_impute(args, "na.show", NA), + format = v3_impute(args, "legend.format", list(), "format"), + orientation = ifelse(v3_impute(args, "legend.size.is.portrait", TRUE, "orientation"), "portrait", "landscape"), + reverse = v3_impute(args, "legend.size.reverse", FALSE, "reverse")) + v3_tm_legend(fun = "tm_text", vv = "size", arg_list = v3_list_get()) + size.legend = do.call("tm_legend", size.legend.args) + + + v4_opt_args = c("along.lines", "shadow", "just", "clustering", "point.label", "remove.overlap") + v3_opt_args = c("along.lines", "shadow", "just", "clustering", "auto.placement", "remove.overlap") + + #if () + + #} } diff --git a/R/tm_shape.R b/R/tm_shape.R index b4af1b53..7742a33c 100644 --- a/R/tm_shape.R +++ b/R/tm_shape.R @@ -43,7 +43,7 @@ tm_shape = function(shp, args = as.list(match.call(expand.dots = TRUE)[-1]) if ("projection" %in% names(args)) { - warning("The 'projection' argument of 'tm_shape()' is deprecated as of tmap 4.0. Pleaes use 'crs' instead.", call. = FALSE) + v3_instead_message(arg_old = "projection", arg_new = "crs", fun = "tm_shape") crs = args$projection } diff --git a/R/tmapGridSymbols.R b/R/tmapGridSymbols.R index f66ec3b7..100cbb2a 100644 --- a/R/tmapGridSymbols.R +++ b/R/tmapGridSymbols.R @@ -72,15 +72,16 @@ tmapGridSymbols = function(shpTM, dt, gp, bbx, facet_row, facet_col, facet_page, if (!is.na(shi) && shi>999) { + size = gp$size[i]*2/3 * args$icon.scale grbs <- if (gp$lwd[i] == 0) { gList(shapeLib[[shi-999]]) } else { gList(shapeLib[[shi-999]], rectGrob(gp=gpar(fill=NA, col=gp$col[i], lwd=gp$lwd[i]))) } - gTree(children=grbs, vp=viewport(x=grid::unit(coords[i,1] + justx * gp$size[i]*2/3, "native"), - y=grid::unit(coords[i,2] + justy * gp$size[i]*2/3, "native"), - width=unit(gp$size[i]*2/3, "lines"), - height=unit(gp$size[i]*2/3, "lines"))) + gTree(children=grbs, vp=viewport(x=grid::unit(coords[i,1] + justx * size, "native"), + y=grid::unit(coords[i,2] + justy * size, "native"), + width=unit(size, "lines"), + height=unit(size, "lines"))) } else { pointsGrob(x=grid::unit(coords[i,1] + justx * gp$size[i], "native"), y=grid::unit(coords[i,2] + justx * gp$size[i], "native"), diff --git a/R/tmapLeaflet_layers.R b/R/tmapLeaflet_layers.R index ac0fbf76..fe1f3fa6 100644 --- a/R/tmapLeaflet_layers.R +++ b/R/tmapLeaflet_layers.R @@ -96,6 +96,7 @@ tmapLeafletLines = function(shpTM, dt, pdt, popup.format, hdt, idt, gp, bbx, fac } tmapLeafletSymbols = function(shpTM, dt, pdt, popup.format, hdt, idt, gp, bbx, facet_row, facet_col, facet_page, id, pane, group, o, ...) { + args = list(...) lf = get_lf(facet_row, facet_col, facet_page) rc_text = frc(facet_row, facet_col) @@ -148,6 +149,8 @@ tmapLeafletSymbols = function(shpTM, dt, pdt, popup.format, hdt, idt, gp, bbx, f symbols_icons <- merge_icons(iconLib) size = gp2$width[sid] / gp2$baseSize + size[sid] = size[sid] * args$icon.scale + for (i in seq_along(sid)) { symbols$iconUrl[sid[i]] = symbols_icons$iconUrl[i] symbols$iconWidth[sid[i]] <- symbols_icons$iconWidth[i] * size[i] diff --git a/R/tmapScaleCategorical.R b/R/tmapScaleCategorical.R index 39c7aaa3..66904e03 100644 --- a/R/tmapScaleCategorical.R +++ b/R/tmapScaleCategorical.R @@ -172,12 +172,16 @@ tmapScaleCategorical = function(x1, scale, legend, chart, o, aes, layer, layer_a } attr(labs, "align") = label.format$text.align + # special case: if icons are used, specify this information in the symbol legend, such that it can be taken (in step4_plot_collect_legends) by other legends (e.g. for symbol sizes) + icon_scale = if ((aes == "shape") && any(values > 999)) layer_args$icon.scale else 1 + legend = within(legend, { nitems = length(labs) labels = labs dvalues = vals vvalues = values vneutral = value.neutral + icon_scale = icon_scale na.show = get("na.show", envir = parent.env(environment())) scale = "categorical" }) diff --git a/R/tmapScaleIntervals.R b/R/tmapScaleIntervals.R index 39f2bf3e..ce2093c9 100644 --- a/R/tmapScaleIntervals.R +++ b/R/tmapScaleIntervals.R @@ -92,7 +92,7 @@ tmapScaleIntervals = function(x1, scale, legend, chart, o, aes, layer, layer_arg rng <- range(x1, na.rm = TRUE) if (rng[1] < 0 && rng[2] > 0 && is.null(midpoint)) { - if (show.messages) message("Variable(s) \"", paste(aes, collapse = "\", \""), "\" contains positive and negative values, so midpoint is set to 0. Set midpoint = NA to show the full spectrum of the color palette.") + if (show.messages) message(paste0("[scale] tm_", layer[1], ":() the data variable assigned to '", aes, "' contains positive and negative values, so midpoint is set to 0. Set 'midpoint = NA' in 'fill.scale = tm_scale_intervals()' to use all visual values (e.g. colors)")) midpoint <- 0 } else { if ((n %% 2) == 1) { @@ -136,7 +136,7 @@ tmapScaleIntervals = function(x1, scale, legend, chart, o, aes, layer, layer_arg # detransform log if (is.log) { - if (any((breaks %% 1) != 0)) warning("non-rounded breaks occur, because style = \"log10_pretty\" is designed for large values", call. = FALSE) + if (any((breaks %% 1) != 0)) message("non-rounded breaks occur, because style = \"log10_pretty\" is designed for large values") breaks <- 10^breaks } diff --git a/R/tmapScale_misc.R b/R/tmapScale_misc.R index c4b8e7f3..1c36680b 100644 --- a/R/tmapScale_misc.R +++ b/R/tmapScale_misc.R @@ -39,13 +39,10 @@ get_scale_defaults = function(scale, o, aes, layer, cls, ct = NULL) { value.blank = getAesOption("value.blank", o, aes, layer, cls = cls) if (is.na(value.na) || identical(value.na, value.blank)) label.na = "" - - # label.na TRUE: always show NA's, but use option # label.na FALSE or "": never show NA's # label.na NA: show NA is there are any # label.na "qwerty" always snow NA's - label.show = !isFALSE(label.na) && (isTRUE(label.na) || (!is.na(label.na) && label.na != "")) if (is.na(label.na)) label.show = NA # will be TRUE if there are NAs if (is.logical(label.na)) label.na = getAesOption("label.na", o, aes, layer, cls = cls) diff --git a/R/tmap_options.R b/R/tmap_options.R index 1baef313..85c9b000 100644 --- a/R/tmap_options.R +++ b/R/tmap_options.R @@ -1187,8 +1187,10 @@ tm_format = function(format, ...) { } formatArgs$style = NA + + if ("title" %in% names(formatArgs)) { - warning("The 'title' argument of 'tm_format()' is deprecated as of tmap 4.0. Please use 'tm_title()' instead.", call. = FALSE) + v3_use_component("title", "tm_title", "tm_format") title = formatArgs$title formatArgs$title = NULL do.call(tm_options, formatArgs) + tm_title(text = title) diff --git a/R/v4_v3.R b/R/v4_v3.R new file mode 100644 index 00000000..47ff09c4 --- /dev/null +++ b/R/v4_v3.R @@ -0,0 +1,168 @@ +v3_only = function(fun) { + setdiff(funs_v3[[fun]], funs_v4[[fun]]) +} + +v3_start_message = function() { + if (!.TMAP$v3) { + message("-- tmap v3 code detected --") + .TMAP$v3 = TRUE + } + invisible(NULL) +} + +v3_reset_flag = function() { + .TMAP$v3 = FALSE + invisible(NULL) +} + + +v3_use_component = function(arg = "title", comp = "tm_title", container = "tm_format") { + v3_start_message() + message(paste0("[v3->v4] ", container, "(): use ", comp, "() instead of the argument '", arg, "'")) +} + +v3_tm_scale_instead_of_style = function(style, scale_fun, vv, layer_fun, arg_list) { + if (scale_fun == "intervals") { + arg_list$old = c("style", arg_list$old) + arg_list$new = c("style", arg_list$new) + } + if (length(arg_list$old)) { + al = do.call(paste, c(mapply(function(x,y) { + if (x == y) paste0("'", x, "'") else paste0("'", x, "' (rename to '", y, "')") + }, arg_list$old, arg_list$new, SIMPLIFY = FALSE), sep = ", ")) + xtra = paste0(" and migrate the argument(s) ", al, " to 'tm_scale_", scale_fun, "()'") + } else { + xtra = "" + } + + message(paste0("[v3->v4] ", layer_fun, "(): instead of 'style = \"", style, "\"', use '", vv, ".scale = tm_scale_", scale_fun, "()'", xtra)) +} + +v3_instead_message = function(arg_old, arg_new, fun) { + v3_start_message() + message(paste0("[v3->v4] ", fun, "(): use '", arg_new, "' instead of '", arg_old, "'")) +} + + +v3_instead = function(args_called, old, new, fun, extra_called = character()) { + args = args_called$args + called = args_called$called + + if (old %in% called) { + args[[new]] = args[[old]] + args[[old]] = NULL + + # may be needed to trigger something (e.g. "shape" to use symbols instead of dots) + if (length(extra_called)) { + called = unique(c(called, extra_called)) + } + message(paste0("[v3->v4] ", fun, "(): use '", new, "' instead of '", old, "'")) + } + list(args = args, called = called) +} + +v3_instead_value = function(args_called, old, new, fun, value_old, value_new) { + args = args_called$args + called = args_called$called + + if (old %in% called) { + if (identical(args[[old]], value_old)) { + args[[old]] = NULL + args[[new]] = value_new + if (is.null(value_old)) value_old = "NULL" + message(paste0("[v3->v4] ", fun, "(): use '", new, " = ", value_new, "' instead of '", old, " = ", value_old, "'")) + list(args = args, called = called) + } else { + v3_instead(args_called, old, new, fun) + } + } else { + list(args = args, called = called) + } +} + +v3_list_init = function() { + .TMAP$v3_list = list(old = character(), new = character()) + #.TMAP$v3_list = paste0(.TMAP$v3_list, v3_list_impute_item(name, value) + invisible(NULL) +} +v3_list_impute_item = function(name, new_name) { + .TMAP$v3_list$old = c(.TMAP$v3_list$old, name) + .TMAP$v3_list$new = c(.TMAP$v3_list$new, new_name) +} +v3_list_get = function() { + .TMAP$v3_list +} + +v3_impute = function(args, name, value, new_name = name) { + if (name %in% names(args)) { + v3_list_impute_item(name, new_name) + args[[name]] + } else value +} + +v3_list_text = function(olds, news) { + do.call(paste, c(mapply(function(x,y) { + if (x == y) { + paste0("'", x, "'") + } else if (nchar(y) < 20) { + paste0("'", x, "' (rename to '", y, "')") + } else { + paste0("'", x, "' (use '", y, "')") + } + }, olds , news, SIMPLIFY = FALSE), sep = ", ")) +} + +v3_tm_legend = function(fun, vv, arg_list) { + if (length(arg_list$old)) { + al = v3_list_text(olds = arg_list$old, news = arg_list$new) + message(paste0("[v3->v4] ", fun, "(): migrate the argument(s) related to the legend of the visual variable '", vv, "', namely ", al, " to '", vv, ".legend = tm_legend()'")) + } + NULL +} + +v3_tm_legend_general = function(fun) { + v3_start_message() + message(paste0("[v3->v4] ", fun, "(): use 'tm_legend()' inside a layer function, e.g. 'tm_polygons(..., fill.legend = tm_legend())'")) +} + + +v3_tm_scale = function(scale_fun, vv, layer_fun, arg_list) { + if (length(arg_list$old)) { + al = v3_list_text(olds = arg_list$old, news = arg_list$new) + message(paste0("[v3->v4] ", layer_fun, "(): migrate the argument(s) related to the scale of the visual variable '", vv, "', namely ", al, " to '", vv, ".scale = tm_scale_", scale_fun, "()'")) + } + NULL +} + +v3_tm_chart_hist = function(layer_fun, vv, arg) { + message(paste0("[v3->v4] ", layer_fun, "(): use '", vv, ".chart = tm_chart_histogram()' instead of '", arg, " = TRUE'")) + +} + +v3_message_col_fill = function(layer_fun = layer_fun) { + message(paste0("[v3->v4] ", layer_fun, "(): use 'fill' for the fill color of polygons/symbols (instead of 'col'), and 'col' for the outlines (instead of 'border.col')")) +} + +v3_message_vv_null = function(layer_fun = layer_fun) { + message(paste0("[v3->v4] ", layer_fun, "(): use 'NA' instead of 'NULL' to hide a visual variable")) +} + + +v3_message_fill_alpha = function(layer_fun = layer_fun) { + message(paste0("[v3->v4] ", layer_fun, "(): use 'fill_alpha' instead of 'alpha''")) +} + +v3_message_col_alpha = function(layer_fun = layer_fun) { + message(paste0("[v3->v4] ", layer_fun, "(): use 'col_alpha' instead of 'border.alpha''")) +} + +v3_add_legend = function(type, args) { + newtype = c(fill = "polygons", symbol = "symbols", line = "lines") + message(paste0("[v3->v4] tm_add_legend(): use 'type = \"", newtype[type],"\"' instead of 'type = \"", type,"\"'")) + if ("col" %in% args && !c("fill" %in% args)) { + message(paste0("[v3->v4] tm_add_legend(): use 'fill' instead of 'coll' for the fill color of ", newtype[type])) + } + if ("border.col" %in% args) { + message(paste0("[v3->v4] tm_add_legend(): use 'col' instead of 'border.col' for the outline color of ", newtype[type])) + } +}