thinreports 0.6.0.pre3

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 (146) hide show
  1. data/.yardopts +1 -0
  2. data/README.rdoc +100 -0
  3. data/Rakefile +10 -0
  4. data/doc/yardoc_templates/default/layout/html/footer.erb +10 -0
  5. data/lib/thinreports.rb +11 -0
  6. data/lib/thinreports/core.rb +20 -0
  7. data/lib/thinreports/core/errors.rb +58 -0
  8. data/lib/thinreports/core/events.rb +71 -0
  9. data/lib/thinreports/core/ext.rb +5 -0
  10. data/lib/thinreports/core/ext/array.rb +19 -0
  11. data/lib/thinreports/core/ext/hash.rb +19 -0
  12. data/lib/thinreports/core/ext/object.rb +25 -0
  13. data/lib/thinreports/core/format.rb +14 -0
  14. data/lib/thinreports/core/format/base.rb +93 -0
  15. data/lib/thinreports/core/format/builder.rb +65 -0
  16. data/lib/thinreports/core/ordered_hash.rb +39 -0
  17. data/lib/thinreports/core/page.rb +91 -0
  18. data/lib/thinreports/core/shape.rb +53 -0
  19. data/lib/thinreports/core/shape/base.rb +16 -0
  20. data/lib/thinreports/core/shape/base/interface.rb +38 -0
  21. data/lib/thinreports/core/shape/base/internal.rb +60 -0
  22. data/lib/thinreports/core/shape/basic.rb +15 -0
  23. data/lib/thinreports/core/shape/basic/format.rb +26 -0
  24. data/lib/thinreports/core/shape/basic/interface.rb +57 -0
  25. data/lib/thinreports/core/shape/basic/internal.rb +29 -0
  26. data/lib/thinreports/core/shape/list.rb +25 -0
  27. data/lib/thinreports/core/shape/list/configuration.rb +33 -0
  28. data/lib/thinreports/core/shape/list/events.rb +30 -0
  29. data/lib/thinreports/core/shape/list/format.rb +72 -0
  30. data/lib/thinreports/core/shape/list/manager.rb +209 -0
  31. data/lib/thinreports/core/shape/list/page.rb +118 -0
  32. data/lib/thinreports/core/shape/list/page_state.rb +40 -0
  33. data/lib/thinreports/core/shape/list/section_format.rb +32 -0
  34. data/lib/thinreports/core/shape/list/section_interface.rb +48 -0
  35. data/lib/thinreports/core/shape/list/section_internal.rb +29 -0
  36. data/lib/thinreports/core/shape/list/store.rb +34 -0
  37. data/lib/thinreports/core/shape/manager.rb +14 -0
  38. data/lib/thinreports/core/shape/manager/format.rb +28 -0
  39. data/lib/thinreports/core/shape/manager/internal.rb +87 -0
  40. data/lib/thinreports/core/shape/manager/target.rb +85 -0
  41. data/lib/thinreports/core/shape/tblock.rb +16 -0
  42. data/lib/thinreports/core/shape/tblock/format.rb +36 -0
  43. data/lib/thinreports/core/shape/tblock/formatter.rb +32 -0
  44. data/lib/thinreports/core/shape/tblock/formatter/basic.rb +38 -0
  45. data/lib/thinreports/core/shape/tblock/formatter/datetime.rb +21 -0
  46. data/lib/thinreports/core/shape/tblock/formatter/number.rb +49 -0
  47. data/lib/thinreports/core/shape/tblock/formatter/padding.rb +43 -0
  48. data/lib/thinreports/core/shape/tblock/interface.rb +52 -0
  49. data/lib/thinreports/core/shape/tblock/internal.rb +70 -0
  50. data/lib/thinreports/core/shape/text.rb +15 -0
  51. data/lib/thinreports/core/shape/text/format.rb +25 -0
  52. data/lib/thinreports/core/shape/text/interface.rb +16 -0
  53. data/lib/thinreports/core/shape/text/internal.rb +17 -0
  54. data/lib/thinreports/core/utils.rb +48 -0
  55. data/lib/thinreports/generator.rb +30 -0
  56. data/lib/thinreports/generator/base.rb +49 -0
  57. data/lib/thinreports/generator/pdf.rb +63 -0
  58. data/lib/thinreports/generator/pdf/document.rb +171 -0
  59. data/lib/thinreports/generator/pdf/document/draw_shape.rb +74 -0
  60. data/lib/thinreports/generator/pdf/document/font.rb +59 -0
  61. data/lib/thinreports/generator/pdf/document/graphics.rb +42 -0
  62. data/lib/thinreports/generator/pdf/document/graphics/attributes.rb +92 -0
  63. data/lib/thinreports/generator/pdf/document/graphics/basic.rb +132 -0
  64. data/lib/thinreports/generator/pdf/document/graphics/image.rb +51 -0
  65. data/lib/thinreports/generator/pdf/document/graphics/text.rb +130 -0
  66. data/lib/thinreports/generator/pdf/document/parse_color.rb +51 -0
  67. data/lib/thinreports/generator/pdf/document/parse_svg.rb +102 -0
  68. data/lib/thinreports/generator/pdf/drawer.rb +16 -0
  69. data/lib/thinreports/generator/pdf/drawer/base.rb +56 -0
  70. data/lib/thinreports/generator/pdf/drawer/list.rb +39 -0
  71. data/lib/thinreports/generator/pdf/drawer/list_section.rb +46 -0
  72. data/lib/thinreports/generator/pdf/drawer/page.rb +101 -0
  73. data/lib/thinreports/generator/pdf/prawn_ext.rb +36 -0
  74. data/lib/thinreports/generator/pxd.rb +75 -0
  75. data/lib/thinreports/generator/pxd/helper.rb +33 -0
  76. data/lib/thinreports/generator/pxd/list_renderer.rb +58 -0
  77. data/lib/thinreports/generator/pxd/page_renderer.rb +75 -0
  78. data/lib/thinreports/layout.rb +17 -0
  79. data/lib/thinreports/layout/base.rb +78 -0
  80. data/lib/thinreports/layout/configuration.rb +27 -0
  81. data/lib/thinreports/layout/format.rb +77 -0
  82. data/lib/thinreports/layout/version.rb +43 -0
  83. data/lib/thinreports/report.rb +31 -0
  84. data/lib/thinreports/report/base.rb +160 -0
  85. data/lib/thinreports/report/events.rb +32 -0
  86. data/lib/thinreports/report/internal.rb +131 -0
  87. data/resources/fonts/IPA_Font_License_Agreement_v1.0.txt +117 -0
  88. data/resources/fonts/ipag.ttf +0 -0
  89. data/resources/fonts/ipagp.ttf +0 -0
  90. data/resources/fonts/ipam.ttf +0 -0
  91. data/resources/fonts/ipamp.ttf +0 -0
  92. data/tasks/clean.rake +6 -0
  93. data/tasks/doc.rake +13 -0
  94. data/tasks/test.rake +18 -0
  95. data/test/unit/core/ext/array_spec.rb +29 -0
  96. data/test/unit/core/ext/hash_spec.rb +29 -0
  97. data/test/unit/core/ext/object_spec.rb +30 -0
  98. data/test/unit/core/format/test_base.rb +148 -0
  99. data/test/unit/core/format/test_builder.rb +114 -0
  100. data/test/unit/core/ordered_hash_spec.rb +51 -0
  101. data/test/unit/core/shape/base/test_interface.rb +52 -0
  102. data/test/unit/core/shape/base/test_internal.rb +109 -0
  103. data/test/unit/core/shape/basic/test_format.rb +59 -0
  104. data/test/unit/core/shape/basic/test_interface.rb +70 -0
  105. data/test/unit/core/shape/basic/test_internal.rb +42 -0
  106. data/test/unit/core/shape/list/test_configuration.rb +52 -0
  107. data/test/unit/core/shape/list/test_events.rb +28 -0
  108. data/test/unit/core/shape/list/test_format.rb +71 -0
  109. data/test/unit/core/shape/list/test_page.rb +10 -0
  110. data/test/unit/core/shape/list/test_page_state.rb +31 -0
  111. data/test/unit/core/shape/list/test_section_format.rb +46 -0
  112. data/test/unit/core/shape/list/test_section_interface.rb +52 -0
  113. data/test/unit/core/shape/list/test_section_internal.rb +30 -0
  114. data/test/unit/core/shape/list/test_store.rb +41 -0
  115. data/test/unit/core/shape/manager/test_format.rb +40 -0
  116. data/test/unit/core/shape/manager/test_internal.rb +137 -0
  117. data/test/unit/core/shape/manager/test_target.rb +109 -0
  118. data/test/unit/core/shape/tblock/formatter/test_basic.rb +24 -0
  119. data/test/unit/core/shape/tblock/formatter/test_datetime.rb +47 -0
  120. data/test/unit/core/shape/tblock/formatter/test_number.rb +76 -0
  121. data/test/unit/core/shape/tblock/formatter/test_padding.rb +72 -0
  122. data/test/unit/core/shape/tblock/test_format.rb +125 -0
  123. data/test/unit/core/shape/tblock/test_formatter.rb +28 -0
  124. data/test/unit/core/shape/tblock/test_interface.rb +40 -0
  125. data/test/unit/core/shape/tblock/test_internal.rb +139 -0
  126. data/test/unit/core/shape/text/test_format.rb +73 -0
  127. data/test/unit/core/shape/text/test_internal.rb +21 -0
  128. data/test/unit/core/test_events.rb +91 -0
  129. data/test/unit/core/test_shape.rb +35 -0
  130. data/test/unit/core/utils_spec.rb +56 -0
  131. data/test/unit/generator/pdf/document/graphics/test_attributes.rb +103 -0
  132. data/test/unit/generator/pdf/document/test_font.rb +54 -0
  133. data/test/unit/generator/pdf/document/test_graphics.rb +43 -0
  134. data/test/unit/generator/pdf/document/test_parse_color.rb +30 -0
  135. data/test/unit/generator/test_base.rb +51 -0
  136. data/test/unit/helper.rb +37 -0
  137. data/test/unit/layout/test_base.rb +92 -0
  138. data/test/unit/layout/test_configuration.rb +46 -0
  139. data/test/unit/layout/test_format.rb +104 -0
  140. data/test/unit/layout/test_version.rb +62 -0
  141. data/test/unit/report/test_base.rb +187 -0
  142. data/test/unit/report/test_events.rb +22 -0
  143. data/test/unit/report/test_internal.rb +234 -0
  144. data/test/unit/test_layout.rb +12 -0
  145. data/test/unit/test_report.rb +30 -0
  146. metadata +218 -0
@@ -0,0 +1,75 @@
1
+ # coding: utf-8
2
+
3
+ require 'stringio'
4
+ require 'tempfile'
5
+
6
+ module ThinReports
7
+ module Generator
8
+
9
+ class Pxd < Base
10
+ require 'thinreports/generator/pxd/helper'
11
+
12
+ autoload :PageRenderer, 'thinreports/generator/pxd/page_renderer'
13
+ autoload :ListRenderer, 'thinreports/generator/pxd/list_renderer'
14
+
15
+ include Helper
16
+
17
+ # @param report (see ThinReports::Generator::Base#initialize)
18
+ # @param [Hash] options See http://www.pxdoc.com/tech/wiki.cgi?page=pxd
19
+ def initialize(report, options)
20
+ super
21
+ @renderers = {}
22
+ end
23
+
24
+ # @see ThinReports::Generator::Base#generate
25
+ def generate
26
+ output = StringIO.new('', 'r+:UTF-8')
27
+ render_start_pxd(output)
28
+
29
+ report.pages.each do |page|
30
+ render_page(output, page)
31
+ end
32
+
33
+ render_end_pxd(output)
34
+ output.string
35
+ end
36
+
37
+ # @see ThinReports::Generator::Base#generate_file
38
+ def generate_file(filename)
39
+ File.open(filename, 'w') {|f| f << generate }
40
+ end
41
+
42
+ private
43
+
44
+ def renderer(page)
45
+ @renderers[page.layout.format.identifier] ||=
46
+ PageRenderer.new(page.layout.format)
47
+ end
48
+
49
+ def render_page(output, page)
50
+ output << unless page.blank?
51
+ content_tag(:page, renderer(page).render(page.manager), nil,
52
+ :escape => false)
53
+ else
54
+ tag(:page)
55
+ end
56
+ end
57
+
58
+ def render_start_pxd(output)
59
+ format = default_layout.format
60
+ attrs = @options.merge('title' => format.report_title,
61
+ 'paper-type' => format.page_paper_type,
62
+ 'orientation' => format.page_orientation,
63
+ 'width' => format.page_width,
64
+ 'height' => format.page_height,
65
+ 'dpi' => '72')
66
+ output << tag(:pxd, attrs, true)
67
+ end
68
+
69
+ def render_end_pxd(output)
70
+ output << '</pxd>'
71
+ end
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+
3
+ require 'erb'
4
+
5
+ module ThinReports
6
+ module Generator
7
+
8
+ # @private
9
+ module Pxd::Helper
10
+ private
11
+
12
+ def content_tag(tag_name, content = nil, attrs = nil, options = {})
13
+ content = h(content) unless options[:escape] == false
14
+ tag(tag_name, attrs, true) << content.to_s << "</#{h(tag_name)}>"
15
+ end
16
+
17
+ def tag(tag_name, attrs = nil, open = false)
18
+ attrs = tag_attributes(attrs)
19
+ attrs = ' ' + attrs unless attrs.blank?
20
+ "<#{h(tag_name)}#{attrs}#{open ? '' : ' /'}>"
21
+ end
22
+
23
+ def tag_attributes(attrs)
24
+ attrs && attrs.map{|k, v| "#{h(k)}=\"#{h(v)}\"" }.join(' ')
25
+ end
26
+
27
+ def h(s)
28
+ ERB::Util.html_escape(s)
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,58 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Generator
5
+
6
+ # @private
7
+ class Pxd::ListRenderer
8
+ include Pxd::Helper
9
+
10
+ def initialize
11
+ @renderers = {}
12
+ @list = nil
13
+ end
14
+
15
+ # @param [ThinReports::Core::Shape::List::PageState] list
16
+ def render(list)
17
+ @list = list
18
+
19
+ result = String.new
20
+ render_section(result, list.header) if list.header
21
+
22
+ list.rows.each do |row|
23
+ render_section(result, row)
24
+ end
25
+ result
26
+ end
27
+
28
+ private
29
+
30
+ # @param [String] result
31
+ # @param [ThinReports::Core::Shape::List::SectionInterface] section
32
+ def render_section(result, section)
33
+ internal = section.internal
34
+ attributes = internal.attributes
35
+ contents = renderer(internal.section_name).render(section.manager)
36
+
37
+ # Only for when older than Ver 0.6.0.pre2.
38
+ # Since 0.6.0.pre3, ignore this.
39
+ if internal.relative_top
40
+ attributes['transform'] =
41
+ "translate(#{internal.relative_position.join(',')})"
42
+ end
43
+
44
+ result << content_tag(internal.svg_tag, contents, attributes,
45
+ :escape => false)
46
+ end
47
+
48
+ # @param [Symbol] section_name
49
+ # @return [ThinReports::Generator::Pxd::PageRenderer]
50
+ def renderer(section_name)
51
+ @renderers[section_name] ||=
52
+ Pxd::PageRenderer.new(@list.format.sections[section_name])
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,75 @@
1
+ # coding: utf-8
2
+
3
+ require 'erb'
4
+
5
+ module ThinReports
6
+ module Generator
7
+
8
+ # @private
9
+ class Pxd::PageRenderer
10
+ include Pxd::Helper
11
+
12
+ def initialize(format)
13
+ @engine = ERB.new(read_layout(format))
14
+ @manager = {}
15
+ @lists = {}
16
+ end
17
+
18
+ # @param [ThinReports::Core::Shape::Manager::Internal] manager
19
+ # @return [String]
20
+ def render(manager)
21
+ @manager = manager
22
+ @engine.result(binding)
23
+ end
24
+
25
+ def render_shape(id)
26
+ return '' unless shape = @manager.final_shape(id)
27
+
28
+ shape = shape.internal
29
+ case
30
+ when shape.type_of?(:tblock)
31
+ render_tblock(shape)
32
+ when shape.type_of?(:list)
33
+ render_list(shape)
34
+ when shape.type_of?(:text)
35
+ render_text(shape)
36
+ else
37
+ render_basic(shape)
38
+ end
39
+ end
40
+ alias_method :r, :render_shape
41
+
42
+ private
43
+
44
+ def render_basic(shape)
45
+ tag(shape.svg_tag, shape.attributes)
46
+ end
47
+
48
+ def render_text(shape)
49
+ content_tag(shape.svg_tag, shape.svg_content,
50
+ shape.attribute, :escape => false)
51
+ end
52
+
53
+ def render_tblock(shape)
54
+ value = h(shape.real_value)
55
+ value = if shape.multiple?
56
+ value.gsub(/\r\n|\n/, '<tBreak/>')
57
+ else
58
+ value.gsub(/\r\n|\n/, ' ')
59
+ end
60
+ content_tag(shape.svg_tag, value, shape.attributes, :escape => false)
61
+ end
62
+
63
+ def render_list(shape)
64
+ renderer = @lists[shape.id] ||= Pxd::ListRenderer.new
65
+ renderer.render(shape)
66
+ end
67
+
68
+ def read_layout(format)
69
+ format.layout.gsub(/ x\-[a-z\d\-]+?=".*?"/, '').
70
+ gsub(/ class=".*?"/, '')
71
+ end
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,17 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+
5
+ module Layout
6
+ # @see ThinReports::Layout::Base#initialize
7
+ def self.new(filename, options = {})
8
+ Base.new(filename, options)
9
+ end
10
+ end
11
+
12
+ end
13
+
14
+ require 'thinreports/layout/version'
15
+ require 'thinreports/layout/base'
16
+ require 'thinreports/layout/format'
17
+ require 'thinreports/layout/configuration'
@@ -0,0 +1,78 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Layout
5
+
6
+ class Base
7
+ EXT_NAME = 'tlf'
8
+
9
+ class << self
10
+ # @param [String] filename
11
+ # @return [ThinReports::Layout::Format]
12
+ # @raise [ThinReports::Errors::InvalidLayoutFormat]
13
+ # @raise [ThinReports::Errors::IncompatibleLayoutFormat]
14
+ # @private
15
+ def load_format(filename)
16
+ filename += ".#{EXT_NAME}" unless filename =~/\.#{EXT_NAME}$/
17
+
18
+ unless File.exists?(filename)
19
+ raise ThinReports::Errors::LayoutFileNotFound
20
+ end
21
+ # Build format.
22
+ ThinReports::Layout::Format.build(filename)
23
+ end
24
+
25
+ # @private
26
+ def Page
27
+ const_defined?(:Page) ? Page : Core::Page
28
+ end
29
+
30
+ private
31
+
32
+ # @private
33
+ def PageHelpers(&block)
34
+ const_set(:Page, ::Class.new(Core::Page, &block))
35
+ end
36
+ end
37
+
38
+ # @private
39
+ attr_reader :format
40
+
41
+ # @return [String]
42
+ attr_reader :filename
43
+
44
+ # @return [Symbol]
45
+ attr_reader :id
46
+
47
+ # @param [String] filename
48
+ # @param [Hash] options
49
+ # @option options [Symbol] :id (nil)
50
+ def initialize(filename, options = {})
51
+ @filename = filename
52
+ @format = self.class.load_format(filename)
53
+ @id = options[:id]
54
+ end
55
+
56
+ # @return [Boolean] Return the true if is default layout.
57
+ def default?
58
+ @id.nil?
59
+ end
60
+
61
+ # @yield [config]
62
+ # @yieldparam [List::Configuration] config
63
+ # @return [List::Configuration]
64
+ def config(&block)
65
+ @config ||= Layout::Configuration.new(self)
66
+ block_exec_on(@config, &block)
67
+ end
68
+
69
+ # @param [ThinReports::Report::Base] parent
70
+ # @return [Page]
71
+ # @private
72
+ def init_new_page(parent)
73
+ self.class.Page.new(parent, self)
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+
3
+ module ThinReports
4
+ module Layout
5
+
6
+ class Configuration
7
+ include Core::Shape::Manager::Target
8
+
9
+ undef_method :items, :values
10
+
11
+ # @param [ThinReports::Layout::Base]
12
+ def initialize(layout)
13
+ initialize_manager(layout.format) do |f|
14
+ Core::Shape::Configuration(f.type).new
15
+ end
16
+ end
17
+
18
+ # @param [String, Symbol] shape_id
19
+ # @return [Object, nil]
20
+ # @private
21
+ def activate(shape_id)
22
+ (config = manager.shapes[shape_id.to_sym]) && config.copy
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,77 @@
1
+ # coding: utf-8
2
+
3
+ require 'digest/sha1'
4
+
5
+ module ThinReports
6
+ module Layout
7
+
8
+ # @private
9
+ class Format < Core::Shape::Manager::Format
10
+ config_reader :last_version => %w( version )
11
+ config_reader :report_title => %w( title )
12
+ config_reader :page_paper_type => %w( config page paper-type ),
13
+ :page_width => %w( config page width ),
14
+ :page_height => %w( config page height ),
15
+ :page_orientation => %w( config page orientation ),
16
+ :page_margin_top => %w( config page margin-top ),
17
+ :page_margin_bottom => %w( config page margin-bottom ),
18
+ :page_margin_left => %w( config page margin-left ),
19
+ :page_margin_left => %w( config page margin-right )
20
+
21
+ config_checker 'user', :user_paper_type => %w( config page paper-type )
22
+
23
+ class << self
24
+
25
+ private
26
+
27
+ # @param [String] filename
28
+ # @param [Hash] options
29
+ # @option options [Boolean] :force (false)
30
+ # @private
31
+ def build_internal(filename, options = {})
32
+ build_once(filename, options[:force]) do |content, id|
33
+ raw_format = parse_json(content)
34
+
35
+ # Check the compatibility of specified layout file.
36
+ unless ThinReports::Layout::Version.compatible?(raw_format['version'])
37
+ info = [filename, raw_format['version'],
38
+ ThinReports::Layout::Version.required_rules_inspect]
39
+ raise ThinReports::Errors::IncompatibleLayoutFormat.new(*info)
40
+ end
41
+
42
+ # Build and initialize format.
43
+ new(raw_format, id) do |f|
44
+ build_layout(f) do |type, shape_format|
45
+ Core::Shape::Format(type).build(shape_format)
46
+ end
47
+ clean(f.layout)
48
+ end
49
+ end
50
+ end
51
+
52
+ # @private
53
+ def build_once(filename, force = false, &block)
54
+ content = read_format_file(filename)
55
+
56
+ if force
57
+ block.call(content, nil)
58
+ else
59
+ id = Digest::SHA1.hexdigest(content).to_sym
60
+ built_format_registry[id] ||= block.call(content, id)
61
+ end
62
+ end
63
+
64
+ # @private
65
+ def read_format_file(filename)
66
+ File.open(filename, 'r:UTF-8') {|f| f.read }
67
+ end
68
+
69
+ # @private
70
+ def built_format_registry
71
+ @built_format_registry ||= {}
72
+ end
73
+ end
74
+ end
75
+
76
+ end
77
+ end