dyi 1.1.1 → 1.1.2

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 (48) hide show
  1. data/CHANGES +7 -1
  2. data/lib/dyi.rb +3 -1
  3. data/lib/dyi/animation.rb +5 -4
  4. data/lib/dyi/canvas.rb +5 -8
  5. data/lib/dyi/chart.rb +1 -1
  6. data/lib/dyi/chart/array_reader.rb +104 -10
  7. data/lib/dyi/chart/axis_util.rb +31 -17
  8. data/lib/dyi/chart/base.rb +104 -7
  9. data/lib/dyi/chart/csv_reader.rb +56 -8
  10. data/lib/dyi/chart/excel_reader.rb +27 -4
  11. data/lib/dyi/chart/legend.rb +10 -8
  12. data/lib/dyi/chart/line_chart.rb +29 -25
  13. data/lib/dyi/chart/pie_chart.rb +192 -29
  14. data/lib/dyi/chart/table.rb +12 -10
  15. data/lib/dyi/color.rb +9 -7
  16. data/lib/dyi/coordinate.rb +177 -61
  17. data/lib/dyi/drawing.rb +1 -1
  18. data/lib/dyi/drawing/clipping.rb +9 -3
  19. data/lib/dyi/drawing/color_effect.rb +7 -4
  20. data/lib/dyi/drawing/filter.rb +10 -7
  21. data/lib/dyi/drawing/pen.rb +421 -11
  22. data/lib/dyi/drawing/pen_3d.rb +12 -7
  23. data/lib/dyi/element.rb +5 -4
  24. data/lib/dyi/event.rb +3 -3
  25. data/lib/dyi/font.rb +6 -4
  26. data/lib/dyi/formatter.rb +1 -1
  27. data/lib/dyi/formatter/base.rb +24 -15
  28. data/lib/dyi/formatter/emf_formatter.rb +6 -5
  29. data/lib/dyi/formatter/eps_formatter.rb +15 -14
  30. data/lib/dyi/formatter/svg_formatter.rb +16 -14
  31. data/lib/dyi/formatter/svg_reader.rb +4 -3
  32. data/lib/dyi/formatter/xaml_formatter.rb +9 -7
  33. data/lib/dyi/length.rb +213 -114
  34. data/lib/dyi/matrix.rb +4 -2
  35. data/lib/dyi/painting.rb +161 -87
  36. data/lib/dyi/script.rb +1 -1
  37. data/lib/dyi/script/ecmascript.rb +18 -29
  38. data/lib/dyi/script/simple_script.rb +4 -8
  39. data/lib/dyi/shape.rb +1 -1
  40. data/lib/dyi/shape/base.rb +8 -17
  41. data/lib/dyi/shape/path.rb +102 -19
  42. data/lib/dyi/stylesheet.rb +4 -3
  43. data/lib/dyi/svg_element.rb +9 -7
  44. data/lib/dyi/type.rb +5 -2
  45. data/lib/dyi/util.rb +36 -1
  46. data/lib/ironruby.rb +1 -1
  47. data/lib/util.rb +53 -5
  48. metadata +4 -19
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: UTF-8 -*-
2
2
 
3
- # Copyright (c) 2009-2011 Sound-F Co., Ltd. All rights reserved.
3
+ # Copyright (c) 2009-2012 Sound-F Co., Ltd. All rights reserved.
4
4
  #
5
5
  # Author:: Mamoru Yuo
6
6
  #
@@ -27,8 +27,48 @@ require 'nkf'
27
27
  module DYI
28
28
  module Chart
29
29
 
30
- # CsvReader class provides a interface to CSV file and data for a chart
30
+ # +CsvReader+ class provides a interface to CSV file and data for a chart
31
31
  # object.
