/* * @(#)Sticky.java 7/26/2005 * * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved. */ package com.jidesoft.swing; import javax.swing.*; import javax.swing.tree.TreePath; import java.awt.*; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; /** * <code>Sticky</code> is a helper class to make JList or JTree or JTable changing selection when mouse moves. To use * it, you simply call * <pre><code> * JList list = new JList(); * new Sticky(list); * </code></pre> * or * <pre><code> * JTree tree = new JTree(); * new Sticky(tree); * </code></pre> */ public class Sticky { private JComponent _target; private static final StickyMouseMotionListener STICKY_MOUSE_MOTION_LISTENER = new StickyMouseMotionListener(); public Sticky(JList list) { _target = list; install(); } public Sticky(JTree tree) { _target = tree; install(); } public Sticky(JTable table) { _target = table; install(); } /** * Installs the listener to make the list or tree sticky. This method is called by constructor, so you don't need to * call it unless you called {@link #uninstall()} to remove the listener. */ public void install() { _target.addMouseMotionListener(STICKY_MOUSE_MOTION_LISTENER); } /** * Uninstalls the listener. */ public void uninstall() { _target.removeMouseMotionListener(STICKY_MOUSE_MOTION_LISTENER); } static private class StickyMouseMotionListener extends MouseMotionAdapter { // // MouseMotionListener: // NOTE: this is added to both the List and ComboBox // @Override public void mouseMoved(MouseEvent anEvent) { if (anEvent.getSource() instanceof JList) { JList list = (JList) anEvent.getSource(); Point location = anEvent.getPoint(); Rectangle r = new Rectangle(); list.computeVisibleRect(r); if (r.contains(location)) { updateListSelectionForEvent(anEvent, list, false); } } else if (anEvent.getSource() instanceof JTree) { JTree tree = (JTree) anEvent.getSource(); Point location = anEvent.getPoint(); Rectangle r = new Rectangle(); tree.computeVisibleRect(r); if (r.contains(location)) { updateTreeSelectionForEvent(anEvent, tree, false); } } else if (anEvent.getSource() instanceof JTable) { JTable table = (JTable) anEvent.getSource(); Point location = anEvent.getPoint(); Rectangle r = new Rectangle(); table.computeVisibleRect(r); if (r.contains(location)) { updateTableSelectionForEvent(anEvent, table, false); } } } } /** * A utility method used by the event listeners. Given a mouse event, it changes the list selection to the list * item below the mouse. */ private static void updateListSelectionForEvent(MouseEvent anEvent, JList list, boolean shouldScroll) { // XXX - only seems to be called from this class. shouldScroll flag is // never true Point location = anEvent.getPoint(); if (list == null) return; int index = list.locationToIndex(location); if (index == -1) { if (location.y < 0) index = 0; else index = list.getModel() == null ? 0 : list.getModel().getSize() - 1; } if (list.getSelectedIndex() != index && index >= 0 && index < list.getModel().getSize()) { list.setSelectedIndex(index); if (shouldScroll) list.ensureIndexIsVisible(index); } } /** * A utility method used by the event listeners. Given a mouse event, it changes the list selection to the list * item below the mouse. */ private static void updateTreeSelectionForEvent(MouseEvent anEvent, JTree tree, boolean shouldScroll) { Point location = anEvent.getPoint(); if (tree == null) return; int index = tree.getRowForLocation(location.x, location.y); if (index != -1) { TreePath pathForRow = tree.getPathForRow(index); if (tree.getSelectionPath() != pathForRow) { tree.setSelectionRow(index); if (shouldScroll) tree.makeVisible(pathForRow); } } } /** * A utility method used by the event listeners. Given a mouse event, it changes the table selection to the table * item below the mouse. */ private static void updateTableSelectionForEvent(MouseEvent anEvent, JTable table, boolean shouldScroll) { // XXX - only seems to be called from this class. shouldScroll flag is // never true Point location = anEvent.getPoint(); if (table == null) return; int index = table.rowAtPoint(location); if (index == -1) { if (location.y < 0) index = 0; else index = table.getModel() == null ? 0 : table.getModel().getRowCount() - 1; } if (table.getSelectedRow() != index) { table.getSelectionModel().setSelectionInterval(index, index); if (shouldScroll) JideSwingUtilities.ensureRowVisible(table, index); } } }