Save This Page
Home » openjdk-7 » javax » swing » [javadoc | source]
    1   /*
    2    * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   
   27   package javax.swing;
   28   
   29   import java.awt.event;
   30   import java.applet;
   31   import java.awt;
   32   import java.io.Serializable;
   33   import sun.swing.UIAction;
   34   
   35   /**
   36    * Manages all the <code>ToolTips</code> in the system.
   37    * <p>
   38    * ToolTipManager contains numerous properties for configuring how long it
   39    * will take for the tooltips to become visible, and how long till they
   40    * hide. Consider a component that has a different tooltip based on where
   41    * the mouse is, such as JTree. When the mouse moves into the JTree and
   42    * over a region that has a valid tooltip, the tooltip will become
   43    * visibile after <code>initialDelay</code> milliseconds. After
   44    * <code>dismissDelay</code> milliseconds the tooltip will be hidden. If
   45    * the mouse is over a region that has a valid tooltip, and the tooltip
   46    * is currently visible, when the mouse moves to a region that doesn't have
   47    * a valid tooltip the tooltip will be hidden. If the mouse then moves back
   48    * into a region that has a valid tooltip within <code>reshowDelay</code>
   49    * milliseconds, the tooltip will immediately be shown, otherwise the
   50    * tooltip will be shown again after <code>initialDelay</code> milliseconds.
   51    *
   52    * @see JComponent#createToolTip
   53    * @author Dave Moore
   54    * @author Rich Schiavi
   55    */
   56   public class ToolTipManager extends MouseAdapter implements MouseMotionListener  {
   57       Timer enterTimer, exitTimer, insideTimer;
   58       String toolTipText;
   59       Point  preferredLocation;
   60       JComponent insideComponent;
   61       MouseEvent mouseEvent;
   62       boolean showImmediately;
   63       final static ToolTipManager sharedInstance = new ToolTipManager();
   64       transient Popup tipWindow;
   65       /** The Window tip is being displayed in. This will be non-null if
   66        * the Window tip is in differs from that of insideComponent's Window.
   67        */
   68       private Window window;
   69       JToolTip tip;
   70   
   71       private Rectangle popupRect = null;
   72       private Rectangle popupFrameRect = null;
   73   
   74       boolean enabled = true;
   75       private boolean tipShowing = false;
   76   
   77       private FocusListener focusChangeListener = null;
   78       private MouseMotionListener moveBeforeEnterListener = null;
   79       private KeyListener accessibilityKeyListener = null;
   80   
   81       // PENDING(ges)
   82       protected boolean lightWeightPopupEnabled = true;
   83       protected boolean heavyWeightPopupEnabled = false;
   84   
   85       ToolTipManager() {
   86           enterTimer = new Timer(750, new insideTimerAction());
   87           enterTimer.setRepeats(false);
   88           exitTimer = new Timer(500, new outsideTimerAction());
   89           exitTimer.setRepeats(false);
   90           insideTimer = new Timer(4000, new stillInsideTimerAction());
   91           insideTimer.setRepeats(false);
   92   
   93           moveBeforeEnterListener = new MoveBeforeEnterListener();
   94           accessibilityKeyListener = new AccessibilityKeyListener();
   95       }
   96   
   97       /**
   98        * Enables or disables the tooltip.
   99        *
  100        * @param flag  true to enable the tip, false otherwise
  101        */
  102       public void setEnabled(boolean flag) {
  103           enabled = flag;
  104           if (!flag) {
  105               hideTipWindow();
  106           }
  107       }
  108   
  109       /**
  110        * Returns true if this object is enabled.
  111        *
  112        * @return true if this object is enabled, false otherwise
  113        */
  114       public boolean isEnabled() {
  115           return enabled;
  116       }
  117   
  118       /**
  119        * When displaying the <code>JToolTip</code>, the
  120        * <code>ToolTipManager</code> chooses to use a lightweight
  121        * <code>JPanel</code> if it fits. This method allows you to
  122        * disable this feature. You have to do disable it if your
  123        * application mixes light weight and heavy weights components.
  124        *
  125        * @param aFlag true if a lightweight panel is desired, false otherwise
  126        *
  127        */
  128       public void setLightWeightPopupEnabled(boolean aFlag){
  129           lightWeightPopupEnabled = aFlag;
  130       }
  131   
  132       /**
  133        * Returns true if lightweight (all-Java) <code>Tooltips</code>
  134        * are in use, or false if heavyweight (native peer)
  135        * <code>Tooltips</code> are being used.
  136        *
  137        * @return true if lightweight <code>ToolTips</code> are in use
  138        */
  139       public boolean isLightWeightPopupEnabled() {
  140           return lightWeightPopupEnabled;
  141       }
  142   
  143   
  144       /**
  145        * Specifies the initial delay value.
  146        *
  147        * @param milliseconds  the number of milliseconds to delay
  148        *        (after the cursor has paused) before displaying the
  149        *        tooltip
  150        * @see #getInitialDelay
  151        */
  152       public void setInitialDelay(int milliseconds) {
  153           enterTimer.setInitialDelay(milliseconds);
  154       }
  155   
  156       /**
  157        * Returns the initial delay value.
  158        *
  159        * @return an integer representing the initial delay value,
  160        *          in milliseconds
  161        * @see #setInitialDelay
  162        */
  163       public int getInitialDelay() {
  164           return enterTimer.getInitialDelay();
  165       }
  166   
  167       /**
  168        * Specifies the dismissal delay value.
  169        *
  170        * @param milliseconds  the number of milliseconds to delay
  171        *        before taking away the tooltip
  172        * @see #getDismissDelay
  173        */
  174       public void setDismissDelay(int milliseconds) {
  175           insideTimer.setInitialDelay(milliseconds);
  176       }
  177   
  178       /**
  179        * Returns the dismissal delay value.
  180        *
  181        * @return an integer representing the dismissal delay value,
  182        *          in milliseconds
  183        * @see #setDismissDelay
  184        */
  185       public int getDismissDelay() {
  186           return insideTimer.getInitialDelay();
  187       }
  188   
  189       /**
  190        * Used to specify the amount of time before the user has to wait
  191        * <code>initialDelay</code> milliseconds before a tooltip will be
  192        * shown. That is, if the tooltip is hidden, and the user moves into
  193        * a region of the same Component that has a valid tooltip within
  194        * <code>milliseconds</code> milliseconds the tooltip will immediately
  195        * be shown. Otherwise, if the user moves into a region with a valid
  196        * tooltip after <code>milliseconds</code> milliseconds, the user
  197        * will have to wait an additional <code>initialDelay</code>
  198        * milliseconds before the tooltip is shown again.
  199        *
  200        * @param milliseconds time in milliseconds
  201        * @see #getReshowDelay
  202        */
  203       public void setReshowDelay(int milliseconds) {
  204           exitTimer.setInitialDelay(milliseconds);
  205       }
  206   
  207       /**
  208        * Returns the reshow delay property.
  209        *
  210        * @return reshown delay property
  211        * @see #setReshowDelay
  212        */
  213       public int getReshowDelay() {
  214           return exitTimer.getInitialDelay();
  215       }
  216   
  217       void showTipWindow() {
  218           if(insideComponent == null || !insideComponent.isShowing())
  219               return;
  220           String mode = UIManager.getString("ToolTipManager.enableToolTipMode");
  221           if ("activeApplication".equals(mode)) {
  222               KeyboardFocusManager kfm =
  223                       KeyboardFocusManager.getCurrentKeyboardFocusManager();
  224               if (kfm.getFocusedWindow() == null) {
  225                   return;
  226               }
  227           }
  228           if (enabled) {
  229               Dimension size;
  230               Point screenLocation = insideComponent.getLocationOnScreen();
  231               Point location = new Point();
  232               GraphicsConfiguration gc;
  233               gc = insideComponent.getGraphicsConfiguration();
  234               Rectangle sBounds = gc.getBounds();
  235               Insets screenInsets = Toolkit.getDefaultToolkit()
  236                                                .getScreenInsets(gc);
  237               // Take into account screen insets, decrease viewport
  238               sBounds.x += screenInsets.left;
  239               sBounds.y += screenInsets.top;
  240               sBounds.width -= (screenInsets.left + screenInsets.right);
  241               sBounds.height -= (screenInsets.top + screenInsets.bottom);
  242           boolean leftToRight
  243                   = SwingUtilities.isLeftToRight(insideComponent);
  244   
  245               // Just to be paranoid
  246               hideTipWindow();
  247   
  248               tip = insideComponent.createToolTip();
  249               tip.setTipText(toolTipText);
  250               size = tip.getPreferredSize();
  251   
  252               if(preferredLocation != null) {
  253                   location.x = screenLocation.x + preferredLocation.x;
  254                   location.y = screenLocation.y + preferredLocation.y;
  255           if (!leftToRight) {
  256               location.x -= size.width;
  257           }
  258               } else {
  259                   location.x = screenLocation.x + mouseEvent.getX();
  260                   location.y = screenLocation.y + mouseEvent.getY() + 20;
  261           if (!leftToRight) {
  262               if(location.x - size.width>=0) {
  263                   location.x -= size.width;
  264               }
  265           }
  266   
  267               }
  268   
  269           // we do not adjust x/y when using awt.Window tips
  270           if (popupRect == null){
  271           popupRect = new Rectangle();
  272           }
  273           popupRect.setBounds(location.x,location.y,
  274                   size.width,size.height);
  275   
  276           // Fit as much of the tooltip on screen as possible
  277               if (location.x < sBounds.x) {
  278                   location.x = sBounds.x;
  279               }
  280               else if (location.x - sBounds.x + size.width > sBounds.width) {
  281                   location.x = sBounds.x + Math.max(0, sBounds.width - size.width)
  282   ;
  283               }
  284               if (location.y < sBounds.y) {
  285                   location.y = sBounds.y;
  286               }
  287               else if (location.y - sBounds.y + size.height > sBounds.height) {
  288                   location.y = sBounds.y + Math.max(0, sBounds.height - size.height);
  289               }
  290   
  291               PopupFactory popupFactory = PopupFactory.getSharedInstance();
  292   
  293               if (lightWeightPopupEnabled) {
  294           int y = getPopupFitHeight(popupRect, insideComponent);
  295           int x = getPopupFitWidth(popupRect,insideComponent);
  296           if (x>0 || y>0) {
  297               popupFactory.setPopupType(PopupFactory.MEDIUM_WEIGHT_POPUP);
  298           } else {
  299               popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP);
  300           }
  301               }
  302               else {
  303                   popupFactory.setPopupType(PopupFactory.MEDIUM_WEIGHT_POPUP);
  304               }
  305           tipWindow = popupFactory.getPopup(insideComponent, tip,
  306                             location.x,
  307                             location.y);
  308               popupFactory.setPopupType(PopupFactory.LIGHT_WEIGHT_POPUP);
  309   
  310           tipWindow.show();
  311   
  312               Window componentWindow = SwingUtilities.windowForComponent(
  313                                                       insideComponent);
  314   
  315               window = SwingUtilities.windowForComponent(tip);
  316               if (window != null && window != componentWindow) {
  317                   window.addMouseListener(this);
  318               }
  319               else {
  320                   window = null;
  321               }
  322   
  323               insideTimer.start();
  324           tipShowing = true;
  325           }
  326       }
  327   
  328       void hideTipWindow() {
  329           if (tipWindow != null) {
  330               if (window != null) {
  331                   window.removeMouseListener(this);
  332                   window = null;
  333               }
  334               tipWindow.hide();
  335               tipWindow = null;
  336               tipShowing = false;
  337               tip = null;
  338               insideTimer.stop();
  339           }
  340       }
  341   
  342       /**
  343        * Returns a shared <code>ToolTipManager</code> instance.
  344        *
  345        * @return a shared <code>ToolTipManager</code> object
  346        */
  347       public static ToolTipManager sharedInstance() {
  348           return sharedInstance;
  349       }
  350   
  351       // add keylistener here to trigger tip for access
  352       /**
  353        * Registers a component for tooltip management.
  354        * <p>
  355        * This will register key bindings to show and hide the tooltip text
  356        * only if <code>component</code> has focus bindings. This is done
  357        * so that components that are not normally focus traversable, such
  358        * as <code>JLabel</code>, are not made focus traversable as a result
  359        * of invoking this method.
  360        *
  361        * @param component  a <code>JComponent</code> object to add
  362        * @see JComponent#isFocusTraversable
  363        */
  364       public void registerComponent(JComponent component) {
  365           component.removeMouseListener(this);
  366           component.addMouseListener(this);
  367           component.removeMouseMotionListener(moveBeforeEnterListener);
  368           component.addMouseMotionListener(moveBeforeEnterListener);
  369           component.removeKeyListener(accessibilityKeyListener);
  370           component.addKeyListener(accessibilityKeyListener);
  371       }
  372   
  373       /**
  374        * Removes a component from tooltip control.
  375        *
  376        * @param component  a <code>JComponent</code> object to remove
  377        */
  378       public void unregisterComponent(JComponent component) {
  379           component.removeMouseListener(this);
  380           component.removeMouseMotionListener(moveBeforeEnterListener);
  381           component.removeKeyListener(accessibilityKeyListener);
  382       }
  383   
  384       // implements java.awt.event.MouseListener
  385       /**
  386        *  Called when the mouse enters the region of a component.
  387        *  This determines whether the tool tip should be shown.
  388        *
  389        *  @param event  the event in question
  390        */
  391       public void mouseEntered(MouseEvent event) {
  392           initiateToolTip(event);
  393       }
  394   
  395       private void initiateToolTip(MouseEvent event) {
  396           if (event.getSource() == window) {
  397               return;
  398           }
  399           JComponent component = (JComponent)event.getSource();
  400           component.removeMouseMotionListener(moveBeforeEnterListener);
  401   
  402           exitTimer.stop();
  403   
  404           Point location = event.getPoint();
  405           // ensure tooltip shows only in proper place
  406           if (location.x < 0 ||
  407               location.x >=component.getWidth() ||
  408               location.y < 0 ||
  409               location.y >= component.getHeight()) {
  410               return;
  411           }
  412   
  413           if (insideComponent != null) {
  414               enterTimer.stop();
  415           }
  416           // A component in an unactive internal frame is sent two
  417           // mouseEntered events, make sure we don't end up adding
  418           // ourselves an extra time.
  419           component.removeMouseMotionListener(this);
  420           component.addMouseMotionListener(this);
  421   
  422           boolean sameComponent = (insideComponent == component);
  423   
  424           insideComponent = component;
  425       if (tipWindow != null){
  426               mouseEvent = event;
  427               if (showImmediately) {
  428                   String newToolTipText = component.getToolTipText(event);
  429                   Point newPreferredLocation = component.getToolTipLocation(
  430                                                            event);
  431                   boolean sameLoc = (preferredLocation != null) ?
  432                               preferredLocation.equals(newPreferredLocation) :
  433                               (newPreferredLocation == null);
  434   
  435                   if (!sameComponent || !toolTipText.equals(newToolTipText) ||
  436                            !sameLoc) {
  437                       toolTipText = newToolTipText;
  438                       preferredLocation = newPreferredLocation;
  439                       showTipWindow();
  440                   }
  441               } else {
  442                   enterTimer.start();
  443               }
  444           }
  445       }
  446   
  447       // implements java.awt.event.MouseListener
  448       /**
  449        *  Called when the mouse exits the region of a component.
  450        *  Any tool tip showing should be hidden.
  451        *
  452        *  @param event  the event in question
  453        */
  454       public void mouseExited(MouseEvent event) {
  455           boolean shouldHide = true;
  456           if (insideComponent == null) {
  457               // Drag exit
  458           }
  459           if (window != null && event.getSource() == window) {
  460             // if we get an exit and have a heavy window
  461             // we need to check if it if overlapping the inside component
  462               Container insideComponentWindow = insideComponent.getTopLevelAncestor();
  463               // insideComponent may be removed after tooltip is made visible
  464               if (insideComponentWindow != null) {
  465                   Point location = event.getPoint();
  466                   SwingUtilities.convertPointToScreen(location, window);
  467   
  468                   location.x -= insideComponentWindow.getX();
  469                   location.y -= insideComponentWindow.getY();
  470   
  471                   location = SwingUtilities.convertPoint(null, location, insideComponent);
  472                   if (location.x >= 0 && location.x < insideComponent.getWidth() &&
  473                           location.y >= 0 && location.y < insideComponent.getHeight()) {
  474                       shouldHide = false;
  475                   } else {
  476                       shouldHide = true;
  477                   }
  478               }
  479           } else if(event.getSource() == insideComponent && tipWindow != null) {
  480               Window win = SwingUtilities.getWindowAncestor(insideComponent);
  481               if (win != null) {  // insideComponent may have been hidden (e.g. in a menu)
  482                   Point location = SwingUtilities.convertPoint(insideComponent,
  483                                                                event.getPoint(),
  484                                                                win);
  485                   Rectangle bounds = insideComponent.getTopLevelAncestor().getBounds();
  486                   location.x += bounds.x;
  487                   location.y += bounds.y;
  488   
  489                   Point loc = new Point(0, 0);
  490                   SwingUtilities.convertPointToScreen(loc, tip);
  491                   bounds.x = loc.x;
  492                   bounds.y = loc.y;
  493                   bounds.width = tip.getWidth();
  494                   bounds.height = tip.getHeight();
  495   
  496                   if (location.x >= bounds.x && location.x < (bounds.x + bounds.width) &&
  497                       location.y >= bounds.y && location.y < (bounds.y + bounds.height)) {
  498                       shouldHide = false;
  499                   } else {
  500                       shouldHide = true;
  501                   }
  502               }
  503           }
  504   
  505           if (shouldHide) {
  506               enterTimer.stop();
  507           if (insideComponent != null) {
  508                   insideComponent.removeMouseMotionListener(this);
  509               }
  510               insideComponent = null;
  511               toolTipText = null;
  512               mouseEvent = null;
  513               hideTipWindow();
  514               exitTimer.restart();
  515           }
  516       }
  517   
  518       // implements java.awt.event.MouseListener
  519       /**
  520        *  Called when the mouse is pressed.
  521        *  Any tool tip showing should be hidden.
  522        *
  523        *  @param event  the event in question
  524        */
  525       public void mousePressed(MouseEvent event) {
  526           hideTipWindow();
  527           enterTimer.stop();
  528           showImmediately = false;
  529           insideComponent = null;
  530           mouseEvent = null;
  531       }
  532   
  533       // implements java.awt.event.MouseMotionListener
  534       /**
  535        *  Called when the mouse is pressed and dragged.
  536        *  Does nothing.
  537        *
  538        *  @param event  the event in question
  539        */
  540       public void mouseDragged(MouseEvent event) {
  541       }
  542   
  543       // implements java.awt.event.MouseMotionListener
  544       /**
  545        *  Called when the mouse is moved.
  546        *  Determines whether the tool tip should be displayed.
  547        *
  548        *  @param event  the event in question
  549        */
  550       public void mouseMoved(MouseEvent event) {
  551           if (tipShowing) {
  552               checkForTipChange(event);
  553           }
  554           else if (showImmediately) {
  555               JComponent component = (JComponent)event.getSource();
  556               toolTipText = component.getToolTipText(event);
  557               if (toolTipText != null) {
  558                   preferredLocation = component.getToolTipLocation(event);
  559                   mouseEvent = event;
  560                   insideComponent = component;
  561                   exitTimer.stop();
  562                   showTipWindow();
  563               }
  564           }
  565           else {
  566               // Lazily lookup the values from within insideTimerAction
  567               insideComponent = (JComponent)event.getSource();
  568               mouseEvent = event;
  569               toolTipText = null;
  570               enterTimer.restart();
  571           }
  572       }
  573   
  574       /**
  575        * Checks to see if the tooltip needs to be changed in response to
  576        * the MouseMoved event <code>event</code>.
  577        */
  578       private void checkForTipChange(MouseEvent event) {
  579           JComponent component = (JComponent)event.getSource();
  580           String newText = component.getToolTipText(event);
  581           Point  newPreferredLocation = component.getToolTipLocation(event);
  582   
  583           if (newText != null || newPreferredLocation != null) {
  584               mouseEvent = event;
  585               if (((newText != null && newText.equals(toolTipText)) || newText == null) &&
  586                   ((newPreferredLocation != null && newPreferredLocation.equals(preferredLocation))
  587                    || newPreferredLocation == null)) {
  588                   if (tipWindow != null) {
  589                       insideTimer.restart();
  590                   } else {
  591                       enterTimer.restart();
  592                   }
  593               } else {
  594                   toolTipText = newText;
  595                   preferredLocation = newPreferredLocation;
  596                   if (showImmediately) {
  597                       hideTipWindow();
  598                       showTipWindow();
  599                       exitTimer.stop();
  600                   } else {
  601                       enterTimer.restart();
  602                   }
  603               }
  604           } else {
  605               toolTipText = null;
  606               preferredLocation = null;
  607               mouseEvent = null;
  608               insideComponent = null;
  609               hideTipWindow();
  610               enterTimer.stop();
  611               exitTimer.restart();
  612           }
  613       }
  614   
  615       protected class insideTimerAction implements ActionListener {
  616           public void actionPerformed(ActionEvent e) {
  617               if(insideComponent != null && insideComponent.isShowing()) {
  618                   // Lazy lookup
  619                   if (toolTipText == null && mouseEvent != null) {
  620                       toolTipText = insideComponent.getToolTipText(mouseEvent);
  621                       preferredLocation = insideComponent.getToolTipLocation(
  622                                                 mouseEvent);
  623                   }
  624                   if(toolTipText != null) {
  625                       showImmediately = true;
  626                       showTipWindow();
  627                   }
  628                   else {
  629                       insideComponent = null;
  630                       toolTipText = null;
  631                       preferredLocation = null;
  632                       mouseEvent = null;
  633                       hideTipWindow();
  634                   }
  635               }
  636           }
  637       }
  638   
  639       protected class outsideTimerAction implements ActionListener {
  640           public void actionPerformed(ActionEvent e) {
  641               showImmediately = false;
  642           }
  643       }
  644   
  645       protected class stillInsideTimerAction implements ActionListener {
  646           public void actionPerformed(ActionEvent e) {
  647               hideTipWindow();
  648               enterTimer.stop();
  649               showImmediately = false;
  650               insideComponent = null;
  651               mouseEvent = null;
  652           }
  653       }
  654   
  655     /* This listener is registered when the tooltip is first registered
  656      * on a component in order to catch the situation where the tooltip
  657      * was turned on while the mouse was already within the bounds of
  658      * the component.  This way, the tooltip will be initiated on a
  659      * mouse-entered or mouse-moved, whichever occurs first.  Once the
  660      * tooltip has been initiated, we can remove this listener and rely
  661      * solely on mouse-entered to initiate the tooltip.
  662      */
  663       private class MoveBeforeEnterListener extends MouseMotionAdapter {
  664           public void mouseMoved(MouseEvent e) {
  665               initiateToolTip(e);
  666           }
  667       }
  668   
  669       static Frame frameForComponent(Component component) {
  670           while (!(component instanceof Frame)) {
  671               component = component.getParent();
  672           }
  673           return (Frame)component;
  674       }
  675   
  676     private FocusListener createFocusChangeListener(){
  677       return new FocusAdapter(){
  678         public void focusLost(FocusEvent evt){
  679           hideTipWindow();
  680           insideComponent = null;
  681           JComponent c = (JComponent)evt.getSource();
  682           c.removeFocusListener(focusChangeListener);
  683         }
  684       };
  685     }
  686   
  687     // Returns: 0 no adjust
  688     //         -1 can't fit
  689     //         >0 adjust value by amount returned
  690     private int getPopupFitWidth(Rectangle popupRectInScreen, Component invoker){
  691       if (invoker != null){
  692         Container parent;
  693         for (parent = invoker.getParent(); parent != null; parent = parent.getParent()){
  694           // fix internal frame size bug: 4139087 - 4159012
  695           if(parent instanceof JFrame || parent instanceof JDialog ||
  696              parent instanceof JWindow) { // no check for awt.Frame since we use Heavy tips
  697             return getWidthAdjust(parent.getBounds(),popupRectInScreen);
  698           } else if (parent instanceof JApplet || parent instanceof JInternalFrame) {
  699             if (popupFrameRect == null){
  700               popupFrameRect = new Rectangle();
  701             }
  702             Point p = parent.getLocationOnScreen();
  703             popupFrameRect.setBounds(p.x,p.y,
  704                                      parent.getBounds().width,
  705                                      parent.getBounds().height);
  706             return getWidthAdjust(popupFrameRect,popupRectInScreen);
  707           }
  708         }
  709       }
  710       return 0;
  711     }
  712   
  713     // Returns:  0 no adjust
  714     //          >0 adjust by value return
  715     private int getPopupFitHeight(Rectangle popupRectInScreen, Component invoker){
  716       if (invoker != null){
  717         Container parent;
  718         for (parent = invoker.getParent(); parent != null; parent = parent.getParent()){
  719           if(parent instanceof JFrame || parent instanceof JDialog ||
  720              parent instanceof JWindow) {
  721             return getHeightAdjust(parent.getBounds(),popupRectInScreen);
  722           } else if (parent instanceof JApplet || parent instanceof JInternalFrame) {
  723             if (popupFrameRect == null){
  724               popupFrameRect = new Rectangle();
  725             }
  726             Point p = parent.getLocationOnScreen();
  727             popupFrameRect.setBounds(p.x,p.y,
  728                                      parent.getBounds().width,
  729                                      parent.getBounds().height);
  730             return getHeightAdjust(popupFrameRect,popupRectInScreen);
  731           }
  732         }
  733       }
  734       return 0;
  735     }
  736   
  737     private int getHeightAdjust(Rectangle a, Rectangle b){
  738       if (b.y >= a.y && (b.y + b.height) <= (a.y + a.height))
  739         return 0;
  740       else
  741         return (((b.y + b.height) - (a.y + a.height)) + 5);
  742     }
  743   
  744     // Return the number of pixels over the edge we are extending.
  745     // If we are over the edge the ToolTipManager can adjust.
  746     // REMIND: what if the Tooltip is just too big to fit at all - we currently will just clip
  747     private int getWidthAdjust(Rectangle a, Rectangle b){
  748       //    System.out.println("width b.x/b.width: " + b.x + "/" + b.width +
  749       //                 "a.x/a.width: " + a.x + "/" + a.width);
  750       if (b.x >= a.x && (b.x + b.width) <= (a.x + a.width)){
  751         return 0;
  752       }
  753       else {
  754         return (((b.x + b.width) - (a.x +a.width)) + 5);
  755       }
  756     }
  757   
  758   
  759       //
  760       // Actions
  761       //
  762       private void show(JComponent source) {
  763           if (tipWindow != null) { // showing we unshow
  764               hideTipWindow();
  765               insideComponent = null;
  766           }
  767           else {
  768               hideTipWindow(); // be safe
  769               enterTimer.stop();
  770               exitTimer.stop();
  771               insideTimer.stop();
  772               insideComponent = source;
  773               if (insideComponent != null){
  774                   toolTipText = insideComponent.getToolTipText();
  775                   preferredLocation = new Point(10,insideComponent.getHeight()+
  776                                                 10);  // manual set
  777                   showTipWindow();
  778                   // put a focuschange listener on to bring the tip down
  779                   if (focusChangeListener == null){
  780                       focusChangeListener = createFocusChangeListener();
  781                   }
  782                   insideComponent.addFocusListener(focusChangeListener);
  783               }
  784           }
  785       }
  786   
  787       private void hide(JComponent source) {
  788           hideTipWindow();
  789           source.removeFocusListener(focusChangeListener);
  790           preferredLocation = null;
  791           insideComponent = null;
  792       }
  793   
  794       /* This listener is registered when the tooltip is first registered
  795        * on a component in order to process accessibility keybindings.
  796        * This will apply globally across L&F
  797        *
  798        * Post Tip: Ctrl+F1
  799        * Unpost Tip: Esc and Ctrl+F1
  800        */
  801       private class AccessibilityKeyListener extends KeyAdapter {
  802           public void keyPressed(KeyEvent e) {
  803               if (!e.isConsumed()) {
  804                   JComponent source = (JComponent) e.getComponent();
  805                   if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
  806                       if (tipWindow != null) {
  807                           hide(source);
  808                           e.consume();
  809                       }
  810                   } else if (e.getKeyCode() == KeyEvent.VK_F1
  811                           && e.getModifiers() == Event.CTRL_MASK) {
  812                       // Shown tooltip will be hidden
  813                       ToolTipManager.this.show(source);
  814                       e.consume();
  815                   }
  816               }
  817           }
  818       }
  819   }

Save This Page
Home » openjdk-7 » javax » swing » [javadoc | source]