ctioga2 0.11 → 0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -40,6 +40,7 @@ require 'ctioga2/graphics/styles/background'
40
40
  require 'ctioga2/graphics/styles/plot'
41
41
 
42
42
  require 'ctioga2/graphics/styles/legend'
43
+ require 'ctioga2/graphics/styles/scope'
43
44
 
44
45
 
45
46
 
@@ -35,7 +35,12 @@ module CTioga2
35
35
  typed_attribute "#{e}_color".to_sym, 'color'
36
36
  end
37
37
 
38
- def draw_arrow(t, x1, y1, x2, y2)
38
+ TiogaDefaults = {
39
+ 'head_marker' => Tioga::MarkerConstants::Arrowhead,
40
+ 'tail_marker' => Tioga::MarkerConstants::BarThin
41
+ }
42
+
43
+ def old_draw_arrow(t, x1, y1, x2, y2)
39
44
  dict = self.to_hash
40
45
  dict.rename_key('width', 'line_width')
41
46
  dict.rename_key('style', 'line_style')
@@ -49,7 +54,142 @@ module CTioga2
49
54
  t.show_arrow(dict)
50
55
  end
51
56
 
57
+
58
+ # Draws an arrow.
59
+ def draw_arrow(t, x1, y1, x2, y2)
60
+ dx = x2 - x1
61
+ dy = y2 - y1
62
+
63
+ angle = Types::Dimension.get_angle(t, dx, dy)
64
+
65
+ len = Types::Dimension.get_distance(t, dx, dy)
66
+
67
+ rs = symbol_size(t, "head")
68
+ ls = symbol_size(t, "tail")
69
+
70
+ x1n, y1n, x2n, y2n = *Types::Dimension::adjust_line(t, x1, y1, x2, y2, -ls, -rs)
71
+
72
+ # Must shorten the path first...
73
+ sv = t.line_cap
74
+
75
+ # This has for effect to disable changing the line cap when
76
+ # there are now arrows to draw.
77
+ if ! (has_marker?('head') || has_marker?('tail'))
78
+ sv = Tioga::FigureConstants::LINE_CAP_BUTT
79
+ end
80
+ if sv != Tioga::FigureConstants::LINE_CAP_BUTT
81
+ t.line_cap = Tioga::FigureConstants::LINE_CAP_BUTT
82
+ end
83
+ draw_line(t, x1n, y1n, x2n, y2n)
84
+ if sv != Tioga::FigureConstants::LINE_CAP_BUTT
85
+ t.line_cap = sv
86
+ end
87
+
88
+ # Then, draw the arrow heads/tails
89
+ draw_symbol(t, 'head', angle, x2, y2)
90
+ draw_symbol(t, 'tail', angle - 180, x1, y1)
91
+
92
+ end
93
+
94
+ protected
95
+
96
+ # Return the dimension of the arrow size
97
+ def symbol_size(t, name)
98
+ sz = Types::Dimension.new(:dy,self.send("#{name}_scale") || 1.0)
99
+ sz.value *= case just(name)
100
+ when Tioga::FigureConstants::CENTERED
101
+ 0
102
+ when Tioga::FigureConstants::RIGHT_JUSTIFIED
103
+ 0.5
104
+ end
105
+ return sz
106
+ end
107
+
108
+ def just(name)
109
+ mkr = self.send("#{name}_marker")
110
+ if mkr == Tioga::MarkerConstants::Arrowhead or
111
+ mkr == Tioga::MarkerConstants::ArrowheadOpen
112
+ Tioga::FigureConstants::RIGHT_JUSTIFIED
113
+ else
114
+ Tioga::FigureConstants::CENTERED
115
+ end
116
+ end
117
+
118
+ def has_marker?(name)
119
+ mkr = self.send("#{name}_marker")
120
+ if ! mkr or mkr == 'None'
121
+ return false
122
+ else
123
+ return true
124
+ end
125
+ end
126
+
127
+ # Draw the arrow symbol for the given name (head or tail),
128
+ # with the given base angle and at the given position
129
+ def draw_symbol(t, name, angle, x, y)
130
+ hsh = {}
131
+ for k in %w(marker scale color angle)
132
+ tmp = self.send("#{name}_#{k}")
133
+ if tmp
134
+ hsh[k] = tmp
135
+ end
136
+ end
137
+ mkr = hsh['marker']
138
+ if ! mkr or mkr == 'None'
139
+ return
140
+ end
141
+
142
+ hsh['angle'] ||= 0
143
+ hsh['angle'] += angle
144
+
145
+ hsh['x'] = x
146
+ hsh['y'] = y
147
+
148
+ # Color defaults to line color
149
+ if @color and !hsh.key?('color')
150
+ hsh['color'] = @color
151
+ end
152
+
153
+ hsh['justification'] = just(name)
154
+ t.show_marker(hsh)
155
+ end
156
+
52
157
  end
