package jas.plot; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; import javax.swing.JPopupMenu; /** * TextBlock is the base class for creating moveable text boxes in the jas display. */ public abstract class TextBlock extends MovableObject { public TextBlock(String prefix) { super(prefix); setBorderType(LINE); setFont(new Font("SansSerif",Font.PLAIN,10)); } /**When implemented, getNLines() should return an integer count of the * number of lines of text to be displayed in the text block. */ public abstract int getNLines(); /**When implemented, getLine(int n) should return a String corresponding to the nth * text line to be displayed in the text block. */ public abstract String getLine(int n); /**When implemented, getSplitStringAlignment() should return an integer between 1 and 3 * corresponding to the chosen alignment for the second half of strings split by '\t'. * For leftalignment: return 1. For rightaignment: return 2. For noalignment: return 3. * */ public abstract int getSplitStringAlign(); /**Sets the horizontal and vertical dimensions of the text block. */ public Dimension getPreferredSize() { if (fm == null) fm = getToolkit().getFontMetrics(getFont()); allocateSize(); Insets i = getInsets(); return new Dimension(blockwidth+i.right+i.left,i.top+i.bottom+blockheight); } /**Draws each line of text in the text block. If "\n" is returned by getLine() a * seperator line will be drawn in the block. All other strings are formatted by * formatLine() before being drawn. */ public void paintComponent(Graphics g) { super.paintComponent(g); // paint the background (perhaps) g.setColor(getForeground()); if (fm == null) fm = g.getFontMetrics(getFont()); Insets insets = getInsets(); int y = fm.getAscent()+insets.top; String line; int fmheight=fm.getHeight(); int splitalign=getSplitStringAlign(); boolean callrevalidate = false; if(getNLines() != numberlinesallocated)callrevalidate = true; for (int i=0; i<getNLines(); i++) { line = getLine(i); if(line !=null){ if(line.equals("\n")){ if(i>0){ y-=fmheight/2; g.drawLine(insets.left,y,blockwidth+insets.right,y); y += fmheight; } }else{ String[] splitline = formatLine(line); if(fm.stringWidth(splitline[0])>maxleftsplitwidth ||(splitline[1]!=null && fm.stringWidth(splitline[1])>maxrightsplitwidth))callrevalidate = true; g.drawString(splitline[0],insets.left,y); if(splitline[1]!=null && splitalign==LEFTALIGNSPLIT){ g.drawString(splitline[1],insets.left+maxleftsplitwidth,y); }else if(splitline[1]!=null && splitalign==RIGHTALIGNSPLIT){ g.drawString(splitline[1],insets.left+rightAlignSplitWidth(splitline[1]),y); }else if(splitline[1]!=null && splitalign==NOALIGNSPLIT){ g.drawString(splitline[1],insets.left+fm.stringWidth(splitline[0]),y); } y += fmheight; } } } if (callrevalidate) revalidate(); } public void modifyPopupMenu(final JPopupMenu menu, final Component source) { menu.add(new FontMenuItem(this,getPrefix())); super.modifyPopupMenu(menu,source); } /**If the input string contains a '\t' character then it is seperated into two strings * , which allows for the setting of accurate spacings between the two strings in * the text block. */ private String[] formatLine(String s){ String[] splitline= new String[2]; if(s!=null){ int index = s.indexOf('\t'); if(index>=0){ splitline[0] = " " + s.substring(0,index)+ " : "; splitline[1] = s.substring(index+1)+ " " ; }else splitline[0] =s; } return splitline; } /**Base method for determining the width (blockwidth) of the text block according * to the max length of text lines to be drawn in the block, and the height * according to the number of lines to be displayed. */ protected void allocateSize(){ String s; maxleftsplitwidth=0; maxrightsplitwidth=0; blockwidth=30; blockheight=0; int fmheight=fm.getHeight(); numberlinesallocated = getNLines(); for (int i=0; i<getNLines(); i++) { s =getLine(i); if(s!= null){ if(s.equals("\n")){ if(i>0)blockheight+=fmheight/2; }else{ blockheight+=fmheight; blockWidth(s); } } } if (blockheight==0) blockheight=fmheight; } /** For strings that are to be displayed as two seperate strings to allow the setting of * accurate spacings between the two strings in the text block. If strings contains * '\t' then checks to see if fontmetrics size of input string is greater than the namewidth. If so then namewidth is set to fm size of * current string. */ private int rightAlignSplitWidth(String s){ int width=0; int rightwidth=0; if(s!=null){ rightwidth=fm.stringWidth(s); width = blockwidth - rightwidth-WIDTHSPACE; } return width; } /**Checks to see if fontmetrics size of input string is greater than the blockwidth. * If so then blockwidth is set to fm size of current string. */ private void blockWidth(String s){ String[] splitline = formatLine(s); int width=0; int leftwidth=0; int rightwidth=0; int splitalign=getSplitStringAlign(); if(splitline[0]!=null)leftwidth=fm.stringWidth(splitline[0]); if(splitline[1]!=null)rightwidth=fm.stringWidth(splitline[1]); if(splitalign==1 && (splitline[1] !=null)){ if(leftwidth>maxleftsplitwidth)maxleftsplitwidth=leftwidth; if(rightwidth>maxrightsplitwidth)maxrightsplitwidth=rightwidth; width=maxrightsplitwidth +maxleftsplitwidth+WIDTHSPACE; }else{ width=rightwidth +leftwidth+WIDTHSPACE; } if(width > blockwidth) blockwidth = width; } protected FontMetrics fm; private int blockwidth; private int blockheight; private int maxleftsplitwidth; private int maxrightsplitwidth; private int numberlinesallocated; final private static int WIDTHSPACE=5; final private static int LEFTALIGNSPLIT=1; final private static int RIGHTALIGNSPLIT=2; final private static int NOALIGNSPLIT=3; public void setFont(Font p1) { super.setFont(p1); fm=null; this.revalidate(); this.repaint(); } }