32
+ #
33
+ #= Basic Usage
34
+ #
35
+ # Using +PieChart+ and CsvReader, you can create the pie chart as the
36
+ # following:
37
+ # # contents of asian_gdp.csv
38
+ # # -------------------------
39
+ # # China,5878
40
+ # # Japan,5459
41
+ # # India,1538
42
+ # # South Koria,1007
43
+ # # Other Countries, 2863
44
+ #
45
+ # require 'rubygems'
46
+ # require 'dyi'
47
+ #
48
+ # reader = DYI::Chart::CsvReader.read('asian_gdp.csv',
49
+ # :schema => [:name, :value],
50
+ # :data_types => [:string, :number])
51
+ #
52
+ # # Creates the Pie Chart
53
+ # chart = DYI::Chart::PieChart.new(450,250)
54
+ # chart.load_data(reader)
55
+ # chart.save('asian_gdp.svg')
56
+ # Creating the instance, you should not call +new+ method but {.read} method.
57
+ #
58
+ # The optional argument +:schema+ means a field name. See {ArrayReader} for
59
+ # +:schema+ option. The optional argument +:data_types+ means data types of
60
+ # the field. Using this option, +CsvReader+ converts text data that the CSV
61
+ # data included into a appropriate ruby object. (+:data_types+ option has
62
+ # been implemented in +ArrayReader+, although +ArrayReader+ ignores this
63
+ # option.) If +:data_types+ option is not specified, the values of all the
64
+ # fields are converted into instances of +Float+. +:data_types+ option can
65
+ # specify the following values: +:string+, +:decimal+, +:number+(synonym of
66
+ # +:decimal+), +:float+, +:integer+, +:date+, +:datetime+, +:boolean+
67
+ #
68
+ # See {CsvReader.read CsvReader.read} for other optional arguments.
69
+ # @see ArrayReader
70
+ # @see ArrayReader.read
71
+ # @since 0.0.0
32
72
  class CsvReader < ArrayReader
33
73
 
34
74
  # @private
@@ -37,6 +77,7 @@ module DYI
37
77
  # Parses CSV data and sets data.
38
78
  # @param [String] csv CSV data
39
79
  # @option (see ArrayReader#read)
80
+ # @option options [Array<Symbol>] :data_types array of field data types
40
81
  # @option options [String] :date_format date format string of CSV data,
41
82
  # parsing a date string in CSV at +Date#strptime+
42
83
  # @option options [String] :datetime_format date-time format string of CSV
@@ -47,8 +88,10 @@ module DYI
47
88
  # @option options [String] :col_sep a separator of columns, default to
48
89
  # <tt>","</tt>
49
90
  # @option options [String] :row_sep a separator of rows, default to
50
- # +:auto+ which means that a separetor is <tt>"\r\n"</tt>, <tt>"\n"</tt>,
51
- # or <tt>"\r"</tt> sequence
91
+ # +:auto+, which means that a separetor is <tt>"\r\n"</tt>,
92
+ # <tt>"\n"</tt>, or <tt>"\r"</tt> sequence
93
+ # @raise [ArgumentError] unknown encode is given for +:encode+
94
+ # @see ArrayReader#read
52
95
  # @since 1.1.1
53
96
  def parse(csv, options={})
54
97
  options = options.clone
@@ -75,6 +118,8 @@ module DYI
75
118
  # Parses CSV file and sets data.
76
119
  # @param [String] path a path of the CSV file
77
120
  # @option (see #parse)
121
+ # @raise (see #parse)
122
+ # @see (see #parse)
78
123
  def read(path, options={})
79
124
  parse(IO.read(path), options)
80
125
  end
@@ -112,8 +157,9 @@ module DYI
112
157
  # Parses CSV file and creates instance of CsvReader.
113
158
  # @param (see #read)
114
159
  # @option (see #read)
115
- # @return [CsvReader] a new instance of CsvReader
116
- # @see ArrayReader.read
160
+ # @return (see .parse)
161
+ # @raise (see #read)
162
+ # @see (see .parse)
117
163
  def read(path, options={})
118
164
  new.read(path, options)
119
165
  end
@@ -122,9 +168,11 @@ module DYI
122
168
  # @param (see #parse)
123
169
  # @option (see #parse)
124
170
  # @return [CsvReader] a new instance of CsvReader
171
+ # @raise (see #parse)
125
172
  # @see ArrayReader.read
126
- def parse(path, options={})
127
- new.parse(path, options)
173
+ # @since 1.1.1
174
+ def parse(csv, options={})
175
+ new.parse(csv, options)
128
176
  end
129
177
  end
130
178
  end
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: UTF-8 -*-
2
2
 
3
- # Copyright (c) 2009-2011 Sound-F Co., Ltd. All rights reserved.
3
+ # Copyright (c) 2009-2012 Sound-F Co., Ltd. All rights reserved.
4
4
  #
5
5
  # Author:: Mamoru Yuo
6
6
  #
@@ -28,12 +28,28 @@ end
28
28
  require 'date'
29
29
  require 'nkf'
30
30
 
31
- module DYI #:nodoc:
32
- module Chart #:nodoc:
31
+ module DYI
32
+ module Chart
33
33
 
34
+ # +ExcelReader+ class provides a interface to Microsoft Excel file and data
35
+ # for a chart object. Creating the instance, you should not call +new+
36
+ # method but {.read} method.
37
+ #
38
+ # This class requires that _win32ole_ has been installed your system.
39
+ # @see ArrayReader
40
+ # @since 0.0.0
34
41
  class ExcelReader < ArrayReader