158
+
159
+ # This class represents all the stylistic information necessary
160
+ # to draw a line parallel to a certain direction, indicated by
161
+ # an angle (default to horizontal)
162
+ class OrientedLineStyle < ArrowStyle
163
+ # The angle, in degrees.
164
+ typed_attribute :angle, 'float'
165
+
166
+ # The alignment of the line with respect to the point given.
167
+ typed_attribute :origin, 'justification'
168
+
169
+ # len is a dimension
170
+ def draw_oriented_arrow(t, xo, yo, len)
171
+
172
+ angle = @angle || 0.0
173
+
174
+ dx,dy = *len.to_figure(t, angle)
175
+
176
+ case @origin || Tioga::FigureConstants::LEFT_JUSTIFIED
177
+ when Tioga::FigureConstants::LEFT_JUSTIFIED
178
+ x1, y1 = xo, yo
179
+ x2, y2 = xo + dx, yo + dy
180
+ when Tioga::FigureConstants::CENTERED
181
+ x1, y1 = xo - 0.5 * dx, yo - 0.5 * dy
182
+ x2, y2 = xo + 0.5 * dx, yo + 0.5 * dy
183
+ when Tioga::FigureConstants::RIGHT_JUSTIFIED
184
+ x1, y1 = xo - dx, yo - dy
185
+ x2, y2 = xo, yo
186
+ end
187
+
188
+ draw_arrow(t, x1, y1, x2, y2)
189
+ end
190
+
191
+ end
192
+
53
193
  end
54
194
  end
55
195
  end
@@ -67,6 +67,12 @@ module CTioga2
67
67
  # The color of the stroke for the lines of the axis
68
68
  typed_attribute :stroke_color, 'color'
69
69
 
70
+ # The line width
71
+ typed_attribute :line_width, 'float'
72
+
73
+ # The line style
74
+ # typed_attribute :line_style,
75
+
70
76
  typed_attribute :major_tick_length, 'float'
71
77
  typed_attribute :major_tick_width, 'float'
72
78
 
@@ -144,7 +150,18 @@ minor_tick_length minor_tick_width)
144
150
  else
145
151
  spec['type']
146
152
  end
147
- t.show_axis(spec)
153
+ t.context do
154
+ if @line_width
155
+ # Holy gods, there is no way in Tioga to choose the line
156
+ # width.
157
+ #
158
+ # Here is essentially the proof that I must reimplement
159
+ # the axes.
160
+ t.xaxis_line_width = @line_width
161
+ t.yaxis_line_width = @line_width
162
+ end
163
+ t.show_axis(spec)
164
+ end
148
165
  # Now, we draw axis ticks
149
166
  if (type == Tioga::FigureConstants::AXIS_WITH_MAJOR_TICKS_AND_NUMERIC_LABELS) || (type == Tioga::FigureConstants::AXIS_WITH_TICKS_AND_NUMERIC_LABELS)
150
167
 
@@ -216,7 +216,7 @@ module CTioga2
216
216
  ret[key % k] = v
217
217
  end
218
218
  end
219
-
219
+
220
220
  if @sub_styles # Not always present too
221
221
  for sub in @sub_styles
222
222
  sym, cls, fmt, fc = *sub
@@ -239,7 +239,18 @@ module CTioga2
239
239
  end
240
240
 
241
241
  def self.sub_styles
242
- return @sub_styles
242
+ # p [:ss, self]
243
+ rv = if self.superclass.respond_to?(:sub_styles)
244
+ self.superclass.sub_styles
245
+ else
246
+ []
247
+ end
248
+ # p [:sparents, self, rv]
249
+ if @sub_styles
250
+ rv += @sub_styles
251
+ end
252
+ # p [:sparents_own, self, rv]
253
+ return rv
243
254
  end
