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