001: /*
002: * @(#)Sticky.java 7/26/2005
003: *
004: * Copyright 2002 - 2005 JIDE Software Inc. All rights reserved.
005: */
006: package com.jidesoft.swing;
007:
008: import javax.swing.*;
009: import javax.swing.tree.TreePath;
010: import java.awt.*;
011: import java.awt.event.MouseEvent;
012: import java.awt.event.MouseMotionAdapter;
013:
014: /**
015: * <code>Sticky</code> is a helper class to make JList or JTree changing selection when mouse moves.
016: * To use it, you simply call
017: * <pre><code>
018: * JList list = new JList();
019: * new Sticky(list);
020: * </code></pre>
021: * or
022: * <pre><code>
023: * JTree tree = new JTree();
024: * new Sticky(tree);
025: * </code></pre>
026: */
027: public class Sticky {
028: private JComponent _target;
029: private final static StrickyMouseMotionListener STICKY_MOUSE_MOTION_LISTENER = new StrickyMouseMotionListener();
030:
031: public Sticky(JList list) {
032: _target = list;
033: install();
034: }
035:
036: public Sticky(JTree tree) {
037: _target = tree;
038: install();
039: }
040:
041: public Sticky(JTable table) {
042: _target = table;
043: install();
044: }
045:
046: /**
047: * Installs the listener to make the list or tree sticky. This method is called by constructor, so you
048: * don't need to call it unless you called {@link #uninstall()} to remove the listener.
049: */
050: public void install() {
051: _target.addMouseMotionListener(STICKY_MOUSE_MOTION_LISTENER);
052: }
053:
054: /**
055: * Uninstalls the listener.
056: */
057: public void uninstall() {
058: _target.removeMouseMotionListener(STICKY_MOUSE_MOTION_LISTENER);
059: }
060:
061: static private class StrickyMouseMotionListener extends
062: MouseMotionAdapter {
063: //
064: // MouseMotionListener:
065: // NOTE: this is added to both the List and ComboBox
066: //
067: @Override
068: public void mouseMoved(MouseEvent anEvent) {
069: if (anEvent.getSource() instanceof JList) {
070: JList list = (JList) anEvent.getSource();
071: Point location = anEvent.getPoint();
072: Rectangle r = new Rectangle();
073: list.computeVisibleRect(r);
074: if (r.contains(location)) {
075: updateListSelectionForEvent(anEvent, list, false);
076: }
077: } else if (anEvent.getSource() instanceof JTree) {
078: JTree tree = (JTree) anEvent.getSource();
079: Point location = anEvent.getPoint();
080: Rectangle r = new Rectangle();
081: tree.computeVisibleRect(r);
082: if (r.contains(location)) {
083: updateTreeSelectionForEvent(anEvent, tree, false);
084: }
085: } else if (anEvent.getSource() instanceof JTable) {
086: JTable table = (JTable) anEvent.getSource();
087: Point location = anEvent.getPoint();
088: Rectangle r = new Rectangle();
089: table.computeVisibleRect(r);
090: if (r.contains(location)) {
091: updateTableSelectionForEvent(anEvent, table, false);
092: }
093: }
094: }
095: }
096:
097: /**
098: * A utility method used by the event listeners. Given a mouse event, it changes
099: * the list selection to the list item below the mouse.
100: */
101: private static void updateListSelectionForEvent(MouseEvent anEvent,
102: JList list, boolean shouldScroll) {
103: // XXX - only seems to be called from this class. shouldScroll flag is
104: // never true
105: Point location = anEvent.getPoint();
106: if (list == null)
107: return;
108: int index = list.locationToIndex(location);
109: if (index == -1) {
110: if (location.y < 0)
111: index = 0;
112: else
113: index = list.getModel() == null ? 0 : list.getModel()
114: .getSize() - 1;
115: }
116: if (list.getSelectedIndex() != index && index >= 0
117: && index < list.getModel().getSize()) {
118: list.setSelectedIndex(index);
119: if (shouldScroll)
120: list.ensureIndexIsVisible(index);
121: }
122: }
123:
124: /**
125: * A utility method used by the event listeners. Given a mouse event, it changes
126: * the list selection to the list item below the mouse.
127: */
128: private static void updateTreeSelectionForEvent(MouseEvent anEvent,
129: JTree tree, boolean shouldScroll) {
130: Point location = anEvent.getPoint();
131: if (tree == null)
132: return;
133: int index = tree.getRowForLocation(location.x, location.y);
134: if (index != -1) {
135: TreePath pathForRow = tree.getPathForRow(index);
136: if (tree.getSelectionPath() != pathForRow) {
137: tree.setSelectionRow(index);
138: if (shouldScroll)
139: tree.makeVisible(pathForRow);
140: }
141: }
142: }
143:
144: /**
145: * A utility method used by the event listeners. Given a mouse event, it changes
146: * the table selection to the table item below the mouse.
147: */
148: private static void updateTableSelectionForEvent(
149: MouseEvent anEvent, JTable table, boolean shouldScroll) {
150: // XXX - only seems to be called from this class. shouldScroll flag is
151: // never true
152: Point location = anEvent.getPoint();
153: if (table == null)
154: return;
155: int index = table.rowAtPoint(location);
156: if (index == -1) {
157: if (location.y < 0)
158: index = 0;
159: else
160: index = table.getModel() == null ? 0 : table.getModel()
161: .getRowCount() - 1;
162: }
163: if (table.getSelectedRow() != index) {
164: table.getSelectionModel()
165: .setSelectionInterval(index, index);
166: if (shouldScroll)
167: JideSwingUtilities.ensureRowVisible(table, index);
168: }
169: }
170: }
|