2011年10月14日

PDFガントチャートに縦線を.改良onRedmine1.2.0

※タイトル少し変えました

RedmineのガントチャートをPDF出力したときに,日付単位に縦線を入れる修正は,自分の環境(redmine1.2.0)では,ちょっと問題があって,1月分なら期待通りに表示されるのですが,2ヶ月以上の表示となると線の位置と数がおかしくなってうまく行ってませんでした.

参考:以前のブログ「ガントチャート日付表示 on Redmine-1.2.0」


僕は,基本的に月単位の報告にしか使用しないので,この問題は放っておいたのですが(ごめんなさい),先日コメントで問い合わせをいただきましてちょっと気になってはいました.
また,最近,数カ月単位でスケジュールを報告する機会が出てきて,その時に改めてこりゃひどいなと思ったので今週改めてソースを眺めました.

例えば,3ヶ月以上だと,曜日の表示はされないのですが,縦線は曜日間隔で引かれてしまうため,不要な非常に見づらくなります.(やたらと縦線ばかり引かれたガントチャートになります.)


今週,眺めてて,原因が分かったので,「ガントチャートを2ヶ月出力したPDF」でも縦線が入るように修正しました.
ついでに,3ヶ月以上つまり,日付け単位の表示ではなく,週単位表示の場合には週単位で縦線を引くように修正しました.

月単位表示の時には対応していないので週単位で表示されてしまうかと思います.と思ったけど,ここまでブログで書いてたら,不完全さが気になって,というか悔しくなって,対応しました.


■Redmine 1.2.0用のパッチ(for lib/redmine/helper/gantt.rb)

gantt_diff


■Redmine 1.2.0用の変更したファイル (for lib/redmine/helper/gantt.rb)


gantt_modfile




ご利用は自己責任で :)


あと,redmine_better_gantt_chart プラグインはこの修正をマージするのが面倒で入れていませんでしたが(以前,ガントチャートがうまく動かなくなったときに疑って外したままなのです...),最新のソースコードを見たら,マージできそうだったのでやってみました.こちらもうまく行ったと思います.

■better_gantt_chart 向けパッチ
(for redmine_better_gantt_chart/lib/redmine/helpers/better_gantt.rb)


better_gantt_diff



■better_gantt_chart 変更ソース
(for redmine_better_gantt_chart/lib/redmine/helpers/better_gantt.rb)

better_gantt_modfile




また,問題あったら対応するかもしれません.

better_gantt_chart の矢印線はいいのですけど,PDFでは出せないんですよね.
改ページの時にどのような対応をすれば良いのか仕様が難しいですし.(作者の方が言ってた気がします.)



最後に,DIFFファイルも載せておきます.

redmine/lib/redmine/helpers/gantt.rb


--- org\gantt.rb 2011-05-30 18:47:30.000000000 +0900
+++ mod\gantt.rb 2011-10-14 19:22:56.164506500 +0900
@@ -1,3 +1,4 @@
+# -*- coding: cp932 -*-
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
#
@@ -254,9 +255,68 @@
case options[:format]
when :pdf
options[:pdf].Line(15, options[:top], PDF::TotalWidth, options[:top])
+ vertical_line_pdf(options)
end
end

