From 20f3536073086624f362a3a52553ad086fb01124 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Fri, 20 Nov 2020 15:48:53 +0100 Subject: [PATCH] use add_attributes macro with modification --- Project.toml | 1 + src/Plots.jl | 1 + src/arg_desc.jl | 105 ++++----- src/args.jl | 328 ++++++++-------------------- src/backends.jl | 246 ++++++--------------- src/backends/deprecated/pgfplots.jl | 32 +-- src/backends/gr.jl | 43 ++-- src/backends/inspectdr.jl | 59 +++-- src/backends/pgfplotsx.jl | 29 +-- src/backends/plotly.jl | 14 +- src/backends/pyplot.jl | 48 ++-- src/backends/unicodeplots.jl | 2 +- src/components.jl | 17 +- src/consts.jl | 51 +++++ src/utils.jl | 30 +-- test/test_defaults.jl | 63 +++++- 16 files changed, 445 insertions(+), 624 deletions(-) create mode 100644 src/consts.jl diff --git a/Project.toml b/Project.toml index 4b31941a..dff864c1 100644 --- a/Project.toml +++ b/Project.toml @@ -56,6 +56,7 @@ UnicodePlots = "2.4" julia = "1.5" [extras] +Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" Gtk = "4c0ca9eb-093a-5379-98c5-f87ac0bbbf44" diff --git a/src/Plots.jl b/src/Plots.jl index cea12a03..b1fe9125 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -209,6 +209,7 @@ include("colorbars.jl") include("axes.jl") include("args.jl") include("components.jl") +include("consts.jl") include("themes.jl") include("plot.jl") include("pipeline.jl") diff --git a/src/arg_desc.jl b/src/arg_desc.jl index 5ec9a4d6..7bad0950 100644 --- a/src/arg_desc.jl +++ b/src/arg_desc.jl @@ -76,65 +76,52 @@ const _arg_desc = KW( :fontfamily => "String or Symbol. Default font family for title, legend entries, tick labels and guides", :warn_on_unsupported => "Bool. Warn on unsupported attributes, series types and marker shapes", - # subplot args - :title => "String. Subplot title.", - :titlelocation => "Symbol. Position of subplot title. Values: `:left`, `:center`, `:right`", - :titlefontfamily => "String or Symbol. Font family of subplot title.", - :titlefontsize => "Integer. Font pointsize of subplot title.", - :titlefonthalign => "Symbol. Font horizontal alignment of subplot title: :hcenter, :left, :right or :center", - :titlefontvalign => "Symbol. Font vertical alignment of subplot title: :vcenter, :top, :bottom or :center", - :titlefontrotation => "Real. Font rotation of subplot title", - :titlefontcolor => "Color Type. Font color of subplot title", - :background_color_subplot => "Color Type or `:match` (matches `:background_color`). Base background color of the subplot.", - :background_color_legend => "Color Type or `:match` (matches `:background_color_subplot`). Background color of the legend.", - :background_color_inside => "Color Type or `:match` (matches `:background_color_subplot`). Background color inside the plot area (under the grid).", - :foreground_color_subplot => "Color Type or `:match` (matches `:foreground_color`). Base foreground color of the subplot.", - :foreground_color_legend => "Color Type or `:match` (matches `:foreground_color_subplot`). Foreground color of the legend.", - :foreground_color_title => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of subplot title.", - :color_palette => "Vector of colors (cycle through) or color gradient (generate list from gradient) or `:auto` (generate a color list using `Colors.distiguishable_colors` and custom seed colors chosen to contrast with the background). The color palette is a color list from which series colors are automatically chosen.", - :legend => "Bool (show the legend?) or (x,y) tuple or Symbol (legend position) or angle or (angle,inout) tuple. Bottom left corner of legend is placed at (x,y). Symbol values: `:none`; `:best`; `:inline`; `:inside`; `:legend`; any valid combination of `:(outer ?)(top/bottom ?)(right/left ?)`, i.e.: `:top`, `:topright`, `:outerleft`, `:outerbottomright` ... (note: only some may be supported in each backend). Legend is positioned at (angle degrees) (so (90,:outer) is roughly equivalent to :outertop), close to the inside of the axes or the outside if inout=:outer.", - :legendfontfamily => "String or Symbol. Font family of legend entries.", - :legendfontsize => "Integer. Font pointsize of legend entries.", - :legendfonthalign => "Symbol. Font horizontal alignment of legend entries: :hcenter, :left, :right or :center", - :legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center", - :legendfontrotation => "Real. Font rotation of legend entries", - :legendfontcolor => "Color Type. Font color of legend entries", - :legendtitle => "String. Legend title.", - :legendtitlefontfamily => "String or Symbol. Font family of the legend title.", - :legendtitlefontsize => "Integer. Font pointsize the legend title.", - :legendtitlefonthalign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center", - :legendtitlefontvalign => "Symbol. Font vertical alignment of the legend title: :vcenter, :top, :bottom or :center", - :legendtitlefontrotation => "Real. Font rotation of the legend title", - :legendtitlefontcolor => "Color Type. Font color of the legend title", - :colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)", - :clims => "`:auto`, NTuple{2,Number}, or a function that takes series data in and returns NTuple{2,Number}. Fixes the limits of the colorbar.", - :colorbar_fontfamily => "String or Symbol. Font family of colobar entries.", - :colorbar_ticks => "Vector of numbers (set the tick values), Tuple of (tickvalues, ticklabels), or `:auto`", - :colorbar_tickfontfamily => "String or Symbol. Font family of colorbar tick labels.", - :colorbar_tickfontsize => "Integer. Font pointsize of colorbar tick entries.", - :colorbar_tickfontcolor => "Color Type. Font color of colorbar tick entries", - :colorbar_scale => "Symbol. Scale of the colorbar axis: `:none`, `:ln`, `:log2`, `:log10`", - :colorbar_formatter => "Function, :scientific, :plain or :auto. A method which converts a number to a string for tick labeling.", - :legendfont => "Font. Font of legend items.", - :legendtitlefont => "Font. Font of the legend title.", - :annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String, PlotText (created with `text(args...)`), or a tuple of arguments to `text` (e.g., `(\"Label\", 8, :red, :top)`). Add one-off text annotations at the x,y coordinates.", - :annotationfontfamily => "String or Symbol. Font family of annotations.", - :annotationfontsize => "Integer. Font pointsize of annotations.", - :annotationhalign => "Symbol. horizontal alignment of annotations, :hcenter, :left, :right or :center.", - :annotationvalign => "Symbol. Vertical alignment of annotations, :vcenter, :top, :bottom or :center.", - :annotationrotation => "Float. Rotation of annotations in degrees.", - :annotationcolor => "Colorant or :match. Color of annotations.", - :projection => "Symbol or String. '3d' or 'polar'", - :aspect_ratio => "Symbol (:equal or :none) or Number. Plot area is resized so that 1 y-unit is the same size as `aspect_ratio` x-units. With `:none`, images inherit aspect ratio of the plot area.", - :margin => "Measure (multiply by `mm`, `px`, etc). Base for individual margins... not directly used. Specifies the extra padding around subplots.", - :left_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the left of the subplot.", - :top_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the top of the subplot.", - :right_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the right of the subplot.", - :bottom_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the bottom of the subplot.", - :subplot_index => "Integer. Internal (not set by user). Specifies the index of this subplot in the Plot's `plt.subplot` list.", - :colorbar_title => "String. Title of colorbar.", - :framestyle => "Symbol. Style of the axes frame. Choose from $(_allFramestyles)", - :camera => "NTuple{2, Real}. Sets the view angle (azimuthal, elevation) for 3D plots", +# subplot args +:title => "String. Subplot title.", +:titlelocation => "Symbol. Position of subplot title. Values: `:left`, `:center`, `:right`", +:titlefontfamily => "String or Symbol. Font family of subplot title.", +:titlefontsize => "Integer. Font pointsize of subplot title.", +:titlefonthalign => "Symbol. Font horizontal alignment of subplot title: :hcenter, :left, :right or :center", +:titlefontvalign => "Symbol. Font vertical alignment of subplot title: :vcenter, :top, :bottom or :center", +:titlefontrotation => "Real. Font rotation of subplot title", +:titlefontcolor => "Color Type. Font color of subplot title", +:background_color_subplot => "Color Type or `:match` (matches `:background_color`). Base background color of the subplot.", +:legend_background_color => "Color Type or `:match` (matches `:background_color_subplot`). Background color of the legend.", +:background_color_inside => "Color Type or `:match` (matches `:background_color_subplot`). Background color inside the plot area (under the grid).", +:foreground_color_subplot => "Color Type or `:match` (matches `:foreground_color`). Base foreground color of the subplot.", +:legend_foreground_color => "Color Type or `:match` (matches `:foreground_color_subplot`). Foreground color of the legend.", +:foreground_color_title => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of subplot title.", +:color_palette => "Vector of colors (cycle through) or color gradient (generate list from gradient) or `:auto` (generate a color list using `Colors.distiguishable_colors` and custom seed colors chosen to contrast with the background). The color palette is a color list from which series colors are automatically chosen.", +:legend => "Bool (show the legend?) or (x,y) tuple or Symbol (legend position). Bottom left corner of legend is placed at (x,y). Symbol values: `:none`; `:best`; `:inline`; `:inside`; `:legend`; any valid combination of `:(outer ?)(top/bottom ?)(right/left ?)`, i.e.: `:top`, `:topright`, `:outerleft`, `:outerbottomright` ... (note: only some may be supported in each backend)", +:legend_font_family => "String or Symbol. Font family of legend entries.", +:legend_font_pointsize => "Integer. Font pointsize of legend entries.", +:legend_font_halign => "Symbol. Font horizontal alignment of legend entries: :hcenter, :left, :right or :center", +:legend_font_valign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center", +:legend_font_rotation => "Real. Font rotation of legend entries", +:legend_font_color => "Color Type. Font color of legend entries", +:legend_title => "String. Legend title.", +:legend_title_font_family => "String or Symbol. Font family of the legend title.", +:legend_title_font_pointsize => "Integer. Font pointsize the legend title.", +:legend_title_font_halign => "Symbol. Font horizontal alignment of the legend title: :hcenter, :left, :right or :center", +:legend_title_font_valign => "Symbol. Font vertical alignment of the legend title: :vcenter, :top, :bottom or :center", +:legend_title_font_rotation => "Real. Font rotation of the legend title", +:legend_title_font_color => "Color Type. Font color of the legend title", +:colorbar => "Bool (show the colorbar?) or Symbol (colorbar position). Symbol values: `:none`, `:best`, `:right`, `:left`, `:top`, `:bottom`, `:legend` (matches legend value) (note: only some may be supported in each backend)", +:clims => "`:auto`, NTuple{2,Number}, or a function that takes series data in and returns NTuple{2,Number}. Fixes the limits of the colorbar.", +:legendfont => "Font. Font of legend items.", +:legend_titlefont => "Font. Font of the legend title.", +:annotations => "(x,y,text) tuple(s). Can be a single tuple or a list of them. Text can be String or PlotText (created with `text(args...)`) Add one-off text annotations at the x,y coordinates.", +:projection => "Symbol or String. '3d' or 'polar'", +:aspect_ratio => "Symbol (:equal or :none) or Number. Plot area is resized so that 1 y-unit is the same size as `aspect_ratio` x-units. With `:none`, images inherit aspect ratio of the plot area.", +:margin => "Measure (multiply by `mm`, `px`, etc). Base for individual margins... not directly used. Specifies the extra padding around subplots.", +:left_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the left of the subplot.", +:top_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the top of the subplot.", +:right_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding to the right of the subplot.", +:bottom_margin => "Measure (multiply by `mm`, `px`, etc) or `:match` (matches `:margin`). Specifies the extra padding on the bottom of the subplot.", +:subplot_index => "Integer. Internal (not set by user). Specifies the index of this subplot in the Plot's `plt.subplot` list.", +:colorbar_title => "String. Title of colorbar.", +:framestyle => "Symbol. Style of the axes frame. Choose from $(_allFramestyles)", +:camera => "NTuple{2, Real}. Sets the view angle (azimuthal, elevation) for 3D plots", # axis args :guide => "String. Axis guide (label).", diff --git a/src/args.jl b/src/args.jl index 6e1b3ec8..066356c1 100644 --- a/src/args.jl +++ b/src/args.jl @@ -435,76 +435,43 @@ const _plot_defaults = KW( ) const _subplot_defaults = KW( - :title => "", - :titlelocation => :center, # also :left or :right - :fontfamily_subplot => :match, - :titlefontfamily => :match, - :titlefontsize => 14, - :titlefonthalign => :hcenter, - :titlefontvalign => :vcenter, - :titlefontrotation => 0.0, - :titlefontcolor => :match, + :title => "", + :titlelocation => :center, # also :left or :right + :fontfamily_subplot => :match, + :titlefontfamily => :match, + :titlefontsize => 14, + :titlefonthalign => :hcenter, + :titlefontvalign => :vcenter, + :titlefontrotation => 0.0, + :titlefontcolor => :match, :background_color_subplot => :match, # default for other bg colors... match takes plot default - :background_color_legend => :match, # background of legend - :background_color_inside => :match, # background inside grid + :background_color_inside => :match, # background inside grid :foreground_color_subplot => :match, # default for other fg colors... match takes plot default - :foreground_color_legend => :match, # foreground of legend - :foreground_color_title => :match, # title color - :color_palette => :auto, - :legend => :best, - :legendtitle => nothing, - :colorbar => :legend, - :clims => :auto, - :colorbar_fontfamily => :match, - :colorbar_ticks => :auto, - :colorbar_tickfontfamily => :match, - :colorbar_tickfontsize => 8, - :colorbar_tickfonthalign => :hcenter, - :colorbar_tickfontvalign => :vcenter, - :colorbar_tickfontrotation => 0.0, - :colorbar_tickfontcolor => :match, - :colorbar_scale => :identity, - :colorbar_formatter => :auto, - :colorbar_discrete_values => [], - :colorbar_continuous_values => zeros(0), - :legendfontfamily => :match, - :legendfontsize => 8, - :legendfonthalign => :hcenter, - :legendfontvalign => :vcenter, - :legendfontrotation => 0.0, - :legendfontcolor => :match, - :legendtitlefontfamily => :match, - :legendtitlefontsize => 11, - :legendtitlefonthalign => :hcenter, - :legendtitlefontvalign => :vcenter, - :legendtitlefontrotation => 0.0, - :legendtitlefontcolor => :match, - :annotations => [], # annotation tuples... list of (x,y,annotation) - :annotationfontfamily => :match, - :annotationfontsize => 14, - :annotationhalign => :hcenter, - :annotationvalign => :vcenter, - :annotationrotation => 0.0, - :annotationcolor => :match, - :projection => :none, # can also be :polar or :3d - :aspect_ratio => :auto, # choose from :none or :equal - :margin => 1mm, - :left_margin => :match, - :top_margin => :match, - :right_margin => :match, - :bottom_margin => :match, - :subplot_index => -1, - :colorbar_title => "", - :colorbar_titlefontsize => 10, - :colorbar_title_location => :center, # also :left or :right - :colorbar_titlefontfamily => :match, - :colorbar_titlefonthalign => :hcenter, - :colorbar_titlefontvalign => :vcenter, - :colorbar_titlefontrotation => 0.0, - :colorbar_titlefontcolor => :match, - :framestyle => :axes, - :camera => (30, 30), - :extra_kwargs => Dict(), + :foreground_color_title => :match, # title color + :color_palette => :auto, + :colorbar => :legend, + :clims => :auto, + :annotations => [], # annotation tuples... list of (x,y,annotation) + :projection => :none, # can also be :polar or :3d + :aspect_ratio => :auto, # choose from :none or :equal + :margin => 1mm, + :left_margin => :match, + :top_margin => :match, + :right_margin => :match, + :bottom_margin => :match, + :subplot_index => -1, + :colorbar_title => "", + :colorbar_titlefontsize => 10, + :colorbar_title_location => :center, # also :left or :right + :colorbar_fontfamily => :match, + :colorbar_titlefontfamily => :match, + :colorbar_titlefonthalign => :hcenter, + :colorbar_titlefontvalign => :vcenter, + :colorbar_titlefontrotation => 0.0, + :colorbar_titlefontcolor => :match, + :framestyle => :axes, + :camera => (30,30), + :extra_kwargs => Dict() ) const _axis_defaults = KW( @@ -581,64 +548,6 @@ reset_axis_defaults_byletter!() const _all_defaults = KW[_series_defaults, _plot_defaults, _subplot_defaults] -const _initial_defaults = deepcopy(_all_defaults) -const _initial_axis_defaults = deepcopy(_axis_defaults) - -# to be able to reset font sizes to initial values -const _initial_plt_fontsizes = - Dict(:plot_titlefontsize => _plot_defaults[:plot_titlefontsize]) - -const _initial_sp_fontsizes = Dict( - :titlefontsize => _subplot_defaults[:titlefontsize], - :legendfontsize => _subplot_defaults[:legendfontsize], - :legendtitlefontsize => _subplot_defaults[:legendtitlefontsize], - :annotationfontsize => _subplot_defaults[:annotationfontsize], - :colorbar_tickfontsize => _subplot_defaults[:colorbar_tickfontsize], - :colorbar_titlefontsize => _subplot_defaults[:colorbar_titlefontsize], -) - -const _initial_ax_fontsizes = Dict( - :tickfontsize => _axis_defaults[:tickfontsize], - :guidefontsize => _axis_defaults[:guidefontsize], -) - -const _initial_fontsizes = - merge(_initial_plt_fontsizes, _initial_sp_fontsizes, _initial_ax_fontsizes) - -const _internal_args = - [:plot_object, :series_plotindex, :markershape_to_add, :letter, :idxfilter] - -const _axis_args = sort(union(collect(keys(_axis_defaults)))) -const _series_args = sort(union(collect(keys(_series_defaults)))) -const _subplot_args = sort(union(collect(keys(_subplot_defaults)))) -const _plot_args = sort(union(collect(keys(_plot_defaults)))) - -const _magic_axis_args = [:axis, :tickfont, :guidefont, :grid, :minorgrid] -const _magic_subplot_args = - [:titlefont, :legendfont, :legendtitlefont, :plot_titlefont, :colorbar_titlefont] -const _magic_series_args = [:line, :marker, :fill] - -const _all_axis_args = sort(union([_axis_args; _magic_axis_args])) -const _all_subplot_args = sort(union([_subplot_args; _magic_subplot_args])) -const _all_series_args = sort(union([_series_args; _magic_series_args])) -const _all_plot_args = _plot_args - -for letter in (:x, :y, :z) - _attrsymbolcache[letter] = Dict{Symbol,Symbol}() - for k in keys(_axis_defaults) - # populate attribute cache - lk = Symbol(letter, k) - _attrsymbolcache[letter][k] = lk - # allow the underscore version too: xguide or x_guide - add_aliases(lk, Symbol(letter, "_", k)) - end - for k in (_magic_axis_args..., :(_discrete_indices)) - _attrsymbolcache[letter][k] = Symbol(letter, k) - end -end - -const _all_args = - sort(union([_all_axis_args; _all_subplot_args; _all_series_args; _all_plot_args])) is_subplot_attr(k) = k in _all_subplot_args is_series_attr(k) = k in _all_series_args @@ -671,6 +580,11 @@ aliases(aliasMap::Dict{Symbol,Symbol}, val) = sortedkeys(filter((k, v) -> v == val, aliasMap)) # ----------------------------------------------------------------------------- +# legend +add_aliases(:legend_postion, :legend) +add_aliases(:legend_background_color, :background_color_legend) +add_aliases(:legend_foreground_color, :foreground_color_legend) +add_aliases(:legend_font_pointsize, :legendfontsize) # margin add_aliases(:left_margin, :leftmargin) @@ -686,92 +600,36 @@ add_aliases(:markerstrokecolor, :msc, :mscolor, :mscolour, :markerstrokecolour) add_aliases(:markerstrokewidth, :msw, :mswidth) add_aliases(:fillcolor, :fc, :fcolor, :fcolour, :fillcolour) -add_aliases( - :background_color, - :bg, - :bgcolor, - :bg_color, - :background, - :background_colour, - :bgcolour, - :bg_colour, -) -add_aliases( - :background_color_legend, - :bg_legend, - :bglegend, - :bgcolor_legend, - :bg_color_legend, - :background_legend, - :background_colour_legend, - :bgcolour_legend, - :bg_colour_legend, -) -add_aliases( - :background_color_subplot, - :bg_subplot, - :bgsubplot, - :bgcolor_subplot, - :bg_color_subplot, - :background_subplot, - :background_colour_subplot, - :bgcolour_subplot, - :bg_colour_subplot, -) -add_aliases( - :background_color_inside, - :bg_inside, - :bginside, - :bgcolor_inside, - :bg_color_inside, - :background_inside, - :background_colour_inside, - :bgcolour_inside, - :bg_colour_inside, -) -add_aliases( - :background_color_outside, - :bg_outside, - :bgoutside, - :bgcolor_outside, - :bg_color_outside, - :background_outside, - :background_colour_outside, - :bgcolour_outside, - :bg_colour_outside, -) -add_aliases( - :foreground_color, - :fg, - :fgcolor, - :fg_color, - :foreground, - :foreground_colour, - :fgcolour, - :fg_colour, -) -add_aliases( - :foreground_color_legend, - :fg_legend, - :fglegend, - :fgcolor_legend, - :fg_color_legend, - :foreground_legend, - :foreground_colour_legend, - :fgcolour_legend, - :fg_colour_legend, -) -add_aliases( - :foreground_color_subplot, - :fg_subplot, - :fgsubplot, - :fgcolor_subplot, - :fg_color_subplot, - :foreground_subplot, - :foreground_colour_subplot, - :fgcolour_subplot, - :fg_colour_subplot, -) +add_aliases(:background_color, :bg, :bgcolor, :bg_color, :background, + :background_colour, :bgcolour, :bg_colour) +add_aliases(:legend_background_color, :bg_legend, :bglegend, :bgcolor_legend, :bg_color_legend, :background_legend, + :background_colour_legend, :bgcolour_legend, :bg_colour_legend) +add_aliases(:background_color_subplot, :bg_subplot, :bgsubplot, :bgcolor_subplot, :bg_color_subplot, :background_subplot, + :background_colour_subplot, :bgcolour_subplot, :bg_colour_subplot) +add_aliases(:background_color_inside, :bg_inside, :bginside, :bgcolor_inside, :bg_color_inside, :background_inside, + :background_colour_inside, :bgcolour_inside, :bg_colour_inside) +add_aliases(:background_color_outside, :bg_outside, :bgoutside, :bgcolor_outside, :bg_color_outside, :background_outside, + :background_colour_outside, :bgcolour_outside, :bg_colour_outside) +add_aliases(:foreground_color, :fg, :fgcolor, :fg_color, :foreground, + :foreground_colour, :fgcolour, :fg_colour) +add_aliases(:legend_foreground_color, :fg_legend, :fglegend, :fgcolor_legend, :fg_color_legend, :foreground_legend, + :foreground_colour_legend, :fgcolour_legend, :fg_colour_legend) +add_aliases(:foreground_color_subplot, :fg_subplot, :fgsubplot, :fgcolor_subplot, :fg_color_subplot, :foreground_subplot, + :foreground_colour_subplot, :fgcolour_subplot, :fg_colour_subplot) +add_aliases(:foreground_color_grid, :fg_grid, :fggrid, :fgcolor_grid, :fg_color_grid, :foreground_grid, + :foreground_colour_grid, :fgcolour_grid, :fg_colour_grid, :gridcolor) +add_aliases(:foreground_color_minor_grid, :fg_minor_grid, :fgminorgrid, :fgcolor_minorgrid, :fg_color_minorgrid, :foreground_minorgrid, + :foreground_colour_minor_grid, :fgcolour_minorgrid, :fg_colour_minor_grid, :minorgridcolor) +add_aliases(:foreground_color_title, :fg_title, :fgtitle, :fgcolor_title, :fg_color_title, :foreground_title, + :foreground_colour_title, :fgcolour_title, :fg_colour_title, :titlecolor) +add_aliases(:foreground_color_axis, :fg_axis, :fgaxis, :fgcolor_axis, :fg_color_axis, :foreground_axis, + :foreground_colour_axis, :fgcolour_axis, :fg_colour_axis, :axiscolor) +add_aliases(:foreground_color_border, :fg_border, :fgborder, :fgcolor_border, :fg_color_border, :foreground_border, + :foreground_colour_border, :fgcolour_border, :fg_colour_border, :bordercolor) +add_aliases(:foreground_color_text, :fg_text, :fgtext, :fgcolor_text, :fg_color_text, :foreground_text, + :foreground_colour_text, :fgcolour_text, :fg_colour_text, :textcolor) +add_aliases(:foreground_color_guide, :fg_guide, :fgguide, :fgcolor_guide, :fg_color_guide, :foreground_guide, + :foreground_colour_guide, :fgcolour_guide, :fg_colour_guide, :guidecolor) add_aliases( :foreground_color_title, @@ -1020,13 +878,6 @@ add_aliases(:camera, :cam, :viewangle, :view_angle) add_aliases(:contour_labels, :contourlabels, :clabels, :clabs) add_aliases(:warn_on_unsupported, :warn) -# add all pluralized forms to the _keyAliases dict -for arg in _all_args - add_aliases(arg, makeplural(arg)) -end -# add all non_underscored forms to the _keyAliases -add_non_underscore_aliases!(_keyAliases) - # ----------------------------------------------------------------------------- function parse_axis_kw(s::Symbol) @@ -1535,8 +1386,8 @@ function RecipesPipeline.preprocess_attributes!(plotattributes::AKW) # end # legends - if haskey(plotattributes, :legend) - plotattributes[:legend] = convertLegendValue(plotattributes[:legend]) + if haskey(plotattributes, :legend_position) + plotattributes[:legend_position] = convertLegendValue(plotattributes[:legend_position]) end if haskey(plotattributes, :colorbar) plotattributes[:colorbar] = convertLegendValue(plotattributes[:colorbar]) @@ -1765,9 +1616,9 @@ end # when a value can be `:match`, this is the key that should be used instead for value retrieval const _match_map = KW( :background_color_outside => :background_color, - :background_color_legend => :background_color_subplot, + :legend_background_color => :background_color_subplot, :background_color_inside => :background_color_subplot, - :foreground_color_legend => :foreground_color_subplot, + :legend_foreground_color => :foreground_color_subplot, :foreground_color_title => :foreground_color_subplot, :left_margin => :margin, :top_margin => :margin, @@ -1909,10 +1760,10 @@ function _update_subplot_periphery(sp::Subplot, anns::AVec) sp.attr[:annotations] = newanns # handle legend/colorbar - sp.attr[:legend] = convertLegendValue(sp.attr[:legend]) + sp.attr[:legend_position] = convertLegendValue(sp.attr[:legend_position]) sp.attr[:colorbar] = convertLegendValue(sp.attr[:colorbar]) if sp.attr[:colorbar] == :legend - sp.attr[:colorbar] = sp.attr[:legend] + sp.attr[:colorbar] = sp.attr[:legend_position] end return end @@ -1921,12 +1772,12 @@ function _update_subplot_colors(sp::Subplot) # background colors color_or_nothing!(sp.attr, :background_color_subplot) sp.attr[:color_palette] = get_color_palette(sp.attr[:color_palette], 30) - color_or_nothing!(sp.attr, :background_color_legend) + color_or_nothing!(sp.attr, :legend_background_color) color_or_nothing!(sp.attr, :background_color_inside) # foreground colors color_or_nothing!(sp.attr, :foreground_color_subplot) - color_or_nothing!(sp.attr, :foreground_color_legend) + color_or_nothing!(sp.attr, :legend_foreground_color) color_or_nothing!(sp.attr, :foreground_color_title) return end @@ -2221,13 +2072,12 @@ macro add_attributes(level, expr) T = T.args[1] end - key_args = Any[] - value_args = Any[] + key_dict = KW() - _splitdef!(expr.args[3], value_args, key_args) + _splitdef!(expr.args[3], key_dict) insert_block = Expr(:block) - for (key, value) in zip(key_args, value_args) + for (key, value) in key_dict # e.g. _series_defualts[key] = value exp_key = Symbol(lowercase(string(T)), "_", key) pl_key = makeplural(exp_key) @@ -2264,7 +2114,7 @@ macro add_attributes(level, expr) end |> esc end -function _splitdef!(blk, value_args, key_args) +function _splitdef!(blk, key_dict) for i in eachindex(blk.args) ei = blk.args[i] if ei isa Symbol @@ -2279,20 +2129,24 @@ function _splitdef!(blk, value_args, key_args) elseif lhs isa Expr && lhs.head === :(::) && lhs.args[1] isa Symbol # var::T = defexpr var = lhs.args[1] - else + type = lhs.args[2] + if @isdefined type + for field in fieldnames(getproperty(Plots, type)) + key_dict[Symbol(var, "_", field)] = :(getfield($(ei.args[2]), $(QuoteNode(field)))) + end + end + else # something else, e.g. inline inner constructor # F(...) = ... continue end defexpr = ei.args[2] # defexpr - push!(value_args, defexpr) - push!(key_args, var) + key_dict[var] = defexpr blk.args[i] = lhs elseif ei.head === :(::) && ei.args[1] isa Symbol # var::Typ var = ei.args[1] - push!(value_args, var) - push!(key_args, var) + key_dict[var] = defexpr elseif ei.head === :block # can arise with use of @static inside type decl _kwdef!(ei, value_args, key_args) diff --git a/src/backends.jl b/src/backends.jl index c9e65aa5..9809e2fa 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -310,14 +310,9 @@ _initialize_backend(pkg::GRBackend) = nothing const _gr_attr = merge_with_base_supported([ :annotations, - :background_color_legend, - :background_color_inside, - :background_color_outside, - :foreground_color_legend, - :foreground_color_grid, - :foreground_color_axis, - :foreground_color_text, - :foreground_color_border, + :legend_background_color, :background_color_inside, :background_color_outside, + :legend_foreground_color, :foreground_color_grid, :foreground_color_axis, + :foreground_color_text, :foreground_color_border, :label, :seriescolor, :seriesalpha, @@ -337,58 +332,20 @@ const _gr_attr = merge_with_base_supported([ :fillalpha, :bins, :layout, - :title, - :window_title, - :guide, - :lims, - :ticks, - :scale, - :flip, - :titlefontfamily, - :titlefontsize, - :titlefonthalign, - :titlefontvalign, - :titlefontrotation, - :titlefontcolor, - :legendfontfamily, - :legendfontsize, - :legendfonthalign, - :legendfontvalign, - :legendfontrotation, - :legendfontcolor, - :tickfontfamily, - :tickfontsize, - :tickfonthalign, - :tickfontvalign, - :tickfontrotation, - :tickfontcolor, - :guidefontfamily, - :guidefontsize, - :guidefonthalign, - :guidefontvalign, - :guidefontrotation, - :guidefontcolor, - :grid, - :gridalpha, - :gridstyle, - :gridlinewidth, - :legend, - :legendtitle, - :colorbar, - :colorbar_title, - :colorbar_entry, - :colorbar_titlefontfamily, - :colorbar_titlefontsize, - :colorbar_titlefontvalign, - :colorbar_titlefonthalign, - :colorbar_titlefontrotation, - :colorbar_titlefontcolor, - :fill_z, - :line_z, - :marker_z, - :levels, - :ribbon, - :quiver, + :title, :window_title, + :guide, :lims, :ticks, :scale, :flip, + :titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign, + :titlefontrotation, :titlefontcolor, + :legend_font_family, :legend_font_pointsize, :legend_font_halign, :legend_font_valign, + :legend_font_rotation, :legend_font_color, + :tickfontfamily, :tickfontsize, :tickfonthalign, :tickfontvalign, + :tickfontrotation, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign, + :guidefontrotation, :guidefontcolor, + :grid, :gridalpha, :gridstyle, :gridlinewidth, + :legend, :legend_title, :colorbar, :colorbar_title, :colorbar_entry, + :fill_z, :line_z, :marker_z, :levels, + :ribbon, :quiver, :orientation, :overwrite_figure, :polar, @@ -439,15 +396,10 @@ end const _plotly_attr = merge_with_base_supported([ :annotations, - :background_color_legend, - :background_color_inside, - :background_color_outside, - :foreground_color_legend, - :foreground_color_guide, - :foreground_color_grid, - :foreground_color_axis, - :foreground_color_text, - :foreground_color_border, + :legend_background_color, :background_color_inside, :background_color_outside, + :legend_foreground_color, :foreground_color_guide, + :foreground_color_grid, :foreground_color_axis, + :foreground_color_text, :foreground_color_border, :foreground_color_title, :label, :seriescolor, @@ -475,15 +427,9 @@ const _plotly_attr = merge_with_base_supported([ :titlefonthalign, :titlefontvalign, :titlefontcolor, - :legendfontfamily, - :legendfontsize, - :legendfontcolor, - :tickfontfamily, - :tickfontsize, - :tickfontcolor, - :guidefontfamily, - :guidefontsize, - :guidefontcolor, + :legend_font_family, :legend_font_pointsize, :legend_font_color, + :tickfontfamily, :tickfontsize, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefontcolor, :window_title, :guide, :lims, @@ -565,14 +511,12 @@ defaultOutputFormat(plt::Plot{Plots.PlotlyBackend}) = "html" const _pgfplots_attr = merge_with_base_supported([ :annotations, - :background_color_legend, + :legend_background_color, :background_color_inside, # :background_color_outside, - # :foreground_color_legend, - :foreground_color_grid, - :foreground_color_axis, - :foreground_color_text, - :foreground_color_border, + # :legend_foreground_color, + :foreground_color_grid, :foreground_color_axis, + :foreground_color_text, :foreground_color_border, :label, :seriescolor, :seriesalpha, @@ -688,16 +632,9 @@ end const _pyplot_attr = merge_with_base_supported([ :annotations, - :background_color_legend, - :background_color_inside, - :background_color_outside, - :foreground_color_grid, - :foreground_color_legend, - :foreground_color_title, - :foreground_color_axis, - :foreground_color_border, - :foreground_color_guide, - :foreground_color_text, + :legend_background_color, :background_color_inside, :background_color_outside, + :foreground_color_grid, :legend_foreground_color, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, :label, :linecolor, :linestyle, @@ -721,41 +658,16 @@ const _pyplot_attr = merge_with_base_supported([ :titlelocation, :titlefont, :window_title, - :guide, - :guide_position, - :lims, - :ticks, - :scale, - :flip, - :rotation, - :titlefontfamily, - :titlefontsize, - :titlefontcolor, - :legendfontfamily, - :legendfontsize, - :legendfontcolor, - :tickfontfamily, - :tickfontsize, - :tickfontcolor, - :guidefontfamily, - :guidefontsize, - :guidefontcolor, - :grid, - :gridalpha, - :gridstyle, - :gridlinewidth, - :legend, - :legendtitle, - :colorbar, - :colorbar_title, - :colorbar_entry, - :colorbar_ticks, - :colorbar_tickfontfamily, - :colorbar_tickfontsize, - :colorbar_tickfonthalign, - :colorbar_tickfontvalign, - :colorbar_tickfontrotation, - :colorbar_tickfontcolor, + :guide, :guide_position, :lims, :ticks, :scale, :flip, :rotation, + :titlefontfamily, :titlefontsize, :titlefontcolor, + :legend_font_family, :legend_font_pointsize, :legend_font_color, + :tickfontfamily, :tickfontsize, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefontcolor, + :grid, :gridalpha, :gridstyle, :gridlinewidth, + :legend, :legend_title, :colorbar, :colorbar_title, :colorbar_entry, + :colorbar_ticks, :colorbar_tickfontfamily, :colorbar_tickfontsize, + :colorbar_tickfonthalign, :colorbar_tickfontvalign, + :colorbar_tickfontrotation, :colorbar_tickfontcolor, :colorbar_scale, :marker_z, :line_z, @@ -981,16 +893,9 @@ const _canvas_type = Ref(:auto) const _hdf5_attr = merge_with_base_supported([ :annotations, - :background_color_legend, - :background_color_inside, - :background_color_outside, - :foreground_color_grid, - :foreground_color_legend, - :foreground_color_title, - :foreground_color_axis, - :foreground_color_border, - :foreground_color_guide, - :foreground_color_text, + :legend_background_color, :background_color_inside, :background_color_outside, + :foreground_color_grid, :legend_foreground_color, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, :label, :linecolor, :linestyle, @@ -1083,16 +988,10 @@ const HDF5PLOT_PLOTREF = HDF5Plot_PlotRef(nothing) const _inspectdr_attr = merge_with_base_supported([ :annotations, - :background_color_legend, - :background_color_inside, - :background_color_outside, + :legend_background_color, :background_color_inside, :background_color_outside, # :foreground_color_grid, - :foreground_color_legend, - :foreground_color_title, - :foreground_color_axis, - :foreground_color_border, - :foreground_color_guide, - :foreground_color_text, + :legend_foreground_color, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, :label, :seriescolor, :seriesalpha, @@ -1114,28 +1013,17 @@ const _inspectdr_attr = merge_with_base_supported([ :title, :titlelocation, :window_title, - :guide, - :lims, - :scale, #:ticks, :flip, :rotation, - :titlefontfamily, - :titlefontsize, - :titlefontcolor, - :legendfontfamily, - :legendfontsize, - :legendfontcolor, - :tickfontfamily, - :tickfontsize, - :tickfontcolor, - :guidefontfamily, - :guidefontsize, - :guidefontcolor, - :grid, - :legend, #:colorbar, - # :marker_z, - # :line_z, - # :levels, - # :ribbon, :quiver, :arrow, - # :orientation, + :guide, :lims, :scale, #:ticks, :flip, :rotation, + :titlefontfamily, :titlefontsize, :titlefontcolor, + :legend_font_family, :legend_font_pointsize, :legend_font_color, + :tickfontfamily, :tickfontsize, :tickfontcolor, + :guidefontfamily, :guidefontsize, :guidefontcolor, + :grid, :legend, #:colorbar, +# :marker_z, +# :line_z, +# :levels, + # :ribbon, :quiver, :arrow, +# :orientation, :overwrite_figure, :polar, # :normalize, :weights, @@ -1186,10 +1074,10 @@ const _inspectdr_scale = [:identity, :ln, :log2, :log10] const _pgfplotsx_attr = merge_with_base_supported([ :annotations, - :background_color_legend, + :legend_background_color, :background_color_inside, :background_color_outside, - :foreground_color_legend, + :legend_foreground_color, :foreground_color_grid, :foreground_color_axis, :foreground_color_text, @@ -1226,12 +1114,12 @@ const _pgfplotsx_attr = merge_with_base_supported([ :titlefontvalign, :titlefontrotation, :titlefontcolor, - :legendfontfamily, - :legendfontsize, - :legendfonthalign, - :legendfontvalign, - :legendfontrotation, - :legendfontcolor, + :legend_font_family, + :legend_font_pointsize, + :legend_font_halign, + :legend_font_valign, + :legend_font_rotation, + :legend_font_color, :tickfontfamily, :tickfontsize, :tickfonthalign, @@ -1249,7 +1137,7 @@ const _pgfplotsx_attr = merge_with_base_supported([ :gridstyle, :gridlinewidth, :legend, - :legendtitle, + :legend_title, :colorbar, :colorbar_title, :colorbar_entry, diff --git a/src/backends/deprecated/pgfplots.jl b/src/backends/deprecated/pgfplots.jl index 471618e0..034bb4f5 100644 --- a/src/backends/deprecated/pgfplots.jl +++ b/src/backends/deprecated/pgfplots.jl @@ -227,7 +227,7 @@ function pgf_series(sp::Subplot, series::Series) end # add to legend? - if i == 1 && sp[:legend] != :none && should_add_to_legend(series) + if i == 1 && sp[:legend_position] != :none && should_add_to_legend(series) if plotattributes[:fillrange] !== nothing push!(style, "forget plot") push!(series_collection, pgf_fill_legend_hack(plotattributes, args)) @@ -590,32 +590,22 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend}) kw[:axisEqual] = "true" end - legpos = sp[:legend] + legpos = sp[:legend_position] if haskey(_pgfplots_legend_pos, legpos) kw[:legendPos] = _pgfplots_legend_pos[legpos] end - cstr, bg_alpha = pgf_color(plot_color(sp[:background_color_legend])) - fg_alpha = alpha(plot_color(sp[:foreground_color_legend])) + cstr, bg_alpha = pgf_color(plot_color(sp[:legend_background_color])) + fg_alpha = alpha(plot_color(sp[:legend_foreground_color])) - push!( - style, - string( - "legend style = {", - pgf_linestyle( - pgf_thickness_scaling(sp), - sp[:foreground_color_legend], - fg_alpha, - "solid", - ), - ",", + push!(style, string( + "legend style = {", + pgf_linestyle(pgf_thickness_scaling(sp), sp[:legend_foreground_color], fg_alpha, "solid", ), ",", "fill = $cstr,", "fill opacity = $bg_alpha,", - "text opacity = $(alpha(plot_color(sp[:legendfontcolor]))),", - "font = ", - pgf_font(sp[:legendfontsize], pgf_thickness_scaling(sp)), - "}", - ), - ) + "text opacity = $(alpha(plot_color(sp[:legend_font_color]))),", + "font = ", pgf_font(sp[:legend_font_pointsize], pgf_thickness_scaling(sp)), + "}", + )) if any(s[:seriestype] == :contour for s in series_list(sp)) kw[:view] = "{0}{90}" diff --git a/src/backends/gr.jl b/src/backends/gr.jl index a4cdfd56..c117b491 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -1024,7 +1024,7 @@ end ## Legend function gr_add_legend(sp, leg, viewport_plotarea) - if sp[:legend] ∉ (:none, :inline) + if !(sp[:legend_position] in(:none, :inline)) GR.savestate() GR.selntran(0) GR.setscale(0) @@ -1032,14 +1032,14 @@ function gr_add_legend(sp, leg, viewport_plotarea) if leg.w > 0 xpos, ypos = gr_legend_pos(sp, leg, viewport_plotarea) GR.setfillintstyle(GR.INTSTYLE_SOLID) - gr_set_fillcolor(sp[:background_color_legend]) + gr_set_fillcolor(sp[:legend_background_color]) GR.fillrect( xpos - leg.leftw, xpos + leg.textw + leg.rightw, ypos + leg.dy, ypos - leg.h, ) # Allocating white space for actual legend width here - gr_set_line(1, :solid, sp[:foreground_color_legend], sp) + gr_set_line(1, :solid, sp[:legend_foreground_color], sp) GR.drawrect( xpos - leg.leftw, xpos + leg.textw + leg.rightw, @@ -1047,10 +1047,10 @@ function gr_add_legend(sp, leg, viewport_plotarea) ypos - leg.h, ) # Drawing actual legend width here i = 0 - if sp[:legendtitle] !== nothing + if sp[:legend_title] !== nothing GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF) gr_set_font(legendtitlefont(sp), sp) - gr_text(xpos - 0.03 + 0.5 * leg.w, ypos, string(sp[:legendtitle])) + gr_text(xpos - 0.03 + 0.5 * leg.w, ypos, string(sp[:legend_title])) ypos -= leg.dy gr_set_font(legendfont(sp), sp) end @@ -1059,7 +1059,7 @@ function gr_add_legend(sp, leg, viewport_plotarea) should_add_to_legend(series) || continue st = series[:seriestype] lc = get_linecolor(series, clims) - gr_set_line(sp[:legendfontsize] / 8, get_linestyle(series), lc, sp) + gr_set_line(sp[:legend_font_pointsize] / 8, get_linestyle(series), lc, sp) if ( (st == :shape || series[:fillrange] !== nothing) && @@ -1100,16 +1100,16 @@ function gr_add_legend(sp, leg, viewport_plotarea) ms = first(series[:markersize]) msw = first(series[:markerstrokewidth]) s, sw = if ms > 0 - 0.8 * sp[:legendfontsize], 0.8 * sp[:legendfontsize] * msw / ms + 0.8 * sp[:legend_font_pointsize], 0.8 * sp[:legend_font_pointsize] * msw / ms else - 0, 0.8 * sp[:legendfontsize] * msw / 8 + 0, 0.8 * sp[:legend_font_pointsize] * msw / 8 end gr_draw_markers(series, xpos - leg.width_factor * 2, ypos, clims, s, sw) end lab = series[:label] GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF) - gr_set_textcolor(plot_color(sp[:legendfontcolor])) + gr_set_textcolor(plot_color(sp[:legend_font_color])) gr_text(xpos, ypos, string(lab)) ypos -= leg.dy end @@ -1120,7 +1120,7 @@ function gr_add_legend(sp, leg, viewport_plotarea) end function gr_legend_pos(sp::Subplot, leg, viewport_plotarea) - s = sp[:legend] + s = sp[:legend_position] s isa Real && return gr_legend_pos(s, leg, viewport_plotarea) if s isa Tuple{<:Real,Symbol} if s[2] !== :outer @@ -1236,15 +1236,15 @@ function gr_legend_pos(theta::Real, leg, viewport_plotarea; axisclearance = noth end function gr_get_legend_geometry(viewport_plotarea, sp) - legendn = legendw = dy = 0 - if sp[:legend] != :none + legendn = 0 + legendw = 0 + if sp[:legend_position] != :none GR.savestate() GR.selntran(0) GR.setscale(0) - if sp[:legendtitle] !== nothing + if sp[:legend_title] !== nothing gr_set_font(legendtitlefont(sp), sp) - legendn += 1 - tbx, tby = gr_inqtext(0, 0, string(sp[:legendtitle])) + tbx, tby = gr_inqtext(0, 0, string(sp[:legend_title])) legendw = tbx[3] - tbx[1] dy = tby[3] - tby[1] end @@ -1271,8 +1271,7 @@ function gr_get_legend_geometry(viewport_plotarea, sp) x_legend_offset = (viewport_plotarea[2] - viewport_plotarea[1]) / 30 y_legend_offset = (viewport_plotarea[4] - viewport_plotarea[3]) / 30 - dy *= get(sp[:extra_kwargs], :legend_hfactor, 1) - + dy = gr_point_mult(sp) * sp[:legend_font_pointsize] * 1.75 legendh = dy * legendn return ( @@ -1291,7 +1290,7 @@ end ## Viewport, window and scale function gr_update_viewport_legend!(viewport_plotarea, sp, leg) - s = sp[:legend] + leg_str = string(sp[:legend_position]) xaxis, yaxis = sp[:xaxis], sp[:yaxis] xmirror = @@ -1340,7 +1339,7 @@ function gr_update_viewport_legend!(viewport_plotarea, sp, leg) leg.h + leg.dy + leg.yoffset + !xmirror * gr_axis_height(sp, sp[:xaxis]) end end - if s === :inline + if sp[:legend_position] == :inline if sp[:yaxis][:mirror] viewport_plotarea[1] += leg.w else @@ -1841,7 +1840,7 @@ function gr_add_series(sp, series) elseif st in (:surface, :wireframe, :mesh3d) gr_draw_surface(series, x, y, z, clims) elseif st === :volume - sp[:legend] = :none + sp[:legend_position] = :none GR.gr3.clear() dmin, dmax = GR.gr3.volume(y.v, 0) elseif st === :heatmap @@ -1859,9 +1858,9 @@ function gr_add_series(sp, series) gr_text(GR.wctondc(xi, yi)..., str) end - if sp[:legend] == :inline && should_add_to_legend(series) + if sp[:legend_position] == :inline && should_add_to_legend(series) gr_set_font(legendfont(sp), sp) - gr_set_textcolor(plot_color(sp[:legendfontcolor])) + gr_set_textcolor(plot_color(sp[:legend_font_color])) if sp[:yaxis][:mirror] (_, i) = sp[:xaxis][:flip] ? findmax(x) : findmin(x) GR.settextalign(GR.TEXT_HALIGN_RIGHT, GR.TEXT_VALIGN_HALF) diff --git a/src/backends/inspectdr.jl b/src/backends/inspectdr.jl index e5db6d2b..748710e5 100644 --- a/src/backends/inspectdr.jl +++ b/src/backends/inspectdr.jl @@ -390,38 +390,33 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend}) #Modify base layout of new object: l = plot.layout.defaults = deepcopy(InspectDR.defaults.plotlayout) - #IMPORTANT: Must deepcopy to ensure we don't change layouts of other plots. - #Works because plot uses defaults (not user-overwritten `layout.values`) - l.frame_canvas.fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot]) - l.frame_data.fillcolor = _inspectdr_mapcolor(sp[:background_color_inside]) - l.frame_data.line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis]) - l.font_title = InspectDR.Font( - sp[:titlefontfamily], - _inspectdr_mapptsize(sp[:titlefontsize]), - color = _inspectdr_mapcolor(sp[:titlefontcolor]), - ) - #Cannot independently control fonts of axes with InspectDR: - l.font_axislabel = InspectDR.Font( - xaxis[:guidefontfamily], - _inspectdr_mapptsize(xaxis[:guidefontsize]), - color = _inspectdr_mapcolor(xaxis[:guidefontcolor]), - ) - l.font_ticklabel = InspectDR.Font( - xaxis[:tickfontfamily], - _inspectdr_mapptsize(xaxis[:tickfontsize]), - color = _inspectdr_mapcolor(xaxis[:tickfontcolor]), - ) - l.enable_legend = (sp[:legend] != :none) - #l.halloc_legend = 150 #TODO: compute??? - l.font_legend = InspectDR.Font( - sp[:legendfontfamily], - _inspectdr_mapptsize(sp[:legendfontsize]), - color = _inspectdr_mapcolor(sp[:legendfontcolor]), - ) - l.frame_legend.fillcolor = _inspectdr_mapcolor(sp[:background_color_legend]) - - #_round!() ensures values use integer spacings (looks better on screen): - InspectDR._round!(InspectDR.autofit2font!(l, legend_width = 10.0)) #10 "em"s wide + #IMPORTANT: Must deepcopy to ensure we don't change layouts of other plots. + #Works because plot uses defaults (not user-overwritten `layout.values`) + l.frame_canvas.fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot]) + l.frame_data.fillcolor = _inspectdr_mapcolor(sp[:background_color_inside]) + l.frame_data.line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis]) + l.font_title = InspectDR.Font(sp[:titlefontfamily], + _inspectdr_mapptsize(sp[:titlefontsize]), + color = _inspectdr_mapcolor(sp[:titlefontcolor]) + ) + #Cannot independently control fonts of axes with InspectDR: + l.font_axislabel = InspectDR.Font(xaxis[:guidefontfamily], + _inspectdr_mapptsize(xaxis[:guidefontsize]), + color = _inspectdr_mapcolor(xaxis[:guidefontcolor]) + ) + l.font_ticklabel = InspectDR.Font(xaxis[:tickfontfamily], + _inspectdr_mapptsize(xaxis[:tickfontsize]), + color = _inspectdr_mapcolor(xaxis[:tickfontcolor]) + ) + l[:enable_legend] = (sp[:legend_position] != :none) + #l[:halloc_legend] = 150 #TODO: compute??? + l[:font_legend] = InspectDR.Font(sp[:legend_font_family], + _inspectdr_mapptsize(sp[:legend_font_pointsize]), + color = _inspectdr_mapcolor(sp[:legend_font_color]) + ) + l[:frame_legend].fillcolor = _inspectdr_mapcolor(sp[:legend_background_color]) + #_round!() ensures values use integer spacings (looks better on screen): + InspectDR._round!(InspectDR.autofit2font!(l, legend_width=10.0)) #10 "em"s wide return end diff --git a/src/backends/pgfplotsx.jl b/src/backends/pgfplotsx.jl index 6bcb694f..37f6da2a 100644 --- a/src/backends/pgfplotsx.jl +++ b/src/backends/pgfplotsx.jl @@ -146,7 +146,7 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend}) "point meta max" => get_clims(sp)[2], "point meta min" => get_clims(sp)[1], "legend cell align" => "left", - "legend columns" => pgfx_legend_col(sp[:legend]), + "legend columns" => pgfx_legend_col(sp[:legend_position]), "title" => sp[:title], "title style" => PGFPlotsX.Options( pgfx_get_title_pos(title_loc)..., @@ -166,8 +166,9 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend}) sp_width > 0 * mm ? push!(axis_opt, "width" => string(axis_width)) : nothing sp_height > 0 * mm ? push!(axis_opt, "height" => string(axis_height)) : nothing for letter in (:x, :y, :z) - if letter != :z || RecipesPipeline.is3d(sp) - pgfx_axis!(axis_opt, sp, letter) + if letter != :z || + RecipesPipeline.is3d(sp) + pgfx_axis!(axis_opt, sp, letter) end end # Search series for any gradient. In case one series uses a gradient set @@ -248,12 +249,12 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend}) extra_sp = wraptuple(extra_sp) push!(axis, extra_sp...) end - if sp[:legendtitle] !== nothing + if sp[:legend_title] !== nothing push!(axis, PGFPlotsX.Options("\\addlegendimage{empty legend}" => nothing)) push!( axis, PGFPlotsX.LegendEntry( - string("\\hspace{-.6cm}{\\textbf{", sp[:legendtitle], "}}"), + string("\\hspace{-.6cm}{\\textbf{", sp[:legend_title], "}}"), false, ), ) @@ -378,11 +379,8 @@ function pgfx_add_series!(::Val{:path}, axis, series_opt, series, series_func, o ) end end - if ( - k == 1 && - series[:subplot][:legend] != :none && - pgfx_should_add_to_legend(series) - ) + if i == 1 && + series[:subplot][:legend_position] != :none && pgfx_should_add_to_legend(series) pgfx_filllegend!(series_opt, opt) end end @@ -655,7 +653,7 @@ function pgfx_add_series!(::Val{:xsticks}, axis, series_opt, series, series_func end function pgfx_add_legend!(axis, series, opt, i = 1) - if series[:subplot][:legend] != :none + if series[:subplot][:legend_position] != :none leg_entry = if opt[:label] isa AVec get(opt[:label], i, "") elseif opt[:label] isa AbstractString @@ -1232,9 +1230,7 @@ end function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter) axis = sp[get_attr_symbol(letter, :axis)] - # turn off scaled ticks - push!(opt, "scaled $(letter) ticks" => "false", string(letter, :label) => axis[:guide]) - tick_color = plot_color(axis[:foreground_color_axis]) +# turn off scaled ticks push!( opt, "$(letter) tick style" => @@ -1455,9 +1451,8 @@ end # Set the (left, top, right, bottom) minimum padding around the plot area # to fit ticks, tick labels, guides, colorbars, etc. function _update_min_padding!(sp::Subplot{PGFPlotsXBackend}) - leg = sp[:legend] - if leg in (:best, :outertopright, :outerright, :outerbottomright) || - (leg isa Tuple && leg[1] >= 1) + leg = sp[:legend_position] + if leg in (:best, :outertopright, :outerright, :outerbottomright) || (leg isa Tuple && leg[1] >= 1) sp.minpad = (0mm, 0mm, 5mm, 0mm) else sp.minpad = (0mm, 0mm, 0mm, 0mm) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 5269ab14..79ab1f70 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -338,12 +338,12 @@ function plotly_layout(plt::Plot) end function plotly_add_legend!(plotattributes_out::KW, sp::Subplot) - plotattributes_out[:showlegend] = sp[:legend] != :none - legend_position = plotly_legend_pos(sp[:legend]) - if sp[:legend] != :none - plotattributes_out[:legend] = KW( - :bgcolor => rgba_string(sp[:background_color_legend]), - :bordercolor => rgba_string(sp[:foreground_color_legend]), + plotattributes_out[:showlegend] = sp[:legend_position] != :none + legend_position = plotly_legend_pos(sp[:legend_position]) + if sp[:legend_position] != :none + plotattributes_out[:legend_position] = KW( + :bgcolor => rgba_string(sp[:legend_background_color]), + :bordercolor => rgba_string(sp[:legend_foreground_color]), :borderwidth => 1, :traceorder => "normal", :xanchor => legend_position.xanchor, @@ -353,7 +353,7 @@ function plotly_add_legend!(plotattributes_out::KW, sp::Subplot) :x => legend_position.coords[1], :y => legend_position.coords[2], :title => KW( - :text => sp[:legendtitle] === nothing ? "" : string(sp[:legendtitle]), + :text => sp[:legend_title] === nothing ? "" : string(sp[:legend_title]), :font => plotly_font(legendtitlefont(sp)), ), ) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 0cb1ee40..36c9b69f 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1566,7 +1566,7 @@ end py_legend_bbox(pos) = pos function py_add_legend(plt::Plot, sp::Subplot, ax) - leg = sp[:legend] + leg = sp[:legend_position] if leg != :none # gotta do this to ensure both axes are included labels = [] @@ -1607,10 +1607,20 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) linestyle = py_linestyle(series[:seriestype], ls), capstyle = "butt", ) - - # plot two handles on top of each other by passing in a tuple - # https://matplotlib.org/stable/tutorials/intermediate/legend_guide.html - push!(handles, (line_handle, fill_handle)) + elseif series[:seriestype] in (:path, :straightline, :scatter, :steppre, :stepmid, :steppost) + hasline = get_linewidth(series) > 0 + PyPlot.plt."Line2D"((0, 1),(0,0), + color = py_color(single_color(get_linecolor(series, clims)), get_linealpha(series)), + linewidth = py_thickness_scale(plt, hasline * sp[:legend_font_pointsize] / 8), + linestyle = py_linestyle(:path, get_linestyle(series)), + solid_capstyle = "butt", solid_joinstyle = "miter", + dash_capstyle = "butt", dash_joinstyle = "miter", + marker = py_marker(_cycle(series[:markershape], 1)), + markersize = py_thickness_scale(plt, 0.8 * sp[:legend_font_pointsize]), + markeredgecolor = py_color(single_color(get_markerstrokecolor(series)), get_markerstrokealpha(series)), + markerfacecolor = py_color(single_color(get_markercolor(series, clims)), get_markeralpha(series)), + markeredgewidth = py_thickness_scale(plt, 0.8 * get_markerstrokewidth(series) * sp[:legend_font_pointsize] / first(series[:markersize])) # retain the markersize/markerstroke ratio from the markers on the plot + ) else # plot line handle (which includes solid fill) only push!(handles, line_handle) @@ -1667,35 +1677,23 @@ function py_add_legend(plt::Plot, sp::Subplot, ax) loc = py_legend_pos(leg), bbox_to_anchor = py_legend_bbox(leg), scatterpoints = 1, - fontsize = py_thickness_scale(plt, sp[:legendfontsize]), - facecolor = py_color(sp[:background_color_legend]), - edgecolor = py_color(sp[:foreground_color_legend]), - framealpha = alpha(plot_color(sp[:background_color_legend])), + fontsize = py_thickness_scale(plt, sp[:legend_font_pointsize]), + facecolor = py_color(sp[:legend_background_color]), + edgecolor = py_color(sp[:legend_foreground_color]), + framealpha = alpha(plot_color(sp[:legend_background_color])), fancybox = false, # makes the legend box square borderpad = 0.8, # to match GR legendbox ) frame = leg."get_frame"() frame."set_linewidth"(py_thickness_scale(plt, 1)) leg."set_zorder"(1000) - if sp[:legendtitle] !== nothing - leg."set_title"(sp[:legendtitle]) - PyPlot.plt."setp"( - leg."get_title"(), - color = py_color(sp[:legendtitlefontcolor]), - family = sp[:legendtitlefontfamily], - math_fontfamily = py_get_matching_math_font(sp[:legendtitlefontfamily]), - fontsize = py_thickness_scale(plt, sp[:legendtitlefontsize]), - ) + if sp[:legend_title] !== nothing + leg."set_title"(sp[:legend_title]) + PyPlot.plt."setp"(leg."get_title"(), color = py_color(sp[:legend_title_font_color]), family = sp[:legend_title_font_family], fontsize = py_thickness_scale(plt, sp[:legend_title_font_pointsize])) end for txt in leg."get_texts"() - PyPlot.plt."setp"( - txt, - color = py_color(sp[:legendfontcolor]), - family = sp[:legendfontfamily], - math_fontfamily = py_get_matching_math_font(sp[:legendtitlefontfamily]), - fontsize = py_thickness_scale(plt, sp[:legendfontsize]), - ) + PyPlot.plt."setp"(txt, color = py_color(sp[:legend_font_color]), family = sp[:legend_font_family], fontsize = py_thickness_scale(plt, sp[:legend_font_pointsize])) end end end diff --git a/src/backends/unicodeplots.jl b/src/backends/unicodeplots.jl index a7697c10..21c44b47 100644 --- a/src/backends/unicodeplots.jl +++ b/src/backends/unicodeplots.jl @@ -54,7 +54,7 @@ function unicodeplots_rebuild(plt::Plot{UnicodePlotsBackend}) o = UnicodePlots.Plot(x, y, _canvas_map[canvas_type]; kw...) for series in series_list(sp) - o = addUnicodeSeries!(sp, o, kw, series, sp[:legend] != :none) + addUnicodeSeries!(o, series.plotattributes, sp[:legend_position] != :none, xlim, ylim) end for ann in sp[:annotations] diff --git a/src/components.jl b/src/components.jl index 75088ba1..b2f3ae5f 100644 --- a/src/components.jl +++ b/src/components.jl @@ -775,12 +775,13 @@ end ### Legend -@add_annotations subplot struct Legend - background_color - foreground_color - position - title - font::Font # TODO: check if macro is recursive enough - title_font - column +# TODO: what about :match for the fonts? +@add_attributes subplot struct Legend + background_color = :match + foreground_color = :match + position = :best + title = nothing + font::Font = font(8) + title_font::Font = font(11) + column = 1 end diff --git a/src/consts.jl b/src/consts.jl new file mode 100644 index 00000000..49bee86b --- /dev/null +++ b/src/consts.jl @@ -0,0 +1,51 @@ + +const _all_defaults = KW[_series_defaults, _plot_defaults, _subplot_defaults] + +const _initial_defaults = deepcopy(_all_defaults) +const _initial_axis_defaults = deepcopy(_axis_defaults) + +# to be able to reset font sizes to initial values +const _initial_fontsizes = Dict( + :titlefontsize => _subplot_defaults[:titlefontsize], + :legend_font_pointsize => _subplot_defaults[:legend_font_pointsize], + :legend_title_font_pointsize => _subplot_defaults[:legend_title_font_pointsize], + :tickfontsize => _axis_defaults[:tickfontsize], + :guidefontsize => _axis_defaults[:guidefontsize], +) + +const _internal_args = + [:plot_object, :series_plotindex, :markershape_to_add, :letter, :idxfilter] + +const _axis_args = sort(union(collect(keys(_axis_defaults)))) +const _series_args = sort(union(collect(keys(_series_defaults)))) +const _subplot_args = sort(union(collect(keys(_subplot_defaults)))) +const _plot_args = sort(union(collect(keys(_plot_defaults)))) + +const _magic_axis_args = [:axis, :tickfont, :guidefont, :grid, :minorgrid] +const _magic_subplot_args = [ + :titlefont, + :legendfont, + :legend_titlefont, + :plot_titlefont, + :colorbar_titlefont, +] +const _magic_series_args = [:line, :marker, :fill] + +const _all_axis_args = sort(union([_axis_args; _magic_axis_args])) +const _all_subplot_args = sort(union([_subplot_args; _magic_subplot_args])) +const _all_series_args = sort(union([_series_args; _magic_series_args])) +const _all_plot_args = _plot_args + +const _all_args = sort(union([ + _all_axis_args + _all_subplot_args + _all_series_args + _all_plot_args +])) + +# add all pluralized forms to the _keyAliases dict +for arg in _all_args + add_aliases(arg, makeplural(arg)) +end +# add all non_underscored forms to the _keyAliases +add_non_underscore_aliases!(_keyAliases) diff --git a/src/utils.jl b/src/utils.jl index 5f6d3c59..a5409ba3 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -648,7 +648,7 @@ function with(f::Function, args...; kw...) newdefs[:xticks] = nothing newdefs[:yticks] = nothing newdefs[:grid] = false - newdefs[:legend] = false + newdefs[:legend_position] = false end # dict to store old and new keyword args for anything that changes @@ -982,22 +982,22 @@ titlefont(sp::Subplot) = font(; color = sp[:titlefontcolor], ) -legendfont(sp::Subplot) = font(; - family = sp[:legendfontfamily], - pointsize = sp[:legendfontsize], - valign = sp[:legendfontvalign], - halign = sp[:legendfonthalign], - rotation = sp[:legendfontrotation], - color = sp[:legendfontcolor], +legendfont(sp::Subplot) = font( + sp[:legend_font_family], + sp[:legend_font_pointsize], + sp[:legend_font_valign], + sp[:legend_font_halign], + sp[:legend_font_rotation], + sp[:legend_font_color], ) -legendtitlefont(sp::Subplot) = font(; - family = sp[:legendtitlefontfamily], - pointsize = sp[:legendtitlefontsize], - valign = sp[:legendtitlefontvalign], - halign = sp[:legendtitlefonthalign], - rotation = sp[:legendtitlefontrotation], - color = sp[:legendtitlefontcolor], +legendtitlefont(sp::Subplot) = font( + sp[:legend_title_font_family], + sp[:legend_title_font_pointsize], + sp[:legend_title_font_valign], + sp[:legend_title_font_halign], + sp[:legend_title_font_rotation], + sp[:legend_title_font_color], ) tickfont(ax::Axis) = font(; diff --git a/test/test_defaults.jl b/test/test_defaults.jl index 9ce50738..8ca669d7 100644 --- a/test/test_defaults.jl +++ b/test/test_defaults.jl @@ -1,4 +1,4 @@ -using Plots, Test +using Plots, Test, Colors const PLOTS_DEFAULTS = Dict(:theme => :wong2, :fontfamily => :palantino) Plots.__init__() @@ -11,3 +11,64 @@ end empty!(PLOTS_DEFAULTS) Plots.__init__() + +@testset "Legend defaults" begin + p = plot() + @test p[1][:legend_font_family] == "sans-serif" + @test p[1][:legend_font_pointsize] == 8 + @test p[1][:legend_font_halign] == :hcenter + @test p[1][:legend_font_valign] == :vcenter + @test p[1][:legend_font_rotation] == 0.0 + @test p[1][:legend_font_color] == RGB{Colors.N0f8}(0.0,0.0,0.0) + @test p[1][:legend_position] == :best + @test p[1][:legend_title] == nothing + @test p[1][:legend_title_font_family] == "sans-serif" + @test p[1][:legend_title_font_pointsize] == 11 + @test p[1][:legend_title_font_halign] == :hcenter + @test p[1][:legend_title_font_valign] == :vcenter + @test p[1][:legend_title_font_rotation] == 0.0 + @test p[1][:legend_title_font_color] == RGB{Colors.N0f8}(0.0,0.0,0.0) + @test p[1][:legend_background_color] == RGBA{Float64}(1.0,1.0,1.0,1.0) + @test p[1][:legend_foreground_color] == RGB{Colors.N0f8}(0.0,0.0,0.0) +end # testset + +@testset "Legend API" begin + p = plot(; + legendfontfamily = "serif", + legendfontsize = 12, + legendfonthalign = :left, + legendfontvalign = :top, + legendfontrotation = 1, + legendfontcolor = :red, + legend = :outertopleft, + legendtitle = "The legend", + legendtitlefontfamily = "helvetica", + legendtitlefontsize = 3, + legendtitlefonthalign = :right, + legendtitlefontvalign = :bottom, + legendtitlefontrotation = -5.2, + legendtitlefontcolor = :blue, + background_color_legend = :cyan, + foreground_color_legend = :green, + ) + @test p[1][:legend_font_family] == "serif" + @test p[1][:legend_font_pointsize] == 12 + @test p[1][:legend_font_halign] == :left + @test p[1][:legend_font_valign] == :top + @test p[1][:legend_font_rotation] == 1.0 + @test_broken p[1][:legend_font_color] == RGB{Colors.N0f8}(1.0,0.0,0.0) + # FIXME: this doesn't get set + @test_broken p[1][:legend_position] == :outertopleft + # FIXME: this doesn't get set + @test_broken p[1][:legend_title] == "The legend" + @test p[1][:legend_title_font_family] == "helvetica" + # FIXME: this doesn't get set + @test_broken p[1][:legend_title_font_pointsize] == 3 + @test p[1][:legend_title_font_halign] == :right + @test p[1][:legend_title_font_valign] == :bottom + @test p[1][:legend_title_font_rotation] == -5.2 + # This currently propagates "blue" + @test_broken p[1][:legend_title_font_color] == RGB{Colors.N0f8}(0.0,0.0,1.0) + @test p[1][:legend_background_color] == RGBA{Float64}(0.0,1.0,1.0,1.0) + @test p[1][:legend_foreground_color] == RGBA{Float64}(0.0,0.5019607843137255,0.0,1.0) +end # testset