/* * This file is part of muCommander, http://www.mucommander.com * Copyright (C) 2002-2016 Maxence Bernard * * muCommander 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. * * muCommander 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 com.mucommander.ui.notifier; import java.awt.SystemTray; import javax.swing.SwingUtilities; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.mucommander.commons.runtime.JavaVersion; import com.mucommander.commons.runtime.OsFamily; import com.mucommander.ui.main.WindowManager; /** * AbstractNotifier is a generic representation of a system notifier. It also provides factory methods to * retrieve the current platform's notifier instance, if there is one. * <p> * A notifier serves the purpose of displaying notifications to the screen, to inform the user of an event when * the application is not visible (in the background). * </p> * <p> * The notifier instance returnd by {@link #getNotifier()} is platform-dependent. At this time, two notifier * implementations are available: * <ul> * <li>{@link GrowlNotifier}: for Mac OS X, requires Growl to be installed * <li>{@link SystemTrayNotifier}: for Java 1.6 and up, using the java.awt.SystemTray API * </ul> * </p> * * @author Maxence Bernard */ public abstract class AbstractNotifier { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractNotifier.class); /** AbstractNotifier instance, null if none is available on the current platform */ private static AbstractNotifier notifier; static { // Finds and creates a suitable AbstractNotifier instance for the platform, if there is one if(OsFamily.MAC_OS_X.isCurrent()) notifier = new GrowlNotifier(); else if(JavaVersion.JAVA_1_6.isCurrentOrHigher() && SystemTray.isSupported()) notifier = new SystemTrayNotifier(); } /** * Returns <code>true<code> if an AbstractNotifier instance is available. In other words, if <code>true</code> is * returned, {@link #getNotifier()} will return a non-null value. * * @return true if an AbstractNotifier instance is available */ public static boolean isAvailable() { return notifier!=null; } /** * Returns an AbstractNotifier instance that can be used on the current platform, <code>null</code> if none * is available. * Note that the returned <code>AbstractNotifier</code> must be enabled before it can be used, which is not * guaranteed to succeed. * * @return an AbstractNotifier instance that can be used on the current platform, null if none is available */ public static AbstractNotifier getNotifier() { return notifier; } /** * Displays a notification with the specified type, title and description and returns <code>true</code> if the * notification could be displayed. The notification will not be displayed if the current muCommander window * (or one of its child windows) is presently in the foreground, so that the user doesn't get notified for things * that he/she can already see on the screen. * * <p> * The notification will not be displayed if: * <ul> * <li>muCommander is in the foreground * <li>this notifier is not enabled * <li>the notification could not be delivered because of an error * </ul> * </p> * * <p> * Note that this method is executed in a separate thread after all pending Swing events have been processed, * to ensure in the event of a window being made inactive that the notification will not be triggered. This method * immediately return s(i.e. does not wait for pending events) and thus is not be able to return if the notification * was displayed or not, unlike {@link #displayNotification(NotificationType, String, String)}. * </p> * * @param notificationType one of the available notification types, see {@link NotificationType} for possible values * @param title the title of the notification to display * @param description the description of the notification to display */ public void displayBackgroundNotification(final NotificationType notificationType, final String title, final String description) { SwingUtilities.invokeLater( new Thread() { @Override public void run() { if(WindowManager.getCurrentMainFrame().isAncestorOfActiveWindow()) { LOGGER.debug("Ignoring notification, application is in foreground"); return; } if(!displayNotification(notificationType, title, description)) LOGGER.debug("Notification failed to be displayed"); } } ); } ////////////////////// // Abstract methods // ////////////////////// /** * Enables/disables this notifier and returns <code>true</code> if the operation succeeded. A typical case * for returning false, is when the underlying notification system (e.g. Growl under Mac OS X) could not be reached. * * @param enabled true to enable this notifier, false to disable it * @return true if the operation succeeded */ public abstract boolean setEnabled(boolean enabled); /** * Returns <code>true</code> if this notifier is enabled and ready to display notifications. * * @return true if this notifier is enabled and ready to display notifications */ public abstract boolean isEnabled(); /** * Displays a notification with the specified type, title and description and returns <code>true</code> if the * notification could be displayed. Unlike {@link #displayBackgroundNotification(NotificationType, String, String)}, the * notification will be attempted for display even if muCommander is currently in the foreground. * * <p> * Returns <code>true</code> if the notification could be displayed, <code>false</code> if: * <ul> * <li>this notifier is not enabled * <li>the notification could not be delivered because of an error * </ul> * </p> * * @param notificationType one of the available notification types, see {@link NotificationType} for possible values * @param title the title of the notification to display * @param description the description of the notification to display * @return true if the notification was properly sent, false otherwise */ public abstract boolean displayNotification(NotificationType notificationType, String title, String description); /** * Returns a pretty name for the underlying notification system that can be displayed to the end user. * * @return a pretty name for the underlying notification system */ public abstract String getPrettyName(); }