+ # --------------------------vertical line.start
+ def vertical_line_pdf(options)
+ left = options[:subject_width]
+ day = 0
+ options[:pdf].SetFontStyle('B',7)
+ width = options[:zoom]
+ options[:pdf].SetDrawColor(200,200,200)
+ if options[:show_weeks]
+ if options[:show_days]
+ (self.date_to - self.date_from).to_i.times do
+ leftwidth = (left + width/2 ).to_i
+ options[:pdf].SetY(options[:top_start].to_i)
+ options[:pdf].SetX(left)
+ if Time.now.beginning_of_day == self.date_from.since(day.days)
+ options[:pdf].SetDrawColor(255, 0, 0)
+ options[:pdf].RDMCell(width, options[:top].to_i - options[:top_start].to_i, "", "R", 0, "C")
+ options[:pdf].SetDrawColor(200,200,200)
+ else
+ options[:pdf].RDMCell(width, options[:top].to_i - options[:top_start].to_i, "", "R", 0, "C")
+ end
+ left = left + width
+ day = day + 1
+ end
+ else
+ if self.date_from.cwday == 1
+ # self.date_from is monday
+ week_f = self.date_from
+ else
+ # find next monday after self.date_from
+ week_f = self.date_from + (7 - self.date_from.cwday + 1)
+ width = (self.date_to - week_f + 1) * options[:zoom] -1
+ left = left + (7 - self.date_from.cwday + options[:zoom])
+ end
+ while week_f <= self.date_to
+ width = (week_f + 6 <= self.date_to) ? 7 * options[:zoom] : (self.date_to - week_f + 1) * options[:zoom]
+ options[:pdf].SetY(options[:top_start].to_i)
+ options[:pdf].SetX(left)
+ options[:pdf].RDMCell(width, options[:top].to_i - options[:top_start].to_i, "", "LTR", 0, "C")
+ left = left + width
+ week_f = week_f + 7
+ end
+ end
+ else
+ month_f = self.date_from
+ left = options[:subject_width]
+ self.months.times do
+ width = ((month_f >> 1) - month_f).to_i * options[:zoom]
+ options[:pdf].SetY(options[:top_start].to_i)
+ options[:pdf].SetX(left)
+ options[:pdf].RDMCell(width, options[:top].to_i - options[:top_start].to_i, "", "LTR", 0, "C")
+ left = left + width
+ month_f = (month_f >> 1)
+ end
+ end
+ options[:pdf].SetDrawColor(0, 0, 0)
+ end
+ # --------------------------vertical line.end
+
def subject_for_project(project, options)
case options[:format]
when :html
@@ -410,6 +470,9 @@
imgl.new_image(subject_width+g_width+1, height)
gc = Magick::Draw.new

+ #gc.font = "c:\\WINDOWS\Fonts\VL-Gothic-Regular.ttf"
+ gc.font = "C:\\WINDWS\\FONTS\\MSGOTHIC.TTC" #和文フォントの指定
+ gc.pointsize = 12
# Subjects
gc.stroke('transparent')
subjects(:image => gc, :top => (headers_height + 20), :indent => 4, :format => :image)
@@ -465,19 +528,19 @@

# Days details (week-end in grey)
if show_days
- left = subject_width
- height = g_height + header_height - 1
- wday = @date_from.cwday
- (date_to - @date_from + 1).to_i.times do
- width = zoom
- gc.fill(wday == 6 || wday == 7 ? '#eee' : 'white')
- gc.stroke('#ddd')
- gc.stroke_width(1)
- gc.rectangle(left, 2*header_height, left + width, 2*header_height + g_height-1)
- left = left + width
- wday = wday + 1
- wday = 1 if wday > 7
- end
+ left = subject_width
+ height = g_height + header_height - 1
+ wday = @date_from.cwday
+ (date_to - @date_from + 1).to_i.times do
+ width = zoom
+ gc.fill(wday == 6 || wday == 7 ? '#eee' : 'white')
+ gc.stroke('#ddd')
+ gc.stroke_width(1)
+ gc.rectangle(left, 2*header_height, left + width, 2*header_height + g_height-1)
+ left = left + width
+ wday = wday + 1
+ wday = 1 if wday > 7
+ end
end

# border
@@ -524,13 +587,16 @@
headers_height = header_height
show_weeks = false
show_days = false
+ show_day_num = false # <= 追加

if self.months < 7
show_weeks = true
headers_height = 2*header_height
if self.months < 3
show_days = true
- headers_height = 3*header_height
+ show_day_num = true
+ #headers_height = 3*header_height
+ headers_height = 4*header_height
end
end

@@ -551,7 +617,7 @@
pdf.SetX(left)
pdf.RDMCell(width, height, "#{month_f.year}-#{month_f.month}", "LTR", 0, "C")
left = left + width
- month_f = month_f >> 1
+ month_f = ( month_f >> 1 )
end

# Weeks headers
@@ -590,6 +656,14 @@
width = zoom
pdf.SetY(y_start + 2 * header_height)
pdf.SetX(left)
+ case(wday)
+ when 6
+ pdf.SetTextColor(0, 0, 255)
+ when 7
+ pdf.SetTextColor(255, 0, 0)
+ else
+ pdf.SetTextColor(0, 0, 0)
+ end
pdf.RDMCell(width, height, day_name(wday).first, "LTR", 0, "C")
left = left + width
wday = wday + 1
@@ -597,12 +671,49 @@
end
end

