dyi 0.0.2 → 1.0.0
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.
- data/CHANGES +13 -0
- data/examples/animation.rb +28 -0
- data/examples/class_diagram.rb +1 -1
- data/examples/css.rb +34 -0
- data/examples/line_and_bar.rb +1 -2
- data/examples/line_chart.rb +5 -6
- data/examples/logo.rb +1 -1
- data/examples/pie_chart.rb +11 -4
- data/examples/simple_shapes.rb +1 -1
- data/lib/dyi.rb +8 -2
- data/lib/dyi/animation.rb +259 -0
- data/lib/dyi/canvas.rb +202 -0
- data/lib/dyi/chart.rb +2 -0
- data/lib/dyi/chart/array_reader.rb +112 -63
- data/lib/dyi/chart/axis_util.rb +298 -0
- data/lib/dyi/chart/base.rb +188 -466
- data/lib/dyi/chart/csv_reader.rb +0 -4
- data/lib/dyi/chart/legend.rb +82 -0
- data/lib/dyi/chart/line_chart.rb +31 -23
- data/lib/dyi/chart/pie_chart.rb +237 -30
- data/lib/dyi/color.rb +1 -1
- data/lib/dyi/drawing.rb +8 -1
- data/lib/dyi/drawing/clipping.rb +14 -1
- data/lib/dyi/drawing/pen.rb +12 -2
- data/lib/dyi/element.rb +167 -0
- data/lib/dyi/event.rb +148 -0
- data/lib/dyi/formatter/base.rb +43 -3
- data/lib/dyi/formatter/eps_formatter.rb +2 -2
- data/lib/dyi/formatter/svg_formatter.rb +430 -74
- data/lib/dyi/painting.rb +6 -1
- data/lib/dyi/script.rb +29 -0
- data/lib/dyi/script/ecmascript.rb +273 -0
- data/lib/dyi/script/simple_script.rb +94 -0
- data/lib/dyi/shape.rb +5 -1331
- data/lib/dyi/shape/base.rb +612 -0
- data/lib/dyi/shape/path.rb +902 -0
- data/lib/dyi/stylesheet.rb +86 -0
- data/lib/ironruby.rb +11 -11
- metadata +17 -4
- data/lib/dyi/drawing/canvas.rb +0 -100
data/lib/dyi/chart/csv_reader.rb
CHANGED
@@ -0,0 +1,82 @@
|
|
1
|
+
# -*- encoding: UTF-8 -*-
|
2
|
+
|
3
|
+
# Copyright (c) 2009-2011 Sound-F Co., Ltd. All rights reserved.
|
4
|
+
#
|
5
|
+
# Author:: Mamoru Yuo
|
6
|
+
#
|
7
|
+
# This file is part of DYI.
|
8
|
+
#
|
9
|
+
# DYI is free software: you can redistribute it and/or modify it
|
10
|
+
# under the terms of the GNU General Public License as published by
|
11
|
+
# the Free Software Foundation, either version 3 of the License, or
|
12
|
+
# (at your option) any later version.
|
13
|
+
#
|
14
|
+
# DYI is distributed in the hope that it will be useful,
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17
|
+
# GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License
|
20
|
+
# along with DYI. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
|
22
|
+
module DYI #:nodoc:
|
23
|
+
module Chart #:nodoc:
|
24
|
+
|
25
|
+
module Legend
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def draw_legend(names, shapes=nil, records=nil, colors=nil) #:nodoc:
|
30
|
+
legend_canvas.translate(legend_point.x, legend_point.y)
|
31
|
+
if show_legend?
|
32
|
+
pen = Drawing::Pen.black_pen(:font => legend_font)
|
33
|
+
brush = Drawing::Brush.new
|
34
|
+
names.each_with_index do |name, index|
|
35
|
+
y = legend_font_size * (1.2 * (index + 1))
|
36
|
+
group = Shape::ShapeGroup.draw_on(legend_canvas)
|
37
|
+
case shapes && shapes[index]
|
38
|
+
when Shape::Base
|
39
|
+
shapes[index].draw_on(group)
|
40
|
+
when NilClass
|
41
|
+
brush.color = colors && colors[index] || chart_color(index)
|
42
|
+
brush.draw_rectangle(
|
43
|
+
group,
|
44
|
+
Coordinate.new(legend_font_size * 0.2, y - legend_font_size * 0.8),
|
45
|
+
legend_font_size * 0.8,
|
46
|
+
legend_font_size * 0.8)
|
47
|
+
end
|
48
|
+
pen.draw_text(
|
49
|
+
group,
|
50
|
+
Coordinate.new(legend_font_size * 0.2 + legend_font_size, y),
|
51
|
+
name)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def legend_font_size #:nodoc:
|
57
|
+
legend_font ? legend_font.draw_size : Font::DEFAULT_SIZE
|
58
|
+
end
|
59
|
+
|
60
|
+
def default_legend_point #:nodoc:
|
61
|
+
Coordinate.new(0,0)
|
62
|
+
end
|
63
|
+
|
64
|
+
def default_legend_format #:nodoc:
|
65
|
+
"{name}"
|
66
|
+
end
|
67
|
+
|
68
|
+
class << self
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def included(klass) #:nodoc:
|
73
|
+
klass.__send__(:opt_accessor, :show_legend, :type => :boolean, :default => true)
|
74
|
+
klass.__send__(:opt_accessor, :legend_font, :type => :font)
|
75
|
+
klass.__send__(:opt_accessor, :legend_format, :type => :string, :default_method => :default_legend_format)
|
76
|
+
klass.__send__(:opt_accessor, :legend_point, :type => :point, :default_method => :default_legend_point)
|
77
|
+
klass.__send__(:opt_accessor, :legend_css_class, :type => :string)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/dyi/chart/line_chart.rb
CHANGED
@@ -50,7 +50,7 @@ module DYI #:nodoc:
|
|
50
50
|
opt_accessor :max_x_label_count, {:type => :integer, :default_proc => proc{|c| c.chart_width.div(Length.new(96))}}
|
51
51
|
opt_accessor :show_x_labels, {:type => :boolean, :default => true}
|
52
52
|
opt_accessor :legend_texts, {:type => :array, :item_type => :string}
|
53
|
-
opt_accessor :data_columns, {:type => :array, :item_type => :integer}
|
53
|
+
# opt_accessor :data_columns, {:type => :array, :item_type => :integer}
|
54
54
|
opt_accessor :use_effect, {:type => :boolean, :default => true}
|
55
55
|
opt_accessor :bar_seriese_interval, {:type => :float, :default => 0.3}
|
56
56
|
opt_accessor :color_columns, {:type => :array, :item_type => :integer}
|
@@ -130,7 +130,7 @@ module DYI #:nodoc:
|
|
130
130
|
|
131
131
|
def bar_chart_brush(color, bar_width=nil)
|
132
132
|
if represent_3d?
|
133
|
-
bar_width ||= chart_width * bar_width_ratio / data.
|
133
|
+
bar_width ||= chart_width * bar_width_ratio / data.records_size
|
134
134
|
Drawing::CylinderBrush.new(:color => color, :ry => bar_width * (back_translate_value[:dy] * bar_width_ratio).quo(back_translate_value[:dx] * 2))
|
135
135
|
else
|
136
136
|
Drawing::Brush.new(:color => color)
|
@@ -153,9 +153,9 @@ module DYI #:nodoc:
|
|
153
153
|
main_series_data = []
|
154
154
|
sub_series_data = []
|
155
155
|
@bar_series = []
|
156
|
-
|
157
|
-
main_series_data.push(*data.
|
158
|
-
sub_series_data.push(*data.
|
156
|
+
data.values_size.times do |i|
|
157
|
+
main_series_data.push(*data.series(i)) unless use_y_second_axis?(i)
|
158
|
+
sub_series_data.push(*data.series(i)) if use_y_second_axis?(i)
|
159
159
|
@bar_series.push(i) if chart_type(i) == :bar
|
160
160
|
end
|
161
161
|
settings =
|
@@ -172,15 +172,15 @@ module DYI #:nodoc:
|
|
172
172
|
second_axis_settings[:min],
|
173
173
|
second_axis_settings[:max]) if use_y_second_axis?
|
174
174
|
|
175
|
-
|
176
|
-
draw_chart(
|
175
|
+
data.values_size.times do |i|
|
176
|
+
draw_chart(i, chart_type(i), chart_color(i), use_y_second_axis?(i) ? sub_settings : settings) if chart_type(i) == :stackedbar
|
177
177
|
end
|
178
|
-
(
|
179
|
-
draw_chart(
|
178
|
+
(data.values_size - 1).downto(0) do |i|
|
179
|
+
draw_chart(i, chart_type(i), chart_color(i), use_y_second_axis?(i) ? sub_settings : settings) if chart_type(i) != :stackedbar
|
180
180
|
end
|
181
181
|
|
182
182
|
draw_axis(settings, sub_settings)
|
183
|
-
texts = legend_texts || data_columns.map{|i| data.column_title(i)}
|
183
|
+
texts = legend_texts # || data_columns.map{|i| data.column_title(i)}
|
184
184
|
draw_legend(texts, legend_shapes)
|
185
185
|
end
|
186
186
|
|
@@ -314,28 +314,28 @@ module DYI #:nodoc:
|
|
314
314
|
end
|
315
315
|
|
316
316
|
def needs_x_scale?(i)
|
317
|
-
return true if data.
|
318
|
-
i % ((data.
|
317
|
+
return true if data.records_size < max_x_label_count
|
318
|
+
i % ((data.records_size - 1) / [max_x_label_count - 1, 1].max) == 0
|
319
319
|
end
|
320
320
|
|
321
321
|
def draw_x_axis(main_pen, sub_pen, text_pen, text_margin) #:nodoc:
|
322
322
|
main_pen.draw_line(represent_3d? ? @axis_back_canvas : @axis_front_canvas, [margin_left, height - margin_bottom], [width - margin_right, height - margin_bottom])
|
323
323
|
|
324
|
-
data.
|
324
|
+
data.records_size.times do |i|
|
325
325
|
next unless needs_x_scale?(i)
|
326
|
-
text_x = order_position_on_chart(margin_left, chart_width, data.
|
327
|
-
scale_x = x_axis_type == :range ? order_position_on_chart(margin_left, chart_width, data.
|
326
|
+
text_x = order_position_on_chart(margin_left, chart_width, data.records_size, i, x_axis_type)
|
327
|
+
scale_x = x_axis_type == :range ? order_position_on_chart(margin_left, chart_width, data.records_size + 1, i) : text_x
|
328
328
|
text_pen.draw_text(
|
329
329
|
@axis_front_canvas,
|
330
330
|
[text_x, height - margin_bottom + text_margin],
|
331
|
-
format_x_label(data.
|
331
|
+
format_x_label(data.name_values[i]),
|
332
332
|
:text_anchor => 'middle', :alignment_baseline => 'top') if show_x_labels?
|
333
333
|
|
334
334
|
sub_pen.draw_line_on_direction(
|
335
335
|
@axis_front_canvas,
|
336
336
|
[scale_x, height - margin_bottom],
|
337
337
|
0,
|
338
|
-
-(axis_font ? axis_font.draw_size : Font::DEFAULT_SIZE) * 0.5) if i > 0 && i < data.
|
338
|
+
-(axis_font ? axis_font.draw_size : Font::DEFAULT_SIZE) * 0.5) if i > 0 && i < data.records_size - (x_axis_type == :range ? 0 : 1)
|
339
339
|
end
|
340
340
|
end
|
341
341
|
|
@@ -349,7 +349,7 @@ module DYI #:nodoc:
|
|
349
349
|
end
|
350
350
|
|
351
351
|
def draw_line(id, color, settings) #:nodoc:
|
352
|
-
values = data.
|
352
|
+
values = data.series(id)
|
353
353
|
return if values.compact.size == 0
|
354
354
|
first_index = values.each_with_index {|value, i| break i if value}
|
355
355
|
pen_options = {:color => color, :width => line_width}
|
@@ -369,7 +369,7 @@ module DYI #:nodoc:
|
|
369
369
|
end
|
370
370
|
|
371
371
|
def draw_area(id, color, settings) #:nodoc:
|
372
|
-
values = data.
|
372
|
+
values = data.series(id)
|
373
373
|
return if values.compact.size == 0
|
374
374
|
first_index = values.each_with_index {|value, i| break i if value}
|
375
375
|
brush = area_chart_brush(color)
|
@@ -390,7 +390,7 @@ module DYI #:nodoc:
|
|
390
390
|
|
391
391
|
def draw_bar(id, color, settings) #:nodoc:
|
392
392
|
bar_group = Shape::ShapeGroup.new(@chart_options).draw_on(@chart_front_canvas)
|
393
|
-
values = data.
|
393
|
+
values = data.series(id)
|
394
394
|
return if values.compact.size == 0
|
395
395
|
bar_width = chart_width * bar_width_ratio / values.size / (@bar_series.size + (@bar_series.size - 1) * bar_seriese_interval)
|
396
396
|
|
@@ -400,7 +400,7 @@ module DYI #:nodoc:
|
|
400
400
|
next if value.nil?
|
401
401
|
x = order_position_on_chart(margin_left, chart_width, values.size, i, x_axis_type, bar_width_ratio) + bar_width * (1 + bar_seriese_interval) * @bar_series.index(id)
|
402
402
|
y = value_position_on_chart(margin_top, settings, value, true)
|
403
|
-
brush = bar_chart_brush(data[i
|
403
|
+
brush = bar_chart_brush(data.has_field?(:color) ? data.records[i].color : color, bar_width) if data.has_field?(:color)
|
404
404
|
brush.draw_rectangle(bar_group, [x, y], bar_width, height - margin_bottom - y)
|
405
405
|
end
|
406
406
|
bar_group.translate(back_translate_value[:dx] / 2, back_translate_value[:dy] / 2) if represent_3d?
|
@@ -409,7 +409,7 @@ module DYI #:nodoc:
|
|
409
409
|
def draw_stackedbar(id, color, settings) #:nodoc:
|
410
410
|
bar_group = Shape::ShapeGroup.new(@chart_options).draw_on(@chart_front_canvas)
|
411
411
|
|
412
|
-
values = data.
|
412
|
+
values = data.series(id)
|
413
413
|
return if values.compact.size == 0
|
414
414
|
bar_width = chart_width * bar_width_ratio / values.size
|
415
415
|
|
@@ -429,9 +429,17 @@ module DYI #:nodoc:
|
|
429
429
|
bar_group.translate(back_translate_value[:dx] / 2, back_translate_value[:dy] / 2) if represent_3d?
|
430
430
|
end
|
431
431
|
|
432
|
+
# @since 1.0.0
|
433
|
+
def chart_color(index) #:nodoc:
|
434
|
+
if chart_colors
|
435
|
+
color = chart_colors[index]
|
436
|
+
end
|
437
|
+
color || DEFAULT_CHART_COLOR[index % DEFAULT_CHART_COLOR.size]
|
438
|
+
end
|
439
|
+
|
432
440
|
def legend_shapes #:nodoc:
|
433
441
|
result = []
|
434
|
-
|
442
|
+
(0...data.values_size).each_with_index do |id, index|
|
435
443
|
result <<
|
436
444
|
case chart_type(index)
|
437
445
|
when :line, nil
|
data/lib/dyi/chart/pie_chart.rb
CHANGED
@@ -24,6 +24,8 @@ module DYI #:nodoc:
|
|
24
24
|
|
25
25
|
class PieChart < Base
|
26
26
|
include Legend
|
27
|
+
include DYI::Script::EcmaScript::DomLevel2
|
28
|
+
|
27
29
|
attr_reader :chart_canvas, :data_label_canvas, :legend_canvas
|
28
30
|
|
29
31
|
opt_accessor :center_point, {:type => :point, :default_method => :default_center_point}
|
@@ -35,88 +37,153 @@ module DYI #:nodoc:
|
|
35
37
|
opt_accessor :chart_stroke_color, {:type => :color}
|
36
38
|
opt_accessor :chart_stroke_width, {:type => :float, :default => 1}
|
37
39
|
opt_accessor :moved_elements, {:type => :array, :item_type => :float}
|
40
|
+
opt_accessor :pie_css_class, :type => :string
|
38
41
|
opt_accessor :show_data_label, {:type => :boolean, :default => true}
|
42
|
+
opt_accessor :data_label_css_class, :type => :string
|
39
43
|
opt_accessor :data_label_position, {:type => :float, :default => 0.8}
|
40
44
|
opt_accessor :data_label_font, {:type => :font}
|
41
|
-
opt_accessor :data_label_format, {:type => :string, :default => "{name}
|
45
|
+
opt_accessor :data_label_format, {:type => :string, :default => "{?name}"}
|
42
46
|
opt_accessor :hide_data_label_ratio, {:type => :float, :default => 0.00}
|
47
|
+
opt_accessor :show_baloon, :type => :boolean, :default => true
|
48
|
+
opt_accessor :baloon_font, :type => :font
|
49
|
+
opt_accessor :baloon_position, {:type => :float, :default => 0.8}
|
50
|
+
opt_accessor :baloon_format, :type => :string, :default => "{?name}\n{?value}"
|
51
|
+
opt_accessor :baloon_padding, :type => :hash, :default => {}, :keys => [:vertical, :horizontal], :item_type => :length
|
52
|
+
opt_accessor :baloon_round, :type => :length, :default => 6
|
53
|
+
opt_accessor :baloon_background_color, :type => :color
|
54
|
+
opt_accessor :baloon_background_colors, :type => :array, :item_type => :color
|
55
|
+
opt_accessor :baloon_border_color, :type => :color
|
56
|
+
opt_accessor :baloon_border_colors, :type => :array, :item_type => :color
|
57
|
+
opt_accessor :baloon_border_width, :type => :length, :default => 2
|
58
|
+
opt_accessor :baloon_css_class, :type => :string
|
59
|
+
opt_accessor :animation_duration, :type => :float, :default => 0.5
|
43
60
|
|
44
61
|
def back_translate_value
|
45
62
|
{:dy => (Length.new_or_nil(_3d_settings[:dy]) || chart_radius_y.quo(2))}
|
46
63
|
end
|
47
64
|
|
65
|
+
# @since 1.0.0
|
66
|
+
def get_baloon_background_color(index)
|
67
|
+
(baloon_background_colors && baloon_background_colors[index]) ||
|
68
|
+
baloon_background_color ||
|
69
|
+
chart_color(index).merge('white', 0.7)
|
70
|
+
end
|
71
|
+
|
72
|
+
# @since 1.0.0
|
73
|
+
def get_baloon_border_color(index)
|
74
|
+
(baloon_border_colors && baloon_border_colors[index]) ||
|
75
|
+
baloon_border_color ||
|
76
|
+
chart_color(index).merge('black', 0.3)
|
77
|
+
end
|
78
|
+
|
48
79
|
private
|
49
80
|
|
50
81
|
def default_center_point #:nodoc:
|
51
|
-
|
82
|
+
margin = [width - chart_radius_x * 2, height - chart_radius_y * 2].min.quo(2)
|
83
|
+
Coordinate.new(margin + chart_radius_x, margin + chart_radius_y)
|
52
84
|
end
|
53
85
|
|
54
86
|
def default_chart_radius_x #:nodoc:
|
55
|
-
[
|
87
|
+
[width, height].min * 0.4
|
56
88
|
end
|
57
89
|
|
58
90
|
def default_chart_radius_y #:nodoc:
|
59
91
|
represent_3d? ? chart_radius_x.quo(2) : chart_radius_x
|
60
92
|
end
|
61
93
|
|
62
|
-
def default_csv_format #:nodoc:
|
63
|
-
[:$name, 0, :$color]
|
64
|
-
end
|
65
|
-
|
66
94
|
def default_legend_point #:nodoc:
|
67
|
-
|
95
|
+
if width - chart_radius_x * 2 < height - chart_radius_y * 2
|
96
|
+
Coordinate.new(width * 0.1, chart_radius_y * 2 + (width - chart_radius_x * 2) * 0.8)
|
97
|
+
else
|
98
|
+
Coordinate.new(chart_radius_x * 2 + (height - chart_radius_y * 2) * 0.8, height * 0.1 + Length.new(10))
|
99
|
+
end
|
68
100
|
end
|
69
101
|
|
70
102
|
def default_legend_format #:nodoc:
|
71
|
-
"{name}\t{percent}"
|
103
|
+
"{?name}\t{?percent}"
|
72
104
|
end
|
73
105
|
|
74
106
|
def create_vector_image #:nodoc:
|
107
|
+
super
|
75
108
|
if represent_3d?
|
76
109
|
brush = Drawing::ColumnBrush.new(back_translate_value.merge(chart_stroke_color ? {:stroke_width => chart_stroke_width, :stroke => chart_stroke_color} : {}))
|
77
110
|
else
|
78
111
|
brush = Drawing::Brush.new(chart_stroke_color ? {:stroke_width => chart_stroke_width, :stroke => chart_stroke_color, :stroke_miterlimit => chart_stroke_width} : {})
|
79
112
|
end
|
113
|
+
attrs = if pie_css_class && !pie_css_class.empty?
|
114
|
+
{:css_class => pie_css_class}
|
115
|
+
else
|
116
|
+
{}
|
117
|
+
end
|
80
118
|
@chart_canvas = Shape::ShapeGroup.draw_on(@canvas)
|
81
|
-
|
82
|
-
|
83
|
-
|
119
|
+
attrs = if data_label_css_class && !data_label_css_class.empty?
|
120
|
+
{:css_class => data_label_css_class}
|
121
|
+
else
|
122
|
+
{}
|
123
|
+
end
|
124
|
+
@data_label_canvas = Shape::ShapeGroup.draw_on(@canvas, attrs)
|
125
|
+
attrs = if legend_css_class && !legend_css_class.empty?
|
126
|
+
{:css_class => legend_css_class}
|
127
|
+
else
|
128
|
+
{}
|
129
|
+
end
|
130
|
+
@legend_canvas = Shape::ShapeGroup.draw_on(@canvas, attrs)
|
131
|
+
@legends = []
|
132
|
+
@sectors = []
|
133
|
+
draw_legend(data.records, nil)
|
134
|
+
total_value = data.inject(0.0) {|sum, record| sum + (record.value || 0)}
|
84
135
|
accumulation = 0.0
|
85
136
|
accumulations = []
|
86
137
|
stop_index = -1
|
87
|
-
data.
|
138
|
+
data.each_with_index do |record, i|
|
88
139
|
accumulations.push(accumulation)
|
140
|
+
value = record.value
|
89
141
|
if value && total_value > (accumulation + value) * 2 && value != 0.0
|
90
|
-
# brush.color = data[:$color] && data[:$color][i] || chart_color(i)
|
91
142
|
brush.color = chart_color(i)
|
92
|
-
|
93
|
-
draw_chart(brush, name, value, accumulation, total_value, i)
|
143
|
+
draw_chart(brush, record, accumulation, total_value, i)
|
94
144
|
stop_index = i
|
95
145
|
end
|
96
146
|
accumulation += value if value
|
97
147
|
end
|
98
|
-
(data.
|
99
|
-
value = data.
|
148
|
+
(data.records_size - 1).downto(stop_index + 1) do |i|
|
149
|
+
value = (record = data.records[i]).value
|
100
150
|
if value && value != 0.0
|
101
|
-
# brush.color = data[:$color] && data[:$color][i] || chart_color(i)
|
102
151
|
brush.color = chart_color(i)
|
103
|
-
|
104
|
-
|
152
|
+
draw_chart(brush, record, accumulations[i], total_value, i)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
@sectors.each_with_index do |sector, i|
|
156
|
+
@legends.each_with_index do |legend, j|
|
157
|
+
if i != j
|
158
|
+
sector.parent.add_painting_animation(:to => {:opacity => 0.35},
|
159
|
+
:duration => animation_duration,
|
160
|
+
:fill => 'freeze',
|
161
|
+
:begin_event => Event.mouseover(legend),
|
162
|
+
:end_event => Event.mouseout(legend))
|
163
|
+
sector.parent.add_painting_animation(:to => {:opacity => 1},
|
164
|
+
:fill => 'freeze',
|
165
|
+
:begin_event => Event.mouseout(legend))
|
166
|
+
end
|
105
167
|
end
|
106
168
|
end
|
107
|
-
# draw_legend(data.row_titles, nil, nil, data[:$color])
|
108
|
-
draw_legend(data.row_titles, nil, nil, nil)
|
109
169
|
end
|
110
170
|
|
111
|
-
def draw_chart(brush,
|
171
|
+
def draw_chart(brush, record, accumulation, total_value, index) #:nodoc:
|
112
172
|
canvas = Shape::ShapeGroup.draw_on(@chart_canvas)
|
113
|
-
|
173
|
+
attrs = {}
|
174
|
+
if data.has_field?(:css_class) && (css_class = record.css_class)
|
175
|
+
attrs[:css_class] = record.css_class
|
176
|
+
end
|
177
|
+
value = record.value
|
178
|
+
pie_sector = brush.draw_sector(
|
114
179
|
canvas,
|
115
180
|
center_point,
|
116
181
|
chart_radius_x,
|
117
182
|
chart_radius_y,
|
118
183
|
accumulation * 360.0 / total_value - 90,
|
119
|
-
value * 360.0 / total_value
|
184
|
+
value * 360.0 / total_value,
|
185
|
+
attrs)
|
186
|
+
@sectors[index] = pie_sector
|
120
187
|
|
121
188
|
if moved_elements && (dr = moved_elements[index])
|
122
189
|
canvas.translate(
|
@@ -126,15 +193,155 @@ module DYI #:nodoc:
|
|
126
193
|
|
127
194
|
ratio = value.to_f.quo(total_value)
|
128
195
|
if show_data_label?
|
129
|
-
|
196
|
+
label_point = Coordinate.new(
|
130
197
|
chart_radius_x * (data_label_position + (dr || 0)) * Math.cos(((accumulation * 2.0 + value) / total_value - 0.5) * Math::PI),
|
131
198
|
chart_radius_y * (data_label_position + (dr || 0)) * Math.sin(((accumulation * 2.0 + value) / total_value - 0.5) * Math::PI))
|
132
199
|
Drawing::Pen.black_pen(:font => data_label_font).draw_text(
|
133
200
|
@data_label_canvas,
|
134
|
-
center_point +
|
135
|
-
data_label_format
|
136
|
-
:text_anchor => 'middle')
|
201
|
+
center_point + label_point,
|
202
|
+
format_string(data_label_format, record, total_value),
|
203
|
+
attrs.merge(:text_anchor => 'middle'))
|
137
204
|
end if hide_data_label_ratio < ratio
|
205
|
+
draw_baloon(brush, record, accumulation, total_value, index, ratio, pie_sector)
|
206
|
+
end
|
207
|
+
|
208
|
+
# @since 1.0.0
|
209
|
+
def draw_baloon(brush, record, accumulation, total_value, index, ratio, pie_sector)
|
210
|
+
value = record.value
|
211
|
+
if show_baloon?
|
212
|
+
dr = moved_elements && moved_elements[index]
|
213
|
+
baloon_point = Coordinate.new(
|
214
|
+
chart_radius_x * (baloon_position + (dr || 0)) *
|
215
|
+
Math.cos(((accumulation * 2.0 + value) / total_value - 0.5) * Math::PI),
|
216
|
+
chart_radius_y * (baloon_position + (dr || 0)) *
|
217
|
+
Math.sin(((accumulation * 2.0 + value) / total_value - 0.5) * Math::PI))
|
218
|
+
baloon_options = {:text_anchor => 'middle', :show_border => true}
|
219
|
+
if data.has_field?(:css_class) && (css_class = record.css_class)
|
220
|
+
baloon_options[:css_class] = record.css_class
|
221
|
+
end
|
222
|
+
baloon_options[:vertical_padding] = baloon_padding[:vertical_padding] || 2
|
223
|
+
baloon_options[:horizontal_padding] = baloon_padding[:horizontal_padding] || 5
|
224
|
+
baloon_options[:background_color] = get_baloon_background_color(index)
|
225
|
+
baloon_options[:border_color] = get_baloon_border_color(index)
|
226
|
+
baloon_options[:border_width] = baloon_border_width
|
227
|
+
baloon_options[:border_rx] = baloon_round
|
228
|
+
if baloon_css_class && baloon_css_class.empty?
|
229
|
+
@data_label_canvas.add_css_class(baloon_css_class)
|
230
|
+
end
|
231
|
+
text = Drawing::Pen.black_pen(:font => baloon_font, :opacity => 0.0).draw_text(
|
232
|
+
@data_label_canvas,
|
233
|
+
center_point + baloon_point,
|
234
|
+
format_string(data_label_format, record, total_value),
|
235
|
+
baloon_options)
|
236
|
+
text.add_painting_animation(:to => {:opacity => 1},
|
237
|
+
:duration => animation_duration,
|
238
|
+
:fill => 'freeze',
|
239
|
+
:begin_event => Event.mouseover(pie_sector))
|
240
|
+
text.add_painting_animation(:to => {:opacity => 0},
|
241
|
+
:duration => animation_duration,
|
242
|
+
:fill => 'freeze',
|
243
|
+
:begin_event => Event.mouseout(pie_sector))
|
244
|
+
if @legends
|
245
|
+
text.add_painting_animation(:to => {:opacity => 1},
|
246
|
+
:duration => animation_duration,
|
247
|
+
:fill => 'freeze',
|
248
|
+
:begin_event => Event.mouseover(@legends[index]))
|
249
|
+
text.add_painting_animation(:to => {:opacity => 0},
|
250
|
+
:duration => animation_duration,
|
251
|
+
:fill => 'freeze',
|
252
|
+
:begin_event => Event.mouseout(@legends[index]))
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
# @since 1.0.0
|
258
|
+
def draw_legend(records, shapes=nil)
|
259
|
+
legend_canvas.translate(legend_point.x, legend_point.y)
|
260
|
+
if show_legend?
|
261
|
+
pen = Drawing::Pen.black_pen(:font => legend_font)
|
262
|
+
brush = Drawing::Brush.new
|
263
|
+
toatal = records.inject(0.0){|sum, record| sum + record.value}
|
264
|
+
formats = legend_format.split("\t")
|
265
|
+
legend_labels = []
|
266
|
+
records.each_with_index do |record, i|
|
267
|
+
legend_labels << formats.map do |format|
|
268
|
+
format_string(format, record, toatal)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
require 'pp'
|
272
|
+
max_lengths = legend_labels.inject(Array.new(formats.size, 0)) do |maxs, labels|
|
273
|
+
(0...formats.size).each do |i|
|
274
|
+
maxs[i] = labels[i].bytesize if maxs[i] < labels[i].bytesize
|
275
|
+
end
|
276
|
+
maxs
|
277
|
+
end
|
278
|
+
canvas.add_initialize_script(form_legend_labels(legend_canvas))
|
279
|
+
records.each_with_index do |record, i|
|
280
|
+
y = legend_font_size * (1.2 * (i + 1))
|
281
|
+
attrs = {}
|
282
|
+
if data.has_field?(:css_class) && (css_class = record.css_class)
|
283
|
+
attrs[:css_class] = record.css_class
|
284
|
+
end
|
285
|
+
group = Shape::ShapeGroup.draw_on(legend_canvas, attrs)
|
286
|
+
@legends << group
|
287
|
+
case shapes && shapes[i]
|
288
|
+
when Shape::Base
|
289
|
+
shapes[i].draw_on(group)
|
290
|
+
when NilClass
|
291
|
+
brush.color = chart_color(i)
|
292
|
+
brush.draw_rectangle(
|
293
|
+
group,
|
294
|
+
Coordinate.new(legend_font_size * 0.2, y - legend_font_size * 0.8),
|
295
|
+
legend_font_size * 0.8,
|
296
|
+
legend_font_size * 0.8)
|
297
|
+
end
|
298
|
+
x = legend_font_size * 0.2 + legend_font_size
|
299
|
+
legend_labels[i].each_with_index do |label, j|
|
300
|
+
formats[j] =~ /\A\{!(\w)\}/
|
301
|
+
case $1
|
302
|
+
when 's'
|
303
|
+
attrs = {:text_anchor => 'start'}
|
304
|
+
pen.draw_text(group, Coordinate.new(x, y), label, attrs)
|
305
|
+
x += legend_font_size * max_lengths[j] * 0.5
|
306
|
+
when 'm'
|
307
|
+
attrs = {:text_anchor => 'middle'}
|
308
|
+
x += legend_font_size * max_lengths[j] * 0.25
|
309
|
+
pen.draw_text(group, Coordinate.new(x, y), label, attrs)
|
310
|
+
x += legend_font_size * max_lengths[j] * 0.25
|
311
|
+
when 'e'
|
312
|
+
attrs = {:text_anchor => 'end'}
|
313
|
+
x += legend_font_size * max_lengths[j] * 0.5
|
314
|
+
pen.draw_text(group, Coordinate.new(x, y), label, attrs)
|
315
|
+
else
|
316
|
+
attrs = {}
|
317
|
+
pen.draw_text(group, Coordinate.new(x, y), label, attrs)
|
318
|
+
x += legend_font_size * max_lengths[j] * 0.5
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def format_string(format, record, total_value)
|
326
|
+
format = format.gsub(/\A\{!(\w)\}/, '')
|
327
|
+
format.gsub(/\{\?((?![0-9])\w+)(:[^}]*)?\}/){|m|
|
328
|
+
fmt = $2 ? $2[1..-1] : nil
|
329
|
+
if $1 == 'percent'
|
330
|
+
value = record.value.quo(total_value)
|
331
|
+
fmt ||= '0.0%'
|
332
|
+
else
|
333
|
+
value = record.__send__($1)
|
334
|
+
end
|
335
|
+
if fmt
|
336
|
+
case value
|
337
|
+
when Numeric then value.strfnum(fmt)
|
338
|
+
when DateTime, Time then value.strftime(fmt)
|
339
|
+
else fmt % value
|
340
|
+
end
|
341
|
+
else
|
342
|
+
value
|
343
|
+
end
|
344
|
+
}
|
138
345
|
end
|
139
346
|
end
|
140
347
|
end
|