ctioga2 0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +339 -0
- data/Changelog +6 -0
- data/bin/ctioga2 +26 -0
- data/lib/ctioga2/commands/arguments.rb +58 -0
- data/lib/ctioga2/commands/commands.rb +258 -0
- data/lib/ctioga2/commands/doc/doc.rb +118 -0
- data/lib/ctioga2/commands/doc/documentation-commands.rb +119 -0
- data/lib/ctioga2/commands/doc/help.rb +95 -0
- data/lib/ctioga2/commands/doc/html.rb +230 -0
- data/lib/ctioga2/commands/doc/introspection.rb +211 -0
- data/lib/ctioga2/commands/doc/man.rb +279 -0
- data/lib/ctioga2/commands/doc/markup.rb +359 -0
- data/lib/ctioga2/commands/general-commands.rb +119 -0
- data/lib/ctioga2/commands/general-types.rb +118 -0
- data/lib/ctioga2/commands/groups.rb +73 -0
- data/lib/ctioga2/commands/interpreter.rb +257 -0
- data/lib/ctioga2/commands/parsers/command-line.rb +187 -0
- data/lib/ctioga2/commands/parsers/file.rb +186 -0
- data/lib/ctioga2/commands/strings.rb +303 -0
- data/lib/ctioga2/commands/type.rb +100 -0
- data/lib/ctioga2/commands/variables.rb +101 -0
- data/lib/ctioga2/data/backends/backend.rb +260 -0
- data/lib/ctioga2/data/backends/backends.rb +39 -0
- data/lib/ctioga2/data/backends/backends/gnuplot.rb +140 -0
- data/lib/ctioga2/data/backends/backends/math.rb +121 -0
- data/lib/ctioga2/data/backends/backends/text.rb +335 -0
- data/lib/ctioga2/data/backends/description.rb +405 -0
- data/lib/ctioga2/data/backends/factory.rb +73 -0
- data/lib/ctioga2/data/backends/parameter.rb +109 -0
- data/lib/ctioga2/data/datacolumn.rb +245 -0
- data/lib/ctioga2/data/dataset.rb +233 -0
- data/lib/ctioga2/data/filters.rb +131 -0
- data/lib/ctioga2/data/merge.rb +43 -0
- data/lib/ctioga2/data/point.rb +72 -0
- data/lib/ctioga2/data/stack.rb +294 -0
- data/lib/ctioga2/graphics/coordinates.rb +73 -0
- data/lib/ctioga2/graphics/elements.rb +111 -0
- data/lib/ctioga2/graphics/elements/containers.rb +111 -0
- data/lib/ctioga2/graphics/elements/curve2d.rb +155 -0
- data/lib/ctioga2/graphics/elements/element.rb +90 -0
- data/lib/ctioga2/graphics/elements/primitive.rb +256 -0
- data/lib/ctioga2/graphics/elements/subplot.rb +140 -0
- data/lib/ctioga2/graphics/generator.rb +68 -0
- data/lib/ctioga2/graphics/legends.rb +108 -0
- data/lib/ctioga2/graphics/legends/area.rb +199 -0
- data/lib/ctioga2/graphics/legends/items.rb +183 -0
- data/lib/ctioga2/graphics/legends/provider.rb +58 -0
- data/lib/ctioga2/graphics/legends/storage.rb +65 -0
- data/lib/ctioga2/graphics/root.rb +209 -0
- data/lib/ctioga2/graphics/styles.rb +30 -0
- data/lib/ctioga2/graphics/styles/axes.rb +247 -0
- data/lib/ctioga2/graphics/styles/background.rb +122 -0
- data/lib/ctioga2/graphics/styles/base.rb +115 -0
- data/lib/ctioga2/graphics/styles/carrays.rb +53 -0
- data/lib/ctioga2/graphics/styles/curve.rb +101 -0
- data/lib/ctioga2/graphics/styles/drawable.rb +87 -0
- data/lib/ctioga2/graphics/styles/factory.rb +351 -0
- data/lib/ctioga2/graphics/styles/legend.rb +63 -0
- data/lib/ctioga2/graphics/styles/plot.rb +410 -0
- data/lib/ctioga2/graphics/styles/sets.rb +64 -0
- data/lib/ctioga2/graphics/styles/texts.rb +277 -0
- data/lib/ctioga2/graphics/subplot-commands.rb +141 -0
- data/lib/ctioga2/graphics/types.rb +188 -0
- data/lib/ctioga2/graphics/types/bijection.rb +79 -0
- data/lib/ctioga2/graphics/types/boundaries.rb +170 -0
- data/lib/ctioga2/graphics/types/boxes.rb +157 -0
- data/lib/ctioga2/graphics/types/dimensions.rb +157 -0
- data/lib/ctioga2/graphics/types/point.rb +247 -0
- data/lib/ctioga2/log.rb +97 -0
- data/lib/ctioga2/metabuilder/type.rb +316 -0
- data/lib/ctioga2/metabuilder/types.rb +39 -0
- data/lib/ctioga2/metabuilder/types/coordinates.rb +124 -0
- data/lib/ctioga2/metabuilder/types/dates.rb +43 -0
- data/lib/ctioga2/metabuilder/types/lists.rb +188 -0
- data/lib/ctioga2/metabuilder/types/numbers.rb +97 -0
- data/lib/ctioga2/metabuilder/types/strings.rb +93 -0
- data/lib/ctioga2/metabuilder/types/styles.rb +178 -0
- data/lib/ctioga2/plotmaker.rb +677 -0
- data/lib/ctioga2/postprocess.rb +115 -0
- data/lib/ctioga2/utils.rb +120 -0
- data/setup.rb +1586 -0
- metadata +144 -0
@@ -0,0 +1,351 @@
|
|
1
|
+
# factory.rb: an object in charge of generating the style for Curves
|
2
|
+
# copyright (c) 2009 by Vincent Fourmond
|
3
|
+
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation; either version 2 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details (in the COPYING file).
|
13
|
+
|
14
|
+
require 'ctioga2/utils'
|
15
|
+
require 'ctioga2/log'
|
16
|
+
|
17
|
+
# This module contains all the classes used by ctioga
|
18
|
+
module CTioga2
|
19
|
+
|
20
|
+
Version::register_svn_info('$Revision: 59 $', '$Date: 2009-05-28 23:15:50 +0200 (Thu, 28 May 2009) $')
|
21
|
+
|
22
|
+
module Graphics
|
23
|
+
|
24
|
+
module Styles
|
25
|
+
|
26
|
+
# This object is in charge of the generation of the CurveStyle
|
27
|
+
# object for the next curve to be drawn.
|
28
|
+
class CurveStyleFactory
|
29
|
+
|
30
|
+
include Log
|
31
|
+
|
32
|
+
# A private class that defines a parameter for the Factory
|
33
|
+
class CurveStyleFactoryParameter
|
34
|
+
|
35
|
+
# The code-like name of the parameter
|
36
|
+
attr_accessor :name
|
37
|
+
|
38
|
+
# The Commands::CommandType of the parameter
|
39
|
+
attr_accessor :type
|
40
|
+
|
41
|
+
# The pre-defined sets available to use with that
|
42
|
+
# parameter. It is a hash.
|
43
|
+
attr_accessor :sets
|
44
|
+
|
45
|
+
# The description of the parameter.
|
46
|
+
attr_accessor :description
|
47
|
+
|
48
|
+
# The short option for setting the parameter directly from
|
49
|
+
# the command-line.
|
50
|
+
attr_accessor :short_option
|
51
|
+
|
52
|
+
# The MetaBuilder::Type object that can convert a String to
|
53
|
+
# an Array suitable for use with CircularArray.
|
54
|
+
attr_accessor :sets_type
|
55
|
+
|
56
|
+
|
57
|
+
# Creates a new CurveStyleFactoryParameter object.
|
58
|
+
def initialize(name, type, sets, description,
|
59
|
+
short_option = nil)
|
60
|
+
@name = name
|
61
|
+
@type = Commands::CommandType.get_type(type)
|
62
|
+
@sets = sets
|
63
|
+
@description = description
|
64
|
+
@short_option = short_option
|
65
|
+
|
66
|
+
# TODO: it is not very satisfying to mix CommandTypes and
|
67
|
+
# MetaBuilder::Type on the same level.
|
68
|
+
if @sets
|
69
|
+
@sets_type =
|
70
|
+
MetaBuilder::Type.get_type({
|
71
|
+
:type => :set,
|
72
|
+
:subtype => @type.type,
|
73
|
+
:shortcuts => @sets
|
74
|
+
})
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns a suitable default set for the given object.
|
79
|
+
def default_set
|
80
|
+
return nil unless @sets
|
81
|
+
if @sets.key? 'default'
|
82
|
+
return @sets['default']
|
83
|
+
else
|
84
|
+
@sets.each do |k,v|
|
85
|
+
return v
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
# Switch some parameter back to automatic
|
93
|
+
AutoRE = /auto/i
|
94
|
+
|
95
|
+
# Sets some parameter to _false_.
|
96
|
+
DisableRE = /no(ne)?|off/i
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
# Creates a new parameter for the style factory.
|
101
|
+
def self.define_parameter(target, name, type, sets, description,
|
102
|
+
short_option = nil)
|
103
|
+
# We define two new types:
|
104
|
+
# - first, the color-or-auto type:
|
105
|
+
base_type = Commands::CommandType.get_type(type)
|
106
|
+
|
107
|
+
if ! Commands::Interpreter.type("#{base_type.name}-or-auto")
|
108
|
+
mb_type = base_type.type.dup
|
109
|
+
mb_type.re_shortcuts = (mb_type.re_shortcuts ?
|
110
|
+
mb_type.re_shortcuts.dup : {})
|
111
|
+
|
112
|
+
mb_type.re_shortcuts[AutoRE] = 'auto'
|
113
|
+
mb_type.re_shortcuts[DisableRE] = false
|
114
|
+
|
115
|
+
# Now, register a type for the type or automatic.
|
116
|
+
CmdType.new("#{base_type.name}-or-auto", mb_type,
|
117
|
+
"Same thing as type #{base_type.name}, or 'auto'")
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
if sets and ! Commands::Interpreter.type("#{base_type.name}-set")
|
122
|
+
# Now, register a type for the type or automatic.
|
123
|
+
CmdType.new("#{base_type.name}-set",{
|
124
|
+
:type => :set,
|
125
|
+
:subtype => base_type.type,
|
126
|
+
:shortcuts => sets
|
127
|
+
} ,
|
128
|
+
"Sets of #{base_type.name}")
|
129
|
+
end
|
130
|
+
param =
|
131
|
+
CurveStyleFactoryParameter.new(name, type, sets,
|
132
|
+
description, short_option)
|
133
|
+
@parameters ||= {}
|
134
|
+
@parameters[target] = param
|
135
|
+
|
136
|
+
@name_to_target ||= {}
|
137
|
+
@name_to_target[name] = target
|
138
|
+
end
|
139
|
+
|
140
|
+
# Returns the Hash containing the class parameters.
|
141
|
+
def self.parameters
|
142
|
+
return @parameters || {}
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
# Returns the Hash containing the class parameters.
|
147
|
+
def self.name_to_target
|
148
|
+
return @name_to_target
|
149
|
+
end
|
150
|
+
|
151
|
+
# The CmdGroup for stylistic information about
|
152
|
+
# curves.
|
153
|
+
CurveStyleGroup =
|
154
|
+
CmdGroup.new('curve-style', "Curve styles",
|
155
|
+
"Set stylistic details about curves", 1)
|
156
|
+
|
157
|
+
|
158
|
+
# Creates two commands for each parameter of the object:
|
159
|
+
# * a command to set the override
|
160
|
+
# * a command to choose the sets.
|
161
|
+
def self.create_commands
|
162
|
+
parameters.each do |target, param|
|
163
|
+
override_cmd =
|
164
|
+
Cmd.new("#{param.name}",
|
165
|
+
param.short_option,
|
166
|
+
"--#{param.name}",
|
167
|
+
[
|
168
|
+
CmdArg.new("#{param.type.name}-or-auto")
|
169
|
+
], {},
|
170
|
+
"Sets the #{param.description} for subsequent curves",
|
171
|
+
"Sets the #{param.description} for subsequent curves, until cancelled with 'auto' as argument.", CurveStyleGroup) do |plotmaker, value|
|
172
|
+
plotmaker.curve_generator.style_factory.
|
173
|
+
set_parameter_override(target, value)
|
174
|
+
end
|
175
|
+
|
176
|
+
if param.sets
|
177
|
+
set_cmd =
|
178
|
+
Cmd.new("#{param.name}-set",
|
179
|
+
nil,
|
180
|
+
"--#{param.name}-set",
|
181
|
+
[
|
182
|
+
CmdArg.new("#{param.type.name}-set")
|
183
|
+
], {},
|
184
|
+
"Chooses a set for the #{param.description} of subsequent curves",
|
185
|
+
"Chooses a set for the #{param.description} of subsequent curves",
|
186
|
+
CurveStyleGroup) do |plotmaker, value|
|
187
|
+
plotmaker.curve_generator.style_factory.
|
188
|
+
set_parameter_set(target, value)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# This function returns a hash suitable for use with the plot
|
195
|
+
# command as optional arguments, that will end up as the
|
196
|
+
# _one_time_ hash in #next.
|
197
|
+
def self.plot_optional_arguments
|
198
|
+
args = {}
|
199
|
+
for option_name, param in @parameters
|
200
|
+
args[param.name] =
|
201
|
+
CmdArg.new(param.type)
|
202
|
+
end
|
203
|
+
|
204
|
+
# Here, we add the support for a /legend= option
|
205
|
+
args['legend'] = CmdArg.new('text')
|
206
|
+
@name_to_target['legend'] = 'legend'
|
207
|
+
|
208
|
+
return args
|
209
|
+
end
|
210
|
+
|
211
|
+
|
212
|
+
# A hash containing values that override default ones derived
|
213
|
+
# from the CircularArray objects.
|
214
|
+
attr_accessor :override_parameters
|
215
|
+
|
216
|
+
# A hash of CircularArray objects.
|
217
|
+
attr_accessor :parameter_carrays
|
218
|
+
|
219
|
+
|
220
|
+
# Creates a new CurveStyleFactory.
|
221
|
+
def initialize
|
222
|
+
# Overrides as in the first ctioga
|
223
|
+
@override_parameters = {
|
224
|
+
'line_style' => LineStyles::Solid,
|
225
|
+
'marker_marker' => false,
|
226
|
+
'marker_scale' => 0.5
|
227
|
+
}
|
228
|
+
@parameters_carrays = {}
|
229
|
+
for target, param in self.class.parameters
|
230
|
+
set = param.default_set
|
231
|
+
if set
|
232
|
+
@parameters_carrays[target] = CircularArray.new(set)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# Gets the style for the next curve. The _one_time_ hash
|
238
|
+
# contains values 'parameter name' (name, and not target) =>
|
239
|
+
# value that are used for this time only.
|
240
|
+
def next(one_time = {})
|
241
|
+
base = {}
|
242
|
+
for target, array in @parameters_carrays
|
243
|
+
base[target] = array.next
|
244
|
+
end
|
245
|
+
base.merge!(@override_parameters)
|
246
|
+
base.merge!(hash_name_to_target(one_time))
|
247
|
+
# TODO: here, resolve 'links', such as :->color ?
|
248
|
+
return CurveStyle.from_hash(base)
|
249
|
+
end
|
250
|
+
|
251
|
+
|
252
|
+
|
253
|
+
# Sets the override for the given parameter. This corresponds
|
254
|
+
# to fixing manually the corresponding element until the
|
255
|
+
# override is removed, by a call with a _value_ that matches
|
256
|
+
# AutoRE.
|
257
|
+
#
|
258
|
+
# The _value_ should ideally be a String that is further
|
259
|
+
# converted to the appropriate type. Non-string objects will
|
260
|
+
# be left untouched.
|
261
|
+
def set_parameter_override(target, value)
|
262
|
+
param = get_parameter(target)
|
263
|
+
# Perform automatic type conversion only on strings.
|
264
|
+
if value.is_a? String
|
265
|
+
if value =~ AutoRE
|
266
|
+
@override_parameters.delete(target)
|
267
|
+
return
|
268
|
+
end
|
269
|
+
if value =~ DisableRE
|
270
|
+
value = false
|
271
|
+
else
|
272
|
+
value = param.type.string_to_type(value)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
@override_parameters[target] = value
|
277
|
+
end
|
278
|
+
|
279
|
+
# Sets the CircularArray set corresponding to the named
|
280
|
+
def set_parameter_set(target, value)
|
281
|
+
param = get_parameter(target)
|
282
|
+
# Perform automatic type conversion only on strings.
|
283
|
+
if value.is_a? String
|
284
|
+
value = param.sets_type.string_to_type(value)
|
285
|
+
end
|
286
|
+
@parameters_carrays[target].set = value
|
287
|
+
end
|
288
|
+
|
289
|
+
# Now, the parameters:
|
290
|
+
define_parameter 'line_color', 'color', 'color',
|
291
|
+
Sets::ColorSets, "color", "-c"
|
292
|
+
|
293
|
+
define_parameter 'line_width', 'line-width', 'float',
|
294
|
+
Sets::LineWidthSets, "line width", nil
|
295
|
+
|
296
|
+
define_parameter 'line_style', 'line-style', 'line-style',
|
297
|
+
Sets::LineStyleSets, "line style", nil
|
298
|
+
|
299
|
+
define_parameter 'marker_marker', 'marker', 'marker',
|
300
|
+
Sets::MarkerSets, "marker", '-m'
|
301
|
+
|
302
|
+
define_parameter 'marker_color', 'marker-color', 'color',
|
303
|
+
Sets::ColorSets, "marker color", nil
|
304
|
+
|
305
|
+
define_parameter 'marker_scale', 'marker-scale', 'float',
|
306
|
+
Sets::LineWidthSets, "marker scale", nil
|
307
|
+
|
308
|
+
|
309
|
+
# And finally, we register all necessary commands...
|
310
|
+
create_commands
|
311
|
+
|
312
|
+
# A constant suitable for use as the optional arguments of the
|
313
|
+
# plot command.
|
314
|
+
PlotCommandOptions = plot_optional_arguments
|
315
|
+
|
316
|
+
protected
|
317
|
+
|
318
|
+
# Returns the CurveFactoryParameterType object corresponding
|
319
|
+
# to the named parameter.
|
320
|
+
def get_parameter(target)
|
321
|
+
if ! parameters.key? target
|
322
|
+
raise "Unkown parameter: #{target}"
|
323
|
+
else
|
324
|
+
return parameters[target]
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
# Returns the class parameters hash
|
329
|
+
def parameters
|
330
|
+
return self.class.parameters
|
331
|
+
end
|
332
|
+
|
333
|
+
# Converts the one-time parameters, which is a hash whose keys
|
334
|
+
# are the names of the parameters to targets.
|
335
|
+
def hash_name_to_target(h)
|
336
|
+
retval = {}
|
337
|
+
convert = self.class.name_to_target
|
338
|
+
for k,v in h
|
339
|
+
if convert.key? k
|
340
|
+
retval[convert[k]] = v
|
341
|
+
else
|
342
|
+
warn "Unkown key for hash_name_to_target: #{k}"
|
343
|
+
end
|
344
|
+
end
|
345
|
+
return retval
|
346
|
+
end
|
347
|
+
end
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# legend.rb: style of legends
|
2
|
+
# copyright (c) 2009 by Vincent Fourmond
|
3
|
+
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation; either version 2 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details (in the COPYING file).
|
13
|
+
|
14
|
+
require 'ctioga2/utils'
|
15
|
+
require 'ctioga2/log'
|
16
|
+
|
17
|
+
# This module contains all the classes used by ctioga
|
18
|
+
module CTioga2
|
19
|
+
|
20
|
+
Version::register_svn_info('$Revision: 55 $', '$Date: 2009-05-27 00:01:34 +0200 (Wed, 27 May 2009) $')
|
21
|
+
|
22
|
+
module Graphics
|
23
|
+
|
24
|
+
module Styles
|
25
|
+
|
26
|
+
# Style of a given Legends::LegendStorage object.
|
27
|
+
class LegendStorageStyle < BasicStyle
|
28
|
+
|
29
|
+
# The distance between two lines, a Types::Dimension object.
|
30
|
+
attr_accessor :dy
|
31
|
+
|
32
|
+
# The width of the legend pictogram, a Types::Dimension object.
|
33
|
+
attr_accessor :picto_width
|
34
|
+
|
35
|
+
# The height of the legend pictogram, a Types::Dimension object.
|
36
|
+
attr_accessor :picto_height
|
37
|
+
|
38
|
+
# The distance between the legend pictogram and the text
|
39
|
+
attr_accessor :picto_to_text
|
40
|
+
|
41
|
+
# The scale of the legend
|
42
|
+
attr_accessor :scale
|
43
|
+
|
44
|
+
# The scale of the legend text -- relative to the overall
|
45
|
+
# scale.
|
46
|
+
attr_accessor :text_scale
|
47
|
+
|
48
|
+
def initialize
|
49
|
+
@dy = Types::Dimension.new(:dy, 1.6, :y)
|
50
|
+
|
51
|
+
@picto_width = Types::Dimension.new(:dy, 1.6, :x)
|
52
|
+
@picto_height = Types::Dimension.new(:dy, 0.6, :y)
|
53
|
+
|
54
|
+
@picto_to_text = Types::Dimension.new(:dy, 0.3, :x)
|
55
|
+
|
56
|
+
@scale = 0.8
|
57
|
+
@text_scale = 0.82
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,410 @@
|
|
1
|
+
# plot.rb: the style of a plot object.
|
2
|
+
# copyright (c) 2009 by Vincent Fourmond
|
3
|
+
|
4
|
+
# This program is free software; you can redistribute it and/or modify
|
5
|
+
# it under the terms of the GNU General Public License as published by
|
6
|
+
# the Free Software Foundation; either version 2 of the License, or
|
7
|
+
# (at your option) any later version.
|
8
|
+
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details (in the COPYING file).
|
13
|
+
|
14
|
+
require 'ctioga2/utils'
|
15
|
+
require 'ctioga2/log'
|
16
|
+
|
17
|
+
require 'ctioga2/graphics/coordinates'
|
18
|
+
|
19
|
+
# This module contains all the classes used by ctioga
|
20
|
+
module CTioga2
|
21
|
+
|
22
|
+
Version::register_svn_info('$Revision: 94 $', '$Date: 2009-06-25 23:37:13 +0200 (Thu, 25 Jun 2009) $')
|
23
|
+
|
24
|
+
module Graphics
|
25
|
+
|
26
|
+
module Styles
|
27
|
+
|
28
|
+
# The style of a Elements::Subplot object.
|
29
|
+
#
|
30
|
+
# TODO: it should hold
|
31
|
+
# * labels
|
32
|
+
# * axes and edges (in a *clean* way !)
|
33
|
+
# * ticks
|
34
|
+
# * background (uniform fill + watermark if applicable + possibly
|
35
|
+
# a picture .?)
|
36
|
+
class PlotStyle
|
37
|
+
|
38
|
+
include Tioga::FigureConstants
|
39
|
+
|
40
|
+
# The various sides of the plot. A hash location -> AxisStyle.
|
41
|
+
attr_accessor :axes
|
42
|
+
|
43
|
+
# The default location of the X axis (well, mainly, the X label)
|
44
|
+
attr_accessor :xaxis_location
|
45
|
+
|
46
|
+
# The default location of the Y axis (well, mainly, the Y label)
|
47
|
+
attr_accessor :yaxis_location
|
48
|
+
|
49
|
+
# The title of the plot
|
50
|
+
attr_accessor :title
|
51
|
+
|
52
|
+
# A margin to be left around the data points
|
53
|
+
attr_accessor :plot_margin
|
54
|
+
|
55
|
+
# Coordinate tranforms
|
56
|
+
attr_accessor :transforms
|
57
|
+
|
58
|
+
# Style of the background of the plot
|
59
|
+
attr_accessor :background
|
60
|
+
|
61
|
+
# Scale of the lines of the plot. The plot is wrapped in a
|
62
|
+
# t.rescale_lines call.
|
63
|
+
attr_accessor :lines_scale
|
64
|
+
|
65
|
+
# Scale of the text of the plot. The plot is wrapped in a
|
66
|
+
# t.rescale_text call.
|
67
|
+
attr_accessor :text_scale
|
68
|
+
|
69
|
+
# A padding around the box when automatic spacing is in auto
|
70
|
+
# mode. A Dimension.
|
71
|
+
attr_accessor :padding
|
72
|
+
|
73
|
+
def initialize
|
74
|
+
# Default style for the plots.
|
75
|
+
@axes = {}
|
76
|
+
@axes[:left] = AxisStyle.new(:left,
|
77
|
+
AXIS_WITH_TICKS_AND_NUMERIC_LABELS,
|
78
|
+
'$y$')
|
79
|
+
@axes[:bottom] = AxisStyle.new(:bottom,
|
80
|
+
AXIS_WITH_TICKS_AND_NUMERIC_LABELS,
|
81
|
+
'$x$')
|
82
|
+
|
83
|
+
@axes[:right] = AxisStyle.new(:right, AXIS_WITH_TICKS_ONLY)
|
84
|
+
@axes[:top] = AxisStyle.new(:top, AXIS_WITH_TICKS_ONLY)
|
85
|
+
|
86
|
+
@xaxis_location = :bottom
|
87
|
+
@yaxis_location = :left
|
88
|
+
|
89
|
+
@title = TextLabel.new
|
90
|
+
@title.loc = :top
|
91
|
+
|
92
|
+
@plot_margin = nil
|
93
|
+
|
94
|
+
@transforms = CoordinateTransforms.new
|
95
|
+
|
96
|
+
@background = BackgroundStyle.new
|
97
|
+
|
98
|
+
# A padding of 4bp ? Why ?? Why not ?
|
99
|
+
@padding = Types::Dimension.new(:bp, 4)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Whether to use log scale for the given axis.
|
103
|
+
#
|
104
|
+
# Now the question is: how should that affect user-defined
|
105
|
+
# axes ? It should not.
|
106
|
+
def set_log_scale(which, val)
|
107
|
+
case which
|
108
|
+
when :x
|
109
|
+
@axes[:top].log = val
|
110
|
+
@axes[:bottom].log = val
|
111
|
+
@transforms.x_log = val
|
112
|
+
when :y
|
113
|
+
@axes[:left].log = val
|
114
|
+
@axes[:right].log = val
|
115
|
+
@transforms.y_log = val
|
116
|
+
else
|
117
|
+
raise "Unknown axis: #{which.inspect}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Returns the AxisStyle corresponding to the named
|
122
|
+
# axis. _name_ can be:
|
123
|
+
# * one of the named elements of axes (ie, by default: top,
|
124
|
+
# left, right, bottom). All names are stripped from spaces
|
125
|
+
# around, and downcased (see #clean_axis_name).
|
126
|
+
# * x(axis)?/y(axis)?, which returns the default object for the
|
127
|
+
# given location
|
128
|
+
def get_axis_style(name)
|
129
|
+
if name =~ /^\s*([xy])(?:axis)?\s*$/i
|
130
|
+
return @axes[self.send("#{$1.downcase}axis_location")]
|
131
|
+
else
|
132
|
+
style = @axes[clean_axis_name(name)]
|
133
|
+
if ! style
|
134
|
+
raise "Unkown named axis: '#{name}'"
|
135
|
+
else
|
136
|
+
return style
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns a BaseTextStyle or similar for the given
|
142
|
+
# location. The location is of the form:
|
143
|
+
# axis_name(_(ticks?|label))
|
144
|
+
# or
|
145
|
+
# title
|
146
|
+
#
|
147
|
+
# If neither label nor ticks is specified in the first form,
|
148
|
+
# ticks are implied.
|
149
|
+
def get_label_style(location)
|
150
|
+
if location =~ /^\s*title\s*$/
|
151
|
+
return @title
|
152
|
+
end
|
153
|
+
location =~ /^\s*(.*?)(?:_(ticks?|label))?\s*$/i
|
154
|
+
which = $2
|
155
|
+
axis = get_axis_style($1)
|
156
|
+
if which =~ /label/
|
157
|
+
return axis.axis_label
|
158
|
+
else
|
159
|
+
return axis.tick_label_style
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Sets the style of the given label. Sets the text as well, if
|
164
|
+
# _text_ is not _nil_
|
165
|
+
def set_label_style(which, hash, text = nil)
|
166
|
+
style = get_label_style(which)
|
167
|
+
hash = hash.merge({'text' => text}) unless text.nil?
|
168
|
+
if hash.key?('text') and ! style.is_a?(TextLabel)
|
169
|
+
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 ?")
|
170
|
+
end
|
171
|
+
style.set_from_hash(hash)
|
172
|
+
end
|
173
|
+
|
174
|
+
|
175
|
+
# Draws all axes for the plot.
|
176
|
+
def draw_all_axes(t)
|
177
|
+
for which, axis in @axes
|
178
|
+
axis.draw_axis(t)
|
179
|
+
end
|
180
|
+
# We draw the title last
|
181
|
+
title.draw(t, 'title')
|
182
|
+
end
|
183
|
+
|
184
|
+
# Draws all axes background lines for the plot.
|
185
|
+
def draw_all_background_lines(t)
|
186
|
+
for which, axis in @axes
|
187
|
+
axis.draw_background_lines(t)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Sets up the FigureMaker object for the plot. To be called
|
192
|
+
# just after the outermost context call for the concerned
|
193
|
+
# plot.
|
194
|
+
def setup_figure_maker(t)
|
195
|
+
if @lines_scale
|
196
|
+
t.rescale_lines(@lines_scale)
|
197
|
+
end
|
198
|
+
if @text_scale
|
199
|
+
t.rescale_text(@text_scale)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
|
204
|
+
# Returns a deep copy of _self_, with all references stripped.
|
205
|
+
def deep_copy
|
206
|
+
return Marshal.load(Marshal.dump(self))
|
207
|
+
end
|
208
|
+
|
209
|
+
# Returns the PlotStyle object of the current plot
|
210
|
+
def self.current_plot_style(plotmaker)
|
211
|
+
return plotmaker.root_object.current_plot.style
|
212
|
+
end
|
213
|
+
|
214
|
+
# Estimate the margins of the plot whose style this object
|
215
|
+
# controls. These margins are used when the plot margins are
|
216
|
+
# in automatic mode.
|
217
|
+
#
|
218
|
+
# Returns a Types::MarginsBox
|
219
|
+
def estimate_margins(t)
|
220
|
+
margins = [:left, :right, :top, :bottom].map do |side|
|
221
|
+
ext = @axes[side].extension(t,self)
|
222
|
+
if side == @title.loc
|
223
|
+
ext2 = @title.label_extension(t, 'title', side) *
|
224
|
+
(@text_scale || 1)
|
225
|
+
if ext < ext2
|
226
|
+
ext = ext2
|
227
|
+
end
|
228
|
+
end
|
229
|
+
Types::Dimension.new(:dy, ext)
|
230
|
+
end
|
231
|
+
|
232
|
+
# TODO: add the plot title !
|
233
|
+
box = Types::MarginsBox.new(*margins)
|
234
|
+
if @padding
|
235
|
+
for dim in box.margins
|
236
|
+
dim.replace_if_bigger(t, @padding)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
return box
|
240
|
+
end
|
241
|
+
|
242
|
+
protected
|
243
|
+
|
244
|
+
# Takes a string and returns a Symbol suitable for use with
|
245
|
+
# the #axes hash (lower case without spaces).
|
246
|
+
def clean_axis_name(name)
|
247
|
+
if name.is_a?(::Symbol) # Argh ! Tioga redefined Symbol !
|
248
|
+
return name
|
249
|
+
end
|
250
|
+
name =~ /^\s*(.*?)\s*$/
|
251
|
+
return $1.downcase.to_sym
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
AxisGroup = CmdGroup.new('axes-labels',
|
257
|
+
"Axes and labels", "Axes and labels", 40)
|
258
|
+
|
259
|
+
|
260
|
+
|
261
|
+
AxisTypeCommands = []
|
262
|
+
[:left, :right, :top, :bottom].each do |loc|
|
263
|
+
AxisTypeCommands <<
|
264
|
+
Cmd.new("#{loc}",nil,"--#{loc}",
|
265
|
+
[
|
266
|
+
CmdArg.new('axis-decoration'),
|
267
|
+
], PartialAxisStyle) do |plotmaker, dec, opts|
|
268
|
+
style = AxisStyle.current_axis_style(plotmaker, loc)
|
269
|
+
style.decoration = dec
|
270
|
+
|
271
|
+
style.set_from_hash(opts)
|
272
|
+
end
|
273
|
+
AxisTypeCommands.last.
|
274
|
+
describe("Sets the type of the #{loc} axis",
|
275
|
+
<<"EOH", AxisGroup)
|
276
|
+
Sets the type of the #{loc} axis.
|
277
|
+
EOH
|
278
|
+
end
|
279
|
+
|
280
|
+
AxisStyleCommand =
|
281
|
+
Cmd.new("axis-style",nil,"--axis-style",
|
282
|
+
[
|
283
|
+
CmdArg.new('axis'),
|
284
|
+
], FullAxisStyle) do |plotmaker, which, opts|
|
285
|
+
style = AxisStyle.current_axis_style(plotmaker, which)
|
286
|
+
style.set_from_hash(opts)
|
287
|
+
end
|
288
|
+
AxisStyleCommand.
|
289
|
+
describe("Sets the style of the given axis",
|
290
|
+
<<"EOH", AxisGroup)
|
291
|
+
This command can be used to set various aspects of the style of the
|
292
|
+
given axis, through its various options:
|
293
|
+
* decoration
|
294
|
+
EOH
|
295
|
+
|
296
|
+
BackgroundLinesCommands =
|
297
|
+
Cmd.new('background-lines', nil, '--background-lines',
|
298
|
+
[
|
299
|
+
CmdArg.new('axis'),
|
300
|
+
CmdArg.new('color-or-false')
|
301
|
+
],{
|
302
|
+
'style' => CmdArg.new('line-style'),
|
303
|
+
'width' => CmdArg.new('float')
|
304
|
+
}) do |plotmaker, which, color, options|
|
305
|
+
axis = AxisStyle.current_axis_style(plotmaker, which)
|
306
|
+
if color
|
307
|
+
style = {'color' => color}
|
308
|
+
style.merge!(options)
|
309
|
+
if axis.background_lines
|
310
|
+
axis.background_lines.set_from_hash(style)
|
311
|
+
else
|
312
|
+
axis.background_lines = StrokeStyle.from_hash(style)
|
313
|
+
end
|
314
|
+
else
|
315
|
+
axis.background_lines = false
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
BackgroundLinesCommands.
|
320
|
+
describe("Sets the color of the background lines",
|
321
|
+
<<"EOH", AxisGroup)
|
322
|
+
Sets the color of the background lines for the given axis.
|
323
|
+
EOH
|
324
|
+
|
325
|
+
|
326
|
+
XAxisLabelCommand =
|
327
|
+
Cmd.new('xlabel', '-x', '--xlabel', [ CmdArg.new('text') ],
|
328
|
+
FullTextStyleOptions) do |plotmaker, label, options|
|
329
|
+
PlotStyle.current_plot_style(plotmaker).
|
330
|
+
set_label_style('x_label', options, label)
|
331
|
+
end
|
332
|
+
|
333
|
+
XAxisLabelCommand.describe("Sets the X label of the plot",
|
334
|
+
<<"EOH", AxisGroup)
|
335
|
+
Sets the X label of the current plot.
|
336
|
+
EOH
|
337
|
+
|
338
|
+
NoXAxisLabelCommand =
|
339
|
+
Cmd.new('no-xlabel', nil, '--no-xlabel', []) do |plotmaker|
|
340
|
+
PlotStyle.current_plot_style(plotmaker).
|
341
|
+
set_label_style('x_label', {}, false)
|
342
|
+
end
|
343
|
+
|
344
|
+
NoXAxisLabelCommand.describe("Disables X label for the plot",
|
345
|
+
<<"EOH", AxisGroup)
|
346
|
+
Disables the X label for the current plot.
|
347
|
+
EOH
|
348
|
+
|
349
|
+
|
350
|
+
YAxisLabelCommand =
|
351
|
+
Cmd.new('ylabel', '-y', '--ylabel', [ CmdArg.new('text') ],
|
352
|
+
FullTextStyleOptions) do |plotmaker, label, options|
|
353
|
+
PlotStyle.current_plot_style(plotmaker).
|
354
|
+
set_label_style('y_label', options, label)
|
355
|
+
end
|
356
|
+
|
357
|
+
YAxisLabelCommand.describe("Sets the Y label of the plot",
|
358
|
+
<<"EOH", AxisGroup)
|
359
|
+
Sets the Y label of the current plot.
|
360
|
+
EOH
|
361
|
+
|
362
|
+
NoYAxisLabelCommand =
|
363
|
+
Cmd.new('no-ylabel', nil, '--no-ylabel', []) do |plotmaker|
|
364
|
+
PlotStyle.current_plot_style(plotmaker).
|
365
|
+
set_label_style('y_label', {}, false)
|
366
|
+
end
|
367
|
+
|
368
|
+
NoYAxisLabelCommand.describe("Disables Y label for the plot",
|
369
|
+
<<"EOH", AxisGroup)
|
370
|
+
Disables the Y label for the current plot.
|
371
|
+
EOH
|
372
|
+
|
373
|
+
TitleLabelCommand =
|
374
|
+
Cmd.new('title', '-t', '--title', [ CmdArg.new('text') ],
|
375
|
+
FullTextStyleOptions) do |plotmaker, label, options|
|
376
|
+
PlotStyle.current_plot_style(plotmaker).
|
377
|
+
set_label_style('title', options, label)
|
378
|
+
end
|
379
|
+
|
380
|
+
TitleLabelCommand.describe("Sets the title of the plot",
|
381
|
+
<<"EOH", AxisGroup)
|
382
|
+
Sets the title of the current plot.
|
383
|
+
EOH
|
384
|
+
|
385
|
+
LabelStyleCommand =
|
386
|
+
Cmd.new('label-style', nil, '--label-style',
|
387
|
+
[ CmdArg.new('label') ], # Here: change the label too...
|
388
|
+
FullTextLabelOptions) do |plotmaker, which, options|
|
389
|
+
PlotStyle.current_plot_style(plotmaker).
|
390
|
+
set_label_style(which, options)
|
391
|
+
end
|
392
|
+
|
393
|
+
LabelStyleCommand.describe("Sets the style of the given label",
|
394
|
+
<<"EOH", AxisGroup)
|
395
|
+
Sets the style of the given label (see the type {type: label} for more
|
396
|
+
information).
|
397
|
+
|
398
|
+
The option text permits to also set the text of the label (does not
|
399
|
+
work for ticks).
|
400
|
+
|
401
|
+
For tick labels, setting the color option also sets the color for the
|
402
|
+
lines of the corresponding axis. If you don't want that, you can
|
403
|
+
override the color using the /stroke_color option of
|
404
|
+
{command: axis-style}. This will only work with Tioga version 1.11 or
|
405
|
+
greater.
|
406
|
+
EOH
|
407
|
+
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|