/* * Kontalk Java client * Copyright (C) 2016 Kontalk Devteam <devteam@kontalk.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.kontalk.view; import java.awt.AWTException; import java.awt.Image; import java.awt.SystemTray; import java.awt.TrayIcon; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Observable; import java.util.logging.Level; import java.util.logging.Logger; import com.alee.laf.menu.WebMenuItem; import com.alee.laf.menu.WebPopupMenu; import com.alee.laf.rootpane.WebDialog; import org.kontalk.model.Model; import org.kontalk.model.chat.ChatList; import org.kontalk.persistence.Config; import org.kontalk.util.Tr; /** * * @author Alexander Bikadorov {@literal <bikaejkb@mail.tu-berlin.de>} */ final class TrayManager implements ObserverTrait { private static final Logger LOGGER = Logger.getLogger(TrayManager.class.getName()); private static final Image NORMAL_TRAY = Utils.getImage("kontalk.png"); private static final Image NOTIFICATION_TRAY = Utils.getImage("kontalk_notification.png"); private final View mView; private final Model mModel; private final MainFrame mMainFrame; private TrayIcon mTrayIcon = null; TrayManager(View view, Model model, MainFrame mainFrame) { mView = view; mModel = model; mMainFrame = mainFrame; this.setTray(); } void setTray() { if (!Config.getInstance().getBoolean(Config.MAIN_TRAY)) { this.removeTray(); return; } if (!SystemTray.isSupported()) { LOGGER.info("tray icon not supported"); return; } if (mTrayIcon == null) mTrayIcon = this.createTrayIcon(); SystemTray tray = SystemTray.getSystemTray(); if (tray.getTrayIcons().length > 0) return; try { tray.add(mTrayIcon); } catch (AWTException ex) { LOGGER.log(Level.WARNING, "can't add tray icon", ex); } } void removeTray() { if (mTrayIcon != null) { SystemTray tray = SystemTray.getSystemTray(); tray.remove(mTrayIcon); } } @Override public void updateOnEDT(Observable o, Object arg) { if (arg != ChatList.ViewChange.UNREAD) return; if (mTrayIcon == null) return; mTrayIcon.setImage(getTrayImage()); } private Image getTrayImage() { return mModel.chats().isUnread() ? NOTIFICATION_TRAY : NORMAL_TRAY ; } private TrayIcon createTrayIcon() { // popup menu outside of frame, officially not supported final WebPopupMenu popup = new WebPopupMenu(); WebMenuItem quitItem = new WebMenuItem(Tr.tr("Quit")); quitItem.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent event) { mView.callShutDown(); } }); popup.add(quitItem); // workaround: menu does not disappear when focus is lost final WebDialog hiddenDialog = new WebDialog(); hiddenDialog.setUndecorated(true); // create an action listener to listen for default action executed on the tray icon MouseListener listener = new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { // menu must be shown on mouse release //check(e); } @Override public void mouseReleased(MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1) mMainFrame.toggleState(); else check(e); } private void check(MouseEvent e) { // if (!e.isPopupTrigger()) // return; hiddenDialog.setVisible(true); // TODO ugly code popup.setLocation(e.getX() - 20, e.getY() - 40); popup.setInvoker(hiddenDialog); popup.setCornerWidth(0); popup.setVisible(true); } }; TrayIcon trayIcon = new TrayIcon(this.getTrayImage(), "Kontalk" /*, popup*/); trayIcon.setImageAutoSize(true); trayIcon.addMouseListener(listener); return trayIcon; } }