thinreports 0.6.0.pre3 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. data/README.rdoc +37 -32
  2. data/doc/yardoc_templates/default/layout/html/footer.erb +1 -1
  3. data/lib/thinreports.rb +2 -1
  4. data/lib/thinreports/config.rb +21 -0
  5. data/lib/thinreports/core/errors.rb +14 -1
  6. data/lib/thinreports/core/format/builder.rb +6 -1
  7. data/lib/thinreports/core/page.rb +6 -6
  8. data/lib/thinreports/core/shape.rb +8 -9
  9. data/lib/thinreports/core/shape/base/internal.rb +6 -12
  10. data/lib/thinreports/core/shape/basic.rb +3 -0
  11. data/lib/thinreports/core/shape/basic/block_format.rb +12 -0
  12. data/lib/thinreports/core/shape/basic/block_interface.rb +25 -0
  13. data/lib/thinreports/core/shape/basic/block_internal.rb +33 -0
  14. data/lib/thinreports/core/shape/basic/interface.rb +37 -11
  15. data/lib/thinreports/core/shape/basic/internal.rb +3 -12
  16. data/lib/thinreports/core/shape/image_block.rb +15 -0
  17. data/lib/thinreports/core/shape/image_block/format.rb +13 -0
  18. data/lib/thinreports/core/shape/image_block/interface.rb +19 -0
  19. data/lib/thinreports/core/shape/image_block/internal.rb +16 -0
  20. data/lib/thinreports/core/shape/list/events.rb +19 -2
  21. data/lib/thinreports/core/shape/list/manager.rb +17 -4
  22. data/lib/thinreports/core/shape/list/page.rb +2 -2
  23. data/lib/thinreports/core/shape/list/page_state.rb +4 -0
  24. data/lib/thinreports/core/shape/list/section_internal.rb +4 -0
  25. data/lib/thinreports/core/shape/manager/format.rb +1 -1
  26. data/lib/thinreports/core/shape/manager/internal.rb +24 -11
  27. data/lib/thinreports/core/shape/manager/target.rb +2 -2
  28. data/lib/thinreports/core/shape/style.rb +15 -0
  29. data/lib/thinreports/core/shape/style/base.rb +149 -0
  30. data/lib/thinreports/core/shape/style/basic.rb +17 -0
  31. data/lib/thinreports/core/shape/style/graphic.rb +60 -0
  32. data/lib/thinreports/core/shape/style/text.rb +138 -0
  33. data/lib/thinreports/core/shape/text/internal.rb +4 -0
  34. data/lib/thinreports/core/shape/text_block.rb +16 -0
  35. data/lib/thinreports/core/shape/{tblock → text_block}/format.rb +3 -3
  36. data/lib/thinreports/core/shape/{tblock → text_block}/formatter.rb +7 -7
  37. data/lib/thinreports/core/shape/{tblock → text_block}/formatter/basic.rb +1 -1
  38. data/lib/thinreports/core/shape/{tblock → text_block}/formatter/datetime.rb +1 -1
  39. data/lib/thinreports/core/shape/{tblock → text_block}/formatter/number.rb +1 -1
  40. data/lib/thinreports/core/shape/{tblock → text_block}/formatter/padding.rb +10 -8
  41. data/lib/thinreports/core/shape/{tblock → text_block}/interface.rb +2 -21
  42. data/lib/thinreports/core/shape/{tblock → text_block}/internal.rb +16 -10
  43. data/lib/thinreports/core/utils.rb +0 -8
  44. data/lib/thinreports/generator.rb +2 -2
  45. data/lib/thinreports/generator/configuration.rb +30 -0
  46. data/lib/thinreports/generator/pdf.rb +13 -10
  47. data/lib/thinreports/generator/pdf/configuration.rb +28 -0
  48. data/lib/thinreports/generator/pdf/document.rb +16 -56
  49. data/lib/thinreports/generator/pdf/document/draw_shape.rb +35 -17
  50. data/lib/thinreports/generator/pdf/document/font.rb +25 -9
  51. data/lib/thinreports/generator/pdf/document/graphics.rb +1 -1
  52. data/lib/thinreports/generator/pdf/document/graphics/attributes.rb +18 -4
  53. data/lib/thinreports/generator/pdf/document/graphics/basic.rb +1 -1
  54. data/lib/thinreports/generator/pdf/document/graphics/image.rb +18 -1
  55. data/lib/thinreports/generator/pdf/document/graphics/text.rb +29 -6
  56. data/lib/thinreports/generator/pdf/document/page.rb +70 -0
  57. data/lib/thinreports/generator/pdf/document/parse_color.rb +1 -1
  58. data/lib/thinreports/generator/pdf/document/parse_svg.rb +1 -1
  59. data/lib/thinreports/generator/pdf/drawer.rb +1 -1
  60. data/lib/thinreports/generator/pdf/drawer/base.rb +5 -7
  61. data/lib/thinreports/generator/pdf/drawer/list.rb +4 -4
  62. data/lib/thinreports/generator/pdf/drawer/list_section.rb +8 -3
  63. data/lib/thinreports/generator/pdf/drawer/page.rb +10 -3
  64. data/lib/thinreports/generator/pdf/prawn_ext.rb +16 -21
  65. data/lib/thinreports/layout/format.rb +2 -2
  66. data/lib/thinreports/layout/version.rb +2 -2
  67. data/lib/thinreports/report/base.rb +68 -31
  68. data/tasks/test.rake +48 -4
  69. data/test/benchmark/basic_estimate.tlf +1 -0
  70. data/test/benchmark/bench_basic_estimate.rb +95 -0
  71. data/test/case/character_spacing/character_spacing.rb +7 -0
  72. data/test/case/character_spacing/character_spacing.tlf +1 -0
  73. data/test/case/dynamic_image/dynamic_image.rb +41 -0
  74. data/test/case/dynamic_image/dynamic_image.tlf +1 -0
  75. data/test/case/dynamic_image/img200x100.png +0 -0
  76. data/test/case/dynamic_image/img50x50.png +0 -0
  77. data/test/case/dynamic_style/dynamic_style.rb +154 -0
  78. data/test/case/dynamic_style/dynamic_style.tlf +1 -0
  79. data/test/case/dynamic_style/dynamic_style_in_list.tlf +1 -0
  80. data/test/case/dynamic_style/image.png +0 -0
  81. data/test/case/eudc/eudc.rb +20 -0
  82. data/test/case/eudc/eudc.tlf +1 -0
  83. data/test/case/eudc/eudc.ttf +0 -0
  84. data/test/case/helper.rb +27 -0
  85. data/test/case/hidden_shapes/hidden_shapes.rb +13 -0
  86. data/test/case/hidden_shapes/hidden_shapes.tlf +1 -0
  87. data/test/case/list_events/list_events.rb +32 -0
  88. data/test/case/list_events/list_events.tlf +1 -0
  89. data/test/case/list_header_inheriting/list_header_inheriting.rb +19 -0
  90. data/test/case/list_header_inheriting/list_header_inheriting.tlf +1 -0
  91. data/test/case/list_manual_generation/list_manual_generation.rb +24 -0
  92. data/test/case/list_manual_generation/list_manual_generation.tlf +1 -0
  93. data/test/case/single_line_tblock/single_line_tblock.rb +15 -0
  94. data/test/case/single_line_tblock/single_line_tblock.tlf +1 -0
  95. data/test/case/tblock_styles/tblock_styles.rb +27 -0
  96. data/test/case/tblock_styles/tblock_styles.tlf +1 -0
  97. data/test/case/text_align/text_align.rb +9 -0
  98. data/test/case/text_align/text_align.tlf +1 -0
  99. data/test/unit/core/shape/base/test_internal.rb +65 -85
  100. data/test/unit/core/shape/basic/test_basic_format.rb +30 -0
  101. data/test/unit/core/shape/basic/test_basic_interface.rb +27 -0
  102. data/test/unit/core/shape/basic/test_basic_internal.rb +55 -0
  103. data/test/unit/core/shape/basic/test_interface.rb +84 -36
  104. data/test/unit/core/shape/basic/test_internal.rb +32 -24
  105. data/test/unit/core/shape/image_block/test_format.rb +58 -0
  106. data/test/unit/core/shape/image_block/test_interface.rb +23 -0
  107. data/test/unit/core/shape/image_block/test_internal.rb +28 -0
  108. data/test/unit/core/shape/list/test_events.rb +19 -11
  109. data/test/unit/core/shape/list/test_manager.rb +112 -0
  110. data/test/unit/core/shape/list/test_page.rb +57 -0
  111. data/test/unit/core/shape/list/test_section_format.rb +1 -1
  112. data/test/unit/core/shape/list/test_section_interface.rb +37 -30
  113. data/test/unit/core/shape/list/test_section_internal.rb +39 -14
  114. data/test/unit/core/shape/manager/test_format.rb +12 -18
  115. data/test/unit/core/shape/manager/test_internal.rb +127 -93
  116. data/test/unit/core/shape/manager/test_target.rb +63 -56
  117. data/test/unit/core/shape/styles/test_base.rb +219 -0
  118. data/test/unit/core/shape/styles/test_basic.rb +24 -0
  119. data/test/unit/core/shape/styles/test_graphic.rb +69 -0
  120. data/test/unit/core/shape/styles/test_text.rb +318 -0
  121. data/test/unit/core/shape/{tblock → text_block}/formatter/test_basic.rb +2 -2
  122. data/test/unit/core/shape/{tblock → text_block}/formatter/test_datetime.rb +2 -2
  123. data/test/unit/core/shape/{tblock → text_block}/formatter/test_number.rb +2 -2
  124. data/test/unit/core/shape/{tblock → text_block}/formatter/test_padding.rb +11 -6
  125. data/test/unit/core/shape/text_block/test_format.rb +160 -0
  126. data/test/unit/core/shape/{tblock → text_block}/test_formatter.rb +2 -2
  127. data/test/unit/core/shape/text_block/test_interface.rb +46 -0
  128. data/test/unit/core/shape/text_block/test_internal.rb +128 -0
  129. data/test/unit/core/test_shape.rb +31 -6
  130. data/test/unit/data/basic_layout1.tlf +1 -0
  131. data/test/unit/data/basic_layout2.tlf +1 -0
  132. data/test/unit/data/basic_list_layout.tlf +1 -0
  133. data/test/unit/generator/pdf/document/graphics/test_attributes.rb +81 -52
  134. data/test/unit/generator/pdf/document/graphics/test_text.rb +159 -0
  135. data/test/unit/generator/pdf/document/test_font.rb +21 -6
  136. data/test/unit/generator/pdf/document/test_graphics.rb +2 -2
  137. data/test/unit/generator/pdf/document/test_page.rb +95 -0
  138. data/test/unit/generator/pdf/document/test_parse_color.rb +2 -2
  139. data/test/unit/generator/pdf/test_configuration.rb +24 -0
  140. data/test/unit/generator/pdf/test_document.rb +28 -0
  141. data/test/unit/generator/test_configuration.rb +25 -0
  142. data/test/unit/generator/test_pdf.rb +19 -0
  143. data/test/unit/helper.rb +18 -0
  144. data/test/unit/layout/test_format.rb +24 -7
  145. data/test/unit/layout/test_version.rb +61 -27
  146. data/test/unit/report/test_base.rb +185 -89
  147. data/test/unit/test_config.rb +22 -0
  148. data/test/unit/test_report.rb +4 -4
  149. metadata +94 -43
  150. data/lib/thinreports/core/shape/tblock.rb +0 -16
  151. data/lib/thinreports/generator/pxd.rb +0 -75
  152. data/lib/thinreports/generator/pxd/helper.rb +0 -33
  153. data/lib/thinreports/generator/pxd/list_renderer.rb +0 -58
  154. data/lib/thinreports/generator/pxd/page_renderer.rb +0 -75
  155. data/tasks/clean.rake +0 -6
  156. data/test/unit/core/shape/tblock/test_format.rb +0 -125
  157. data/test/unit/core/shape/tblock/test_interface.rb +0 -40
  158. data/test/unit/core/shape/tblock/test_internal.rb +0 -139
@@ -6,24 +6,15 @@ module ThinReports
6
6
  # @private
7
7
  class Basic::Internal < Base::Internal
8
8
  # Delegate to Format's methods
9
- format_delegators :id, :svg_tag, :svg_attrs, :type
9
+ format_delegators :id, :svg_tag, :type
10
10
 
11
- def visible(visibility)
12
- states[:display] = visibility
13
- end
14
-
15
- def visible?
16
- states.key?(:display) ? states[:display] : format.display?
17
- end
18
-
19
- def svg_attr(attr_name, value)
20
- attrs[attr_name.to_s] = value
11
+ def style
12
+ @style ||= Style::Graphic.new(format)
21
13
  end
22
14
 
23
15
  def type_of?(type_name)
24
16
  ['s-basic', self.type].include?("s-#{type_name}")
25
17
  end
26
18
  end
27
-
28
19
  end
29
20
  end
@@ -0,0 +1,15 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core::Shape
5
+
6
+ module ImageBlock
7
+ TYPE_NAME = 's-iblock'
8
+ end
9
+
10
+ end
11
+ end
12
+
13
+ require 'thinreports/core/shape/image_block/format'
14
+ require 'thinreports/core/shape/image_block/internal'
15
+ require 'thinreports/core/shape/image_block/interface'
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core::Shape
5
+
6
+ # @private
7
+ class ImageBlock::Format < Basic::BlockFormat
8
+ config_reader :position_x => %w( position-x ),
9
+ :position_y => %w( position-y )
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core::Shape
5
+
6
+ class ImageBlock::Interface < Basic::BlockInterface
7
+ # @see #value
8
+ alias_method :src, :value
9
+
10
+ private
11
+
12
+ # @see ThinReports::Core::Shape::Base::Interface#init_internal
13
+ def init_internal(parent, format)
14
+ ImageBlock::Internal.new(parent, format)
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core::Shape
5
+
6
+ # @private
7
+ class ImageBlock::Internal < Basic::BlockInternal
8
+ alias_method :src, :read_value
9
+
10
+ def type_of?(type_name)
11
+ type_name == :iblock || super
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -6,7 +6,24 @@ module ThinReports
6
6
  class List::Events < Core::Events
