Class: Dinbrief::Letter

Inherits:
Prawn::Document
  • Object
show all
Defined in:
lib/dinbrief/letter.rb,
lib/dinbrief/letter/constants.rb,
lib/dinbrief/letter/design_elements.rb,
lib/dinbrief/letter/typeset_methods.rb

Constant Summary collapse

DocumentDefaults =

The following options are available (with the default values marked in [])

{                # The following options are available (with the default values marked in [])
  :page_size          => 'A4',      # One of the Document::PageGeometry sizes [LETTER]
  :page_layout        => :portrait, # Either :portrait or :landscape
  :left_margin        => 25.mm,      # Sets the left margin in points [0.5 inch]
  :right_margin       => 20.mm,      # Sets the right margin in points [0.5 inch]
  :top_margin         => 30.mm,      # Sets the top margin in points [0.5 inch]
  :bottom_margin      => 3.cm,      # Sets the bottom margin in points [0.5 inch]
  :skip_page_creation => false,     # Creates a document without starting the first page [false]
  :compress           => false,     # Compresses content streams before rendering them [false]
  :optimize_objects   => false,     # Reduce number of PDF objects in output, at expense of render time [false]
  :background         => nil,       # An image path to be used as background on all pages [nil]
  :info               => nil,       # Generic hash allowing for custom metadata properties [nil]
  :template           => nil        # The path to an existing PDF file to use as a template [nil]
}
MeasurementDefaults =
{
  # Folding Marks
  :fold_mark_1_y    => 87.mm,
  :fold_mark_2_y    => -105.mm,
  :fold_mark_x      => 5.mm,
  :fold_mark_width  => 5.mm,
  :punch_mark_y     => 148.5.mm,
  :punch_mark_x     => 5.mm,
  :punch_mark_width => 5.mm,

  # Return Address Field
  :return_address_x          => 20.mm,
  :return_address_y          => -45.mm - 10.mm,
  :return_address_rule_x     => 20.mm,
  :return_address_rule_y     => -45.mm - 14.mm,
  :return_address_rule_width => 85.mm,
  :return_address_rule_linewidth => 0.5.pt,
  :return_address_fontsize   => 8.pt,
  :return_address_align      => :center,
  :return_address_width      => 85.mm,

  # Address Field
  :address_x          => 25.mm,
  :address_y          => -45.mm - 17.mm,
  :address_width      => 80.mm,
  :address_height     => 28.mm,
  :address_fontsize   => 10.pt,
  :address_valign     => :center,

  # Info Block
  :info_block_x        => 125.mm,
  :info_block_y        => -45.mm,
  :info_block_width    => 75.mm,
  :info_block_height   => 40.mm,
  :info_block_fontsize => 9.pt,

  # Date
  :date_x        => 125.mm,
  :date_y        => -87.mm,
  :date_fontsize => 10.pt,

  # Subject
  :subject_x        => 25.mm,
  :subject_y        => - 105.mm + 2.mm,
  :subject_fontsize => 11.pt,
  :subject_style    => :bold,

  # Body
  :body_fontsize => 10.pt,
  :body_style    => nil,
  :body_preskip  => 105.mm - 30.mm + 6.mm,

  # Header
  :header_x      => 20.mm,
  :header_y      => 297.mm,
  :header_width  => 210.mm-30.mm,
  :header_height => 45.mm,

  # Footer
  :footer_x      => 20.mm,
  :footer_y      => 22.mm,
  :footer_width  => 210.mm-30.mm,
  :footer_height => 12.mm,

  # Page Numbering
  :page_numbering_string => "<page>/<total>",
  :page_numbering_x      => 180.mm,
  :page_numbering_y      => 26.mm,
  :page_numbering_width  => 10.mm,
  :page_numbering_align  => :right,
  :page_numbering_fontsize => 10.pt
}
LetterDefaults =
{
  :show_fold_tics           => true,
  :show_punch_tic           => true,
  :show_return_address_rule => true,
  :show_page_numbers        => true
}
InfoTranslations =
{
  :yoursign     => 'Ihr Zeichen',
  :yourmessage  => 'Ihre Nachricht vom',
  :oursign      => 'Unser Zeichen',
  :ourmessage   => 'Unsere Nachricht vom',
  :name         => 'Name',
  :phone        => 'Telefon',
  :fax          => 'Telefax',
  :email        => 'E-Mail',
  :date         => 'Datum'
}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.letter(pdf_or_filename, options = {}, &block) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'lib/dinbrief/letter.rb', line 7