244
255
 
245
256
  # Sets the values of the attributes from the given
@@ -275,7 +286,9 @@ module CTioga2
275
286
  cur_var = cls.new
276
287
  set_after = true
277
288
  end
289
+ # p :bef, fmt
278
290
  fmt = name % fmt
291
+ # p :aft, fmt
279
292
  nb = cur_var.set_from_hash(hash, fmt)
280
293
 
281
294
  # Here, this means that missing attributes do not get
@@ -325,6 +338,18 @@ module CTioga2
325
338
  end
326
339
  end
327
340
  end
341
+
342
+ # Now, substyles
343
+ for sb in self.class.sub_styles
344
+ symb, cls, fmt, fc = *sb
345
+ if instance_variable_defined?("@#{symb.to_s}")
346
+ sub = instance_variable_get("@#{symb.to_s}")
347
+ fmt = name % fmt
348
+ if ! sub.nil?
349
+ retval.update(sub.to_hash(fmt))
350
+ end
351
+ end
352
+ end
328
353
  return retval
329
354
  end
330
355
 
@@ -333,6 +358,20 @@ module CTioga2
333
358
  set_from_hash(other_object.to_hash)
334
359
  end
335
360
 
361
+ # Sets the style from the given hash or other object, if the
362
+ # style is not present yet.
363
+ def use_defaults_from(hsh)
364
+ if hsh.is_a? BasicStyle
365
+ hsh = hsh.to_hash
366
+ end
367
+ at = self.class.attribute_types
368
+ for k, v in hsh
369
+ if at.key?(k.to_sym) and ! instance_variable_defined?("@#{k}".to_sym)
370
+ self.send("#{k}=", v)
371
+ end
372
+ end
373
+ end
374
+
336
375
  # Converts a hash in text format into a format suitable for
337
376
  # feeding to #set_from_hash. Only relevant keys are
338
377
  # converted. Keys that exist in the options hash but are not
@@ -1,4 +1,4 @@
1
- # arrows.rb: style objects for lines and arrows
1
+ # box.rb: style objects for boxes
2
2
  # copyright (c) 2012 by Vincent Fourmond
3
3
 
4
4
  # This program is free software; you can redistribute it and/or modify
@@ -59,39 +59,6 @@ module CTioga2
59
59
 
60
60
  end
61
61
 
62
- # This class represents all the stylistic information necessary
63
- # to draw a line parallel to a certain direction, indicated by
64
- # an angle (default to horizontal)
65
- class OrientedLineStyle < StrokeStyle
66
- # The angle, in degrees.
67
- typed_attribute :angle, 'float'
68
-
69
- # The alignment of the line with respect to the point given.
70
- typed_attribute :origin, 'justification'
71
-
72
- # len is a dimension
73
- def draw_oriented_line(t, xo, yo, len)
74
-
75
- angle = @angle || 0.0
76
-
77
- dx,dy = *len.to_figure(t, angle)
78
-
79
- case @origin || Tioga::FigureConstants::LEFT_JUSTIFIED
80
- when Tioga::FigureConstants::LEFT_JUSTIFIED
81
- x1, y1 = xo, yo
82
- x2, y2 = xo + dx, yo + dy
83
- when Tioga::FigureConstants::CENTERED
84
- x1, y1 = xo - 0.5 * dx, yo - 0.5 * dy
85
- x2, y2 = xo + 0.5 * dx, yo + 0.5 * dy
86
- when Tioga::FigureConstants::RIGHT_JUSTIFIED
87
- x1, y1 = xo - dx, yo - dy
88
- x2, y2 = xo, yo
89
- end
90
-
91
- draw_line(t, x1, y1, x2, y2)
92
- end
93
-
94
- end
95
62
 
96
63
  # This class represents all the stylistic information to draw a
97
64
  # Marker.
@@ -102,42 +69,81 @@ module CTioga2
102
69
  # be handled directly in the marker specification...
103
70
  class MarkerStyle < BasicStyle
104
71
 
105
- # The color
106
- typed_attribute :color, 'color'
107
-
108
72
  # The marker
109
73
  typed_attribute :marker, 'marker'
110
74
 
111
75
  # The marker scale
112
76
  typed_attribute :scale, 'float'
113
77
 