7
7
  def initialize
8
8
  super(:page_footer_insert,
9
- :footer_insert)
9
+ :footer_insert,
10
+ :page_finalize)
11
+ end
12
+
13
+ class PageEvent < Event
14
+ # @return [ThinReports::Core::Page]
15
+ attr_reader :page
16
+
17
+ # @param type (see ThinReports::Core::Events::Event#initialize)
18
+ # @param [ThinReports::Core::Shape::List::Page] target
19
+ # @param [ThinReports::Core::Page] page
20
+ def initialize(type, target, page)
21
+ super(type, target)
22
+ @page = page
23
+ end
24
+
25
+ # @return [ThinReports::Core::Shape::List::Page]
26
+ alias_method :list, :target
10
27
  end
11
28
 
12
29
  class SectionEvent < Event
@@ -14,7 +31,7 @@ module ThinReports
14
31
  attr_reader :store
15
32
 
16
33
  # @param type (see ThinReports::Core::Events::Event#initialize)
17
- # @param target (see ThinReports::Core::Events::Event#initialize)
34
+ # @param [ThinReports::Core::Shape::List::SectionInterface] target
18
35
  # @param [ThinReports::Core::Shape::List::Store] store
19
36
  def initialize(type, target, store)
20
37
  super(type, target)
@@ -43,7 +43,7 @@ module ThinReports
43
43
  # @see List::Page#header