def self.letter(pdf_or_filename, options={}, &block)
  case pdf_or_filename
  when Dinbrief::Letter
    make_letter(pdf_or_filename, &block)
    pdf_or_filename
  when Prawn::Document
    raise "Give an instance of Dinbrief::Letter to letter method."
  when String
    self.generate(pdf_or_filename, DocumentDefaults.merge(options)) do |pdf|
      make_letter(pdf, &block)
    end
  end
end

.make_letter(letter) {|letter.letter_builder| ... } ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
# File 'lib/dinbrief/letter.rb', line 21

def self.make_letter(letter, &block)
  yield(letter.letter_builder)
  letter.meta_header()
  letter.meta_footer()
  letter.methods.map(&:to_s).select{|m|m.start_with?("typeset_")}.each do |m|
    next if m=='typeset_body'
    letter.send(m)
  end
  letter.typeset_body
  letter.add_page_numbers
end

Instance Method Details

#add_page_numbersObject



33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/dinbrief/letter.rb', line 33

def add_page_numbers
  if show_page_numbers?
    number_pages page_numbering_string, {
      :start_count_at => 1,
      :page_filter    => :all, #[2..9999],
      :at             => [page_numbering_x, page_numbering_y],
      :align          => page_numbering_align,
      :size           => page_numbering_fontsize,
      :width          => page_numbering_width
    }
  end
end

#lb_get(nam) ⇒ Object



50
51
52
# File 'lib/dinbrief/letter.rb', line 50

def lb_get(nam)
  @letter_builder.instance_variable_get("@#{nam}")
end

#letter_builderObject



46
47
48
# File 'lib/dinbrief/letter.rb', line 46

def letter_builder()
  @letter_builder ||= LetterBuilder.new(self)
end

creates a footer bounding box on the bottom of the page and renders some dummy content. If a ‘footer’ method is implemented, it’s called, so you can easily define your own footer.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/dinbrief/letter/design_elements.rb', line 49

def meta_footer()
  bounding_box([footer_x, footer_y],
    :width => footer_width,
    :height => footer_height
  ) do |pdf|
    if self.respond_to? :footer
      footer()
    else
      line_width 0.1.pt
      stroke_bounds
      text_box(%{To replace this default footer by yours, just implement a 'footer' function in your Dinbrief::Letter subclass and draw whatever you like. There, you are inside this bordered box with [0,0] being the lower left corner.
        © 2011–#{Time.now.year} Peter Horn, metaminded UG},
        :at => [20.mm, 12.mm],
        :width => 140.mm,
        :align => :center,
        :size => 8.pt,
      )
    end
  end
end

#meta_headerObject

creates a header bounding box on the top of the page and renders some dummy content. If a ‘header’ method is implemented, it’s called, so you can easily define your own header.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/dinbrief/letter/design_elements.rb', line 10

def meta_header
  bounding_box([header_x, header_y],
    :width => header_width,
    :height => header_height
  ) do |pdf|
    if self.respond_to? :header
      header()
    else
      line_width 0.1.pt
      stroke_bounds
      text_box("DIN Brief Letter\na Ruby GEM for Prawn",
        :at => [0.mm, 35.mm],
        :size => 16.pt
      )
      draw_text("© 2011–#{Time.now.year} Peter Horn, metaminded UG",
        :at => [0.mm, 13.mm],
        :size => 10.pt
      )
      text_box(%{To replace this default header by yours,
        just implement a 'header' function in your Dinbrief::Letter
        subclass and draw whatever you like.
        There, you are inside this bordered box with [0,0] being
        the lower left corner.},
        :at => [85.mm, 35.mm],
        :width => 90.mm,
        :align => :left,
        :size => 10.pt,
        :font => "Times-Roman"

      )
    end
  end
end

#typeset_addressObject

typeset the recipients address



77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/dinbrief/letter/typeset_methods.rb', line 77

def typeset_address
  raise "An address should be given." unless lb_get(:address)
  bounding_box([address_x, address_y],
    :width => address_width,
    :height => address_height,
    :valign => address_valign,
  ) do
    text(lb_get(:address),
      :size => address_fontsize
    )
  end
end

#typeset_bodyObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/dinbrief/letter/typeset_methods.rb', line 99

def typeset_body
  gbody = lb_get(:body)
  raise "A body should be given." unless gbody
  move_cursor_to bounds.height
  move_down body_preskip
  if gbody.respond_to?(:call)
    font_size(body_fontsize)
    #font_style(body_style)
    gbody.call(self)
  else
    text(gbody.strip,
      :size => body_fontsize,
      :style => body_style
    )
  end
end

#typeset_infoObject

typeset info block (sign, name, phone…)



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/dinbrief/letter/typeset_methods.rb', line 7

def typeset_info
  bounding_box([info_block_x, info_block_y],
    :width => info_block_width,
    :height => info_block_height
  ) do
    #stroke_bounds
    i = lb_get(:info)
    case i
    when String
      text i, :size => info_block_fontsize
    when Proc
      i.(self)
    else
      info = [:yoursign, :yourmessage, :oursign, :ourmessage,
      :name, :phone, :fax, :email].map do |nam|
        iv = lb_get nam
        iv ? "#{InfoTranslations[nam]}: #{iv}" : nil
      end.compact.join("\n")
      return unless info
      text info,
        :size => info_block_fontsize
    end
  end
  date = lb_get(:date) || Time.now.strftime("%d.%m.%Y")
  text_box("#{InfoTranslations[:date]}: #{date}",
    :at => [date_x, date_y],
    :size => date_fontsize
  )
end

#typeset_marksObject

draw the fold- and punchmarks



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/dinbrief/letter/typeset_methods.rb', line 62

def typeset_marks
  line_width(0.2)
  if show_fold_tics?
    line([fold_mark_x, fold_mark_1_y], [fold_mark_x+fold_mark_width, fold_mark_1_y])
    line([fold_mark_x, fold_mark_2_y], [fold_mark_x+fold_mark_width, fold_mark_2_y])
  end
  if show_punch_tic?
    line([punch_mark_x, punch_mark_y], [punch_mark_x+punch_mark_width, punch_mark_y])
  end
  stroke
end

#typeset_return_addressObject

typeset rerturn address above address field



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/dinbrief/letter/typeset_methods.rb', line 40

def typeset_return_address
  return unless lb_get(:return_address)
  text_box(lb_get(:return_address),
    at:       [return_address_x, return_address_y],
    width:    return_address_width,
    height:   3.mm,
    size:     return_address_fontsize,
    align:    return_address_align,
    overflow: :shrink_to_fit,
  )
  return unless show_return_address_rule?
  line_width return_address_rule_linewidth
  line(
    [return_address_rule_x, return_address_rule_y],
    [return_address_rule_x + return_address_rule_width, return_address_rule_y]
  )
  stroke
end

#typeset_subjectObject



90
91
92
93
94
95
96
97
# File 'lib/dinbrief/letter/typeset_methods.rb', line 90

def typeset_subject
  return unless lb_get(:subject)
  text_box(lb_get(:subject),
    :at => [subject_x, subject_y],
    :size => subject_fontsize,
    :style => subject_style
  )
end