aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/impl/systray/jdic
diff options
context:
space:
mode:
authorYana Stamcheva <yana@jitsi.org>2007-04-11 14:12:49 +0000
committerYana Stamcheva <yana@jitsi.org>2007-04-11 14:12:49 +0000
commitd0f74ba480a5498aabc1756a25b8db7b8b287ed3 (patch)
treeed642d8762f0ec5e1c2548fa80d602097055b9cc /src/net/java/sip/communicator/impl/systray/jdic
parent90cd15901f03e6a513a29efb9990bc16264f7e81 (diff)
downloadjitsi-d0f74ba480a5498aabc1756a25b8db7b8b287ed3.zip
jitsi-d0f74ba480a5498aabc1756a25b8db7b8b287ed3.tar.gz
jitsi-d0f74ba480a5498aabc1756a25b8db7b8b287ed3.tar.bz2
Systray Service jdic implementation
Diffstat (limited to 'src/net/java/sip/communicator/impl/systray/jdic')
-rw-r--r--src/net/java/sip/communicator/impl/systray/jdic/ProviderRegistration.java108
-rw-r--r--src/net/java/sip/communicator/impl/systray/jdic/ProviderUnRegistration.java81
-rw-r--r--src/net/java/sip/communicator/impl/systray/jdic/StatusSelector.java202
-rw-r--r--src/net/java/sip/communicator/impl/systray/jdic/StatusSimpleSelector.java130
-rw-r--r--src/net/java/sip/communicator/impl/systray/jdic/StatusSubMenu.java94
-rw-r--r--src/net/java/sip/communicator/impl/systray/jdic/SystrayServiceJdicImpl.java491
-rw-r--r--src/net/java/sip/communicator/impl/systray/jdic/TrayMenu.java161
7 files changed, 1267 insertions, 0 deletions
diff --git a/src/net/java/sip/communicator/impl/systray/jdic/ProviderRegistration.java b/src/net/java/sip/communicator/impl/systray/jdic/ProviderRegistration.java
new file mode 100644
index 0000000..c7250e8
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/systray/jdic/ProviderRegistration.java
@@ -0,0 +1,108 @@
+/*
+ * 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.jdic;
+
+import net.java.sip.communicator.service.gui.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.util.*;
+
+/**
+ * The <tt>ProviderRegistration</tt> is used by the systray plugin
+ * to make the registration to a protocol provider. This operation
+ * is implemented within a thread, so that sip-communicator can
+ * continue its execution during this operation.
+ *
+ * @author Nicolas Chamouard
+ */
+
+public class ProviderRegistration
+ extends Thread
+ implements SecurityAuthority
+{
+ /**
+ * The protocol provider to whom we want to register
+ */
+ private ProtocolProviderService protocolProvider;
+
+ private UIService uiService;
+
+ /**
+ * The logger for this class.
+ */
+ private Logger logger = Logger.getLogger(ProviderRegistration.class.getName());
+
+ /**
+ * Creates an instance of <tt>ProviderRegistration</tt>.
+ * @param protocolProvider the provider we want to register
+ * @param secAuth temporary, will be changed
+ */
+ public ProviderRegistration(UIService uiService,
+ ProtocolProviderService protocolProvider)
+ {
+ this.protocolProvider = protocolProvider;
+ this.uiService = uiService;
+ }
+
+ /**
+ * Start the thread which will register to the provider
+ */
+ public void run()
+ {
+ try {
+ protocolProvider.register(this);
+ }
+ catch (OperationFailedException ex)
+ {
+ int errorCode = ex.getErrorCode();
+ if (errorCode == OperationFailedException.GENERAL_ERROR)
+ {
+ logger.error("Provider could not be registered"
+ + " due to the following general error: ", ex);
+ }
+ else if (errorCode == OperationFailedException.INTERNAL_ERROR)
+ {
+ logger.error("Provider could not be registered"
+ + " due to the following internal error: ", ex);
+ }
+ else if (errorCode == OperationFailedException.NETWORK_FAILURE)
+ {
+ logger.error("Provider could not be registered"
+ + " due to a network failure: " + ex);
+ }
+ else if (errorCode == OperationFailedException
+ .INVALID_ACCOUNT_PROPERTIES)
+ {
+ logger.error("Provider could not be registered"
+ + " due to an invalid account property: ", ex);
+ }
+ else
+ {
+ logger.error("Provider could not be registered.", ex);
+ }
+ }
+ }
+
+ /**
+ * Used to login to the protocol providers
+ * @param realm the realm that the credentials are needed for
+ * @param defaultValues the values to propose the user by default
+ * @return The Credentials associated with the speciefied realm
+ */
+ public UserCredentials obtainCredentials(String realm,
+ UserCredentials userCredentials)
+ {
+ ExportedWindow loginWindow = uiService.getAuthenticationWindow(
+ protocolProvider, realm, userCredentials);
+
+ loginWindow.setVisible(true);
+
+ return userCredentials;
+ }
+
+
+ } \ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/systray/jdic/ProviderUnRegistration.java b/src/net/java/sip/communicator/impl/systray/jdic/ProviderUnRegistration.java
new file mode 100644
index 0000000..373a483
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/systray/jdic/ProviderUnRegistration.java
@@ -0,0 +1,81 @@
+/*
+ * 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.jdic;
+
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.util.*;
+
+/**
+ * The <tt>ProviderUnRegistration</tt> is used by the systray plugin
+ * to make the unregistration to a protocol provider. This operation
+ * is implemented within a thread, so that sip-communicator can
+ * continue its execution smoothly.
+ *
+ * @author Nicolas Chamouard
+ */
+public class ProviderUnRegistration
+ extends Thread
+{
+ /**
+ * The protocol provider to whom we want to unregister
+ */
+ ProtocolProviderService protocolProvider;
+ /**
+ * The logger for this class.
+ */
+ private Logger logger = Logger.getLogger(ProviderUnRegistration.class.getName());
+
+ /**
+ * Creates an instance of <tt>ProviderUnRegistration</tt>.
+ * @param protocolProvider the provider we want to unregister
+ */
+ ProviderUnRegistration(ProtocolProviderService protocolProvider)
+ {
+ this.protocolProvider = protocolProvider;
+ }
+
+ /**
+ * Start the thread which will unregister to the provider
+ */
+ public void run()
+ {
+ try
+ {
+ protocolProvider.unregister();
+ }
+ catch (OperationFailedException ex)
+ {
+ int errorCode = ex.getErrorCode();
+ if (errorCode == OperationFailedException.GENERAL_ERROR)
+ {
+ logger.error("Provider could not be unregistered"
+ + " due to the following general error: ", ex);
+ }
+ else if (errorCode == OperationFailedException.INTERNAL_ERROR)
+ {
+ logger.error("Provider could not be unregistered"
+ + " due to the following internal error: ", ex);
+ }
+ else if (errorCode == OperationFailedException.NETWORK_FAILURE)
+ {
+ logger.error("Provider could not be unregistered"
+ + " due to a network failure: " + ex);
+ }
+ else if (errorCode == OperationFailedException
+ .INVALID_ACCOUNT_PROPERTIES)
+ {
+ logger.error("Provider could not be unregistered"
+ + " due to an invalid account property: ", ex);
+ }
+ else
+ {
+ logger.error("Provider could not be unregistered.", ex);
+ }
+ }
+ }
+ } \ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/systray/jdic/StatusSelector.java b/src/net/java/sip/communicator/impl/systray/jdic/StatusSelector.java
new file mode 100644
index 0000000..f3f1f09
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/systray/jdic/StatusSelector.java
@@ -0,0 +1,202 @@
+/*
+ * 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.jdic;
+
+
+import java.awt.event.*;
+import java.util.*;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.util.*;
+
+
+/**
+ * The <tt>StatusSelector</tt> is a submenu which allows to select a status for
+ * a protocol provider which supports the OperationSetPresence.
+ *
+ * @author Nicolas Chamouard
+ *
+ */
+public class StatusSelector
+ extends JMenu
+ implements ActionListener
+{
+ /**
+ * A reference of <tt>Systray</tt>
+ */
+ private SystrayServiceJdicImpl parentSystray;
+ /**
+ * The protocol provider
+ */
+ private ProtocolProviderService provider;
+ /**
+ * The presence status
+ */
+ private OperationSetPresence presence;
+
+ /**
+ * The logger for this class.
+ */
+ private Logger logger = Logger.getLogger(
+ StatusSelector.class.getName());
+
+ /**
+ * Creates an instance of StatusSelector
+ *
+ * @param tray a reference of the parent <tt>Systray</tt>
+ * @param pro the protocol provider
+ * @param pre the presence status
+ */
+ public StatusSelector(SystrayServiceJdicImpl tray,
+ ProtocolProviderService pro, OperationSetPresence pre)
+ {
+
+ this.parentSystray = tray;
+ this.provider = pro;
+ this.presence = pre;
+
+ /* the parent item */
+
+ this.setText(provider.getAccountID().getUserID());
+ this.setIcon(new ImageIcon(
+ presence.getPresenceStatus().getStatusIcon()));
+
+ /* the submenu itself */
+
+ Iterator statusIterator = this.presence.getSupportedStatusSet();
+
+ while(statusIterator.hasNext())
+ {
+ PresenceStatus status = (PresenceStatus) statusIterator.next();
+
+ ImageIcon icon = new ImageIcon(status.getStatusIcon());
+ JMenuItem item = new JMenuItem(status.getStatusName(),icon);
+
+ item.addActionListener(this);
+
+ this.add(item);
+ }
+
+ }
+
+ /**
+ * Change the status of the protocol according to
+ * the menu item selected
+ * @param evt the event containing the menu item name
+ */
+ public void actionPerformed(ActionEvent evt)
+ {
+
+ JMenuItem menuItem = (JMenuItem) evt.getSource();
+
+ Iterator statusSet = presence.getSupportedStatusSet();
+
+ while (statusSet.hasNext())
+ {
+ PresenceStatus status = ((PresenceStatus) statusSet.next());
+
+ if (status.getStatusName().equals(menuItem.getText()))
+ {
+
+ if (this.provider.getRegistrationState()
+ == RegistrationState.REGISTERED
+ && !presence.getPresenceStatus().equals(status))
+ {
+ if (status.isOnline())
+ {
+ new PublishPresenceStatusThread(status).start();
+ }
+ else
+ {
+ new ProviderUnRegistration(this.provider).start();
+ }
+ }
+ else if (this.provider.getRegistrationState()
+ != RegistrationState.REGISTERED
+ && this.provider.getRegistrationState()
+ != RegistrationState.REGISTERING
+ && this.provider.getRegistrationState()
+ != RegistrationState.AUTHENTICATING
+ && status.isOnline())
+ {
+ new ProviderRegistration(parentSystray.getUiService(),
+ provider).start();
+ }
+ else
+ {
+ if(!status.isOnline()
+ && !(this.provider.getRegistrationState()
+ == RegistrationState.UNREGISTERING))
+ {
+ new ProviderUnRegistration(this.provider).start();
+ }
+ }
+
+ parentSystray.saveStatusInformation(
+ provider, status.getStatusName());
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * This class allow to use a thread to change the presence status.
+ */
+ private class PublishPresenceStatusThread extends Thread
+ {
+ PresenceStatus status;
+
+ public PublishPresenceStatusThread(PresenceStatus status)
+ {
+ this.status = status;
+ }
+
+ public void run()
+ {
+ try {
+ presence.publishPresenceStatus(status, "");
+ }
+ catch (IllegalArgumentException e1)
+ {
+
+ logger.error("Error - changing status", e1);
+ }
+ catch (IllegalStateException e1)
+ {
+
+ logger.error("Error - changing status", e1);
+ }
+ catch (OperationFailedException e1)
+ {
+
+ if (e1.getErrorCode()
+ == OperationFailedException.GENERAL_ERROR)
+ {
+
+ }
+ else if (e1.getErrorCode()
+ == OperationFailedException
+ .NETWORK_FAILURE)
+ {
+
+ }
+ else if (e1.getErrorCode()
+ == OperationFailedException
+ .PROVIDER_NOT_REGISTERED)
+ {
+
+ }
+ logger.error("Error - changing status", e1);
+ }
+ }
+ }
+
+}
diff --git a/src/net/java/sip/communicator/impl/systray/jdic/StatusSimpleSelector.java b/src/net/java/sip/communicator/impl/systray/jdic/StatusSimpleSelector.java
new file mode 100644
index 0000000..e899034
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/systray/jdic/StatusSimpleSelector.java
@@ -0,0 +1,130 @@
+/*
+ * 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.jdic;
+
+
+import java.awt.event.*;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.impl.systray.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.util.*;
+
+
+/**
+ * The <tt>StatusSimpleSelector</tt> is a submenu which allow
+ * to select a status for a protocol provider which does not
+ * support the OperationSetPresence
+ *
+ * @author Nicolas Chamouard
+ *
+ */
+public class StatusSimpleSelector
+ extends JMenu
+ implements ActionListener
+{
+ /**
+ * A reference of <tt>Systray</tt>
+ */
+ private SystrayServiceJdicImpl parentSystray;
+ /**
+ * The protocol provider
+ */
+ private ProtocolProviderService provider;
+
+ /**
+ * The logger for this class.
+ */
+ private Logger logger = Logger.getLogger(
+ StatusSimpleSelector.class.getName());
+
+ /**
+ * The menu item for the online status
+ */
+ private JMenuItem onlineItem = new JMenuItem(
+ Resources.getString("onlineStatus"),
+ new ImageIcon(Resources.getImage("sipLogo")));
+ /**
+ * The menu item for the offline status
+ */
+ private JMenuItem offlineItem = new JMenuItem(
+ Resources.getString("offlineStatus"),
+ new ImageIcon(Resources.getImage("sipLogoOffline")));
+
+ /**
+ * Creates an instance of <tt>StatusSimpleSelector</tt>
+ *
+ * @param tray a reference of the parent <tt>Systray</tt>
+ * @param pro the protocol provider
+ */
+ public StatusSimpleSelector(SystrayServiceJdicImpl tray,ProtocolProviderService pro)
+ {
+
+ this.provider = pro;
+ this.parentSystray = tray;
+
+ /* the parent item */
+
+ ImageIcon icon;
+
+ if(provider.isRegistered())
+ {
+ icon = new ImageIcon(Resources.getImage("sipLogo"));
+ }
+ else
+ {
+ icon = new ImageIcon(Resources.getImage("sipLogoOffline"));
+ }
+
+ this.setText(provider.getAccountID().getUserID());
+ this.setIcon(icon);
+
+ /* the menu itself */
+
+ this.onlineItem.addActionListener(this);
+ this.offlineItem.addActionListener(this);
+
+ this.onlineItem.setName("online");
+ this.offlineItem.setName("offline");
+
+ this.add(onlineItem);
+ this.add(offlineItem);
+ }
+
+ /**
+ * Change the status of the protocol according to
+ * the menu item selected
+ * @param evt the event containing the menu item name
+ */
+ public void actionPerformed(ActionEvent evt)
+ {
+
+ JMenuItem menuItem = (JMenuItem) evt.getSource();
+ String itemName = menuItem.getName();
+
+ if(itemName.equals("online"))
+ {
+ if(!this.provider.isRegistered())
+ {
+ new ProviderRegistration(
+ parentSystray.getUiService(), provider).start();
+ }
+ }
+ else
+ {
+ if( !this.provider.getRegistrationState()
+ .equals(RegistrationState.UNREGISTERED)
+ && !this.provider.getRegistrationState()
+ .equals(RegistrationState.UNREGISTERING))
+ {
+ new ProviderUnRegistration(this.provider).start();
+ }
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/systray/jdic/StatusSubMenu.java b/src/net/java/sip/communicator/impl/systray/jdic/StatusSubMenu.java
new file mode 100644
index 0000000..4c0b3fe
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/systray/jdic/StatusSubMenu.java
@@ -0,0 +1,94 @@
+/*
+ * 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.jdic;
+
+
+import java.awt.*;
+import java.util.*;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.impl.systray.*;
+import net.java.sip.communicator.service.protocol.*;
+
+/**
+ * The <tt>StatusSubMenu</tt> provides a menu which allow
+ * to select the status for each of the protocol providers
+ * registered when the menu appears
+ *
+ * @author Nicolas Chamouard
+ *
+ */
+
+public class StatusSubMenu
+extends JMenu
+//implements ActionListener
+{
+
+ /**
+ * A reference of <tt>Systray</tt>
+ */
+ private SystrayServiceJdicImpl parentSystray;
+
+ /**
+ * Creates an instance of <tt>StatusSubMenu</tt>.
+ * @param tray a reference of the parent <tt>Systray</tt>
+ */
+ public StatusSubMenu(SystrayServiceJdicImpl tray)
+ {
+
+ parentSystray = tray;
+
+ this.setText(Resources.getString("setStatus"));
+ this.setIcon(
+ new ImageIcon(Resources.getImage("statusMenuIcon")));
+
+ /* makes the menu look better */
+ this.setPreferredSize(new Dimension(28, 24));
+
+ update();
+
+ }
+
+ /**
+ * Updates the Menu by retrieving provider informations
+ */
+ public void update()
+ {
+ this.removeAll();
+
+ Iterator it=parentSystray.getProtocolProviders();
+
+ while(it.hasNext()){
+ ProtocolProviderService provider =
+ (ProtocolProviderService) it.next();
+
+ Map supportedOperationSets
+ = provider.getSupportedOperationSets();
+
+ OperationSetPresence presence = (OperationSetPresence)
+ supportedOperationSets.get(OperationSetPresence.class.getName());
+
+ if (presence == null)
+ {
+ StatusSimpleSelector s =
+ new StatusSimpleSelector(parentSystray,provider);
+
+ this.add(s);
+ }
+ else
+ {
+ StatusSelector s =
+ new StatusSelector(parentSystray,provider,presence);
+
+ this.add(s);
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/net/java/sip/communicator/impl/systray/jdic/SystrayServiceJdicImpl.java b/src/net/java/sip/communicator/impl/systray/jdic/SystrayServiceJdicImpl.java
new file mode 100644
index 0000000..97efb7d
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/systray/jdic/SystrayServiceJdicImpl.java
@@ -0,0 +1,491 @@
+/*
+ * 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.jdic;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.awt.image.*;
+import java.util.*;
+import java.util.List;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.impl.systray.*;
+import net.java.sip.communicator.service.configuration.*;
+import net.java.sip.communicator.service.gui.*;
+import net.java.sip.communicator.service.gui.event.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.event.*;
+import net.java.sip.communicator.service.systray.*;
+import net.java.sip.communicator.service.systray.event.*;
+import net.java.sip.communicator.util.*;
+
+import org.jdesktop.jdic.tray.*;
+import org.osgi.framework.*;
+
+/**
+ * The <tt>Systray</tt> provides a Icon and the associated <tt>TrayMenu</tt>
+ * in the system tray using the Jdic library.
+ *
+ * @author Nicolas Chamouard
+ * @author Yana Stamcheva
+ */
+public class SystrayServiceJdicImpl
+ implements SystrayService,
+ ServiceListener,
+ MessageListener,
+ ChatFocusListener
+{
+ /**
+ * A reference of the <tt>UIservice</tt>.
+ */
+ private UIService uiService;
+
+ /**
+ * The systray.
+ */
+ private SystemTray systray;
+
+ /**
+ * The icon in the system tray.
+ */
+ private TrayIcon trayIcon;
+
+ /**
+ * The menu that spring with a right click.
+ */
+ private TrayMenu menu;
+
+ /**
+ * The list of all providers.
+ */
+ private Map protocolProviderTable = new LinkedHashMap();
+
+ /**
+ * The list of all added popup message listeners.
+ */
+ private Vector popupMessageListeners = new Vector();
+
+ /**
+ * The logger for this class.
+ */
+ private static Logger logger =
+ Logger.getLogger(SystrayServiceJdicImpl.class.getName());
+
+ private ImageIcon logoIcon;
+
+ /**
+ * Creates an instance of <tt>Systray</tt>.
+ * @param service a reference of the current <tt>UIservice</tt>
+ */
+ public SystrayServiceJdicImpl(UIService service)
+ {
+ this.uiService = service;
+
+ try
+ {
+ systray = SystemTray.getDefaultSystemTray();
+ }
+ catch (Throwable e)
+ {
+ logger.error("Failed to create a systray!", e);
+ }
+
+ if(systray != null)
+ {
+ this.initSystray();
+ this.initProvidersTable();
+
+ uiService.setExitOnMainWindowClose(false);
+
+ SystrayActivator.bundleContext.addServiceListener(this);
+ }
+ }
+
+ /**
+ * Initializes the systray icon and related listeners.
+ */
+ private void initSystray()
+ {
+ menu = new TrayMenu(uiService,this);
+
+ String osName = System.getProperty("os.name");
+ // If we're running under Windows, we use a special icon without
+ // background.
+ if (osName.startsWith("Windows"))
+ {
+ logoIcon = new ImageIcon(
+ Resources.getImage("trayIconWindows"));
+ }
+ else
+ {
+ logoIcon = new ImageIcon(
+ Resources.getImage("trayIcon"));
+ }
+
+ trayIcon = new TrayIcon(logoIcon, "SIP Communicator", menu);
+ trayIcon.setIconAutoSize(true);
+
+ //Show/hide the contact list when user clicks on the systray.
+ trayIcon.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ if(uiService.isVisible())
+ {
+ uiService.setVisible(false);
+ }
+ else
+ {
+ uiService.setVisible(true);
+ }
+ }
+ });
+
+ //Notify all interested listener that user has clicked on the systray
+ //popup message.
+ trayIcon.addBalloonActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ firePopupMessageEvent(e.getSource());
+
+ ExportedWindow chatWindow
+ = uiService.getExportedWindow(ExportedWindow.CHAT_WINDOW);
+
+ if(chatWindow != null && chatWindow.isVisible())
+ {
+ chatWindow.bringToFront();
+ }
+ }
+ });
+
+ systray.addTrayIcon(trayIcon);
+ }
+
+ /**
+ * We fill the protocolProviderTable with all
+ * running protocol providers at the start of
+ * the bundle.
+ */
+ private void initProvidersTable()
+ {
+ BundleContext bc = SystrayActivator.bundleContext;
+
+ 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)
+ {
+
+ for (int i = 0; i < protocolProviderRefs.length; i++)
+ {
+ ProtocolProviderService provider = (ProtocolProviderService) bc
+ .getService(protocolProviderRefs[i]);
+
+ this.protocolProviderTable.put(
+ provider.getAccountID(),
+ provider);
+
+ handleProviderAdded(provider);
+ }
+ }
+ }
+
+ /**
+ * Returns a set of all protocol providers.
+ *
+ * @return a set of all protocol providers.
+ */
+ public Iterator getProtocolProviders()
+ {
+ return this.protocolProviderTable.values().iterator();
+ }
+
+ /**
+ * Currently unused
+ * @param evt ignored
+ */
+ public void messageDelivered(MessageDeliveredEvent evt)
+ {
+ }
+
+ /**
+ * Currently unused
+ * @param evt ignored
+ */
+ public void messageDeliveryFailed(MessageDeliveryFailedEvent evt)
+ {
+ }
+
+ /**
+ * Display in a balloon the newly received message
+ * @param evt the event containing the message
+ */
+ public void messageReceived(MessageReceivedEvent evt)
+ {
+ Chat chat = uiService.getChat(evt.getSourceContact());
+
+ if(!chat.isChatFocused())
+ {
+ String title = Resources.getString("messageReceived") + " "
+ + evt.getSourceContact().getDisplayName();
+
+ String message = evt.getSourceMessage().getContent();
+
+ if(message.length() > 100)
+ message = message.substring(0, 100).concat("...");
+
+ GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+ GraphicsDevice gs = ge.getDefaultScreenDevice();
+ GraphicsConfiguration gc = gs.getDefaultConfiguration();
+
+ // Create an image that does not support transparency
+ BufferedImage img = gc.createCompatibleImage(logoIcon.getIconWidth(),
+ logoIcon.getIconHeight(), Transparency.TRANSLUCENT);
+
+ Image msgImg = new ImageIcon(
+ Resources.getImage("messageIcon")).getImage();
+
+ Graphics2D g = (Graphics2D) img.getGraphics();
+
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g.drawImage(logoIcon.getImage(), 0, 0, null);
+ g.drawImage(msgImg,
+ logoIcon.getIconWidth()/2 - msgImg.getWidth(null)/2,
+ logoIcon.getIconHeight()/2 - msgImg.getHeight(null)/2, null);
+
+ this.trayIcon.setIcon(new ImageIcon(img));
+
+ this.trayIcon.displayMessage(
+ title, message, TrayIcon.NONE_MESSAGE_TYPE);
+
+ chat.addChatFocusListener(this);
+ }
+ }
+
+ /**
+ * When a service ist registered or unregistered, we update
+ * the provider tables and add/remove listeners (if it supports
+ * BasicInstantMessenging implementation)
+ *
+ * @param event ServiceEvent
+ */
+ public void serviceChanged(ServiceEvent event)
+ {
+ ProtocolProviderService provider = (ProtocolProviderService)
+ SystrayActivator.bundleContext.getService(event.getServiceReference());
+
+ if (event.getType() == ServiceEvent.REGISTERED){
+ protocolProviderTable.put(provider.getAccountID(),provider);
+ handleProviderAdded(provider);
+
+ }
+ if (event.getType() == ServiceEvent.UNREGISTERING){
+ protocolProviderTable.remove(provider.getAccountID());
+ handleProviderRemoved(provider);
+ }
+
+ }
+
+ /**
+ * Checks if the provider has an implementation
+ * of OperationSetBasicInstantMessaging and
+ * if so add a listerner to it
+ *
+ * @param provider ProtocolProviderService
+ */
+ private void handleProviderAdded(ProtocolProviderService provider)
+ {
+ OperationSetBasicInstantMessaging opSetIm
+ = (OperationSetBasicInstantMessaging) provider
+ .getSupportedOperationSets().get(
+ OperationSetBasicInstantMessaging.class.getName());
+
+ if(opSetIm != null)
+ opSetIm.addMessageListener(this);
+
+ }
+
+ /**
+ * Checks if the provider has an implementation
+ * of OperationSetBasicInstantMessaging and
+ * if so remove its listerner
+ *
+ * @param provider ProtocolProviderService
+ */
+ private void handleProviderRemoved(ProtocolProviderService provider)
+ {
+ OperationSetBasicInstantMessaging opSetIm
+ = (OperationSetBasicInstantMessaging) provider
+ .getSupportedOperationSets().get(
+ OperationSetBasicInstantMessaging.class.getName());
+
+ if(opSetIm != null)
+ opSetIm.removeMessageListener(this);
+
+ }
+
+ /**
+ * Saves the last status for all accounts. This information is used
+ * on loging. Each time user logs in he's logged with the same status
+ * as he was the last time before closing the application.
+ */
+ public void saveStatusInformation(ProtocolProviderService protocolProvider,
+ String statusName)
+ {
+ ServiceReference configReference = SystrayActivator.bundleContext
+ .getServiceReference(ConfigurationService.class.getName());
+
+ ConfigurationService configService
+ = (ConfigurationService) SystrayActivator.bundleContext
+ .getService(configReference);
+
+ if(configService != null)
+ {
+ String prefix = "net.java.sip.communicator.impl.gui.accounts";
+
+ List accounts = configService
+ .getPropertyNamesByPrefix(prefix, true);
+
+ boolean savedAccount = false;
+ Iterator accountsIter = accounts.iterator();
+
+ while(accountsIter.hasNext()) {
+ String accountRootPropName
+ = (String) accountsIter.next();
+
+ String accountUID
+ = configService.getString(accountRootPropName);
+
+ if(accountUID.equals(protocolProvider
+ .getAccountID().getAccountUniqueID())) {
+
+ configService.setProperty(
+ accountRootPropName + ".lastAccountStatus",
+ statusName);
+
+ savedAccount = true;
+ }
+ }
+
+ if(!savedAccount) {
+ String accNodeName
+ = "acc" + Long.toString(System.currentTimeMillis());
+
+ String accountPackage
+ = "net.java.sip.communicator.impl.gui.accounts."
+ + accNodeName;
+
+ configService.setProperty(accountPackage,
+ protocolProvider.getAccountID().getAccountUniqueID());
+
+ configService.setProperty(
+ accountPackage+".lastAccountStatus",
+ statusName);
+ }
+ }
+ }
+
+ public UIService getUiService()
+ {
+ return uiService;
+ }
+
+ /**
+ * Implements the <tt>SystratService.showPopupMessage</tt> method. Shows
+ * a popup message, above the systray icon, which has the given title,
+ * message content and message type.
+ */
+ public void showPopupMessage(String title, String messageContent,
+ int messageType)
+ {
+ 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;
+
+ this.trayIcon.displayMessage(
+ title, messageContent, trayMsgType);
+ }
+
+ /**
+ * Implements the <tt>SystrayService.addPopupMessageListener</tt> method.
+ */
+ public void addPopupMessageListener(SystrayPopupMessageListener listener)
+ {
+ synchronized (popupMessageListeners)
+ {
+ this.popupMessageListeners.add(listener);
+ }
+ }
+
+ /**
+ * Implements the <tt>SystrayService.removePopupMessageListener</tt> method.
+ */
+ public void removePopupMessageListener(SystrayPopupMessageListener listener)
+ {
+ synchronized (popupMessageListeners)
+ {
+ this.popupMessageListeners.remove(listener);
+ }
+ }
+
+ private void firePopupMessageEvent(Object sourceObject)
+ {
+ SystrayPopupMessageEvent evt
+ = new SystrayPopupMessageEvent(sourceObject);
+
+ logger.trace("Will dispatch the following systray msg event: " + evt);
+
+ Iterator listeners = null;
+ synchronized (popupMessageListeners)
+ {
+ listeners = new ArrayList(popupMessageListeners).iterator();
+ }
+
+ while (listeners.hasNext())
+ {
+ SystrayPopupMessageListener listener
+ = (SystrayPopupMessageListener) listeners.next();
+
+ listener.popupMessageClicked(evt);
+ }
+ }
+
+ public void chatFocusGained(ChatFocusEvent event)
+ {
+ Chat chat = event.getChat();
+
+ chat.removeChatFocusListener(this);
+
+ this.trayIcon.setIcon(logoIcon);
+ }
+
+ public void chatFocusLost(ChatFocusEvent event)
+ {
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/systray/jdic/TrayMenu.java b/src/net/java/sip/communicator/impl/systray/jdic/TrayMenu.java
new file mode 100644
index 0000000..6447ad4
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/systray/jdic/TrayMenu.java
@@ -0,0 +1,161 @@
+/*
+ * 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.jdic;
+
+import java.awt.event.*;
+
+import javax.swing.*;
+import javax.swing.event.*;
+
+import net.java.sip.communicator.impl.systray.*;
+import net.java.sip.communicator.service.gui.*;
+import net.java.sip.communicator.util.*;
+
+import org.osgi.framework.*;
+
+/**
+ * The <tt>Traymenu</tt> is the menu that appears when the user right-click
+ * on the systray icon
+ *
+ * @author Nicolas Chamouard
+ */
+public class TrayMenu
+ extends JPopupMenu
+ implements ActionListener,
+ PopupMenuListener
+{
+ /**
+ * The logger for this class.
+ */
+ private Logger logger = Logger.getLogger(TrayMenu.class.getName());
+
+ /**
+ * A reference of the <tt>Uiservice</tt>
+ */
+ private UIService uiService;
+ /**
+ * A reference of <tt>Systray</tt>
+ */
+ private SystrayServiceJdicImpl parentSystray;
+
+ private JMenuItem settingsItem = new JMenuItem(
+ Resources.getString("settings"),
+ new ImageIcon(Resources.getImage("settingsMenuIcon")));
+
+ private JMenuItem closeItem = new JMenuItem(
+ Resources.getString("close"),
+ new ImageIcon(Resources.getImage("closeMenuIcon")));
+
+ private JMenuItem addContactMenuItem = new JMenuItem(
+ Resources.getString("addContact"),
+ new ImageIcon(Resources.getImage("addContactIcon")));
+
+ private StatusSubMenu setStatusMenu;
+
+ /**
+ * The configuration window called by the menu item "settings"
+ */
+ private ConfigurationWindow configDialog;
+
+
+ /**
+ * Creates an instance of <tt>TrayMenu</tt>.
+ * @param service a reference of the current <tt>UIservice</tt>
+ * @param tray a reference of the parent <tt>Systray</tt>
+ */
+ public TrayMenu(UIService service, SystrayServiceJdicImpl tray)
+ {
+ uiService = service;
+ parentSystray = tray;
+
+ setStatusMenu = new StatusSubMenu(tray);
+
+ this.add(settingsItem);
+ this.add(addContactMenuItem);
+ this.addSeparator();
+ this.add(setStatusMenu);
+ this.addSeparator();
+ this.add(closeItem);
+
+ this.settingsItem.setName("settings");
+ this.closeItem.setName("close");
+ this.addContactMenuItem.setName("addContact");
+
+ this.settingsItem.addActionListener(this);
+ this.closeItem.addActionListener(this);
+ this.addContactMenuItem.addActionListener(this);
+
+ this.addPopupMenuListener(this);
+ }
+
+ /**
+ * Handles the <tt>ActionEvent</tt> when one of the menu items is selected.
+ * @param evt the event containing the menu item name
+ */
+ public void actionPerformed(ActionEvent evt)
+ {
+
+ JMenuItem menuItem = (JMenuItem) evt.getSource();
+ String itemName = menuItem.getName();
+
+ if(itemName.equals("settings"))
+ {
+ configDialog = uiService.getConfigurationWindow();
+ configDialog.setVisible(true);
+ }
+ else if(itemName.equals("close"))
+ {
+ try
+ {
+ SystrayActivator.bundleContext.getBundle(0).stop();
+ } catch (BundleException ex)
+ {
+ logger.error("Failed to gently shutdown Felix", ex);
+ System.exit(0);
+ }
+
+ }
+ else if(itemName.equals("addContact"))
+ {
+ ExportedWindow dialog = uiService.getExportedWindow(
+ ExportedWindow.ADD_CONTACT_WINDOW);
+
+ if(dialog != null)
+ dialog.setVisible(true);
+ else
+ uiService.getPopupDialog().showMessagePopupDialog(
+ Resources.getString("failedToLoadAddContactDialog"));
+ }
+ }
+
+ /**
+ * Currently unused
+ * @param evt ignored
+ */
+ public void popupMenuCanceled(PopupMenuEvent evt)
+ {
+ }
+
+ /**
+ * Currently unused
+ * @param evt ignored
+ */
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent evt)
+ {
+ }
+
+ /**
+ * Fill the menu with items when it is displayed
+ * @param evt ignored
+ */
+ public void popupMenuWillBecomeVisible(PopupMenuEvent evt)
+ {
+ setStatusMenu.update();
+ }
+
+} \ No newline at end of file