42
+
43
+ # @private
35
44
  OFFSET = DateTime.now.offset
36
45
 
46
+ # Parses Excel file and sets data.
47
+ # @param [String] path a path of the Excel file
48
+ # @option (see ArrayReader#read)
49
+ # @option options [String, Integer] :sheet sheet name of data source or
50
+ # sheet number (starting from 1)
51
+ # @raise [NotImplementedError] _win32ole_ has not been installed
52
+ # @see ArrayReader#read
37
53
  def read(path, options={})
38
54
  if defined? WIN32OLE
39
55
  # for Windows
@@ -45,7 +61,7 @@ module DYI #:nodoc:
45
61
  sheet_values = sheet.range(sheet.cells(1,1), sheet.cells(range.end(4).row, range.end(2).column)).value
46
62
  else
47
63
  # except Windows
48
- raise NotImplementedError, 'win32ole is not installed'
64
+ raise NotImplementedError, 'win32ole has not been installed'
49
65
  end
50
66
 
51
67
  begin
@@ -91,6 +107,13 @@ module DYI #:nodoc:
91
107
  end
92
108
 
93
109
  class << self
110
+
111
+ # Parses Excel file and creates instance of ExcelReader.
112
+ # @param (see #read)
113
+ # @option (see #read)
114
+ # @return [ExcelReader] a new instance of ExcelReader
115
+ # @raise (see #read)
116
+ # @see ArrayReader.read
94
117
  def read(path, options={})
95
118
  new.read(path, options)
96
119
  end
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: UTF-8 -*-
2
2
 
3
- # Copyright (c) 2009-2011 Sound-F Co., Ltd. All rights reserved.
3
+ # Copyright (c) 2009-2012 Sound-F Co., Ltd. All rights reserved.
4
4
  #
5
5
  # Author:: Mamoru Yuo
6
6
  #
@@ -19,14 +19,16 @@
19
19
  # You should have received a copy of the GNU General Public License
20
20
  # along with DYI. If not, see <http://www.gnu.org/licenses/>.
21
21
 
22
- module DYI #:nodoc:
23
- module Chart #:nodoc:
22
+ #
23
+ module DYI
24
+ module Chart
24
25
 
26
+ # @since 0.0.0
25
27
  module Legend
26
28
 
27
29
  private
28
30
 
29
- def draw_legend(names, shapes=nil, records=nil, colors=nil) #:nodoc:
31
+ def draw_legend(names, shapes=nil, records=nil, colors=nil)
30
32
  legend_canvas.translate(legend_point.x, legend_point.y)
31
33
  if show_legend?
32
34
  pen = Drawing::Pen.black_pen(:font => legend_font)
@@ -53,15 +55,15 @@ module DYI #:nodoc:
53
55
  end
54
56
  end
55
57
 
56
- def legend_font_size #:nodoc:
58
+ def legend_font_size
57
59
  legend_font ? legend_font.draw_size : Font::DEFAULT_SIZE
58
60
  end
59
61
 
60
- def default_legend_point #:nodoc:
62
+ def default_legend_point
61
63
  Coordinate.new(0,0)
62
64
  end
63
65
 
64
- def default_legend_format #:nodoc:
66
+ def default_legend_format
65
67
  "{name}"
66
68
  end
67
69
 
@@ -69,7 +71,7 @@ module DYI #:nodoc:
69
71
 
70
72
  private
71
73
 
72
- def included(klass) #:nodoc:
74
+ def included(klass)
73
75
  klass.__send__(:opt_accessor, :show_legend, :type => :boolean, :default => true)
74
76
  klass.__send__(:opt_accessor, :legend_font, :type => :font)
75
77
  klass.__send__(:opt_accessor, :legend_format, :type => :string, :default_method => :default_legend_format)
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: UTF-8 -*-
2
2
 
3
- # Copyright (c) 2009-2011 Sound-F Co., Ltd. All rights reserved.
3
+ # Copyright (c) 2009-2012 Sound-F Co., Ltd. All rights reserved.
4
4
  #
5
5
  # Author:: Mamoru Yuo
6
6
  #
@@ -19,9 +19,12 @@
19
19
  # You should have received a copy of the GNU General Public License
20
20
  # along with DYI. If not, see <http://www.gnu.org/licenses/>.
21
21
 
22
- module DYI #:nodoc:
23
- module Chart #:nodoc:
22
+ #
23
+ module DYI
24
+
25
+ module Chart
24
26
 
27
+ # @since 0.0.0
25
28
  class LineChart < Base
26
29
  include AxisUtil
27
30
  include Legend
@@ -50,7 +53,6 @@ module DYI #:nodoc:
50
53
  opt_accessor :max_x_label_count, {:type => :integer, :default_proc => proc{|c| c.chart_width.div(Length.new(96))}}
