prep 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
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