diff --git a/src/net/java/sip/communicator/impl/gui/main/presence/PresenceStatusSelectorBox.java b/src/net/java/sip/communicator/impl/gui/main/presence/PresenceStatusSelectorBox.java new file mode 100644 index 000000000..ae44a0e9b --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/presence/PresenceStatusSelectorBox.java @@ -0,0 +1,380 @@ +/* + * 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.gui.main.presence; + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; +import java.util.*; + +import javax.swing.*; +import javax.swing.Timer; + +import net.java.sip.communicator.impl.gui.customcontrols.*; +import net.java.sip.communicator.impl.gui.i18n.*; +import net.java.sip.communicator.impl.gui.main.*; +import net.java.sip.communicator.impl.gui.utils.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +/** + * The StatusSelectorBox is a SIPCommSelectorBox that contains + * the list of statuses for a protocol provider. This is where the user could + * select its status. + * + * @author Yana Stamcheva + */ +public class PresenceStatusSelectorBox + extends StatusSelectorBox +{ + + private Logger logger = Logger.getLogger( + PresenceStatusSelectorBox.class.getName()); + + private MainFrame mainFrame; + + private BufferedImage[] animatedImageArray; + + private Connecting connecting = new Connecting(); + + private ProtocolProviderService protocolProvider; + + private Iterator statusIterator; + + private PresenceStatus offlineStatus; + + private PresenceStatus onlineStatus; + + private PresenceStatus lastSelectedStatus; + + private int accountIndex; + + /** + * Creates an instance of StatusSelectorBox and initializes + * the selector box with data. + * + * @param mainFrame The main application window. + * @param protocolProvider The protocol provider. + * @param accountIndex If we have more than one account for a protocol, + * each account has an index. + */ + public PresenceStatusSelectorBox(MainFrame mainFrame, + ProtocolProviderService protocolProvider, + int accountIndex) { + + this.mainFrame = mainFrame; + this.protocolProvider = protocolProvider; + this.accountIndex = accountIndex; + + this.mainFrame.getProtocolPresence(protocolProvider); + + this.statusIterator = this.mainFrame + .getProtocolPresence(protocolProvider).getSupportedStatusSet(); + + this.setToolTipText(protocolProvider.getAccountID().getUserID()); + + while(statusIterator.hasNext()) { + PresenceStatus status = (PresenceStatus) statusIterator.next(); + int connectivity = status.getStatus(); + + if(connectivity < 1) { + this.offlineStatus = status; + } + else if((onlineStatus != null + && (onlineStatus.getStatus() < connectivity)) + || (onlineStatus == null + && (connectivity > 50 && connectivity < 80))) { + this.onlineStatus = status; + } + + this.addItem(status.getStatusName(), + new ImageIcon( + ImageLoader.getBytesInImage(status.getStatusIcon())), + new ItemActionListener()); + } + this.setSelectedStatus(offlineStatus); + } + + /** + * Handles the ActionEvent triggered when one of the items + * in the list is selected. + */ + private class ItemActionListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + if (e.getSource() instanceof JMenuItem) { + + JMenuItem menuItem = (JMenuItem) e.getSource(); + + OperationSetPresence presence = mainFrame + .getProtocolPresence(protocolProvider); + + Iterator statusSet = presence.getSupportedStatusSet(); + + while (statusSet.hasNext()) { + + PresenceStatus status = ((PresenceStatus) statusSet.next()); + + if (status.getStatusName().equals(menuItem.getText()) + && !presence.getPresenceStatus().equals(status)) { + + try { + if(protocolProvider.isRegistered()) { + if (status.isOnline()) { + presence.publishPresenceStatus( + status, ""); + } + else { + mainFrame.getLoginManager() + .setManuallyDisconnected(true); + protocolProvider.unregister(); + } + setSelectedStatus(status); + } + else { + lastSelectedStatus = status; + mainFrame.getLoginManager() + .login(protocolProvider); + } + mainFrame.saveStatusInformation( + protocolProvider, 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) { + SIPCommMsgTextArea msgText + = new SIPCommMsgTextArea(Messages + .getString("statusChangeGeneralError")); + + JOptionPane.showMessageDialog(null, msgText, + Messages.getString("generalError"), + JOptionPane.ERROR_MESSAGE); + } + else if (e1.getErrorCode() + == OperationFailedException + .NETWORK_FAILURE) { + SIPCommMsgTextArea msgText + = new SIPCommMsgTextArea( + Messages.getString( + "statusChangeNetworkFailure")); + + JOptionPane.showMessageDialog( + null, + msgText, + Messages.getString("networkFailure"), + JOptionPane.ERROR_MESSAGE); + } + else if (e1.getErrorCode() + == OperationFailedException + .PROVIDER_NOT_REGISTERED) { + SIPCommMsgTextArea msgText + = new SIPCommMsgTextArea( + Messages.getString( + "statusChangeNetworkFailure")); + + JOptionPane.showMessageDialog( + null, + msgText, + Messages.getString("networkFailure"), + JOptionPane.ERROR_MESSAGE); + } + logger.error("Error - changing status", e1); + } + break; + } + } + } + } + } + + /** + * Starts the timer that changes the images given by the array, thus + * creating an animated image that indicates that the user is connecting. + * + * @param images A BufferedImage array that contains all images + * from which to create the animated image indicating the connecting state. + */ + public void startConnecting(BufferedImage[] images) { + + this.animatedImageArray = images; + + this.setIcon(new ImageIcon(images[0])); + + this.connecting.start(); + } + + /** + * Stops the timer that manages the connecting animated icon. + */ + public void updateStatus(Object presenceStatus) { + + PresenceStatus status = (PresenceStatus) presenceStatus; + + OperationSetPresence presence = mainFrame + .getProtocolPresence(protocolProvider); + + this.connecting.stop(); + + this.setSelectedStatus(status); + + if(protocolProvider.isRegistered()) { + 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) { + SIPCommMsgTextArea msgText + = new SIPCommMsgTextArea(Messages + .getString("statusChangeGeneralError")); + + JOptionPane.showMessageDialog(null, msgText, + Messages.getString("generalError"), + JOptionPane.ERROR_MESSAGE); + } + else if (e1.getErrorCode() + == OperationFailedException + .NETWORK_FAILURE) { + SIPCommMsgTextArea msgText + = new SIPCommMsgTextArea( + Messages.getString( + "statusChangeNetworkFailure")); + + JOptionPane.showMessageDialog( + null, + msgText, + Messages.getString("networkFailure"), + JOptionPane.ERROR_MESSAGE); + } + else if (e1.getErrorCode() + == OperationFailedException + .PROVIDER_NOT_REGISTERED) { + SIPCommMsgTextArea msgText + = new SIPCommMsgTextArea( + Messages.getString( + "statusChangeNetworkFailure")); + + JOptionPane.showMessageDialog( + null, + msgText, + Messages.getString("networkFailure"), + JOptionPane.ERROR_MESSAGE); + } + logger.error("Error - changing status", e1); + } + } + } + + /** + * A Timer that creates an animated icon, which indicates the + * connecting state. + */ + private class Connecting extends Timer { + + public Connecting() { + + super(100, null); + + this.addActionListener(new TimerActionListener()); + } + + private class TimerActionListener implements ActionListener { + + private int j = 1; + + public void actionPerformed(ActionEvent evt) { + + PresenceStatusSelectorBox.this.setIcon(new ImageIcon( + animatedImageArray[j])); + j = (j + 1) % animatedImageArray.length; + } + + } + } + + /** + * Selects the given status in the status menu. + * @param status the status to select + */ + public void setSelectedStatus(PresenceStatus status) + { + Image statusImage = ImageLoader.getBytesInImage(status.getStatusIcon()); + + this.setSelected(status.getStatusName(), + new ImageIcon(statusImage)); + } + + /** + * Returns the Offline status in this selector box. + * @return the Offline status in this selector box + */ + public PresenceStatus getOfflineStatus() + { + return offlineStatus; + } + + /** + * Returns the Online status in this selector box. + * @return the Online status in this selector box + */ + public PresenceStatus getOnlineStatus() + { + return onlineStatus; + } + + /** + * Returns the status that is currently selected. + * @return the status that is currently selected + */ + public PresenceStatus getLastSelectedStatus() + { + return lastSelectedStatus; + } + + public int getAccountIndex() + { + return accountIndex; + } + + public void setAccountIndex(int accountIndex) + { + this.accountIndex = accountIndex; + } + + public void paintComponent(Graphics g) + { + super.paintComponent(g); + + if(accountIndex > 0) { + AntialiasingManager.activateAntialiasing(g); + g.setColor(Color.DARK_GRAY); + g.setFont(Constants.FONT.deriveFont(Font.BOLD, 9)); + g.drawString(new Integer(accountIndex).toString(), 20, 12); + } + } + + public void updateStatus() + {} +} diff --git a/src/net/java/sip/communicator/impl/gui/main/presence/SimpleStatusSelectorBox.java b/src/net/java/sip/communicator/impl/gui/main/presence/SimpleStatusSelectorBox.java new file mode 100644 index 000000000..0fc41f4c0 --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/presence/SimpleStatusSelectorBox.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.gui.main.presence; + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; + +import javax.swing.*; + +import net.java.sip.communicator.impl.gui.customcontrols.*; +import net.java.sip.communicator.impl.gui.i18n.*; +import net.java.sip.communicator.impl.gui.main.*; +import net.java.sip.communicator.impl.gui.utils.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; + +/** + * The SimpleStatusSelectorBox is a SIPCommSelectorBox that + * contains two statuses ONLINE and OFFLINE. It's used to represent the status + * of a protocol provider which doesn't support presence operation set. + * + * @author Yana Stamcheva + */ +public class SimpleStatusSelectorBox + extends StatusSelectorBox + implements ActionListener +{ + + private Logger logger = Logger.getLogger( + PresenceStatusSelectorBox.class.getName()); + + private MainFrame mainFrame; + + private BufferedImage[] animatedImageArray; + + private Connecting connecting = new Connecting(); + + private ProtocolProviderService protocolProvider; + + private Icon onlineIcon + = new ImageIcon(ImageLoader.getImage(ImageLoader.SIP_LOGO)); + + private Icon offlineIcon + = new ImageIcon(LightGrayFilter.createDisabledImage( + ImageLoader.getImage(ImageLoader.SIP_LOGO))); + + private JMenuItem onlineItem = new JMenuItem( + Messages.getString("online"), + onlineIcon); + + private JMenuItem offlineItem = new JMenuItem( + Messages.getString("offline"), + offlineIcon); + + private int accountIndex; + + /** + * Creates an instance of SimpleStatusSelectorBox. + * + * @param mainFrame The main application window. + * @param protocolProvider The protocol provider. + * @param accountIndex If we have more than one account for a protocol, + * each account has an index. + */ + public SimpleStatusSelectorBox(MainFrame mainFrame, + ProtocolProviderService protocolProvider, + int accountIndex) + { + this.mainFrame = mainFrame; + this.protocolProvider = protocolProvider; + this.accountIndex = accountIndex; + + this.setToolTipText(protocolProvider.getAccountID().getUserID()); + + onlineItem.setName("online"); + offlineItem.setName("offline"); + + onlineItem.addActionListener(this); + offlineItem.addActionListener(this); + + this.addItem(onlineItem); + this.addItem(offlineItem); + } + + /** + * Handles the ActionEvent triggered when one of the items + * in the list is selected. + */ + public void actionPerformed(ActionEvent e) + { + JMenuItem menuItem = (JMenuItem) e.getSource(); + String itemName = menuItem.getName(); + + if(itemName.equals("online")) { + if(!protocolProvider.isRegistered()) { + this.mainFrame.getLoginManager().login(protocolProvider); + } + } + else { + try { + mainFrame.getLoginManager() + .setManuallyDisconnected(true); + protocolProvider.unregister(); + } + catch (OperationFailedException e1) { + logger.error("Unable to unregister the protocol provider: " + + protocolProvider + + " due to the following exception: " + e1); + } + } + } + + + /** + * Starts the timer that changes the images given by the array, thus + * creating an animated image that indicates that the user is connecting. + * + * @param images A BufferedImage array that contains all images + * from which to create the animated image indicating the connecting state. + */ + public void startConnecting(BufferedImage[] images) + { + this.animatedImageArray = images; + + this.setIcon(new ImageIcon(images[0])); + + this.connecting.start(); + } + + /** + * Stops the timer that manages the connecting animated icon. + */ + public void updateStatus() + { + this.connecting.stop(); + + if(protocolProvider.isRegistered()) { + setSelected(onlineItem, onlineIcon); + } + else { + setSelected(offlineItem, offlineIcon); + } + } + + /** + * A Timer that creates an animated icon, which indicates the + * connecting state. + */ + private class Connecting extends Timer { + + public Connecting() { + + super(100, null); + + this.addActionListener(new TimerActionListener()); + } + + private class TimerActionListener implements ActionListener { + + private int j = 1; + + public void actionPerformed(ActionEvent evt) { + + SimpleStatusSelectorBox.this.setIcon(new ImageIcon( + animatedImageArray[j])); + j = (j + 1) % animatedImageArray.length; + } + + } + } + + public int getAccountIndex() + { + return accountIndex; + } + + public void setAccountIndex(int accountIndex) + { + this.accountIndex = accountIndex; + } + + public void paintComponent(Graphics g) + { + super.paintComponent(g); + + if(accountIndex > 0) { + AntialiasingManager.activateAntialiasing(g); + g.setColor(Color.DARK_GRAY); + g.setFont(Constants.FONT.deriveFont(Font.BOLD, 9)); + g.drawString(new Integer(accountIndex).toString(), 20, 12); + } + } + + public void updateStatus(Object status) + {} +} diff --git a/src/net/java/sip/communicator/impl/gui/main/presence/StatusPanel.java b/src/net/java/sip/communicator/impl/gui/main/presence/StatusPanel.java new file mode 100644 index 000000000..85ff62520 --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/presence/StatusPanel.java @@ -0,0 +1,256 @@ +/* + * 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.gui.main.presence; + +import java.util.*; +import java.util.List; + +import java.awt.*; +import javax.swing.*; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.impl.gui.customcontrols.*; +import net.java.sip.communicator.impl.gui.main.*; +import net.java.sip.communicator.impl.gui.utils.*; +import net.java.sip.communicator.service.configuration.*; +import net.java.sip.communicator.service.protocol.*; + +/** + * The StatusPanel is the place where the user can see and change + * its status for all registered protocols. + * + * @author Yana Stamcheva + */ +public class StatusPanel extends JPanel { + + private Hashtable protocolStatusCombos = new Hashtable(); + + private MainFrame mainFrame; + + /** + * Creates an instance of StatusPanel. + * @param mainFrame The main application window. + */ + public StatusPanel(MainFrame mainFrame) { + + this.mainFrame = mainFrame; + + this.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); + + this.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, + Constants.MOVER_START_COLOR)); + } + + /** + * Creates the selector box, containing all protocol statuses, adds it to + * the StatusPanel and refreshes the panel. + * + * @param protocolProvider The protocol provider. + */ + public void addAccount(ProtocolProviderService protocolProvider) + { + StatusSelectorBox protocolStatusCombo; + + int providerIndex = this.mainFrame.getProviderIndex(protocolProvider); + if(mainFrame.getProtocolPresence(protocolProvider) != null) { + protocolStatusCombo + = new PresenceStatusSelectorBox( + this.mainFrame, protocolProvider, + providerIndex); + } + else { + protocolStatusCombo + = new SimpleStatusSelectorBox( + this.mainFrame, protocolProvider, + providerIndex); + } + + this.protocolStatusCombos.put(protocolProvider, + protocolStatusCombo); + + this.add(protocolStatusCombo); + + this.getParent().validate(); + } + + /** + * Removes the selector box, containing all protocol statuses, from + * the StatusPanel and refreshes the panel. + * + * @param pps The protocol provider to remove. + */ + public void removeAccount(ProtocolProviderService pps) { + + StatusSelectorBox protocolStatusCombo + = (StatusSelectorBox) this.protocolStatusCombos.get(pps); + + this.protocolStatusCombos.remove(pps); + this.remove(protocolStatusCombo); + + this.revalidate(); + this.repaint(); + } + + /** + * Updates the account given by the protocol provider. + * + * @param protocolProvider the protocol provider for the account to update + */ + public void updateAccount(ProtocolProviderService protocolProvider) { + StatusSelectorBox protocolStatusCombo + = (StatusSelectorBox) this.protocolStatusCombos + .get(protocolProvider); + + protocolStatusCombo.setAccountIndex( + mainFrame.getProviderIndex(protocolProvider)); + + this.revalidate(); + this.repaint(); + } + + + /** + * Shows the protocol animated icon, which indicates that it is in a + * connecting state. + * + * @param protocolProvider The protocol provider. + */ + public void startConnecting(ProtocolProviderService protocolProvider) { + + StatusSelectorBox selectorBox + = (StatusSelectorBox) protocolStatusCombos + .get(protocolProvider); + + selectorBox.startConnecting(Constants + .getProtocolAnimatedIcon(protocolProvider.getProtocolName())); + + selectorBox.repaint(); + } + + /** + * Returns the last status that was stored in the configuration xml for the + * given protocol provider. + * @param protocolProvider the protocol provider + * @return the last status that was stored in the configuration xml for the + * given protocol provider + */ + public PresenceStatus getProtocolProviderLastStatus( + ProtocolProviderService protocolProvider) + { + ConfigurationService configService + = GuiActivator.getConfigurationService(); + + //find the last contact status saved in the configuration. + String lastStatus = null; + + OperationSetPresence presence + = mainFrame.getProtocolPresence(protocolProvider); + + if(presence == null) + return null; + + Iterator i = presence.getSupportedStatusSet(); + + String prefix = "net.java.sip.communicator.impl.ui.accounts"; + + List accounts = configService + .getPropertyNamesByPrefix(prefix, true); + + Iterator accountsIter = accounts.iterator(); + + while(accountsIter.hasNext()) { + String accountRootPropName + = (String) accountsIter.next(); + + String accountUID + = configService.getString(accountRootPropName); + + if(accountUID.equals(protocolProvider + .getAccountID().getAccountUniqueID())) { + lastStatus = configService.getString( + accountRootPropName + ".lastAccountStatus"); + + if(lastStatus != null) + break; + } + } + + if(lastStatus != null) { + PresenceStatus status; + while(i.hasNext()) { + status = (PresenceStatus)i.next(); + if(status.getStatusName().equals(lastStatus)) { + return status; + } + } + } + return null; + } + + /** + * Updates the status for this protocol provider. + * + * @param protocolProvider The ProtocolProvider, which presence status to + * update. + */ + public void updateStatus(ProtocolProviderService protocolProvider) { + StatusSelectorBox selectorBox + = (StatusSelectorBox) protocolStatusCombos + .get(protocolProvider); + + + if(selectorBox == null) + return; + + if(selectorBox instanceof PresenceStatusSelectorBox) { + PresenceStatusSelectorBox presenceSelectorBox + = (PresenceStatusSelectorBox) selectorBox; + + if(!protocolProvider.isRegistered()) + presenceSelectorBox.updateStatus( + presenceSelectorBox.getOfflineStatus()); + else { + if(presenceSelectorBox.getLastSelectedStatus() != null) { + presenceSelectorBox.updateStatus( + presenceSelectorBox.getLastSelectedStatus()); + } + else { + PresenceStatus lastStatus + = getProtocolProviderLastStatus(protocolProvider); + + if(lastStatus == null) { + presenceSelectorBox.updateStatus( + presenceSelectorBox.getOnlineStatus()); + } + else { + presenceSelectorBox.updateStatus(lastStatus); + } + } + } + } + else { + ((SimpleStatusSelectorBox)selectorBox).updateStatus(); + } + selectorBox.repaint(); + } + + /** + * Checks if the given protocol has already its StatusSelectorBox + * in the StatusPanel. + * + * @param pps The protocol provider to check. + * @return True if the protcol has already its StatusSelectorBox in the + * StatusPanel, False otherwise. + */ + public boolean containsAccount(ProtocolProviderService pps) { + if (protocolStatusCombos.containsKey(pps)) + return true; + else + return false; + } +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/gui/main/presence/StatusSelectorBox.java b/src/net/java/sip/communicator/impl/gui/main/presence/StatusSelectorBox.java new file mode 100644 index 000000000..a56f197ac --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/presence/StatusSelectorBox.java @@ -0,0 +1,22 @@ +/* + * 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.gui.main.presence; + +import java.awt.image.*; + +import net.java.sip.communicator.impl.gui.customcontrols.*; + +public abstract class StatusSelectorBox extends SIPCommSelectorBox +{ + public void startConnecting(BufferedImage[] images){} + + public void updateStatus(){} + + public int getAccountIndex(){return -1;} + + public void setAccountIndex(int index){} +}