diff options
author | Yana Stamcheva <yana@jitsi.org> | 2007-04-11 14:12:49 +0000 |
---|---|---|
committer | Yana Stamcheva <yana@jitsi.org> | 2007-04-11 14:12:49 +0000 |
commit | d0f74ba480a5498aabc1756a25b8db7b8b287ed3 (patch) | |
tree | ed642d8762f0ec5e1c2548fa80d602097055b9cc | |
parent | 90cd15901f03e6a513a29efb9990bc16264f7e81 (diff) | |
download | jitsi-d0f74ba480a5498aabc1756a25b8db7b8b287ed3.zip jitsi-d0f74ba480a5498aabc1756a25b8db7b8b287ed3.tar.gz jitsi-d0f74ba480a5498aabc1756a25b8db7b8b287ed3.tar.bz2 |
Systray Service jdic implementation
21 files changed, 1452 insertions, 0 deletions
diff --git a/src/net/java/sip/communicator/impl/systray/Resources.java b/src/net/java/sip/communicator/impl/systray/Resources.java new file mode 100644 index 0000000..a90f1ae --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/Resources.java @@ -0,0 +1,73 @@ +/* + * 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.io.*; +import java.util.*; + +import net.java.sip.communicator.util.*; +/** + * The Messages class manages the access to the internationalization + * properties files. + * + * @author Nicolas Chamouard + */ +public class Resources +{ + + private static Logger log = Logger.getLogger(Resources.class); + + private static final String BUNDLE_NAME + = "net.java.sip.communicator.impl.systray.resources"; + + private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle + .getBundle(BUNDLE_NAME); + + + /** + * Returns an internationalized string corresponding to the given key. + * @param key The key of the string. + * @return An internationalized string corresponding to the given key. + */ + public static String getString(String key) + { + try + { + return RESOURCE_BUNDLE.getString(key); + + } catch (MissingResourceException e) + { + return '!' + key + '!'; + } + } + + /** + * Loads an image from a given image identifier. + * @param key The key of the image. + * @return The image for the given identifier. + */ + public static byte[] getImage(String key) + { + byte[] image = new byte[100000]; + + String path=Resources.getString(key); + + try + { + Resources.class.getClassLoader() + .getResourceAsStream(path).read(image); + + } catch (IOException e) + { + log.error("Failed to load image:" + key, e); + } + + return image; + } + +} diff --git a/src/net/java/sip/communicator/impl/systray/SystrayActivator.java b/src/net/java/sip/communicator/impl/systray/SystrayActivator.java new file mode 100644 index 0000000..a36e9c9 --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/SystrayActivator.java @@ -0,0 +1,63 @@ +/* + * 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 net.java.sip.communicator.impl.systray.jdic.*; +import net.java.sip.communicator.service.gui.*; +import net.java.sip.communicator.util.*; + +import org.osgi.framework.*; + +/** + * Registers the <tt>Systray</tt> in the UI Service. + * + * @author Nicolas Chamouard + */ +public class SystrayActivator + implements BundleActivator +{ + /** + * A currently valid bundle context. + */ + public static BundleContext bundleContext; + + public static UIService uiService; + + private static Logger logger = Logger.getLogger( + SystrayActivator.class.getName()); + + /** + * Called when this bundle is started. + * + * @param bc The execution context of the bundle being started. + * @throws Exception If + */ + public void start(BundleContext bc) throws Exception + { + bundleContext = bc; + + ServiceReference uiServiceRef = bundleContext + .getServiceReference(UIService.class.getName()); + + uiService = (UIService) bundleContext.getService(uiServiceRef); + + SystrayServiceJdicImpl systray = new SystrayServiceJdicImpl(uiService); + } + + /** + * Called when this bundle is stopped so the Framework can perform the + * bundle-specific activities necessary to stop the bundle. + * + * @param bc The execution context of the bundle being stopped. + * @throws Exception If this method throws an exception, the bundle is + * still marked as stopped, and the Framework will remove the bundle's + * listeners, unregister all services registered by the bundle, and + * release all services used by the bundle. + */ + public void stop(BundleContext bc) throws Exception { + } +} 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 diff --git a/src/net/java/sip/communicator/impl/systray/resources.properties b/src/net/java/sip/communicator/impl/systray/resources.properties new file mode 100644 index 0000000..2c6e76a --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/resources.properties @@ -0,0 +1,18 @@ +trayIcon=net/java/sip/communicator/impl/systray/resources/systrayIcon.png +trayIconWindows=net/java/sip/communicator/impl/systray/resources/systrayIconWindows.png +trayIconWindowsAnimated=net/java/sip/communicator/impl/systray/resources/systrayIconWindows.gif +addContactIcon=net/java/sip/communicator/impl/systray/resources/addContactIcon.png +statusMenuIcon=net/java/sip/communicator/impl/systray/resources/statusIcon.png +settingsMenuIcon=net/java/sip/communicator/impl/systray/resources/configureIcon.png +closeMenuIcon=net/java/sip/communicator/impl/systray/resources/quit.png +sipLogo=net/java/sip/communicator/impl/systray/resources/sipLogo.png +sipLogoOffline=net/java/sip/communicator/impl/systray/resources/sipLogoOffline.png +messageIcon=net/java/sip/communicator/impl/systray/resources/envelope.png +settings=Settings... +addContact=Add contact... +setStatus=Set Status +close=Close +onlineStatus=Online +offlineStatus=Offline +messageReceived=Message received from +failedToLoadAddContactDialog=Failed to load the "Add contact" wizard dialog.
\ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/systray/resources/addContactIcon.png b/src/net/java/sip/communicator/impl/systray/resources/addContactIcon.png Binary files differnew file mode 100644 index 0000000..947ecd7 --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/resources/addContactIcon.png diff --git a/src/net/java/sip/communicator/impl/systray/resources/configureIcon.png b/src/net/java/sip/communicator/impl/systray/resources/configureIcon.png Binary files differnew file mode 100644 index 0000000..82fbd1d --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/resources/configureIcon.png diff --git a/src/net/java/sip/communicator/impl/systray/resources/envelope.png b/src/net/java/sip/communicator/impl/systray/resources/envelope.png Binary files differnew file mode 100644 index 0000000..812e145 --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/resources/envelope.png diff --git a/src/net/java/sip/communicator/impl/systray/resources/quit.png b/src/net/java/sip/communicator/impl/systray/resources/quit.png Binary files differnew file mode 100644 index 0000000..f8ca474 --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/resources/quit.png diff --git a/src/net/java/sip/communicator/impl/systray/resources/sipLogo.png b/src/net/java/sip/communicator/impl/systray/resources/sipLogo.png Binary files differnew file mode 100644 index 0000000..df2392b --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/resources/sipLogo.png diff --git a/src/net/java/sip/communicator/impl/systray/resources/sipLogoOffline.png b/src/net/java/sip/communicator/impl/systray/resources/sipLogoOffline.png Binary files differnew file mode 100644 index 0000000..c00126a --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/resources/sipLogoOffline.png diff --git a/src/net/java/sip/communicator/impl/systray/resources/statusIcon.png b/src/net/java/sip/communicator/impl/systray/resources/statusIcon.png Binary files differnew file mode 100644 index 0000000..c3b794b --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/resources/statusIcon.png diff --git a/src/net/java/sip/communicator/impl/systray/resources/systrayIcon.png b/src/net/java/sip/communicator/impl/systray/resources/systrayIcon.png Binary files differnew file mode 100644 index 0000000..6f2ee2f --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/resources/systrayIcon.png diff --git a/src/net/java/sip/communicator/impl/systray/resources/systrayIconWindows.gif b/src/net/java/sip/communicator/impl/systray/resources/systrayIconWindows.gif Binary files differnew file mode 100644 index 0000000..0056045 --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/resources/systrayIconWindows.gif diff --git a/src/net/java/sip/communicator/impl/systray/resources/systrayIconWindows.png b/src/net/java/sip/communicator/impl/systray/resources/systrayIconWindows.png Binary files differnew file mode 100644 index 0000000..9708772 --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/resources/systrayIconWindows.png diff --git a/src/net/java/sip/communicator/impl/systray/systray.manifest.mf b/src/net/java/sip/communicator/impl/systray/systray.manifest.mf new file mode 100644 index 0000000..23d9a18 --- /dev/null +++ b/src/net/java/sip/communicator/impl/systray/systray.manifest.mf @@ -0,0 +1,31 @@ +Bundle-Activator: net.java.sip.communicator.impl.systray.SystrayActivator
+Bundle-Name: Systray
+Bundle-Description: Systray.
+Bundle-Vendor: sip-communicator.org
+Bundle-Version: 0.0.1
+Export-Package: net.java.sip.communicator.service.systray,
+ net.java.sip.communicator.service.systray.event
+Import-Package: org.osgi.framework,
+ org.jdesktop.jdic.tray,
+ net.java.sip.communicator.util,
+ net.java.sip.communicator.service.configuration,
+ net.java.sip.communicator.service.protocol,
+ net.java.sip.communicator.service.protocol.event,
+ net.java.sip.communicator.service.gui,
+ net.java.sip.communicator.service.gui.event,
+ net.java.sip.communicator.service.systray,
+ net.java.sip.communicator.service.systray.event,
+ javax.swing,
+ javax.swing.event,
+ javax.swing.table,
+ javax.swing.text,
+ javax.swing.text.html,
+ javax.accessibility,
+ javax.swing.plaf,
+ javax.swing.plaf.metal,
+ javax.swing.plaf.basic,
+ javax.imageio,
+ javax.swing.filechooser,
+ javax.swing.tree,
+ javax.swing.undo,
+ javax.swing.border
|