51
54
  opt_accessor :show_x_labels, {:type => :boolean, :default => true}
52
55
  opt_accessor :legend_texts, {:type => :array, :item_type => :string}
53
- # opt_accessor :data_columns, {:type => :array, :item_type => :integer}
54
56
  opt_accessor :use_effect, {:type => :boolean, :default => true}
55
57
  opt_accessor :bar_seriese_interval, {:type => :float, :default => 0.3}
56
58
  opt_accessor :color_columns, {:type => :array, :item_type => :integer}
@@ -141,18 +143,19 @@ module DYI #:nodoc:
141
143
  Drawing::Brush.new(:color => color)
142
144
  end
143
145
 
144
- private
145
-
146
+ # @since 1.1.0
146
147
  def initialize(*args)
147
148
  super
148
149
  init_container
149
150
  end
150
151
 
151
- def default_legend_point #:nodoc:
152
+ private
153
+
154
+ def default_legend_point
152
155
  Coordinate.new(margin_left, 0)
153
156
  end
154
157
 
155
- def create_vector_image #:nodoc:
158
+ def create_vector_image
156
159
  super
157
160
 
158
161
  main_series_data = []
@@ -177,11 +180,12 @@ module DYI #:nodoc:
177
180
  second_axis_settings[:min],
178
181
  second_axis_settings[:max]) if use_y_second_axis?
179
182
 
180
- data.values_size.times do |i|
181
- draw_chart(i, chart_type(i), chart_color(i), use_y_second_axis?(i) ? sub_settings : settings) if chart_type(i) == :stackedbar
182
- end
183
- (data.values_size - 1).downto(0) do |i|
184
- draw_chart(i, chart_type(i), chart_color(i), use_y_second_axis?(i) ? sub_settings : settings) if chart_type(i) != :stackedbar
183
+ [:stackedbar, :bar, :area, :line].each do |chart_type|
184
+ data.values_size.times do |i|
185
+ if chart_type(i) == chart_type
186
+ draw_chart(i, chart_type(i), chart_color(i), use_y_second_axis?(i) ? sub_settings : settings)
187
+ end
188
+ end
185
189
  end
186
190
 
187
191
  draw_axis(settings, sub_settings)
@@ -189,7 +193,7 @@ module DYI #:nodoc:
189
193
  draw_legend(texts, legend_shapes)
190
194
  end
191
195
 
192
- def init_container #:nodoc:
196
+ def init_container
193
197
  # mask = Drawing::ColorEffect::Mask.new(@canvas)
194
198
  # mask.add_shapes(Shape::Rectangle.new(Drawing::Brush.new(:color => '#FFFFFF'), [margin_left, margin_top], chart_width, chart_height))
195
199
  @axis_back_canvas = Shape::ShapeGroup.draw_on(@canvas) unless @axis_back_canvas
@@ -206,7 +210,7 @@ module DYI #:nodoc:
206
210
  @chart_front_canvas.set_clipping(chart_clip)
207
211
  end
208
212
 
209
- def draw_axis(settings, sub_settings) #:nodoc:
213
+ def draw_axis(settings, sub_settings)
210
214
  line_options = {:linecap => 'square'}
211
215
  line_pen = represent_3d? ? Drawing::CubicPen.new(line_options.merge(s_3d_pen_options)) : Drawing::Pen.new(line_options)
212
216
  sub_pen = represent_3d? ? Drawing::Pen.new : line_pen
@@ -218,7 +222,7 @@ module DYI #:nodoc:
218
222
  draw_scale(sub_pen, text_pen, settings, sub_settings, text_margin)
219
223
  end
220
224
 
221
- def draw_y_axis(pen) #:nodoc:
225
+ def draw_y_axis(pen)
222
226
  if use_y_second_axis? || main_y_axis == :left
223
227
  start_point = [margin_left, height - margin_bottom]
224
228
  end_point = [margin_left, margin_top]
@@ -232,7 +236,7 @@ module DYI #:nodoc:
232
236
  end
233
237
  end
234
238
 
235
- def draw_scale(line_pen, text_pen, settings, sub_settings, text_margin) #:nodoc:
239
+ def draw_scale(line_pen, text_pen, settings, sub_settings, text_margin)
236
240
  if settings[:min] == settings[:min_scale_value] - settings[:scale_interval]
237
241
  y = value_position_on_chart(margin_top, settings, settings[:min], true)
238
242
  if use_y_second_axis? || main_y_axis == :left
@@ -321,7 +325,7 @@ module DYI #:nodoc:
321
325
  i % ((data.records_size - 1) / [max_x_label_count - 1, 1].max) == 0
