//=====================================================================
// File:    TextPrinter.java
// Class:   TextPrinter
// Package: AFLPgui
//
// Author:  James J. Benham
// Date:    August 12, 1998
// Contact: james_benham@hmc.edu
//
// Genographer v1.0 - Computer assisted scoring of gels.
// Copyright (C) 1998  Montana State University
// 
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; version 2
// of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// The GNU General Public License is distributed in the file GPL
//=====================================================================

package AFLPgui;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.PrintJob;
import java.util.Vector;

/**
 * This class will take a printjob and a string and print that string
 * to the printer, wrapping lines that are to long and moving to a new
 * page when neccessary. It will also add a footer to the bottom of 
 * each page saying "Page i of totalNum".
 *
 * @see java.awt.PrintJob
 *
 * @author James J. Benham
 * @version 1.0.0
 * @date August 12, 1998
 */

public class TextPrinter
{
  private static final int H_BORDER = 36;
  private static final int V_BORDER = 33;

  private PrintJob printJob;
  /** The font to print in*/
  Font font;
  /** The header/footer to print on each page */
  String header;

  /** The margin on the top as well as the bottom*/
  int topMargin;
  /** The marin on the left and right of the page*/
  int leftMargin;
  /** The amount of extra space to leave for the footer*/
  int footerSpace;

  /**
   * Creates a new textprinter with a font of Sans Serif, 12pt.
   *
   * @param pJob  the printer job that will provide the graphics to print to
   */
  public TextPrinter(PrintJob pJob)
  {
    topMargin = 20;
    leftMargin = 20;
    footerSpace = 20;

    printJob = pJob;

    font = new Font("Sans Serif", Font.PLAIN, 12);
  }

  /**
   * Prints the given string to the destination of the print job given
   * in the constructor. If a line is to long, then it will be wrapped
   * by character, not by word. This means that words may be split.
   * It will also print a footer that gives the page number out of the
   * total pages.
   *
   * @param output  the text to print. Lines should be seperated with a
   *                '\n' character.
   * @param firstPage  the first page of the print job.
   */
  public void printString(String output, Graphics firstPage)
  {
    Vector lineIndicies = new Vector();
    char outChars[] = new char[output.length()];
    output.getChars(0, output.length() -1, outChars, 0);

    // Get the graphics to draw on
    Graphics pg = firstPage;
    pg.setFont(font);

    FontMetrics fm = pg.getFontMetrics();

    int lineHeight = fm.getHeight();
    footerSpace = lineHeight;

    int width = printJob.getPageDimension().width - 2*leftMargin - H_BORDER;
    int height = (printJob.getPageDimension().height - 2*topMargin -
            footerSpace - V_BORDER);

    int startChar;
    int endChar = -1;   // so start char ends up in right initial position
    int currentLineLength;
    int charIndex = 0;
    int currentPageLength;
    int numLines = 0;

    while(charIndex < outChars.length)
      {
     // set the beginning for this line
     startChar = endChar + 1;
     
     // check to see if we are on a new line, in which case we
     // want to skip over that charachter.
     if(outChars[charIndex] == '\n')
       {
         startChar++;  // don't want to include the '\n' char
         charIndex++;
       }
     
     // read in a line, which ends when we hit a line seperator or
     // run over the length;
     currentLineLength = 0;
     while( (charIndex < outChars.length) && 
            (outChars[charIndex] != '\n') &&
            (currentLineLength < width))
       {
         currentLineLength += fm.charWidth(outChars[charIndex]);
         charIndex++;
       }
     
     // and set the end
     endChar = charIndex;
     // check to see if it caused the loop termination, in
     // which case, set it back. 
     if(endChar == outChars.length)
       endChar--;

     // Remove the end of line symbol for the list
     if(outChars[endChar] == '\n')
         endChar--;

     lineIndicies.addElement(new Integer(startChar));
     lineIndicies.addElement(new Integer(endChar));

     numLines++;
      }

    // figure out how many pages we have
    int numPages = (int) Math.ceil((double) numLines*lineHeight/height);
    int linesPerPage = height/lineHeight;
    int currentLine = 0;

    for(int i=0; i < numPages; i++)
      {
     int length = currentLine + linesPerPage;
     for(int j=currentLine; j < length; j++)
       {
         if(j < numLines)
           {
          startChar = ((Integer) 
                    lineIndicies.elementAt(2*j)).intValue();
          endChar = ((Integer)
                  lineIndicies.elementAt(2*j + 1)).intValue();
          // add one to y, since this specifies the baseline
          pg.drawChars(outChars, startChar, endChar - startChar + 1,
                    leftMargin,
                    (j - i*linesPerPage + 1)*lineHeight);
           }
       }

     // Draw the footer.
     pg.drawString("Page " + (i + 1) + " of " + numPages, 
                leftMargin, height + footerSpace);
       
     // get the next page
     pg.dispose();
     currentLine += linesPerPage;

     // Don't fetch an extra page.
     if(i < (numPages - 1))
       {
         pg = printJob.getGraphics();
         pg.setFont(font);
       }
     else
       System.out.println("Page not fetched.");
      }
  }
}
