/******************************************************************************* * Breakout Cave Survey Visualizer * * Copyright (C) 2014 James Edwards * * jedwards8 at fastmail dot fm * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *******************************************************************************/ package org.andork.swing.list; import java.awt.Component; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; import javax.swing.JList; import javax.swing.ListCellRenderer; import javax.swing.SwingUtilities; import org.andork.awt.event.MouseRetargeter; public class ListCellRendererRetargeter extends MouseRetargeter { protected MouseEvent prevEvent; protected boolean allowButtonChange; protected int rolloverIndex; protected int pressIndex; @Override protected Point convertPoint(Component origComp, Point origPoint, Component newTarget) { JList list = (JList) origComp; int index = findRolloverIndex(list, origPoint); if (index >= 0) { Rectangle bounds = list.getCellBounds(index, index); Point newPoint = new Point(origPoint.x - bounds.x, origPoint.y - bounds.y); ListCellRenderer cellRenderer = list.getCellRenderer(); Object value = list.getModel().getElementAt(index); boolean isSelected = list.getSelectionModel().isSelectedIndex(index); boolean cellHasFocus = list.hasFocus() && isSelected; Component rendComp = cellRenderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus); if (rendComp != null) { rendComp.setBounds(list.getCellBounds(index, index)); rendComp.doLayout(); return SwingUtilities.convertPoint(rendComp, newPoint, newTarget); } } return new Point(0, 0); } private int findRolloverIndex(JList list, Point p) { for (int i = 0; i < list.getModel().getSize(); i++) { Rectangle bounds = list.getCellBounds(i, i); if (bounds.y + bounds.height > p.y) { return i; } } return -1; } @Override protected Component getDeepestComponent(MouseEvent e) { JList list = (JList) e.getComponent(); int index = findRolloverIndex(list, e.getPoint()); if (index >= 0) { Rectangle bounds = list.getCellBounds(index, index); int x = e.getX() - bounds.x; int y = e.getY() - bounds.y; ListCellRenderer cellRenderer = list.getCellRenderer(); Object value = list.getModel().getElementAt(index); boolean isSelected = list.getSelectionModel().isSelectedIndex(index); boolean cellHasFocus = list.hasFocus() && isSelected; Component rendComp = cellRenderer.getListCellRendererComponent( list, value, index, isSelected, cellHasFocus); if (rendComp != null) { rendComp.setBounds(list.getCellBounds(index, index)); rendComp.doLayout(); Component deepest = SwingUtilities.getDeepestComponentAt(rendComp, x, y); return deepest != rendComp ? deepest : null; } } return null; } public int getPressIndex() { return pressIndex; } public int getRolloverIndex() { return rolloverIndex; } public boolean isAllowButtonChange() { return allowButtonChange; } @Override public void mouseDragged(MouseEvent e) { JList list = (JList) e.getComponent(); rolloverIndex = list.locationToIndex(e.getPoint()); repaintFor(prevEvent); super.mouseDragged(e); repaintFor(e); prevEvent = e; } @Override public void mouseEntered(MouseEvent e) { JList list = (JList) e.getComponent(); rolloverIndex = list.locationToIndex(e.getPoint()); repaintFor(prevEvent); super.mouseEntered(e); repaintFor(e); prevEvent = e; } @Override public void mouseExited(MouseEvent e) { rolloverIndex = -1; repaintFor(prevEvent); super.mouseExited(e); prevEvent = null; } @Override public void mouseMoved(MouseEvent e) { JList list = (JList) e.getComponent(); rolloverIndex = list.locationToIndex(e.getPoint()); repaintFor(prevEvent); super.mouseMoved(e); repaintFor(e); prevEvent = e; } @Override public void mousePressed(MouseEvent e) { JList list = (JList) e.getComponent(); pressIndex = rolloverIndex = list.locationToIndex(e.getPoint()); repaintFor(prevEvent); super.mousePressed(e); repaintFor(e); prevEvent = e; } @Override public void mouseReleased(MouseEvent e) { JList list = (JList) e.getComponent(); rolloverIndex = list.locationToIndex(e.getPoint()); repaintFor(prevEvent); repaintCell(list, pressIndex); super.mouseReleased(e); repaintFor(e); prevEvent = e; } protected void repaintCell(JList list, int index) { if (index >= 0) { list.repaint(list.getCellBounds(index, index)); } } protected void repaintFor(MouseEvent e) { if (e == null) { return; } JList list = (JList) e.getComponent(); int index = list.locationToIndex(e.getPoint()); repaintCell(list, index); } @Override protected void retarget(MouseEvent e, Component target, int newID) { allowButtonChange = true; try { super.retarget(e, target, newID); } finally { allowButtonChange = false; } } @Override protected void retarget(MouseWheelEvent e, Component target) { allowButtonChange = true; try { super.retarget(e, target); } finally { allowButtonChange = false; } } }