diff options
author | Symphorien Wanko <wsympho@gmail.com> | 2009-02-17 10:19:19 +0000 |
---|---|---|
committer | Symphorien Wanko <wsympho@gmail.com> | 2009-02-17 10:19:19 +0000 |
commit | ff8ec3ad3f95716e141bc19381e8b6773d63f01c (patch) | |
tree | 6184808c33f5f4e57559ee60407de669b6b8e2df /src/net/java/sip | |
parent | 5762c48e3910e6e4ff92a4a4a0e3dfbb57905a10 (diff) | |
download | jitsi-ff8ec3ad3f95716e141bc19381e8b6773d63f01c.zip jitsi-ff8ec3ad3f95716e141bc19381e8b6773d63f01c.tar.gz jitsi-ff8ec3ad3f95716e141bc19381e8b6773d63f01c.tar.bz2 |
swing based popup notifications with tests for the PopupMessage interface.
added checks for null SystemTrayPeer as it this possible it doesnt exists on the cruise control machine
Diffstat (limited to 'src/net/java/sip')
23 files changed, 1462 insertions, 615 deletions
diff --git a/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationActivator.java b/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationActivator.java index ba5d495..bab6539 100644 --- a/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationActivator.java +++ b/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationActivator.java @@ -6,6 +6,7 @@ */ package net.java.sip.communicator.impl.growlnotification; +import net.java.sip.communicator.service.resources.*; import org.osgi.framework.*; import net.java.sip.communicator.util.*; @@ -18,16 +19,26 @@ import net.java.sip.communicator.util.*; public class GrowlNotificationActivator implements BundleActivator { + /** + * The bundle context in which we started + */ + public static BundleContext bundleContext; + private static final Logger logger = Logger.getLogger(GrowlNotificationActivator.class); /** + * A reference to the resource management service. + */ + private static ResourceManagementService resourcesService; + + /** * Initialize and start Growl Notifications Service * * @param bundleContext BundleContext * @throws Exception */ - public void start(BundleContext bundleContext) throws Exception + public void start(BundleContext bc) throws Exception { /* Check Java version: do not start if Java 6 */ /* Actually, this plugin uses the Growl Java bindings which @@ -47,10 +58,26 @@ public class GrowlNotificationActivator logger.info("Growl Notification Plugin ...[Started]"); } + bundleContext = bc; } public void stop(BundleContext bundleContext) throws Exception { logger.info("Growl Notification Service ...[Stopped]"); } + + /** + * Returns the <tt>ResourceManagementService</tt> obtained from the bundle + * context. + * @return the <tt>ResourceManagementService</tt> obtained from the bundle + * context + */ + public static ResourceManagementService getResources() + { + if (resourcesService == null) + resourcesService = + ResourceManagementServiceUtils.getService(bundleContext); + return resourcesService; + + } } diff --git a/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationServiceImpl.java b/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationServiceImpl.java index 225a45e..8751393 100644 --- a/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationServiceImpl.java +++ b/src/net/java/sip/communicator/impl/growlnotification/GrowlNotificationServiceImpl.java @@ -7,14 +7,15 @@ package net.java.sip.communicator.impl.growlnotification; import java.lang.reflect.*; +import java.util.*; import org.osgi.framework.*; import com.growl.*; +import net.java.sip.communicator.service.systray.*; +import net.java.sip.communicator.service.systray.event.*; import net.java.sip.communicator.util.*; -import net.java.sip.communicator.service.protocol.*; -import net.java.sip.communicator.service.protocol.event.*; /** * The Growl Notification Service displays on-screen information such as @@ -23,8 +24,7 @@ import net.java.sip.communicator.service.protocol.event.*; * @author Romain Kuntz */ public class GrowlNotificationServiceImpl - implements MessageListener, - ServiceListener + implements PopupMessageHandler { /** * The logger for this class. @@ -33,11 +33,6 @@ public class GrowlNotificationServiceImpl Logger.getLogger(GrowlNotificationServiceImpl.class); /** - * The BundleContext that we got from the OSGI bus. - */ - private BundleContext bundleContext = null; - - /** * The Growl notifier */ private Growl notifier; @@ -68,6 +63,10 @@ public class GrowlNotificationServiceImpl */ private String sipIconPath = "resources/images/logo/sc_logo_128x128.icns"; + /** The list of all added popup listeners */ + private final List<SystrayPopupMessageListener> popupMessageListeners = + new Vector<SystrayPopupMessageListener>(); + /** * starts the service. Creates a Growl notifier, and check the current * registerd protocol providers which supports BasicIM and adds message @@ -80,7 +79,6 @@ public class GrowlNotificationServiceImpl throws Exception { logger.debug("Starting the Growl Notification implementation."); - this.bundleContext = bc; /* Register to Growl */ try @@ -121,38 +119,7 @@ public class GrowlNotificationServiceImpl throw ex; } - /* Start listening for newly register or removed protocol providers */ - bc.addServiceListener(this); - - ServiceReference[] protocolProviderRefs = null; - try - { - protocolProviderRefs = bc.getServiceReferences( - ProtocolProviderService.class.getName(), - null); - } - catch (InvalidSyntaxException ex) - { - // this shouldn't happen since we're providing no parameter string - // but let's log just in case. - logger.error("Error while retrieving service refs", ex); - return; - } - - // in case we found any - if (protocolProviderRefs != null) - { - logger.debug("Found " - + protocolProviderRefs.length - + " already installed providers."); - for (int i = 0; i < protocolProviderRefs.length; i++) - { - ProtocolProviderService provider = (ProtocolProviderService) bc - .getService(protocolProviderRefs[i]); - - this.handleProviderAdded(provider); - } - } + bc.registerService(PopupMessageHandler.class.getName(), this, null); } /** @@ -162,197 +129,6 @@ public class GrowlNotificationServiceImpl */ public void stop(BundleContext bc) { - // start listening for newly register or removed protocol providers - bc.removeServiceListener(this); - - ServiceReference[] protocolProviderRefs = null; - try - { - protocolProviderRefs = bc.getServiceReferences( - ProtocolProviderService.class.getName(), - null); - } - catch (InvalidSyntaxException ex) - { - // this shouldn't happen since we're providing no parameter string - // but let's log just in case. - logger.error( - "Error while retrieving service refs", ex); - return; - } - - // in case we found any - if (protocolProviderRefs != null) - { - for (int i = 0; i < protocolProviderRefs.length; i++) - { - ProtocolProviderService provider = (ProtocolProviderService) bc - .getService(protocolProviderRefs[i]); - - this.handleProviderRemoved(provider); - } - } - } - - // //////////////////////////////////////////////////////////////////////// - // MessageListener implementation methods - - /** - * Passes the newly received message to growl. - * @param evt MessageReceivedEvent the vent containing the new message. - */ - public void messageReceived(MessageReceivedEvent evt) - { - //byte[] contactImage = null; - //try - //{ - // contactImage = evt.getSourceContact().getImage(); - //} - //catch (Exception ex) - //{ - // logger.error("Failed to load contact photo for Growl", ex); - //} - - try - { - notifyGrowlOf("Message Received" - , sipIconPath - , evt.getSourceContact().getDisplayName() - , evt.getSourceMessage().getContent()); - } - catch (Exception ex) - { - logger.error("Could not notify the received message to Growl", ex); - } - } - - /** - * Notify growl that a message has been sent. - * @param evt the event containing the message that has just been sent. - */ - public void messageDelivered(MessageDeliveredEvent evt) - { - try - { - notifyGrowlOf("Message Sent" - , sipIconPath - , "Me" - , evt.getSourceMessage().getContent()); - } - catch (Exception ex) - { - logger.error("Could not pass the sent message to Growl", ex); - } - } - - /** - * Currently unused - * @param evt ignored - */ - public void messageDeliveryFailed(MessageDeliveryFailedEvent evt) - { - } - // ////////////////////////////////////////////////////////////////////////// - - /** - * When new protocol provider is registered we check - * does it supports BasicIM and if so add a listener to it - * - * @param serviceEvent ServiceEvent - */ - public void serviceChanged(ServiceEvent serviceEvent) - { - Object sService - = bundleContext.getService(serviceEvent.getServiceReference()); - - logger.trace("Received a service event for: " - + sService.getClass().getName()); - - // we don't care if the source service is not a protocol provider - if (! (sService instanceof ProtocolProviderService)) - { - return; - } - - logger.debug("Service is a protocol provider."); - if (serviceEvent.getType() == ServiceEvent.REGISTERED) - { - logger.debug("Handling registration of a new Protocol Provider."); - - this.handleProviderAdded((ProtocolProviderService)sService); - } - else if (serviceEvent.getType() == ServiceEvent.UNREGISTERING) - { - this.handleProviderRemoved( (ProtocolProviderService) sService); - } - - } - - /** - * Used to attach the Growl Notification Service to existing or - * just registered protocol provider. Checks if the provider has - * implementation of OperationSetBasicInstantMessaging - * - * @param provider ProtocolProviderService - */ - private void handleProviderAdded(ProtocolProviderService provider) - { - logger.debug("Adding protocol provider " + provider.getProtocolName()); - - // check whether the provider has a basic im operation set - OperationSetBasicInstantMessaging opSetIm = - (OperationSetBasicInstantMessaging) provider - .getOperationSet(OperationSetBasicInstantMessaging.class); - - if (opSetIm != null) - { - opSetIm.addMessageListener(this); - try - { - notifyGrowlOf("Protocol events" - , sipIconPath - , "New Protocol Registered" - , provider.getProtocolName() + " registered"); - } - catch (Exception ex) - { - logger.error("Could not notify the message to Growl", ex); - } - } - else - { - logger.trace("Service did not have a im op. set."); - } - } - - /** - * Removes the specified provider from the list of currently known providers - * and ignores all the messages exchanged by it - * - * @param provider the ProtocolProviderService that has been unregistered. - */ - private void handleProviderRemoved(ProtocolProviderService provider) - { - OperationSetBasicInstantMessaging opSetIm = - (OperationSetBasicInstantMessaging) provider - .getOperationSet(OperationSetBasicInstantMessaging.class); - - if (opSetIm != null) - { - opSetIm.removeMessageListener(this); - try - { - notifyGrowlOf("Protocol events" - , sipIconPath - , "Protocol deregistered" - , provider.getProtocolName() - + " deregistered"); - } - catch (Exception ex) - { - logger.error("Could not notify the message to Growl", ex); - } - } } /** @@ -408,4 +184,50 @@ public class GrowlNotificationServiceImpl setDefaultNotifMethod.invoke(notifier, new Object[]{inDefNotes}); } + public void addPopupMessageListener(SystrayPopupMessageListener listener) + { + synchronized (popupMessageListeners) + { + if (!popupMessageListeners.contains(listener)) + popupMessageListeners.add(listener); + } + } + + public void removePopupMessageListener(SystrayPopupMessageListener listener) + { + synchronized (popupMessageListeners) + { + popupMessageListeners.remove(listener); + } + } + + /** + * Implements <tt>PopupMessageHandler#showPopupMessage()</tt> + * + * @param popupMessage the message we will show + */ + public void showPopupMessage(PopupMessage popupMessage) + { + try + { + notifyGrowlOf("Message Received" + , sipIconPath + , popupMessage.getMessageTitle() + , popupMessage.getMessage()); + } + catch (Exception ex) + { + logger.error("Could not notify the received message to Growl", ex); + } + } + + /** + * Implements <tt>toString</tt> from <tt>PopupMessageHandler</tt> + * @return a description of this handler + */ + public String toString() + { + return GrowlNotificationActivator.getResources() + .getI18NString("impl.growlnotification.POPUP_MESSAGE_HANDLER"); + } } diff --git a/src/net/java/sip/communicator/impl/growlnotification/growlnotification.manifest.mf b/src/net/java/sip/communicator/impl/growlnotification/growlnotification.manifest.mf index c8b5a53..fb78f33 100644 --- a/src/net/java/sip/communicator/impl/growlnotification/growlnotification.manifest.mf +++ b/src/net/java/sip/communicator/impl/growlnotification/growlnotification.manifest.mf @@ -6,6 +6,7 @@ Bundle-Version: 0.0.1 System-Bundle: yes Import-Package: org.osgi.framework, net.java.sip.communicator.util, - net.java.sip.communicator.service.protocol, - net.java.sip.communicator.service.protocol.event, + net.java.sip.communicator.service.resources, + net.java.sip.communicator.service.systray, + net.java.sip.communicator.service.systray.event, com.growl diff --git a/src/net/java/sip/communicator/impl/notification/NotificationServiceImpl.java b/src/net/java/sip/communicator/impl/notification/NotificationServiceImpl.java index 9e89f1f..cd635fe 100644 --- a/src/net/java/sip/communicator/impl/notification/NotificationServiceImpl.java +++ b/src/net/java/sip/communicator/impl/notification/NotificationServiceImpl.java @@ -12,6 +12,7 @@ import net.java.sip.communicator.impl.notification.EventNotification.*; import net.java.sip.communicator.service.configuration.*; import net.java.sip.communicator.service.notification.*; import net.java.sip.communicator.service.notification.event.*; +import net.java.sip.communicator.service.systray.*; import net.java.sip.communicator.util.*; /** @@ -394,13 +395,13 @@ public class NotificationServiceImpl NotificationActionHandler handler = action.getActionHandler(); - if (!handler.isEnabled()) + if ((handler == null) || !handler.isEnabled()) continue; if (actionType.equals(NotificationService.ACTION_POPUP_MESSAGE)) { ((PopupMessageNotificationHandler) handler) - .popupMessage(title, message); + .popupMessage(new PopupMessage(title, message)); } else if (actionType.equals(NotificationService.ACTION_LOG_MESSAGE)) { diff --git a/src/net/java/sip/communicator/impl/notification/PopupMessageNotificationHandlerImpl.java b/src/net/java/sip/communicator/impl/notification/PopupMessageNotificationHandlerImpl.java index 05349b9..b335217 100644 --- a/src/net/java/sip/communicator/impl/notification/PopupMessageNotificationHandlerImpl.java +++ b/src/net/java/sip/communicator/impl/notification/PopupMessageNotificationHandlerImpl.java @@ -46,19 +46,17 @@ public class PopupMessageNotificationHandlerImpl /** * Shows a popup message through the <tt>SystrayService</tt>. - * - * @param title the title of the popup + * * @param message the message to show in the popup */ - public void popupMessage(String title, String message) + public void popupMessage(PopupMessage message) { SystrayService systray = NotificationActivator.getSystray(); - + if(systray == null) return; - - systray.showPopupMessage(title, message, - SystrayService.NONE_MESSAGE_TYPE); + + systray.showPopupMessage(message); } /** diff --git a/src/net/java/sip/communicator/impl/swingnotification/PopupMessageHandlerSwingImpl.java b/src/net/java/sip/communicator/impl/swingnotification/PopupMessageHandlerSwingImpl.java new file mode 100644 index 0000000..79748e1 --- /dev/null +++ b/src/net/java/sip/communicator/impl/swingnotification/PopupMessageHandlerSwingImpl.java @@ -0,0 +1,295 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.swingnotification; + +import java.awt.*; +import java.awt.event.*; +import java.util.*; +import java.util.List; +import javax.swing.*; + +import javax.swing.Timer; +import net.java.sip.communicator.service.systray.*; +import net.java.sip.communicator.service.systray.event.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.swing.*; + +/** + * An implementation of <tt>PopupMessageHandler</tt> using swing. + * @author Symphorien Wanko + */ +public class PopupMessageHandlerSwingImpl implements PopupMessageHandler +{ + + /** logger for the <tt>PopupMessageHandlerSwingImpl</tt> class */ + private final Logger logger = + Logger.getLogger(PopupMessageHandlerSwingImpl.class); + + /** The list of all added popup listeners */ + private final List<SystrayPopupMessageListener> popupMessageListeners = + new Vector<SystrayPopupMessageListener>(); + + /** An icon representing the contact from which the notification comes */ + private ImageIcon defaultIcon = + SwingNotificationActivator.getResources().getImage( + "service.gui.DEFAULT_USER_PHOTO");; + + /** + * Adds a listerner to receive popup events + * @param listener the listener to add + */ + public void addPopupMessageListener(SystrayPopupMessageListener listener) + { + synchronized (popupMessageListeners) + { + if (!popupMessageListeners.contains(listener)) + popupMessageListeners.add(listener); + } + } + + /** + * Removes a listerner previously added with <tt>addPopupMessageListener</tt> + * @param listener the listener to remove + */ + public void removePopupMessageListener(SystrayPopupMessageListener listener) + { + synchronized (popupMessageListeners) + { + popupMessageListeners.remove(listener); + } + } + + /** + * Implements <tt>PopupMessageHandler#showPopupMessage()</tt> + * + * @param popupMessage the message we will show + */ + public void showPopupMessage(PopupMessage popupMessage) + { + final GraphicsConfiguration graphicsConf = + GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice(). + getDefaultConfiguration(); + + final JWindow notificationWindow = new JWindow(graphicsConf); + notificationWindow.setPreferredSize(new Dimension(225, 125)); + + final Timer popupTimer = new Timer(10000, new ActionListener() + { + + public void actionPerformed(ActionEvent e) + { + if (notificationWindow.isVisible()) + new Thread(new PopupDiscarder(notificationWindow)).start(); + } + }); + + popupTimer.setRepeats(false); + + notificationWindow.addMouseListener(new MouseAdapter() + { + + @Override + public void mouseEntered(MouseEvent e) + { + popupTimer.stop(); + } + + @Override + public void mouseExited(MouseEvent e) + { + popupTimer.start(); + } + + @Override + public void mouseClicked(MouseEvent e) + { + firePopupMessageClicked(new SystrayPopupMessageEvent(e)); + notificationWindow.dispose(); + } + }); + + if (popupMessage.getComponent() != null) + notificationWindow.add(popupMessage.getComponent()); + else + notificationWindow.add(createPopup( + popupMessage.getMessageTitle(), + popupMessage.getMessage(), + popupMessage.getIcon())); + notificationWindow.setAlwaysOnTop(true); + notificationWindow.pack(); + + new Thread(new PopupLauncher(notificationWindow, graphicsConf)).start(); + popupTimer.start(); + } + + /** + * builds the popup component with given informations. + * + * @param title message title + * @param message message content + * @param icon message icon + * @return + */ + private JComponent createPopup(String title, String message, + ImageIcon icon) + { + String msg; + + if (message.length() > 70) + msg = "<html><b>" + message.substring(0, 77) + "..."; + else + msg = "<html><b>" + message; + + JLabel msgContent = new JLabel(msg); + + if (title.length() > 40) + title = title.substring(0, 28) + "..."; + JLabel msgFrom = new JLabel(title); + msgFrom.setForeground(Color.DARK_GRAY); + + JLabel msgIcon = (icon == null) ? + new JLabel(defaultIcon) : + new JLabel(icon); + msgIcon.setOpaque(false); + msgIcon.setPreferredSize(new Dimension(45, 45)); + + JPanel notificationContent = new JPanel(new BorderLayout(5, 1)); + notificationContent.setBorder( + BorderFactory.createEmptyBorder(10, 10, 10, 10)); + notificationContent.setOpaque(false); + + notificationContent.add(msgFrom, BorderLayout.NORTH); + notificationContent.add(msgContent, BorderLayout.CENTER); + notificationContent.add(msgIcon, BorderLayout.WEST); + + return new PopupNotificationPanel(notificationContent); + } + + /** + * Notifies all interested listeners that a <tt>SystrayPopupMessageEvent</tt> + * occured. + * + * @param SystrayPopupMessageEvent the evt to send to listener. + */ + private void firePopupMessageClicked(SystrayPopupMessageEvent evt) + { + logger.trace("Will dispatch the following popup event: " + evt); + + List<SystrayPopupMessageListener> listeners; + synchronized (popupMessageListeners) + { + listeners = + new ArrayList<SystrayPopupMessageListener>( + popupMessageListeners); + } + + for (SystrayPopupMessageListener listener : listeners) + listener.popupMessageClicked(evt); + } + + /** + * Implements <tt>toString</tt> from <tt>PopupMessageHandler</tt> + * @return a description of this handler + */ + public String toString() + { + return SwingNotificationActivator.getResources() + .getI18NString("impl.swingnotification.POPUP_MESSAGE_HANDLER"); + } + + /** + * provide animation to hide a popup. The animation could be described + * as an "inverse" of the one made by <tt>PopupLauncher</tt>. + */ + class PopupDiscarder implements Runnable + { + + private JWindow notificationWindow; + + PopupDiscarder(JWindow notificationWindow) + { + this.notificationWindow = notificationWindow; + } + + public void run() + { + int height = notificationWindow.getY(); + int x = notificationWindow.getX(); + do + { + notificationWindow.setLocation( + x, + notificationWindow.getY() + 2); + try + { + Thread.sleep(10); + height -= 2; + } catch (InterruptedException ex) + { + logger.warn("exception while discarding" + + " popup notification window :", ex); + } + } while (height > 0); + notificationWindow.dispose(); + } + } + + /** + * provide animation to show a popup. The popup comes from the bottom of + * screen and will stay in the bottom right corner. + */ + class PopupLauncher implements Runnable + { + + private final JWindow notificationWindow; + + private final int x; + + private final int y; + + PopupLauncher(JWindow notificationWindow, + GraphicsConfiguration graphicsConf) + { + this.notificationWindow = notificationWindow; + + final Rectangle rec = graphicsConf.getBounds(); + + final Insets ins = + Toolkit.getDefaultToolkit().getScreenInsets(graphicsConf); + + x = rec.width + rec.x - + ins.right - notificationWindow.getWidth() - 1; + + y = rec.height + rec.y - + ins.bottom - notificationWindow.getHeight() - 1; + + notificationWindow.setLocation(x, rec.height); + notificationWindow.setVisible(true); + } + + public void run() + { + int height = y - notificationWindow.getY(); + do + { + notificationWindow.setLocation( + x, + notificationWindow.getY() - 2); + try + { + Thread.sleep(10); + height += 2; + } catch (InterruptedException ex) + { + logger.warn("exception while showing" + + " popup notification window :", ex); + } + } while (height < 0); + } + } +} diff --git a/src/net/java/sip/communicator/impl/swingnotification/SwingNotificationActivator.java b/src/net/java/sip/communicator/impl/swingnotification/SwingNotificationActivator.java new file mode 100644 index 0000000..d9e61d3 --- /dev/null +++ b/src/net/java/sip/communicator/impl/swingnotification/SwingNotificationActivator.java @@ -0,0 +1,113 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.swingnotification; + +import org.osgi.framework.*; + +import net.java.sip.communicator.service.configuration.*; +import net.java.sip.communicator.service.resources.*; +import net.java.sip.communicator.service.systray.*; +import net.java.sip.communicator.util.*; + +/** + * Activator for the swing notification service. + * @author Symphorien Wanko + */ +public class SwingNotificationActivator implements BundleActivator +{ + /** + * The bundle context in which we started + */ + public static BundleContext bundleContext; + + /** + * A reference to the configuration service. + */ + private static ConfigurationService configService; + + /** + * Logger for this class. + */ + private static final Logger logger = + Logger.getLogger(SwingNotificationActivator.class); + + /** + * A reference to the resource management service. + */ + private static ResourceManagementService resourcesService; + + /** + * start the swing notification service and set the swing popup handler as + * the default if there is no default popup handler. + * @param bc + * @throws java.lang.Exception + */ + public void start(BundleContext bc) throws Exception + { + logger.info("Swing Notification ...[ STARTING ]"); + + bundleContext = bc; + + PopupMessageHandler handler = null; + handler = new PopupMessageHandlerSwingImpl(); + + getConfigurationService(); + + String defaultHandler = + (String) configService.getProperty("systray.POPUP_HANDLER"); + if (defaultHandler == null) + { + configService.setProperty( + "systray.POPUP_HANDLER", handler.getClass().getName()); + } + bc.registerService( + PopupMessageHandler.class.getName() + , handler + , null); + + logger.info("Swing Notification ...[REGISTERED]"); + } + + public void stop(BundleContext arg0) throws Exception + { + + } + + /** + * Returns the <tt>ConfigurationService</tt> obtained from the bundle + * context. + * @return the <tt>ConfigurationService</tt> obtained from the bundle + * context + */ + public static ConfigurationService getConfigurationService() + { + if(configService == null) { + ServiceReference configReference = bundleContext + .getServiceReference(ConfigurationService.class.getName()); + + configService = (ConfigurationService) bundleContext + .getService(configReference); + } + + return configService; + } + + /** + * Returns the <tt>ResourceManagementService</tt> obtained from the bundle + * context. + * @return the <tt>ResourceManagementService</tt> obtained from the bundle + * context + */ + public static ResourceManagementService getResources() + { + if (resourcesService == null) + resourcesService = + ResourceManagementServiceUtils.getService(bundleContext); + return resourcesService; + + } +} diff --git a/src/net/java/sip/communicator/impl/swingnotification/swingnotification.manifest.mf b/src/net/java/sip/communicator/impl/swingnotification/swingnotification.manifest.mf new file mode 100644 index 0000000..edaf035 --- /dev/null +++ b/src/net/java/sip/communicator/impl/swingnotification/swingnotification.manifest.mf @@ -0,0 +1,14 @@ +Bundle-Activator: net.java.sip.communicator.impl.swingnotification.SwingNotificationActivator
+Bundle-Name: Swing Notification Service Provider
+Bundle-Description: A bundle that implements swing notification.
+Bundle-Vendor: sip-communicator.org
+Bundle-Version: 0.0.1
+System-Bundle: yes
+Import-Package: org.osgi.framework,
+ net.java.sip.communicator.service.configuration,
+ net.java.sip.communicator.service.resources,
+ net.java.sip.communicator.service.systray,
+ net.java.sip.communicator.service.systray.event,
+ net.java.sip.communicator.util,
+ net.java.sip.communicator.util.swing,
+ javax.swing
diff --git a/src/net/java/sip/communicator/impl/systray/PopupMessageHandlerTrayIconImpl.java b/src/net/java/sip/communicator/impl/systray/PopupMessageHandlerTrayIconImpl.java new file mode 100644 index 0000000..1cbe327 --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/PopupMessageHandlerTrayIconImpl.java @@ -0,0 +1,131 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.impl.systray; + +import java.awt.event.*; +import java.util.*; +import java.util.List; + +import net.java.sip.communicator.impl.systray.jdic.*; +import net.java.sip.communicator.service.systray.*; +import net.java.sip.communicator.service.systray.event.*; +import net.java.sip.communicator.util.*; + +/** + * An implementation of the <tt>PopupMsystrayessageHandler</tt> using the tray icon. + */ +public class PopupMessageHandlerTrayIconImpl implements PopupMessageHandler +{ + /** + * The logger for this class. + */ + private static Logger logger = + Logger.getLogger(PopupMessageHandlerTrayIconImpl.class); + + /** The list of all added systray popup listeners */ + private final List<SystrayPopupMessageListener> PopupMessageListener = + new Vector<SystrayPopupMessageListener>(); + + /** the tray icon we will use to popup messages */ + private TrayIcon trayIcon; + + + /** + * Creates a new <tt>PopupMessageHandlerTrayIconImpl</tt> which will uses + * the provided <tt>TrayIcon</tt> to show message. + * @param icon the icon we will use to show popup message. + */ + public PopupMessageHandlerTrayIconImpl(TrayIcon icon) + { + trayIcon = icon; + icon.addBalloonActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + firePopupMessageClicked(new SystrayPopupMessageEvent(e)); + } + }); + } + + /** + * Implementation of <tt>PopupMessageHandler.addPopupMessageListener</tt> + * @param listener the listener to add + */ + public void addPopupMessageListener(SystrayPopupMessageListener listener) + { + synchronized (PopupMessageListener) + { + if (!PopupMessageListener.contains(listener)) + PopupMessageListener.add(listener); + } + } + + /** + * Implementation of <tt>PopupMessageHandler.removePopupMessageListener</tt> + * @param listener the listener to remove + */ + public void removePopupMessageListener(SystrayPopupMessageListener listener) + { + synchronized (PopupMessageListener) + { + PopupMessageListener.remove(listener); + } + } + + /** + * Implements <tt>PopupMessageHandler#showPopupMessage()</tt> + * + * @param popupMessage the message we will show + */ + public void showPopupMessage(PopupMessage popupMessage) + { + // remove eventual html code before showing the popup message + String messageContent = popupMessage.getMessage() + .replaceAll("</?\\w++[^>]*+>", ""); + String messageTitle = popupMessage.getMessageTitle() + .replaceAll("</?\\w++[^>]*+>", ""); + + if(messageContent.length() > 40) + messageContent = messageContent.substring(0, 40).concat("..."); + trayIcon.displayMessage( + messageTitle, + messageContent, + TrayIcon.NONE_MESSAGE_TYPE); + } + + /** + * Notifies all interested listeners that a <tt>SystrayPopupMessageEvent</tt> + * has occured. + * + * @param SystrayPopupMessageEvent the evt to send to listener. + */ + private void firePopupMessageClicked(SystrayPopupMessageEvent evt) + { + logger.trace("Will dispatch the following systray popup event: " + evt); + + List<SystrayPopupMessageListener> listeners; + synchronized (PopupMessageListener) + { + listeners = + new ArrayList<SystrayPopupMessageListener>( + PopupMessageListener); + } + + for (SystrayPopupMessageListener listener : listeners) + listener.popupMessageClicked(evt); + } + + /** + * Implements <tt>toString</tt> from <tt>PopupMessageHandler</tt> + * @return a description of this handler + */ + public String toString() + { + return SystrayActivator.getResources() + .getI18NString("impl.systray.POPUP_MESSAGE_HANDLER"); + } +} diff --git a/src/net/java/sip/communicator/impl/systray/SystrayActivator.java b/src/net/java/sip/communicator/impl/systray/SystrayActivator.java index d0f3128..82511a0 100644 --- a/src/net/java/sip/communicator/impl/systray/SystrayActivator.java +++ b/src/net/java/sip/communicator/impl/systray/SystrayActivator.java @@ -116,8 +116,8 @@ public class SystrayActivator ServiceReference serviceRef = bundleContext .getServiceReference(UIService.class.getName()); - uiService = (UIService) bundleContext - .getService(serviceRef); + if (serviceRef != null) + uiService = (UIService) bundleContext.getService(serviceRef); } return uiService; diff --git a/src/net/java/sip/communicator/impl/systray/jdic/SystemTray.java b/src/net/java/sip/communicator/impl/systray/jdic/SystemTray.java index 0463345..26b186a 100644 --- a/src/net/java/sip/communicator/impl/systray/jdic/SystemTray.java +++ b/src/net/java/sip/communicator/impl/systray/jdic/SystemTray.java @@ -56,8 +56,17 @@ public class SystemTray // We'll try org.jdesktop.jdic.tray then.
}
if (peer == null)
- peer = new JdicSystemTrayPeer();
-
+ try
+ {
+ peer = new JdicSystemTrayPeer();
+ }
+ catch (Exception ex)
+ {
+ logger
+ .error(
+ "Failed to initialize the org.jdesktop.jdic.tray implementation.",
+ ex);
+ }
return (defaultSystemTray = new SystemTray(peer));
}
@@ -72,7 +81,8 @@ public class SystemTray throws NullPointerException,
IllegalArgumentException
{
- getPeer().addTrayIcon(trayIcon.getPeer());
+ if (peer != null)
+ peer.addTrayIcon(trayIcon.getPeer());
}
SystemTrayPeer getPeer()
@@ -82,7 +92,9 @@ public class SystemTray public boolean isSwing()
{
- return getPeer().isSwing();
+ if (peer != null)
+ return getPeer().isSwing();
+ return false;
}
static interface SystemTrayPeer
diff --git a/src/net/java/sip/communicator/impl/systray/jdic/SystrayServiceJdicImpl.java b/src/net/java/sip/communicator/impl/systray/jdic/SystrayServiceJdicImpl.java index b59a227..9ccc8b0 100644 --- a/src/net/java/sip/communicator/impl/systray/jdic/SystrayServiceJdicImpl.java +++ b/src/net/java/sip/communicator/impl/systray/jdic/SystrayServiceJdicImpl.java @@ -6,11 +6,12 @@ */ package net.java.sip.communicator.impl.systray.jdic; +import org.osgi.framework.*; + import java.awt.Toolkit; import java.awt.event.*; import java.net.*; import java.util.*; -import java.util.Timer; import javax.swing.*; import javax.swing.event.*; @@ -31,10 +32,12 @@ import net.java.sip.communicator.util.*; * @author Nicolas Chamouard * @author Yana Stamcheva * @author Lubomir Marinov + * @author Symphorien Wanko */ public class SystrayServiceJdicImpl implements SystrayService { + /** * The systray. */ @@ -51,61 +54,71 @@ public class SystrayServiceJdicImpl private Object menu; /** - * The list of all added popup message listeners. + * The popup handler currently used to show popup messages */ - private final List<SystrayPopupMessageListener> popupMessageListeners = - new Vector<SystrayPopupMessageListener>(); + private PopupMessageHandler activePopupHandler; /** - * List of all messages waiting to be shown. + * A set of usable <tt>PopupMessageHandler</tt> */ - private final List<SystrayMessage> messageQueue = - new ArrayList<SystrayMessage>(); - - private Timer popupTimer = new Timer(); + private final Hashtable<String, PopupMessageHandler> popupHandlerSet = + new Hashtable<String, PopupMessageHandler>(); /** - * The delay between the message pop ups. + * Stores the system time, when the main window was restored the last time */ - private int messageDelay = 1000; - - private int maxMessageNumber = 3; - - private SystrayMessage aggregatedMessage; + private long setVisibleTime = 0; /** - * Stores the system time, when the main window was restored the last time + * A reference of the <tt>ConfigurationService</tt> obtained from the + * <tt>SystrayServiceActivator</tt> */ - private long setVisibleTime = 0; + private final ConfigurationService configService = SystrayActivator. + getConfigurationService(); /** * The logger for this class. */ - private static Logger logger = - Logger.getLogger(SystrayServiceJdicImpl.class.getName()); + private static final Logger logger = + Logger.getLogger(SystrayServiceJdicImpl.class); /** * The various icons used on the systray */ private ImageIcon currentIcon; + private ImageIcon logoIcon; + private ImageIcon logoIconOffline; + private ImageIcon logoIconAway; + private ImageIcon logoIconFFC; + private ImageIcon logoIconWhite; + private ImageIcon envelopeIcon; + private ImageIcon envelopeIconWhite; /** * The dock Icons used only in Mac version */ private URL dockIconOffline; + private URL dockIconAway; + private URL dockIconFFC; private boolean initialized = false; /** + * the listener we will use for popup message event (clicks on the popup) + */ + private final SystrayPopupMessageListener popupMessageListener = + new SystrayPopupMessageListenerImpl(); + + /** * Creates an instance of <tt>Systray</tt>. */ public SystrayServiceJdicImpl() @@ -113,17 +126,20 @@ public class SystrayServiceJdicImpl try { systray = SystemTray.getDefaultSystemTray(); - } - catch (Throwable e) + } catch (Throwable e) { logger.error("Failed to create a systray!", e); } - if(systray != null) + if (systray != null) { this.initSystray(); - SystrayActivator.getUIService().setExitOnMainWindowClose(false); + UIService ui = SystrayActivator.getUIService(); + if (ui != null) + { + ui.setExitOnMainWindowClose(false); + } } } @@ -132,13 +148,12 @@ public class SystrayServiceJdicImpl */ private void initSystray() { - popupTimer.scheduleAtFixedRate(new ShowPopupTask(), 0, messageDelay); // Get the system's double click speed Object o = Toolkit.getDefaultToolkit().getDesktopProperty( - "awt.multiClickInterval"); - final int doubleClickSpeed = (o instanceof Integer ? ((Integer) o) - .intValue() : 500); + "awt.multiClickInterval"); + final int doubleClickSpeed = (o instanceof Integer ? ((Integer) o). + intValue() : 500); menu = TrayMenuFactory.createTrayMenu(this, systray.isSwing()); @@ -147,35 +162,31 @@ public class SystrayServiceJdicImpl // background. if (osName.startsWith("Windows")) { - logoIcon - = Resources.getImage("service.systray.TRAY_ICON_WINDOWS"); - logoIconOffline - = Resources.getImage("service.systray.TRAY_ICON_WINDOWS_OFFLINE"); - logoIconAway - = Resources.getImage("service.systray.TRAY_ICON_WINDOWS_AWAY"); - logoIconFFC - = Resources.getImage("service.systray.TRAY_ICON_WINDOWS_FFC"); - envelopeIcon - = Resources.getImage("service.systray.MESSAGE_ICON_WINDOWS"); - } - - // If we're running under MacOSX, we use a special black and + logoIcon = Resources.getImage("service.systray.TRAY_ICON_WINDOWS"); + logoIconOffline = Resources.getImage( + "service.systray.TRAY_ICON_WINDOWS_OFFLINE"); + logoIconAway = Resources.getImage( + "service.systray.TRAY_ICON_WINDOWS_AWAY"); + logoIconFFC = Resources.getImage( + "service.systray.TRAY_ICON_WINDOWS_FFC"); + envelopeIcon = Resources.getImage( + "service.systray.MESSAGE_ICON_WINDOWS"); + } // If we're running under MacOSX, we use a special black and // white icons without background. else if (osName.startsWith("Mac OS X")) { - logoIcon - = Resources.getImage("service.systray.TRAY_ICON_MACOSX"); - logoIconWhite - = Resources.getImage("service.systray.TRAY_ICON_MACOSX_WHITE"); - envelopeIcon - = Resources.getImage("service.systray.MESSAGE_ICON_MACOSX"); - envelopeIconWhite - = Resources.getImage("service.systray.MESSAGE_ICON_MACOSX_WHITE"); - } - else + logoIcon = Resources.getImage("service.systray.TRAY_ICON_MACOSX"); + logoIconWhite = Resources.getImage( + "service.systray.TRAY_ICON_MACOSX_WHITE"); + envelopeIcon = Resources.getImage( + "service.systray.MESSAGE_ICON_MACOSX"); + envelopeIconWhite = Resources.getImage( + "service.systray.MESSAGE_ICON_MACOSX_WHITE"); + } else { logoIcon = Resources.getImage("service.systray.TRAY_ICON"); - logoIconOffline = Resources.getImage("service.systray.TRAY_ICON_OFFLINE"); + logoIconOffline = Resources.getImage( + "service.systray.TRAY_ICON_OFFLINE"); logoIconAway = Resources.getImage("service.systray.TRAY_ICON_AWAY"); logoIconFFC = Resources.getImage("service.systray.TRAY_ICON_FFC"); envelopeIcon = Resources.getImage("service.systray.MESSAGE_ICON"); @@ -186,9 +197,10 @@ public class SystrayServiceJdicImpl // default to set offline , if any protocols become // online will set it to online currentIcon = logoIconOffline; - } - else + } else + { currentIcon = logoIcon; + } trayIcon = new TrayIcon( currentIcon, @@ -200,29 +212,27 @@ public class SystrayServiceJdicImpl if (osName.startsWith("Mac OS X")) { // init dock Icons - dockIconOffline - = Resources.getImageURL("service.systray.DOCK_ICON_OFFLINE"); - dockIconAway - = Resources.getImageURL("service.systray.DOCK_ICON_AWAY"); - dockIconFFC - = Resources.getImageURL("service.systray.DOCK_ICON_FFC"); + dockIconOffline = Resources.getImageURL( + "service.systray.DOCK_ICON_OFFLINE"); + dockIconAway = Resources.getImageURL( + "service.systray.DOCK_ICON_AWAY"); + dockIconFFC = Resources.getImageURL("service.systray.DOCK_ICON_FFC"); } //Show/hide the contact list when user clicks on the systray. trayIcon.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { long currentTime = System.currentTimeMillis(); UIService uiService = SystrayActivator.getUIService(); + boolean isVisible = !uiService.isVisible(); - boolean isVisible; - - isVisible = ! uiService.isVisible(); - if (isVisible) { + if (isVisible) + { setVisibleTime = currentTime; - } - else if (currentTime < (setVisibleTime + doubleClickSpeed)) + } else if (currentTime < (setVisibleTime + doubleClickSpeed)) { // Do nothing. the last restore is less than 2 seconds, so it is very // likely, that the user made a double click. prevent the main window @@ -232,12 +242,9 @@ public class SystrayServiceJdicImpl uiService.setVisible(isVisible); - ConfigurationService configService - = SystrayActivator.getConfigurationService(); - configService.setProperty( - "net.java.sip.communicator.impl.systray.showApplication", - Boolean.toString(isVisible)); + "net.java.sip.communicator.impl.systray.showApplication", + Boolean.toString(isVisible)); } }); @@ -247,14 +254,14 @@ public class SystrayServiceJdicImpl { TrayMenuFactory.addPopupMenuListener(menu, new PopupMenuListener() { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { if (currentIcon == envelopeIcon) { trayIcon.setIcon(envelopeIconWhite); currentIcon = envelopeIconWhite; - } - else + } else { trayIcon.setIcon(logoIconWhite); currentIcon = logoIconWhite; @@ -267,10 +274,9 @@ public class SystrayServiceJdicImpl { trayIcon.setIcon(envelopeIcon); currentIcon = envelopeIcon; - } - else + } else { - trayIcon.setIcon(logoIcon); + getTrayIcon().setIcon(logoIcon); currentIcon = logoIcon; } } @@ -282,25 +288,67 @@ public class SystrayServiceJdicImpl }); } - //Notify all interested listener that user has clicked on the systray - //popup message. - trayIcon.addBalloonActionListener(new ActionListener() - { - public void actionPerformed(ActionEvent e) - { - UIService uiService = SystrayActivator.getUIService(); + PopupMessageHandler pph = new PopupMessageHandlerTrayIconImpl(trayIcon); + popupHandlerSet.put(pph.getClass().getName(), pph); + SystrayActivator.bundleContext.registerService( + PopupMessageHandler.class.getName(), + pph, null); - firePopupMessageEvent(e.getSource()); - - ExportedWindow chatWindow - = uiService.getExportedWindow(ExportedWindow.CHAT_WINDOW); + try + { + SystrayActivator.bundleContext.addServiceListener( + new ServiceListenerImpl(), + "(objectclass=" + PopupMessageHandler.class.getName() + ")"); + } catch (Exception e) + { + logger.warn(e); + } - if(chatWindow != null && chatWindow.isVisible()) + // now we look if some handler has been registered before we start + // to listen + ServiceReference[] handlerRefs = null; + try + { + handlerRefs = SystrayActivator.bundleContext.getServiceReferences( + PopupMessageHandler.class.getName(), + null); + } catch (InvalidSyntaxException ex) + { + logger.error("Error while retrieving service refs", ex); + } + if (handlerRefs != null) + { + String configuredHandler = (String) configService.getProperty( + "systray.POPUP_HANDLER"); + for (int i = 0; i < handlerRefs.length; i++) + { + PopupMessageHandler handler = + (PopupMessageHandler) SystrayActivator.bundleContext. + getService(handlerRefs[i]); + String handlerName = handler.getClass().getName(); + if (!popupHandlerSet.containsKey(handlerName)) { - chatWindow.bringToFront(); + popupHandlerSet.put(handlerName, handler); + logger.info("added the following popup handler : " + + handler); + if (configuredHandler.equals(handler.getClass().getName())) + { + setActivePopupMessageHandler(handler); + } } + } - }); + } + + // either we have an incorrect config value or the default popup handler + // is not yet available. we use the available popup handler and will + // auto switch to the configured one when it will be available. + // we will be aware of it since we listen for new registerred + // service in the bundle context. + if (activePopupHandler == null) + { + setActivePopupMessageHandler(pph); + } systray.addTrayIcon(trayIcon); @@ -317,86 +365,65 @@ public class SystrayServiceJdicImpl * @param statusName the status name to save */ public void saveStatusInformation( - ProtocolProviderService protocolProvider, - String statusName) + ProtocolProviderService protocolProvider, + String statusName) { - ConfigurationService configService - = SystrayActivator.getConfigurationService(); - - if(configService != null) + if (configService != null) { String prefix = "net.java.sip.communicator.impl.gui.accounts"; - List<String> accounts = configService - .getPropertyNamesByPrefix(prefix, true); + List<String> accounts = configService.getPropertyNamesByPrefix( + prefix, true); boolean savedAccount = false; - for (String accountRootPropName : accounts) { - String accountUID - = configService.getString(accountRootPropName); + for (String accountRootPropName : accounts) + { + String accountUID = configService.getString(accountRootPropName); - if(accountUID.equals(protocolProvider - .getAccountID().getAccountUniqueID())) { + if (accountUID.equals(protocolProvider.getAccountID(). + getAccountUniqueID())) + { configService.setProperty( - accountRootPropName + ".lastAccountStatus", - statusName); + accountRootPropName + ".lastAccountStatus", + statusName); savedAccount = true; } } - if(!savedAccount) { - String accNodeName - = "acc" + Long.toString(System.currentTimeMillis()); + if (!savedAccount) + { + String accNodeName = "acc" + Long.toString(System. + currentTimeMillis()); - String accountPackage - = "net.java.sip.communicator.impl.gui.accounts." - + accNodeName; + String accountPackage = + "net.java.sip.communicator.impl.gui.accounts." + accNodeName; configService.setProperty(accountPackage, - protocolProvider.getAccountID().getAccountUniqueID()); + protocolProvider.getAccountID().getAccountUniqueID()); configService.setProperty( - accountPackage+".lastAccountStatus", - statusName); + accountPackage + ".lastAccountStatus", + statusName); } } } /** - * Implements the <tt>SystratService.showPopupMessage</tt> method. Shows - * a pop up message, above the Systray icon, which has the given title, - * message content and message type. + * Implements <tt>SystraService#showPopupMessage()</tt> * - * @param title the title of the message - * @param messageContent the content text - * @param messageType the type of the message + * @param popupMessage the message we will show */ - public void showPopupMessage( String title, - String messageContent, - int messageType) + public void showPopupMessage(PopupMessage popupMessage) { - if(!checkInitialized()) - return; - - int trayMsgType = TrayIcon.NONE_MESSAGE_TYPE; - - if (messageType == SystrayService.ERROR_MESSAGE_TYPE) - trayMsgType = TrayIcon.ERROR_MESSAGE_TYPE; - else if (messageType == SystrayService.INFORMATION_MESSAGE_TYPE) - trayMsgType = TrayIcon.INFO_MESSAGE_TYPE; - else if (messageType == SystrayService.WARNING_MESSAGE_TYPE) - trayMsgType = TrayIcon.WARNING_MESSAGE_TYPE; - - // remove eventual html code before showing the popup message - messageContent = messageContent.replaceAll("</?\\w++[^>]*+>", ""); - - if(messageContent.length() > 40) - messageContent = messageContent.substring(0, 40).concat("..."); - - messageQueue.add(new SystrayMessage(title, messageContent, trayMsgType)); + // since popup handler could be loaded and unloader on the fly, + // we have to check if we currently have a valid one. + if (activePopupHandler != null) + { + activePopupHandler.showPopupMessage(popupMessage); + } } /** @@ -406,9 +433,9 @@ public class SystrayServiceJdicImpl */ public void addPopupMessageListener(SystrayPopupMessageListener listener) { - synchronized (popupMessageListeners) + if (activePopupHandler != null) { - this.popupMessageListeners.add(listener); + activePopupHandler.addPopupMessageListener(listener); } } @@ -419,36 +446,9 @@ public class SystrayServiceJdicImpl */ public void removePopupMessageListener(SystrayPopupMessageListener listener) { - synchronized (popupMessageListeners) - { - this.popupMessageListeners.remove(listener); - } - } - - /** - * Notifies all interested listeners that a <tt>SystrayPopupMessageEvent</tt> - * has occured. - * - * @param sourceObject the source of this event - */ - private void firePopupMessageEvent(Object sourceObject) - { - SystrayPopupMessageEvent evt - = new SystrayPopupMessageEvent(sourceObject); - - logger.trace("Will dispatch the following systray msg event: " + evt); - - List<SystrayPopupMessageListener> listeners; - synchronized (popupMessageListeners) - { - listeners = - new ArrayList<SystrayPopupMessageListener>( - popupMessageListeners); - } - - for (SystrayPopupMessageListener listener : listeners) + if (activePopupHandler != null) { - listener.popupMessageClicked(evt); + activePopupHandler.removePopupMessageListener(listener); } } @@ -459,8 +459,10 @@ public class SystrayServiceJdicImpl */ public void setSystrayIcon(int imageType) { - if(!checkInitialized()) + if (!checkInitialized()) + { return; + } String osName = System.getProperty("os.name"); @@ -468,51 +470,43 @@ public class SystrayServiceJdicImpl if (imageType == SystrayService.SC_IMG_TYPE) { - if (osName.startsWith("Mac OS X") - && TrayMenuFactory.isVisible(menu)) + if (osName.startsWith("Mac OS X") && TrayMenuFactory.isVisible(menu)) { toChangeSystrayIcon = logoIconWhite; - } - else + } else { toChangeSystrayIcon = logoIcon; } - } - else if (imageType == SystrayService.SC_IMG_OFFLINE_TYPE) + } else if (imageType == SystrayService.SC_IMG_OFFLINE_TYPE) { if (!osName.startsWith("Mac OS X")) { toChangeSystrayIcon = logoIconOffline; } - } - else if (imageType == SystrayService.SC_IMG_AWAY_TYPE) + } else if (imageType == SystrayService.SC_IMG_AWAY_TYPE) { if (!osName.startsWith("Mac OS X")) { toChangeSystrayIcon = logoIconAway; } - } - else if (imageType == SystrayService.SC_IMG_FFC_TYPE) + } else if (imageType == SystrayService.SC_IMG_FFC_TYPE) { if (!osName.startsWith("Mac OS X")) { toChangeSystrayIcon = logoIconFFC; } - } - else if (imageType == SystrayService.ENVELOPE_IMG_TYPE) + } else if (imageType == SystrayService.ENVELOPE_IMG_TYPE) { - if (osName.startsWith("Mac OS X") - && TrayMenuFactory.isVisible(menu)) + if (osName.startsWith("Mac OS X") && TrayMenuFactory.isVisible(menu)) { toChangeSystrayIcon = envelopeIconWhite; - } - else + } else { toChangeSystrayIcon = envelopeIcon; } } - if(toChangeSystrayIcon != null) + if (toChangeSystrayIcon != null) { this.trayIcon.setIcon(toChangeSystrayIcon); this.currentIcon = toChangeSystrayIcon; @@ -521,29 +515,32 @@ public class SystrayServiceJdicImpl if (osName.startsWith("Mac OS X")) { URL toChangeDockIcon = null; - switch(imageType) + switch (imageType) { case SystrayService.SC_IMG_TYPE: // online will restore the original image break; - case SystrayService.SC_IMG_OFFLINE_TYPE : - toChangeDockIcon = dockIconOffline; break; - case SystrayService.SC_IMG_AWAY_TYPE : - toChangeDockIcon = dockIconAway; break; - case SystrayService.SC_IMG_FFC_TYPE : - toChangeDockIcon = dockIconFFC; break; + case SystrayService.SC_IMG_OFFLINE_TYPE: + toChangeDockIcon = dockIconOffline; + break; + case SystrayService.SC_IMG_AWAY_TYPE: + toChangeDockIcon = dockIconAway; + break; + case SystrayService.SC_IMG_FFC_TYPE: + toChangeDockIcon = dockIconFFC; + break; } try { - if(toChangeDockIcon != null) + if (toChangeDockIcon != null) { Dock.setDockTileImage(toChangeDockIcon); - } - else + } else + { Dock.restoreDockTileImage(); - } - catch (Exception e) + } + } catch (Exception e) { logger.error("failed to change dock icon", e); } @@ -552,171 +549,126 @@ public class SystrayServiceJdicImpl private boolean checkInitialized() { - if(!initialized) + if (!initialized) { logger.error("Systray not init"); return false; - } - else + } else + { return true; + } } /** - * Shows the oldest message in the message queue and then removes it from - * the queue. + * @return the trayIcon */ - private class ShowPopupTask extends TimerTask + public TrayIcon getTrayIcon() { - public void run() - { - if(messageQueue.isEmpty()) - return; - - int messageNumber = messageQueue.size(); - - SystrayMessage msg = messageQueue.get(0); - - if(messageNumber > maxMessageNumber) - { - messageQueue.clear(); - - if(aggregatedMessage != null) - { - aggregatedMessage - .addAggregatedMessageNumber(messageNumber); - } - else - { - String messageContent = msg.getMessageContent(); - - if(!messageContent.endsWith("...")) - messageContent.concat("..."); - - aggregatedMessage = new SystrayMessage( - "Messages start by: " + messageContent, - messageNumber); - } - - messageQueue.add(aggregatedMessage); - } - else - { - trayIcon.displayMessage(msg.getTitle(), - msg.getMessageContent(), - msg.getMessageType()); - - messageQueue.remove(0); - - if(msg.equals(aggregatedMessage)) - aggregatedMessage = null; - } - } + return trayIcon; } /** - * Represents a systray message. + * Set the handler which will be used for popup message + * @param newHandler the handler to set. providing a null handler is like + * disabling popup. + * @return the previously used popup handler */ - private class SystrayMessage + public PopupMessageHandler setActivePopupMessageHandler( + PopupMessageHandler newHandler) { - private String title; - private String messageContent; - private int messageType; - private int aggregatedMessageNumber; - - /** - * Creates an instance of <tt>SystrayMessage</tt> by specifying the - * message <tt>title</tt>, the content of the message and the type of - * the message. - * - * @param title the title of the message - * @param messageContent the content of the message - * @param messageType the type of the message - */ - public SystrayMessage( String title, - String messageContent, - int messageType) - { - this.title = title; - this.messageContent = messageContent; - this.messageType = messageType; - } - - /** - * Creates an instance of <tt>SystrayMessage</tt> by specifying the - * message <tt>title</tt>, the content of the message, the type of - * the message and the number of messages that this message has - * aggregated. - * - * @param messageContent the content of the message - * @param aggregatedMessageNumber the number of messages that this - * message has aggregated - */ - public SystrayMessage( String messageContent, - int aggregatedMessageNumber) - { - this.aggregatedMessageNumber = aggregatedMessageNumber; - - this.title = "You have received " - + aggregatedMessageNumber - + " new messages."; - - this.messageContent = messageContent; - this.messageType = TrayIcon.INFO_MESSAGE_TYPE; - } - - /** - * Returns the title of the message. - * - * @return the title of the message - */ - public String getTitle() + PopupMessageHandler oldHandler = activePopupHandler; + if (oldHandler != null) { - return title; + oldHandler.removePopupMessageListener(popupMessageListener); } - /** - * Returns the message content. - * - * @return the message content - */ - public String getMessageContent() + if (newHandler != null) { - return messageContent; + newHandler.addPopupMessageListener(popupMessageListener); } + activePopupHandler = newHandler; - /** - * Returns the message type. - * - * @return the message type - */ - public int getMessageType() - { - return messageType; - } + return oldHandler; + } + + /** + * Get the handler currently used by this implementation to popup message + * @return the current handler + */ + public PopupMessageHandler getActivePopupMessageHandler() + { + return activePopupHandler; + } - /** - * Returns the number of aggregated messages this message represents. - * - * @return the number of aggregated messages this message represents. - */ - public int getAggregatedMessageNumber() + /** our listener for popup message click */ + private static class SystrayPopupMessageListenerImpl + implements SystrayPopupMessageListener + { + + /** implements <tt>SystrayPopupMessageListener.popupMessageClicked()</tt> */ + public void popupMessageClicked(SystrayPopupMessageEvent evt) { - return aggregatedMessageNumber; + UIService uiService = SystrayActivator.getUIService(); + ExportedWindow chatWindow = uiService.getExportedWindow( + ExportedWindow.CHAT_WINDOW); + if (chatWindow != null && chatWindow.isVisible()) + { + chatWindow.bringToFront(); + } } + } - /** - * Adds the given number of messages to the number of aggregated - * messages contained in this message. - * - * @param messageNumber the number of messages to add to the number of - * aggregated messages contained in this message - */ - public void addAggregatedMessageNumber(int messageNumber) + /** an implementation of <tt>ServiceListener</tt> we will use */ + private class ServiceListenerImpl implements ServiceListener + { + + /** implements <tt>ServiceListener.serviceChanged</tt> */ + public void serviceChanged(ServiceEvent serviceEvent) { - this.aggregatedMessageNumber += messageNumber; + try + { + PopupMessageHandler handler = + (PopupMessageHandler) SystrayActivator.bundleContext. + getService(serviceEvent.getServiceReference()); - this.title = "You have received " + aggregatedMessageNumber - + " new messages."; + if (serviceEvent.getType() == ServiceEvent.REGISTERED) + { + if (!popupHandlerSet.containsKey( + handler.getClass().getName())) + { + logger.info( + "adding the following popup handler : " + handler); + popupHandlerSet.put( + handler.getClass().getName(), handler); + } else + logger.warn("the following popup handler has not " + + "been added since it is already known : " + handler); + + String configuredHandler = (String) configService. + getProperty("systray.POPUP_HANDLER"); + + if (configuredHandler.equals(handler.getClass().getName())) + setActivePopupMessageHandler(handler); + } else if (serviceEvent.getType() == ServiceEvent.UNREGISTERING) + { + popupHandlerSet.remove(handler.getClass().getName()); + if (activePopupHandler == handler) + { + activePopupHandler.removePopupMessageListener( + popupMessageListener); + activePopupHandler = null; + //we just lost our default handler, we replace it + //with the first one we find + if (!popupHandlerSet.isEmpty()) + setActivePopupMessageHandler( + popupHandlerSet.get( + popupHandlerSet.keys().nextElement())); + } + } + } catch (IllegalStateException e) + { + logger.debug(e); + } } } } diff --git a/src/net/java/sip/communicator/impl/systray/jdic/TrayIcon.java b/src/net/java/sip/communicator/impl/systray/jdic/TrayIcon.java index 35e0b42..cb1c9c3 100644 --- a/src/net/java/sip/communicator/impl/systray/jdic/TrayIcon.java +++ b/src/net/java/sip/communicator/impl/systray/jdic/TrayIcon.java @@ -11,6 +11,7 @@ import java.awt.event.*; import java.lang.reflect.*;
import javax.swing.*;
+import net.java.sip.communicator.impl.systray.jdic.SystemTray.*;
/**
* @author Lubomir Marinov
@@ -37,25 +38,31 @@ public class TrayIcon HeadlessException,
SecurityException
{
- peer =
- SystemTray.getDefaultSystemTray().getPeer().createTrayIcon(icon,
- tooltip, popup);
+ SystemTrayPeer systemTrayPeer =
+ SystemTray.getDefaultSystemTray().getPeer();
+ if (systemTrayPeer != null)
+ peer = systemTrayPeer.createTrayIcon(icon, tooltip, popup);
+ else
+ peer = null;
}
public void addActionListener(ActionListener listener)
{
- getPeer().addActionListener(listener);
+ if (peer != null)
+ peer.addActionListener(listener);
}
public void addBalloonActionListener(ActionListener listener)
{
- getPeer().addBalloonActionListener(listener);
+ if (peer != null)
+ peer.addBalloonActionListener(listener);
}
public void displayMessage(String caption, String text, int messageType)
throws NullPointerException
{
- getPeer().displayMessage(caption, text, messageType);
+ if (peer != null)
+ peer.displayMessage(caption, text, messageType);
}
TrayIconPeer getPeer()
@@ -65,12 +72,14 @@ public class TrayIcon public void setIcon(ImageIcon icon) throws NullPointerException
{
- getPeer().setIcon(icon);
+ if (peer != null)
+ peer.setIcon(icon);
}
public void setIconAutoSize(boolean autoSize)
{
- getPeer().setIconAutoSize(autoSize);
+ if (peer != null)
+ peer.setIconAutoSize(autoSize);
}
static interface TrayIconPeer
diff --git a/src/net/java/sip/communicator/plugin/generalconfig/ConfigurationManager.java b/src/net/java/sip/communicator/plugin/generalconfig/ConfigurationManager.java index 8b5e7f0..6069031 100644 --- a/src/net/java/sip/communicator/plugin/generalconfig/ConfigurationManager.java +++ b/src/net/java/sip/communicator/plugin/generalconfig/ConfigurationManager.java @@ -34,7 +34,7 @@ public class ConfigurationManager private static int windowTransparency; private static boolean isTransparentWindowEnabled; - + private static ConfigurationService configService = GeneralConfigPluginActivator.getConfigurationService(); @@ -284,6 +284,26 @@ public class ConfigurationManager } /** + * Gets the configuration handler which is currently in use. + * + * @return the configuration handler which is currently in use + */ + public static String getPopupHandlerConfig() + { + return (String) configService.getProperty("systray.POPUP_HANDLER"); + } + + /** + * Saves the popup handler choice made by the user. + * + * @param handler the handler which will be used + */ + public static void setPopupHandlerConfig(String handler) + { + configService.setProperty("systray.POPUP_HANDLER", handler); + } + + /** * Returns <code>true</code> if transparent windows are enabled, * <code>false</code> otherwise. * diff --git a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigPluginActivator.java b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigPluginActivator.java index 94f870a..d2fe808 100644 --- a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigPluginActivator.java +++ b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigPluginActivator.java @@ -8,6 +8,7 @@ package net.java.sip.communicator.plugin.generalconfig; import net.java.sip.communicator.service.configuration.*; import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.systray.*; import net.java.sip.communicator.util.*; import org.osgi.framework.*; @@ -18,6 +19,8 @@ public class GeneralConfigPluginActivator implements BundleActivator private static ConfigurationService configService; + private static SystrayService systrayService; + protected static BundleContext bundleContext; private static UIService uiService; @@ -66,7 +69,26 @@ public class GeneralConfigPluginActivator implements BundleActivator return configService; } - + + /** + * Returns the <tt>SystrayService</tt> obtained from the bundle + * context. + * @return the <tt>SystrayService</tt> obtained from the bundle + * context + */ + public static SystrayService getSystrayService() + { + if(systrayService == null) { + ServiceReference configReference = bundleContext + .getServiceReference(SystrayService.class.getName()); + + systrayService = (SystrayService) bundleContext + .getService(configReference); + } + + return systrayService; + } + /** * Returns the <tt>UIService</tt>. * diff --git a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java index 31c4e10..81dc7a5 100644 --- a/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java +++ b/src/net/java/sip/communicator/plugin/generalconfig/GeneralConfigurationPanel.java @@ -14,10 +14,12 @@ import javax.swing.*; import javax.swing.event.*; import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.service.systray.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.swing.*; import com.izforge.izpack.util.os.*; +import org.osgi.framework.*; /** * @author Yana Stamcheva @@ -41,6 +43,9 @@ public class GeneralConfigurationPanel private JCheckBox enableTypingNotifiCheckBox; private JCheckBox showHistoryCheckBox; private JPanel logHistoryPanel; + private JPanel notifConfigPanel; + private JLabel notifConfigLabel; + private JComboBox notifConfigComboBox; public GeneralConfigurationPanel() { @@ -218,6 +223,76 @@ public class GeneralConfigurationPanel Resources.getString("plugin.generalconfig.BRING_WINDOW_TO_FRONT")); bringToFrontCheckBox.addActionListener(this); } + { + ServiceReference[] handlerRefs = null; + BundleContext bc = GeneralConfigPluginActivator.bundleContext; + try + { + handlerRefs = bc.getServiceReferences( + PopupMessageHandler.class.getName(), + null); + } + catch (InvalidSyntaxException ex) + { + logger.warn("Error while retrieving service refs", ex); + } + // user has choice only if there is more than one handler + if ((handlerRefs != null) && (handlerRefs.length > 1)) + { + notifConfigPanel = new JPanel(); + notifConfigPanel.setOpaque(false); + notifConfigPanel.setLayout(new BorderLayout(10, 10)); + notifConfigPanel.setAlignmentX(0.0f); + notifConfigPanel.setPreferredSize( + new java.awt.Dimension(380, 22)); + + mainPanel.add(notifConfigPanel); + mainPanel.add(Box.createVerticalStrut(10)); + { + notifConfigLabel = new JLabel( + Resources.getString( + "plugin.notificationconfig.POPUP_NOTIF_HANDLER")); + notifConfigPanel.add( + notifConfigLabel, BorderLayout.WEST); + } + { + notifConfigComboBox = new JComboBox(); + + String currentConfig = + ConfigurationManager.getPopupHandlerConfig(); + for (ServiceReference ref : handlerRefs) + { + PopupMessageHandler handler = + (PopupMessageHandler) bc.getService(ref); + + notifConfigComboBox.addItem(handler); + + String handlerName = handler.getClass().getName(); + + if (handlerName.equals(currentConfig)) + notifConfigComboBox.setSelectedItem(handler); + } + + notifConfigComboBox.addItemListener(new ItemListener() + { + public void itemStateChanged(ItemEvent evt) + { + PopupMessageHandler handler = + (PopupMessageHandler) + notifConfigComboBox.getSelectedItem(); + + ConfigurationManager.setPopupHandlerConfig( + handler.getClass().getName()); + + GeneralConfigPluginActivator.getSystrayService() + .setActivePopupMessageHandler(handler); + } + }); + notifConfigPanel.add( + notifConfigComboBox, BorderLayout.CENTER); + } + } + } // { // JPanel transparencyPanel = new JPanel(); // BorderLayout transparencyPanelLayout diff --git a/src/net/java/sip/communicator/plugin/generalconfig/generalconfig.manifest.mf b/src/net/java/sip/communicator/plugin/generalconfig/generalconfig.manifest.mf index 3bdd7f8..e12d62e 100644 --- a/src/net/java/sip/communicator/plugin/generalconfig/generalconfig.manifest.mf +++ b/src/net/java/sip/communicator/plugin/generalconfig/generalconfig.manifest.mf @@ -11,6 +11,7 @@ Import-Package: org.osgi.framework, net.java.sip.communicator.service.gui, net.java.sip.communicator.service.gui.event, net.java.sip.communicator.service.resources, + net.java.sip.communicator.service.systray, net.java.sip.communicator.util, net.java.sip.communicator.util.swing, javax.swing, diff --git a/src/net/java/sip/communicator/service/notification/PopupMessageNotificationHandler.java b/src/net/java/sip/communicator/service/notification/PopupMessageNotificationHandler.java index 2aa519d..281bb68 100644 --- a/src/net/java/sip/communicator/service/notification/PopupMessageNotificationHandler.java +++ b/src/net/java/sip/communicator/service/notification/PopupMessageNotificationHandler.java @@ -6,6 +6,8 @@ */ package net.java.sip.communicator.service.notification; +import net.java.sip.communicator.service.systray.*; + /** * The <tt>PopupMessageNotificationHandler</tt> interface is meant to be * implemented by the notification bundle in order to provide handling of @@ -26,11 +28,9 @@ public interface PopupMessageNotificationHandler public String getDefaultMessage(); /** - * Pops up a message with the given <tt>message</tt> content and the given - * <tt>title</tt>. + * Shows the given <tt>PopupMessage</tt> * - * @param title the title of the popup * @param message the message to show in the popup */ - public void popupMessage(String title, String message); + public void popupMessage(PopupMessage message); } diff --git a/src/net/java/sip/communicator/service/systray/PopupMessage.java b/src/net/java/sip/communicator/service/systray/PopupMessage.java new file mode 100644 index 0000000..3f82324 --- /dev/null +++ b/src/net/java/sip/communicator/service/systray/PopupMessage.java @@ -0,0 +1,192 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.service.systray; + +import javax.swing.*; +import net.java.sip.communicator.service.protocol.*; + +/** + * The <tt>PopupMessage</tt> class encloses informations to show in a popup. + * While a message title and a message body are mandatory informations, + * a popup message could provides more stuffs like a component or an image which + * may be used by a <tt>PopupMessageHandler</tt> capable to handle it. + * + * @author Symphorien Wanko + */ +public class PopupMessage +{ + + /** message to show in the popup */ + private String message; + + /** title of the message */ + private String messageTitle; + + /** An icon representing the contact from which the notification comes */ + private ImageIcon imageIcon; + + /** A ready to show <tt>JComponet</tt> for this <tt>PopupMessage</tt> */ + private JComponent component; + + /** type of the message */ + private int messageType; + + /** the contact which is the cause of this popup message */ + private Contact contact; + + /** + * Creates a <tt>PopupMessage</tt> with the given title and message inside + * + * @param messageTitle title of the message + * @param message message to show in the systray + */ + public PopupMessage(String messageTitle, String message) + { + this.messageTitle = messageTitle; + this.message = message; + } + + /** + * Creates a system tray message with the given title and message content. The + * message type will affect the icon used to present the message. + * + * @param title the title, which will be shown + * @param content the content of the message to display + * @param messageType the message type; one of XXX_MESSAGE_TYPE constants + * declared in <tt>SystrayService + */ + public PopupMessage(String title, String content, int messageType) + { + this(title, content); + this.messageType = messageType; + } + + /** + * Creates a new <tt>PopupMessage</tt> with the given title, message and + * icon. + * + * @param messageTitle title of the message + * @param message message to show in the systray + * @param imageIcon an incon to show in the popup message. + */ + public PopupMessage(String title, String message, ImageIcon imageIcon) + { + this(title, message); + this.imageIcon = imageIcon; + } + + /** + * Creates a new <tt>PopupMessage</tt> with the given + * <tt>JComponent</tt> as its content. This constructor also takes a title + * and a message as replacements in cases the component is not usable. + * + * @param component the component to put in the <tt>PopupMessage</tt> + * @param title of the message + * @param message message to use in place of the component + */ + public PopupMessage(JComponent component, String title, String message) + { + this(title, message); + this.component = component; + } + + /** + * @return the message + */ + public String getMessage() + { + return message; + } + + /** + * @param message the message to set + */ + public void setMessage(String message) + { + this.message = message; + } + + /** + * @return the messageTitle + */ + public String getMessageTitle() + { + return messageTitle; + } + + /** + * @param messageTitle the messageTitle to set + */ + public void setMessageTitle(String messageTitle) + { + this.messageTitle = messageTitle; + } + + /** + * @return the component + */ + public JComponent getComponent() + { + return component; + } + + /** + * @param component the component to set + */ + public void setComponent(JComponent component) + { + this.component = component; + } + + /** + * @return the imageIcon + */ + public ImageIcon getIcon() + { + return imageIcon; + } + + /** + * @param imageIcon the imageIcon to set + */ + public void setIcon(ImageIcon imageIcon) + { + this.imageIcon = imageIcon; + } + + /** + * @return the messageType + */ + public int getMessageType() + { + return messageType; + } + + /** + * @param messageType the messageType to set + */ + public void setMessageType(int messageType) + { + this.messageType = messageType; + } + + /** + * @return the contact + */ + public Contact getContact() + { + return contact; + } + + /** + * @param contact the contact to set + */ + public void setContact(Contact contact) + { + this.contact = contact; + } +} diff --git a/src/net/java/sip/communicator/service/systray/PopupMessageHandler.java b/src/net/java/sip/communicator/service/systray/PopupMessageHandler.java new file mode 100644 index 0000000..0198a64 --- /dev/null +++ b/src/net/java/sip/communicator/service/systray/PopupMessageHandler.java @@ -0,0 +1,55 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.service.systray; + +import net.java.sip.communicator.service.systray.event.*; + +/** + * The <tt>PopupMessageHandler</tt> role is to give differents methods to + * display <tt>PopupMessage</tt> and listen for events (user click) + * coming from that popup. + * + * @author Symphorien Wanko + */ +public interface PopupMessageHandler +{ + + /** + * Register a listener to be informed of systray popup events. + * + * @param listener the listened which will be informed of systray popup + * events + */ + public void addPopupMessageListener(SystrayPopupMessageListener listener); + + /** + * Removes a listener previously added with <tt>addPopupMessageListener</tt>. + * + * @param listener the listener to remove + */ + public void removePopupMessageListener(SystrayPopupMessageListener listener); + + /** + * Shows the given <tt>PopupMessage</tt>. Any given <tt>PopupMessage</tt> + * will provides a minimum of two values : a message title and + * a message body. thoose two values are respectively available via + * <tt>PopupMessage#getMessageTitle()</tt> and + * <tt>PopupMessage#getMessage()</tt> + * + * @param popupMessage the message to show + */ + public void showPopupMessage(PopupMessage popupMessage); + + /** + * Returns a readable description of this popup handler. It is expected + * to be a localized string. + * + * @returns a string describing this popup handler + */ + @Override + public String toString(); +} diff --git a/src/net/java/sip/communicator/service/systray/SystrayService.java b/src/net/java/sip/communicator/service/systray/SystrayService.java index 951bcaf..7123f2e 100644 --- a/src/net/java/sip/communicator/service/systray/SystrayService.java +++ b/src/net/java/sip/communicator/service/systray/SystrayService.java @@ -62,16 +62,11 @@ public interface SystrayService public static final int ENVELOPE_IMG_TYPE = 1; /** - * Shows a system tray message with the given title and message content. The - * message type will affect the icon used to present the message. + * Shows the given <tt>PopupMessage</tt> * - * @param title the title, which will be shown - * @param messageContent the content of the message to display - * @param messageType the message type; one of XXX_MESSAGE_TYPE constants - * declared in this class + * @param popupMessage the message to show */ - public void showPopupMessage(String title, - String messageContent, int messageType); + public void showPopupMessage(PopupMessage popupMessage); /** * Adds a listener for <tt>SystrayPopupMessageEvent</tt>s posted when user @@ -89,6 +84,20 @@ public interface SystrayService public void removePopupMessageListener(SystrayPopupMessageListener listener); /** + * Set the handler which will be used for popup message + * @param popupHandler the handler to use + * @return the previously used popup handler + */ + public PopupMessageHandler setActivePopupMessageHandler( + PopupMessageHandler popupHandler); + + /** + * Get the handler currently used by the systray service for popup message + * @return the handler used by the systray service + */ + public PopupMessageHandler getActivePopupMessageHandler(); + + /** * Sets a new icon to the systray. * * @param imageType the type of the image to set diff --git a/src/net/java/sip/communicator/util/swing/PopupNotificationPanel.java b/src/net/java/sip/communicator/util/swing/PopupNotificationPanel.java new file mode 100644 index 0000000..7933b51 --- /dev/null +++ b/src/net/java/sip/communicator/util/swing/PopupNotificationPanel.java @@ -0,0 +1,98 @@ +/* + * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ + +package net.java.sip.communicator.util.swing; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +import net.java.sip.communicator.util.*; + +/** + * A custom panel to handle systray popup notification + * + * @author Symphorien Wanko + */ +public class PopupNotificationPanel extends SIPCommFrame.MainContentPane +{ + /** logger for this class */ + private final Logger logger = Logger.getLogger(SIPCommFrame.class); + + /** + * Creates a new <tt>PopupNotificationPanel</tt> with a customized panel title + */ + private PopupNotificationPanel() + { + JLabel notifTitle = new JLabel( + UtilActivator.getResources().getSettingsString( + "service.gui.APPLICATION_NAME"), + UtilActivator.getResources().getImage( + "service.gui.SIP_COMMUNICATOR_LOGO"), + SwingConstants.LEFT); + + final JLabel notifClose = new JLabel( + UtilActivator.getResources() + .getImage("service.gui.lookandfeel.CLOSE_TAB_ICON")); + notifClose.setToolTipText(UtilActivator.getResources() + .getI18NString("service.gui.CLOSE")); + + notifClose.addMouseListener(new MouseAdapter() + { + @Override + public void mouseClicked(MouseEvent e) + { + try + { + // TODO : that is pretty ugly. It will be nice if + // it is possible to reach the top window in a better way + JWindow jw = (JWindow) notifClose + .getParent().getParent().getParent() + .getParent().getParent().getParent(); + jw.dispose(); + } + catch (Exception ex) + { + // should never happens : if the user clicks on the close + // icon, it means that the popup window were visible + logger.warn("error while getting the popup window :" + , ex); + } + } + }); + + BorderLayout borderLayout = new BorderLayout(); + borderLayout.setVgap(5); + + JPanel notificationWindowTitle = new JPanel(borderLayout); + notificationWindowTitle + .setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + notificationWindowTitle.setOpaque(false); + + notificationWindowTitle.add(notifTitle, BorderLayout.WEST); + notificationWindowTitle.add(notifClose, BorderLayout.EAST); + + JSeparator jSep = new JSeparator(); + + notificationWindowTitle.add(jSep, BorderLayout.SOUTH); + add(notificationWindowTitle, BorderLayout.NORTH); + setBorder(BorderFactory.createLineBorder(Color.GRAY)); + } + + /** + * Creates a new notifcation panel with <tt>notificationContent</tt> as + * the component to put in that panel + * + * @param notificationContent content to add in the new created + * <tt>PopupNotificationPanel</tt> + */ + public PopupNotificationPanel(JPanel notificationContent) + { + this(); + add(notificationContent, BorderLayout.CENTER); + } +} diff --git a/src/net/java/sip/communicator/util/swing/SIPCommFrame.java b/src/net/java/sip/communicator/util/swing/SIPCommFrame.java index 716eeb4..db14b42 100644 --- a/src/net/java/sip/communicator/util/swing/SIPCommFrame.java +++ b/src/net/java/sip/communicator/util/swing/SIPCommFrame.java @@ -395,7 +395,7 @@ public abstract class SIPCommFrame } } - static class MainContentPane + public static class MainContentPane extends JPanel { private final boolean isColorBgEnabled; |