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/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