+
+ # Day num headers
+ if show_day_num # num
+ left = subject_width
+ height = header_height
+ wday = self.date_from.cwday
+ day_num = self.date_from
+ pdf.SetFontStyle('B',7)
+ (self.date_to - self.date_from + 1).to_i.times do
+ width = zoom
+ pdf.SetY(y_start + 3 * header_height)
+ pdf.SetX(left)
+ case(wday)
+ when 6
+ pdf.SetTextColor(0, 0, 255)
+ when 7
+ pdf.SetTextColor(255, 0, 0)
+ else
+ pdf.SetTextColor(0, 0, 0)
+ end
+ pdf.RDMCell(width, height, day_num.day.to_s, "LTR", 0, "C")
+ left = left + width
+ day_num = day_num + 1
+ wday = wday + 1
+ wday = 1 if wday > 7
+ end
+ end
+
pdf.SetY(y_start)
pdf.SetX(15)
+ case(wday)
+ when 6
+ pdf.SetTextColor(0, 0, 255)
+ when 7
+ pdf.SetTextColor(255, 0, 0)
+ else
+ pdf.SetTextColor(0, 0, 0)
+ end
pdf.RDMCell(subject_width+g_width-15, headers_height, "", 1)

# Tasks
top = headers_height + y_start
+ pdf.SetTextColor(0, 0, 0)
options = {
:top => top,
:zoom => zoom,
@@ -612,6 +723,9 @@
:indent_increment => 5,
:top_increment => 5,
:format => :pdf,
+ :top_start => top,
+ :show_weeks => show_weeks,
+ :show_days => show_days,
:pdf => pdf
}
render(options)
@@ -699,8 +813,10 @@
def pdf_new_page?(options)
if options[:top] > 180
options[:pdf].Line(15, options[:top], PDF::TotalWidth, options[:top])
+ vertical_line_pdf(options)
options[:pdf].AddPage("L")
- options[:top] = 15
+ #options[:top] = 15
+ options[:top] = options[:top_start] = 15
options[:pdf].Line(15, options[:top] - 0.1, PDF::TotalWidth, options[:top] - 0.1)
end
end




■redmine_better_gantt_chart/lib/redmine/helpers/better_gantt.rb


--- org\better_gantt.rb 2011-09-07 05:58:22.000000000 +0900
+++ mod\better_gantt.rb 2011-10-14 19:22:08.787990500 +0900
@@ -1,3 +1,4 @@
+# -*- coding: cp932 -*-
# Redmine - project management software
# Copyright (C) 2006-2011 Jean-Philippe Lang
#
@@ -255,9 +256,68 @@
case options[:format]
when :pdf
options[:pdf].Line(15, options[:top], PDF::TotalWidth, options[:top])
+ vertical_line_pdf(options)
end
end