322
326
  end
323
327
 
324
- def draw_x_axis(main_pen, sub_pen, text_pen, text_margin) #:nodoc:
328
+ def draw_x_axis(main_pen, sub_pen, text_pen, text_margin)
325
329
  main_pen.draw_line(represent_3d? ? @axis_back_canvas : @axis_front_canvas, [margin_left, height - margin_bottom], [width - margin_right, height - margin_bottom])
326
330
 
327
331
  data.records_size.times do |i|
@@ -342,7 +346,7 @@ module DYI #:nodoc:
342
346
  end
343
347
  end
344
348
 
345
- def draw_chart(id, chart_type, color, settings) #:nodoc:
349
+ def draw_chart(id, chart_type, color, settings)
346
350
  case chart_type
347
351
  when :line then draw_line(id, color, settings)
348
352
  when :area then draw_area(id, color, settings)
@@ -351,7 +355,7 @@ module DYI #:nodoc:
351
355
  end
352
356
  end
353
357
 
354
- def draw_line(id, color, settings) #:nodoc:
358
+ def draw_line(id, color, settings)
355
359
  values = data.series(id)
356
360
  return if values.compact.size == 0
357
361
  first_index = values.each_with_index {|value, i| break i if value}
@@ -371,7 +375,7 @@ module DYI #:nodoc:
371
375
  pen.linejoin = 'bevel'
372
376
  end
373
377
 
374
- def draw_area(id, color, settings) #:nodoc:
378
+ def draw_area(id, color, settings)
375
379
  values = data.series(id)
376
380
  return if values.compact.size == 0
377
381
  first_index = values.each_with_index {|value, i| break i if value}
@@ -391,7 +395,7 @@ module DYI #:nodoc:
391
395
  polygone.translate(back_translate_value[:dx], back_translate_value[:dy]) if represent_3d?
392
396
  end
393
397
 
394
- def draw_bar(id, color, settings) #:nodoc:
398
+ def draw_bar(id, color, settings)
395
399
  bar_group = Shape::ShapeGroup.new(@chart_options).draw_on(@chart_front_canvas)
396
400
  values = data.series(id)
397
401
  return if values.compact.size == 0
@@ -409,7 +413,7 @@ module DYI #:nodoc:
409
413
  bar_group.translate(back_translate_value[:dx] / 2, back_translate_value[:dy] / 2) if represent_3d?
410
414
  end
411
415
 
412
- def draw_stackedbar(id, color, settings) #:nodoc:
416
+ def draw_stackedbar(id, color, settings)
413
417
  bar_group = Shape::ShapeGroup.new(@chart_options).draw_on(@chart_front_canvas)
414
418
 
415
419
  values = data.series(id)
@@ -433,14 +437,14 @@ module DYI #:nodoc:
433
437
  end
434
438
 
435
439
  # @since 1.0.0
436
- def chart_color(index) #:nodoc:
440
+ def chart_color(index)
437
441
  if chart_colors
438
442
  color = chart_colors[index]
439
443
  end
440
444
  color || DEFAULT_CHART_COLOR[index % DEFAULT_CHART_COLOR.size]
441
445
  end
442
446
 
443
- def legend_shapes #:nodoc:
447
+ def legend_shapes
444
448
  result = []
445
449
  (0...data.values_size).each_with_index do |id, index|
446
450
  result <<
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: UTF-8 -*-
2
2
 
3
- # Copyright (c) 2009-2011 Sound-F Co., Ltd. All rights reserved.
3
+ # Copyright (c) 2009-2012 Sound-F Co., Ltd. All rights reserved.
4
4
  #
5
5
  # Author:: Mamoru Yuo
6
6
  #
@@ -19,43 +19,205 @@
19
19
  # You should have received a copy of the GNU General Public License
20
20
  # along with DYI. If not, see <http://www.gnu.org/licenses/>.
21
21
 
22
- module DYI #:nodoc:
23
- module Chart #:nodoc:
22
+ #
23
+ module DYI
24
+ module Chart
24
25
 
