class PrawnCalendar::WeeklyCalendar

This Class represents a weekly calendar

Attributes

c_annotation_gutter[RW]

the gutter of calendar annotations

c_col_division[RW]

the number of divisions in calender columns this is to adjust the proportion of the first and the subsequent columns

for example c_col_division = 5 and c_first_col_division = 2 makes the first column width be 2/5 of the calender column width

c_date_end[RW]

the end of the interval

c_date_start[RW]

the start of the interval

c_days[RW]

An array with labels of the day. e.g. [“Mo”, “Di”, “Mi”, “Do”, “Fr”, “Sa”, “So”]

c_entry_fontsize[RW]

The fontsize of calendar entries

c_entry_gutter[RW]

The gutter of calendar entries

c_entry_radius[RW]

The radius of the calendar entries

c_entry_right_gutter[RW]

The right margin of calendar entries

c_extra_rows[RW]

The number of Rows shown in the calendar without time These rows are intended for additional comments

c_firstcol_division[RW]

the number of divisions in the first column the one showing the time

see [c_col_division] for more details.

c_fontsize[RW]

The font size of the calendar annotations

c_row_division[RW]

the number of divisions of the calenar rows. this finally determines the resolution of time shown in the calendar. Defaults to 4 which is (15 minutes)

c_time_end[RW]

the time where calendar display ends (defaults to 22)

c_time_start[RW]

the time where calendar display starts (defaults to 8)

pdf[RW]

the Prawn instance xxx

Public Class Methods

new(pdf) { |self| ... } click to toggle source

This is the constructor @param pdf [Prawn] The handle to prawn which renders the calendar @param &block [Proc] Code to change the initial configruation of the calendar.

@return [type] [description]

# File lib/prawn_calendar.rb, line 103
def initialize(pdf, &block)
  @pdf=pdf

  @c_annotation_gutter  = 2
  @c_col_division       = 5
  self.c_date_start=(Date.today.iso8601) # default to today.
  @c_days               = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"]
  @c_entry_fontsize     = 7
  @c_entry_gutter       = 0
  @c_entry_radius       = 2
  @c_entry_right_gutter = 2
  @c_extra_rows         = 1
  @c_firstcol_division  = 2
  @c_fontsize           = 8
  @c_row_division       = 4
  @c_time_end           = 22
  @c_time_start         = 8
  yield(self) if block_given?
end

Public Instance Methods

c_date_start=(day) click to toggle source

This is the write accessor to the attributre c_cate_start. Note that this adjusts the start date such that it comes to a monday and sets the end of the interval to the subseqent sunday

@param day [String] Iso 8601 form of the start date.

@return [type] [description]

# File lib/prawn_calendar.rb, line 85
def c_date_start=(day)
  # round to the beginning of the day.
  d = Date.iso8601(day)
  # note that we start the week on monday, therefore d -(d-1).wday
  # note that Date adds days, while Time adds seconds
  #
  # compute the beginning of the week
  @c_date_start = (d -(d-1).wday).to_time
  # set end to the last second of end date
  @c_date_end   = (@c_date_start.to_date + 7).to_time-1
end
cal_entry(starttime, endtime, text, extraargs={}) click to toggle source

This makes a calendar entry based on time.

Please note

  • it is not very robust yet

  • it only supports single day entries

  • entries are truncated if they do not fit into the range of hours in this case, the end time is added to the text

@param starttime [String] Starttime in iso8601 format @param endtime [String] Endtime in iso8601 format @param text [String] The text of calender entry @param extraargs [Hash] additional arguments

:recurring true/false

@return nil