44
44
  def header(values = {}, &block)
45
45
  unless format.has_header?
46
- raise ThinReports::Errors::DisabledListSection, 'header'
46
+ raise ThinReports::Errors::DisabledListSection.new('header')
47
47
  end
48
48
  current_page_state.header ||= init_section(:header)
49
49
  build_section(current_page_state.header, values, &block)
@@ -102,8 +102,14 @@ module ThinReports
102
102
  # @param [Symbol] section_name
103
103
  # @return [Boolean]
104
104
  def overflow_with?(section_name = :detail)
105
+ max_height = page_max_height
106
+
107
+ if section_name == :footer && format.has_page_footer?
108
+ max_height += format.section_height(:page_footer)
109
+ end
110
+
105
111
  height = format.section_height(section_name)
106
- current_page_state.height + height > page_max_height
112
+ (current_page_state.height + height) > max_height
107
113
  end
108
114
 
109
115
  # @return [Numeric]
@@ -134,6 +140,7 @@ module ThinReports
134
140
 
135
141
  # @param [Hash] options
136
142
  # @option [Boolean] :ignore_page_footer (false)
143
+ # When the switch of the page is generated by #finalize, it is used.
137
144
  # @private
138
145
  def finalize_page(options = {})
139
146
  return if current_page_state.finalized?