26
+ # +PieChart+ creates the image of pie chart.
27
+ #
28
+ #= Basic Usage
29
+ #
30
+ # Using +PieChart+ and ArrayReader (or sub class of ArrayReader), you can
31
+ # create the pie chart as the following:
32
+ # require 'rubygems'
33
+ # require 'dyi'
34
+ #
35
+ # # Nominal GDP of Asian Countries (2010)
36
+ # chart_data = [['China', 5878],
37
+ # ['Japan', 5459],
38
+ # ['India', 1538],
39
+ # ['South Koria', 1007],
40
+ # ['Other Countries', 2863]]
41
+ # reader = DYI::Chart::ArrayReader.read(chart_data, :schema => [:name, :value])
42
+ #
43
+ # # Creates the Pie Chart
44
+ # chart = DYI::Chart::PieChart.new(450,250)
45
+ # chart.load_data(reader)
46
+ # chart.save('asian_gdp.svg')
47
+ # See {ArrayReader} about how to set the chart data.
48
+ #
49
+ # The chart options of +PieChart+ are specified at the constractor. See
50
+ # <em>Instance Attribute</em> of this class, {Base} and {Legend} for the
51
+ # attributes that can be specified. The specified attributes can be refered
52
+ # and set.
53
+ # # Creates the Pie Chart
54
+ # chart = DYI::Chart::PieChart.new(500,250,
55
+ # :center_point => [130, 100],
56
+ # :legend_point => [250, 50],
57
+ # :represent_3d => true,
58
+ # :_3d_settings => {:dy => 20},
59
+ # :legend_format => "{?name}\t{!e}{?value:#,0}\t{!e}({?percent:0.0%})",
60
+ # :chart_stroke_color => 'white')
61
+ # puts chart.represent_3d? # => true
62
+ # chart.show_baloon = false
63
+ # puts chart.show_baloon? # => false
64
+ #
65
+ # chart.load_data(reader)
66
+ # chart.save('asian_gdp.svg')
67
+ #
68
+ #= Adds Custom Elements to Chart
69
+ #
70
+ # Using {#canvas canvas} attribute, you can add arbitrary graphical elements.
71
+ # # Creates the Pie Chart
72
+ # chart = DYI::Chart::PieChart.new(500,250,
73
+ # :center_point => [130, 100],
74
+ # :legend_point => [250, 50],
75
+ # :represent_3d => true,
76
+ # :_3d_settings => {:dy => 20},
77
+ # :legend_format => "{?name}\t{!e}{?value:#,0}\t{!e}({?percent:0.0%})",
78
+ # :chart_stroke_color => 'white')
79
+ #
80
+ # DYI::Drawing::Pen.black_pen.draw_text(chart.canvas,
81
+ # [250, 20],
82
+ # 'Nominal GDP of Asian Countries (2010)',
83
+ # :text_anchor => 'middle')
84
+ # chart.load_data(reader)
85
+ # chart.save('asian_gdp.svg')
86
+ # @see LineChart
87
+ # @see ArrayReader
88
+ # @since 0.0.0
25
89
  class PieChart < Base
26
90
  include Legend
27
91
 
28
- attr_reader :chart_canvas, :data_label_canvas, :legend_canvas
29
-
30
- opt_accessor :center_point, {:type => :point, :default_method => :default_center_point}
31
- opt_accessor :chart_radius_x, {:type => :length, :default_method => :default_chart_radius_x}
32
- opt_accessor :chart_radius_y, {:type => :length, :default_method => :default_chart_radius_y}
33
- opt_accessor :inner_radius, {:type => :float, :default => 0.0, :range => 0.0 ... 1.0}
34
- opt_accessor :represent_3d, {:type => :boolean}
35
- opt_accessor :_3d_settings, {:type => :hash, :default => {}, :keys => [:dy], :item_type => :float}
36
- opt_accessor :chart_colors, {:type => :array, :item_type => :color}
37
- opt_accessor :chart_stroke_color, {:type => :color}
38
- opt_accessor :chart_stroke_width, {:type => :float, :default => 1}
39
- opt_accessor :moved_elements, {:type => :array, :item_type => :float}
92
+ # Returns the container element which body of chart is drawn on.
93
+ # @return [Shape::ShapeGroup] the container element which chart parts is
94
+ # drawn on
95
+ attr_reader :chart_canvas
96
+
97
+ # Returns the container element which data labels is drawn on.
98
+ # @return [Shape::ShapeGroup] the container element which chart parts is
99
+ # drawn on
100
+ attr_reader :data_label_canvas
101
+
102
+ # Returns the container element which legend is drawn on.
103
+ # @return [Shape::ShapeGroup] the container element which chart parts is
104
+ # drawn on
105
+ attr_reader :legend_canvas
106
+
107
+ # Returns or sets the center point of the pie chart.
108
+ opt_accessor :center_point, :type => :point, :default_method => :default_center_point
109
+
110
+ # Returns or sets the x-axis radius of the pie chart.
111
+ opt_accessor :chart_radius_x, :type => :length, :default_method => :default_chart_radius_x
112
+
113
+ # Returns or sets the y-axis radius of the pie chart.
114
+ opt_accessor :chart_radius_y, :type => :length, :default_method => :default_chart_radius_y
115
+
116
+ # Returns or sets the ratio of inner radius to outer radius of the
117
+ # doughnut chart. The value of +inner_radius+ should be a positive number
118
+ # or zero less than 1.0. Defalt to 0.0 (that means that chart is not
119
+ # doughnut).
120
+ opt_accessor :inner_radius, :type => :float, :default => 0.0, :range => 0.0 ... 1.0
121
+
122
+ # Returns or sets whether the chart is made three-dimensional. Defalt to
123
+ # false.
124
+ opt_accessor :represent_3d, :type => :boolean
125
+
126
+ # Returns or sets the three-demenal setting hash.
127
+ # This attribute is valid if the +respond_3d+ attribute equals true.
128
+ # The hash includes the following key:
129
+ # [+:dy+] ({Length}) the thickness of the pie
130
+ opt_accessor :_3d_settings, :type => :hash, :default => {}, :keys => [:dy], :item_type => :length
131
+
132
+ # Returns or sets specific colors for the slices.
133
+ opt_accessor :chart_colors, :type => :array, :item_type => :color
134
+
135
+ # Returns or sets the color of the outline of the slices.
136
+ opt_accessor :chart_stroke_color, :type => :color
137
+
138
+ # Returns or sets the width of the outline of the slices. Default to 1.0.
139
+ opt_accessor :chart_stroke_width, :type => :float, :default => 1.0
140
+
141
+ # Returns or sets the array of the ratio of the distance which the slices
142
+ # are moved from the center to the outside.
143
+ opt_accessor :moved_elements, :type => :array, :item_type => :float
144
+
145
+ # Returns or sets the CSS class of the pie area.
40
146
  opt_accessor :pie_css_class, :type => :string
