Class: CTioga2::Graphics::Styles::PlotStyle

Inherits:
Object
  • Object
show all
Includes:
Log, Tioga::FigureConstants
Defined in:
lib/ctioga2/graphics/styles/plot.rb

Overview

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.

Constant Summary collapse

@@current_index =
0

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Log

context, debug, error, fatal, #format_exception, #identify, info, init_logger, log_to, logger, set_level, #spawn, warn

Constructor Details

#initializePlotStyle

Returns a new instance of PlotStyle.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/ctioga2/graphics/styles/plot.rb', line 90

def initialize
  # Default style for the plots.
  @axes = {}
  @axes[:left] = 
    StyleSheet.style_for(AxisStyle, 'left', :left, 
                         AXIS_WITH_TICKS_AND_NUMERIC_LABELS,
                         '$y$')
  @axes[:bottom] = 
    StyleSheet.style_for(AxisStyle, 'bottom', :bottom, 
                         AXIS_WITH_TICKS_AND_NUMERIC_LABELS,
                         '$x$')

  @axes[:right] = 
    StyleSheet.style_for(AxisStyle, 'right', :right, 
                         AXIS_WITH_TICKS_ONLY)
  @axes[:top] = 
    StyleSheet.style_for(AxisStyle, 'top', :top, 
                         AXIS_WITH_TICKS_ONLY)

  @xaxis_location = :bottom
  @yaxis_location = :left

  @title = 
    StyleSheet.style_for(TextLabel, 'title',
                         nil, 
                         Types::PlotLocation.new(:top))
  @plot_margin = nil

  @transforms = CoordinateTransforms.new

  @background = 
    StyleSheet.style_for(BackgroundStyle, 'background')

  # 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

Instance Attribute Details

#axesObject

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



45
46
47
# File 'lib/ctioga2/graphics/styles/plot.rb', line 45

def axes
  @axes
end

#backgroundObject

Style of the background of the plot



65
66
67
# File 'lib/ctioga2/graphics/styles/plot.rb', line 65

def background
  @background
end

#frame_real_sizeObject

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 the output dimensions.



85
86
87
# File 'lib/ctioga2/graphics/styles/plot.rb', line 85

def frame_real_size
  @frame_real_size
end

#lines_scaleObject

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



69
70
71
# File 'lib/ctioga2/graphics/styles/plot.rb', line 69

def lines_scale
  @lines_scale
end

#paddingObject

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



77
78
79
# File 'lib/ctioga2/graphics/styles/plot.rb', line 77

def padding
  @padding
end

#plot_marginObject

A margin to be left around the data points



57
58
59
# File 'lib/ctioga2/graphics/styles/plot.rb', line 57

def plot_margin
  @plot_margin
end

#text_auto_adjustObject

Mode for auto-adjust



80
81
82
# File 'lib/ctioga2/graphics/styles/plot.rb', line 80

def text_auto_adjust
  @text_auto_adjust
end

#text_scaleObject

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



73
74
75
# File 'lib/ctioga2/graphics/styles/plot.rb', line 73

def text_scale
  @text_scale
end

#titleObject

The title of the plot



54
55
56
# File 'lib/ctioga2/graphics/styles/plot.rb', line 54

def title
  @title
end

#transformsObject

TODO:

they should be axis-specific.

Coordinate tranforms



62
63
64
# File 'lib/ctioga2/graphics/styles/plot.rb', line 62

def transforms
  @transforms
end

#xaxis_locationObject

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



48
49
50
# File 'lib/ctioga2/graphics/styles/plot.rb', line 48

def xaxis_location
  @xaxis_location
end

#yaxis_locationObject

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



51
52
53
# File 'lib/ctioga2/graphics/styles/plot.rb', line 51

def yaxis_location
  @yaxis_location
end

Class Method Details

.current_plot_style(plotmaker) ⇒ Object

Returns the PlotStyle object of the current plot



296
297
298
# File 'lib/ctioga2/graphics/styles/plot.rb', line 296

def self.current_plot_style(plotmaker)
  return plotmaker.root_object.current_plot.style
end

Instance Method Details

#apply_transforms!(dataset) ⇒ Object

Apply (destructively) the current transformations to the given dataset



141
142
143
# File 'lib/ctioga2/graphics/styles/plot.rb', line 141

