package ImageSelector;

import java.awt.*;
import java.lang.*;
import java.util.*;

/** 
 * This class creates a canvas on which text can be displayed, similar to
 * a Label, but it allows the text to contain carriage returns and to span
 * several lines.<p>
 * 
 * Copyright (c) 1996, Tim DeBruine, Enterprise Integration Technologies,
 * Inc. All rights reserved.<p>
 *
 * RESTRICTED RIGHTS LEGEND: Use, duplication or disclosure by the 
 * Government is subject to restrictions as set forth in 
 * subparagraph(c)(1)(ii) of the Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 and in similar clauses in the
 * FAR and NASA FAR supplement.<p>
 * 
 * This software is bound by the terms and conditions listed in the
 * attached <a href="../LICENSE">LICENSE file</A>.
 * @author Tim DeBruine
 * @version 1.0
 */ 

public class TextDisplayCanvas extends Canvas {
  String title;
  String data;
  int width,height;
  final int gap=5;
  final int leftStart=3;
  
  /** sets the text to be displayed
   *@param s the text to be displayed
   */
  
  public void setText(String s) {data=s;}
  
  /** sets the title to be displayed above the text area
   *@param t the title
   */
  public void setTitle(String t) {title=t;}
  
  
  /** constructor
   *@param t the title to be displayed above the text area
   *@param w the width of the text area
   *@param h the height of the text area plus the height of the title
   */
  public TextDisplayCanvas(String t,int w,int h) {
    title=t;
    width=w;
    height=h;
  }

  public void paint(Graphics g) {
	
    FontMetrics fm;
    Color c;
		
    c=g.getColor();
    g.setColor(Color.lightGray);
    g.fillRect(0,0,width,height);
    g.setColor(c);
	
    // get font metrics to draw to
      fm=g.getFontMetrics();		
	
    graphics1.drawIndented3DRect(g,0,fm.getHeight()+gap,width-1,height-fm.getHeight()-gap-1);
    DrawMultiLineString(g,data,leftStart,gap+fm.getHeight(),width-leftStart-5,height-5-fm.getHeight());
    g.drawString(title,0,fm.getHeight());
  }	

  public Dimension minimumSize() {
    return new Dimension(width,height);
  }
	
  public Dimension preferredSize() {
    return minimumSize();
  }
	
  /** This method will break a string into several lines as needed to be displayed
   * onto a graphics object in an area set by the caller.
   *@param g the object to draw on
   *@param s the text
   *@param x the x coord of the upper left-hand-corner of the area in which to draw
   *@param y the y coord of the upper left-hand-corner of the area in which to draw
   *@param w the width of the area in which to draw
   *@param h the heigth of the area in which to draw
   */
  static void DrawMultiLineString(Graphics g,String s,int x,int y,
				  int w,int h) {
		
    FontMetrics fm;
    String currentLine;
    String word;
    String temp;
    Vector wordList;
    int drawy;
    int pos,total;
	
    // get font metrics
      fm=g.getFontMetrics();
		
    // start creating lines and displaying them until 
      // out of space to display or until source string is done
	pos=0;
    drawy=y+fm.getHeight();
		
    // create a vector of all the "words" in the string
      wordList=new Vector();
    makeList(s,wordList);
		
    pos=0;
    total=wordList.size();
		
    for (;;) {
      if (pos>=total || drawy>(y+h)) break;
			
      // build up a string
	currentLine="";
      for (;;) {
	if (pos>=total) break;
	if (wordList.elementAt(pos)=="\n") {
	  pos++;
	  break;
	}
	temp=currentLine+wordList.elementAt(pos);
	if (fm.stringWidth(temp)>w) break;
	pos++;
	currentLine=temp;
      }
			
      // print string
	g.drawString(currentLine,x,drawy);

      // advance down a line
	drawy+=fm.getHeight();
    }
  }
  /** makes a list from a string, consisting of words and carriage returns
   *@param s the string to parse
   *@param v the vector in which to put the list
   */	
  static public void makeList(String s,Vector v) {
    String temp;
    int pos;
    int len;
    int nextSpace;
    int nextNonSpace;
    int state;
		
		
    len=s.length();
    pos=0;
    state=1;
    temp="";
		
    for (;;) {
			
      // quit when we hit end of string
	if (pos==len) {
				
	  // if we were about to parse space, then we have not
	    // yet added the last word and we must do so
	      if (state==2) {
		specialAdd(v,temp);
	      }
	  break;
	}
			
      // next state decode
			
	switch (state) {
	case 1:			// beginning
			
	  // get next space and nonspace characters
	    nextSpace=findNextSpace(s,pos);
	  nextNonSpace=findNextNonSpace(s,pos);
				
	  // decide if we should parse a word or a space first
	    if (nextSpace==-1) state=3;
	    else if (nextNonSpace==-1) state=2;
	    else if (nextNonSpace<nextSpace) state=3;
	    else state=2;
				
	  break;
	case 2:			// parsing space
			
	  // find nextNonSpace, read in word
	    nextNonSpace=findNextNonSpace(s,pos);
				
	  if (nextNonSpace==-1) nextNonSpace=len;
	  temp=temp+s.substring(pos,nextNonSpace);

	  // add temp to vector
	    specialAdd(v,temp);
				
	  pos=nextNonSpace;
	  state=3;			
	  break;

	case 3:			// parsing word
			
	  // find nextSpace, read in word
	    nextSpace=findNextSpace(s,pos);
				
	  if (nextSpace==-1) nextSpace=len;
	  temp=s.substring(pos,nextSpace);
				
	  pos=nextSpace;
	  state=2;
	  break;
	}
    }
  }	

  /** finds the next occurrance of a space in a string
   *@param s the string
   *@param p the position at which to begin looking
   *@value the position, or -1 if not found
   */	
  static public int findNextSpace(String s,int p) {
    return s.indexOf(' ',p);
  }
	
  /** finds the next occurrance of a non-space character in a string
   *@param s the string
   *@param p the position at which to begin looking
   *@value the position, or -1 if not found
   */	
  static public int findNextNonSpace(String s,int p) {
    int i;
    int len;
		
    len=s.length();
		
    while (p<len) {
      if (s.charAt(p)!=' ') return p;
      p++;
    }		
    return -1;
  }
	
  public void forceRepaint() {
    paint(getGraphics());
  }
	
  static void specialAdd(Vector v,String s) {
    int pos;
    int next;
		
    pos=0;		
		
    for (;;) {
      if (pos>=s.length()) return;
      next=s.indexOf('\n',pos);
			
      if (next==-1) {
	v.addElement(s.substring(pos,s.length()));
	return;
      }
      else {
	v.addElement(s.substring(pos,next));
	v.addElement("\n");
	pos=next+1;
      }
    }
  }	
}


