GNU Classpath (0.20) | |
Frames | No Frames |
1: /* DefaultTableColumnModel.java -- 2: Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing.table; 40: 41: import java.beans.PropertyChangeEvent; 42: import java.beans.PropertyChangeListener; 43: import java.io.Serializable; 44: import java.util.Enumeration; 45: import java.util.EventListener; 46: import java.util.Vector; 47: 48: import javax.swing.DefaultListSelectionModel; 49: import javax.swing.ListSelectionModel; 50: import javax.swing.event.ChangeEvent; 51: import javax.swing.event.EventListenerList; 52: import javax.swing.event.ListSelectionEvent; 53: import javax.swing.event.ListSelectionListener; 54: import javax.swing.event.TableColumnModelEvent; 55: import javax.swing.event.TableColumnModelListener; 56: 57: /** 58: * DefaultTableColumnModel 59: * @author Andrew Selkirk 60: * @version 1.0 61: */ 62: public class DefaultTableColumnModel 63: implements TableColumnModel, PropertyChangeListener, ListSelectionListener, 64: Serializable 65: { 66: private static final long serialVersionUID = 6580012493508960512L; 67: 68: /** 69: * Columns that this model keeps track of. 70: */ 71: protected Vector tableColumns; 72: 73: /** 74: * Selection Model that keeps track of columns selection 75: */ 76: protected ListSelectionModel selectionModel; 77: 78: /** 79: * Space between two columns. By default it is set to 1 80: */ 81: protected int columnMargin; 82: 83: /** 84: * listenerList keeps track of all listeners registered with this model 85: */ 86: protected EventListenerList listenerList = new EventListenerList(); 87: 88: /** 89: * changeEvent is fired when change occurs in one of the columns properties 90: */ 91: protected transient ChangeEvent changeEvent = new ChangeEvent(this); 92: 93: /** 94: * Indicates whether columns can be selected 95: */ 96: protected boolean columnSelectionAllowed; 97: 98: /** 99: * Total width of all the columns in this model 100: */ 101: protected int totalColumnWidth; 102: 103: /** 104: * Constructor DefaultTableColumnModel 105: */ 106: public DefaultTableColumnModel() 107: { 108: tableColumns = new Vector(); 109: setSelectionModel(createSelectionModel()); 110: columnMargin = 1; 111: columnSelectionAllowed = false; 112: } 113: 114: /** 115: * addColumn adds column to the model. This method fires ColumnAdded 116: * event to model's registered TableColumnModelListeners. 117: * 118: * @param col column to add 119: */ 120: public void addColumn(TableColumn col) 121: { 122: if (col == null) 123: throw new IllegalArgumentException("Null 'col' argument."); 124: tableColumns.add(col); 125: invalidateWidthCache(); 126: fireColumnAdded(new TableColumnModelEvent(this, 0, tableColumns.size() - 1)); 127: } 128: 129: /** 130: * removeColumn removes table column from the model. This method fires 131: * ColumnRemoved event to model's registered TableColumnModelListeners. 132: * 133: * @param col column to be removed 134: */ 135: public void removeColumn(TableColumn col) 136: { 137: int index = this.tableColumns.indexOf(col); 138: if (index < 0) 139: return; 140: fireColumnRemoved(new TableColumnModelEvent(this, index, 0)); 141: tableColumns.remove(col); 142: invalidateWidthCache(); 143: } 144: 145: /** 146: * moveColumn moves column at index i to index j. This method fires 147: * ColumnMoved event to model's registered TableColumnModelListeners. 148: * 149: * @param i index of the column that will be moved 150: * @param j index of column's new location 151: */ 152: public void moveColumn(int i, int j) 153: { 154: int columnCount = getColumnCount(); 155: if (i < 0 || i >= columnCount) 156: throw new IllegalArgumentException("Index 'i' out of range."); 157: if (j < 0 || j >= columnCount) 158: throw new IllegalArgumentException("Index 'j' out of range."); 159: Object column = tableColumns.remove(i); 160: tableColumns.add(j, column); 161: fireColumnAdded(new TableColumnModelEvent(this, i, j)); 162: } 163: 164: /** 165: * setColumnMargin sets margin of the columns. 166: * @param m new column margin 167: */ 168: public void setColumnMargin(int m) 169: { 170: columnMargin = m; 171: fireColumnMarginChanged(); 172: } 173: 174: /** 175: * getColumnCount returns number of columns in the model 176: * @return int number of columns in the model 177: */ 178: public int getColumnCount() 179: { 180: return tableColumns.size(); 181: } 182: 183: /** 184: * getColumns 185: * @return Enumeration 186: */ 187: public Enumeration getColumns() 188: { 189: return tableColumns.elements(); 190: } 191: 192: /** 193: * Returns the index of the {@link TableColumn} with the given identifier. 194: * 195: * @param identifier the identifier (<code>null</code> not permitted). 196: * 197: * @return The index of the {@link TableColumn} with the given identifier. 198: * 199: * @throws IllegalArgumentException if <code>identifier</code> is 200: * <code>null</code> or there is no column with that identifier. 201: */ 202: public int getColumnIndex(Object identifier) 203: { 204: if (identifier == null) 205: throw new IllegalArgumentException("Null identifier."); 206: int columnCount = tableColumns.size(); 207: for (int i = 0; i < columnCount; i++) 208: { 209: TableColumn tc = (TableColumn) tableColumns.get(i); 210: if (identifier.equals(tc.getIdentifier())) 211: return i; 212: } 213: throw new IllegalArgumentException("No TableColumn with that identifier."); 214: } 215: 216: /** 217: * getColumn returns column at the specified index 218: * @param i index of the column 219: * @return TableColumn column at the specified index 220: */ 221: public TableColumn getColumn(int i) 222: { 223: return (TableColumn) tableColumns.get(i); 224: } 225: 226: /** 227: * getColumnMargin returns column margin 228: * @return int column margin 229: */ 230: public int getColumnMargin() 231: { 232: return columnMargin; 233: } 234: 235: /** 236: * getColumnIndexAtX returns column that contains specified x-coordinate. 237: * @param x x-coordinate that column should contain 238: * @return int index of the column that contains specified x-coordinate relative 239: * to this column model 240: */ 241: public int getColumnIndexAtX(int x) 242: { 243: for (int i = 0; i < tableColumns.size(); ++i) 244: { 245: int w = ((TableColumn)tableColumns.get(i)).getWidth(); 246: if (0 <= x && x < w) 247: return i; 248: else 249: x -= w; 250: } 251: return -1; 252: } 253: 254: /** 255: * getTotalColumnWidth returns total width of all the columns including 256: * column's margins. 257: * 258: * @return total width of all the columns 259: */ 260: public int getTotalColumnWidth() 261: { 262: if (totalColumnWidth == -1) 263: recalcWidthCache(); 264: return totalColumnWidth; 265: } 266: 267: /** 268: * setSelectionModel sets selection model that will be used by this ColumnTableModel 269: * to keep track of currently selected columns 270: * 271: * @param model new selection model 272: * @exception IllegalArgumentException if model is null 273: */ 274: public void setSelectionModel(ListSelectionModel model) 275: { 276: if (model == null) 277: throw new IllegalArgumentException(); 278: 279: selectionModel = model; 280: selectionModel.addListSelectionListener(this); 281: } 282: 283: /** 284: * getSelectionModel returns selection model 285: * @return ListSelectionModel selection model 286: */ 287: public ListSelectionModel getSelectionModel() 288: { 289: return selectionModel; 290: } 291: 292: /** 293: * setColumnSelectionAllowed sets whether column selection is allowed 294: * or not. 295: * 296: * @param flag true if column selection is allowed and false otherwise 297: */ 298: public void setColumnSelectionAllowed(boolean flag) 299: { 300: columnSelectionAllowed = flag; 301: } 302: 303: /** 304: * getColumnSelectionAllowed indicates whether column selection is 305: * allowed or not. 306: * 307: * @return boolean true if column selection is allowed and false otherwise. 308: */ 309: public boolean getColumnSelectionAllowed() 310: { 311: return columnSelectionAllowed; 312: } 313: 314: /** 315: * getSelectedColumns returns array containing indexes of currently 316: * selected columns 317: * 318: * @return int[] array containing indexes of currently selected columns 319: */ 320: public int[] getSelectedColumns() 321: { 322: // FIXME: Implementation of this method was taken from private method 323: // JTable.getSelections(), which is used in various places in JTable 324: // including selected row calculations and cannot be simply removed. 325: // This design should be improved to illuminate duplication of code. 326: 327: ListSelectionModel lsm = this.selectionModel; 328: int sz = getSelectedColumnCount(); 329: int [] ret = new int[sz]; 330: 331: int lo = lsm.getMinSelectionIndex(); 332: int hi = lsm.getMaxSelectionIndex(); 333: int j = 0; 334: java.util.ArrayList ls = new java.util.ArrayList(); 335: if (lo != -1 && hi != -1) 336: { 337: switch (lsm.getSelectionMode()) 338: { 339: case ListSelectionModel.SINGLE_SELECTION: 340: ret[0] = lo; 341: break; 342: 343: case ListSelectionModel.SINGLE_INTERVAL_SELECTION: 344: for (int i = lo; i <= hi; ++i) 345: ret[j++] = i; 346: break; 347: 348: case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION: 349: for (int i = lo; i <= hi; ++i) 350: if (lsm.isSelectedIndex(i)) 351: ret[j++] = i; 352: break; 353: } 354: } 355: return ret; 356: } 357: 358: /** 359: * getSelectedColumnCount returns number of currently selected columns 360: * @return int number of currently selected columns 361: */ 362: public int getSelectedColumnCount() 363: { 364: // FIXME: Implementation of this method was taken from private method 365: // JTable.countSelections(), which is used in various places in JTable 366: // including selected row calculations and cannot be simply removed. 367: // This design should be improved to illuminate duplication of code. 368: 369: ListSelectionModel lsm = this.selectionModel; 370: int lo = lsm.getMinSelectionIndex(); 371: int hi = lsm.getMaxSelectionIndex(); 372: int sum = 0; 373: 374: if (lo != -1 && hi != -1) 375: { 376: switch (lsm.getSelectionMode()) 377: { 378: case ListSelectionModel.SINGLE_SELECTION: 379: sum = 1; 380: break; 381: 382: case ListSelectionModel.SINGLE_INTERVAL_SELECTION: 383: sum = hi - lo + 1; 384: break; 385: 386: case ListSelectionModel.MULTIPLE_INTERVAL_SELECTION: 387: for (int i = lo; i <= hi; ++i) 388: if (lsm.isSelectedIndex(i)) 389: ++sum; 390: break; 391: } 392: } 393: 394: return sum; 395: } 396: 397: /** 398: * addColumnModelListener adds specified listener to the model's 399: * listener list 400: * 401: * @param listener the listener to add 402: */ 403: public void addColumnModelListener(TableColumnModelListener listener) 404: { 405: listenerList.add(TableColumnModelListener.class, listener); 406: } 407: 408: /** 409: * removeColumnModelListener removes specified listener from the model's 410: * listener list. 411: * 412: * @param listener the listener to remove 413: */ 414: public void removeColumnModelListener(TableColumnModelListener listener) 415: { 416: listenerList.remove(TableColumnModelListener.class, listener); 417: } 418: 419: /** 420: * @since 1.4 421: */ 422: public TableColumnModelListener[] getColumnModelListeners() 423: { 424: return (TableColumnModelListener[]) 425: listenerList.getListeners(TableColumnModelListener.class); 426: } 427: 428: /** 429: * fireColumnAdded fires TableColumnModelEvent to registered 430: * TableColumnModelListeners to indicate that column was added 431: * 432: * @param e TableColumnModelEvent 433: */ 434: protected void fireColumnAdded(TableColumnModelEvent e) 435: { 436: TableColumnModelListener[] listeners = getColumnModelListeners(); 437: 438: for (int i=0; i< listeners.length; i++) 439: listeners[i].columnAdded(e); 440: } 441: 442: /** 443: * fireColumnAdded fires TableColumnModelEvent to registered 444: * TableColumnModelListeners to indicate that column was removed 445: * 446: * @param e TableColumnModelEvent 447: */ 448: protected void fireColumnRemoved(TableColumnModelEvent e) 449: { 450: TableColumnModelListener[] listeners = getColumnModelListeners(); 451: 452: for (int i=0; i< listeners.length; i++) 453: listeners[i].columnRemoved(e); 454: } 455: 456: /** 457: * fireColumnAdded fires TableColumnModelEvent to registered 458: * TableColumnModelListeners to indicate that column was moved 459: * 460: * @param e TableColumnModelEvent 461: */ 462: protected void fireColumnMoved(TableColumnModelEvent e) 463: { 464: TableColumnModelListener[] listeners = getColumnModelListeners(); 465: 466: for (int i=0; i< listeners.length; i++) 467: listeners[i].columnMoved(e); 468: } 469: 470: /** 471: * fireColumnSelectionChanged fires TableColumnModelEvent to model's 472: * registered TableColumnModelListeners to indicate that different column 473: * was selected. 474: * 475: * @param evt ListSelectionEvent 476: */ 477: protected void fireColumnSelectionChanged(ListSelectionEvent evt) 478: { 479: EventListener [] listeners = getListeners(TableColumnModelListener.class); 480: for (int i = 0; i < listeners.length; ++i) 481: ((TableColumnModelListener)listeners[i]).columnSelectionChanged(evt); 482: } 483: 484: /** 485: * fireColumnMarginChanged fires TableColumnModelEvent to model's 486: * registered TableColumnModelListeners to indicate that column margin 487: * was changed. 488: */ 489: protected void fireColumnMarginChanged() 490: { 491: EventListener [] listeners = getListeners(TableColumnModelListener.class); 492: for (int i = 0; i < listeners.length; ++i) 493: ((TableColumnModelListener)listeners[i]).columnMarginChanged(changeEvent); 494: } 495: 496: /** 497: * getListeners returns currently registered listeners with this model. 498: * @param listenerType type of listeners to return 499: * 500: * @return EventListener[] array of model's listeners of the specified type 501: */ 502: public EventListener[] getListeners(Class listenerType) 503: { 504: return listenerList.getListeners(listenerType); 505: } 506: 507: /** 508: * propertyChange handles changes occuring in the properties of the 509: * model's columns. 510: * 511: * @param evt PropertyChangeEvent 512: */ 513: public void propertyChange(PropertyChangeEvent evt) 514: { 515: if (evt.getPropertyName().equals(TableColumn.COLUMN_WIDTH_PROPERTY)) 516: invalidateWidthCache(); 517: } 518: 519: /** 520: * valueChanged handles changes in the selectionModel. 521: * @param e ListSelectionEvent 522: */ 523: public void valueChanged(ListSelectionEvent e) 524: { 525: fireColumnSelectionChanged(e); 526: } 527: 528: /** 529: * createSelectionModel creates selection model that will keep track 530: * of currently selected column(s) 531: * 532: * @return ListSelectionModel selection model of the columns 533: */ 534: protected ListSelectionModel createSelectionModel() 535: { 536: return new DefaultListSelectionModel(); 537: } 538: 539: /** 540: * recalcWidthCache calculates total width of the columns. 541: * If the current cache of the total width is in invalidated state, 542: * then width is recalculated. Otherwise nothing is done. 543: */ 544: protected void recalcWidthCache() 545: { 546: if (totalColumnWidth == -1) 547: { 548: totalColumnWidth = 0; 549: for (int i = 0; i < tableColumns.size(); ++i) 550: { 551: totalColumnWidth += ((TableColumn)tableColumns.get(i)).getWidth(); 552: } 553: } 554: } 555: 556: /** 557: * invalidateWidthCache 558: */ 559: private void invalidateWidthCache() 560: { 561: totalColumnWidth = -1; 562: } 563: }
GNU Classpath (0.20) |