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