home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 1998 October
/
PCWorld_1998-10_cd.bin
/
software
/
prehled
/
inprise
/
JSAMPLES.Z
/
WrappingTextViewer.java
< prev
next >
Wrap
Text File
|
1998-05-08
|
11KB
|
310 lines
/*
* Copyright (c) 1997-1998 Borland International, Inc. All Rights Reserved.
*
* This SOURCE CODE FILE, which has been provided by Borland as part
* of a Borland product for use ONLY by licensed users of the product,
* includes CONFIDENTIAL and PROPRIETARY information of Borland.
*
* USE OF THIS SOFTWARE IS GOVERNED BY THE TERMS AND CONDITIONS
* OF THE LICENSE STATEMENT AND LIMITED WARRANTY FURNISHED WITH
* THE PRODUCT.
*
* IN PARTICULAR, YOU WILL INDEMNIFY AND HOLD BORLAND, ITS RELATED
* COMPANIES AND ITS SUPPLIERS, HARMLESS FROM AND AGAINST ANY CLAIMS
* OR LIABILITIES ARISING OUT OF THE USE, REPRODUCTION, OR DISTRIBUTION
* OF YOUR PROGRAMS, INCLUDING ANY CLAIMS OR LIABILITIES ARISING OUT OF
* OR RESULTING FROM THE USE, MODIFICATION, OR DISTRIBUTION OF PROGRAMS
* OR FILES CREATED FROM, BASED ON, AND/OR DERIVED FROM THIS SOURCE
* CODE FILE.
*/
package borland.samples.intl.beans;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.text.*;
import java.util.*;
import borland.jbcl.control.*;
import borland.jbcl.dataset.*;
import borland.jbcl.view.*;
import borland.jbcl.model.*;
import borland.jbcl.layout.*;
import borland.samples.intl.beans.event.*;
/**
* WrappingTextViewer displays and wraps text in a locale-sensitive way.
* A 'component resized' listener detects when the dimensions of the bean
* have changed. Based on the new dimensions, the text is wrapped into
* lines which are then appended to a JBCL ListControl.
* WrappingTextViewer is also an example of a (read-only) data-aware control. It
* accepts a dataset and column name, and updates itself on changes to its
* data.
*/
public class WrappingTextViewer extends BevelPanel implements ComponentListener, LocaleChangeListener, NavigationListener, DataChangeListener, AccessListener {
private BasicVectorContainer basicVectorContainer = new BasicVectorContainer();
private BasicViewManager basicViewManager = new BasicViewManager(new TextItemPainter(),
null);
private ListControl listControl = new ListControl();
private BreakIterator breakIterator = BreakIterator.getLineInstance(getLocale());
private String text = null;
private int lastWidth = 0;
private int maxLineWidth = 0;
private FontMetrics fontMetrics = null;
private Font font = null;
private int margin = 30;
private String columnName = null;
private DataSet dataSet = null;
private Dimension screenSize;
private Dimension preferredSize;
public WrappingTextViewer() {
this("");
}
public WrappingTextViewer(String text) {
screenSize = Toolkit.getDefaultToolkit().getScreenSize();
preferredSize = new Dimension(screenSize.width / 4, screenSize.height / 2);
listControl.setModel(basicVectorContainer);
listControl.setViewManager(basicViewManager);
listControl.setReadOnly(true);
listControl.setUniformWidth(true);
listControl.setUniformHeight(true);
addComponentListener(this);
setLayout(new BorderLayout());
add(listControl, BorderLayout.CENTER);
setText(text);
}
public void setText(String text) {
this.text = text;
if ((maxLineWidth > 0) && (fontMetrics != null)) {
wrapText(true);
}
}
public String getText() {
return text;
}
public void setLocale(Locale locale) {
super.setLocale(locale);
breakIterator = BreakIterator.getLineInstance(locale);
setText(text);
}
public Locale getLocale() {
try {
return super.getLocale();
} catch (IllegalComponentStateException e) {
return Locale.getDefault();
}
}
public void setFont(Font font) {
super.setFont(font);
if (this.font != font) {
fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
listControl.setItemHeight(fontMetrics.getLeading() + fontMetrics.getMaxAscent() + fontMetrics.getMaxDescent());
this.font = font;
wrapText(true);
}
}
public void localeChanged(LocaleChangeEvent e) {
breakIterator = BreakIterator.getLineInstance(e.getLocale());
setText(text);
}
protected void wrapText(boolean doUnconditionally) {
if (!doUnconditionally && lastWidth == maxLineWidth) {
return;
} else {
lastWidth = maxLineWidth;
}
Component component = this;
Frame frame = new Frame();
while ((component = component.getParent()) != null) {
if (component instanceof Frame) {
frame = (Frame) component;
break;
}
}
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
basicVectorContainer.removeAll();
BufferedReader bufferedReader = new BufferedReader(new StringReader(text));
String line;
try {
while ((line = bufferedReader.readLine()) != null) {
breakIterator.setText(line);
if (fontMetrics.stringWidth(line) < maxLineWidth) {
basicVectorContainer.addItem(line);
} else {
char [] chars = new char[line.length()+1];
line.getChars(0, chars.length-1, chars, 0);
chars[chars.length-1] = ' ';
int lastStartPosition = 0;// char position
int lastBreakPosition = -1;// char position
int wordWidth = 0; // display width, not char count
int lineWidth = 0; // display width, not char count
int breakCharWidth = 0; // display width, not char count
int current = 0; // index into char array
breakIterator.first();
while (breakIterator.next() != BreakIterator.DONE) {
current = breakIterator.current() - 1;
// the width of the word (wordWidth) and break character (breakCharWidth) are maintained separately.
// the width of the break character is only included in the width of the word (see below) if
// it's not a whitespace character.
wordWidth = fontMetrics.charsWidth(chars, lastBreakPosition+1, (current - lastBreakPosition - 1));
breakCharWidth = fontMetrics.charWidth(chars[current]);
// if the break character is not a whitespace char (e.g., a Japanese kanji character)
// then it has to be included as part of the word width calculation below
if (!Character.isWhitespace(chars[current])) {
wordWidth += breakCharWidth;
breakCharWidth = 0;
}
// will adding the next word make the current line too long?
if (lineWidth + wordWidth >= maxLineWidth) {
// failed on first word, treat this as a special case
if (lastBreakPosition == -1) {
basicVectorContainer.addItem(new String(chars, lastStartPosition, current));
lastStartPosition = 0;
lastBreakPosition = current;
lineWidth = 0;
continue;
}
// can't always assume it's okay to remove the break character because in some languages (e.g., Japanese)
// the break character may not be a whitespace character
int whitespaceOffset = 1;
if (Character.isWhitespace(chars[lastBreakPosition])) {
whitespaceOffset = 0;
}
basicVectorContainer.addItem(new String(chars, lastStartPosition, lastBreakPosition-lastStartPosition+whitespaceOffset));
lastStartPosition = lastBreakPosition + 1;
lastBreakPosition = current;
lineWidth = wordWidth + breakCharWidth;
continue;
}
lastBreakPosition = current;
lineWidth += wordWidth + breakCharWidth;
}
basicVectorContainer.addItem(line.substring(lastStartPosition));
}
}
} catch (Exception e) {
e.printStackTrace();
}
frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
public void componentResized(ComponentEvent e) {
Font targetFont = e.getComponent().getFont();
maxLineWidth = e.getComponent().getSize().width - margin;
if (targetFont != font) {
fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(targetFont);
listControl.setItemHeight(fontMetrics.getLeading() + fontMetrics.getMaxAscent() + fontMetrics.getMaxDescent());
font = targetFont;
}
wrapText(false);
}
public void componentMoved(ComponentEvent e) {
}
public void componentShown(ComponentEvent e) {
}
public void componentHidden(ComponentEvent e) {
}
public Dimension getPreferredSize() {
return new Dimension(preferredSize.width, preferredSize.height);
}
public void setPreferredSize(Dimension preferredSize) {
this.preferredSize = new Dimension(preferredSize.width, preferredSize.height);
}
// methods necessary to implement for a data-aware control
public String getColumnName() {
return columnName;
}
public void setColumnName(String columnName) {
this.columnName = columnName;
}
public DataSet getDataSet() {
return dataSet;
}
public void setDataSet(DataSet dataSet) {
if (dataSet != null) {
dataSet.removeAccessListener(this);
dataSet.removeNavigationListener(this);
dataSet.removeDataChangeListener(this);
}
this.dataSet = dataSet;
if (dataSet == null)
setText("");
else {
updateText();
dataSet.addAccessListener(this);
dataSet.addNavigationListener(this);
dataSet.addDataChangeListener(this);
}
}
public void accessChange(AccessEvent e) {
updateText();
}
public void navigated(NavigationEvent e) {
updateText();
}
public void dataChanged(DataChangeEvent e) {
if ((e.getID() == DataChangeEvent.ROW_CHANGE_POSTED) &&
(e.getRowAffected() == dataSet.getRow())) {
updateText();
}
}
public void postRow(DataChangeEvent e) {
}
private void updateText() {
try {
if ((dataSet != null) &&
(columnName != null) &&
(dataSet.isOpen()) &&
(dataSet.hasColumn(columnName) != null)) {
setText(dataSet.getString(columnName));
} else {
setText("");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}