@@ -144,12 +151,18 @@ module ThinReports
144
151
 
145
152
  if !options[:ignore_page_footer] && format.has_page_footer?
146
153
  footer = insert_new_row(:page_footer)
147
- # Dispatch event on footer insert.
154
+ # Dispatch page-footer insert event.
148
155
  events.
149
156
  dispatch(List::Events::SectionEvent.new(:page_footer_insert,
150
157
  footer, store))
151
158
  end
152
159
  current_page_state.finalized!
160
+
161
+ # Dispatch page finalize event.
162
+ events.
163
+ dispatch(List::Events::PageEvent.new(:page_finalize,
164
+ current_page,
165
+ current_page_state.parent))
153
166
  end
154
167
 
155
168
  # @private
@@ -169,7 +182,7 @@ module ThinReports
169
182
  else
170
183
  footer = insert_new_row(:footer)
171
184
  end
172
- # Dispatch event on footer insert.
185
+ # Dispatch footer insert event.
173
186
  events.dispatch(List::Events::SectionEvent.new(:footer_insert,
174
187
  footer, store))
175
188
  end
@@ -86,13 +86,13 @@ module ThinReports
86
86
 
87
87
  new_list = self.class.new(new_parent, internal.format,
88
88
  internal.copy(new_parent), manager)
89
-
90
- new_list.internal.header = internal.header.copy(new_list)
91
89
  internal.rows.each do |row|
92
90
  new_list.internal.rows << row.copy(new_list)
93
91
  end
94
92
  new_list.finalized!
95
93
  end
94
+ # New-List inherit List-Header of Old-List.
95
+ new_list.internal.header = internal.header.copy(new_list)
96
96
  new_list
97
97
  end
98
98
 
@@ -18,6 +18,10 @@ module ThinReports
18
18
  @finalized = false
19
19
  end
20
20
 
21
+ def style
22
+ @style ||= Style::Basic.new(format)
23
+ end
24
+
21
25
  def finalized?
22
26
  @finalized
23
27
  end
@@ -13,6 +13,10 @@ module ThinReports
13
13
  # @return [Symbol]
14
14
  attr_accessor :section_name
15
15
 
16
+ def style
17
+ @style ||= Style::Base.new(format)
18
+ end
19
+
16
20
  # @param [Numeric] ry
