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 >
Text File  |  1998-05-08  |  11KB  |  310 lines

  1. /*
  2.  * Copyright (c) 1997-1998 Borland International, Inc. All Rights Reserved.
  3.  * 
  4.  * This SOURCE CODE FILE, which has been provided by Borland as part
  5.  * of a Borland product for use ONLY by licensed users of the product,
  6.  * includes CONFIDENTIAL and PROPRIETARY information of Borland.  
  7.  *
  8.  * USE OF THIS SOFTWARE IS GOVERNED BY THE TERMS AND CONDITIONS 
  9.  * OF THE LICENSE STATEMENT AND LIMITED WARRANTY FURNISHED WITH
  10.  * THE PRODUCT.
  11.  *
  12.  * IN PARTICULAR, YOU WILL INDEMNIFY AND HOLD BORLAND, ITS RELATED
  13.  * COMPANIES AND ITS SUPPLIERS, HARMLESS FROM AND AGAINST ANY CLAIMS
  14.  * OR LIABILITIES ARISING OUT OF THE USE, REPRODUCTION, OR DISTRIBUTION
  15.  * OF YOUR PROGRAMS, INCLUDING ANY CLAIMS OR LIABILITIES ARISING OUT OF
  16.  * OR RESULTING FROM THE USE, MODIFICATION, OR DISTRIBUTION OF PROGRAMS
  17.  * OR FILES CREATED FROM, BASED ON, AND/OR DERIVED FROM THIS SOURCE
  18.  * CODE FILE.
  19.  */
  20. package borland.samples.intl.beans;
  21.  
  22. import java.awt.*;
  23. import java.awt.event.*;
  24. import java.io.*;
  25. import java.text.*;
  26. import java.util.*;
  27. import borland.jbcl.control.*;
  28. import borland.jbcl.dataset.*;
  29. import borland.jbcl.view.*;
  30. import borland.jbcl.model.*;
  31. import borland.jbcl.layout.*;
  32.  
  33. import borland.samples.intl.beans.event.*;
  34.  
  35. /**
  36.  * WrappingTextViewer displays and wraps text in a locale-sensitive way.
  37.  * A 'component resized' listener detects when the dimensions of the bean
  38.  * have changed.  Based on the new dimensions, the text is wrapped into
  39.  * lines which are then appended to a JBCL ListControl.
  40.  * WrappingTextViewer is also an example of a (read-only) data-aware control.  It
  41.  * accepts a dataset and column name, and updates itself on changes to its
  42.  * data.
  43.  */
  44. public class WrappingTextViewer extends BevelPanel implements ComponentListener, LocaleChangeListener, NavigationListener, DataChangeListener, AccessListener {
  45.   private BasicVectorContainer basicVectorContainer = new BasicVectorContainer();
  46.   private BasicViewManager basicViewManager = new BasicViewManager(new TextItemPainter(),
  47.                                                                    null);
  48.   private ListControl listControl = new ListControl();
  49.   private BreakIterator breakIterator = BreakIterator.getLineInstance(getLocale());
  50.   private String text = null;
  51.   private int lastWidth = 0;
  52.   private int maxLineWidth = 0;
  53.   private FontMetrics fontMetrics = null;
  54.   private Font font = null;
  55.   private int margin = 30;
  56.   private String columnName = null;
  57.   private DataSet dataSet = null;
  58.   private Dimension screenSize;
  59.   private Dimension preferredSize;
  60.  
  61.   public WrappingTextViewer() {
  62.     this("");
  63.   }
  64.  
  65.   public WrappingTextViewer(String text) {
  66.     screenSize = Toolkit.getDefaultToolkit().getScreenSize();
  67.     preferredSize = new Dimension(screenSize.width / 4, screenSize.height / 2);
  68.  
  69.     listControl.setModel(basicVectorContainer);
  70.     listControl.setViewManager(basicViewManager);
  71.     listControl.setReadOnly(true);
  72.     listControl.setUniformWidth(true);
  73.     listControl.setUniformHeight(true);
  74.     addComponentListener(this);
  75.     setLayout(new BorderLayout());
  76.     add(listControl, BorderLayout.CENTER);
  77.     setText(text);
  78.   }
  79.  
  80.   public void setText(String text) {
  81.     this.text = text;
  82.     if ((maxLineWidth > 0) && (fontMetrics != null)) {
  83.       wrapText(true);
  84.     }
  85.   }
  86.  
  87.   public String getText() {
  88.     return text;
  89.   }
  90.  
  91.   public void setLocale(Locale locale) {
  92.     super.setLocale(locale);
  93.     breakIterator = BreakIterator.getLineInstance(locale);
  94.     setText(text);
  95.   }
  96.  
  97.   public Locale getLocale() {
  98.     try {
  99.       return super.getLocale();
  100.     } catch (IllegalComponentStateException e) {
  101.       return Locale.getDefault();
  102.     }
  103.   }
  104.  
  105.   public void setFont(Font font) {
  106.     super.setFont(font);
  107.     if (this.font != font) {
  108.       fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(font);
  109.       listControl.setItemHeight(fontMetrics.getLeading() + fontMetrics.getMaxAscent() + fontMetrics.getMaxDescent());
  110.       this.font = font;
  111.       wrapText(true);
  112.     }
  113.   }
  114.  
  115.   public void localeChanged(LocaleChangeEvent e) {
  116.     breakIterator = BreakIterator.getLineInstance(e.getLocale());
  117.     setText(text);
  118.   }
  119.  
  120.   protected void wrapText(boolean doUnconditionally) {
  121.  
  122.     if (!doUnconditionally && lastWidth == maxLineWidth) {
  123.       return;
  124.     } else {
  125.       lastWidth = maxLineWidth;
  126.     }
  127.  
  128.     Component component = this;
  129.     Frame frame = new Frame();
  130.  
  131.     while ((component = component.getParent()) != null) {
  132.       if (component instanceof Frame) {
  133.         frame = (Frame) component;
  134.         break;
  135.       }
  136.     }
  137.  
  138.     this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
  139.     frame.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
  140.  
  141.     basicVectorContainer.removeAll();
  142.  
  143.     BufferedReader bufferedReader = new BufferedReader(new StringReader(text));
  144.     
  145.     String line;
  146.     try {
  147.       while ((line = bufferedReader.readLine()) != null) {
  148.         breakIterator.setText(line);
  149.         if (fontMetrics.stringWidth(line) < maxLineWidth) {
  150.           basicVectorContainer.addItem(line);
  151.         } else {
  152.           char [] chars = new char[line.length()+1];
  153.           line.getChars(0, chars.length-1, chars, 0);
  154.           chars[chars.length-1] = ' ';
  155.  
  156.           int lastStartPosition = 0;// char position 
  157.           int lastBreakPosition = -1;// char position 
  158.           int wordWidth = 0;         // display width, not char count
  159.           int lineWidth = 0;         // display width, not char count
  160.           int breakCharWidth = 0;    // display width, not char count
  161.           int current = 0;           // index into char array
  162.  
  163.           breakIterator.first();
  164.           while (breakIterator.next() != BreakIterator.DONE) {
  165.             current = breakIterator.current() - 1;
  166.  
  167.             // the width of the word (wordWidth) and break character (breakCharWidth) are maintained separately.
  168.             // the width of the break character is only included in the width of the word (see below) if
  169.             // it's not a whitespace character.
  170.             wordWidth = fontMetrics.charsWidth(chars, lastBreakPosition+1, (current - lastBreakPosition - 1));
  171.  
  172.             breakCharWidth = fontMetrics.charWidth(chars[current]);
  173.             // if the break character is not a whitespace char (e.g., a Japanese kanji character)
  174.             // then it has to be included as part of the word width calculation below
  175.             if (!Character.isWhitespace(chars[current])) {
  176.               wordWidth += breakCharWidth;
  177.               breakCharWidth = 0;
  178.             }
  179.             // will adding the next word make the current line too long?
  180.             if (lineWidth + wordWidth >= maxLineWidth) {
  181.               // failed on first word, treat this as a special case
  182.               if (lastBreakPosition == -1) {
  183.                 basicVectorContainer.addItem(new String(chars, lastStartPosition, current));
  184.                 lastStartPosition = 0;
  185.                 lastBreakPosition = current;
  186.                 lineWidth = 0;
  187.                 continue;
  188.               }
  189.               // can't always assume it's okay to remove the break character because in some languages (e.g., Japanese)
  190.               // the break character may not be a whitespace character
  191.               int whitespaceOffset = 1;
  192.               if (Character.isWhitespace(chars[lastBreakPosition])) {
  193.                 whitespaceOffset = 0;
  194.               }
  195.               basicVectorContainer.addItem(new String(chars, lastStartPosition, lastBreakPosition-lastStartPosition+whitespaceOffset));
  196.               lastStartPosition = lastBreakPosition + 1;
  197.               lastBreakPosition = current;
  198.               lineWidth = wordWidth + breakCharWidth;
  199.               continue;
  200.             }
  201.  
  202.             lastBreakPosition = current;
  203.             lineWidth += wordWidth + breakCharWidth;
  204.           }
  205.           basicVectorContainer.addItem(line.substring(lastStartPosition));
  206.         }
  207.       }
  208.     } catch (Exception e) {
  209.       e.printStackTrace();
  210.     }
  211.     frame.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
  212.     this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
  213.   }
  214.  
  215.   public void componentResized(ComponentEvent e) {
  216.     Font targetFont = e.getComponent().getFont();
  217.     maxLineWidth = e.getComponent().getSize().width - margin;
  218.     if (targetFont != font) {
  219.       fontMetrics = Toolkit.getDefaultToolkit().getFontMetrics(targetFont);
  220.       listControl.setItemHeight(fontMetrics.getLeading() + fontMetrics.getMaxAscent() + fontMetrics.getMaxDescent());
  221.       font = targetFont;
  222.     }
  223.     wrapText(false);
  224.   }
  225.  
  226.   public void componentMoved(ComponentEvent e) {
  227.   }
  228.  
  229.   public void componentShown(ComponentEvent e) {
  230.   }
  231.  
  232.   public void componentHidden(ComponentEvent e) {
  233.   }
  234.  
  235.   public Dimension getPreferredSize() {
  236.     return new Dimension(preferredSize.width, preferredSize.height);
  237.   }
  238.  
  239.   public void setPreferredSize(Dimension preferredSize) {
  240.     this.preferredSize = new Dimension(preferredSize.width, preferredSize.height);
  241.   }
  242.   
  243.  
  244.   // methods necessary to implement for a data-aware control  
  245.  
  246.   public String getColumnName() {
  247.     return columnName;
  248.   }
  249.  
  250.   public void setColumnName(String columnName) {
  251.     this.columnName = columnName;
  252.   }
  253.  
  254.   public DataSet getDataSet() {
  255.     return dataSet;
  256.   }
  257.  
  258.   public void setDataSet(DataSet dataSet) {
  259.     if (dataSet != null) {
  260.       dataSet.removeAccessListener(this);
  261.       dataSet.removeNavigationListener(this);
  262.       dataSet.removeDataChangeListener(this);
  263.     }
  264.     this.dataSet = dataSet;
  265.     if (dataSet == null)
  266.       setText("");
  267.     else {
  268.       updateText();
  269.       dataSet.addAccessListener(this);
  270.       dataSet.addNavigationListener(this);
  271.       dataSet.addDataChangeListener(this);
  272.     }
  273.   }
  274.  
  275.   public void accessChange(AccessEvent e) {
  276.     updateText();
  277.   }
  278.  
  279.   public void navigated(NavigationEvent e) {
  280.     updateText();
  281.   }
  282.  
  283.   public void dataChanged(DataChangeEvent e) {
  284.     if ((e.getID() == DataChangeEvent.ROW_CHANGE_POSTED) &&
  285.         (e.getRowAffected() == dataSet.getRow())) {
  286.       updateText();
  287.     }
  288.   }
  289.  
  290.   public void postRow(DataChangeEvent e) {
  291.   }
  292.  
  293.   private void updateText() {
  294.     try {
  295.       if ((dataSet != null) &&
  296.           (columnName != null) &&
  297.           (dataSet.isOpen()) &&
  298.           (dataSet.hasColumn(columnName) != null)) {
  299.         setText(dataSet.getString(columnName));
  300.       } else {
  301.         setText("");
  302.       }
  303.     } catch (Exception ex) {
  304.       ex.printStackTrace();
  305.     }
  306.   }
  307. }
  308.  
  309.  
  310.