# File lib/prawn_calendar.rb, line 176
def cal_entry(starttime, endtime, text, extraargs={})
  time_to_start = Time.iso8601(starttime).localtime
  time_to_end = Time.iso8601(endtime).localtime

  a= ((@c_date_start.to_time .. @c_date_end.to_time).cover?(time_to_start))
  puts "datum ausserhalb des Kalenders #{@c_date_start} < #{time_to_start} < #{@c_date_end} #{text}" if a==false

  hour_to_start = time_to_start.hour
  hour_to_end   = time_to_end.hour
  min_to_start  = time_to_start.min / (60/@c_row_division)
  min_to_end    = time_to_end.min / (60/@c_row_division)

  finaltext="<b>#{text}</b>"

  # handle the case that the entry is out of bounds
  # in this case it is drawn in the extra lines
  # an start/endtime is shown as extra tet
  extratext=nil



  # entry starts too early
  if (hour_to_start == 0) || (hour_to_start) < @c_time_start then
    extratext = true
    hour_to_start = @c_time_start-1
    min_to_start = 0
  end

  # entry ends too early
  if (hour_to_end == 0) || (hour_to_end) < @c_time_start then
    extratext=true
    hour_to_end= @c_time_start
    min_to_end = 0
  end

  # entry starts too late

  if (hour_to_start == 0) || (hour_to_start >= @c_time_end+1) then
    extratext = true
    hour_to_start = @c_time_end + 1
    min_to_start = 0
  end

  # entry ends too late
  if (hour_to_end == 0) || (hour_to_end >= @c_time_end+1) then
    extratext = true
    hour_to_end = @c_time_end + 2
    min_to_end = 0
  end

  if extratext then
    finaltext = finaltext + "<br><font size='#{@c_fontsize-2}'>#{time_to_start.strftime('%k.%M')} - #{time_to_end.strftime('%k.%M')}</font>"
  end




  starttime_s   = time_to_start.strftime("%k.%M")
  endtime_s     = time_to_end.strftime("%k.%M")

  text_to_show  = "#{starttime_s} - #{endtime_s}<br/>#{text}"
  text_to_show  = "#{finaltext}"

  day    = (time_to_start.wday + 6) % 7  # since we start on monday shift it one left
  column = @c_firstcol_division + day * @c_col_division

  srow = 2 * @c_row_division + (hour_to_start - @c_time_start) * @c_row_division + min_to_start
  erow = 2 * @c_row_division + (hour_to_end - @c_time_start) * @c_row_division -1 + min_to_end

  cal_entry_raw([srow, column], erow - srow, text_to_show, extraargs[:recurring])
end
cal_entry_raw(ll, length, text, recurring=false) click to toggle source

This creates a raw calendar entry based on grid coordinates

@param ll [Array] Left corner, see mk_entry for details. @param length [Integer] The number of grid rows covered by the entry @param text [String] The text of the calendar entry

@return nil

# File lib/prawn_calendar.rb, line 257
def cal_entry_raw(ll, length, text, recurring=false)
  width=4
  ur=[ll[0]+length, ll[1]+width]
  @pdf.grid(ll,ur).bounding_box do

    @pdf.fill_color "f0f0f0"

    @pdf.line_width 0.1


    # add one pixel to the borders to keep the entry away from the lines
    @pdf.rounded_rectangle([@c_entry_gutter+1, @pdf.bounds.height - @c_entry_gutter], # startpoint
                           @pdf.bounds.width  - 2 * @c_entry_gutter - @c_entry_right_gutter -2, # width
                           @pdf.bounds.height - 2 * @c_entry_gutter, # height
                           @c_entry_radius                 # radius
                           )
    @pdf.fill_and_stroke

    @pdf.fill_color "000000"

    if recurring==true then
      @pdf.text_box "(w)",
        :at    => [@pdf.bounds.width - 13,8],
        :width => 10,
        :size => 6
    end

    if recurring==true then
      @pdf.rounded_rectangle([@pdf.bounds.width  - 2, @c_entry_gutter], # startpoint
                             2 , # width
                             2 , # height
                             @c_entry_radius                 # radius
                             )
      @pdf.fill_and_stroke
    end



    # text is limited to gutter. Therefore gutter needs to be doubled
    # no limit at right and bottom
    excess_text = @pdf.text_box text,
      :at => [@c_entry_gutter +2, @pdf.bounds.height- 2*@c_entry_gutter-1], # need 1 pixel more a the top
      :width    => @pdf.bounds.width-4*@c_entry_gutter -2*@c_entry_right_gutter,
      :height   => @pdf.bounds.height-4*@c_entry_gutter,
      :overflow => :truncate,
      :kerning  => true,
      :inline_format => true,
      :size     => @c_entry_fontsize
  end
  nil