41
- opt_accessor :show_data_label, {:type => :boolean, :default => true}
147
+
148
+ # Returns or sets whether the data labels are shown. Defalt to true.
149
+ opt_accessor :show_data_label, :type => :boolean, :default => true
150
+
151
+ # Returns or sets the CSS class of the data labels.
42
152
  opt_accessor :data_label_css_class, :type => :string
43
- opt_accessor :data_label_position, {:type => :float, :default => 0.8}
44
- opt_accessor :data_label_font, {:type => :font}
45
- opt_accessor :data_label_format, {:type => :string, :default => "{?name}"}
46
- opt_accessor :hide_data_label_ratio, {:type => :float, :default => 0.00}
153
+
154
+ # Returns or sets the position of the data labels. Zero means the data
155
+ # labels are shown at the center point, and 1.0 means they are shown on
156
+ # the circumference of the pie. Default to 0.8.
157
+ opt_accessor :data_label_position, :type => :float, :default => 0.8
158
+
159
+ # Returns or sets the font of the data labels.
160
+ opt_accessor :data_label_font, :type => :font
161
+
162
+ # Returns or sets the format string of the data labels. Default to <tt>"{?name}"</tt>.
163
+ opt_accessor :data_label_format, :type => :string, :default => "{?name}"
164
+
165
+ # Returns or sets the value to control showing the data labels. If the
166
+ # slice's percentage of the pie is less than this value, its label is not
167
+ # shown. Default to 0.0 (it means all the labels are shown).
168
+ opt_accessor :hide_data_label_ratio, :type => :float, :default => 0.0
169
+
170
+ # Returns or sets whether the baloons are shown when the mouse is over the
171
+ # slices. Defalt to true.
47
172
  opt_accessor :show_baloon, :type => :boolean, :default => true
173
+
174
+ # Returns or sets the font of the baloons.
48
175
  opt_accessor :baloon_font, :type => :font
49
- opt_accessor :baloon_position, {:type => :float, :default => 0.8}
176
+
177
+ # Returns or sets the position of the baloons. Zero means the baloons are
178
+ # shown at the center point, and 1.0 means they are shown on the
179
+ # circumference of the pie. Default to 0.8.
180
+ opt_accessor :baloon_position, :type => :float, :default => 0.8
181
+
182
+ # Returns or sets the format string of the baloons. Default to
183
+ # <tt>"{?name}\n{?value}"</tt>.
50
184
  opt_accessor :baloon_format, :type => :string, :default => "{?name}\n{?value}"
185
+
186
+ # Returns or sets the hash of the vertical and horizontal paddings of the
187
+ # baloons. The hash includes the following key:
188
+ # [+:vertical+] ({Length}) the vertical padding of the baloons
189
+ # [+:horizontal+] ({Length}) the horizontal padding of the baloons
51
190
  opt_accessor :baloon_padding, :type => :hash, :default => {}, :keys => [:vertical, :horizontal], :item_type => :length
