mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 18:14:38 +02:00
8187443: Forest Consolidation: Move files to unified layout
Reviewed-by: darcy, ihse
This commit is contained in:
parent
270fe13182
commit
3789983e89
56923 changed files with 3 additions and 15727 deletions
888
src/java.desktop/share/classes/javax/swing/ToolTipManager.java
Normal file
888
src/java.desktop/share/classes/javax/swing/ToolTipManager.java
Normal file
|
@ -0,0 +1,888 @@
|
|||
/*
|
||||
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
|
||||
package javax.swing;
|
||||
|
||||
import java.awt.event.*;
|
||||
import java.awt.*;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Manages all the <code>ToolTips</code> in the system.
|
||||
* <p>
|
||||
* ToolTipManager contains numerous properties for configuring how long it
|
||||
* will take for the tooltips to become visible, and how long till they
|
||||
* hide. Consider a component that has a different tooltip based on where
|
||||
* the mouse is, such as JTree. When the mouse moves into the JTree and
|
||||
* over a region that has a valid tooltip, the tooltip will become
|
||||
* visible after <code>initialDelay</code> milliseconds. After
|
||||
* <code>dismissDelay</code> milliseconds the tooltip will be hidden. If
|
||||
* the mouse is over a region that has a valid tooltip, and the tooltip
|
||||
* is currently visible, when the mouse moves to a region that doesn't have
|
||||
* a valid tooltip the tooltip will be hidden. If the mouse then moves back
|
||||
* into a region that has a valid tooltip within <code>reshowDelay</code>
|
||||
* milliseconds, the tooltip will immediately be shown, otherwise the
|
||||
* tooltip will be shown again after <code>initialDelay</code> milliseconds.
|
||||
*
|
||||
* @see JComponent#createToolTip
|
||||
* @author Dave Moore
|
||||
* @author Rich Schiavi
|
||||
* @since 1.2
|
||||
*/
|
||||
public class ToolTipManager extends MouseAdapter implements MouseMotionListener {
|
||||
Timer enterTimer, exitTimer, insideTimer;
|
||||
String toolTipText;
|
||||
Point preferredLocation;
|
||||
JComponent insideComponent;
|
||||
MouseEvent mouseEvent;
|
||||
boolean showImmediately;
|
||||
private static final Object TOOL_TIP_MANAGER_KEY = new Object();
|
||||
transient Popup tipWindow;
|
||||
/** The Window tip is being displayed in. This will be non-null if
|
||||
* the Window tip is in differs from that of insideComponent's Window.
|
||||
*/
|
||||
private Window window;
|
||||
JToolTip tip;
|
||||
|
||||
private Rectangle popupRect = null;
|
||||
private Rectangle popupFrameRect = null;
|
||||
|
||||
boolean enabled = true;
|
||||
private boolean tipShowing = false;
|
||||
|
||||
private FocusListener focusChangeListener = null;
|
||||
private MouseMotionListener moveBeforeEnterListener = null;
|
||||
private KeyListener accessibilityKeyListener = null;
|
||||
|
||||
private KeyStroke postTip;
|
||||
private KeyStroke hideTip;
|
||||
|
||||
/**
|
||||
* Lightweight popup enabled.
|
||||
*/
|
||||
protected boolean lightWeightPopupEnabled = true;
|
||||
/**
|
||||
* Heavyweight popup enabled.
|
||||
*/
|
||||
protected boolean heavyWeightPopupEnabled = false;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
ToolTipManager() {
|
||||
enterTimer = new Timer(750, new insideTimerAction());
|
||||
enterTimer.setRepeats(false);
|
||||
exitTimer = new Timer(500, new outsideTimerAction());
|
||||
exitTimer.setRepeats(false);
|
||||
insideTimer = new Timer(4000, new stillInsideTimerAction());
|
||||
insideTimer.setRepeats(false);
|
||||
|
||||
moveBeforeEnterListener = new MoveBeforeEnterListener();
|
||||
accessibilityKeyListener = new AccessibilityKeyListener();
|
||||
|
||||
postTip = KeyStroke.getKeyStroke(KeyEvent.VK_F1, InputEvent.CTRL_MASK);
|
||||
hideTip = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the tooltip.
|
||||
*
|
||||
* @param flag true to enable the tip, false otherwise
|
||||
*/
|
||||
public void setEnabled(boolean flag) {
|
||||
enabled = flag;
|
||||
if (!flag) {
|
||||
hideTipWindow();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this object is enabled.
|
||||
*
|
||||
* @return true if this object is enabled, false otherwise
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* When displaying the <code>JToolTip</code>, the
|
||||
* <code>ToolTipManager</code> chooses to use a lightweight
|
||||
* <code>JPanel</code> if it fits. This method allows you to
|
||||
* disable this feature. You have to do disable it if your
|
||||
* application mixes light weight and heavy weights components.
|
||||
*
|
||||
* @param aFlag true if a lightweight panel is desired, false otherwise
|
||||
*
|
||||
*/
|
||||
public void setLightWeightPopupEnabled(boolean aFlag){
|
||||
lightWeightPopupEnabled = aFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if lightweight (all-Java) <code>Tooltips</code>
|
||||
* are in use, or false if heavyweight (native peer)
|
||||
* <code>Tooltips</code> are being used.
|
||||
*
|
||||
* @return true if lightweight <code>ToolTips</code> are in use
|
||||
*/
|
||||
public boolean isLightWeightPopupEnabled() {
|
||||
return lightWeightPopupEnabled;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Specifies the initial delay value.
|
||||
*
|
||||
* @param milliseconds the number of milliseconds to delay
|
||||
* (after the cursor has paused) before displaying the
|
||||
* tooltip
|
||||
* @see #getInitialDelay
|
||||
*/
|
||||
public void setInitialDelay(int milliseconds) {
|
||||
enterTimer.setInitialDelay(milliseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initial delay value.
|
||||
*
|
||||
* @return an integer representing the initial delay value,
|
||||
* in milliseconds
|
||||
* @see #setInitialDelay
|
||||
*/
|
||||
public int getInitialDelay() {
|
||||
return enterTimer.getInitialDelay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the dismissal delay value.
|
||||
*
|
||||
* @param milliseconds the number of milliseconds to delay
|
||||
* before taking away the tooltip
|
||||
* @see #getDismissDelay
|
||||
*/
|
||||
public void setDismissDelay(int milliseconds) {
|
||||
insideTimer.setInitialDelay(milliseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dismissal delay value.
|
||||
*
|
||||
* @return an integer representing the dismissal delay value,
|
||||
* in milliseconds
|
||||
* @see #setDismissDelay
|
||||
*/
|
||||
public int getDismissDelay() {
|
||||
return insideTimer.getInitialDelay();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to specify the amount of time before the user has to wait
|
||||
* <code>initialDelay</code> milliseconds before a tooltip will be
|
||||
* shown. That is, if the tooltip is hidden, and the user moves into
|
||||
* a region of the same Component that has a valid tooltip within
|
||||
* <code>milliseconds</code> milliseconds the tooltip will immediately
|
||||
* be shown. Otherwise, if the user moves into a region with a valid
|
||||
* tooltip after <code>milliseconds</code> milliseconds, the user
|
||||
* will have to wait an additional <code>initialDelay</code>
|
||||
* milliseconds before the tooltip is shown again.
|
||||
*
|
||||
* @param milliseconds time in milliseconds
|
||||
* @see #getReshowDelay
|
||||
*/
|
||||
public void setReshowDelay(int milliseconds) {
|
||||
exitTimer.setInitialDelay(milliseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reshow delay property.
|
||||
*
|
||||
* @return reshown delay property
|
||||
* @see #setReshowDelay
|
||||
*/
|
||||
public int getReshowDelay() {
|
||||
return exitTimer.getInitialDelay();
|
||||
}
|
||||
|
||||
// Returns GraphicsConfiguration instance that toFind belongs to or null
|
||||
// if drawing point is set to a point beyond visible screen area (e.g.
|
||||
// Point(20000, 20000))
|
||||
private GraphicsConfiguration getDrawingGC(Point toFind) {
|
||||
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsDevice devices[] = env.getScreenDevices();
|
||||
for (GraphicsDevice device : devices) {
|
||||
GraphicsConfiguration config = device.getDefaultConfiguration();
|
||||
Rectangle rect = config.getBounds();
|
||||
if (rect.contains(toFind)) {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
void showTipWindow() {
|
||||
if(insideComponent == null || !insideComponent.isShowing())
|
||||
return;
|
||||
String mode = UIManager.getString("ToolTipManager.enableToolTipMode");
|
||||
if ("activeApplication".equals(mode)) {
|
||||
KeyboardFocusManager kfm =
|
||||
KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
if (kfm.getFocusedWindow() == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (enabled) {
|
||||
Dimension size;
|
||||
Point screenLocation = insideComponent.getLocationOnScreen();
|
||||
Point location;
|
||||
|
||||
Point toFind;
|
||||
if (preferredLocation != null) {
|
||||
toFind = new Point(screenLocation.x + preferredLocation.x,
|
||||
screenLocation.y + preferredLocation.y);
|
||||
} else {
|
||||
toFind = mouseEvent.getLocationOnScreen();
|
||||
}
|
||||
|
||||
GraphicsConfiguration gc = getDrawingGC(toFind);
|
||||
if (gc == null) {
|
||||
toFind = mouseEvent.getLocationOnScreen();
|
||||
gc = getDrawingGC(toFind);
|
||||
if (gc == null) {
|
||||
gc = insideComponent.getGraphicsConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle sBounds = gc.getBounds();
|
||||
Insets screenInsets = Toolkit.getDefaultToolkit()
|
||||
.getScreenInsets(gc);
|
||||
// Take into account screen insets, decrease viewport
|
||||
sBounds.x += screenInsets.left;
|
||||
sBounds.y += screenInsets.top;
|
||||
sBounds.width -= (screenInsets.left + screenInsets.right);
|
||||
sBounds.height -= (screenInsets.top + screenInsets.bottom);
|
||||
boolean leftToRight
|
||||
= SwingUtilities.isLeftToRight(insideComponent);
|
||||
|
||||
// Just to be paranoid
|
||||
hideTipWindow();
|
||||
|
||||
tip = insideComponent.createToolTip();
|
||||
tip.setTipText(toolTipText);
|
||||
size = tip.getPreferredSize();
|
||||
|
||||
if(preferredLocation != null) {
|
||||
location = toFind;
|
||||
if (!leftToRight) {
|
||||
location.x -= size.width;
|
||||
}
|
||||
} else {
|
||||
location = new Point(screenLocation.x + mouseEvent.getX(),
|
||||
screenLocation.y + mouseEvent.getY() + 20);
|
||||
if (!leftToRight) {
|
||||
if(location.x - size.width>=0) {
|
||||
location.x -= size.width;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// we do not adjust x/y when using awt.Window tips
|
||||
if (popupRect == null){
|
||||
popupRect = new Rectangle();
|
||||
}
|
||||
popupRect.setBounds(location.x,location.y,
|
||||
size.width,size.height);
|
||||
|
||||
// Fit as much of the tooltip on screen as possible
|
||||
if (location.x < sBounds.x) {
|
||||
location.x = sBounds.x;
|
||||
}
|
||||
else if (location.x - sBounds.x + size.width > sBounds.width) {
|
||||
location.x = sBounds.x + Math.max(0, sBounds.width - size.width)
|
||||
;
|
||||
}
|
||||
if (location.y < sBounds.y) {
|
||||
location.y = sBounds.y;
|
||||
}
|
||||
else if (location.y - sBounds.y + size.height > sBounds.height) {
|
||||
location.y = sBounds.y + Math.max(0, sBounds.height - size.height);
|
||||
}
|
||||
|
||||
PopupFactory popupFactory = PopupFactory.getSharedInstance();
|
||||
|
||||
if (lightWeightPopupEnabled) {
|
||||
int y = getPopupFitHeight(popupRect, insideComponent);
|
||||
int x = getPopupFitWidth(popupRect,insideComponent);
|
||||
if (x>0 || y>0) {
|
||||
popupFactory.setPopupType(PopupFactory.MEDIUM_WEIGHT_POPUP);
|
||||
} else {
|
||||
popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP);
|
||||
}
|
||||
}
|
||||
else {
|
||||
popupFactory.setPopupType(PopupFactory.MEDIUM_WEIGHT_POPUP);
|
||||
}
|
||||
tipWindow = popupFactory.getPopup(insideComponent, tip,
|
||||
location.x,
|
||||
location.y);
|
||||
popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP);
|
||||
|
||||
tipWindow.show();
|
||||
|
||||
Window componentWindow = SwingUtilities.windowForComponent(
|
||||
insideComponent);
|
||||
|
||||
window = SwingUtilities.windowForComponent(tip);
|
||||
if (window != null && window != componentWindow) {
|
||||
window.addMouseListener(this);
|
||||
}
|
||||
else {
|
||||
window = null;
|
||||
}
|
||||
|
||||
insideTimer.start();
|
||||
tipShowing = true;
|
||||
}
|
||||
}
|
||||
|
||||
void hideTipWindow() {
|
||||
if (tipWindow != null) {
|
||||
if (window != null) {
|
||||
window.removeMouseListener(this);
|
||||
window = null;
|
||||
}
|
||||
tipWindow.hide();
|
||||
tipWindow = null;
|
||||
tipShowing = false;
|
||||
tip = null;
|
||||
insideTimer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a shared <code>ToolTipManager</code> instance.
|
||||
*
|
||||
* @return a shared <code>ToolTipManager</code> object
|
||||
*/
|
||||
public static ToolTipManager sharedInstance() {
|
||||
Object value = SwingUtilities.appContextGet(TOOL_TIP_MANAGER_KEY);
|
||||
if (value instanceof ToolTipManager) {
|
||||
return (ToolTipManager) value;
|
||||
}
|
||||
ToolTipManager manager = new ToolTipManager();
|
||||
SwingUtilities.appContextPut(TOOL_TIP_MANAGER_KEY, manager);
|
||||
return manager;
|
||||
}
|
||||
|
||||
// add keylistener here to trigger tip for access
|
||||
/**
|
||||
* Registers a component for tooltip management.
|
||||
* <p>
|
||||
* This will register key bindings to show and hide the tooltip text
|
||||
* only if <code>component</code> has focus bindings. This is done
|
||||
* so that components that are not normally focus traversable, such
|
||||
* as <code>JLabel</code>, are not made focus traversable as a result
|
||||
* of invoking this method.
|
||||
*
|
||||
* @param component a <code>JComponent</code> object to add
|
||||
* @see JComponent#isFocusTraversable
|
||||
*/
|
||||
public void registerComponent(JComponent component) {
|
||||
component.removeMouseListener(this);
|
||||
component.addMouseListener(this);
|
||||
component.removeMouseMotionListener(moveBeforeEnterListener);
|
||||
component.addMouseMotionListener(moveBeforeEnterListener);
|
||||
component.removeKeyListener(accessibilityKeyListener);
|
||||
component.addKeyListener(accessibilityKeyListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a component from tooltip control.
|
||||
*
|
||||
* @param component a <code>JComponent</code> object to remove
|
||||
*/
|
||||
public void unregisterComponent(JComponent component) {
|
||||
component.removeMouseListener(this);
|
||||
component.removeMouseMotionListener(moveBeforeEnterListener);
|
||||
component.removeKeyListener(accessibilityKeyListener);
|
||||
}
|
||||
|
||||
// implements java.awt.event.MouseListener
|
||||
/**
|
||||
* Called when the mouse enters the region of a component.
|
||||
* This determines whether the tool tip should be shown.
|
||||
*
|
||||
* @param event the event in question
|
||||
*/
|
||||
public void mouseEntered(MouseEvent event) {
|
||||
initiateToolTip(event);
|
||||
}
|
||||
|
||||
private void initiateToolTip(MouseEvent event) {
|
||||
if (event.getSource() == window) {
|
||||
return;
|
||||
}
|
||||
JComponent component = (JComponent)event.getSource();
|
||||
component.removeMouseMotionListener(moveBeforeEnterListener);
|
||||
|
||||
exitTimer.stop();
|
||||
|
||||
Point location = event.getPoint();
|
||||
// ensure tooltip shows only in proper place
|
||||
if (location.x < 0 ||
|
||||
location.x >=component.getWidth() ||
|
||||
location.y < 0 ||
|
||||
location.y >= component.getHeight()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (insideComponent != null) {
|
||||
enterTimer.stop();
|
||||
}
|
||||
// A component in an unactive internal frame is sent two
|
||||
// mouseEntered events, make sure we don't end up adding
|
||||
// ourselves an extra time.
|
||||
component.removeMouseMotionListener(this);
|
||||
component.addMouseMotionListener(this);
|
||||
|
||||
boolean sameComponent = (insideComponent == component);
|
||||
|
||||
insideComponent = component;
|
||||
if (tipWindow != null){
|
||||
mouseEvent = event;
|
||||
if (showImmediately) {
|
||||
String newToolTipText = component.getToolTipText(event);
|
||||
Point newPreferredLocation = component.getToolTipLocation(
|
||||
event);
|
||||
boolean sameLoc = (preferredLocation != null) ?
|
||||
preferredLocation.equals(newPreferredLocation) :
|
||||
(newPreferredLocation == null);
|
||||
|
||||
if (!sameComponent || !Objects.equals(toolTipText, newToolTipText)
|
||||
|| !sameLoc) {
|
||||
toolTipText = newToolTipText;
|
||||
preferredLocation = newPreferredLocation;
|
||||
showTipWindow();
|
||||
}
|
||||
} else {
|
||||
enterTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// implements java.awt.event.MouseListener
|
||||
/**
|
||||
* Called when the mouse exits the region of a component.
|
||||
* Any tool tip showing should be hidden.
|
||||
*
|
||||
* @param event the event in question
|
||||
*/
|
||||
public void mouseExited(MouseEvent event) {
|
||||
boolean shouldHide = true;
|
||||
if (insideComponent == null) {
|
||||
// Drag exit
|
||||
}
|
||||
if (window != null && event.getSource() == window && insideComponent != null) {
|
||||
// if we get an exit and have a heavy window
|
||||
// we need to check if it if overlapping the inside component
|
||||
Container insideComponentWindow = insideComponent.getTopLevelAncestor();
|
||||
// insideComponent may be removed after tooltip is made visible
|
||||
if (insideComponentWindow != null) {
|
||||
Point location = event.getPoint();
|
||||
SwingUtilities.convertPointToScreen(location, window);
|
||||
|
||||
location.x -= insideComponentWindow.getX();
|
||||
location.y -= insideComponentWindow.getY();
|
||||
|
||||
location = SwingUtilities.convertPoint(null, location, insideComponent);
|
||||
if (location.x >= 0 && location.x < insideComponent.getWidth() &&
|
||||
location.y >= 0 && location.y < insideComponent.getHeight()) {
|
||||
shouldHide = false;
|
||||
} else {
|
||||
shouldHide = true;
|
||||
}
|
||||
}
|
||||
} else if(event.getSource() == insideComponent && tipWindow != null) {
|
||||
Window win = SwingUtilities.getWindowAncestor(insideComponent);
|
||||
if (win != null) { // insideComponent may have been hidden (e.g. in a menu)
|
||||
Point location = SwingUtilities.convertPoint(insideComponent,
|
||||
event.getPoint(),
|
||||
win);
|
||||
Rectangle bounds = insideComponent.getTopLevelAncestor().getBounds();
|
||||
location.x += bounds.x;
|
||||
location.y += bounds.y;
|
||||
|
||||
Point loc = new Point(0, 0);
|
||||
SwingUtilities.convertPointToScreen(loc, tip);
|
||||
bounds.x = loc.x;
|
||||
bounds.y = loc.y;
|
||||
bounds.width = tip.getWidth();
|
||||
bounds.height = tip.getHeight();
|
||||
|
||||
if (location.x >= bounds.x && location.x < (bounds.x + bounds.width) &&
|
||||
location.y >= bounds.y && location.y < (bounds.y + bounds.height)) {
|
||||
shouldHide = false;
|
||||
} else {
|
||||
shouldHide = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldHide) {
|
||||
enterTimer.stop();
|
||||
if (insideComponent != null) {
|
||||
insideComponent.removeMouseMotionListener(this);
|
||||
}
|
||||
insideComponent = null;
|
||||
toolTipText = null;
|
||||
mouseEvent = null;
|
||||
hideTipWindow();
|
||||
exitTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
// implements java.awt.event.MouseListener
|
||||
/**
|
||||
* Called when the mouse is pressed.
|
||||
* Any tool tip showing should be hidden.
|
||||
*
|
||||
* @param event the event in question
|
||||
*/
|
||||
public void mousePressed(MouseEvent event) {
|
||||
hideTipWindow();
|
||||
enterTimer.stop();
|
||||
showImmediately = false;
|
||||
insideComponent = null;
|
||||
mouseEvent = null;
|
||||
}
|
||||
|
||||
// implements java.awt.event.MouseMotionListener
|
||||
/**
|
||||
* Called when the mouse is pressed and dragged.
|
||||
* Does nothing.
|
||||
*
|
||||
* @param event the event in question
|
||||
*/
|
||||
public void mouseDragged(MouseEvent event) {
|
||||
}
|
||||
|
||||
// implements java.awt.event.MouseMotionListener
|
||||
/**
|
||||
* Called when the mouse is moved.
|
||||
* Determines whether the tool tip should be displayed.
|
||||
*
|
||||
* @param event the event in question
|
||||
*/
|
||||
public void mouseMoved(MouseEvent event) {
|
||||
if (tipShowing) {
|
||||
checkForTipChange(event);
|
||||
}
|
||||
else if (showImmediately) {
|
||||
JComponent component = (JComponent)event.getSource();
|
||||
toolTipText = component.getToolTipText(event);
|
||||
if (toolTipText != null) {
|
||||
preferredLocation = component.getToolTipLocation(event);
|
||||
mouseEvent = event;
|
||||
insideComponent = component;
|
||||
exitTimer.stop();
|
||||
showTipWindow();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Lazily lookup the values from within insideTimerAction
|
||||
insideComponent = (JComponent)event.getSource();
|
||||
mouseEvent = event;
|
||||
toolTipText = null;
|
||||
enterTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if the tooltip needs to be changed in response to
|
||||
* the MouseMoved event <code>event</code>.
|
||||
*/
|
||||
private void checkForTipChange(MouseEvent event) {
|
||||
JComponent component = (JComponent)event.getSource();
|
||||
String newText = component.getToolTipText(event);
|
||||
Point newPreferredLocation = component.getToolTipLocation(event);
|
||||
|
||||
if (newText != null || newPreferredLocation != null) {
|
||||
mouseEvent = event;
|
||||
if (((newText != null && newText.equals(toolTipText)) || newText == null) &&
|
||||
((newPreferredLocation != null && newPreferredLocation.equals(preferredLocation))
|
||||
|| newPreferredLocation == null)) {
|
||||
if (tipWindow != null) {
|
||||
insideTimer.restart();
|
||||
} else {
|
||||
enterTimer.restart();
|
||||
}
|
||||
} else {
|
||||
toolTipText = newText;
|
||||
preferredLocation = newPreferredLocation;
|
||||
if (showImmediately) {
|
||||
hideTipWindow();
|
||||
showTipWindow();
|
||||
exitTimer.stop();
|
||||
} else {
|
||||
enterTimer.restart();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
toolTipText = null;
|
||||
preferredLocation = null;
|
||||
mouseEvent = null;
|
||||
insideComponent = null;
|
||||
hideTipWindow();
|
||||
enterTimer.stop();
|
||||
exitTimer.restart();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inside timer action.
|
||||
*/
|
||||
protected class insideTimerAction implements ActionListener {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if(insideComponent != null && insideComponent.isShowing()) {
|
||||
// Lazy lookup
|
||||
if (toolTipText == null && mouseEvent != null) {
|
||||
toolTipText = insideComponent.getToolTipText(mouseEvent);
|
||||
preferredLocation = insideComponent.getToolTipLocation(
|
||||
mouseEvent);
|
||||
}
|
||||
if(toolTipText != null) {
|
||||
showImmediately = true;
|
||||
showTipWindow();
|
||||
}
|
||||
else {
|
||||
insideComponent = null;
|
||||
toolTipText = null;
|
||||
preferredLocation = null;
|
||||
mouseEvent = null;
|
||||
hideTipWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outside timer action.
|
||||
*/
|
||||
protected class outsideTimerAction implements ActionListener {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showImmediately = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Still inside timer action.
|
||||
*/
|
||||
protected class stillInsideTimerAction implements ActionListener {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
hideTipWindow();
|
||||
enterTimer.stop();
|
||||
showImmediately = false;
|
||||
insideComponent = null;
|
||||
mouseEvent = null;
|
||||
}
|
||||
}
|
||||
|
||||
/* This listener is registered when the tooltip is first registered
|
||||
* on a component in order to catch the situation where the tooltip
|
||||
* was turned on while the mouse was already within the bounds of
|
||||
* the component. This way, the tooltip will be initiated on a
|
||||
* mouse-entered or mouse-moved, whichever occurs first. Once the
|
||||
* tooltip has been initiated, we can remove this listener and rely
|
||||
* solely on mouse-entered to initiate the tooltip.
|
||||
*/
|
||||
private class MoveBeforeEnterListener extends MouseMotionAdapter {
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
initiateToolTip(e);
|
||||
}
|
||||
}
|
||||
|
||||
static Frame frameForComponent(Component component) {
|
||||
while (!(component instanceof Frame)) {
|
||||
component = component.getParent();
|
||||
}
|
||||
return (Frame)component;
|
||||
}
|
||||
|
||||
private FocusListener createFocusChangeListener(){
|
||||
return new FocusAdapter(){
|
||||
public void focusLost(FocusEvent evt){
|
||||
hideTipWindow();
|
||||
insideComponent = null;
|
||||
JComponent c = (JComponent)evt.getSource();
|
||||
c.removeFocusListener(focusChangeListener);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Returns: 0 no adjust
|
||||
// -1 can't fit
|
||||
// >0 adjust value by amount returned
|
||||
@SuppressWarnings("deprecation")
|
||||
private int getPopupFitWidth(Rectangle popupRectInScreen, Component invoker){
|
||||
if (invoker != null){
|
||||
Container parent;
|
||||
for (parent = invoker.getParent(); parent != null; parent = parent.getParent()){
|
||||
// fix internal frame size bug: 4139087 - 4159012
|
||||
if(parent instanceof JFrame || parent instanceof JDialog ||
|
||||
parent instanceof JWindow) { // no check for awt.Frame since we use Heavy tips
|
||||
return getWidthAdjust(parent.getBounds(),popupRectInScreen);
|
||||
} else if (parent instanceof JApplet || parent instanceof JInternalFrame) {
|
||||
if (popupFrameRect == null){
|
||||
popupFrameRect = new Rectangle();
|
||||
}
|
||||
Point p = parent.getLocationOnScreen();
|
||||
popupFrameRect.setBounds(p.x,p.y,
|
||||
parent.getBounds().width,
|
||||
parent.getBounds().height);
|
||||
return getWidthAdjust(popupFrameRect,popupRectInScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns: 0 no adjust
|
||||
// >0 adjust by value return
|
||||
@SuppressWarnings("deprecation")
|
||||
private int getPopupFitHeight(Rectangle popupRectInScreen, Component invoker){
|
||||
if (invoker != null){
|
||||
Container parent;
|
||||
for (parent = invoker.getParent(); parent != null; parent = parent.getParent()){
|
||||
if(parent instanceof JFrame || parent instanceof JDialog ||
|
||||
parent instanceof JWindow) {
|
||||
return getHeightAdjust(parent.getBounds(),popupRectInScreen);
|
||||
} else if (parent instanceof JApplet || parent instanceof JInternalFrame) {
|
||||
if (popupFrameRect == null){
|
||||
popupFrameRect = new Rectangle();
|
||||
}
|
||||
Point p = parent.getLocationOnScreen();
|
||||
popupFrameRect.setBounds(p.x,p.y,
|
||||
parent.getBounds().width,
|
||||
parent.getBounds().height);
|
||||
return getHeightAdjust(popupFrameRect,popupRectInScreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int getHeightAdjust(Rectangle a, Rectangle b){
|
||||
if (b.y >= a.y && (b.y + b.height) <= (a.y + a.height))
|
||||
return 0;
|
||||
else
|
||||
return (((b.y + b.height) - (a.y + a.height)) + 5);
|
||||
}
|
||||
|
||||
// Return the number of pixels over the edge we are extending.
|
||||
// If we are over the edge the ToolTipManager can adjust.
|
||||
// REMIND: what if the Tooltip is just too big to fit at all - we currently will just clip
|
||||
private int getWidthAdjust(Rectangle a, Rectangle b){
|
||||
// System.out.println("width b.x/b.width: " + b.x + "/" + b.width +
|
||||
// "a.x/a.width: " + a.x + "/" + a.width);
|
||||
if (b.x >= a.x && (b.x + b.width) <= (a.x + a.width)){
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return (((b.x + b.width) - (a.x +a.width)) + 5);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Actions
|
||||
//
|
||||
private void show(JComponent source) {
|
||||
if (tipWindow != null) { // showing we unshow
|
||||
hideTipWindow();
|
||||
insideComponent = null;
|
||||
}
|
||||
else {
|
||||
hideTipWindow(); // be safe
|
||||
enterTimer.stop();
|
||||
exitTimer.stop();
|
||||
insideTimer.stop();
|
||||
insideComponent = source;
|
||||
if (insideComponent != null){
|
||||
toolTipText = insideComponent.getToolTipText();
|
||||
preferredLocation = new Point(10,insideComponent.getHeight()+
|
||||
10); // manual set
|
||||
showTipWindow();
|
||||
// put a focuschange listener on to bring the tip down
|
||||
if (focusChangeListener == null){
|
||||
focusChangeListener = createFocusChangeListener();
|
||||
}
|
||||
insideComponent.addFocusListener(focusChangeListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void hide(JComponent source) {
|
||||
hideTipWindow();
|
||||
source.removeFocusListener(focusChangeListener);
|
||||
preferredLocation = null;
|
||||
insideComponent = null;
|
||||
}
|
||||
|
||||
/* This listener is registered when the tooltip is first registered
|
||||
* on a component in order to process accessibility keybindings.
|
||||
* This will apply globally across L&F
|
||||
*
|
||||
* Post Tip: Ctrl+F1
|
||||
* Unpost Tip: Esc and Ctrl+F1
|
||||
*/
|
||||
private class AccessibilityKeyListener extends KeyAdapter {
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if (!e.isConsumed()) {
|
||||
JComponent source = (JComponent) e.getComponent();
|
||||
KeyStroke keyStrokeForEvent = KeyStroke.getKeyStrokeForEvent(e);
|
||||
if (hideTip.equals(keyStrokeForEvent)) {
|
||||
if (tipWindow != null) {
|
||||
hide(source);
|
||||
e.consume();
|
||||
}
|
||||
} else if (postTip.equals(keyStrokeForEvent)) {
|
||||
// Shown tooltip will be hidden
|
||||
ToolTipManager.this.show(source);
|
||||
e.consume();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue