/* * This file is part of DRBD Management Console by LINBIT HA-Solutions GmbH * by Rasto Levrinc. * * Copyright (C) 2009, Rastislav Levrinc * Copyright (C) 2009, LINBIT HA-Solutions GmbH. * * DRBD Management Console is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2, or (at your option) * any later version. * * DRBD Management Console 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 for more details. * * You should have received a copy of the GNU General Public License * along with drbd; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ package lcmc.common.ui.utils; import lcmc.logger.Logger; import lcmc.logger.LoggerFactory; import lcmc.common.domain.util.Tools; import java.awt.AWTException; import java.awt.Color; import java.awt.Dimension; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.MouseInfo; import java.awt.Point; import java.awt.Rectangle; import java.awt.Robot; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.geom.Point2D; import javax.swing.JList; import javax.swing.JToolTip; import javax.swing.ListModel; /** * A Jlist with updatable tooltips. */ public final class MyList<E> extends JList<E> implements ComponentWithTest { private static final Logger LOG = LoggerFactory.getLogger(MyList.class); private static final GraphicsDevice SCREEN_DEVICE = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); private JToolTip toolTip; /** Robot to move a mouse a little if a tooltip has changed. */ private final Robot robot; private Color toolTipBackground = null; public MyList(final ListModel<E> dataModel, final Color bg) { super(dataModel); toolTip = createToolTip(); Robot r = null; try { r = new Robot(SCREEN_DEVICE); } catch (final AWTException e) { LOG.appWarning("MyList: robot error"); } robot = r; setBackground(bg); } @Override public JToolTip createToolTip() { if (toolTip != null) { toolTip.setComponent(null); } toolTip = super.createToolTip(); if (toolTipBackground != null) { toolTip.setBackground(toolTipBackground); } return toolTip; } @Override public void setToolTipBackground(final Color toolTipBackground) { this.toolTipBackground = toolTipBackground; } /** Sets tooltip and wiggles the mouse to refresh it. */ @Override public void setToolTipText(String text) { if (text == null) { return; } if (text.isEmpty()) { text = " "; /* can't be "" */ } super.setToolTipText(text); toolTip.setTipText(text); if (toolTip != null && toolTip.isShowing() && robot != null) { final GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices(); int xOffset = 0; if (devices.length >= 2) { /* workaround for dual monitors that are flipped. */ //TODO: not sure how is it with three monitors final int x1 = devices[0].getDefaultConfiguration().getBounds().x; final int x2 = devices[1].getDefaultConfiguration().getBounds().x; if (x1 > x2) { xOffset = -x1; } } final Point2D p = MouseInfo.getPointerInfo().getLocation(); robot.mouseMove((int) p.getX() + xOffset - 1, (int) p.getY()); robot.mouseMove((int) p.getX() + xOffset + 1, (int) p.getY()); robot.mouseMove((int) p.getX() + xOffset, (int) p.getY()); } } /** * Returns location of the tooltip, so that it does not cover the menu * item. */ @Override public Point getToolTipLocation(final MouseEvent event) { final Point screenLocation = getLocationOnScreen(); final Rectangle sBounds = Tools.getScreenBounds(this); final Dimension size = toolTip.getPreferredSize(); if (screenLocation.x + size.width + event.getX() + 5 > sBounds.width) { return new Point(event.getX() - size.width - 5, event.getY() + 20); } return new Point(event.getX() + 5, /* to not cover the pointer. */ event.getY() + 20); } /** Clean up. */ void cleanup() { for (int i = 0; i < getModel().getSize(); i++) { final UpdatableItem m = (UpdatableItem) getModel().getElementAt(i); m.cleanup(); } for (final MouseListener ml : getMouseListeners()) { removeMouseListener(ml); } for (final KeyListener kl : getKeyListeners()) { removeKeyListener(kl); } for (final MouseMotionListener mml : getMouseMotionListeners()) { removeMouseMotionListener(mml); } toolTip.setComponent(null); } }