191
+
192
+ # Returns or sets the radius of the circle used to round off the corners
193
+ # of the baloons.
52
194
  opt_accessor :baloon_round, :type => :length, :default => 6
195
+
196
+ # Returns or sets the background color of the baloons. If this property
197
+ # has been set, the background color of all the baloons is the setting
198
+ # value. If +baloon_background_colors+ property has been set, the setting
199
+ # of +baloon_background_colors+ property is applied.
53
200
  opt_accessor :baloon_background_color, :type => :color
201
+
202
+ # Returns or sets the background colors of the baloons of the each slices.
54
203
  opt_accessor :baloon_background_colors, :type => :array, :item_type => :color
204
+
205
+ # Returns or sets the border color of the baloons. If this property has
206
+ # been set, the border color of all the baloons is the setting value. If
207
+ # +baloon_border_colors+ property has been set, the setting of
208
+ # +baloon_border_colors+ property is applied.
55
209
  opt_accessor :baloon_border_color, :type => :color
210
+
211
+ # Returns or sets the border colors of the baloons of the each slices.
56
212
  opt_accessor :baloon_border_colors, :type => :array, :item_type => :color
213
+
214
+ # Returns or sets the border width of the baloons.
57
215
  opt_accessor :baloon_border_width, :type => :length, :default => 2
216
+
217
+ # Returns or sets the CSS class of the baloons.
58
218
  opt_accessor :baloon_css_class, :type => :string
219
+
220
+ # Returns or sets the duration of the animations.
59
221
  opt_accessor :animation_duration, :type => :float, :default => 0.5
60
222
 
61
223
  def back_translate_value
@@ -78,20 +240,20 @@ module DYI #:nodoc:
78
240
 
79
241
  private
80
242
 
81
- def default_center_point #:nodoc:
243
+ def default_center_point
82
244
  margin = [width - chart_radius_x * 2, height - chart_radius_y * 2].min.quo(2)
83
245
  Coordinate.new(margin + chart_radius_x, margin + chart_radius_y)
84
246
  end
85
247
 
86
- def default_chart_radius_x #:nodoc:
248
+ def default_chart_radius_x
87
249
  [width, height].min * 0.4
88
250
  end
89
251
 
90
- def default_chart_radius_y #:nodoc:
252
+ def default_chart_radius_y
91
253
  represent_3d? ? chart_radius_x.quo(2) : chart_radius_x
92
254
  end
93
255
 
94
- def default_legend_point #:nodoc:
256
+ def default_legend_point
95
257
  if width - chart_radius_x * 2 < height - chart_radius_y * 2
96
258
  Coordinate.new(width * 0.1, chart_radius_y * 2 + (width - chart_radius_x * 2) * 0.8)
97
259
  else
@@ -99,11 +261,11 @@ module DYI #:nodoc:
99
261
  end
100
262
  end
101
263
 
102
- def default_legend_format #:nodoc:
264
+ def default_legend_format
103
265
  "{?name}\t{?percent}"
104
266
  end
105
267
 
106
- def create_vector_image #:nodoc:
268
+ def create_vector_image
107
269
  super
108
270
  if represent_3d?
109
271
  brush = Drawing::ColumnBrush.new(back_translate_value.merge(chart_stroke_color ? {:stroke_width => chart_stroke_width, :stroke => chart_stroke_color} : {}))
@@ -168,7 +330,7 @@ module DYI #:nodoc:
168
330
  end
169
331
  end
170
332
 
171
- def draw_chart(brush, record, accumulation, total_value, index) #:nodoc:
333
+ def draw_chart(brush, record, accumulation, total_value, index)
172
334
  canvas = Shape::ShapeGroup.draw_on(@chart_canvas)
173
335
  attrs = {}
174
336
  if data.has_field?(:css_class) && (css_class = record.css_class)
@@ -231,7 +393,7 @@ module DYI #:nodoc:
231
393
  text = Drawing::Pen.black_pen(:font => baloon_font, :opacity => 0.0).draw_text(
232
394
  @data_label_canvas,
233
395
  center_point + baloon_point,
234
- format_string(data_label_format, record, total_value),
396
+ format_string(baloon_format, record, total_value),
235
397
  baloon_options)
236
398
  text.add_painting_animation(:to => {:opacity => 1},
237
399
  :duration => animation_duration,
@@ -321,6 +483,7 @@ module DYI #:nodoc:
321
483
  end
322
484
  end
323
485
 
486
+ # @since 1.0.0
324
487
  def format_string(format, record, total_value)
325
488
  format = format.gsub(/\A\{!(\w)\}/, '')
326
489
  format.gsub(/\{\?((?![0-9])\w+)(:[^}]*)?\}/){|m|