78
+ # The angle
79
+ typed_attribute :angle, 'float'
80
+
81
+ # The default for color
82
+ typed_attribute :color, 'color-or-false'
83
+
84
+ # The stroke color
85
+ typed_attribute :line_color, 'color-or-false'
86
+
87
+ # The fill color
88
+ typed_attribute :fill_color, 'color-or-false'
89
+
90
+ # The stroke width
91
+ typed_attribute :line_width, 'float'
92
+
114
93
  # Shows the marker at a given location/set of locations.
115
94
  #
116
95
  # \p override is a hash that can override part of the
117
96
  # dictionnary specification.
118
97
  def draw_markers_at(t, x, y, override = nil)
119
98
  return if (! @marker || @marker == 'None')
99
+
100
+ dict = {
101
+ 'marker' => @marker
102
+ }
103
+ if @line_width
104
+ dict['stroke_width'] = @line_width
105
+ end
106
+ if !(@fill_color.nil?) || !(@line_color.nil?)
107
+ dict['fill_color'] = @fill_color.nil? ? @color : @fill_color
108
+ dict['stroke_color'] = @line_color.nil? ? @color : @line_color
109
+ dict['rendering_mode'] =
110
+ if dict['fill_color']
111
+ if dict['stroke_color']
112
+ Tioga::FigureConstants::FILL_AND_STROKE
113
+ else
114
+ Tioga::FigureConstants::FILL
115
+ end
116
+ else
117
+ Tioga::FigureConstants::STROKE
118
+ end
119
+ dict.strip_if_false!(%w{fill_color stroke_color})
120
+ else
121
+ dict['color'] = @color
122
+ if ! @color
123
+ return # Nothing to do !
124
+ end
125
+ end
126
+ if @angle
127
+ dict['angle'] = @angle
128
+ end
129
+
130
+ if x.is_a? Numeric
131
+ dict['x'] = x
132
+ dict['y'] = y
133
+ else
134
+ dict['Xs'] = x
135
+ dict['Ys'] = y
136
+ end
137
+
138
+ if @scale
139
+ dict['scale'] = @scale
140
+ end
141
+ if override
142
+ dict.merge!(override)
143
+ end
120
144
  t.context do
121
145
  ## \todo allow custom line types for markers ?
122
146
  t.line_type = LineStyles::Solid
123
- dict = {
124
- 'marker' => @marker,
125
- 'color' => @color
126
- }
127
- if x.is_a? Numeric
128
- dict['x'] = x
129
- dict['y'] = y
130
- else
131
- dict['Xs'] = x
132
- dict['Ys'] = y
133
- end
134
-
135
- if @scale
136
- dict['scale'] = @scale
137
- end
138
- if override
139
- dict.merge!(override)
140
- end
141
147
  t.show_marker(dict)
142
148
  end
143
149
  end
@@ -26,7 +26,12 @@ module CTioga2
26
26
  # This class represents the stylistic information necessary to
27
27
  # draw an error bar. It derives from StrokeStyle, as it is
28
28
  # essentially a stroke.
29
- class ErrorBarStyle < StrokeStyle
29
+ class ErrorBarStyle < BasicStyle
30
+
31
+ # The style of the line that is drawn, as a StrokeStyle.
32
+ sub_style :line, StrokeStyle
33
+
34
+ alias_for :color, :line_color
30
35
 
31
36
  # The error bar style. For now, not much here.
32
37
  attr_accessor :style
@@ -42,8 +47,8 @@ module CTioga2
42
47
  def show_error_bar(t, x, xmin, xmax, y, ymin, ymax)
43
48
  d = { 'x' => x,
44
49
  'y' => y,
45
- 'color' => @color || Tioga::ColorConstants::Black,
46
- 'line_width' => @width || 1.0,
50
+ 'color' => @line.color || Tioga::ColorConstants::Black,
51
+ 'line_width' => @line.width || 1.0,
47
52
  }
48
53
  has = false
49
54
  if (xmin && xmax && (xmax - xmin != 0))
@@ -60,6 +65,8 @@ module CTioga2
60
65
  # We won't draw something when there isn't anything to draw
61
66
  # !
62
67
  if(has)
68
+ # We should stop relying on Tioga for that.
69
+ # Probably this is the place to reimplement that ?
63
70
  t.show_error_bars(d)
64
71
  end
65
72
  end