Coverage Report - de.glossmaker.gui.gloss.main.tableview.MultiLineTable
 
Classes in this File Line Coverage Branch Coverage Complexity
MultiLineTable
0%
0/120
0%
0/50
2,429
MultiLineTable$1
0%
0/3
N/A
2,429
MultiLineTable$2
0%
0/3
N/A
2,429
MultiLineTable$3
0%
0/3
N/A
2,429
MultiLineTable$MyTabExpander
0%
0/5
N/A
2,429
 
 1  
 package de.glossmaker.gui.gloss.main.tableview;
 2  
 
 3  
 
 4  
 
 5  
 import java.awt.*;
 6  
 import java.awt.event.*;
 7  
 import javax.swing.*;
 8  
 import javax.swing.event.*;
 9  
 import javax.swing.table.*;
 10  
 import javax.swing.text.*;
 11  
 import java.util.*;
 12  
 
 13  
 /**
 14  
  * MultiLineTable.java
 15  
  *
 16  
  * Created: Tue May 18 13:15:59 1999
 17  
  *
 18  
  * @author Thomas Wernitz, Da Vinci Communications Ltd <thomas_wernitz@clear.net.nz>
 19  
  *
 20  
  * credit to Zafir Anjum for JTableEx and thanks to SUN for their source code ;)
 21  
  */
 22  
 @SuppressWarnings({ "rawtypes", "serial" })
 23  
 public class MultiLineTable extends JTable {
 24  
   
 25  
   public MultiLineTable() {
 26  0
     this(null, null, null);
 27  0
   }
 28  
 
 29  
   public MultiLineTable(TableModel dm) {
 30  0
     this(dm, null, null);
 31  0
   }
 32  
 
 33  
   public MultiLineTable(TableModel dm, TableColumnModel cm) {
 34  0
     this(dm, cm, null);
 35  0
   }
 36  
 
 37  
   public MultiLineTable(TableModel dm, TableColumnModel cm, ListSelectionModel sm) {
 38  0
     super(dm,cm,sm);
 39  0
     setUI( new MultiLineBasicTableUI() );
 40  
     // I know this sucks tremendously, but I was too lazy to find a proper solution. :(
 41  
     // The problem is, that without this hack, a resize that changes the number of lines in
 42  
     // the TextArea does not result in the proper resizing of the table, because the
 43  
     // new width of the column is not available through getWidth until resize is complete.
 44  
     // Does this make sense? 8-/  Have a look into getRowHeight(int)! 
 45  0
     addComponentListener(new ComponentAdapter() {
 46  
       public void componentResized(ComponentEvent e) {    
 47  0
         revalidate();
 48  0
       }
 49  
     });
 50  0
   }
 51  
 
 52  
   public MultiLineTable(int numRows, int numColumns) {
 53  0
     this(new DefaultTableModel(numRows, numColumns));
 54  0
   }
 55  
 
 56  
   
 57  
 public MultiLineTable(final Vector rowData, final Vector columnNames) {
 58  0
     super( rowData, columnNames );
 59  0
     setUI( new MultiLineBasicTableUI() );
 60  0
     addComponentListener(new ComponentAdapter() {
 61  
       public void componentResized(ComponentEvent e) {    
 62  0
         revalidate();
 63  0
       }
 64  
     });
 65  0
   }
 66  
 
 67  
   public MultiLineTable(final Object[][] rowData, final Object[] columnNames) {
 68  0
     super( rowData, columnNames );
 69  0
     setUI( new MultiLineBasicTableUI() );
 70  0
     addComponentListener(new ComponentAdapter() {
 71  
       public void componentResized(ComponentEvent e) {    
 72  0
         revalidate();
 73  0
       }
 74  
     });
 75  0
   }
 76  
         
 77  
   public int rowAtPoint(Point point) {
 78  0
     int y = point.y;
 79  0
     int rowSpacing = getIntercellSpacing().height;
 80  0
     int rowCount = getRowCount();
 81  0
     int rowHeight = 0;
 82  0
     for (int row=0; row<rowCount; row++) {
 83  0
       rowHeight += getRowHeight(row) + rowSpacing;
 84  0
       if (y < rowHeight) {
 85  0
         return row;
 86  
       }
 87  
     }
 88  0
     return -1;
 89  
   }
 90  
 
 91  
   public int getHeight(String text, int width) {
 92  0
     FontMetrics fm = getFontMetrics(getFont());
 93  0
     int numLines = 1;
 94  0
     Segment s = new Segment(text.toCharArray(), 0, 0);
 95  0
     s.count = s.array.length;
 96  0
     TabExpander te = new MyTabExpander(fm);
 97  0
     int breaks = getBreakLocation(s, fm, 0, width, te, 0);
 98  0
     while((breaks+s.offset) < s.array.length) {
 99  0
       s.offset += breaks;
 100  0
       s.count = s.array.length - s.offset;
 101  0
       numLines++;
 102  0
       breaks = getBreakLocation(s, fm, 0, width, te, 0);
 103  
     }
 104  0
     return numLines * fm.getHeight();
 105  
   }
 106  
 
 107  
   public int getTabbedTextOffset(Segment s, 
 108  
                                  FontMetrics metrics,
 109  
                                  int x0, int x, TabExpander e,
 110  
                                  int startOffset, 
 111  
                                  boolean round) {
 112  0
     int currX = x0;
 113  0
     int nextX = currX;
 114  0
     char[] txt = s.array;
 115  0
     int n = s.offset + s.count;
 116  0
     for (int i = s.offset; i < n; i++) {
 117  0
       if (txt[i] == '\t') {
 118  0
         if (e != null) {
 119  0
           nextX = (int) e.nextTabStop((float) nextX,
 120  
                                       startOffset + i - s.offset);
 121  
         } else {
 122  0
           nextX += metrics.charWidth(' ');
 123  
         }
 124  0
       } else if (txt[i] == '\n') {
 125  0
         return i - s.offset;
 126  0
       } else if (txt[i] == '\r') {
 127  0
         return i + 1 - s.offset; // kill the newline as well
 128  
       } else {
 129  0
         nextX += metrics.charWidth(txt[i]);
 130  
       }
 131  0
       if ((x >= currX) && (x < nextX)) {
 132  
         // found the hit position... return the appropriate side
 133  0
         if ((round == false) || ((x - currX) < (nextX - x))) {
 134  0
           return i - s.offset;
 135  
         } else {
 136  0
           return i + 1 - s.offset;
 137  
         }
 138  
       }
 139  0
       currX = nextX;
 140  
     }
 141  
 
 142  0
     return s.count;
 143  
   }
 144  
 
 145  
   public int getBreakLocation(Segment s, FontMetrics metrics,
 146  
                               int x0, int x, TabExpander e,
 147  
                               int startOffset) {
 148  
     
 149  0
     int index = getTabbedTextOffset(s, metrics, x0, x, 
 150  
                                               e, startOffset, false);
 151  
 
 152  0
     if ((s.offset+index) < s.array.length) {
 153  0
       for (int i = s.offset + Math.min(index, s.count - 1); 
 154  0
            i >= s.offset; i--) {
 155  
         
 156  0
         char ch = s.array[i];
 157  0
         if (Character.isWhitespace(ch)) {
 158  
           // found whitespace, break here
 159  0
           index = i - s.offset + 1;
 160  0
           break;
 161  
         }
 162  
       }
 163  
     }
 164  0
     return index;
 165  
   }
 166  
 
 167  
   class MyTabExpander implements TabExpander {
 168  
     int tabSize;
 169  0
     public MyTabExpander(FontMetrics metrics) {
 170  0
       tabSize = 5 * metrics.charWidth('m');
 171  0
     }
 172  
     public float nextTabStop(float x, int offset) {
 173  0
       int ntabs = (int) x / tabSize;
 174  0
       return (ntabs + 1) * tabSize;
 175  
     }
 176  
   }
 177  
 
 178  
 
 179  
   public int getRowHeight() {
 180  0
     return -1;
 181  
   }
 182  
 
 183  
   public int getRowHeight(int row) {
 184  0
     TableModel tm = getModel();
 185  0
     int fontHeight = getFontMetrics(getFont()).getHeight();
 186  0
     int height = fontHeight;
 187  0
     Enumeration cols = getColumnModel().getColumns();
 188  0
     int i = 0;
 189  0
     while(cols.hasMoreElements()) {
 190  0
       TableColumn col = (TableColumn) cols.nextElement();
 191  0
       TableCellRenderer tcr = col.getCellRenderer();
 192  
       // without the revalidate hack above, the call th getWidth does not give the
 193  
       // right value at the right time. Take out the revalidate and uncomment the
 194  
       // next line to see for your self. If you find a way to do it right, drop me
 195  
       // a mail please! :)
 196  
       // System.out.println(col.getWidth());
 197  0
       int colWidth = col.getWidth();
 198  0
       if (tcr instanceof MultiLineCellRenderer) {
 199  0
         height = Math.max(height, getHeight((String)tm.getValueAt(row,i), colWidth));
 200  
       }
 201  0
       i++;
 202  0
     }
 203  0
     return height;
 204  
   }
 205  
 
 206  
   public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
 207  
     Rectangle cellFrame;
 208  
     TableColumn aColumn;
 209  
 
 210  0
     cellFrame = new Rectangle();
 211  
     //        cellFrame.height = getRowHeight() + rowMargin;
 212  
     //        cellFrame.y = row * cellFrame.height;
 213  0
     cellFrame.height = getRowHeight(row) + rowMargin;
 214  0
     cellFrame.y = 0;
 215  0
     for (int i=0; i<row; i++) {
 216  0
       cellFrame.y += getRowHeight(i) + rowMargin;
 217  
     }
 218  
 
 219  0
     int index = 0;
 220  0
     int columnMargin = getColumnModel().getColumnMargin();
 221  0
     Enumeration enumeration = getColumnModel().getColumns();
 222  0
     while (enumeration.hasMoreElements()) {
 223  0
       aColumn = (TableColumn)enumeration.nextElement();
 224  0
       cellFrame.width = aColumn.getWidth() + columnMargin;
 225  
 
 226  0
       if (index == column)
 227  0
         break;
 228  
 
 229  0
       cellFrame.x += cellFrame.width;
 230  0
       index++;
 231  
     }
 232  
 
 233  0
     if (!includeSpacing) {
 234  0
       Dimension spacing = getIntercellSpacing();
 235  
       // This is not the same as grow(), it rounds differently.
 236  0
       cellFrame.setBounds(cellFrame.x +      spacing.width/2,
 237  
                           cellFrame.y +      spacing.height/2,
 238  
                           cellFrame.width -  spacing.width,
 239  
                           cellFrame.height - spacing.height);
 240  
     }
 241  0
     return cellFrame;
 242  
   }
 243  
 
 244  
 
 245  
   public void columnSelectionChanged(ListSelectionEvent e) {
 246  0
     repaint();
 247  0
   }
 248  
 
 249  
   public void valueChanged(ListSelectionEvent e) {
 250  0
     int firstIndex = e.getFirstIndex();
 251  0
     int  lastIndex = e.getLastIndex();
 252  0
     if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
 253  0
       repaint();
 254  
     }
 255  0
     Rectangle dirtyRegion = getCellRect(firstIndex, 0, false);
 256  0
     int numColumns = getColumnCount();
 257  0
     int index = firstIndex;
 258  0
     for (int i=0;i<numColumns;i++) {
 259  0
       dirtyRegion.add(getCellRect(index, i, false));
 260  
     }
 261  0
     index = lastIndex;
 262  0
     for (int i=0;i<numColumns;i++) {
 263  0
       dirtyRegion.add(getCellRect(index, i, false));
 264  
     }
 265  0
     repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
 266  0
   }
 267  
  
 268  
 } // MultiLineTable