44 |
import java.awt.LayoutManager; |
import java.awt.LayoutManager; |
45 |
import java.awt.Panel; |
import java.awt.Panel; |
46 |
import java.awt.Point; |
import java.awt.Point; |
|
import java.awt.Rectangle; |
|
47 |
import java.awt.event.ActionEvent; |
import java.awt.event.ActionEvent; |
48 |
import java.awt.event.ActionListener; |
import java.awt.event.ActionListener; |
49 |
import java.awt.event.MouseAdapter; |
import java.awt.event.MouseAdapter; |
67 |
*/ |
*/ |
68 |
protected stillInsideTimerAction() |
protected stillInsideTimerAction() |
69 |
{ |
{ |
70 |
|
// Nothing to do here. |
71 |
} |
} |
72 |
|
|
73 |
/** |
/** |
93 |
*/ |
*/ |
94 |
protected outsideTimerAction() |
protected outsideTimerAction() |
95 |
{ |
{ |
96 |
|
// Nothing to do here. |
97 |
} |
} |
98 |
|
|
99 |
/** |
/** |
104 |
*/ |
*/ |
105 |
public void actionPerformed(ActionEvent event) |
public void actionPerformed(ActionEvent event) |
106 |
{ |
{ |
107 |
|
// TODO: What should be done here, if anything? |
108 |
} |
} |
109 |
} |
} |
110 |
|
|
120 |
*/ |
*/ |
121 |
protected insideTimerAction() |
protected insideTimerAction() |
122 |
{ |
{ |
123 |
|
// Nothing to do here. |
124 |
} |
} |
125 |
|
|
126 |
/** |
/** |
424 |
insideTimer.stop(); |
insideTimer.stop(); |
425 |
hideTip(); |
hideTip(); |
426 |
} |
} |
|
|
|
|
if (currentComponent == null) |
|
|
currentComponent = (Component) event.getSource(); |
|
|
|
|
|
currentComponent.invalidate(); |
|
|
currentComponent.validate(); |
|
|
currentComponent.repaint(); |
|
427 |
} |
} |
428 |
|
|
429 |
/** |
/** |
448 |
public void mouseMoved(MouseEvent event) |
public void mouseMoved(MouseEvent event) |
449 |
{ |
{ |
450 |
currentPoint = event.getPoint(); |
currentPoint = event.getPoint(); |
|
if (currentTip != null) |
|
|
{ |
|
|
if (currentComponent == null) |
|
|
currentComponent = (Component) event.getSource(); |
|
|
|
|
|
String text = ((JComponent) currentComponent).getToolTipText(event); |
|
|
currentTip.setTipText(text); |
|
|
} |
|
451 |
if (enterTimer.isRunning()) |
if (enterTimer.isRunning()) |
452 |
enterTimer.restart(); |
enterTimer.restart(); |
453 |
} |
} |
454 |
|
|
455 |
/** |
/** |
459 |
*/ |
*/ |
460 |
void showTip() |
void showTip() |
461 |
{ |
{ |
462 |
if (! enabled || currentComponent == null || |
if (!enabled || currentComponent == null || !currentComponent.isEnabled() |
463 |
(currentTip != null && currentTip.isVisible())) |
|| (currentTip != null && currentTip.isVisible())) |
464 |
return; |
return; |
465 |
|
|
466 |
if (currentTip == null |
if (currentTip == null || currentTip.getComponent() != currentComponent |
|
|| currentTip.getComponent() != currentComponent |
|
467 |
&& currentComponent instanceof JComponent) |
&& currentComponent instanceof JComponent) |
468 |
currentTip = ((JComponent) currentComponent).createToolTip(); |
currentTip = ((JComponent) currentComponent).createToolTip(); |
469 |
|
|
470 |
|
currentTip.setVisible(true); |
471 |
|
Container parent = currentComponent.getParent(); |
472 |
Point p = currentPoint; |
Point p = currentPoint; |
473 |
Dimension dims = currentTip.getPreferredSize(); |
Dimension dims = currentTip.getPreferredSize(); |
474 |
if (canToolTipFit(currentTip)) |
|
475 |
{ |
if (parent instanceof JPopupMenu) |
476 |
JLayeredPane pane = ((JRootPane) SwingUtilities.getAncestorOfClass(JRootPane.class, |
setLightWeightPopupEnabled(((JPopupMenu) parent).isLightWeightPopupEnabled()); |
|
currentComponent)) |
|
|
.getLayeredPane(); |
|
|
|
|
|
// This should never happen, but just in case. |
|
|
if (pane == null) |
|
|
return; |
|
|
|
|
|
if (containerPanel != null) |
|
|
hideTip(); |
|
|
if (isLightWeightPopupEnabled()) |
|
|
{ |
|
|
containerPanel = new Panel(); |
|
|
JRootPane root = new JRootPane(); |
|
|
root.getContentPane().add(currentTip); |
|
|
containerPanel.add(root); |
|
|
} |
|
|
else |
|
|
{ |
|
|
containerPanel = new JPanel(); |
|
|
containerPanel.add(currentTip); |
|
|
} |
|
|
LayoutManager lm = containerPanel.getLayout(); |
|
|
if (lm instanceof FlowLayout) |
|
|
{ |
|
|
FlowLayout fm = (FlowLayout) lm; |
|
|
fm.setVgap(0); |
|
|
fm.setHgap(0); |
|
|
} |
|
|
|
|
|
p = getGoodPoint(p, pane, currentTip, dims); |
|
|
|
|
|
pane.add(containerPanel); |
|
|
containerPanel.setBounds(p.x, p.y, dims.width, dims.height); |
|
|
currentTip.setBounds(0, 0, dims.width, dims.height); |
|
|
|
|
|
pane.revalidate(); |
|
|
pane.repaint(); |
|
|
} |
|
477 |
else |
else |
478 |
|
setLightWeightPopupEnabled(true); |
479 |
|
|
480 |
|
if (isLightWeightPopupEnabled()) |
481 |
{ |
{ |
482 |
if (currentComponent.isShowing()) |
JLayeredPane pane = null; |
483 |
|
JRootPane r = ((JRootPane) SwingUtilities. |
484 |
|
getAncestorOfClass(JRootPane.class, currentComponent)); |
485 |
|
if (r != null) |
486 |
|
pane = r.getLayeredPane(); |
487 |
|
if (pane == null) |
488 |
|
return; |
489 |
|
|
490 |
|
if (containerPanel != null) |
491 |
|
hideTip(); |
492 |
|
|
493 |
|
containerPanel = new Panel(); |
494 |
|
JRootPane root = new JRootPane(); |
495 |
|
root.getContentPane().add(currentTip); |
496 |
|
containerPanel.add(root); |
497 |
|
|
498 |
|
LayoutManager lm = containerPanel.getLayout(); |
499 |
|
if (lm instanceof FlowLayout) |
500 |
{ |
{ |
501 |
SwingUtilities.convertPointToScreen(p, currentComponent); |
FlowLayout fm = (FlowLayout) lm; |
502 |
tooltipWindow = new JDialog(); |
fm.setVgap(0); |
503 |
tooltipWindow.getContentPane().add(currentTip); |
fm.setHgap(0); |
|
tooltipWindow.setUndecorated(true); |
|
|
tooltipWindow.getRootPane(). |
|
|
setWindowDecorationStyle(JRootPane.PLAIN_DIALOG); |
|
|
tooltipWindow.setFocusable(false); |
|
|
tooltipWindow.pack(); |
|
|
tooltipWindow.setBounds(p.x, p.y, dims.width, dims.height); |
|
|
tooltipWindow.show(); |
|
504 |
} |
} |
505 |
|
|
506 |
|
p = SwingUtilities.convertPoint(currentComponent, p, pane); |
507 |
|
p = adjustLocation(p, pane, dims); |
508 |
|
|
509 |
|
pane.add(containerPanel); |
510 |
|
containerPanel.setBounds(p.x, p.y, dims.width, dims.height); |
511 |
|
currentTip.setBounds(0, 0, dims.width, dims.height); |
512 |
|
containerPanel.validate(); |
513 |
|
containerPanel.repaint(); |
514 |
|
} |
515 |
|
else if (currentComponent.isShowing()) |
516 |
|
{ |
517 |
|
SwingUtilities.convertPointToScreen(p, currentComponent); |
518 |
|
p = adjustLocation(p, SwingUtilities.getWindowAncestor(currentComponent), |
519 |
|
dims); |
520 |
|
|
521 |
|
tooltipWindow = new JDialog(); |
522 |
|
tooltipWindow.setContentPane(currentTip); |
523 |
|
tooltipWindow.setUndecorated(true); |
524 |
|
tooltipWindow.getRootPane(). |
525 |
|
setWindowDecorationStyle(JRootPane.PLAIN_DIALOG); |
526 |
|
tooltipWindow.pack(); |
527 |
|
tooltipWindow.setBounds(p.x, p.y, dims.width, dims.height); |
528 |
|
tooltipWindow.show(); |
529 |
|
tooltipWindow.validate(); |
530 |
|
tooltipWindow.repaint(); |
531 |
|
currentTip.revalidate(); |
532 |
|
currentTip.repaint(); |
533 |
} |
} |
|
currentTip.setVisible(true); |
|
534 |
} |
} |
535 |
|
|
536 |
/** |
/** |
537 |
|
* Adjusts the point to a new location on the component, |
538 |
|
* using the currentTip's dimensions. |
539 |
|
* |
540 |
|
* @param p - the point to convert. |
541 |
|
* @param c - the component the point is on. |
542 |
|
* @param d - the dimensions of the currentTip. |
543 |
|
*/ |
544 |
|
private Point adjustLocation(Point p, Component c, Dimension d) |
545 |
|
{ |
546 |
|
if (p.x + d.width > c.getWidth()) |
547 |
|
p.x -= d.width; |
548 |
|
if (p.x < 0) |
549 |
|
p.x = 0; |
550 |
|
if (p.y + d.height < c.getHeight()) |
551 |
|
p.y += d.height; |
552 |
|
if (p.y + d.height > c.getHeight()) |
553 |
|
p.y -= d.height*2; |
554 |
|
|
555 |
|
return p; |
556 |
|
} |
557 |
|
|
558 |
|
/** |
559 |
* This method hides the ToolTip. |
* This method hides the ToolTip. |
560 |
* This is package-private to avoid an accessor method. |
* This is package-private to avoid an accessor method. |
561 |
*/ |
*/ |
570 |
if (parent == null) |
if (parent == null) |
571 |
return; |
return; |
572 |
parent.remove(containerPanel); |
parent.remove(containerPanel); |
|
parent.invalidate(); |
|
|
parent.validate(); |
|
|
parent.repaint(); |
|
573 |
|
|
574 |
parent = currentTip.getParent(); |
parent = currentTip.getParent(); |
575 |
if (parent == null) |
if (parent == null) |
576 |
return; |
return; |
577 |
parent.remove(currentTip); |
parent.remove(currentTip); |
|
|
|
578 |
containerPanel = null; |
containerPanel = null; |
579 |
} |
} |
580 |
if (tooltipWindow != null) |
if (tooltipWindow != null) |
583 |
tooltipWindow.dispose(); |
tooltipWindow.dispose(); |
584 |
tooltipWindow = null; |
tooltipWindow = null; |
585 |
} |
} |
586 |
} |
currentTip = null; |
|
|
|
|
/** |
|
|
* This method returns a point in the LayeredPane where the ToolTip can be |
|
|
* shown. The point returned (if the ToolTip is to be displayed at the |
|
|
* preferred dimensions) will always place the ToolTip inside the |
|
|
* currentComponent if possible. |
|
|
* |
|
|
* @param p The last known good point for the mouse. |
|
|
* @param c The JLayeredPane in the first RootPaneContainer up from the |
|
|
* currentComponent. |
|
|
* @param tip The ToolTip to display. |
|
|
* @param dims The ToolTip preferred dimensions (can be null). |
|
|
* |
|
|
* @return A good point to place the ToolTip. |
|
|
*/ |
|
|
private Point getGoodPoint(Point p, JLayeredPane c, JToolTip tip, |
|
|
Dimension dims) |
|
|
{ |
|
|
if (dims == null) |
|
|
dims = tip.getPreferredSize(); |
|
|
Rectangle bounds = currentComponent.getBounds(); |
|
|
if (p.x + dims.width > bounds.width) |
|
|
p.x = bounds.width - dims.width; |
|
|
if (p.y + dims.height > bounds.height) |
|
|
p.y = bounds.height - dims.height; |
|
|
|
|
|
p = SwingUtilities.convertPoint(currentComponent, p, c); |
|
|
return p; |
|
587 |
} |
} |
588 |
|
|
589 |
/** |
/** |
608 |
Component target = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y); |
Component target = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y); |
609 |
return target; |
return target; |
610 |
} |
} |
|
|
|
|
/** |
|
|
* This method returns whether the ToolTip can fit in the first |
|
|
* RootPaneContainer up from the currentComponent. |
|
|
* |
|
|
* @param tip The ToolTip. |
|
|
* |
|
|
* @return Whether the ToolTip can fit. |
|
|
*/ |
|
|
private boolean canToolTipFit(JToolTip tip) |
|
|
{ |
|
|
JRootPane root = (JRootPane) SwingUtilities.getAncestorOfClass(JRootPane.class, |
|
|
currentComponent); |
|
|
if (root == null) |
|
|
return false; |
|
|
Dimension pref = tip.getPreferredSize(); |
|
|
Dimension rootSize = root.getSize(); |
|
|
if (rootSize.width > pref.width && rootSize.height > pref.height) |
|
|
return true; |
|
|
return false; |
|
|
} |
|
611 |
} |
} |