001/* 002 * $Id: TableRolloverController.java 3641 2010-04-01 10:48:43Z kleopatra $ 003 * 004 * Copyright 2008 Sun Microsystems, Inc., 4150 Network Circle, 005 * Santa Clara, California 95054, U.S.A. All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public 018 * License along with this library; if not, write to the Free Software 019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 020 */ 021package org.jdesktop.swingx.rollover; 022 023import java.awt.Cursor; 024import java.awt.Point; 025import java.awt.Rectangle; 026import java.util.ArrayList; 027import java.util.List; 028 029import javax.swing.JTable; 030import javax.swing.table.TableCellRenderer; 031 032/** 033 * listens to rollover properties. Repaints effected component regions. Updates 034 * link cursor. 035 * 036 * @author Jeanette Winzenburg 037 */ 038public class TableRolloverController<T extends JTable> extends 039 RolloverController<T> { 040 041 private Cursor oldCursor; 042 043 // --------------------------- JTable rollover 044 045 @Override 046 protected void rollover(Point oldLocation, Point newLocation) { 047 // check which rows are effected and need repaint 048 boolean paintOldRow = hasRow(oldLocation); 049 boolean paintNewRow = hasRow(newLocation); 050 if (paintOldRow && paintNewRow) { 051 if (oldLocation.y == newLocation.y) { 052 // row unchanged, no need for repaint 053 paintOldRow = false; 054 paintNewRow = false; 055 } 056 } 057 // check which columns are effected and need repaint 058 boolean paintOldColumn = hasColumn(oldLocation); 059 boolean paintNewColumn = hasColumn(newLocation); 060 if (paintOldColumn && paintNewColumn) { 061 if (oldLocation.x == newLocation.x) { 062 // column unchanged, no need for repaint 063 paintOldColumn = false; 064 paintNewColumn = false; 065 } 066 } 067 068 List<Rectangle> rectangles = getPaintRectangles(null, oldLocation, paintOldRow, paintOldColumn); 069 rectangles = getPaintRectangles(rectangles, newLocation, paintNewRow, paintNewColumn); 070 if (rectangles != null) { 071 for (Rectangle rectangle : rectangles) { 072 component.repaint(rectangle); 073 } 074 } 075 setRolloverCursor(newLocation); 076 } 077 078 /** 079 * @param rectangles List of rectangles to paint, maybe null 080 * @param cellLocation the location of the cell, guaranteed to be not null 081 * @param paintRow boolean indicating whether the row should be painted 082 * @param paintColumn boolean indicating whether the column should be painted 083 * @return list of rectangles to paint, maybe null 084 */ 085 private List<Rectangle> getPaintRectangles(List<Rectangle> rectangles, Point cellLocation, 086 boolean paintRow, boolean paintColumn) { 087 if (!paintRow && !paintColumn) return rectangles; 088 if (rectangles == null) { 089 rectangles = new ArrayList<Rectangle>(); 090 } 091 Rectangle r = component.getCellRect(cellLocation.y, cellLocation.x, 092 false); 093 if (paintRow) { 094 rectangles.add(new Rectangle(0, r.y, component.getWidth(), 095 r.height)); 096 } 097 if (paintColumn) { 098 rectangles.add(new Rectangle(r.x, 0, r.width, component 099 .getHeight())); 100 } 101 return rectangles; 102 } 103 104 /** 105 * @param cellLocation the cell location to check, may be null 106 * @return a boolean indicating whether the given cellLocation has a column 107 * to paint 108 */ 109 private boolean hasColumn(Point cellLocation) { 110 return cellLocation != null && cellLocation.x >= 0; 111 } 112 113 /** 114 * @param cellLocation the cell location to check, may be null 115 * @return a boolean indicating whether the given cellLocation has a row 116 * to paint 117 */ 118 private boolean hasRow(Point cellLocation) { 119 return cellLocation != null && cellLocation.y >= 0; 120 } 121 122 /** 123 * overridden to return false if cell editable. 124 */ 125 @Override 126 protected boolean isClickable(Point location) { 127 return super.isClickable(location) 128 && !component.isCellEditable(location.y, location.x); 129 } 130 131 @Override 132 protected RolloverRenderer getRolloverRenderer(Point location, 133 boolean prepare) { 134 TableCellRenderer renderer = component.getCellRenderer(location.y, 135 location.x); 136 RolloverRenderer rollover = renderer instanceof RolloverRenderer ? (RolloverRenderer) renderer 137 : null; 138 if ((rollover != null) && !rollover.isEnabled()) { 139 rollover = null; 140 } 141 if ((rollover != null) && prepare) { 142 component.prepareRenderer(renderer, location.y, location.x); 143 } 144 return rollover; 145 } 146 147 private void setRolloverCursor(Point location) { 148 if (hasRollover(location)) { 149 if (oldCursor == null) { 150 oldCursor = component.getCursor(); 151 component.setCursor(Cursor 152 .getPredefinedCursor(Cursor.HAND_CURSOR)); 153 } 154 } else { 155 if (oldCursor != null) { 156 component.setCursor(oldCursor); 157 oldCursor = null; 158 } 159 } 160 161 } 162 163 @Override 164 protected Point getFocusedCell() { 165 int leadRow = component.getSelectionModel().getLeadSelectionIndex(); 166 int leadColumn = component.getColumnModel().getSelectionModel() 167 .getLeadSelectionIndex(); 168 return new Point(leadColumn, leadRow); 169 } 170 171}