class CTioga2::Graphics::Styles::PlotStyle
The style of a Elements::Subplot
object.
todo it should hold
-
labels
-
axes and edges (in a clean way !)
-
ticks
-
background (uniform fill + watermark if applicable + possibly a picture .?)
This class is way too complex and needs too much flexibility to be handled by a subclass of BasicStyle
. However, all substyles should be.
Attributes
The various sides of the plot. A hash location -> AxisStyle
.
Style of the background of the plot
If not nil, then the boundaries are computed from the real dimensions of the plot frame, using the given number as a conversion factor from postscript points.
Scale of the lines of the plot. The plot is wrapped in a t.rescale_lines call.
A padding around the box when automatic spacing is in auto mode. A Dimension.
A margin to be left around the data points
The target plot (ie the parent of all the small elements)
Mode for auto-adjust
Scale of the text of the plot. The plot is wrapped in a t.rescale_text call.
The title of the plot
Coordinate tranforms
@todo they should be axis-specific.
The default location of the X axis (well, mainly, the X label)
The default location of the Y axis (well, mainly, the Y label)
Public Class Methods
Returns the PlotStyle
object of the current plot
# File lib/ctioga2/graphics/styles/plot.rb, line 309 def self.current_plot_style(plotmaker) return plotmaker.root_object.current_plot.style end
# File lib/ctioga2/graphics/styles/plot.rb, line 94 def initialize(plt) # Default style for the plots. @target_plot = plt @axes = {} for ax in [:left, :right, :top, :bottom] cls = [ax.to_s] cls << if (ax == :bottom or ax == :top) 'x' else 'y' end dec = if (ax == :bottom or ax == :left) AXIS_WITH_TICKS_AND_NUMERIC_LABELS else AXIS_WITH_TICKS_ONLY end label = nil if ax == :bottom label = '$x$' elsif ax == :left label = '$y$' end axis = Elements::AxisElement.new axis.setup_style(@target_plot, {'class' => cls}) axis.initialize_style(ax, dec, label) @axes[ax] = axis end @xaxis_location = :bottom @yaxis_location = :left @title = Elements::TitleElement.new(@target_plot, {}) @plot_margin = nil @transforms = CoordinateTransforms.new @background = Elements::BackgroundElement.new(@target_plot, {}) # A padding of 6bp ? Why ?? Why not ? @padding = Types::Dimension.new(:bp, 6) @text_size_index = @@current_index @@current_index += 1 # Automatic adjustment of text sizes... @text_sizes = TextSizeWatcher.new @text_sizes.watch("title-#{@text_size_index}") @text_auto_adjust = :both end
Public Instance Methods
Apply (destructively) the current transformations to the given dataset
# File lib/ctioga2/graphics/styles/plot.rb, line 154 def apply_transforms!(dataset) @transforms.transform_2d!(dataset) end
Clear all axes
# File lib/ctioga2/graphics/styles/plot.rb, line 340 def clear_axes() [:left, :right, :top, :bottom].each do |loc| style = get_axis_style(loc) style.decoration = Tioga::FigureConstants::AXIS_HIDDEN style.axis_label.text = false end end
Computes the margins based on the text information.
This is very different from the one above, since this one relies on measured texts to get it right !
# File lib/ctioga2/graphics/styles/plot.rb, line 352 def compute_margins(t, prev_margins) margins = estimate_margins(t) if @text_auto_adjust == :old return margins else pad = if @padding @padding.to_bp(t) else 4 end nm = @text_sizes.update_margins(t, prev_margins, pad) # We include the old margins, unless we have the :measure # text adjust mode if @text_auto_adjust != :measure nm.expand_to!(t, margins) end return nm end end
Returns a deep copy of self, with all references stripped.
# File lib/ctioga2/graphics/styles/plot.rb, line 304 def deep_copy return Marshal.load(Marshal.dump(self)) end
Draws all axes for the plot. The bounds argument is that computed by Subplot#compute_boundaries; it is there to ensure that the axes know whether they have their own coordinate system or if they just follow what's around.
# File lib/ctioga2/graphics/styles/plot.rb, line 267 def draw_all_axes(t, bounds) for which, axis in @axes t.context do begin axis.style.set_bounds_for_axis(t, bounds[which]) axis.style.draw_axis(t, @text_sizes) rescue Exception => e error { "Impossible to draw axis #{which}: #{e.message}" } info { "Full message: #{e.inspect}\n#{e.backtrace.join("\n")}" } end end end # We draw the title last title.style.draw(t, 'title', "title-#{@text_size_index}") end
Draws all axes background lines for the plot.
# File lib/ctioga2/graphics/styles/plot.rb, line 284 def draw_all_background_lines(t) for which, axis in @axes axis.style.draw_background_lines(t) end end
Estimate the margins of the plot whose style this object controls. These margins are used when the plot margins are in automatic mode.
Returns a Types::MarginsBox
# File lib/ctioga2/graphics/styles/plot.rb, line 318 def estimate_margins(t) margins = [:left, :right, :top, :bottom].map do |side| exts = axes_for_side(side).map do |ax| ax.style.extension(t, self) end if @title.style.loc.is_side?(side) exts << @title.style.label_extension(t, 'title', @title.style.loc) * (@text_scale || 1) end Types::Dimension.new(:dy, exts.max || 0) end box = Types::MarginsBox.new(*margins) if @padding for dim in box.margins dim.replace_if_bigger(t, @padding) end end return box end
Returns the key corresponding to the named axis. See get_axis_style
for more information; though ultimately the latter is using this function.
# File lib/ctioga2/graphics/styles/plot.rb, line 214 def get_axis_key(name) if name =~ /^\s*([xy])(?:axis)?\s*$/i return self.send("#{$1.downcase}axis_location") else return clean_axis_name(name) end end
Returns the AxisStyle
corresponding to the named axis. name can be:
-
one of the named axes (ie, by default: top, left, right, bottom). All names are stripped from spaces around, and downcased (see
clean_axis_name
). Can be also user-defined axes. -
x(axis)?/y(axis)?, which returns the default object for the given location
todo Maybe x2 and y2 could be provided to signify “the side which isn't the default” ?
# File lib/ctioga2/graphics/styles/plot.rb, line 201 def get_axis_style(name) axis = @axes[get_axis_key(name)] if ! axis ## @todo Type-safe exception here raise "Unkown named axis: '#{name}'" else return axis.style end end
Returns a BaseTextStyle
or similar for the given location. The location is of the form:
axis_name(_(ticks?|label))
or
title
If neither label nor ticks is specified in the first form, ticks are implied.
# File lib/ctioga2/graphics/styles/plot.rb, line 237 def get_label_style(location) if location =~ /^\s*title\s*$/ return @title.style end location =~ /^\s*(.*?)(?:_(ticks?|label))?\s*$/i which = $2 axis = get_axis_style($1) if which =~ /label/ return axis.axis_label else return axis.tick_label_style end end
# File lib/ctioga2/graphics/styles/plot.rb, line 222 def set_axis(name, axis) key = get_axis_key(name) @axes[key] = axis end
Sets
the axis which should be used for subsequent objects (for which no axis is specified) for the given plot
# File lib/ctioga2/graphics/styles/plot.rb, line 182 def set_default_axis(which, name) axis = get_axis_key(name) self.send("#{which}axis_location=", axis) end
Sets
the style of the given label. Sets
the text as well, if text is not nil
# File lib/ctioga2/graphics/styles/plot.rb, line 253 def set_label_style(which, hash, text = nil) style = get_label_style(which) hash = hash.merge({'text' => text}) unless text.nil? if hash.key?('text') and ! style.is_a?(TextLabel) CTioga2::Log::warn {"Text property of label #{which} was set, but this has no meaning: tick labels can't be set this way. Did you mean to use \"#{which}_label\"" + " instead ?" } end style.set_from_hash(hash) end
Whether to use log scale for the given axis.
Now the question is: how should that affect user-defined axes ? It should not.
todo This really should move to Axis when transformations are handled correctly.
# File lib/ctioga2/graphics/styles/plot.rb, line 165 def set_log_scale(which, val) case which when :x @axes[:top].style.log = val @axes[:bottom].style.log = val @transforms.x_log = val when :y @axes[:left].style.log = val @axes[:right].style.log = val @transforms.y_log = val else raise "Unknown axis: #{which.inspect}" end end
Sets
up the FigureMaker object for the plot. To be called just after the outermost context call for the concerned plot.
# File lib/ctioga2/graphics/styles/plot.rb, line 293 def setup_figure_maker(t) if @lines_scale t.rescale_lines(@lines_scale) end if @text_scale t.rescale_text(@text_scale) end end
Protected Instance Methods
Returns the list of AxisStyle
corresponding to the given side (:top, :eft, etc…)
# File lib/ctioga2/graphics/styles/plot.rb, line 387 def axes_for_side(side) ret = [] for k,v in @axes ret << v if v.style.location.is_side?(side) end return ret end
Takes a string and returns a Symbol suitable for use with the axes
hash (lower case without spaces).
# File lib/ctioga2/graphics/styles/plot.rb, line 377 def clean_axis_name(name) if name.is_a?(::Symbol) # Argh ! Tioga redefined Symbol ! return name end name =~ /^\s*(.*?)\s*$/ return $1.downcase.to_sym end