package awt;

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;

public class TextPanel extends Panel {
	private String [][] text;
	
Fresh text will overwrite text[fresh] Line fresh-1 is shown at bottom of screen; at this line, characters are added
private int fresh; private ActionListener actionListener;
Don't show the last scrollbackLines lines
private int scrollbackLines = 0; public TextPanel() { this(100); } public TextPanel(int capacity) { text = new String[capacity][]; enableEvents(AWTEvent.MOUSE_EVENT_MASK); } public int getCapacity() { return text.length; } public void processMouseEvent(MouseEvent e) { int idx = (getSize().height-e.getY())/getGraphics().getFontMetrics().getHeight(); switch (e.getID()) { case MouseEvent.MOUSE_PRESSED: if (e.getClickCount() == 2) { actionListener.actionPerformed(new ActionEvent(this,ActionEvent.ACTION_PERFORMED,""+idx)); } } super.processMouseEvent(e); } public void addActionListener(ActionListener listener) { actionListener = AWTEventMulticaster.add(actionListener,listener); }
Chop string into words
private String [] chop(String s) { Vector result = new Vector(); int startidx = 0; int len = s.length(); for (int i = 0; i < len; i++) { char c = s.charAt(i); if (c == ' ') { if (i > startidx) result.addElement(s.substring(startidx,i)); startidx = i+1; } else if (c == 0) { //System.out.println("chop: color at "+i); // nullbyte is color-indicator: // next 3 bytes indicate r,g,b values // first add previous word if (i > startidx) result.addElement(s.substring(startidx,i)); result.addElement(s.substring(i,i+4)); i += 3; //System.out.println("next char is at "+(i+1)+" <"+s.charAt(i+1)+">"); startidx = i+1; } } if (startidx < len) result.addElement(s.substring(startidx,len)); String [] res = new String[result.size()]; result.copyInto(res); result.setSize(0); //println(res); return res; }
Calculate height in pixels
private static int height(FontMetrics fm,String [] line,int width) { int x = 0; // position of next word int y = 0; int fontheight = fm.getHeight(); int spacewidth = fm.charWidth(' '); for (int i = 0; i < line.length; i++) { String word = line[i]; if (word.equals("")) continue; if (word.charAt(0) == 0) continue; // color int wordw = fm.stringWidth(word); if (x + wordw > width) { y += fontheight; x = wordw + spacewidth; } else x += wordw + spacewidth; } return y + fontheight; } public int linesUsed() { int result = 0; for (int i = 0; i < text.length; i++) if (text[i] != null) result++; return result; }
paint line with top pixelheight ypos
private static void paintline(Graphics g,String [] line,int width,int y) { g.setColor(Color.black); FontMetrics fm = g.getFontMetrics(); y += fm.getAscent(); int x = 0; // position of next word int fontheight = fm.getHeight(); int spacewidth = fm.charWidth(' '); for (int i = 0; i < line.length; i++) { String word = line[i]; if (word.equals("")) continue; if (word.charAt(0) == 0) { g.setColor(new Color(word.charAt(1),word.charAt(2),word.charAt(3))); continue; } int wordw = fm.stringWidth(word); if (x + wordw > width) { y += fontheight; x = 0; } g.drawString(word,x,y); x += wordw + spacewidth; } return; } public void invalidate() { super.invalidate(); offscreen = null; } private Image offscreen; public void paint(Graphics g) { Dimension siz = getSize(); if (offscreen == null) offscreen = createImage(siz.width,siz.height); Graphics oldg = g; g = offscreen.getGraphics(); g.setClip(0,0,siz.width,siz.height); g.setColor(Color.lightGray); g.fillRect(0,0,siz.width,siz.height); int y = siz.height - 1; // to paint: [0..siz.height] int lin = fresh; int scrollback = scrollbackLines; FontMetrics fm = g.getFontMetrics(); while (true) { if (lin > 0) lin--; else lin = text.length - 1; if (text[lin] == null) break; if (scrollback > 0) scrollback--; else { int h = height(fm,text[lin],siz.width); //System.out.println("height of line "+lin+" "+text[lin][0]+"... is "+h); //System.out.println("\tpaint at y "+y+"..."+(y-h)); y -= h; paintline(g,text[lin],siz.width,y); } if (y < 0) break; } oldg.drawImage(offscreen,0,0,null); } public void update(Graphics g) { paint(g); }
Add color switch
public void add(Color c) { int lineno = fresh - 1; if (lineno < 0) lineno = text.length - 1; if (text[lineno] == null) { text[lineno] = new String[1]; text[lineno][0] = ""; } String [] newline = new String[text[lineno].length + 1]; System.arraycopy(text[lineno],0,newline,0,text[lineno].length); newline[newline.length-1] = "\0"+(char)c.getRed()+(char)c.getGreen()+(char)c.getBlue(); text[lineno] = newline; } public void add(char c) { int lineno = fresh - 1; if (lineno < 0) lineno = text.length - 1; if (text[lineno] == null) { text[lineno] = new String[1]; text[lineno][0] = ""; } if (c == ' ') { // create new word String [] newline = new String[text[lineno].length + 1]; System.arraycopy(text[lineno],0,newline,0,text[lineno].length); newline[newline.length-1] = ""; text[lineno] = newline; } else if (c == '\n') { // new line text[fresh] = new String[1]; text[fresh][0] = ""; if (fresh+1 < text.length) fresh++; else fresh = 0; repaint(); } else { // add char to word text[lineno][text[lineno].length-1] += c; repaint(); } }
Add CR, then full line
public void add(String line,Color c) { add("\0"+(char)c.getRed()+(char)c.getGreen()+(char)c.getBlue()+line); }
Add CR, then full line
public void add(String line) { text[fresh] = chop(line); if (fresh+1 < text.length) fresh++; else fresh = 0; repaint(); }
if idx=0, return last line added if idx=1, return line before last line added if idx = 2, return line before that line, etc etc if idx = getCapacity()-1, return oldest line
public String getLine(int idx) { idx = fresh - 1 - idx; if (idx < 0) idx += text.length; String result = ""; String [] texti = text[idx]; if (texti == null) return null; for (int i = 0; i < texti.length-1; i++) result += texti[i] + " "; return result + texti[texti.length-1]; } public void setScrollbackLines(int back) { scrollbackLines = back; repaint(); } public int getScrollbackLines() { return scrollbackLines; } }