lib/reports/GanttChart.rb in taskjuggler-0.0.7 vs lib/reports/GanttChart.rb in taskjuggler-0.0.8
- old
+ new
@@ -196,13 +196,13 @@
td
end
# This is a noop function.
- def to_csv
+ def to_csv(csv, startColumn)
# Can't put a Gantt chart into a CSV file.
- ''
+ 0
end
# Utility function that convers a date to the corresponding X-position in
# the Gantt chart.
def dateToX(date)
@@ -238,53 +238,65 @@
def completeChart
@lines.each do |line|
@height = line.y + line.height if line.y + line.height > @height
end
+ # To layout the dependency lines, we use a GanttRouter. We only provide
+ # the start and end coordinates of each line and it will do the layout
+ # and routing.
@router = GanttRouter.new(@width, @height)
+ # We don't want horizontal lines to cross the task bars. So we block
+ # these chart zones. Milestones should not be crossed in any direction.
@lines.each do |line|
line.addBlockedZones(@router)
end
+ # Also protect the current date line from other vertical lines.
@router.addZone(@header.nowLineX - 1, 0, 3, @height - 1, false, true)
+ # Generate the dependency arrows for all visible tasks.
@tasks.each do |task, lines|
- generateDepArrows(task, lines)
+ generateDepLines(task, lines)
end
+
+ # Make sure we have exactly one arrow head for each line end point even
+ # if the point is used by multiple lines.
+ @depArrows.each do |line|
+ endPoint = line.last
+ @arrowHeads << endPoint unless @arrowHeads.include?(endPoint)
+ end
end
# Generate an output format independent description of the dependency lines
# for a specific _task_. _lines_ is a list of GanttLines that the tasks are
# displayed on. Reports with multiple scenarios have multiple lines per
# task.
- def generateDepArrows(task, lines)
+ def generateDepLines(task, lines)
# Since we need the line and the index we use an index iterator.
lines.length.times do |lineIndex|
line = lines[lineIndex]
scenarioIdx = line.query.scenarioIdx
# Generate the dependencies on the start of the task.
- collectAndSortArrows('startsuccs', task, scenarioIdx, lineIndex,
+ generateTaskDepLines('startsuccs', task, scenarioIdx, lineIndex,
*line.getTask.startDepLineStart)
# Generate the dependencies on the end of the task.
- collectAndSortArrows('endsuccs', task, scenarioIdx, lineIndex,
+ generateTaskDepLines('endsuccs', task, scenarioIdx, lineIndex,
*line.getTask.endDepLineStart)
end
end
# Generate the dependencies on the start or end of the task depending on
# _kind_. Use 'startsuccs' for the start and 'endsuccs' for end. _startX_
# and _startY_ are the graphic coordinates for the begin of the arrow
# line. _task_ references the Task in question and _scenarioIdx_ the
# scenario. _lineIndex_ specifies the line number in the chart.
- def collectAndSortArrows(kind, task, scenarioIdx, lineIndex, startX, startY)
- # We need to sort the arrows. This is an Array that holds 6 values for
- # each entry: The x and y coordinates for start and end points, the
- # sinus value of the angle between a vertical and the line specified by
- # the points and the length of the line.
+ def generateTaskDepLines(kind, task, scenarioIdx, lineIndex, startX, startY)
+ # This is an Array that holds 4 values for
+ # each entry: The x and y coordinates for start and end points.
touples = []
task[kind, scenarioIdx].each do |t, onEnd|
# Skip inherited dependencies and tasks that are not included in the
# chart.
if (t.parent &&
@@ -292,40 +304,12 @@
!@tasks.include?(t)
next
end
endX, endY = @tasks[t][lineIndex].getTask.send(
onEnd ? :endDepLineEnd : :startDepLineEnd)
- # To make sure that we minimize the crossings of arrows that
- # originate from the same position, we sort the arrows by the
- # smallest angle between the vertical line through the task end
- # and the line between the start and end of the arrow.
- oppLeg = endX - startX
- adjLeg = (startY - endY).abs
- hypothenuse = Math.sqrt(adjLeg ** 2 + oppLeg ** 2)
- # We can now calculate the sinus values of the angle between the
- # vertical and a line through the coordinates.
- touples << [ startX, startY, endX, endY,
- (oppLeg / hypothenuse), hypothenuse ]
+ touples << [ startX, startY, endX, endY ]
end
- # We sort the arrows from small to a large angle. In case the angle is
- # identical, we use the length of the line as second criteria.
- touples.sort! { |t1, t2| t1[4] == t2[4] ? t1[5] <=> t2[5] :
- t1[4] <=> t2[4] }
- touples.each do |t|
- routeArrow(*t[0, 4])
- end
- end
-
- # Route the dependency lines from the start to the end point.
- def routeArrow(startX, startY, endX, endY)
- @depArrows << @router.route([startX, startY], [endX, endY])
-
- # It's enough to have only a single arrow drawn at the end point even if
- # it's the destination of multiple lines.
- @arrowHeads.each do |x, y|
- return if x == endX && y == endY
- end
- @arrowHeads << [ endX, endY ]
+ @depArrows += @router.routeLines(touples) unless touples.empty?()
end
end
end