qhandout 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2010 QWAN - Quality Without a Name
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
data/lib/qhandout.rb ADDED
@@ -0,0 +1,195 @@
1
+ require "rubygems"
2
+
3
+ require "prawn"
4
+ require "prawn/measurement_extensions"
5
+
6
+ GRAY = 'aaaaaa'
7
+ ORCHID = '9932CD'
8
+ BLACK = '000000'
9
+
10
+ class Prawn::Document
11
+ def texts(lines, *parameters)
12
+ lines.each do |line|
13
+ text line, *parameters
14
+ end
15
+ end
16
+
17
+ def with_shadow(parameters = {})
18
+ shadow_color = parameters[:color] || GRAY
19
+ depth = parameters[:depth] || 0.5.mm
20
+
21
+ original_cursor = cursor
22
+ original_fill_color = fill_color
23
+
24
+ fill_color shadow_color
25
+
26
+ move_down depth
27
+ indent depth do
28
+ yield
29
+ end
30
+
31
+ move_cursor_to original_cursor
32
+ fill_color original_fill_color
33
+ yield
34
+ end
35
+
36
+ def text_with_shadow(*text_args)
37
+ with_shadow do
38
+ text *text_args
39
+ end
40
+ end
41
+ end
42
+
43
+ class Handout
44
+ DEFAULT_TRAINERS = [
45
+ ["Rob Westgeest", "Westgeest-Consultancy",
46
+ "Gondelstraat 2", "5017 CK Tilburg, NL", "+31 6 45 776 328", "rob@qwan.it"],
47
+ ["Marc Evers", "Piecemeal Growth", "Delftseschans 18",
48
+ "3432 TD Nieuwegein, NL", "+31 6 4455 0003", "marc@qwan.it"],
49
+ ["Willem van den Ende", "Living Software B.V.", "Spilmanstraat 25",
50
+ "5645 JE Eindhoven, NL", "+31 6 4130 6965", "willem@qwan.it"]]
51
+
52
+ SERIF_FONT = "Times-Roman"
53
+ COMIC_SANS_FONT = "#{Prawn::BASEDIR}/data/fonts/comicsans.ttf"
54
+
55
+
56
+ def self.create(parameters)
57
+ raise "need course name" unless parameters[:course]
58
+ raise "need course dates" unless parameters[:date]
59
+ raise "need location/client" unless parameters[:location]
60
+ raise "need titles and goals for tabs" unless parameters[:tabs]
61
+
62
+ handout = Handout.new parameters
63
+ handout.create_frontpage
64
+ handout.create_toc
65
+ handout.create_tabs
66
+ end
67
+
68
+ def initialize arguments = {}
69
+ @trainers = arguments[:trainers] || DEFAULT_TRAINERS
70
+ @course = arguments[:course] || ""
71
+ @date = arguments[:date] || ""
72
+ @location = arguments[:location] || ""
73
+ @tabs = arguments[:tabs] || [[]]
74
+ end
75
+
76
+ def header(pdf)
77
+ pdf.font COMIC_SANS_FONT
78
+ pdf.fill_color GRAY
79
+
80
+ pdf.with_shadow :color => BLACK do
81
+ pdf.text @course, :size => 20, :align => :center
82
+ end
83
+ end
84
+
85
+ def footer(pdf, text)
86
+ pdf.move_cursor_to(10.mm)
87
+ pdf.text text, :align => :center
88
+ end
89
+
90
+ def new_page(pdf_file, footer_text = "")
91
+ Prawn::Document.generate(pdf_file, :page_size => 'A4',
92
+ :left_margin => 15.mm,
93
+ :right_margin => 15.mm,
94
+ :top_margin => 20.mm,
95
+ :bottom_margin => 15.mm
96
+ ) do | pdf |
97
+ yield pdf
98
+
99
+ footer(pdf, footer_text)
100
+ end
101
+ end
102
+
103
+ def add_trainer_info(pdf)
104
+ pdf.column_box([0, pdf.cursor], :columns => 3, :width => pdf.bounds.width) do
105
+ pdf.texts @trainers[0], :size => 11, :align => :left
106
+ pdf.bounds.move_past_bottom
107
+ pdf.texts @trainers[1], :size => 11, :align => :center
108
+ pdf.bounds.move_past_bottom
109
+ pdf.texts @trainers[2], :size => 11, :align => :right
110
+ end
111
+ end
112
+
113
+ def create_frontpage
114
+ footer = "(c) 2005-2012 QWAN -Quality Without a Name\nwww.qwan.it -- news@qwan.it"
115
+
116
+ new_page("frontpage.pdf", footer) do | pdf |
117
+ pdf.image "#{File.dirname(__FILE__)}/qwan_logo_small.png", :position => :center
118
+
119
+ pdf.font "Helvetica"
120
+ pdf.text "\n\n\nCourse Handout\n\n\n\n", :size => 20, :align => :center
121
+
122
+ pdf.fill_color ORCHID
123
+ pdf.font COMIC_SANS_FONT
124
+ pdf.text_with_shadow @course, :size => 36, :align => :center
125
+
126
+ pdf.fill_color BLACK
127
+ pdf.font "Helvetica"
128
+ pdf.text "\n\n\n\n\n\n#{@date}", :size => 20, :align => :center
129
+
130
+ pdf.text "#{@location}\n\n\n\n\n\n\n\n", :align => :center
131
+
132
+ add_trainer_info(pdf)
133
+ end
134
+ end
135
+
136
+ def tab_number(pdf, tab_nr)
137
+ pdf.bounding_box [pdf.bounds.left, pdf.bounds.top], :width => 60, :height => 60 do
138
+ pdf.text_with_shadow tab_nr, :size => 42
139
+ end
140
+ end
141
+
142
+ def title_and_goal(pdf, goal, title)
143
+ pdf.bounding_box [pdf.bounds.left + 28, pdf.bounds.top], :width => 500, :height => 60 do
144
+ pdf.text_with_shadow title, :size => 18
145
+ pdf.fill_color BLACK
146
+ pdf.text goal, :size => 12
147
+ end
148
+ end
149
+
150
+ def tab_entry(pdf, title, goal, tab_nr)
151
+ pdf.bounding_box [15.mm, pdf.cursor - 5.mm], :width => 600 do
152
+ pdf.font SERIF_FONT
153
+ pdf.fill_color ORCHID
154
+
155
+ tab_number(pdf, tab_nr)
156
+ title_and_goal(pdf, goal, title)
157
+ end
158
+ end
159
+
160
+ def tab_footer
161
+ "#{@course} / #{@date}, #{@location}"
162
+ end
163
+
164
+ def create_toc
165
+ new_page("toc.pdf", tab_footer) do | pdf |
166
+ header(pdf)
167
+
168
+ pdf.move_down 10.mm
169
+
170
+ @tabs.each_with_index do | (title, goal), index |
171
+ tab_entry(pdf, title, goal, (index + 1).to_s)
172
+ end
173
+ end
174
+ end
175
+
176
+ def tab(title, goal, tab_nr)
177
+ new_page("tab#{tab_nr}.pdf", tab_footer) do |pdf|
178
+ pdf.move_down 40.mm
179
+
180
+ tab_entry(pdf, title, "", tab_nr)
181
+
182
+ pdf.bounding_box [30.mm, pdf.cursor - 20.mm], :width => 140.mm do
183
+ pdf.fill_color BLACK
184
+ pdf.text goal, :size => 16
185
+ end
186
+ end
187
+ end
188
+
189
+ def create_tabs
190
+ @tabs.each_with_index do | (title, goal), index |
191
+ tab title, goal, (index+1).to_s
192
+ end
193
+ end
194
+ end
195
+
Binary file
@@ -0,0 +1,21 @@
1
+
2
+ module Test::Unit::Assertions
3
+ def assert_pdf(pdf, expected_argument)
4
+ raise "expected argument must be a hash" unless expected_argument.is_a?(Hash)
5
+ expected = expected_argument[:contains]
6
+ expected = [expected] if expected && expected.is_a?(String)
7
+ not_expected = expected_argument[:does_not_contain]
8
+
9
+ raise "missing expected text" unless expected or not_expected
10
+
11
+ assert File.exist?(pdf), "file '#{pdf}' not found"
12
+
13
+ text = `pdftotext #{pdf} -`
14
+
15
+ expected.each do |expected_text|
16
+ assert_match %r{#{expected_text}}, text, "pdf does not contain '#{expected_text}'"
17
+ end if expected
18
+
19
+ assert_no_match %r{#{not_expected}}, text, "pdf does contains '#{not_expected}'" if not_expected
20
+ end
21
+ end
@@ -0,0 +1,64 @@
1
+ require "rubygems"
2
+ require "test/unit"
3
+ require "test/unit/assertions"
4
+ require "prawn"
5
+
6
+ require "assert_pdf"
7
+
8
+ class AssertPDFTest < Test::Unit::TestCase
9
+ TEST_FILE = "test.pdf"
10
+
11
+ def setup
12
+ Prawn::Document.generate("test.pdf") do |pdf|
13
+ pdf.text "www.qwan.it"
14
+ pdf.text "Rob"
15
+ end
16
+ end
17
+
18
+ def teardown
19
+ File.delete "test.pdf" if File.exist? "test.pdf"
20
+ end
21
+
22
+ def test_pdftotext_available
23
+ `pdftotext test.pdf -`
24
+ assert_equal 0, $?.to_i, "pdftotext not installed?"
25
+ end
26
+
27
+ def test_assert_non_existing_pdf_fails_test
28
+ assert_raises MiniTest::Assertion do
29
+ assert_pdf "doesnotexist.pdf", :contains => "www.qwan.it"
30
+ end
31
+ end
32
+
33
+ def test_assert_existing_pdf_passes_test
34
+ assert_pdf TEST_FILE, :contains => "www.qwan.it"
35
+ end
36
+
37
+ def test_assert_without_expected_text_raises_error
38
+ assert_raises RuntimeError do
39
+ assert_pdf TEST_FILE, "www.qwan.it"
40
+ end
41
+ end
42
+
43
+ def test_assert_text_not_in_pdf_fails
44
+ assert_raises MiniTest::Assertion do
45
+ assert_pdf TEST_FILE, :contains => "Agile"
46
+ end
47
+ end
48
+
49
+ def test_assert_multiple_texts_in_pdf_passes
50
+ assert_pdf TEST_FILE, :contains => ["www.qwan.it", "Rob"]
51
+ end
52
+
53
+ def test_assert_multiple_texts_with_one_not_existing_in_pdf_fails
54
+ assert_raises MiniTest::Assertion do
55
+ assert_pdf TEST_FILE, :contains => ["www.qwan.it", "agile"]
56
+ end
57
+ end
58
+
59
+ def test_asserting_does_non_contain_on_existing_text_fails
60
+ assert_raises MiniTest::Assertion do
61
+ assert_pdf TEST_FILE, :does_not_contain => "www.qwan.it"
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,70 @@
1
+ require "test/unit"
2
+ require "assert_pdf"
3
+ require "qhandout"
4
+
5
+ class HandoutTest < Test::Unit::TestCase
6
+ def setup
7
+ Handout.new(:course => "TDD For Dummies", :date => "10 June 2031", :location => "Utrecht").create_frontpage
8
+ end
9
+
10
+ def teardown
11
+ File.delete "frontpage.pdf" if File.exist? "FrontPage.pdf"
12
+ end
13
+
14
+ def test_frontpage_contains_default_trainers
15
+ assert_pdf "frontpage.pdf", :contains => ["Rob", "Tilburg", "Marc", "Willem"]
16
+ end
17
+
18
+ def test_frontpage_contains_course_dates_location_footer
19
+ assert_pdf "frontpage.pdf", :contains => ["TDD For Dummies", "10 June 2031", "Utrecht"]
20
+ assert_pdf "frontpage.pdf", :contains => ["2005-2012", "www.qwan.it"]
21
+ end
22
+ end
23
+
24
+ class TabsTest < Test::Unit::TestCase
25
+ def setup
26
+ @handout = Handout.new :course => "TDD For Dummies", :date => "10 & 11 June 2031", :location => "Utrecht",
27
+ :tabs => [["Intro", "Get to know each other"], ["RDD", "CRC"]]
28
+ end
29
+
30
+ def delete_if_exists(files)
31
+ files.each do |file|
32
+ File.delete file if File.exist? file
33
+ end
34
+ end
35
+
36
+ def teardown
37
+ delete_if_exists ["toc.pdf", "tab1.pdf", "tab2.pdf"]
38
+ end
39
+
40
+ def test_create_toc
41
+ @handout.create_toc
42
+
43
+ assert_pdf "toc.pdf", :contains => ["TDD For Dummies"]
44
+ assert_pdf "toc.pdf", :contains => ["1", "Intro", "Get to know each other"]
45
+
46
+ assert_pdf "toc.pdf", :contains => ["10 & 11 June 2031", "Utrecht"]
47
+ end
48
+
49
+ def test_create_toc_with_multiple_entries
50
+ @handout.create_toc
51
+
52
+ assert_pdf "toc.pdf", :contains => ["1", "Intro", "Get to know each other"]
53
+ assert_pdf "toc.pdf", :contains => ["2", "TDD", "CRC"]
54
+ end
55
+
56
+ def test_create_tab_page
57
+ @handout.create_tabs
58
+
59
+ assert_pdf "tab1.pdf", :contains => ["1", "Intro", "Get to know each other"]
60
+
61
+ assert_pdf "tab1.pdf", :contains => ["10 & 11 June 2031", "Utrecht"]
62
+ end
63
+
64
+ def test_create_multiple_tab_pages
65
+ @handout.create_tabs
66
+
67
+ assert_pdf "tab2.pdf", :contains => ["2", "RDD", "CRC"]
68
+ assert_pdf "tab2.pdf", :does_not_contain => "Intro"
69
+ end
70
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qhandout
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Marc Evers
9
+ - Rob Westgeest
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-03-30 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rake
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 0.9.2
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: 0.9.2
31
+ - !ruby/object:Gem::Dependency
32
+ name: bundler
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: 1.1.3
39
+ type: :development
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: 1.1.3
47
+ - !ruby/object:Gem::Dependency
48
+ name: jeweler
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.8.3
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ version: 1.8.3
63
+ - !ruby/object:Gem::Dependency
64
+ name: rcov
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :development
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: prawn
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: 0.8.4
87
+ type: :development
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: 0.8.4
95
+ description: Generate course handout toc/tabs
96
+ email: info@qwan.it
97
+ executables: []
98
+ extensions: []
99
+ extra_rdoc_files:
100
+ - LICENSE.txt
101
+ files:
102
+ - VERSION
103
+ - lib/qhandout.rb
104
+ - lib/qwan_logo_small.png
105
+ - test/assert_pdf.rb
106
+ - test/test_assert_pdf.rb
107
+ - test/test_qhandout.rb
108
+ - LICENSE.txt
109
+ homepage: http://www.qwan.it
110
+ licenses:
111
+ - MIT
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ segments:
123
+ - 0
124
+ hash: -189504195
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ! '>='
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubyforge_project:
133
+ rubygems_version: 1.8.21
134
+ signing_key:
135
+ specification_version: 3
136
+ summary: Generate course handout toc/tabs
137
+ test_files: []