#!/usr/bin/env ruby -w
# encoding: UTF-8
#
# = ReportTableLegend.rb -- The TaskJuggler III Project Management Software
#
# Copyright (c) 2006, 2007, 2008, 2009, 2010, 2011, 2012
#               by Chris Schlaeger <chris@linux.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#

class TaskJuggler

  # The ReportTableLegend models an output format independent legend for the
  # ReportTable. It lists the graphical symbols used in the table together with
  # a short textual description.
  class ReportTableLegend

    attr_accessor :showGanttItems

    # Create a new ReportTableLegend object.
    def initialize
      @showGanttItems = false
      @ganttItems = []
      @calendarItems = []
    end

    # Add another Gantt item to the legend. Make sure we don't have any
    # duplicates.
    def addGanttItem(text, color)
      @ganttItems << [ text, color ] unless @ganttItems.include?([ text, color ])
    end

    # Add another chart item to the legend. Make sure we don't have any
    # duplicates.
    def addCalendarItem(text, color)
      unless @calendarItems.include?([ text, color ])
        @calendarItems << [ text, color ]
      end
    end

    # Convert the abstract description into HTML elements.
    def to_html
      return nil if !@showGanttItems && @ganttItems.empty? &&
                    @calendarItems.empty?

      frame = XMLElement.new('div', 'class' => 'tj_table_legend_frame')
      frame << (legend = XMLElement.new('table', 'class' => 'tj_table_legend',
                                                 'cellspacing' => '1'))

      legend << headlineToHTML('Gantt Chart Symbols:')
      # Generate the Gantt chart symbols
      if @showGanttItems
        legend << (row = XMLElement.new('tr', 'class' => 'tj_legend_row'))

        row << ganttItemToHTML(GanttContainer.new(15, 10, 35, 0),
                               'Container Task', 40)
        row << ganttItemToHTML(GanttTaskBar.new(nil, 15, 5, 35, 0),
                               'Normal Task', 40)
        row << ganttItemToHTML(GanttMilestone.new(15, 10, 0), 'Milestone', 20)
        row << XMLElement.new('td', 'class' => 'tj_legend_spacer')
      end

      legend << itemsToHTML(@ganttItems)

      legend << headlineToHTML('Calendar Symbols:')
      legend << itemsToHTML(@calendarItems)

      frame
    end

  private

    # In case we have both the calendar and the Gantt chart in the report
    # element, we have to add description lines before the symbols. The two
    # charts use the same colors for different meanings. This function generates
    # the HTML version of the headlines.
    def headlineToHTML(text)
      unless @calendarItems.empty? || @ganttItems.empty?
        div = XMLElement.new('tr', 'class' => 'tj_legend_headline')
        div << XMLNamedText.new(text, 'td', 'colspan' => '10')
        return div
      end
      nil
    end

    # Turn the Gantt symbold descriptions into HTML elements.
    def ganttItemToHTML(itemRef, name, width)
      cells = []
      # Empty cell for margin first.
      cells << (item = XMLElement.new('td', 'class' => 'tj_legend_spacer'))
      # The symbol cell
      cells << (item = XMLElement.new('td', 'class' => 'tj_legend_item'))
      item << (symbol = XMLElement.new('div', 'class' => 'tj_legend_symbol',
                                       'style' => 'top:3px'))
      symbol << itemRef.to_html
      # The label cell
      cells << (item = XMLElement.new('td', 'class' => 'tj_legend_item'))
      item << (label = XMLElement.new('div', 'class' => 'tj_legend_label'))
      label << XMLText.new(name)

      cells
    end

    # Turn a single color item into HTML elements.
    def itemToHTML(itemRef)
      cells = []
      # Empty cell for margin first.
      cells << XMLElement.new('td', 'class' => 'tj_legend_spacer')
      # The symbol cell
      cells << (item = XMLElement.new('td', 'class' => 'tj_legend_item'))
      item << (symbol = XMLElement.new('div', 'class' => 'tj_legend_symbol'))
      symbol << (box = XMLElement.new('div',
                                      'style' => 'position:relative; ' +
                                                 'top:2px;' +
                                                 'width:20px; height:15px'))
      box << (div = XMLElement.new('div', 'class' => 'loadstackframe',
                                   'style' => 'position:absolute; ' +
                                   'left:5px; width:16px; height:15px;'))
      div << XMLElement.new('div', 'class' => "#{itemRef[1]}",
                            'style' => 'position:absolute; ' +
                                       'left:1px; top:1px; ' +
                                       'width:14px; height:13px;')
      # The label cell
      cells << (item = XMLElement.new('td', 'class' => 'tj_legend_item'))
      item << (label = XMLElement.new('div', 'class' => 'tj_legend_label'))
      label << XMLText.new(itemRef[0])

      cells
    end

    # Turn the color items into HTML elements.
    def itemsToHTML(items)
      rows = []
      row = nil
      gridCells = ((items.length / 3) + (items.length % 3 != 0 ? 1 : 0)) * 3
      gridCells.times do |i|
        # We show no more than 3 items in a row.
        if i % 3 == 0
          rows << (row = XMLElement.new('tr', 'class' => 'tj_legend_row'))
        end

        # If we run out of items before the line is filled, we just insert
        # empty cells to fill the line.
        if i < items.length
          row << itemToHTML(items[i])
        else
          row << XMLElement.new('td', 'class' => 'tj_legend_item',
                                      'colspan' => '3')
        end
        if (i + 1) % 3 == 0
          # Append an empty cell at the end of each row.
          row << XMLElement.new('td', 'class' => 'tj_legend_spacer')
        end
      end
      rows
    end

  end

end