17
21
  def move_top_to(ry)
18
22
  states[:relative_top] = ry
@@ -16,7 +16,7 @@ module ThinReports
16
16
  end
17
17
 
18
18
  def find_shape(id)
19
- shapes && shapes[id]
19
+ shapes[id]
20
20
  end
21
21
 
22
22
  def shapes
@@ -43,20 +43,33 @@ module ThinReports
43
43
  # @param [String, Symbol] id
44
44
  # @return [ThinReports::Core::Shape::Base::Interface, nil]
45
45
  def final_shape(id)
46
+ # When shape was found in registry.
46
47
  if shape = shapes[id]
47
- return shape.visible? ? shape : nil
48
- end
49
-
50
- sformat = find_format(id)
51
- if sformat.display?
52
- case sformat.type
53
- when Tblock::TYPE_NAME
54
- if sformat.has_reference? || !sformat.value.blank?
55
- init_item(sformat)
56
- end
48
+ return nil unless shape.visible?
49
+
50
+ # In the case of TextBlock or ImageBlock.
51
+ if shape.internal.type_of?(:block)
52
+ shape.internal.real_value.blank? ? nil : shape
53
+ else
54
+ shape
55
+ end
56
+ # When shape was not found in registry.
57
+ elsif f = find_format(id)
58
+ return nil unless f.display?
59
+
60
+ case f.type
61
+ # In the case of TextBlock.
62
+ when TextBlock::TYPE_NAME
63
+ f.has_reference? || !f.value.blank? ? init_item(f) : nil
64
+ # In the case of ImageBlock, Return the nil constantly.
65
+ when ImageBlock::TYPE_NAME
66
+ nil
57
67
  else
58
- init_item(sformat)
68
+ init_item(f)
59
69
  end
70
+ # In the case of other, Return the nil constantly.
71
+ else
72
+ nil
60
73
  end
61
74
  end
62
75
 
@@ -28,7 +28,7 @@ module ThinReports
28
28
  shape = find_item(id, :except => Core::Shape::List::TYPE_NAME)
29
29
 
30
30
  unless shape
31
- raise ThinReports::Errors::UnknownItemId, id
31
+ raise ThinReports::Errors::UnknownItemId.new(id)
32
32
  else
33
33
  block_exec_on(shape, &block)
34
34
  end
@@ -59,7 +59,7 @@ module ThinReports
59
59
  shape = find_item(id, :only => Core::Shape::List::TYPE_NAME)
60
60
 
61
61
  unless shape
62
- raise ThinReports::Errors::UnknownItemId, id
62
+ raise ThinReports::Errors::UnknownItemId.new(id, 'List')
63
63
  else
64
64
  manager.lists[id.to_sym] ||= shape
65
65
  block_exec_on(shape, &block)
@@ -0,0 +1,15 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core::Shape
5
+
6
+ module Style
7
+ end
8
+
9
+ end
10
+ end
11
+
12
+ require 'thinreports/core/shape/style/base'
13
+ require 'thinreports/core/shape/style/basic'
14
+ require 'thinreports/core/shape/style/graphic'
15
+ require 'thinreports/core/shape/style/text'
@@ -0,0 +1,149 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Core::Shape
5
+
6
+ # @private
7
+ class Style::Base
8
+ class << self
9
+ # @param [Symbol] style_method
10
+ # @param [String] style
11
+ # @return [void]
12
+ def style_accessor(style_method, style)
13
+ style_reader(style_method, style)
14
+ style_writer(style_method, style)
15
+ end
16
+
17
+ # @see .style_accessor
18
+ def style_reader(style_method, style)
19
+ define_method(style_method) do
20
+ read_internal_style(style)
21
+ end
22
+ end
23
+
24
+ # @see .style_accessor
25
+ def style_writer(style_method, style)
26
+ define_method(:"#{style_method}=") do |value|
27
+ write_internal_style(style, value)
28
+ end
29
+ end
30
+
31
+ # @param [Array<Symbol>] style_methods
32
+ def style_accessible(*style_methods)
33
+ accessible_styles.concat(style_methods)
34
+ end
35
+
36
+ # @return [Array<Symbol>]
37
+ def accessible_styles
38
+ @accessible_styles ||= []
39
+ end
40
+
41
+ # @private
42
+ def inherited(s)
43
+ s.accessible_styles.concat(accessible_styles.dup)
44
+ end
45
+ end
46
+
47
+ # @return [Hash]
48
+ attr_accessor :styles
49
+ # @see .accessible_styles
50
+ attr_reader :accessible_styles
51
+
52
+ # @param [ThinReports::Core::Format::Base] format
53
+ # @param [Hash] default_styles ({})
54
+ def initialize(format, default_styles = {})
55
+ @format = format
56
+ @styles = default_styles
57
+ @base_styles = format.svg_attrs || {}
58
+
59
+ @accessible_styles = self.class.accessible_styles.dup
60
+ @finalized_svg_attributes = nil
61
+ end
62
+
63
+ # @param [Symbol] style_method
64
+ # @return [Object]
65
+ def [](style_method)
66
+ verify_style_method(style_method)
67
+ send(style_method.to_sym)
68
+ end
69
+
70
+ # @param [Symbol] style_method
71
+ # @param [String, Number, Array<String, Number>]
72
+ def []=(style_method, value)
73
+ verify_style_method(style_method)
74
+ send(:"#{style_method}=", value)
75
+ end
76
+
77
+ # @return [String]
78
+ def identifier
79
+ create_identifier(@styles)
80
+ end
81
+
82
+ # @return [self]
83
+ def copy
84
+ self.class.new(@format, @styles.empty? ? {} : @styles.simple_deep_copy)
85
+ end
86
+
87
+ # @return [Hash]
88
+ def finalized_svg_attributes
89
+ if @finalized_svg_attributes.nil?
90
+ @finalized_svg_attributes = if @styles.empty?
91
+ @base_styles.dup
92
+ else
93
+ @base_styles.merge(@styles)
94
+ end
95
+ end
96
+ @finalized_svg_attributes
97
+ end
98
+ alias_method :svg_attrs, :finalized_svg_attributes
99
+
100
+ # @param [String, Symbol] style
101
+ # @return [Object]
102
+ def read_internal_style(style)
103
+ style = style.to_s
104
+ @styles.key?(style) ? @styles[style] : @base_styles[style]
105
+ end
106
+
107
+ # @param [String, Symbol] style
108
+ # @param [Object] value
109
+ def write_internal_style(style, value)
110
+ @styles[style.to_s] = value
111
+ end
112
+
113
+ # @param [Symbol] style_method
114
+ # @return [Boolean]
115
+ def has_style?(style_method)
116
+ accessible_styles.include?(style_method)
117
+ end
118
+
119
+ private
120
+
121
+ # @param [Hash] s
122
+ # @return [String]
123
+ def create_identifier(s)
124
+ s.empty? ? '' : s.hash.to_s
125
+ end
126
+
127
+ # @param [Symbol] style_method
128
+ # @return [Boolean]
129
+ # @raise ThinReports::Errors::UnknownShapeStyleName
130
+ def verify_style_method(style_method)
131
+ unless has_style?(style_method)
132
+ raise ThinReports::Errors::UnknownShapeStyleName.new(style_method,
133
+ accessible_styles)
134
+ end
135
+ end
136
+
137
+ # @param [Object] value
138
+ # @param [Array<Object>] allows
139
+ # @param [String] msg (nil)
140
+ # @raise ArgumentError
141
+ def verify_style_value(value, allows, msg = nil)
142
+ unless allows.include?(value)
143
+ raise ArgumentError, msg
144
+ end
145
+ end
146
+ end
147
+
148
+ end
149
+ end