end
mk_calendar(ll, opts, &block) click to toggle source

Creates an empty calendar

@param ll [Array] the start point of the calendar

values are points, 0,0 is the lower left corner of the calender
see Prawn::Document.bounding_box for details

@param opts [Hash] [the options, keys: :width, :height] @param &block [Proc] The statements to fill the calendar.

@return [type] [description]

# File lib/prawn_calendar.rb, line 321
def mk_calendar(ll, opts, &block)
  @pdf.bounding_box(ll, width: opts[:width], height: opts[:height]) do
    @pdf.stroke_bounds
    rows       = (2 + @c_time_end - @c_time_start +1 + @c_extra_rows) * @c_row_division
    columns    = @c_firstcol_division + @c_days.count * @c_col_division

    @pdf.define_grid(:columns => columns, :rows => rows, :gutter => 0)

    # the frames
    @pdf.line_width 1
    mk_entry([0,0],
             [rows - 1, columns-1], "") # outer frame

    mk_entry([2 * @c_row_division, @c_firstcol_division],
             [rows - 1 , columns-1], "") # inner frame

    mk_entry([2 * @c_row_division, 0],
             [rows -1, @c_firstcol_division - 1], "") # left frame

    # the day - line
    row=0;col=@c_firstcol_division
    curday=@c_date_start.to_date

    @c_days.each do |i|

      columnhead="#{i} #{curday.strftime('%d.%m.')}"
      mk_entry([row,col], [row+@c_row_division-1, col+@c_col_division-1], columnhead)
      #require 'pry';binding.pry
      curday=curday+1
      col += @c_col_division
    end

    # the day after line
    row=@c_row_division; col=@c_firstcol_division
    @pdf.line_width 0.75
    @c_days.each do |i|
      mk_entry([row, col], [rows -1, col + @c_col_division - 1], "")
      col+=@c_col_division
    end

    #the  calendar fields
    @pdf.line_width "0.1"
    col=0;row=@c_row_division

    # the rows
    rowlabels=Array(@c_time_start .. @c_time_end).map{|i| "0#{i}.00"[-5..5]}

    a=[" ", rowlabels, [].fill(" ", 0, @c_extra_rows)]
    a.flatten.each do |i|

      # the first column
      # -1 bcause it denotes tha last filled cell, not the next unfilled one
      mk_entry([row,col],[row + @c_row_division - 1, col+@c_firstcol_division - 1], "#{i}")

      # the other columns
      icol=@c_firstcol_division
      (1..7).each do |i|
        mk_entry([row, icol], [row + @c_row_division -1, icol + @c_col_division - 1], " ")
        icol=icol + @c_col_division
      end
      row += @c_row_division
    end

    #yield the block
    instance_eval(&block)
  end
end
mk_entry(ll, rr, text) click to toggle source

This generates an entry in the calendar gird. Basically it is used for annotations.

Note that the coordinates are counter intuitive related to the usual positioning in pdf/prawn. While bounding_box is [horizontal, vertical] this stuff is [vertial, horizontal]

@param ll [Array] left point [row, column] in grid coordinates

[0,0] is the upper left corner
[0,1] is the second field in the first row.

@param rr [Array] end point [row, column] in grid coordinates

@param text [String] The string to be placed. It allows to use html formatting as far as supported by prawn.

@return nil

# File lib/prawn_calendar.rb, line 141
def mk_entry(ll, rr, text)
  @pdf.grid(ll, rr).bounding_box do

    @pdf.stroke_bounds
    excess_text = @pdf.text_box text,
      :at            => [@c_annotation_gutter, @pdf.bounds.height - @c_annotation_gutter],
      :width         => @pdf.bounds.width  - (2 * @c_annotation_gutter),
      :height        => @pdf.bounds.height - (2 * @c_annotation_gutter),
      :overflow      => :truncate,
      :kerning       => true,
      :inline_format => true,
      :size          => @c_fontsize
  end
  nil
end