2012年8月19日日曜日

【Redmine】ガントチャートpdf出力拡張 vol.1 日付表示を見やすく

目的
ガントチャートpdf出力表示にて、
日付単位の表示が曜日になっているのを日付に変更、
日付毎に縦線を引き、
土日の文字色、背景色を変更する。
また、項目毎に横線を引く。


作業手順
app\controllers\gantts_controller.rbを見ると、
45行目に、format.pdf ...とあり、
ヘルパーであるganttのto_pdfメソッドを呼び出している。
これがpdfファイル作成処理のようだ。

apps\redmine\htdocs\lib\redmine\helper\gantt.rbを見ると、
to_pdfメソッドがあるので解析。
to_pdfメソッド内では、月単位、週単位、日付単位のヘッダを描画、
renderメソッドにて、
以降のチケットの進捗度部分を作成していることが分かった。

まずは、to_pdf内を変更し、
日付単位の曜日表示を日付表示に変更する。

587行目、
wday = self.date_from.cwday
にて、表示曜日の初期値設定を行っているが。
次の行に表示日付の初期値設定を追加する。
date = self.date_from
 
次に、(上記変更により)594行目、
pdf.RDMCell(width, height, day_name(wday).first, "LTR", 0, "C")
にて、曜日名を表示しているが、日付に変更するため、
pdf.RDMCell(width, height, date.day.to_s, "LTR", 0, "C")
に変更。


次に、(上記変更により)596、597行目、
wday = wday + 1
wday = 1 if wday > 7
にて、表示曜日の更新処理を行っているが、 
その次の行に、表示日付の更新処理を追加する。
date = date + 1
これで曜日から日付への変更が完了。


次に、土日の文字色の変更。
(上記変更により)591行目の下に、
以下の処理を追加。
case(wday)
when 6
  pdf.SetTextColor(0, 0, 255)
when 7
  pdf.SetTextColor(255, 0, 0)
else
  pdf.SetTextColor(0, 0, 0)
end

繰り返しを抜けた箇所に、
文字色を戻すため、以下を追加して完了。

pdf.SetTextColor(0, 0, 0)



次に、縦線を引く。
そのためには、
各プロジェクト、バージョン、イシュー毎の
描画描画処理を行っている箇所を解析する必要がある。
renderメソッドを見ていく。

renderメソッドでは、プロジェクトツリーに従い、
各プロジェクト毎にrender_projectメソッドを呼び出している。

render_projectメソッドでは、
まず、subject_for_projectメソッド、line_for_projectメソッドを呼び出し、
プロジェクトの項目名、 進捗度の描画を行っている。

次にバージョンに含まれないイシューの描画のため、
render_issuesメソッド内で各イシュー毎に
subject_for_issueメソッド、line_for_issueメソッドを呼び出し、
イシューの項目名、進捗度の描画を行っている。

次にバージョンのため、
render_versionメソッド内で各バージョン毎に
subject_for_versionメソッド、line_for_versionメソッドを呼び出し、
バージョンの項目名、ラインの描画を行ってい、
バージョンに含まれるイシュー毎に、
render_issuesメソッドを呼び出している。

line_for_xxxメソッド(xxxはワイルドカード)にて、
ヘッダー描画時の日付毎の縦線描画処理を入れることで
容易に対処できそうなので、
line_for_xxxメソッド内に処理を追加する。

しかし、subject_for_xxxメソッドでは、
各項目の外枠を描画しているようなので、
後に回すことで日付毎の線を色を変えて引く際に
端かどうか判定してする必要も無くなる。

ということで、
まずは、line_for_xxxメソッド内に当該処理を追加する。
対象となるメソッドはline_for_projects、line_for_version、line_for_issueである。
各メソッドの先頭に処理を追加する。
追加処理はpdf出力時しか使用しないので、
条件式で括っておく。 必要な値は全てoptions内に含まれるため、
引数はoptionsとし、以下の処理を追加する。(※line_for_projectの場合。)
if project.is_a?(Project) && options[:format] == :pdf
  render_day_separator(options)
end

project.is_a?(Project)は以降の処理に含まれているものであるため、
とりあえず追加している。
この処理はline_for_xxxメソッドによって変更する必要がある。

次に、render_day_separator内で、
日付表示だった場合に描画を行うため、
optionsに日付表示フラグを追加する必要がある。
そのため、to_pdfメソッドでoptionsにshow_daysを追加する。
617行目、
options = {
  :top => top,
  :zoom => zoom,
  :subject_width => subject_width,
  :g_width => g_width,
  :indent => 0,
  :indent_increment => 5,
  :top_increment => 5,
  :format => :pdf,
  :pdf => pdf
}
 に、:show_days => show_daysを追加。
options = {
  :top => top,
  :zoom => zoom,
  :subject_width => subject_width,
  :g_width => g_width,
  :show_days => show_days,
  :indent => 0,
  :indent_increment => 5,
  :top_increment => 5,
  :format => :pdf,
  :pdf => pdf
}

render_day_separatorメソッドに関しては、
少し長いのでソースコードを参照してほしい。
こちらに背景色の変更処理も含まれている。
コメントで土日の背景色設定と書かれている処理がそれにあたる。



次に、subject_for_xxxメソッドとline_for_xxxメソッドの処理順を入れ替える。
その際に、subject_for_xxxメソッド内にある、
pdf_new_page?メソッドをline_for_xxxメソッド内に移動する必要がある。
作業としては、上記追加箇所に追加するだけで良い。

if project.is_a?(Project) && options[:format] == :pdf
  pdf_new_page?(options)
  render_day_separator(options)
end
長かったので、ソースコードを見て、
各自確認をしてもらえればと思う。


変更前、変更後のソースコードは以下にアップされている。
『日付表示を見やすく 』のフォルダにある。

ソースコード



結果
大分見やすくなったはず。
ただ、バーのゲージや端、マイルストンの位置がずれているように見える。
次回、原因を調査する。









0 件のコメント:

コメントを投稿