prep 0.2.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.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +30 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +24 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/bin/prep-helper +48 -0
- data/bin/prep-test +51 -0
- data/examples/generate_group_sample.rb +4 -0
- data/examples/generate_sample.rb +4 -0
- data/examples/generate_sample2.rb +19 -0
- data/examples/generate_sample3.rb +20 -0
- data/examples/generate_sample4.rb +31 -0
- data/examples/generate_sample5.rb +74 -0
- data/examples/generate_sample6.rb +40 -0
- data/examples/generate_sample_dataset.rb +9 -0
- data/examples/group_sample.yml +121 -0
- data/examples/sample.yml +90 -0
- data/examples/sample2.yml +164 -0
- data/examples/sample3.yml +206 -0
- data/examples/sample5.yml +116 -0
- data/examples/sample6.yml +127 -0
- data/lib/core/color.rb +47 -0
- data/lib/core/drawable.rb +163 -0
- data/lib/core/group.rb +193 -0
- data/lib/core/label.rb +125 -0
- data/lib/core/line.rb +95 -0
- data/lib/core/loop.rb +584 -0
- data/lib/core/page.rb +87 -0
- data/lib/core/page_ext.rb +14 -0
- data/lib/core/point.rb +26 -0
- data/lib/core/prep.rb +351 -0
- data/lib/core/rectangle.rb +137 -0
- data/lib/core/region.rb +54 -0
- data/lib/mm2pixcel.rb +5 -0
- data/lib/prep.rb +175 -0
- data/prep.gemspec +108 -0
- data/spec/component_spec.rb +5 -0
- data/spec/prep_spec.rb +7 -0
- data/spec/spec_helper.rb +12 -0
- metadata +197 -0
data/lib/core/group.rb
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
# Group クラスのソースファイル
|
2
|
+
# Author:: maki-tetsu
|
3
|
+
# Date:: 2011/03/11
|
4
|
+
# Copyright:: Copyright (c) 2011 maki-tetsu
|
5
|
+
|
6
|
+
require File.join(File.dirname(__FILE__), "drawable")
|
7
|
+
require File.join(File.dirname(__FILE__), "label")
|
8
|
+
require File.join(File.dirname(__FILE__), "line")
|
9
|
+
require File.join(File.dirname(__FILE__), "rectangle")
|
10
|
+
require File.join(File.dirname(__FILE__), "loop")
|
11
|
+
|
12
|
+
module PREP # nodoc
|
13
|
+
module Core # nodoc
|
14
|
+
# 呼び出し可能グループの定義
|
15
|
+
class Group < Drawable
|
16
|
+
@@allow_all = false
|
17
|
+
|
18
|
+
attr_reader :drawables
|
19
|
+
|
20
|
+
def self.allow_all
|
21
|
+
return @@allow_all
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.allow_all=(v)
|
25
|
+
@@allow_all = !!v
|
26
|
+
end
|
27
|
+
|
28
|
+
# 初期化
|
29
|
+
def initialize(identifier = "main", values = { })
|
30
|
+
super(identifier)
|
31
|
+
|
32
|
+
@drawables = { }
|
33
|
+
values.keys.each do |key|
|
34
|
+
unless key == "type" # type は除外
|
35
|
+
add_drawable(key, values[key])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# 指定された識別子を持つ定義情報を返却
|
41
|
+
def [](drawable_key)
|
42
|
+
if @drawables.has_key?(drawable_key.to_sym)
|
43
|
+
return @drawables[drawable_key.to_sym]
|
44
|
+
else
|
45
|
+
raise "Unknown drawable key \"#{drawable_key}\"."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# 指定された識別子を持つ定義情報の有無を返却
|
50
|
+
def has_identifier?(key)
|
51
|
+
return @drawables.has_key?(key)
|
52
|
+
end
|
53
|
+
|
54
|
+
# 構成要素の追加
|
55
|
+
#
|
56
|
+
# 引数に渡されるのは単一の構成要素
|
57
|
+
def add_drawable(identifier, config, global = false)
|
58
|
+
# 事前にキー重複をチェック
|
59
|
+
if @drawables.has_key?(identifier.to_sym)
|
60
|
+
raise "Duplicated ID \"#{identifier}\"."
|
61
|
+
end
|
62
|
+
# キー重複が無ければ設定情報を読み込む
|
63
|
+
# 構成要素種別の指定を確認
|
64
|
+
case config["type"]
|
65
|
+
when "label"
|
66
|
+
klass = Label
|
67
|
+
unless @@allow_all
|
68
|
+
@drawables.values.each do |drawable|
|
69
|
+
if Loop === drawable
|
70
|
+
raise "Group already has Loop!!"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
when "line"
|
75
|
+
klass = Line
|
76
|
+
unless @@allow_all
|
77
|
+
@drawables.values.each do |drawable|
|
78
|
+
if Loop === drawable
|
79
|
+
raise "Group already has Loop!!"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
when "rectangle"
|
84
|
+
klass = Rectangle
|
85
|
+
unless @@allow_all
|
86
|
+
@drawables.values.each do |drawable|
|
87
|
+
if Loop === drawable
|
88
|
+
raise "Group already has Loop!!"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
when "group"
|
93
|
+
# global でのみグループ定義を許可
|
94
|
+
unless global
|
95
|
+
raise "Group definition allowed at global level only for \"#{identifier}\"."
|
96
|
+
end
|
97
|
+
klass = Group
|
98
|
+
when "loop"
|
99
|
+
klass = Loop
|
100
|
+
unless @@allow_all
|
101
|
+
unless @drawables.size.zero?
|
102
|
+
raise "Group has only one loop!!"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
else
|
106
|
+
raise "Unknown type expression \"#{config["type"]}\"."
|
107
|
+
end
|
108
|
+
|
109
|
+
@drawables[identifier.to_sym] = klass.new(identifier, config)
|
110
|
+
end
|
111
|
+
|
112
|
+
# データセット雛形を生成
|
113
|
+
def generate_sample_dataset(prep)
|
114
|
+
dataset = { }
|
115
|
+
drawable_items.each do |drawable|
|
116
|
+
case drawable
|
117
|
+
when Loop, Group
|
118
|
+
dataset[drawable.identifier.to_sym] = drawable.generate_sample_dataset(prep)
|
119
|
+
when Label
|
120
|
+
dataset[drawable.identifier.to_sym] = drawable.label
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
return dataset
|
125
|
+
end
|
126
|
+
|
127
|
+
# グループを構成する各要素が全体で占有する領域サイズを返却
|
128
|
+
def calculate_region(prep, region, values, stop_on_drawable = nil)
|
129
|
+
if self === stop_on_drawable
|
130
|
+
raise ReRenderJump.new(region)
|
131
|
+
end
|
132
|
+
puts "Calculate region for #{self.class}: #{self.identifier} region: #{region}" if ENV["DEBUG"]
|
133
|
+
values ||= { }
|
134
|
+
|
135
|
+
# 各構成要素の描画領域を計算して最大の領域を計算、width, height のみを利用
|
136
|
+
group_region_size = drawable_items.inject({ }) do |size, drawable|
|
137
|
+
if values.has_key?(drawable.identifier.to_sym)
|
138
|
+
drawable_values = values[drawable.identifier.to_sym]
|
139
|
+
else
|
140
|
+
drawable_values = { }
|
141
|
+
end
|
142
|
+
|
143
|
+
width, height = drawable.calculate_region(prep, region, drawable_values, stop_on_drawable)
|
144
|
+
|
145
|
+
size[:width] ||= width
|
146
|
+
size[:height] ||= height
|
147
|
+
size[:width] = width if size[:width] < width
|
148
|
+
size[:height] = height if size[:height] < height
|
149
|
+
|
150
|
+
next size
|
151
|
+
end
|
152
|
+
|
153
|
+
group_region_size[:width] ||= 0
|
154
|
+
group_region_size[:height] ||= 0
|
155
|
+
|
156
|
+
ret_region = Region.new(0, 0,
|
157
|
+
region.width - group_region_size[:width],
|
158
|
+
region.height - group_region_size[:height])
|
159
|
+
return group_region_size[:width], group_region_size[:height]
|
160
|
+
end
|
161
|
+
|
162
|
+
def draw(prep, region, values, stop_on_drawable = nil)
|
163
|
+
if self === stop_on_drawable
|
164
|
+
raise ReRenderJump.new(region)
|
165
|
+
end
|
166
|
+
STDERR.puts("Draw on #{self.class} #{self.identifier}") if ENV['DEBUG']
|
167
|
+
values ||= { }
|
168
|
+
# 管理対象の各オブジェクトに対して描画を開始
|
169
|
+
drawable_items.each do |drawable|
|
170
|
+
if values.has_key?(drawable.identifier.to_sym)
|
171
|
+
drawable_values = values[drawable.identifier.to_sym]
|
172
|
+
else
|
173
|
+
drawable_values = { }
|
174
|
+
end
|
175
|
+
|
176
|
+
drawable.draw(prep, region, drawable_values, stop_on_drawable)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# 描画対象となる構成要素の一覧を返却
|
181
|
+
def drawable_items
|
182
|
+
return @drawables.values.map { |d|
|
183
|
+
case d
|
184
|
+
when Group
|
185
|
+
next nil
|
186
|
+
else
|
187
|
+
next d
|
188
|
+
end
|
189
|
+
}.compact.sort
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
data/lib/core/label.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# Label クラスのソースファイル
|
2
|
+
# Author:: maki-tetsu
|
3
|
+
# Date:: 2011/03/11
|
4
|
+
# Copyright:: Copyright (c) 2011 maki-tetsu
|
5
|
+
|
6
|
+
require File.join(File.dirname(__FILE__), "drawable")
|
7
|
+
require File.join(File.dirname(__FILE__), "color")
|
8
|
+
require File.join(File.dirname(__FILE__), "region")
|
9
|
+
require File.join(File.dirname(__FILE__), "..", "mm2pixcel")
|
10
|
+
|
11
|
+
require "nkf"
|
12
|
+
|
13
|
+
module PREP # nodoc
|
14
|
+
module Core # nodoc
|
15
|
+
# 文字列描画構成要素クラス
|
16
|
+
class Label < Drawable
|
17
|
+
ALIGNS = {
|
18
|
+
:left => HPDFDoc::HPDF_TALIGN_LEFT,
|
19
|
+
:right => HPDFDoc::HPDF_TALIGN_RIGHT,
|
20
|
+
:center => HPDFDoc::HPDF_TALIGN_CENTER,
|
21
|
+
:justify => HPDFDoc::HPDF_TALIGN_JUSTIFY,
|
22
|
+
}
|
23
|
+
|
24
|
+
@@default_values = {
|
25
|
+
:align => "left",
|
26
|
+
:font => "MS-Mincyo",
|
27
|
+
:size => 12,
|
28
|
+
:color => { :red => 0, :green => 0, :blue => 0 },
|
29
|
+
:layer => 3,
|
30
|
+
:expand => false,
|
31
|
+
}
|
32
|
+
|
33
|
+
attr_reader :region, :label, :align, :font, :color, :size, :expand
|
34
|
+
|
35
|
+
def initialize(identifier, values = { })
|
36
|
+
values = @@default_values.merge(key_string_to_symbol(values))
|
37
|
+
super(identifier, values[:layer])
|
38
|
+
|
39
|
+
@region = Region.new(values[:region][:x].mm2pixcel,
|
40
|
+
values[:region][:y].mm2pixcel,
|
41
|
+
values[:region][:width].mm2pixcel,
|
42
|
+
values[:region][:height].mm2pixcel)
|
43
|
+
if values[:label].nil?
|
44
|
+
raise "Label string cannot be blank for \"#{identifier}\""
|
45
|
+
else
|
46
|
+
@label = values[:label]
|
47
|
+
end
|
48
|
+
|
49
|
+
if ALIGNS.keys.include?(values[:align].to_sym)
|
50
|
+
@align = ALIGNS[values[:align].to_sym]
|
51
|
+
else
|
52
|
+
raise "Unknown label alignment option \"#{values[:align]}\"."
|
53
|
+
end
|
54
|
+
if values[:font].nil? || values[:font] == ""
|
55
|
+
raise "Lable font must be specified."
|
56
|
+
else
|
57
|
+
@font = values[:font]
|
58
|
+
end
|
59
|
+
@color = Color.new(values[:color][:red],
|
60
|
+
values[:color][:green],
|
61
|
+
values[:color][:blue])
|
62
|
+
if values[:size].nil? || values[:size] == ""
|
63
|
+
raise "Label size must be specified."
|
64
|
+
else
|
65
|
+
@size = values[:size]
|
66
|
+
end
|
67
|
+
@expand = values[:expand]
|
68
|
+
end
|
69
|
+
|
70
|
+
def expand_region(setting)
|
71
|
+
@expand_region = @region.dup
|
72
|
+
@expand_region.width = setting[:width] if setting[:width]
|
73
|
+
@expand_region.height = setting[:height] if setting[:height]
|
74
|
+
end
|
75
|
+
|
76
|
+
# 幅と高さを返却
|
77
|
+
def calculate_region(prep, region, value, stop_on_drawable = nil)
|
78
|
+
if self === stop_on_drawable
|
79
|
+
raise ReRenderJump.new(region)
|
80
|
+
end
|
81
|
+
puts "Calculate region for #{self.class}: #{self.identifier} region: #{region}" if ENV["DEBUG"]
|
82
|
+
ret_region = Region.new(0, 0,
|
83
|
+
region.width - (@region.x + @region.width),
|
84
|
+
region.height - (@region.y + @region.height))
|
85
|
+
return @region.x + @region.width, @region.y + @region.height
|
86
|
+
end
|
87
|
+
|
88
|
+
# 指定された領域を元に再計算して描画を実施
|
89
|
+
def draw(prep, region, value, stop_on_drawable = nil)
|
90
|
+
if self === stop_on_drawable
|
91
|
+
raise ReRenderJump.new(region)
|
92
|
+
end
|
93
|
+
STDERR.puts("Draw on #{self.class} #{self.identifier}") if ENV['DEBUG']
|
94
|
+
# 領域判定
|
95
|
+
calculate_region(prep, region, value)
|
96
|
+
# 文字列指定があるかを確認
|
97
|
+
if value.nil? || value.to_s == ""
|
98
|
+
string = self.label.dup
|
99
|
+
else
|
100
|
+
string = value.to_s
|
101
|
+
end
|
102
|
+
# 文字列指定に変数がある場合は判定
|
103
|
+
string.gsub!("[[[current_page_number]]]", prep.current_page_number.to_s)
|
104
|
+
string.gsub!("[[[total_page_count]]]", prep.total_pages.to_s)
|
105
|
+
# 文字列の描画
|
106
|
+
font = prep.pdf.get_font(self.font, "90ms-RKSJ-H")
|
107
|
+
prep.current_page.begin_text
|
108
|
+
prep.current_page.set_rgb_fill(@color.red.to_f, @color.green.to_f, @color.blue.to_f)
|
109
|
+
region_backup = @region.dup
|
110
|
+
if @expand_region
|
111
|
+
@region = @expand_region.dup
|
112
|
+
@expand_region = nil
|
113
|
+
end
|
114
|
+
left, top = calculate_pos(prep.current_page, region, @region.x, @region.y)
|
115
|
+
right, bottom = left + @region.width, top - @region.height
|
116
|
+
prep.current_page.set_font_and_size(font, @size)
|
117
|
+
prep.current_page.text_rect(left, top, right, bottom,
|
118
|
+
NKF.nkf("--oc=cp932 -W8", string), @align)
|
119
|
+
prep.current_page.end_text
|
120
|
+
@region = region_backup
|
121
|
+
prep.current_page.drawed = true
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
data/lib/core/line.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Line クラスのソースファイル
|
2
|
+
# Author:: maki-tetsu
|
3
|
+
# Date:: 2011/03/11
|
4
|
+
# Copyright:: Copyright (c) 2011 maki-tetsu
|
5
|
+
|
6
|
+
require File.join(File.dirname(__FILE__), "drawable")
|
7
|
+
require File.join(File.dirname(__FILE__), "color")
|
8
|
+
require File.join(File.dirname(__FILE__), "point")
|
9
|
+
require File.join(File.dirname(__FILE__), "..", "mm2pixcel")
|
10
|
+
|
11
|
+
module PREP # nodoc
|
12
|
+
module Core # nodoc
|
13
|
+
# 直線描画構成要素クラス
|
14
|
+
class Line < Drawable
|
15
|
+
STYLES = {
|
16
|
+
:solid => "solid",
|
17
|
+
}
|
18
|
+
|
19
|
+
@@default_values = {
|
20
|
+
:color => { :red => 0, :green => 0, :blue => 0 },
|
21
|
+
:width => 1,
|
22
|
+
:style => STYLES[:solid],
|
23
|
+
:layer => 2,
|
24
|
+
}
|
25
|
+
|
26
|
+
attr_reader :start_point, :end_point, :color, :width, :style
|
27
|
+
|
28
|
+
def initialize(identifier, values = { })
|
29
|
+
values = @@default_values.merge(key_string_to_symbol(values))
|
30
|
+
super(identifier, values[:layer])
|
31
|
+
|
32
|
+
@start_point = Point.new(values[:start][:x].mm2pixcel, values[:start][:y].mm2pixcel)
|
33
|
+
@end_point = Point.new(values[:end][:x].mm2pixcel, values[:end][:y].mm2pixcel)
|
34
|
+
@color = Color.new(values[:color][:red], values[:color][:green], values[:color][:blue])
|
35
|
+
self.width = values[:width]
|
36
|
+
self.style = values[:style]
|
37
|
+
end
|
38
|
+
|
39
|
+
def width=(w)
|
40
|
+
if w > 0
|
41
|
+
@width = w
|
42
|
+
else
|
43
|
+
raise "Line width must be grater than zero."
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def style=(s)
|
48
|
+
if STYLES.values.include?(s)
|
49
|
+
@style = s
|
50
|
+
else
|
51
|
+
raise "Line style \"#{s}\" is unknown."
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def calculate_region(prep, region, value, stop_on_drawable = nil)
|
56
|
+
if self === stop_on_drawable
|
57
|
+
raise ReRenderJump.new(region)
|
58
|
+
end
|
59
|
+
puts "Calculate region for #{self.class}: #{self.identifier} region: #{region}" if ENV["DEBUG"]
|
60
|
+
width = [@start_point.x, @end_point.x].max
|
61
|
+
height = [@start_point.y, @end_point.y].max
|
62
|
+
|
63
|
+
ret_region = Region.new(0, 0,
|
64
|
+
region.width - width,
|
65
|
+
region.height - height)
|
66
|
+
return width, height
|
67
|
+
end
|
68
|
+
|
69
|
+
# 直線の描画
|
70
|
+
def draw(prep, region, values, stop_on_drawable = nil)
|
71
|
+
if self === stop_on_drawable
|
72
|
+
raise ReRenderJump.new(region)
|
73
|
+
end
|
74
|
+
STDERR.puts("Draw on #{self.class} #{self.identifier}") if ENV['DEBUG']
|
75
|
+
# 領域判定
|
76
|
+
calculate_region(prep, region, values)
|
77
|
+
# 幅指定
|
78
|
+
prep.current_page.set_line_width(@width)
|
79
|
+
# 色指定
|
80
|
+
prep.current_page.set_rgb_stroke(@color.red.to_f,
|
81
|
+
@color.green.to_f,
|
82
|
+
@color.blue.to_f)
|
83
|
+
# 開始位置へ移動
|
84
|
+
start_x, start_y = calculate_pos(prep.current_page, region, @start_point.x.to_f, @start_point.y.to_f)
|
85
|
+
end_x, end_y = calculate_pos(prep.current_page, region, @end_point.x.to_f, @end_point.y.to_f)
|
86
|
+
prep.current_page.move_to(start_x, start_y)
|
87
|
+
# 終了位置へ向けて直線描画
|
88
|
+
prep.current_page.line_to(end_x, end_y)
|
89
|
+
# 実描画
|
90
|
+
prep.current_page.stroke
|
91
|
+
prep.current_page.drawed = true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/core/loop.rb
ADDED
@@ -0,0 +1,584 @@
|
|
1
|
+
# Loop クラスのソースファイル
|
2
|
+
# Author:: maki-tetsu
|
3
|
+
# Date:: 2011/03/11
|
4
|
+
# Copyright:: Copyright (c) 2011 maki-tetsu
|
5
|
+
|
6
|
+
require File.join(File.dirname(__FILE__), "drawable")
|
7
|
+
require File.join(File.dirname(__FILE__), "..", "mm2pixcel")
|
8
|
+
|
9
|
+
module PREP # nodoc
|
10
|
+
module Core # nodoc
|
11
|
+
# ループ読み込みクラスの定義
|
12
|
+
class Loop < Drawable
|
13
|
+
DIRECTIONS = {
|
14
|
+
:horizontal => 'horizontal',
|
15
|
+
:vertical => 'vertical'
|
16
|
+
}
|
17
|
+
|
18
|
+
@@default_values = {
|
19
|
+
:direction => DIRECTIONS[:vertical],
|
20
|
+
:gap => 0,
|
21
|
+
:page_break => false,
|
22
|
+
:layer => 4,
|
23
|
+
}
|
24
|
+
|
25
|
+
attr_reader :direction, :gap, :header_group, :iterator_group, :footer_group, :point, :page_break, :width, :height
|
26
|
+
|
27
|
+
def initialize(identifier, values = { })
|
28
|
+
values = @@default_values.merge(key_string_to_symbol(values))
|
29
|
+
|
30
|
+
super(identifier, values[:layer])
|
31
|
+
|
32
|
+
self.direction = values[:direction]
|
33
|
+
@header_group = values[:header]
|
34
|
+
@iterator_group = values[:iterator]
|
35
|
+
@gap = values[:gap].mm2pixcel
|
36
|
+
@footer_group = values[:footer]
|
37
|
+
@point = Point.new(values[:x].mm2pixcel, values[:y].mm2pixcel)
|
38
|
+
@page_break = values[:page_break]
|
39
|
+
end
|
40
|
+
|
41
|
+
def direction=(d)
|
42
|
+
if DIRECTIONS.values.include?(d)
|
43
|
+
@direction = d
|
44
|
+
else
|
45
|
+
raise "Unknown direction \"#{d}\"."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# データセット雛形を生成
|
50
|
+
def generate_sample_dataset(prep)
|
51
|
+
dataset = { }
|
52
|
+
|
53
|
+
unless @header_group.nil?
|
54
|
+
header = prep.group(@header_group)
|
55
|
+
dataset[:header] = header.generate_sample_dataset(prep)
|
56
|
+
end
|
57
|
+
iterator = prep.group(@iterator_group)
|
58
|
+
dataset[:values] = [iterator.generate_sample_dataset(prep)]
|
59
|
+
unless @footer_group.nil?
|
60
|
+
footer = prep.group(@footer_group)
|
61
|
+
dataset[:footer] = footer.generate_sample_dataset(prep)
|
62
|
+
end
|
63
|
+
|
64
|
+
return dataset
|
65
|
+
end
|
66
|
+
|
67
|
+
# データに依存してサイズが変化する可能性がある
|
68
|
+
def calculate_region(prep, region, values, stop_on_drawable = nil)
|
69
|
+
if self === stop_on_drawable
|
70
|
+
puts "STOPPING on #{stop_on_drawable.identifier}" if ENV["DEBUG"]
|
71
|
+
gets if ENV["DEBUG"]
|
72
|
+
raise ReRenderJump.new(region)
|
73
|
+
end
|
74
|
+
puts "Calculate region for #{self.class}: #{self.identifier} region: #{region}" if ENV["DEBUG"]
|
75
|
+
# リージョン補正
|
76
|
+
current_region = fit_region(region)
|
77
|
+
# 描画計算の初期位置を保持
|
78
|
+
@initial_calculate_region = current_region.dup
|
79
|
+
|
80
|
+
# ヘッダの領域サイズを計算
|
81
|
+
current_region = calculate_header_region(prep, current_region, values, stop_on_drawable)
|
82
|
+
puts "Header:\t#{current_region}" if ENV["DEBUG"]
|
83
|
+
|
84
|
+
# 繰り返し部分の領域サイズを計算
|
85
|
+
current_region = calculate_iterator_region(prep, current_region, values, stop_on_drawable)
|
86
|
+
puts "Iterator:\t#{current_region}" if ENV["DEBUG"]
|
87
|
+
|
88
|
+
# フッタの領域サイズを計算
|
89
|
+
current_region = calculate_footer_region(prep, current_region, values, stop_on_drawable)
|
90
|
+
puts "Footer:\t#{current_region}" if ENV["DEBUG"]
|
91
|
+
|
92
|
+
begin
|
93
|
+
# 最終的にリージョン補正位置から必要な領域を計算
|
94
|
+
# 元のリージョン範囲から最終的に残っているリージョン範囲を減算すればよい
|
95
|
+
ret_region = Region.new(0, 0,
|
96
|
+
region.width - current_region.width,
|
97
|
+
region.height - current_region.height)
|
98
|
+
|
99
|
+
# 進行方向じゃない方向に対しての差分は別途取得
|
100
|
+
if @direction == DIRECTIONS[:horizontal]
|
101
|
+
ret_region.height = @height
|
102
|
+
else # if @direction == DIRECTIONS[:vertical]
|
103
|
+
ret_region.width = @width
|
104
|
+
end
|
105
|
+
|
106
|
+
return ret_region.width, ret_region.height
|
107
|
+
rescue RegionWidthOverflowError, RegionHeightOverflowError => e
|
108
|
+
# これは負の数を返却してやれば上位では単純な加算しか起きない
|
109
|
+
w, h = region.width - current_region.width, region.height - current_region.height
|
110
|
+
if @direction == DIRECTIONS[:horizontal]
|
111
|
+
h = @height
|
112
|
+
else # if @direction == DIRECTIONS[:vertical]
|
113
|
+
w = @width
|
114
|
+
end
|
115
|
+
|
116
|
+
puts "Inner page break!! width: #{w}, height: #{h}" if ENV["DEBUG"]
|
117
|
+
gets if ENV["DEBUG"]
|
118
|
+
|
119
|
+
return w, h
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# リージョン補正
|
124
|
+
#
|
125
|
+
# 相対位置情報を元にリージョンを補正して返却
|
126
|
+
def fit_region(region)
|
127
|
+
current_region = region.dup
|
128
|
+
current_region.x += point.x
|
129
|
+
current_region.y += point.y
|
130
|
+
current_region.width -= point.x
|
131
|
+
current_region.height -= point.y
|
132
|
+
|
133
|
+
return current_region
|
134
|
+
end
|
135
|
+
|
136
|
+
# 実際の描画を実施
|
137
|
+
def draw(prep, region, values, stop_on_drawable = nil)
|
138
|
+
if self === stop_on_drawable
|
139
|
+
puts "STOPPING on #{stop_on_drawable.identifier}" if ENV["DEBUG"]
|
140
|
+
gets if ENV["DEBUG"]
|
141
|
+
raise ReRenderJump.new(region)
|
142
|
+
end
|
143
|
+
STDERR.puts("Draw on #{self.class} #{self.identifier}") if ENV['DEBUG']
|
144
|
+
# リージョン補正
|
145
|
+
current_region = fit_region(region)
|
146
|
+
# 描画計算の初期位置を保持
|
147
|
+
@initial_draw_region = current_region.dup
|
148
|
+
|
149
|
+
# 領域に関する情報を取得
|
150
|
+
expand_setting = { }
|
151
|
+
if !@page_break
|
152
|
+
# 描画に先立ち領域拡張設定を実施
|
153
|
+
# ループ要素の描画領域を算出(事前計算)
|
154
|
+
rewind_current_page(prep) do
|
155
|
+
calculate_region(prep, region.dup, values)
|
156
|
+
end
|
157
|
+
if @direction == DIRECTIONS[:horizontal]
|
158
|
+
expand_setting[:height] = @height
|
159
|
+
else # if @direction == DIRECTIONS[:vertical]
|
160
|
+
expand_setting[:width] = @width
|
161
|
+
end
|
162
|
+
end
|
163
|
+
# ヘッダおよびフッタの子に関してワンタイム設定を実施
|
164
|
+
unless @header_group.nil?
|
165
|
+
header = prep.group(@header_group)
|
166
|
+
header.drawable_items.each do |drawable|
|
167
|
+
if Label === drawable || Rectangle === drawable
|
168
|
+
if drawable.expand
|
169
|
+
drawable.expand_region(expand_setting)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
unless @footer_group.nil?
|
175
|
+
footer = prep.group(@footer_group)
|
176
|
+
footer.drawable_items.each do |drawable|
|
177
|
+
if Label === drawable || Rectangle === drawable
|
178
|
+
if drawable.expand
|
179
|
+
drawable.expand_region(expand_setting)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
# ヘッダブロック描画
|
185
|
+
current_region = draw_header(prep, current_region, values, stop_on_drawable)
|
186
|
+
|
187
|
+
# 繰り返しブロック描画
|
188
|
+
current_region = draw_iterator(prep, current_region, values, stop_on_drawable)
|
189
|
+
|
190
|
+
# フッタブロック描画
|
191
|
+
current_region = draw_footer(prep, current_region, values, stop_on_drawable)
|
192
|
+
end
|
193
|
+
|
194
|
+
private
|
195
|
+
|
196
|
+
# ヘッダ構成要素を描画するためのメソッド
|
197
|
+
#
|
198
|
+
# 描画後に新しい region を返却
|
199
|
+
def draw_header(prep, region, values, stop_on_drawable = nil)
|
200
|
+
unless @header_group.nil?
|
201
|
+
header = prep.group(@header_group)
|
202
|
+
w, h = rewind_current_page(prep) do
|
203
|
+
header.calculate_region(prep, region, values[:header], stop_on_drawable)
|
204
|
+
end
|
205
|
+
rewind_current_page(prep, self.direction) do
|
206
|
+
header.draw(prep, region, values[:header], stop_on_drawable)
|
207
|
+
end
|
208
|
+
if @direction == DIRECTIONS[:horizontal] # 右方向
|
209
|
+
if (has_iterator_group?(prep) && !values[:values].nil? && !values[:values].size.zero?) || has_footer_group?(prep)
|
210
|
+
w += @gap
|
211
|
+
end
|
212
|
+
region.x += w
|
213
|
+
region.width -= w
|
214
|
+
else # if @direction == DIRECTIONS[:vertical] # 下方向
|
215
|
+
if (has_iterator_group?(prep) && !values[:values].nil? && !values[:values].size.zero?) || has_footer_group?(prep)
|
216
|
+
h += @gap
|
217
|
+
end
|
218
|
+
region.y += h
|
219
|
+
region.height -= h
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
return region
|
224
|
+
end
|
225
|
+
|
226
|
+
# ヘッダ構成要素の描画領域を計算するためのメソッド
|
227
|
+
def calculate_header_region(prep, region, values, stop_on_drawable = nil)
|
228
|
+
unless @header_group.nil?
|
229
|
+
header = prep.group(@header_group)
|
230
|
+
w, h = header.calculate_region(prep, region, values[:header], stop_on_drawable)
|
231
|
+
if @direction == DIRECTIONS[:horizontal] # 右方向
|
232
|
+
if (has_iterator_group?(prep) && !values[:values].nil? && !values[:values].size.zero?) || has_footer_group?(prep)
|
233
|
+
w += @gap
|
234
|
+
end
|
235
|
+
region.x += w
|
236
|
+
region.width -= w
|
237
|
+
@height ||= h
|
238
|
+
@height = h if @height < h
|
239
|
+
else # if @direction == DIRECTIONS[:vertical] # 下方向
|
240
|
+
if (has_iterator_group?(prep) && !values[:values].nil? && !values[:values].size.zero?) || has_footer_group?(prep)
|
241
|
+
h += @gap
|
242
|
+
end
|
243
|
+
region.y += h
|
244
|
+
region.height -= h
|
245
|
+
@width ||= w
|
246
|
+
@width = w if @width < w
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
return region
|
251
|
+
end
|
252
|
+
|
253
|
+
# 繰返し構成要素を描画するためのメソッド
|
254
|
+
def draw_iterator(prep, region, values, stop_on_drawable = nil)
|
255
|
+
iterator = prep.group(@iterator_group)
|
256
|
+
values[:values].each_with_index do |iterator_values, index|
|
257
|
+
begin
|
258
|
+
w, h = rewind_current_page(prep) do
|
259
|
+
iterator.calculate_region(prep, region, iterator_values, stop_on_drawable)
|
260
|
+
end
|
261
|
+
rewind_current_page(prep, self.direction) do
|
262
|
+
iterator.draw(prep, region, iterator_values, stop_on_drawable)
|
263
|
+
end
|
264
|
+
# 描画したので、方向に応じてリージョン補正
|
265
|
+
if @direction == DIRECTIONS[:horizontal] # 右方向
|
266
|
+
if has_footer_group?(prep) || (values[:values].size > index + 1)
|
267
|
+
w += @gap
|
268
|
+
end
|
269
|
+
region.x += w
|
270
|
+
region.width -= w
|
271
|
+
@height ||= h
|
272
|
+
@height = h if @height < h
|
273
|
+
else # if @direction == DIRECTIONS[:vertical] # 下方向
|
274
|
+
if has_footer_group?(prep) || (values[:values].size > index + 1)
|
275
|
+
h += @gap
|
276
|
+
end
|
277
|
+
region.y += h
|
278
|
+
region.height -= h
|
279
|
+
@width ||= w
|
280
|
+
@width = w if @width < w
|
281
|
+
end
|
282
|
+
rescue RegionWidthOverflowError
|
283
|
+
# 幅オーバーフロー時のページ切り替え対応
|
284
|
+
if @page_break && @direction == DIRECTIONS[:horizontal]
|
285
|
+
next_page_exist = prep.exists_move_to_page?(1, 0)
|
286
|
+
|
287
|
+
page = prep.move_page_to(1, 0)
|
288
|
+
if next_page_exist
|
289
|
+
region = @initial_draw_region.dup
|
290
|
+
else
|
291
|
+
region = prep.page_content_region
|
292
|
+
# 過去を再描画
|
293
|
+
begin
|
294
|
+
prep.group(:content).draw(prep, region, prep.values[:content], self)
|
295
|
+
rescue ReRenderJump => e
|
296
|
+
region = fit_region(e.region)
|
297
|
+
else
|
298
|
+
raise "ReRedering Error!!"
|
299
|
+
end
|
300
|
+
end
|
301
|
+
region = draw_header(prep, region, values, stop_on_drawable)
|
302
|
+
# リトライ
|
303
|
+
retry
|
304
|
+
end
|
305
|
+
raise
|
306
|
+
rescue RegionHeightOverflowError
|
307
|
+
# 高さオーバーフロー時のページ切り替え対応
|
308
|
+
if @page_break && @direction == DIRECTIONS[:vertical]
|
309
|
+
next_page_exist = prep.exists_move_to_page?(0, 1)
|
310
|
+
|
311
|
+
page = prep.move_page_to(0, 1)
|
312
|
+
if next_page_exist
|
313
|
+
region = @initial_draw_region.dup
|
314
|
+
else
|
315
|
+
region = prep.page_content_region
|
316
|
+
# 過去を再描画
|
317
|
+
begin
|
318
|
+
prep.group(:content).draw(prep, region, prep.values[:content], self)
|
319
|
+
rescue ReRenderJump => e
|
320
|
+
region = fit_region(e.region)
|
321
|
+
else
|
322
|
+
raise "ReRendering Error!!"
|
323
|
+
end
|
324
|
+
end
|
325
|
+
# ヘッダを再描画
|
326
|
+
region = draw_header(prep, region, values, stop_on_drawable)
|
327
|
+
# リトライ
|
328
|
+
retry
|
329
|
+
end
|
330
|
+
raise
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
return region
|
335
|
+
end
|
336
|
+
|
337
|
+
# 繰返し構成要素の描画領域を計算するためのメソッド
|
338
|
+
def calculate_iterator_region(prep, region, values, stop_on_drawable = nil)
|
339
|
+
iterator = prep.group(@iterator_group)
|
340
|
+
values[:values].each_with_index do |iterator_values, index|
|
341
|
+
begin
|
342
|
+
w, h = iterator.calculate_region(prep, region, iterator_values, stop_on_drawable)
|
343
|
+
# 描画したので、方向に応じてリージョン補正
|
344
|
+
if @direction == DIRECTIONS[:horizontal] # 右方向
|
345
|
+
if has_footer_group?(prep) || (values[:values].size > index + 1)
|
346
|
+
w += @gap
|
347
|
+
end
|
348
|
+
region.x += w
|
349
|
+
region.width -= w
|
350
|
+
@height ||= h
|
351
|
+
@height = h if @height < h
|
352
|
+
else # if @direction == DIRECTIONS[:vertical] # 下方向
|
353
|
+
if has_footer_group?(prep) || (values[:values].size > index + 1)
|
354
|
+
h += @gap
|
355
|
+
end
|
356
|
+
region.y += h
|
357
|
+
region.height -= h
|
358
|
+
@width ||= w
|
359
|
+
@width = w if @width < w
|
360
|
+
end
|
361
|
+
rescue RegionWidthOverflowError
|
362
|
+
# 幅オーバーフロー時のページ切り替え対応
|
363
|
+
if @page_break && @direction == DIRECTIONS[:horizontal]
|
364
|
+
next_page_exist = prep.exists_move_to_page?(1, 0)
|
365
|
+
|
366
|
+
page = prep.move_page_to(1, 0)
|
367
|
+
if next_page_exist
|
368
|
+
region = @initial_calculate_region.dup
|
369
|
+
else
|
370
|
+
region = prep.page_content_region
|
371
|
+
# 過去を再計算
|
372
|
+
begin
|
373
|
+
prep.group(:content).calculate_region(prep, region, prep.values[:content], self)
|
374
|
+
rescue ReRenderJump => e
|
375
|
+
region = fit_region(e.region)
|
376
|
+
else
|
377
|
+
raise "ReRendering Error!!"
|
378
|
+
end
|
379
|
+
end
|
380
|
+
# ヘッダを再計算
|
381
|
+
region = calculate_header_region(prep, region, values, stop_on_drawable)
|
382
|
+
# リトライ
|
383
|
+
retry
|
384
|
+
end
|
385
|
+
raise
|
386
|
+
rescue RegionHeightOverflowError
|
387
|
+
# 高さオーバーフロー時のページ切り替え対応
|
388
|
+
if @page_break && @direction == DIRECTIONS[:vertical]
|
389
|
+
next_page_exist = prep.exists_move_to_page?(0, 1)
|
390
|
+
|
391
|
+
page = prep.move_page_to(0, 1)
|
392
|
+
if next_page_exist
|
393
|
+
region = @initial_calculate_region.dup
|
394
|
+
else
|
395
|
+
region = prep.page_content_region
|
396
|
+
# 過去を再計算
|
397
|
+
begin
|
398
|
+
prep.group(:content).calculate_region(prep, region, prep.values[:content], self)
|
399
|
+
rescue ReRenderJump => e
|
400
|
+
region = fit_region(e.region)
|
401
|
+
else
|
402
|
+
raise "ReRendering Error!!"
|
403
|
+
end
|
404
|
+
end
|
405
|
+
# ヘッダを再計算
|
406
|
+
region = calculate_header_region(prep, region, values, stop_on_drawable)
|
407
|
+
# リトライ
|
408
|
+
retry
|
409
|
+
end
|
410
|
+
raise
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
return region
|
415
|
+
end
|
416
|
+
|
417
|
+
# フッタ構成要素を描画するためのメソッド
|
418
|
+
def draw_footer(prep, region, values, stop_on_drawable = nil)
|
419
|
+
unless @footer_group.nil?
|
420
|
+
begin
|
421
|
+
footer = prep.group(@footer_group)
|
422
|
+
w, h = rewind_current_page(prep) do
|
423
|
+
footer.calculate_region(prep, region, values[:footer], stop_on_drawable)
|
424
|
+
end
|
425
|
+
rewind_current_page(prep, self.direction) do
|
426
|
+
footer.draw(prep, region, values[:footer], stop_on_drawable)
|
427
|
+
end
|
428
|
+
if @direction == DIRECTIONS[:horizontal] # 右方向
|
429
|
+
region.x += w
|
430
|
+
region.width -= w
|
431
|
+
@height ||= h
|
432
|
+
@height = h if @height < h
|
433
|
+
else # if @direction == DIRECTIONS[:vertical] # 下方向
|
434
|
+
region.y += h
|
435
|
+
region.height -= h
|
436
|
+
@width ||= w
|
437
|
+
@width = w if @width < w
|
438
|
+
end
|
439
|
+
rescue RegionWidthOverflowError
|
440
|
+
if @page_break && @direction == DIRECTIONS[:horizontal]
|
441
|
+
next_page_exist = prep.exists_move_to_page?(1, 0)
|
442
|
+
|
443
|
+
page = prep.move_page_to(1, 0)
|
444
|
+
if next_page_exist
|
445
|
+
region = @initial_draw_region.dup
|
446
|
+
else
|
447
|
+
region = prep.page_content_region
|
448
|
+
# 過去を再描画
|
449
|
+
begin
|
450
|
+
prep.group(:content).draw(prep, region, prep.values[:content], self)
|
451
|
+
rescue ReRenderJump => e
|
452
|
+
region = fit_region(e.region)
|
453
|
+
else
|
454
|
+
raise "ReRendering Error!!"
|
455
|
+
end
|
456
|
+
end
|
457
|
+
region = draw_header(prep, region, values, stop_on_drawable)
|
458
|
+
retry
|
459
|
+
end
|
460
|
+
raise
|
461
|
+
rescue RegionHeightOverflowError
|
462
|
+
if @page_break && @direction == DIRECTIONS[:vertical]
|
463
|
+
next_page_exist = prep.exists_move_to_page?(0, 1)
|
464
|
+
|
465
|
+
page = prep.move_page_to(0, 1)
|
466
|
+
if next_page_exist
|
467
|
+
region = @initial_draw_region.dup
|
468
|
+
else
|
469
|
+
region = prep.page_content_region
|
470
|
+
# 過去を再描画
|
471
|
+
begin
|
472
|
+
prep.group(:content).draw(prep, region, prep.values[:content], self)
|
473
|
+
rescue ReRenderJump => e
|
474
|
+
region = fit_region(e.region)
|
475
|
+
else
|
476
|
+
raise "ReRendering Error!!"
|
477
|
+
end
|
478
|
+
end
|
479
|
+
region = draw_header(prep, region, values, stop_on_drawable)
|
480
|
+
retry
|
481
|
+
end
|
482
|
+
raise
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
return region
|
487
|
+
end
|
488
|
+
|
489
|
+
# フッタ構成要素の描画領域を計算するためのメソッド
|
490
|
+
def calculate_footer_region(prep, region, values, stop_on_drawable = nil)
|
491
|
+
unless @footer_group.nil?
|
492
|
+
begin
|
493
|
+
footer = prep.group(@footer_group)
|
494
|
+
w, h = footer.calculate_region(prep, region, values[:footer], stop_on_drawable)
|
495
|
+
if @direction == DIRECTIONS[:horizontal] # 右方向
|
496
|
+
region.x += w
|
497
|
+
region.width -= w
|
498
|
+
@height ||= h
|
499
|
+
@height = h if @height < h
|
500
|
+
else # if @direction == DIRECTIONS[:vertical] # 下方向
|
501
|
+
region.y += h
|
502
|
+
region.height -= h
|
503
|
+
@width ||= w
|
504
|
+
@width = w if @width < w
|
505
|
+
end
|
506
|
+
rescue RegionWidthOverflowError
|
507
|
+
if @page_break && @direction == DIRECTIONS[:horizontal]
|
508
|
+
next_page_exist = prep.exists_move_to_page?(1, 0)
|
509
|
+
|
510
|
+
page = prep.move_page_to(1, 0)
|
511
|
+
if next_page_exist
|
512
|
+
region = @initial_calculate_region.dup
|
513
|
+
else
|
514
|
+
region = prep.page_content_region
|
515
|
+
# 過去を再計算
|
516
|
+
begin
|
517
|
+
prep.group(:content).calculate_region(prep, region, prep.values[:content], self)
|
518
|
+
rescue ReRenderJump => e
|
519
|
+
region = fit_region(e.region)
|
520
|
+
else
|
521
|
+
raise "ReRendering Error!!"
|
522
|
+
end
|
523
|
+
end
|
524
|
+
region = calculate_header_region(prep, region, values, stop_on_drawable)
|
525
|
+
retry
|
526
|
+
end
|
527
|
+
raise
|
528
|
+
rescue RegionHeightOverflowError
|
529
|
+
if @page_break && @direction == DIRECTIONS[:vertical]
|
530
|
+
next_page_exist = prep.exists_move_to_page?(0, 1)
|
531
|
+
|
532
|
+
page = prep.move_page_to(0, 1)
|
533
|
+
if next_page_exist
|
534
|
+
region = @initial_calculate_region.dup
|
535
|
+
else
|
536
|
+
region = prep.page_content_region
|
537
|
+
# 過去を再計算
|
538
|
+
begin
|
539
|
+
prep.group(:content).calculate_region(prep, region, prep.values[:content], self)
|
540
|
+
rescue ReRenderJump => e
|
541
|
+
region = fit_region(e.region)
|
542
|
+
else
|
543
|
+
raise "ReRendering Error!!"
|
544
|
+
end
|
545
|
+
end
|
546
|
+
region = calculate_header_region(prep, region, values, stop_on_drawable)
|
547
|
+
retry
|
548
|
+
end
|
549
|
+
raise
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
return region
|
554
|
+
end
|
555
|
+
|
556
|
+
# ヘッダグループの設定有無を確認
|
557
|
+
def has_header_group?(prep)
|
558
|
+
if @header_group.nil?
|
559
|
+
return false
|
560
|
+
else
|
561
|
+
return prep.has_group?(@header_group)
|
562
|
+
end
|
563
|
+
end
|
564
|
+
|
565
|
+
# 繰返しグループの設定有無を確認
|
566
|
+
def has_iterator_group?(prep)
|
567
|
+
if @iterator_group.nil?
|
568
|
+
return false
|
569
|
+
else
|
570
|
+
return prep.has_group?(@iterator_group)
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
574
|
+
# フッタグループの設定有無を確認
|
575
|
+
def has_footer_group?(prep)
|
576
|
+
if @footer_group.nil?
|
577
|
+
return false
|
578
|
+
else
|
579
|
+
return prep.has_group?(@footer_group)
|
580
|
+
end
|
581
|
+
end
|
582
|
+
end
|
583
|
+
end
|
584
|
+
end
|