/**************************************************************************
* Copyright (c) 2001, 2002, 2003 by Acunia N.V. All rights reserved. *
* *
* This software is copyrighted by and is the sole property of Acunia N.V. *
* and its licensors, if any. All rights, title, ownership, or other *
* interests in the software remain the property of Acunia N.V. and its *
* licensors, if any. *
* *
* This software may only be used in accordance with the corresponding *
* license agreement. Any unauthorized use, duplication, transmission, *
* distribution or disclosure of this software is expressly forbidden. *
* *
* This Copyright notice may not be removed or modified without prior *
* written consent of Acunia N.V. *
* *
* Acunia N.V. reserves the right to modify this software without notice. *
* *
* Acunia N.V. *
* Philips-site 5, box 3 info@acunia.com *
* 3001 Leuven http://www.acunia.com *
* Belgium - EUROPE *
**************************************************************************/
package com.acunia.wonka.rudolph.peers;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
/*
** java.awt drawn TextArea peer for our own uses
** This paints a default 'rudolph' TextArea center and fills it with a given text. furthermore, it initialises (fixed) TextArea
** font and font dimensions
** Using this peer for all paint-instances lets you quickly make a new layout for the Text areas needed,
*/
public class RudolphTextAreaPeer extends RudolphPeer {
/*
** static variables
*/
/*
** @note: the Java specs define the default font to be platform specific.
*/
public static final Font DEFAULT_FONT = new Font("courP14", 0, 14); //new Font("courP17", 0, 17);
/*
** @note: the Java specs define the default number of rows and colums to be platform specific.
*/
public final static int DEFAULTTEXTCHARS = 20;
public final static int DEFAULTTEXTLINES = 5;
//area width for border scrolling
public final static int BORDER = 16;
/*
** paint a text area from a given set of charbufer and start/length position arrays. A cursor is specified by his y-position and offset
**
** @status This is a plug-in allowing you to configure the way the text area text is displayed. Feel free to change
** @variables
** int x0, int y0: : the offset to the topleft corner (x=0,y=0) ofthe component where the TextArea has to be drawn
** int width, int height, : the width and height of the text display area (the TextArea without the scrollbars)
** char[] text, int[] starts, int[] lengths : the lines of text to be displayed. With the buffer/starts[]/lengths[] format
** the <x>-th line of text to be displayed is the array of chars from the text buffer
** starting at buffer char number <starts[x]> and having length <lengths[x]>
** (the corresponding String being new String(buffer, starts[x],lengths[x]) )
** int lineoffset, : the vertical offset of visible lines. The visible part of the text stretches from line
** <lineoffset> to line <lineoffset + getLines(height)>
** int cursorline, int cursoroffset : the line of the cursor, the x-position of the cursor on the screen
** Font f, FontMetrics fm, : the desired font and its FontMetrics
** Color[] peercolors: : an Color[5] array specifying the colors in which to paint the bar (see RudolpPeer for detains)
** Graphics g : our Graphics instance as given in Component.paint(Graphics g)
*/
public static void paintTextArea( int x0, int y0, int width, int height,
char[] text, int[] starts, int[] lengths, int lineoffset,
int cursorline, int cursoroffset,
Font f, FontMetrics fm, Color[] peercolors, Graphics g, boolean drawCursor) {
//textarea box
g.setColor(peercolors[3]); //dark
g.drawLine(x0+1,y0+1,x0+width-2, y0+1);
g.drawLine(x0+1,y0+1,x0+1, y0+height-2);
g.setColor(peercolors[2]); //light
g.drawLine(x0+width-2,y0+1,x0+width-2, y0+height-2);
g.drawLine(x0+1,y0+height-2,x0+width-2, y0+height-2);
//some variables for the text display
int lineheight = fm.getHeight();
int xt = x0+5;
int yt = y0+2+lineheight-fm.getDescent();
// last line to be displayed
int lastline = (height-3)/lineheight+lineoffset;
if(lastline>=starts.length) {
lastline =starts.length;
}
//display text
g.setFont(f);
g.setColor(peercolors[4]);
for(int i=lineoffset; i<lastline; i++) {
g.drawChars(text,starts[i],lengths[i], xt, yt);
yt+=lineheight;
}
//cursor mark : draw a simple I before the cursor character position
if(drawCursor && cursorline>=lineoffset && cursorline<lastline && cursoroffset>=0 && cursoroffset<(width-4)) {
//Okay, in visible area => draw a simple I on the desired line, desired cursor offset
yt=y0+2+(cursorline-lineoffset)*lineheight;
xt=x0+5+cursoroffset;
g.setColor(peercolors[3]);
g.drawLine(xt,yt,xt,yt+lineheight);
g.drawLine(xt-2,yt,xt+2,yt);
g.drawLine(xt-2,yt+lineheight,xt+2,yt+lineheight);
}
else
{
wonka.vm.Etc.woempa(9, "don't draw Cursor");
wonka.vm.Etc.woempa(9, "drawCursor: "+drawCursor);
wonka.vm.Etc.woempa(9, "cursorline: "+cursorline);
wonka.vm.Etc.woempa(9, "lineoffset: "+lineoffset);
wonka.vm.Etc.woempa(9, "lastline: "+lastline);
wonka.vm.Etc.woempa(9, "cursoroffset: "+cursoroffset);
wonka.vm.Etc.woempa(9, "width: "+width);
}
//Ok, done...
}
/*
** paint a text area from a given set of charbufer and start/length position arrays.
** additionally there is a selection starting at a point charno/lineno with given horizontal offset
** and ending at a point charno/lineno with given horizontal offset
** @status This is a plug-in allowing you to configure the way the text area text is displayed. Feel free to change
** @variables
** int x0, int y0: : the offset to the topleft corner (x=0,y=0) ofthe component where the TextArea has to be drawn
** int width, int height, : the width and height of the text display area (the TextArea without the scrollbars)
** char[] text, int[] starts, int[] lengths : the lines of text to be displayed. With the buffer/starts[]/lengths[] format
** the <x>-th line of text to be displayed is the array of chars from the text buffer
** starting at buffer char number <starts[x]> and having length <lengths[x]>
** (the corresponding String being new String(buffer, starts[x],lengths[x]) )
** int lineoffset, : the vertical offset of visible lines. The visible part of the text stretches from line
** <lineoffset> to line <lineoffset + getLines(height)>
** int startline, int startchar, int startoffset : the start of the selection defined by => the line on which the selection starts,
** => the number of the starting character in the text buffer and
** => the offset of the selection start text on the horizontal axis
** int stopline, int stopchar, int stopoffset : the stop of the selection equally defined by => the line on which the selection stops,
** => the number of the first character NO LONGER SELECTED in the text buffer and
** => the offset of the selection stop text on the horizontal axis
** Font f, FontMetrics fm, : the desired font and its FontMetrics
** Color[] peercolors: : an Color[5] array specifying the colors in which to paint the bar (see RudolpPeer for detains)
** Graphics g : our Graphics instance as given in Component.paint(Graphics g)
*/
public static void paintTextArea( int x0, int y0, int width, int height,
char[] text, int[] starts, int[] lengths, int lineoffset,
int startline, int startchar, int startoffset, int stopline, int stopchar, int stopoffset,
Font f, FontMetrics fm, Color[] peercolors, Graphics g, boolean drawCursor) {
//textarea box
g.setColor(peercolors[3]); //dark
g.drawLine(x0+1,y0+1,x0+width-2, y0+1);
g.drawLine(x0+1,y0+1,x0+1, y0+height-2);
g.setColor(peercolors[2]); //light
g.drawLine(x0+width-2,y0+1,x0+width-2, y0+height-2);
g.drawLine(x0+1,y0+height-2,x0+width-2, y0+height-2);
width-=7; // to inner width inside the box
// calculate herler variables for the texts
int lineheight = fm.getHeight();
int xt = x0+5;
int yt = y0+2+lineheight-fm.getDescent();
int lastline = (height-3)/lineheight+lineoffset;
if(lastline>=starts.length)
lastline =starts.length;
//selection rectangle
int xs = x0+2;
int ys = y0+2;
// counter
int i = lineoffset;
// draw text up to start of selection
g.setFont(f);
g.setColor(peercolors[4]);//font color
// draw from offset to insert pos
while(i<lastline && i<startline) {
g.drawChars(text,starts[i],lengths[i], xt, yt);
ys+=lineheight;
yt+=lineheight;
i++;
}
// insert and replace in same line and visible
if(startline==stopline && startline>=lineoffset && startline<lastline) {
if(stopoffset<0 || startoffset>width) {
// selection before or after viewport => full line of not yet or no longer selected text
g.drawChars(text,starts[i],lengths[i], xt, yt);
}
else if(startoffset<=0 && stopoffset>width) {
// selection starts before viewport and ends after it
//full line selection box
g.setColor(peercolors[1]);//background dark
g.fillRect(xt,ys,width-3,lineheight);
//full line of selection text
g.setColor(peercolors[2]);//light
g.drawChars(text,starts[i],lengths[i], xt, yt);
}
else if(startoffset<=0) {
// implicit also && xr<=width)
//starts before viewport, but ends inside
//selection box from viewport to stopdata
g.setColor(peercolors[1]);//background dark
g.fillRect(xt,ys,stopoffset,lineheight);
//selection text from viewport to stopdata
g.setColor(peercolors[2]);//light
int temp = stopchar-starts[i];
if(temp > text.length - starts[i]) temp = text.length-starts[i];
g.drawChars(text,starts[i],temp, xt, yt);
//text after selection
g.setColor(peercolors[4]);//font color
temp = starts[i]+lengths[i]-stopchar;
if(temp > text.length - stopchar) temp = text.length-stopchar;
g.drawChars(text,(stopchar < text.length ? stopchar : 0), (stopchar < text.length ? temp : 0), xt+stopoffset, yt);
}
else if(startoffset>0 && stopoffset>width) {
// starts in viewport, but ends after it
// text up to selection
g.drawChars(text,starts[i],startchar-starts[i], xt, yt);
//selection box
g.setColor(peercolors[1]);//background dark
g.fillRect(xt+startoffset,ys,width-startoffset-2,lineheight);
//selection text
g.setColor(peercolors[2]);//light
g.drawChars(text,startchar,starts[i]+lengths[i]-startchar, xt+startoffset, yt);
//set color for text after selection
g.setColor(peercolors[4]);//font color
}
else {
//if(startoffset>0 && stopoffset<=width) //normal case, both starts and stop in viewport
// text up to selection
int temp = startchar - starts[i];
if(temp > text.length - starts[i]) temp = text.length - starts[i];
g.drawChars(text,starts[i],temp, xt, yt);
//selection box
g.setColor(peercolors[1]);//background dark
g.fillRect(xt+startoffset,ys,stopoffset-startoffset,lineheight);
//selection text
g.setColor(peercolors[2]);//light
temp = stopchar - startchar;
if(temp > text.length - startchar) temp = text.length - startchar;
g.drawChars(text,(startchar < text.length ? startchar : 0), (startchar < text.length ? temp : 0), xt+startoffset, yt);
//text after selection
g.setColor(peercolors[4]);//font color
temp = starts[i]+lengths[i]-stopchar;
if(temp > text.length - stopchar) temp = text.length - stopchar;
g.drawChars(text,(stopchar < text.length ? stopchar : 0), (stopchar < text.length ? temp : 0), xt+stopoffset, yt);
}
//next line
//ys+=lineheight; //no longer needed
yt+=lineheight;
i++;
}
// else if we have a (at least partly)visible multi-line selection
else if(stopline>=lineoffset && startline<lastline)
{
//first line: startdata to end:
//----------------------------
if(startline>=lineoffset)
{
if(startoffset<0) {
// selection starts before viewport => draw the selected text over the whole line
//selection box
g.setColor(peercolors[1]);//background dark
g.fillRect(xt,ys,width,lineheight);
//selection text
g.setColor(peercolors[2]);//light
g.drawChars(text,starts[i],lengths[i], xt, yt);
}
else if(startoffset > width) {
//selection starts after viewport: draw then text before the selection
// text up to selection
g.setColor(peercolors[4]);//foreground
g.drawChars(text,starts[i],lengths[i], xt, yt);
}
else {
//selection starts IN viewport : draw text before selection and selected fart after it
// text up to selection
g.setColor(peercolors[4]);//foreground
g.drawChars(text,starts[i],startchar-starts[i], xt, yt);
//selection box
g.setColor(peercolors[1]);//background dark
g.fillRect(xt+startoffset,ys,width-startoffset,lineheight);
//selection text
g.setColor(peercolors[2]);//light
if(startchar < text.length && lengths[i]+starts[i] < text.length && startchar <= lengths[i]+starts[i])
g.drawChars(text,startchar,lengths[i]+starts[i]-startchar, xt+startoffset, yt);
}
//next line
ys+=lineheight;
yt+=lineheight;
i++;
}
//lines between insert and replace line
//-------------------------------------
while(i<stopline && i<lastline) {
//selection box over the complete length
g.setColor(peercolors[1]);//background dark
g.fillRect(xt,ys,width,lineheight);
//selection text
g.setColor(peercolors[2]);//light
g.drawChars(text,starts[i],lengths[i], xt, yt);
//next line
ys+=lineheight;
yt+=lineheight;
i++;
}
//last line: if visible, draw the last selected part and the part after the replace mark
//--------------------------------------------------------------------------------------
if(i<lastline) {
if(stopoffset<0) {
// selection end not yet in viewport => draw the normal text after the selection
// text after selection
g.setColor(peercolors[4]);//foreground
g.drawChars(text,starts[i], lengths[i], xt, yt);
}
else if(stopoffset>width) {
//selection end after viewport, draw the stil selected text
//selection box from left to right offset
g.setColor(peercolors[1]);//background dark
g.fillRect(xt,ys, width, lineheight);
//last selected text
g.setColor(peercolors[2]);//light
g.drawChars(text,starts[i],lengths[i], xt, yt);
//next texts will be drawn in textcolor
g.setColor(peercolors[4]);//foreground
}
else {
// selected text inside viewport: draw still selected part and the normal text after if
//selection box from left to selection offset
g.setColor(peercolors[1]);//background dark
g.fillRect(xt,ys, stopoffset, lineheight);
//last selected text
g.setColor(peercolors[2]);//light
g.drawChars(text,starts[i],stopchar-starts[i], xt, yt);
// text after selection
g.setColor(peercolors[4]);//foreground
if(stopchar < text.length && lengths[i]+starts[i] < text.length && stopchar <= lengths[i]+starts[i])
g.drawChars(text,stopchar, starts[i]+lengths[i]-stopchar, xt+stopoffset, yt);
}
//next line
yt+=lineheight;
i++;
}
}
//draw part after replace
while(i<lastline) {
//still implicit i<texts.length && y<ymax
g.drawChars(text,starts[i],lengths[i], xt, yt);
yt+=lineheight;
i++;
}
//Ok, done...
}
/*
** Simplified version of the above
** As we have no left-right scrolling, we know that the selection is always completely visible, thus we can throw away
** the complex visibility tests on start-and stop data
** @status This is a plug-in allowing you to configure the way the text area text is displayed. Feel free to change
** @variables
** int x0, int y0: : the offset to the topleft corner (x=0,y=0) ofthe component where the TextArea has to be drawn
** int width, int height, : the width and height of the text display area (the TextArea without the scrollbars)
** char[] text, int[] starts, int[] lengths : the lines of text to be displayed. With the buffer/starts[]/lengths[] format
** the <x>-th line of text to be displayed is the array of chars from the text buffer
** starting at buffer char number <starts[x]> and having length <lengths[x]>
** (the corresponding String being new String(buffer, starts[x],lengths[x]) )
** int lineoffset, : the vertical offset of visible lines. The visible part of the text stretches from line
** <lineoffset> to line <lineoffset + getLines(height)>
** int startline, int startchar, int startoffset : the start of the selection defined by => the line on which the selection starts,
** => the number of the starting character in the text buffer and
** => the offset of the selection start text on the horizontal axis
** ( Through the simplifications assumed above, we know that startoffset between 0 and width)
** int stopline, int stopchar, int stopoffset : the stop of the selection equally defined by => the line on which the selection stops,
** => the number of the first character NO LONGER SELECTED in the text buffer and
** => the offset of the selection stop text on the horizontal axis
** ( Through the simplifications assumed above, we know that stopoffset between 0 and width)
** Font f, FontMetrics fm, : the desired font and its FontMetrics
** Color[] peercolors: : an Color[5] array specifying the colors in which to paint the bar (see RudolpPeer for detains)
** Graphics g : our Graphics instance as given in Component.paint(Graphics g)
*/
public static void paintTextAreaNoScroll( int x0, int y0, int width, int height,
char[] text, int[] starts, int[] lengths, int lineoffset,
int startline, int startchar, int startoffset, int stopline, int stopchar, int stopoffset,
Font f, FontMetrics fm, Color[] peercolors, Graphics g) {
//textarea box
g.setColor(peercolors[3]); //dark
g.drawLine(x0+1,y0+1,x0+width-2, y0+1);
g.drawLine(x0+1,y0+1,x0+1, y0+height-2);
g.setColor(peercolors[2]); //light
g.drawLine(x0+width-2,y0+1,x0+width-2, y0+height-2);
g.drawLine(x0+1,y0+height-2,x0+width-2, y0+height-2);
// text variable calculations
int lineheight = fm.getHeight();
int xt = x0+5;
int yt = y0+2+lineheight-fm.getDescent();
int lastline = (height-3)/lineheight+lineoffset;
if(lastline>=starts.length)
lastline =starts.length;
//selection rectangle
int xs = x0+2;
int ys = y0+2;
// counter
int i = lineoffset;
// text display...
g.setFont(f);
g.setColor(peercolors[4]);//font color
// draw from offset to selection start
while(i<lastline && i<startline) {
g.drawChars(text,starts[i],lengths[i], xt, yt);
ys+=lineheight;
yt+=lineheight;
i++;
}
// Paint the selected text
if(startline==stopline && startline>=lineoffset && startline<lastline) {
// insert and replace in same line and visible
//if(startdata.charoffset>0 && stopdata.charoffset<=width) //normal case
xs=xt+startoffset;
// text up to selection
g.drawChars(text,starts[i],startchar-starts[i], xt, yt);
//selection box
g.setColor(peercolors[1]);//background dark
g.fillRect(xs,ys,stopoffset-startoffset,lineheight);
//selection text
g.setColor(peercolors[2]);//light
g.drawChars(text,startchar,stopchar-startchar, xs, yt);
//text after selection
g.setColor(peercolors[4]);//font color
g.drawChars(text,stopchar, starts[i]+lengths[i]-stopchar, xt+stopoffset, yt);
//next line
//ys+=lineheight; //no longer needed
yt+=lineheight;
i++;
}
else if(stopline>=lineoffset && startline<lastline) {
// Multi-line selections (we KNOW however that the first and last lines are partly selected
//and the lines in between are selected completely
//first line: startdata to end:
//----------------------------
if(startline>=lineoffset) {
xs=xt+startoffset;
// text up to selection
g.setColor(peercolors[4]);//foreground
g.drawChars(text,starts[i],startchar-starts[i], xt, yt);
//selection box
g.setColor(peercolors[1]);//background dark
g.fillRect(xs,ys,width-startoffset-6,lineheight);
//selection text
g.setColor(peercolors[2]);//light
g.drawChars(text,startchar,lengths[i]+starts[i]-startchar, xs, yt);
//next line
ys+=lineheight;
yt+=lineheight;
i++;
}
//lines between insert and replace line
//-------------------------------------
xs=width-6; // inner text width; temporarily poses for fillrect.width of complete textline
while(i<stopline && i<lastline) {
//selection box over the complete length
g.setColor(peercolors[1]);//background dark
g.fillRect(xt,ys,xs,lineheight);
//selection text
g.setColor(peercolors[2]);//light
g.drawChars(text,starts[i],lengths[i], xt, yt);
//next line
ys+=lineheight;
yt+=lineheight;
i++;
}
//last line: if visible, draw the last selected part and the part after the replace mark
//--------------------------------------------------------------------------------------
if(i<lastline) {
//selection box from left to selection offset
g.setColor(peercolors[1]);//background dark
g.fillRect(xt,ys, stopoffset, lineheight);
//last selected text
g.setColor(peercolors[2]);//light
g.drawChars(text,starts[i],stopchar-starts[i], xt, yt);
// text after selection
g.setColor(peercolors[4]);//foreground
g.drawChars(text,stopchar, starts[i]+lengths[i]-stopchar, xt+stopoffset, yt);
//next line
yt+=lineheight;
i++;
}
}
//draw part after replace
//g.setColor(peercolors[4]);//font color
while(i<lastline) {
// implicit also i<texts.length && y<ymax
g.drawChars(text,starts[i],lengths[i], xt, yt);
yt+=lineheight;
i++;
}
//Ok, done...
}
/*
** the number of lines to fit in a given screen width/ the minimum width of a screen containing a number of lines
** (the vertical area for the screen starts at y0+1 and ends at y0+height -2)
*/
public static int getLines(int height, FontMetrics fm) {
return (fm.getHeight()>0)?(height-3)/fm.getHeight():0;
}
public static int getHeight(int lines, FontMetrics fm) {
return lines*fm.getHeight()+3;
}
public static int getLine(int height, FontMetrics fm) {
return (fm.getHeight()>0)?(height-1)/fm.getHeight():0;
}
public static int getYPos(int lines, FontMetrics fm) {
return lines*fm.getHeight()+1;
}
/*
** from width of the inner area for displaying texts to horizontal size of the total display area and vice versa
** (the vertical area for the screen starts at x0+1 and ends at x0+width -2)
*/
public static int getInnerwidth(int screensize) {
return (screensize>6)?screensize-6:0;
}
public static int getScreenSize(int innerwidth) {
return innerwidth+6;
}
public static int getTextPos(int x) {
return (x>5)? x-5:0;
}
}