ctioga2 0.10.1 → 0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 =