// jDownloader - Downloadmanager
// Copyright (C) 2008 JD-Team support@jdownloader.org
//
// This program 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 3 of the License, or
// (at your option) any later version.
//
// This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
package org.appwork.swing.trayicon;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.PointerInfo;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.JWindow;
import javax.swing.SwingConstants;
import net.miginfocom.swing.MigLayout;
import org.appwork.utils.event.BasicEvent;
import org.appwork.utils.os.CrossSystem;
import org.appwork.utils.swing.EDTHelper;
public abstract class TrayIconPopup extends JWindow {
/**
*
*/
private static final long serialVersionUID = -6632773260637754243L;
private boolean enteredPopup;
private transient final Thread hideThread;
private boolean hideThreadrunning = false;
private final AWTrayIcon owner;
/**
* @param awTrayIcon
*/
public TrayIconPopup(final AWTrayIcon awTrayIcon) {
super(awTrayIcon.getFrame());
this.owner = awTrayIcon;
this.setLayout(new MigLayout("ins 0", "[grow,fill]", "[grow,fill]"));
JPanel content = new JPanel(new MigLayout("ins 5, wrap 1", "[grow,fill]", "[]"));
content.setBorder(BorderFactory.createLineBorder(content.getBackground().darker()));
content = this.init(content);
if (content != null) {
this.add(content);
}
this.setAlwaysOnTop(true);
this.pack();
this.addMouseListener(new MouseListener() {
public void mouseClicked(final MouseEvent e) {
}
public void mouseEntered(final MouseEvent e) {
TrayIconPopup.this.enteredPopup = true;
}
public void mouseExited(final MouseEvent e) {
}
public void mousePressed(final MouseEvent e) {
}
public void mouseReleased(final MouseEvent e) {
}
});
this.hideThread = new Thread() {
/*
* this thread handles closing of popup because enter/exit/move
* events are too slow and can miss the exitevent
*/
@Override
public void run() {
while (true && TrayIconPopup.this.hideThreadrunning) {
try {
Thread.sleep(500);
} catch (final InterruptedException e) {
}
if (TrayIconPopup.this.enteredPopup && TrayIconPopup.this.hideThreadrunning) {
final PointerInfo mouse = MouseInfo.getPointerInfo();
final Point current = TrayIconPopup.this.getLocation();
if (mouse.getLocation().x < current.x || mouse.getLocation().x > current.x + TrayIconPopup.this.getSize().width) {
TrayIconPopup.this.dispose();
break;
} else if (mouse.getLocation().y < current.y || mouse.getLocation().y > current.y + TrayIconPopup.this.getSize().height) {
TrayIconPopup.this.dispose();
break;
}
}
}
}
};
this.hideThreadrunning = true;
this.hideThread.start();
}
protected Component createButton(final AbstractAction action) {
final JToggleButton bt = new JToggleButton(action);
bt.setOpaque(false);
bt.setContentAreaFilled(false);
bt.setBorderPainted(false);
bt.setIcon((Icon) action.getValue(Action.SMALL_ICON));
bt.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
TrayIconPopup.this.dispose();
}
});
bt.setFocusPainted(false);
bt.setHorizontalAlignment(SwingConstants.LEFT);
bt.setIconTextGap(5);
bt.addMouseListener(new HoverEffect(bt));
return bt;
}
@Override
public void dispose() {
this.hideThreadrunning = false;
super.dispose();
this.owner.getEventSender().fireEvent(new BasicEvent<AWTrayIcon>(this.owner, AWTrayIcon.EVENT_HIDE_POPUP, this.owner, null));
}
/**
* @return the owner
*/
public AWTrayIcon getTrayIcon() {
return this.owner;
}
/**
* layout window
*
* @param content
*/
abstract protected JPanel init(JPanel content);
/**
* @param point
*/
public void setPosition(final Point p) {
final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
final int limitX = (int) screenSize.getWidth() / 2;
final int limitY = (int) screenSize.getHeight() / 2;
if (!CrossSystem.isMac()) {
if (p.x <= limitX) {
if (p.y <= limitY) {
// top left
this.setLocation(p.x, p.y);
} else {
// bottom left
this.setLocation(p.x, p.y - this.getHeight());
}
} else {
if (p.y <= limitY) {
// top right
this.setLocation(p.x - this.getWidth(), p.y);
} else {
// bottom right
this.setLocation(p.x - this.getWidth(), p.y - this.getHeight());
}
}
} else {
if (p.getX() <= screenSize.getWidth() - this.getWidth()) {
this.setLocation((int) p.getX(), 22);
} else {
this.setLocation(p.x - this.getWidth(), 22);
}
}
}
/**
* start autohide in 3 secs if mouse did not enter popup before
*
* @param awTrayIcon
*/
public void startAutoHide() {
new Thread() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (final InterruptedException e) {
}
if (!TrayIconPopup.this.enteredPopup) {
new EDTHelper<Object>() {
@Override
public Object edtRun() {
TrayIconPopup.this.dispose();
return null;
}
}.start();
}
}
}.start();
}
}