ctioga2 0.10.1 → 0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/Changelog +18 -0
  3. data/bin/ctioga2 +28 -0
  4. data/lib/ctioga2/commands/commands.rb +1 -0
  5. data/lib/ctioga2/commands/doc/documentation-commands.rb +13 -0
  6. data/lib/ctioga2/commands/doc/help.rb +3 -2
  7. data/lib/ctioga2/commands/doc/html.rb +48 -0
  8. data/lib/ctioga2/commands/doc/introspection.rb +2 -2
  9. data/lib/ctioga2/commands/general-types.rb +10 -0
  10. data/lib/ctioga2/commands/parsers/file.rb +23 -2
  11. data/lib/ctioga2/data/backends/backends.rb +1 -2
  12. data/lib/ctioga2/data/backends/backends/smath.rb +129 -0
  13. data/lib/ctioga2/data/backends/backends/text.rb +1 -0
  14. data/lib/ctioga2/data/dataset.rb +1 -1
  15. data/lib/ctioga2/data/stack.rb +13 -3
  16. data/lib/ctioga2/graphics/elements.rb +2 -0
  17. data/lib/ctioga2/graphics/elements/containers.rb +3 -1
  18. data/lib/ctioga2/graphics/elements/element.rb +194 -5
  19. data/lib/ctioga2/graphics/elements/gradient-region.rb +5 -2
  20. data/lib/ctioga2/graphics/elements/histogram.rb +7 -2
  21. data/lib/ctioga2/graphics/elements/plot-elements.rb +88 -0
  22. data/lib/ctioga2/graphics/elements/primitive.rb +28 -12
  23. data/lib/ctioga2/graphics/elements/region.rb +6 -1
  24. data/lib/ctioga2/graphics/elements/style-lists.rb +2 -2
  25. data/lib/ctioga2/graphics/elements/subplot.rb +3 -3
  26. data/lib/ctioga2/graphics/elements/tangent.rb +5 -8
  27. data/lib/ctioga2/graphics/generator.rb +10 -0
  28. data/lib/ctioga2/graphics/geometry.rb +96 -0
  29. data/lib/ctioga2/graphics/legends.rb +4 -2
  30. data/lib/ctioga2/graphics/legends/area.rb +12 -4
  31. data/lib/ctioga2/graphics/root.rb +16 -14
  32. data/lib/ctioga2/graphics/styles.rb +5 -2
  33. data/lib/ctioga2/graphics/styles/arrows.rb +5 -0
  34. data/lib/ctioga2/graphics/styles/axes.rb +1 -1
  35. data/lib/ctioga2/graphics/styles/base.rb +95 -14
  36. data/lib/ctioga2/graphics/styles/curve.rb +8 -0
  37. data/lib/ctioga2/graphics/styles/drawable.rb +35 -48
  38. data/lib/ctioga2/graphics/styles/factory.rb +23 -23
  39. data/lib/ctioga2/graphics/styles/fill.rb +268 -0
  40. data/lib/ctioga2/graphics/styles/plot.rb +90 -46
  41. data/lib/ctioga2/graphics/styles/sets.rb +3 -0
  42. data/lib/ctioga2/graphics/styles/{sheet.rb → styles.rb} +70 -160
  43. data/lib/ctioga2/graphics/styles/stylesheet.rb +355 -0
  44. data/lib/ctioga2/graphics/styles/texts.rb +4 -2
  45. data/lib/ctioga2/graphics/styles/ticks.rb +44 -4
  46. data/lib/ctioga2/graphics/subplot-commands.rb +84 -9
  47. data/lib/ctioga2/graphics/types.rb +1 -1
  48. data/lib/ctioga2/graphics/types/dimensions.rb +40 -0
  49. data/lib/ctioga2/graphics/types/grid.rb +21 -5
  50. data/lib/ctioga2/graphics/types/point.rb +2 -1
  51. data/lib/ctioga2/log.rb +5 -1
  52. data/lib/ctioga2/metabuilder/types/styles.rb +11 -7
  53. data/lib/ctioga2/plotmaker.rb +2 -0
  54. data/lib/ctioga2/utils.rb +21 -6
  55. data/lib/ctioga2/version.rb +2 -2
  56. metadata +105 -108
@@ -13,7 +13,9 @@
13
13
 
14
14
 
15
15
  require 'ctioga2/graphics/types'
16
+ require 'ctioga2/graphics/styles'
16
17
  require 'ctioga2/graphics/elements/element'
18
+ require 'ctioga2/graphics/elements/plot-elements'
17
19
  require 'ctioga2/graphics/elements/containers'
18
20
  require 'ctioga2/graphics/elements/redirecting-container'
19
21
  require 'ctioga2/graphics/elements/subplot'
@@ -60,9 +60,11 @@ module CTioga2
60
60
  # children or not ?)
61
61
 
62
62
  # Creates an empty new Container with the given _parent_.
63
- def initialize(parent = nil, root = nil)
63
+ def initialize(parent, root, options)
64
64
  super()
65
65
  @parent = parent
66
+
67
+ setup_style(parent, options)
66
68
 
67
69
  # elements to be given to tioga
68
70
  @elements = []
@@ -1,5 +1,5 @@
1
1
  # element.rb: base class of all drawable elements
2
- # copyright (c) 2006, 2007, 2008, 2009 by Vincent Fourmond:
2
+ # copyright (c) 2006, 2007, 2008, 2009, 2014 by Vincent Fourmond:
3
3
 
4
4
  # This program is free software; you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -23,9 +23,25 @@ module CTioga2
23
23
 
24
24
  # All elements that can be drawn onto a FigureMaker object
25
25
  module Elements
26
-
26
+
27
27
  # The base class for every single object that is drawn on
28
- # Tioga's output.
28
+ # Tioga's output. Each object can have a style attached to it,
29
+ # and obtained from the StyleSheet class.
30
+ #
31
+ # For styling-related purposes, all subclasses of this class
32
+ # have the following characteristics:
33
+ # * a style name (a "type selector")
34
+ # * a style class (the corresponding underlying class)
35
+ #
36
+ # All instances of this classes have several properties:
37
+ # * a (unique) id
38
+ # * a list of classes (specified as comma-separated stuff)
39
+ #
40
+ # Ideas for how the style should be used:
41
+ # - first create the object
42
+ # - then, soon afterwards, use #setup_style to give it a
43
+ # workable position in the style list
44
+ # - then, use get_style to get the style ;-)...
29
45
  class TiogaElement
30
46
  include Log
31
47
 
@@ -43,7 +59,105 @@ module CTioga2
43
59
  # Depth
44
60
  attr_writer :depth
45
61
 
46
- def initialize()
62
+ # Style-related attributes:
63
+
64
+ # The id
65
+ attr_reader :object_id
66
+
67
+ # The classes (order matter)
68
+ attr_accessor :object_classes
69
+
70
+ # The parent (in the style point of view, which may be
71
+ # different from the rest)
72
+ attr_accessor :object_parent
73
+
74
+ # Wether or not the object is hidden
75
+ attr_accessor :hidden
76
+
77
+ StyleBaseOptions = {
78
+ 'id' => CmdArg.new('text'),
79
+ 'class' => CmdArg.new('text-list')
80
+ }
81
+
82
+ def self.define_style(name, cls = nil)
83
+ @style_name = name
84
+ @style_class = cls
85
+ register_style(name, cls)
86
+ end
87
+
88
+ @@style_classes = {}
89
+ @@all_styles = {}
90
+
91
+ def self.styled_classes
92
+ return @@all_styles
93
+ end
94
+
95
+ def self.register_style(name, cls)
96
+ @@all_styles[name] = self
97
+ if @@style_classes.key? name
98
+ if @@style_classes[name] != cls
99
+ raise "Trying to register different classes under the same name"
100
+ end
101
+ else
102
+ @@style_classes[name] = cls
103
+ end
104
+ end
105
+
106
+ def self.base_style
107
+ if @style_name
108
+ return self
109
+ elsif self == TiogaElement
110
+ return nil
111
+ else
112
+ return self.superclass.base_style
113
+ end
114
+ end
115
+
116
+ def self.style_class
117
+ if @style_name
118
+ return @style_class
119
+ else
120
+ bs = base_style
121
+ return (bs ? bs.style_class : nil)
122
+ end
123
+ end
124
+
125
+ def self.style_name
126
+ if @style_name
127
+ return @style_name
128
+ else
129
+ bs = base_style
130
+ return (bs ? bs.style_name : nil)
131
+ end
132
+ end
133
+
134
+ def style_class
135
+ return self.class.style_class
136
+ end
137
+
138
+ def style_name
139
+ return self.class.style_name
140
+ end
141
+
142
+ def has_style?
143
+ if style_class
144
+ return true
145
+ else
146
+ return false
147
+ end
148
+ end
149
+
150
+ def self.all_styles
151
+ return @style_classes
152
+ end
153
+
154
+
155
+
156
+ def self.inherited(cls)
157
+ # p cls
158
+ end
159
+
160
+ def initialize
47
161
  @clipped = true
48
162
 
49
163
  @depth = 50 # Hey, like xfig
@@ -51,6 +165,57 @@ module CTioga2
51
165
  @gp_cache = {}
52
166
  end
53
167
 
168
+ def self.register_object(obj)
169
+ @registered_objects ||= {}
170
+ if i = obj.object_id
171
+ if @registered_objects.key? i
172
+ warn { "Second object with ID #{i}, ignoring the name" }
173
+ else
174
+ @registered_objects[i] = obj
175
+ end
176
+ end
177
+ end
178
+
179
+ def self.find_object(obj_id)
180
+ @registered_objects ||= {}
181
+ if @registered_objects.key? obj_id
182
+ return @registered_objects[obj_id]
183
+ else
184
+ raise "No such object: '#{obj_id}'"
185
+ end
186
+ end
187
+
188
+
189
+ def setup_style(obj_parent, opts)
190
+ @cached_options = opts
191
+ @object_id = opts["id"] || nil
192
+ @object_classes = opts["class"] || []
193
+ @object_parent = obj_parent
194
+
195
+ TiogaElement.register_object(self)
196
+ @style_is_setup = true
197
+ end
198
+
199
+
200
+ def get_style()
201
+ check_styled()
202
+ return Styles::StyleSheet.style_for(self)
203
+ end
204
+
205
+ def update_style(style)
206
+ check_styled()
207
+ stl = Styles::StyleSheet.style_hash_for(self)
208
+ style.set_from_hash(stl)
209
+ end
210
+
211
+ def check_styled()
212
+ if ! self.style_class
213
+ raise "Object has no attached style class !"
214
+ elsif ! @style_is_setup
215
+ raise "Should have setup style before !"
216
+ end
217
+ end
218
+
54
219
  def depth
55
220
  @depth || 50
56
221
  end
@@ -66,7 +231,12 @@ module CTioga2
66
231
  # #real_do, which should be redefined by the children. You can
67
232
  # redefine _do_ too if you need another debugging output.
68
233
  def do(f)
69
- debug { "plotting #{self.inspect}" }
234
+ if @hidden
235
+ debug { "not plotting hidden #{self.inspect}" }
236
+ return
237
+ else
238
+ debug { "plotting #{self.inspect}" }
239
+ end
70
240
  @gp_cache = {}
71
241
  real_do(f)
72
242
  end
@@ -107,6 +277,8 @@ module CTioga2
107
277
  # drawn.
108
278
  attr_accessor :curve_style
109
279
 
280
+ define_style 'curve', Styles::CurveStyle
281
+
110
282
  undef :location=, :location
111
283
 
112
284
  # Returns the LocationStyle object of the curve. Returns the
@@ -132,6 +304,23 @@ module CTioga2
132
304
  end
133
305
  end
134
306
 
307
+ ObjectType =
308
+ CmdType.new('object', {:type => :function_based,
309
+ :class => Elements::TiogaElement,
310
+ :func_name => :find_object}, <<EOD)
311
+ A named object (whose name was given using the /id= option to the
312
+ appropriate command).
313
+ EOD
314
+
315
+ ObjectsType =
316
+ CmdType.new('objects', {:type => :array,
317
+ :subtype => {:type => :function_based,
318
+ :class => Elements::TiogaElement,
319
+ :func_name => :find_object}
320
+ }, <<EOD)
321
+ A list of comma-separated {type: object}s.
322
+ EOD
323
+
135
324
  end
136
325
  end
137
326
  end
@@ -1,4 +1,4 @@
1
- # region.rb: draw curves-delimited fills
1
+ # gradient-region.rb: draw neat color gradient
2
2
  # copyright (c) 2010 by Vincent Fourmond
3
3
 
4
4
  # This program is free software; you can redistribute it and/or modify
@@ -34,6 +34,8 @@ module CTioga2
34
34
  undef :elements
