001/*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License").  You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2009 Sun Microsystems, Inc.
025 *      Portions Copyright 2015 ForgeRock AS
026 */
027
028package org.opends.guitools.controlpanel.event;
029
030import java.awt.Component;
031import java.awt.Dimension;
032import java.awt.Point;
033import java.awt.Rectangle;
034import java.awt.event.MouseAdapter;
035import java.awt.event.MouseEvent;
036
037import javax.swing.JComponent;
038import javax.swing.JTable;
039import javax.swing.JToolTip;
040import javax.swing.Popup;
041import javax.swing.PopupFactory;
042import javax.swing.table.TableCellRenderer;
043
044/**
045 * This class listens to events and displays a tooltip when the user clicks on
046 * the object that registered this listener.
047 *
048 */
049public class ClickTooltipDisplayer extends MouseAdapter
050{
051  private boolean isTooltipVisible;
052  private Popup tipWindow;
053
054  /** {@inheritDoc} */
055  public void mouseExited(MouseEvent event)
056  {
057    hideToolTip(event);
058  }
059
060  /** {@inheritDoc} */
061  public void mousePressed(MouseEvent event)
062  {
063    if (isTooltipVisible)
064    {
065      hideToolTip(event);
066    }
067    else
068    {
069      displayToolTip(event);
070    }
071  }
072
073  /**
074   * Displays a tooltip depending on the MouseEvent received.
075   * @param event the mouse event.
076   */
077  private void displayToolTip(MouseEvent event)
078  {
079    JComponent component = (JComponent)event.getSource();
080    String toolTipText;
081    if (component instanceof JTable)
082    {
083      JTable table = (JTable)component;
084      int row = table.rowAtPoint(event.getPoint());
085      int column = table.columnAtPoint(event.getPoint());
086      if (row != -1 && column != -1)
087      {
088        TableCellRenderer renderer = table.getCellRenderer(row, column);
089        Component comp = renderer.getTableCellRendererComponent(table,
090            table.getValueAt(row, column), true, true, row, column);
091        if (comp instanceof JComponent)
092        {
093          // The coordinates must be translated.
094          Rectangle rect = table.getCellRect(row, column, true);
095          int x = event.getPoint().x - rect.x;
096          int y = event.getPoint().y - rect.y;
097          MouseEvent tEv = new MouseEvent(table, event.getID(),
098              event.getWhen(), event.getModifiers(), x, y,
099              event.getClickCount(), event.isPopupTrigger(), event.getButton());
100          toolTipText = ((JComponent)comp).getToolTipText(tEv);
101        }
102        else
103        {
104          toolTipText = null;
105        }
106      }
107      else
108      {
109        toolTipText = null;
110      }
111    }
112    else
113    {
114      toolTipText = component.getToolTipText();
115    }
116    if (toolTipText != null)
117    {
118      Point preferredLocation = component.getToolTipLocation(event);
119      Rectangle sBounds = component.getGraphicsConfiguration().
120      getBounds();
121
122      JToolTip tip = component.createToolTip();
123      tip.setTipText(toolTipText);
124      Dimension size = tip.getPreferredSize();
125      Point location = new Point();
126
127      Point screenLocation = component.getLocationOnScreen();
128      if(preferredLocation != null)
129      {
130        location.x = screenLocation.x + preferredLocation.x;
131        location.y = screenLocation.y + preferredLocation.y;
132      }
133      else
134      {
135        location.x = screenLocation.x + event.getX();
136        location.y = screenLocation.y + event.getY() + 20;
137      }
138
139      if (location.x < sBounds.x) {
140        location.x = sBounds.x;
141      }
142      else if (location.x - sBounds.x + size.width > sBounds.width) {
143        location.x = sBounds.x + Math.max(0, sBounds.width - size.width);
144      }
145      if (location.y < sBounds.y) {
146        location.y = sBounds.y;
147      }
148      else if (location.y - sBounds.y + size.height > sBounds.height) {
149        location.y = sBounds.y + Math.max(0, sBounds.height - size.height);
150      }
151
152      PopupFactory popupFactory = PopupFactory.getSharedInstance();
153      tipWindow = popupFactory.getPopup(component, tip, location.x, location.y);
154      tipWindow.show();
155      isTooltipVisible = true;
156    }
157  }
158
159  /**
160   * Hides the tooltip if we are displaying it.
161   * @param event the mouse event.
162   */
163  private void hideToolTip(MouseEvent event)
164  {
165    if (tipWindow != null)
166    {
167      tipWindow.hide();
168      tipWindow = null;
169      isTooltipVisible = false;
170    }
171  }
172}