/**
* Copyright (c) 2009 - 2010 AppWork UG(haftungsbeschränkt) <e-mail@appwork.org>
*
* This file is part of org.appwork.swing.trayicon.view
*
* This software is licensed under the Artistic License 2.0,
* see the LICENSE file or http://www.opensource.org/licenses/artistic-license-2.0.php
* for details
*/
package org.appwork.swing.trayicon;
import java.awt.AWTException;
import java.awt.Image;
import java.awt.Point;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import org.appwork.utils.ImageProvider.ImageProvider;
import org.appwork.utils.event.BasicEvent;
import org.appwork.utils.event.BasicEventSender;
import org.appwork.utils.os.CrossSystem;
import org.appwork.utils.swing.EDTHelper;
import org.appwork.utils.swing.EDTRunner;
/**
* @author thomas
*/
public class AWTrayIcon implements MouseListener, TrayMouseListener {
public static final int EVENT_TOGGLE_FRAME_VISIBILITY = 0;
public static final int EVENT_SHOW_POPUP = 1;
public static final int EVENT_HIDE_POPUP = 2;
private final JFrame frame;
private ExtTrayIcon trayIcon;
private TrayIconPopup trayIconPopup;
private final int visibleToggleClickCount = 2;
private final BasicEventSender<AWTrayIcon> eventSender;
public AWTrayIcon(final JFrame frame) throws AWTException {
this(frame, frame.getIconImages() == null || frame.getIconImages().size() == 0 ? ImageProvider.createIcon(frame.getTitle() != null && frame.getTitle().length() > 0 ? frame.getTitle().charAt(0) + "" : "T", 32, 32) : frame.getIconImages().get(0));
}
public AWTrayIcon(final JFrame frame, final Image icon) throws AWTException {
this.frame = frame;
this.eventSender = new BasicEventSender<AWTrayIcon>();
final SystemTray systemTray = SystemTray.getSystemTray();
/*
* trayicon message must be set, else windows cannot handle icon right
* (eg autohide feature)
*/
this.trayIcon = new ExtTrayIcon(icon, frame.getTitle());
this.trayIcon.addMouseListener(this);
this.trayIcon.addTrayMouseListener(this);
systemTray.add(this.trayIcon);
}
public TrayIconPopup createPopup() {
return null;
}
public void displayToolTip() {
// trayIcon.getEstimatedTopLeft();
}
public void dispose() {
new EDTRunner() {
@Override
protected void runInEDT() {
try {
if (AWTrayIcon.this.trayIcon != null) {
SystemTray.getSystemTray().remove(AWTrayIcon.this.trayIcon);
AWTrayIcon.this.trayIcon.removeMouseListener(AWTrayIcon.this);
AWTrayIcon.this.trayIcon.removeTrayMouseListener(AWTrayIcon.this);
AWTrayIcon.this.trayIcon = null;
AWTrayIcon.this.hideToolTip();
if (AWTrayIcon.this.trayIconPopup != null) {
AWTrayIcon.this.trayIconPopup.dispose();
AWTrayIcon.this.trayIconPopup = null;
AWTrayIcon.this.eventSender.fireEvent(new BasicEvent<AWTrayIcon>(AWTrayIcon.this, AWTrayIcon.EVENT_HIDE_POPUP, AWTrayIcon.this, null));
}
}
} catch (final Exception e) {
}
}
};
}
/**
* @return the eventSender
*/
public BasicEventSender<AWTrayIcon> getEventSender() {
return this.eventSender;
}
public JFrame getFrame() {
return this.frame;
}
private void hideToolTip() {
}
public boolean isFrameVisible() {
return this.frame.isVisible();
}
public void mouseClicked(final MouseEvent e) {
}
public void mouseEntered(final MouseEvent e) {
}
public void mouseExited(final MouseEvent e) {
this.hideToolTip();
}
public void mouseMoveOverTray(final MouseEvent me) {
if (this.trayIconPopup != null && this.trayIconPopup.isVisible()) { return; }
this.displayToolTip();
}
public void mousePressed(final MouseEvent e) {
this.hideToolTip();
if (e.getSource() instanceof TrayIcon) {
if (!CrossSystem.isMac()) {
if (e.getClickCount() == this.visibleToggleClickCount && !SwingUtilities.isRightMouseButton(e)) {
this.eventSender.fireEvent(new BasicEvent<AWTrayIcon>(this, AWTrayIcon.EVENT_TOGGLE_FRAME_VISIBILITY, this, null));
this.onToggleVisibility();
} else {
if (this.trayIconPopup != null && this.trayIconPopup.isShowing()) {
this.trayIconPopup.dispose();
this.trayIconPopup = null;
this.eventSender.fireEvent(new BasicEvent<AWTrayIcon>(this, AWTrayIcon.EVENT_HIDE_POPUP, this, null));
} else if (SwingUtilities.isRightMouseButton(e)) {
this.trayIconPopup = this.createPopup();
if (this.trayIconPopup == null) { return; }
this.trayIconPopup.setPosition(e.getPoint());
this.trayIconPopup.setVisible(true);
this.trayIconPopup.startAutoHide();
this.eventSender.fireEvent(new BasicEvent<AWTrayIcon>(this, AWTrayIcon.EVENT_SHOW_POPUP, this, null));
}
}
} else {
if (SwingUtilities.isLeftMouseButton(e)) {
if (e.getClickCount() == this.visibleToggleClickCount && !SwingUtilities.isLeftMouseButton(e)) {
this.eventSender.fireEvent(new BasicEvent<AWTrayIcon>(this, AWTrayIcon.EVENT_TOGGLE_FRAME_VISIBILITY, this, null));
this.onToggleVisibility();
} else {
if (this.trayIconPopup != null && this.trayIconPopup.isShowing()) {
this.trayIconPopup.dispose();
this.trayIconPopup = null;
this.eventSender.fireEvent(new BasicEvent<AWTrayIcon>(this, AWTrayIcon.EVENT_HIDE_POPUP, this, null));
} else if (SwingUtilities.isLeftMouseButton(e)) {
this.trayIconPopup = this.createPopup();
if (this.trayIconPopup == null) { return; }
final Point pointOnScreen = e.getLocationOnScreen();
if (e.getX() > 0) {
pointOnScreen.x -= e.getPoint().x;
}
this.trayIconPopup.setPosition(pointOnScreen);
this.trayIconPopup.setVisible(true);
this.trayIconPopup.startAutoHide();
this.eventSender.fireEvent(new BasicEvent<AWTrayIcon>(this, AWTrayIcon.EVENT_SHOW_POPUP, this, null));
}
}
}
}
}
}
public void mouseReleased(final MouseEvent e) {
}
/**
*
*/
public void onToggleVisibility() {
this.setFrameVisible(!this.isFrameVisible());
}
public void setFrameVisible(final boolean visible) {
new EDTHelper<Object>() {
@Override
public Object edtRun() {
/*
* This is a workaround, because toFront does not work on all
* systems. Originally,this workaround used a Timer that resets
* the alwaysontop setting after 2000ms. This should work, too
*/
final JFrame resetAlwaysOnTop;
if (!visible) {
AWTrayIcon.this.frame.setVisible(false);
resetAlwaysOnTop = null;
} else {
if (!AWTrayIcon.this.frame.isAlwaysOnTop()) {
resetAlwaysOnTop = AWTrayIcon.this.frame;
} else {
resetAlwaysOnTop = null;
}
AWTrayIcon.this.frame.setAlwaysOnTop(true);
AWTrayIcon.this.frame.setVisible(true);
AWTrayIcon.this.frame.toFront();
}
if (visible && resetAlwaysOnTop != null) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
resetAlwaysOnTop.setAlwaysOnTop(false);
}
});
}
return null;
}
}.start();
}
public void setImage(final Image icon) {
this.trayIcon.setImage(icon);
}
public void setToolTip(final String tooltip) {
this.trayIcon.setToolTip(tooltip);
}
}