35
35
  undef :subframe
36
36
 
37
+ define_style "gradient"
38
+
37
39
  # The curves which delimit the region
38
40
  attr_accessor :curves
39
41
 
@@ -41,8 +43,9 @@ module CTioga2
41
43
  attr_accessor :start_color, :end_color
42
44
 
43
45
  # Creates a new empty region
44
- def initialize(parent = nil, root = nil)
46
+ def initialize(parent, root, options)
45
47
  @parent = parent
48
+ setup_style(parent, options)
46
49
 
47
50
  # The curves whose color we should change
48
51
  @curves = []
@@ -228,7 +228,12 @@ module CTioga2
228
228
  # values (which means in particular that they won't be
229
229
  # positioned at the exact X value, but that's already the
230
230
  # case anyway).
231
- width = (x_values.max - x_values.min)/(x_values.size - 1)
231
+ width = (x_values.max - x_values.min)/(x_values.size - 1).to_f
232
+ if width.nan? || width == 0.0
233
+ # Only 1 X value, we use a width of 1
234
+ # ??
235
+ width = 0.8
236
+ end
232
237
 
233
238
  # Available width
234
239
  aw = width - intra_sep - inter_sep
@@ -250,7 +255,7 @@ module CTioga2
250
255
  offset += iw
251
256
  next unless col
252
257
  if col.first.histogram_style.intra_sep
253
- offset += h.histogram_style.intra_sep.to_figure(t, :x)
258
+ offset += col.first.histogram_style.intra_sep.to_figure(t, :x)
254
259
  end
255
260
  for h in col
256
261
  cache[h] = c
@@ -0,0 +1,88 @@
1
+ # -*- coding: utf-8 -*-
2
+ # plot-element.rb: collection of small wrappers used for plots
3
+ # copyright (c) 2014 by Vincent Fourmond
4
+
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 2 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # This program is distributed in the hope that it will be useful, but
11
+ # WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # General Public License for more details (in the COPYING file).
14
+
15
+
16
+ require 'ctioga2/utils'
17
+ require 'ctioga2/log'
18
+
19
+ # This module contains all the classes used by ctioga
20
+ module CTioga2
21
+
22
+ # This module contains all graphical elements of CTioga2
23
+ module Graphics
24
+
25
+ module Elements
26
+
27
+ # This simple wrapper makes it possible to style axes (at least
28
+ # using parents styling)
29
+ class AxisElement < TiogaElement
30
+
31
+ define_style 'axis', Styles::AxisStyle
32
+
33
+ attr_accessor :style
34
+
35
+ def initialize_style(loc, dec, label)
36
+ @style = Styles::AxisStyle::new(loc, dec, label)
37
+ update_style(@style)
38
+ end
39
+ end
40
+
41
+ # This simple wrapper makes it possible to style axes (at least
42
+ # using parents styling)
43
+ class MapAxisElement < TiogaElement
44
+
45
+ define_style 'zaxis', Styles::MapAxisStyle
46
+
47
+ attr_accessor :style
48
+
49
+ def initialize(parent, opts)
50
+ setup_style(parent, opts)
51
+ @style = get_style()
52
+ end
53
+ end
54
+
55
+ # Wrapper for the title
56
+ class TitleElement < TiogaElement
57
+
58
+ define_style 'title', Styles::TextLabel
59
+
60
+ attr_accessor :style
61
+
62
+ def initialize(parent, opts)
63
+ setup_style(parent, opts)
64
+ @style = Styles::TextLabel.new(nil, Types::PlotLocation.new(:top))
65
+ update_style(@style)
66
+ end
67
+ end
68
+
69
+ # Wrapper for the background
70
+ class BackgroundElement < TiogaElement
71
+ define_style 'background', Styles::BackgroundStyle
72
+
73
+ attr_accessor :style
74
+
75
+ def initialize(parent, opts)
76
+ setup_style(parent, opts)
77
+ @style = get_style()
78
+ end
79
+
80
+ def draw_background(t)
81
+ @style.draw_background(t)
82
+ end
83
+ end
84
+
85
+
86
+ end
87
+ end
88
+ end
@@ -51,6 +51,9 @@ module CTioga2
51
51
  # compulsory arguments and a hash containing optional ones.
52
52
  attr_accessor :funcall
53
53
 
54
+ # The underlying nameless class
55
+ attr_accessor :primitive_class
56
+
54
57
  # Creates a TiogaPrimitive object
55
58
  def initialize(name, comp, opts = {}, &code)
56
59
  @name = name
@@ -111,6 +114,9 @@ module CTioga2
111
114
  desc = nil, &code)
112
115
  primitive = TiogaPrimitive.new(name, comp, opts, &code)
113
116
  @known_primitives[name] = primitive
117
+
118
+ primitive_class = Class.new(TiogaPrimitiveCall)
119
+ primitive.primitive_class = primitive_class
114
120
 
115
121
  # Now, create the command
116
122
  cmd_args = comp.map do |x|
@@ -132,15 +138,17 @@ module CTioga2
132
138
 
133
139
  cmd_opts['clipped'] = CmdArg.new('boolean')
134
140
  cmd_opts['depth'] = CmdArg.new('integer')
141
+ cmd_opts.merge!(TiogaElement::StyleBaseOptions)
142
+
135
143
  cmd = Cmd.new("draw-#{name}",nil,"--draw-#{name}",
136
144
  cmd_args, cmd_opts) do |plotmaker, *rest|
137
145
  options = rest.pop
138
- call = Elements::
139
- TiogaPrimitiveCall.new(primitive,
146
+ call = primitive_class.new(primitive,
140
147
  rest, options)
148
+ container = plotmaker.root_object.current_plot
149
+ call.setup_style(container, options)
141
150
  call.last_curve_style = plotmaker.curve_style_stack.last
142
- plotmaker.root_object.current_plot.
143
- add_element(call)
151
+ container.add_element(call)
144
152
  end
145
153
  if ! desc
146
154
  desc = "Directly draws #{long_name} on the current plot"
@@ -150,6 +158,7 @@ module CTioga2
150
158
  PrimitiveGroup)
151
159
 
152
160
  PrimitiveCommands[name] = cmd
161
+ return primitive_class
153
162
  end
154
163
 
155
164
  # This creates a primitive base on a style object, given a
@@ -164,13 +173,10 @@ module CTioga2
164
173
  def self.styled_primitive(name, long_name, comp, style_class,
165
174
  style_name, without = [],
166
175
  additional_options = {},
167
- set_style_command = nil, # This
168
- # could be
169
- # removed
176
+ set_style_command = nil,
170
177
  &code)
171
178
  options = style_class.options_hash.without(without)
172
179
  options.merge!(additional_options)
173
- options['base-style'] = 'text' # the base style name
174
180
 
175
181
  set_style_command ||= style_name
176
182
  desc = <<"EOD"
@@ -179,14 +185,15 @@ For more information on the available options, see the
179
185
  {command: define-#{set_style_command}-style} command.
180
186
  EOD
181
187
 
182
- self.primitive(name, long_name, comp, options, desc) do |*all|
188
+ cls = self.primitive(name, long_name, comp, options, desc) do |*all|
183
189
  opts = all.pop
184
- st_name = opts['base-style'] || "base"
185
- style = Styles::StyleSheet.style_for(style_class,st_name)
190
+ style = get_style()
186
191
  style.set_from_hash(opts)
187
192
  all << style << opts
188
193
  code.call(*all)
189
194
  end
195
+ cls.define_style(set_style_command, style_class)
196
+ return cls
190
197
  end
191
198
 
192
199
 
@@ -251,6 +258,15 @@ EOD
251
258
  head.to_figure_xy(t) ))
252
259
  end
253
260
 
261
+ # @todo Do the same thing for arrows...
262
+ styled_primitive("oriented-line", "oriented-line",
263
+ [ 'point', 'dimension' ],
264
+ Styles::OrientedLineStyle,
265
+ 'oriented-line'
266
+ ) do |t, org, dim, style, options|
267
+ style.draw_oriented_line(t, *org.to_figure_xy(t), dim)
268
+ end
269
+
254
270
 
255
271
  styled_primitive("image", "image",
256
272
  [ CmdArg.new('text', 'file'),
@@ -291,7 +307,7 @@ EOD
291
307
  ## @todo this is a really ugly hack for passing
292
308
  ## last_curve_style around
293
309
  $last_curve_style = @last_curve_style
294
- primitive.funcall.call(t, *args)
310
+ instance_exec(t, *args, &primitive.funcall)
295
311
  end
296
312
 
297
313
  DrawingSpecType =