def apply_transforms!(dataset)
  @transforms.transform_2d!(dataset)
end

#clear_axesObject

Clear all axes



327
328
329
330
331
332
333
# File 'lib/ctioga2/graphics/styles/plot.rb', line 327

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) ⇒ Object

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 !



339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/ctioga2/graphics/styles/plot.rb', line 339

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_copyObject

Returns a deep copy of self, with all references stripped.



291
292
293
# File 'lib/ctioga2/graphics/styles/plot.rb', line 291

def deep_copy
  return Marshal.load(Marshal.dump(self))
end

#draw_all_axes(t, bounds) ⇒ Object

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.



254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/ctioga2/graphics/styles/plot.rb', line 254

def draw_all_axes(t, bounds)
  for which, axis in @axes
    t.context do
      begin
        axis.set_bounds_for_axis(t, bounds[which])
        axis.draw_axis(t, @text_sizes)
      rescue Exception => e
        error { "Impossible to draw axis #{which}: #{e.message}" }
        debug { "Full message: #{e.inspect}\n#{e.backtrace.join("\n")}" }
      end
    end
  end
  # We draw the title last
  title.draw(t, 'title', "title-#{@text_size_index}")
end

#draw_all_background_lines(t) ⇒ Object

Draws all axes background lines for the plot.



271
272
273
274
275
# File 'lib/ctioga2/graphics/styles/plot.rb', line 271

def draw_all_background_lines(t)
  for which, axis in @axes
    axis.draw_background_lines(t)
  end
end

#estimate_margins(t) ⇒ Object

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



305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'lib/ctioga2/graphics/styles/plot.rb', line 305

def estimate_margins(t)
  margins = [:left, :right, :top, :bottom].map do |side|
    exts = axes_for_side(side).map do |ax|
      ax.extension(t,self)
    end
    if @title.loc.is_side?(side)
      exts << @title.label_extension(t, 'title', @title.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) ⇒ Object

Returns the key corresponding to the named axis. See #get_axis_style for more information; though ultimately the latter is using this function.



201
202
203
204
205
206
207
# File 'lib/ctioga2/graphics/styles/plot.rb', line 201

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) ⇒ Object

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” ?



188
189
190
191
192
193
194
195
196
# File 'lib/ctioga2/graphics/styles/plot.rb', line 188

def get_axis_style(name)
  style = @axes[get_axis_key(name)]
  if ! style
    ## @todo Type-safe exception here
    raise "Unkown named axis: '#{name}'"
  else
    return style
  end
end

#get_label_style(location) ⇒ Object

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.



224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/ctioga2/graphics/styles/plot.rb', line 224

def get_label_style(location)
  if location =~ /^\s*title\s*$/
    return @title
  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_style(name, style) ⇒ Object



209
210
211
212
# File 'lib/ctioga2/graphics/styles/plot.rb', line 209

def set_axis_style(name, style)
  key = get_axis_key(name)
  @axes[key] = style
end

#set_default_axis(which, name) ⇒ Object

Sets the axis which should be used for subsequent objects (for which no axis is specified) for the given plot



169
170
171
172
# File 'lib/ctioga2/graphics/styles/plot.rb', line 169

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) ⇒ Object

Sets the style of the given label. Sets the text as well, if text is not nil



240
241
242
243
244
245
246
247
# File 'lib/ctioga2/graphics/styles/plot.rb', line 240

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) ⇒ Object

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.



152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/ctioga2/graphics/styles/plot.rb', line 152

def set_log_scale(which, val)
  case which
  when :x
    @axes[:top].log = val
    @axes[:bottom].log = val
    @transforms.x_log = val
  when :y
    @axes[:left].log = val
    @axes[:right].log = val
    @transforms.y_log = val
  else
    raise "Unknown axis: #{which.inspect}"
  end
end

#setup_figure_maker(t) ⇒ Object

Sets up the FigureMaker object for the plot. To be called just after the outermost context call for the concerned plot.



280
281
282
283
284
285
286
287
# File 'lib/ctioga2/graphics/styles/plot.rb', line 280

def setup_figure_maker(t)
  if @lines_scale
    t.rescale_lines(@lines_scale)
  end
  if @text_scale
    t.rescale_text(@text_scale)
  end
end