+ # --------------------------vertical line.start
+ def vertical_line_pdf(options)
+ left = options[:subject_width]
+ day = 0
+ options[:pdf].SetFontStyle('B',7)
+ width = options[:zoom]
+ options[:pdf].SetDrawColor(200,200,200)
+ if options[:show_weeks]
+ if options[:show_days]
+ (self.date_to - self.date_from).to_i.times do
+ leftwidth = (left + width/2 ).to_i
+ options[:pdf].SetY(options[:top_start].to_i)
+ options[:pdf].SetX(left)
+ if Time.now.beginning_of_day == self.date_from.since(day.days)
+ options[:pdf].SetDrawColor(255, 0, 0)
+ options[:pdf].RDMCell(width, options[:top].to_i - options[:top_start].to_i, "", "R", 0, "C")
+ options[:pdf].SetDrawColor(200,200,200)
+ else
+ options[:pdf].RDMCell(width, options[:top].to_i - options[:top_start].to_i, "", "R", 0, "C")
+ end
+ left = left + width
+ day = day + 1
+ end
+ else
+ if self.date_from.cwday == 1
+ # self.date_from is monday
+ week_f = self.date_from
+ else
+ # find next monday after self.date_from
+ week_f = self.date_from + (7 - self.date_from.cwday + 1)
+ width = (self.date_to - week_f + 1) * options[:zoom] -1
+ left = left + (7 - self.date_from.cwday + options[:zoom])
+ end
+ while week_f <= self.date_to
+ width = (week_f + 6 <= self.date_to) ? 7 * options[:zoom] : (self.date_to - week_f + 1) * options[:zoom]
+ options[:pdf].SetY(options[:top_start].to_i)
+ options[:pdf].SetX(left)
+ options[:pdf].RDMCell(width, options[:top].to_i - options[:top_start].to_i, "", "LTR", 0, "C")
+ left = left + width
+ week_f = week_f + 7
+ end
+ end
+ else
+ month_f = self.date_from
+ left = options[:subject_width]
+ self.months.times do
+ width = ((month_f >> 1) - month_f).to_i * options[:zoom]
+ options[:pdf].SetY(options[:top_start].to_i)
+ options[:pdf].SetX(left)
+ options[:pdf].RDMCell(width, options[:top].to_i - options[:top_start].to_i, "", "LTR", 0, "C")
+ left = left + width
+ month_f = (month_f >> 1)
+ end
+ end
+ options[:pdf].SetDrawColor(0, 0, 0)
+ end
+ # --------------------------vertical line.end
+
def subject_for_project(project, options)
case options[:format]
when :html
@@ -540,13 +600,15 @@
headers_height = header_height
show_weeks = false
show_days = false
-
+ show_day_num = false # <= 追加
+
if self.months < 7
show_weeks = true
headers_height = 2*header_height
if self.months < 3
show_days = true
- headers_height = 3*header_height
+ #headers_height = 3*header_height
+ headers_height = 4*header_height
end
end

@@ -606,6 +668,14 @@
width = zoom
pdf.SetY(y_start + 2 * header_height)
pdf.SetX(left)
+ case(wday)
+ when 6
+ pdf.SetTextColor(0, 0, 255)
+ when 7
+ pdf.SetTextColor(255, 0, 0)
+ else
+ pdf.SetTextColor(0, 0, 0)
+ end
pdf.RDMCell(width, height, day_name(wday).first, "LTR", 0, "C")
left = left + width
wday = wday + 1
@@ -613,12 +683,48 @@
end
end

+ # Day num headers
+ if show_day_num # num
+ left = subject_width
+ height = header_height
+ wday = self.date_from.cwday
+ day_num = self.date_from
+ pdf.SetFontStyle('B',7)
+ (self.date_to - self.date_from + 1).to_i.times do
+ width = zoom
+ pdf.SetY(y_start + 3 * header_height)
+ pdf.SetX(left)
+ case(wday)
+ when 6
+ pdf.SetTextColor(0, 0, 255)
+ when 7
+ pdf.SetTextColor(255, 0, 0)
+ else
+ pdf.SetTextColor(0, 0, 0)
+ end
+ pdf.RDMCell(width, height, day_num.day.to_s, "LTR", 0, "C")
+ left = left + width
+ day_num = day_num + 1
+ wday = wday + 1
+ wday = 1 if wday > 7
+ end
+ end
+
pdf.SetY(y_start)
pdf.SetX(15)
+ case(wday)
+ when 6
+ pdf.SetTextColor(0, 0, 255)
+ when 7
+ pdf.SetTextColor(255, 0, 0)
+ else
+ pdf.SetTextColor(0, 0, 0)
+ end
pdf.RDMCell(subject_width+g_width-15, headers_height, "", 1)

# Tasks
top = headers_height + y_start
+ pdf.SetTextColor(0, 0, 0)
options = {
:top => top,
:zoom => zoom,
@@ -628,6 +734,9 @@
:indent_increment => 5,
:top_increment => 5,
:format => :pdf,
+ :top_start => top,
+ :show_weeks => show_weeks,
+ :show_days => show_days,
:pdf => pdf
}
render(options)
@@ -715,8 +824,10 @@
def pdf_new_page?(options)
if options[:top] > 180
options[:pdf].Line(15, options[:top], PDF::TotalWidth, options[:top])
+ vertical_line_pdf(options)
options[:pdf].AddPage("L")
- options[:top] = 15
+ #options[:top] = 15
+ options[:top] = options[:top_start] = 15
options[:pdf].Line(15, options[:top] - 0.1, PDF::TotalWidth, options[:top] - 0.1)
end
end

posted by maplewine at 19:50| Comment(0) | TrackBack(0) | ruby | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック