class CTioga2::Graphics::Styles::PlotStyle

The style of a Elements::Subplot object.

todo it should hold

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

axes[RW]

The various sides of the plot. A hash location -> AxisStyle.

background[RW]

Style of the background of the plot

frame_real_size[RW]

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.

lines_scale[RW]

Scale of the lines of the plot. The plot is wrapped in a t.rescale_lines call.

padding[RW]

A padding around the box when automatic spacing is in auto mode. A Dimension.

plot_margin[RW]

A margin to be left around the data points

target_plot[RW]

The target plot (ie the parent of all the small elements)

text_auto_adjust[RW]

Mode for auto-adjust

text_scale[RW]

Scale of the text of the plot. The plot is wrapped in a t.rescale_text call.

title[RW]

The title of the plot

transforms[RW]

Coordinate tranforms

@todo they should be axis-specific.

xaxis_location[RW]

The default location of the X axis (well, mainly, the X label)

yaxis_location[RW]

The default location of the Y axis (well, mainly, the Y label)

Public Class Methods

current_plot_style(plotmaker) click to toggle source

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
new(plt) click to toggle source
# 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_transforms!(dataset) click to toggle source

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_axes() click to toggle source

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
compute_margins(t, prev_margins) click to toggle source

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
deep_copy() click to toggle source

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
draw_all_axes(t, bounds) click to toggle source

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
draw_all_background_lines(t) click to toggle source

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_margins(t) click to toggle source

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
get_axis_key(name) click to toggle source

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
get_axis_style(name) click to toggle source

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
get_label_style(location) click to toggle source

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
set_axis(name, axis) click to toggle source
# File lib/ctioga2/graphics/styles/plot.rb, line 222
def set_axis(name, axis)
  key = get_axis_key(name)
  @axes[key] = axis
end
set_default_axis(which, name) click to toggle source

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
set_label_style(which, hash, text = nil) click to toggle source

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
set_log_scale(which, val) click to toggle source

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
setup_figure_maker(t) click to toggle source

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

axes_for_side(side) click to toggle source

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
clean_axis_name(name) click to toggle source

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