diff --git a/resources/images/images.properties b/resources/images/images.properties index eed832ebf..c02cec9f1 100644 --- a/resources/images/images.properties +++ b/resources/images/images.properties @@ -95,8 +95,10 @@ service.gui.icons.CHANGE_NICKNAME=resources/images/impl/gui/common/changeNicknam service.gui.icons.BAN_16x16=resources/images/impl/gui/common/ban16x16.png service.gui.icons.KICK_16x16=resources/images/impl/gui/common/kick16x16.png service.gui.icons.VOICEMAIL=resources/images/impl/gui/common/voicemail.png -service.gui.icons.SEND_SMS=resources/images/impl/gui/common/sms.png -service.gui.icons.SEND_SMS_SELECTED=resources/images/impl/gui/common/smsSelected.png +service.gui.icons.SEND_SMS=resources/images/impl/gui/common/sendSMSButton.png +service.gui.icons.SEND_SMS_SELECTED=resources/images/impl/gui/common/sendSMSSelectedButton.png +service.gui.icons.SMS_ICON=resources/images/impl/gui/common/phoneAvatar.png +service.gui.icons.SMS_BUTTON_ICON=resources/images/impl/gui/common/smsButton.png service.gui.icons.TYPING=resources/images/impl/gui/common/typing.gif service.gui.icons.WINDOW_RESIZE_ICON=resources/images/impl/gui/common/windowResizeIcon.png service.gui.icons.LO_VIDEO_ICON=resources/images/impl/gui/common/loVideoIcon.png @@ -243,6 +245,9 @@ service.gui.buttons.CALL_HISTORY_BUTTON_PRESSED=resources/images/impl/gui/button service.gui.buttons.SEARCH_CALL_ICON=resources/images/impl/gui/buttons/searchCallIcon.png service.gui.buttons.SEARCH_CALL_ROLLOVER_ICON=resources/images/impl/gui/buttons/searchCallRolloverIcon.png service.gui.buttons.SEARCH_CALL_PRESSED_ICON=resources/images/impl/gui/buttons/searchCallPressedIcon.png +service.gui.buttons.SEARCH_SMS_ICON=resources/images/impl/gui/buttons/searchSMSIcon.png +service.gui.buttons.SEARCH_SMS_ROLLOVER_ICON=resources/images/impl/gui/buttons/searchSMSRolloverIcon.png +service.gui.buttons.SEARCH_SMS_PRESSED_ICON=resources/images/impl/gui/buttons/searchSMSPressedIcon.png service.gui.buttons.ZOOM_OUT=resources/images/impl/gui/buttons/magnifier_zoom_out.png service.gui.buttons.ZOOM_IN=resources/images/impl/gui/buttons/magnifier_zoom_in.png service.gui.buttons.RESET=resources/images/impl/gui/buttons/reset.png diff --git a/resources/images/impl/gui/buttons/searchSMSIcon.png b/resources/images/impl/gui/buttons/searchSMSIcon.png new file mode 100644 index 000000000..f1e659d9c Binary files /dev/null and b/resources/images/impl/gui/buttons/searchSMSIcon.png differ diff --git a/resources/images/impl/gui/buttons/searchSMSPressedIcon.png b/resources/images/impl/gui/buttons/searchSMSPressedIcon.png new file mode 100644 index 000000000..99406baeb Binary files /dev/null and b/resources/images/impl/gui/buttons/searchSMSPressedIcon.png differ diff --git a/resources/images/impl/gui/buttons/searchSMSRolloverIcon.png b/resources/images/impl/gui/buttons/searchSMSRolloverIcon.png new file mode 100644 index 000000000..fef3a090e Binary files /dev/null and b/resources/images/impl/gui/buttons/searchSMSRolloverIcon.png differ diff --git a/resources/images/impl/gui/common/sendSMSButton.png b/resources/images/impl/gui/common/sendSMSButton.png new file mode 100644 index 000000000..2ec3196a4 Binary files /dev/null and b/resources/images/impl/gui/common/sendSMSButton.png differ diff --git a/resources/images/impl/gui/common/sendSMSSelectedButton.png b/resources/images/impl/gui/common/sendSMSSelectedButton.png new file mode 100644 index 000000000..29e77dfc9 Binary files /dev/null and b/resources/images/impl/gui/common/sendSMSSelectedButton.png differ diff --git a/resources/images/impl/gui/common/sms.png b/resources/images/impl/gui/common/sms.png deleted file mode 100644 index 69b4b3cc3..000000000 Binary files a/resources/images/impl/gui/common/sms.png and /dev/null differ diff --git a/resources/images/impl/gui/common/smsButton.png b/resources/images/impl/gui/common/smsButton.png new file mode 100644 index 000000000..70f1576ea Binary files /dev/null and b/resources/images/impl/gui/common/smsButton.png differ diff --git a/resources/images/impl/gui/common/smsSelected.png b/resources/images/impl/gui/common/smsSelected.png deleted file mode 100644 index 7481b26bb..000000000 Binary files a/resources/images/impl/gui/common/smsSelected.png and /dev/null differ diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index 26d7e3ac9..b51ab1958 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -480,6 +480,7 @@ service.gui.SEND_SMS=S&end SMS service.gui.SEND_SMS_DETAILS=Remember that you need to enter the number in international \ format e.g. starting with +44 for the UK for example, +447777000000 service.gui.SEND_SMS_NOT_SUPPORTED=The protocol you have selected doesn't support SMS messages. +service.gui.SMS=SMS service.gui.SEND_VIA=Send via service.gui.SENT=sent service.gui.SET_GLOBAL_STATUS=Set global status diff --git a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java index a0fd2aeb6..f20cb258d 100644 --- a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java +++ b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java @@ -889,6 +889,31 @@ public boolean hasProtocolProvider( } } + /** + * Checks whether we have the operation set in already loaded + * protocol providers. + * @param opSet the operation set to check. + * @return whether we have provider to handle operation set. + */ + public boolean hasOperationSet(Class opSet) + { + synchronized(this.protocolProviders) + { + Iterator iter = + this.protocolProviders.keySet().iterator(); + while(iter.hasNext()) + { + ProtocolProviderService pp = iter.next(); + if(pp.getOperationSet(opSet) != null) + { + return true; + } + } + + return false; + } + } + /** * Adds an account to the application. * diff --git a/src/net/java/sip/communicator/impl/gui/main/call/ChooseCallAccountPopupMenu.java b/src/net/java/sip/communicator/impl/gui/main/call/ChooseCallAccountPopupMenu.java index 718fde4c8..eb47fa4c3 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/ChooseCallAccountPopupMenu.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/ChooseCallAccountPopupMenu.java @@ -200,13 +200,13 @@ private void addTelephonyProviderItem( public void actionPerformed(ActionEvent e) { if (uiContact != null) - CallManager.createCall( + itemSelected( opSetClass, providerItem.getProtocolProvider(), contactString, uiContact); else - CallManager.createCall( + itemSelected( opSetClass, providerItem.getProtocolProvider(), contactString); @@ -272,13 +272,13 @@ else if (providers.size() > 1) String contactAddress = telephonyContact.getAddress(); if (uiContact != null) - CallManager.createCall( + itemSelected( opSetClass, provider, contactAddress, uiContact); else - CallManager.createCall( + itemSelected( opSetClass, provider, contactAddress); @@ -432,6 +432,44 @@ private Component createInfoLabel(String infoString) return infoLabel; } + /** + * Item was selected, give a chance for extenders to override. + * + * @param opSetClass the operation set to use. + * @param protocolProviderService the protocol provider + * @param contact the contact address + * @param uiContact the MetaContact selected + */ + protected void itemSelected( + Class opSetClass, + ProtocolProviderService protocolProviderService, + String contact, + UIContactImpl uiContact) + { + CallManager.createCall( + opSetClass, + protocolProviderService, + contact, + uiContact); + } + + /** + * Item was selected, give a chance for extenders to override. + * + * @param opSetClass the operation set to use. + * @param protocolProviderService the protocol provider + * @param contact the contact address selected + */ + protected void itemSelected(Class opSetClass, + ProtocolProviderService protocolProviderService, + String contact) + { + CallManager.createCall( + opSetClass, + protocolProviderService, + contact); + } + /** * A custom menu item corresponding to a specific * ProtocolProviderService. diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java index 0b14d2141..2689ae206 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatPanel.java @@ -1676,8 +1676,16 @@ public void sendSmsMessage() SendSmsDialog smsDialog = new SendSmsDialog(this, smsChatTransport, messageText); - smsDialog.setPreferredSize(new Dimension(400, 200)); - smsDialog.setVisible(true); + if(smsChatTransport.askForSMSNumber()) + { + smsDialog.setPreferredSize(new Dimension(400, 200)); + smsDialog.setVisible(true); + } + else + { + smsDialog.sendSmsMessage(null, messageText); + smsDialog.dispose(); + } } /** diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransport.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransport.java index f203643c6..b9d23598d 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransport.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransport.java @@ -149,6 +149,13 @@ public void correctInstantMessage(String message, String mimeType, */ public boolean isContentTypeSupported(String contentType); + /** + * Whether a dialog need to be opened so the user can enter the destination + * number. + * @return true if dialog needs to be open. + */ + public boolean askForSMSNumber(); + /** * Sends the given SMS message trough this chat transport. * @@ -160,13 +167,13 @@ public void sendSmsMessage(String phoneNumber, String message) throws Exception; /** - * Sends the given SMS message trough this chat transport. + * Sends the given SMS message trough this chat transport, leaving + * the transport to choose the destination. * - * @param contact the phone number to which to send the message * @param message The message to send. * @throws Exception if the send doesn't succeed */ - public void sendSmsMessage(Contact contact, String message) + public void sendSmsMessage(String message) throws Exception; /** diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransportSelectorBox.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransportSelectorBox.java index 929ee3e1f..8048b0438 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransportSelectorBox.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatTransportSelectorBox.java @@ -167,6 +167,11 @@ public void addChatTransport(ChatTransport chatTransport) updateTransportStatus(chatTransport); } + + if(!allowsInstantMessage() && allowsSmsMessage()) + chatPanel.getChatWritePanel().setSmsSelected(true); + else + chatPanel.getChatWritePanel().setSmsSelected(false); } /** @@ -419,6 +424,44 @@ else if(!online && !comboChatTransport.getStatus().isOnline()) return null; } + /** + * Returns true if this contains a chat transport that + * supports instant messaging, otherwise returns false. + * + * @return true if this contains a chat transport that + * supports instant messaging, otherwise returns false + */ + private boolean allowsInstantMessage() + { + for(ChatTransport tr : transportMenuItems.keySet()) + { + if(tr.allowsInstantMessage()) + { + return true; + } + } + + return false; + } + + /** + * Returns true if this contains a chat transport that + * supports sms messaging, otherwise returns false. + * + * @return true if this contains a chat transport that + * supports sms messaging, otherwise returns false + */ + private boolean allowsSmsMessage() + { + for(ChatTransport tr : transportMenuItems.keySet()) + { + if(tr.allowsSmsMessage()) + return true; + } + + return false; + } + /** * A custom SIPCommMenu that adds an arrow icon to the right of * the menu image. diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWindowManager.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWindowManager.java index e8db08a35..90c45646e 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWindowManager.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWindowManager.java @@ -1338,7 +1338,7 @@ private class RunChatWindow implements Runnable private Contact protocolContact; - private boolean isSmsSelected = false; + private Boolean isSmsSelected = null; /** * Creates an instance of RunMessageWindow by specifying the @@ -1387,7 +1387,10 @@ public void run() ChatPanel chatPanel = getContactChat(metaContact, protocolContact); - chatPanel.setSmsSelected(isSmsSelected); + // if not explicitly set, do not set it, leave it to default + // or internally make the decision + if(isSmsSelected != null) + chatPanel.setSmsSelected(isSmsSelected); openChat(chatPanel, true); } diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java index 23f66e2cd..a37ce8c8c 100755 --- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatWritePanel.java @@ -20,9 +20,11 @@ import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.main.chat.conference.*; import net.java.sip.communicator.impl.gui.main.chat.menus.*; +import net.java.sip.communicator.impl.gui.utils.*; import net.java.sip.communicator.plugin.desktoputil.*; import net.java.sip.communicator.service.gui.event.*; import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.service.resources.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.skin.*; @@ -75,9 +77,7 @@ public class ChatWritePanel private final Container centerPanel; - private JLabel smsLabel; - - private JCheckBoxMenuItem smsMenuItem; + private SIPCommToggleButton smsButton; private JLabel smsCharCountLabel; @@ -260,66 +260,51 @@ private void initSmsLabel(final JPanel centerPanel) constraints.weighty = 0f; constraints.insets = new Insets(0, 3, 0, 0); - final Icon smsIcon = GuiActivator.getResources() - .getImage("service.gui.icons.SEND_SMS"); - - final Icon selectedIcon = GuiActivator.getResources() - .getImage("service.gui.icons.SEND_SMS_SELECTED"); + ImageID smsIcon = + new ImageID("service.gui.icons.SEND_SMS"); - smsLabel = new JLabel(smsIcon); - - // We hide the sms label until we know if the chat supports sms. - smsLabel.setVisible(false); + ImageID selectedIcon = + new ImageID("service.gui.icons.SEND_SMS_SELECTED"); - smsMenuItem = new JCheckBoxMenuItem(GuiActivator.getResources() - .getI18NString("service.gui.VIA_SMS")); + smsButton = new SIPCommToggleButton( + ImageLoader.getImage(smsIcon), + ImageLoader.getImage(selectedIcon), + ImageLoader.getImage(smsIcon), + ImageLoader.getImage(selectedIcon)); - smsMenuItem.addChangeListener(new ChangeListener() + smsButton.addActionListener(new ActionListener() { - public void stateChanged(ChangeEvent e) + @Override + public void actionPerformed(ActionEvent e) { - smsMode = smsMenuItem.isSelected(); + smsMode = smsButton.isSelected(); Color bgColor; if (smsMode) { - smsLabel.setIcon(selectedIcon); bgColor = new Color(GuiActivator.getResources() .getColor("service.gui.LIST_SELECTION_COLOR")); + + smsCharCountLabel.setVisible(true); + smsNumberLabel.setVisible(true); } else { - smsLabel.setIcon(smsIcon); bgColor = Color.WHITE; + smsCharCountLabel.setVisible(false); + smsNumberLabel.setVisible(false); } centerPanel.setBackground(bgColor); editorPane.setBackground(bgColor); - - smsLabel.repaint(); } }); - smsLabel.addMouseListener(new MouseAdapter() - { - @Override - public void mousePressed(MouseEvent mouseevent) - { - Point location = new Point(smsLabel.getX(), - smsLabel.getY() + smsLabel.getHeight()); - - SwingUtilities.convertPointToScreen(location, smsLabel); - JPopupMenu smsPopupMenu = new JPopupMenu(); - smsPopupMenu.setFocusable(true); - smsPopupMenu.setInvoker(ChatWritePanel.this); - smsPopupMenu.add(smsMenuItem); - smsPopupMenu.setLocation(location.x, location.y); - smsPopupMenu.setVisible(true); - } - }); + // We hide the sms label until we know if the chat supports sms. + smsButton.setVisible(false); - centerPanel.add(smsLabel, constraints); + centerPanel.add(smsButton, constraints); } private void initTextArea(JPanel centerPanel) @@ -460,7 +445,11 @@ public void changeSendCommand(boolean isEnter) */ public void setSmsSelected(boolean selected) { - smsMenuItem.setSelected(selected); + if((selected && !smsButton.isSelected()) + || (!selected && smsButton.isSelected())) + { + smsButton.doClick(); + } } /** @@ -1242,9 +1231,7 @@ public void setSmsLabelVisible(boolean isVisible) smsCharCount = 160; smsNumberCount = 1; - smsLabel.setVisible(isVisible); - smsCharCountLabel.setVisible(isVisible); - smsNumberLabel.setVisible(isVisible); + smsButton.setVisible(isVisible); centerPanel.repaint(); } @@ -1421,7 +1408,7 @@ public void changedUpdate(DocumentEvent documentevent) {} public void insertUpdate(DocumentEvent event) { // If we're in sms mode count the chars typed. - if (smsLabel.isVisible()) + if (smsButton.isVisible()) { if (smsCharCount == 0) { @@ -1445,7 +1432,7 @@ public void insertUpdate(DocumentEvent event) public void removeUpdate(DocumentEvent event) { // If we're in sms mode count the chars typed. - if (smsLabel.isVisible()) + if (smsButton.isVisible()) { if (smsCharCount == 160 && smsNumberCount > 1) { diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/MetaContactChatTransport.java b/src/net/java/sip/communicator/impl/gui/main/chat/MetaContactChatTransport.java index 7ec0e2b9d..8808434b8 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/MetaContactChatTransport.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/MetaContactChatTransport.java @@ -278,7 +278,7 @@ public boolean allowsMessageCorrections() */ public boolean allowsSmsMessage() { - // First try to ask the capabilities operation set if such is + // First try to ask the capabilities operation set if such is // available. OperationSetContactCapabilities capOpSet = getProtocolProvider() .getOperationSet(OperationSetContactCapabilities.class); @@ -462,14 +462,33 @@ public void sendSmsMessage(String phoneNumber, String messageText) smsOpSet.sendSmsMessage(phoneNumber, smsMessage); } + /** + * Whether a dialog need to be opened so the user can enter the destination + * number. + * @return true if dialog needs to be open. + */ + public boolean askForSMSNumber() + { + // If this chat transport does not support sms messaging we do + // nothing here. + if (!allowsSmsMessage()) + return false; + + OperationSetSmsMessaging smsOpSet + = contact + .getProtocolProvider() + .getOperationSet(OperationSetSmsMessaging.class); + + return smsOpSet.askForNumber(contact); + } + /** * Sends the given sms message trough this chat transport. * - * @param contact the destination contact * @param message the message to send * @throws Exception if the send operation is interrupted */ - public void sendSmsMessage(Contact contact, String message) + public void sendSmsMessage(String message) throws Exception { // If this chat transport does not support sms messaging we do diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/SendSmsDialog.java b/src/net/java/sip/communicator/impl/gui/main/chat/SendSmsDialog.java index 00d1ca5f4..c1b1a400e 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/SendSmsDialog.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/SendSmsDialog.java @@ -114,23 +114,27 @@ public void actionPerformed(ActionEvent event) * Sends the given message to the given phoneNumber, using the current * SMS operation set. * - * @param phoneNumber the phone number to which the message should be sent. + * @param phoneNumber the phone number to which the message should be sent, + * if is null, will leave transport to choose * @param message the message to send. */ - private void sendSmsMessage(String phoneNumber, String message) + public void sendSmsMessage(String phoneNumber, String message) { - chatTransport.getParentChatSession().setDefaultSmsNumber(phoneNumber); + if(phoneNumber != null) + chatTransport.getParentChatSession() + .setDefaultSmsNumber(phoneNumber); try { - chatTransport.sendSmsMessage(phoneNumber, message); + if(phoneNumber != null) + chatTransport.sendSmsMessage(phoneNumber, message); + else + chatTransport.sendSmsMessage(message); } catch (IllegalStateException ex) { logger.error("Failed to send SMS.", ex); - chatPanel.refreshWriteArea(); - chatPanel.addMessage( phoneNumber, new Date(), @@ -147,8 +151,6 @@ private void sendSmsMessage(String phoneNumber, String message) { logger.error("Failed to send SMS.", ex); - chatPanel.refreshWriteArea(); - chatPanel.addMessage( phoneNumber, new Date(), @@ -163,6 +165,8 @@ private void sendSmsMessage(String phoneNumber, String message) new String[]{ex.getMessage()})); } + chatPanel.refreshWriteArea(); + this.dispose(); } diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/AdHocConferenceChatTransport.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/AdHocConferenceChatTransport.java index 276b4e82b..0a3698238 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/AdHocConferenceChatTransport.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/AdHocConferenceChatTransport.java @@ -194,10 +194,19 @@ public void sendSmsMessage(String phoneNumber, String message) * Sending sms messages is not supported by this chat transport * implementation. */ - public void sendSmsMessage(Contact contact, String message) + public void sendSmsMessage(String message) throws Exception {} + /** + * Not used. + * @return + */ + public boolean askForSMSNumber() + { + return false; + } + /** * Sending typing notifications is not supported by this chat transport * implementation. diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatTransport.java b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatTransport.java index 399496320..c7abc976a 100644 --- a/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatTransport.java +++ b/src/net/java/sip/communicator/impl/gui/main/chat/conference/ConferenceChatTransport.java @@ -193,10 +193,19 @@ public void sendSmsMessage(String phoneNumber, String message) * Sending sms messages is not supported by this chat transport * implementation. */ - public void sendSmsMessage(Contact contact, String message) + public void sendSmsMessage(String message) throws Exception {} + /** + * Not used. + * @return + */ + public boolean askForSMSNumber() + { + return false; + } + /** * Sending typing notifications is not supported by this chat transport * implementation. diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactSearchFieldUI.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactSearchFieldUI.java index 256d70e71..9a675eab6 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactSearchFieldUI.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactSearchFieldUI.java @@ -13,8 +13,11 @@ import javax.swing.plaf.*; import javax.swing.text.*; +import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.main.call.*; +import net.java.sip.communicator.impl.gui.utils.*; import net.java.sip.communicator.plugin.desktoputil.plaf.*; +import net.java.sip.communicator.service.protocol.*; import net.java.sip.communicator.util.*; import net.java.sip.communicator.util.skin.*; @@ -65,6 +68,11 @@ public ContactSearchFieldUI() protected void customPaintBackground(Graphics g) { isCallButtonEnabled = CallManager.getTelephonyProviders().size() > 0; + + setSMSButtonEnabled( + GuiActivator.getUIService().getMainFrame() + .hasOperationSet(OperationSetSmsMessaging.class)); + super.customPaintBackground(g); } @@ -74,18 +82,16 @@ protected void customPaintBackground(Graphics g) * @param ev the mouse event that has prompted us to create the call. */ @Override - protected void updateCallIcon(MouseEvent ev) + protected void updateIcon(MouseEvent ev) { - super.updateCallIcon(ev); + super.updateIcon(ev); - - if ((ev.getID() == MouseEvent.MOUSE_CLICKED) && isCallIconVisible) + if ((ev.getID() == MouseEvent.MOUSE_CLICKED)) { - Rectangle callButtonRect = getCallButtonRect(); int x = ev.getX(); int y = ev.getY(); - if (callButtonRect.contains(x, y)) + if (isCallIconVisible && getCallButtonRect().contains(x, y)) { JTextComponent c = getComponent(); String searchText = c.getText(); @@ -93,6 +99,16 @@ protected void updateCallIcon(MouseEvent ev) if (searchText != null) CallManager.createCall(searchText, c); } + else if (isSMSIconVisible && getSMSButtonRect().contains(x, y)) + { + JTextComponent c = getComponent(); + final String searchText = c.getText(); + + if (searchText == null) + return; + + SMSManager.sendSMS(getComponent(), searchText); + } } } } diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/UnknownContactPanel.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/UnknownContactPanel.java index b3f09cffd..552c0de99 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/UnknownContactPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/UnknownContactPanel.java @@ -16,6 +16,7 @@ import net.java.sip.communicator.impl.gui.*; import net.java.sip.communicator.impl.gui.main.*; import net.java.sip.communicator.impl.gui.main.call.*; +import net.java.sip.communicator.impl.gui.utils.*; import net.java.sip.communicator.plugin.desktoputil.*; import net.java.sip.communicator.plugin.desktoputil.event.*; import net.java.sip.communicator.service.protocol.*; @@ -42,6 +43,8 @@ public class UnknownContactPanel private final JButton callButton = new JButton( GuiActivator.getResources().getI18NString("service.gui.CALL_CONTACT")); + private JButton smsButton; + private final JTextPane textArea = new JTextPane(); private final TransparentPanel buttonPanel @@ -78,6 +81,8 @@ public UnknownContactPanel(MainFrame window) initCallButton(); + initSMSButton(); + initTextArea(); mainPanel.add(textArea, BorderLayout.CENTER); @@ -168,6 +173,37 @@ public void actionPerformed(ActionEvent e) } } + /** + * Initializes the call button. + */ + private void initSMSButton() + { + if(!parentWindow.hasOperationSet(OperationSetSmsMessaging.class)) + return; + + smsButton = new JButton( + GuiActivator.getResources().getI18NString("service.gui.SEND_SMS")); + + smsButton.setIcon(GuiActivator.getResources() + .getImage("service.gui.icons.SMS_BUTTON_ICON")); + + buttonPanel.add(smsButton); + + smsButton.addActionListener(new ActionListener() + { + @Override + public void actionPerformed(ActionEvent e) + { + final String searchText = parentWindow.getCurrentSearchText(); + + if (searchText == null) + return; + + SMSManager.sendSMS(smsButton, searchText); + } + }); + } + /** * Clicks the call contact button in order to call the unknown contact. */ @@ -245,6 +281,10 @@ public void loadSkin() .getImage("service.gui.icons.ADD_CONTACT_16x16_ICON")); callButton.setIcon(GuiActivator.getResources() .getImage("service.gui.icons.CALL_16x16_ICON")); + + if(smsButton != null) + smsButton.setIcon(GuiActivator.getResources() + .getImage("service.gui.icons.SMS_BUTTON_ICON")); } /** diff --git a/src/net/java/sip/communicator/impl/gui/utils/SMSManager.java b/src/net/java/sip/communicator/impl/gui/utils/SMSManager.java new file mode 100644 index 000000000..43b364662 --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/utils/SMSManager.java @@ -0,0 +1,109 @@ +/* + * Jitsi, 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.utils; + +import net.java.sip.communicator.impl.gui.*; +import net.java.sip.communicator.impl.gui.main.call.*; +import net.java.sip.communicator.impl.gui.main.contactlist.*; +import net.java.sip.communicator.service.contactlist.*; +import net.java.sip.communicator.service.protocol.*; +import net.java.sip.communicator.util.*; +import net.java.sip.communicator.util.account.*; + +import javax.swing.*; +import java.util.*; + +/** + * Handles any sms common actions. + * @author Damian Minkov + */ +public class SMSManager +{ + /** + * The Logger used by the ChatWindowManager class and its + * instances for logging output. + */ + private static final Logger logger + = Logger.getLogger(SMSManager.class); + + /** + * Sends sms, chooses provider and sends the sms. + * @param invoker the component invoker, used to get correct location + * to show popup for choosing provider. + * @param to the destination number + */ + public static void sendSMS(JComponent invoker, final String to) + { + List providers = + AccountUtils + .getRegisteredProviders(OperationSetSmsMessaging.class); + + if(providers.size() == 1) + { + //send + sendSms(providers.get(0), to); + } + else if(providers.size() > 1) + { + ChooseCallAccountPopupMenu chooseAccountDialog + = new ChooseCallAccountPopupMenu( + invoker, + to, + providers) + { + @Override + protected void itemSelected( + Class opSetClass, + ProtocolProviderService protocolProviderService, + String contact, + UIContactImpl uiContact) + { + sendSms(protocolProviderService, to); + } + + @Override + protected void itemSelected( + Class opSetClass, + ProtocolProviderService protocolProviderService, + String contact) + { + sendSms(protocolProviderService, to); + } + }; + + chooseAccountDialog.setLocation(invoker.getLocation()); + chooseAccountDialog.showPopupMenu(); + } + } + + /** + * Sends sms. + * @param protocolProviderService + * @param to + */ + private static void sendSms( + ProtocolProviderService protocolProviderService, + String to) + { + OperationSetSmsMessaging smsMessaging = + protocolProviderService.getOperationSet( + OperationSetSmsMessaging.class); + Contact contact = smsMessaging.getContact(to); + + MetaContact metaContact = GuiActivator.getContactListService() + .findMetaContactByContact(contact); + + if(metaContact == null) + { + logger.error("MetaContact not found for: " + contact); + return; + } + + GuiActivator.getUIService().getChatWindowManager() + .startChat(metaContact, contact, true); + } +} diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java index 3c89cc1b4..136464371 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicInstantMessagingJabberImpl.java @@ -119,6 +119,12 @@ private class TargetAddress private final static String HTML_NAMESPACE = "http://jabber.org/protocol/xhtml-im"; + /** + * List of filters to be used to filter which messages to handle + * current Operation Set. + */ + private List packetFilters = new ArrayList(); + /** * Creates an instance of this operation set. * @param provider a reference to the ProtocolProviderServiceImpl @@ -129,6 +135,11 @@ private class TargetAddress ProtocolProviderServiceJabberImpl provider) { this.jabberProvider = provider; + + packetFilters.add(new GroupMessagePacketFilter()); + packetFilters.add( + new PacketTypeFilter(org.jivesoftware.smack.packet.Message.class)); + provider.addRegistrationStateChangeListener( new RegistrationStateListener()); @@ -169,7 +180,7 @@ public Message createMessage(String content, String contentType, return new MessageJabberImpl(content, contentType, encoding, subject); } - private Message createMessage(String content, String contentType, + Message createMessage(String content, String contentType, String messageUID) { return new MessageJabberImpl(content, contentType, @@ -603,9 +614,8 @@ public void registrationStateChanged(RegistrationStateChangeEvent evt) jabberProvider.getConnection().addPacketListener( smackMessageListener, new AndFilter( - new PacketFilter[]{new GroupMessagePacketFilter(), - new PacketTypeFilter( - org.jivesoftware.smack.packet.Message.class)})); + packetFilters.toArray( + new PacketFilter[packetFilters.size()]))); } else if (evt.getNewState() == RegistrationState.REGISTERED) { @@ -1108,4 +1118,14 @@ public long getInactivityTimeout() { return JID_INACTIVITY_TIMEOUT; } + + /** + * Adds additional filters for incoming messages. To be able to skip some + * messages. + * @param filter to add + */ + public void addMessageFilters(PacketFilter filter) + { + this.packetFilters.add(filter); + } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java index 48afdc792..f44e7c063 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetPersistentPresenceJabberImpl.java @@ -1893,4 +1893,13 @@ private String getAccountPriorityForStatus(String statusName) ProtocolProviderFactory.RESOURCE_PRIORITY + "_" + statusName.replaceAll(" ", "_").toUpperCase()); } + + /** + * Returns the contactlist impl. + * @return + */ + public ServerStoredContactListJabberImpl getSsContactList() + { + return ssContactList; + } } diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ServerStoredContactListJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ServerStoredContactListJabberImpl.java index 295b1c7ad..c9298e831 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/ServerStoredContactListJabberImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/ServerStoredContactListJabberImpl.java @@ -176,7 +176,7 @@ void removeGroupListener(ServerStoredGroupListener listener) * @param group the ContactGroup that has been created/modified/removed * @param eventID the id of the event to generate. */ - private void fireGroupEvent(ContactGroupJabberImpl group, int eventID) + void fireGroupEvent(ContactGroupJabberImpl group, int eventID) { //bail out if no one's listening if(parentOperationSet == null){ diff --git a/src/net/java/sip/communicator/plugin/desktoputil/plaf/SearchFieldUI.java b/src/net/java/sip/communicator/plugin/desktoputil/plaf/SearchFieldUI.java index 53b7d842b..c156190e9 100644 --- a/src/net/java/sip/communicator/plugin/desktoputil/plaf/SearchFieldUI.java +++ b/src/net/java/sip/communicator/plugin/desktoputil/plaf/SearchFieldUI.java @@ -26,6 +26,7 @@ * @author Yana Stamcheva * @author Adam Netocny * @author Marin Dzhigarov + * @author Damian Minkov */ public class SearchFieldUI extends SIPCommTextFieldUI @@ -57,17 +58,43 @@ public static ComponentUI createUI(JComponent c) */ private Image callRolloverIcon; + /** + * The default icon of the sms button. + */ + private Image smsIcon; + + /** + * The pressed icon of the sms button. + */ + private Image smsPressedIcon; + + /** + * The roll over icon of the sms button. + */ + private Image smsRolloverIcon; + /** * The call button tool tip string. */ private final String callString = DesktopUtilActivator.getResources() .getI18NString("service.gui.CALL"); + /** + * The sms button tool tip string. + */ + private final String smsString = DesktopUtilActivator.getResources() + .getI18NString("service.gui.SMS"); + /** * Indicates if the call button is enabled in this search field. */ protected boolean isCallButtonEnabled = true; + /** + * Indicates if the sms button is enabled in this search field. + */ + private boolean isSMSButtonEnabled = false; + /** * Indicates if the call icon is currently visible. */ @@ -83,6 +110,21 @@ public static ComponentUI createUI(JComponent c) */ private boolean isCallMousePressed = false; + /** + * Indicates if the sms icon is currently visible. + */ + protected boolean isSMSIconVisible = false; + + /** + * Indicates if the mouse is currently over the sms button. + */ + private boolean isSMSMouseOver = false; + + /** + * Indicates if the mouse is currently over the sms button. + */ + private boolean isSMSMousePressed = false; + /** * The icon indicating that this is a search field. */ @@ -124,6 +166,29 @@ protected void customPaintBackground(Graphics g) g2.drawImage(searchIcon.getImage(), 3, dy, null); + if (c.getText() != null + && c.getText().length() > 0 + && isSMSButtonEnabled) + { + // Paint sms button. + Rectangle smsRect = getSMSButtonRect(); + int dx = smsRect.x; + dy = smsRect.y; + + if (isSMSMousePressed) + g2.drawImage(smsPressedIcon, dx, dy, null); + else if (isSMSMouseOver) + { + g2.drawImage(smsRolloverIcon, dx, dy, null); + } + else + g2.drawImage(smsIcon, dx, dy, null); + + isSMSIconVisible = true; + } + else + isSMSIconVisible = false; + if (c.getText() != null && c.getText().length() > 0 && isCallButtonEnabled) @@ -176,6 +241,28 @@ protected Rectangle getCallButtonRect() callRolloverIcon.getHeight(null)); } + /** + * Calculates the sms button rectangle. + * + * @return the sms button rectangle + */ + protected Rectangle getSMSButtonRect() + { + Component c = getComponent(); + Rectangle rect = c.getBounds(); + + int dx = getDeleteButtonRect().x - smsRolloverIcon.getWidth(null) - 8; + if(isCallIconVisible) + dx -= callRolloverIcon.getWidth(null) + 4; + + int dy = (rect.y + rect.height) / 2 - smsRolloverIcon.getHeight(null)/2; + + return new Rectangle( dx, + dy, + smsRolloverIcon.getWidth(null), + smsRolloverIcon.getHeight(null)); + } + /** * If we are in the case of disabled delete button, we simply call the * parent implementation of this method, otherwise we recalculate the editor @@ -196,6 +283,9 @@ protected Rectangle getVisibleEditorRect() rect.x += searchIcon.getIconWidth() + 5; rect.width -= (searchIcon.getIconWidth() + 5); + if (isSMSIconVisible) + rect.width -= (smsRolloverIcon.getWidth(null) + 12); + if (isCallIconVisible) rect.width -= (callRolloverIcon.getWidth(null) + 12); else @@ -227,9 +317,33 @@ public void loadSkin() callPressedIcon = r.getImage("service.gui.buttons.SEARCH_CALL_PRESSED_ICON") .getImage(); + } + + if (isSMSButtonEnabled) + { + loadSMSIcons(); + } + + if(isSMSButtonEnabled || isCallButtonEnabled) separatorIcon = r.getImage("service.gui.icons.SEARCH_SEPARATOR").getImage(); - } + } + + /** + * Loads sms icons. + */ + private void loadSMSIcons() + { + ResourceManagementService r = DesktopUtilActivator.getResources(); + + smsIcon + = r.getImage("service.gui.buttons.SEARCH_SMS_ICON").getImage(); + smsRolloverIcon + = r.getImage("service.gui.buttons.SEARCH_SMS_ROLLOVER_ICON") + .getImage(); + smsPressedIcon + = r.getImage("service.gui.buttons.SEARCH_SMS_PRESSED_ICON") + .getImage(); } /** @@ -241,8 +355,8 @@ public void mouseClicked(MouseEvent e) { super.mouseClicked(e); - if(isCallButtonEnabled) - updateCallIcon(e); + if(isCallButtonEnabled || isSMSButtonEnabled) + updateIcon(e); } /** @@ -254,8 +368,8 @@ public void mouseDragged(MouseEvent e) { super.mouseDragged(e); - if(isCallButtonEnabled) - updateCallIcon(e); + if(isCallButtonEnabled || isSMSButtonEnabled) + updateIcon(e); } /** @@ -267,8 +381,8 @@ public void mouseEntered(MouseEvent e) { super.mouseEntered(e); - if(isCallButtonEnabled) - updateCallIcon(e); + if(isCallButtonEnabled || isSMSButtonEnabled) + updateIcon(e); } /** @@ -280,8 +394,8 @@ public void mouseExited(MouseEvent e) { super.mouseExited(e); - if(isCallButtonEnabled) - updateCallIcon(e); + if(isCallButtonEnabled || isSMSButtonEnabled) + updateIcon(e); } /** @@ -293,8 +407,8 @@ public void mouseMoved(MouseEvent e) { super.mouseMoved(e); - if(isCallButtonEnabled) - updateCallIcon(e); + if(isCallButtonEnabled || isSMSButtonEnabled) + updateIcon(e); } @Override @@ -302,8 +416,8 @@ public void mousePressed(MouseEvent e) { super.mousePressed(e); - if(isCallButtonEnabled) - updateCallIcon(e); + if(isCallButtonEnabled || isSMSButtonEnabled) + updateIcon(e); } @Override @@ -311,8 +425,8 @@ public void mouseReleased(MouseEvent e) { super.mouseReleased(e); - if(isCallButtonEnabled) - updateCallIcon(e); + if(isCallButtonEnabled || isSMSButtonEnabled) + updateIcon(e); } /** @@ -336,6 +450,18 @@ public void setCallButtonEnabled(boolean isEnabled) this.isCallButtonEnabled = isEnabled; } + /** + * Enables/disabled the sms button in the search field. + * + * @param isEnabled indicates if the sms button is enabled + */ + public void setSMSButtonEnabled(boolean isEnabled) + { + loadSMSIcons(); + + this.isSMSButtonEnabled = isEnabled; + } + /** * Updates the delete icon, changes the cursor and deletes the content of * the associated text component when the mouse is pressed over the delete @@ -344,13 +470,15 @@ public void setCallButtonEnabled(boolean isEnabled) * @param evt the mouse event that has prompted us to update the delete * icon. */ - protected void updateCallIcon(MouseEvent evt) + protected void updateIcon(MouseEvent evt) { int x = evt.getX(); int y = evt.getY(); Rectangle callButtonRect = getCallButtonRect(); + boolean outsideButtons = true; + if (isCallIconVisible && callButtonRect.contains(x, y)) { JTextComponent c = getComponent(); @@ -359,6 +487,8 @@ protected void updateCallIcon(MouseEvent evt) if (searchText == null) return; + outsideButtons = false; + // Show a tool tip over the call button. getComponent().setToolTipText(callString + " " + searchText); ToolTipManager.sharedInstance().mouseEntered( @@ -380,7 +510,40 @@ protected void updateCallIcon(MouseEvent evt) // Update the default cursor. getComponent().setCursor(Cursor.getDefaultCursor()); } - else + + if (isSMSIconVisible && getSMSButtonRect().contains(x, y)) + { + JTextComponent c = getComponent(); + String searchText = c.getText(); + + if (searchText == null) + return; + + outsideButtons = false; + + // Show a tool tip over the call button. + getComponent().setToolTipText(smsString + " " + searchText); + ToolTipManager.sharedInstance().mouseEntered( + new MouseEvent(c, 0, x, y, + x, y, // X-Y of the mouse for the tool tip + 0, false)); + + if (evt.getID() == MouseEvent.MOUSE_PRESSED) + { + isSMSMouseOver = false; + isSMSMousePressed = true; + } + else + { + isSMSMouseOver = true; + isSMSMousePressed = false; + } + + // Update the default cursor. + getComponent().setCursor(Cursor.getDefaultCursor()); + } + + if(outsideButtons) { // Remove the call button tool tip when the mouse exits the call // button area. @@ -392,6 +555,9 @@ protected void updateCallIcon(MouseEvent evt) isCallMouseOver = false; isCallMousePressed = false; + + isSMSMouseOver = false; + isSMSMousePressed = false; } getComponent().repaint(); diff --git a/src/net/java/sip/communicator/service/protocol/OperationSetSmsMessaging.java b/src/net/java/sip/communicator/service/protocol/OperationSetSmsMessaging.java index e592026fa..25a025f7e 100644 --- a/src/net/java/sip/communicator/service/protocol/OperationSetSmsMessaging.java +++ b/src/net/java/sip/communicator/service/protocol/OperationSetSmsMessaging.java @@ -98,4 +98,19 @@ public void sendSmsMessage(String to, Message message) * false otherwise. */ public boolean isContentTypeSupported(String contentType); + + /** + * Returns the contact to send sms to. + * @param to the number to send sms. + * @return the contact representing the receiver of the sms. + */ + public Contact getContact(String to); + + /** + * Whether the implementation do not know how to send sms to the supplied + * contact and should as for number. + * @param to the contact to send sms. + * @return whether user needs to enter number for the sms recipient. + */ + public boolean askForNumber(Contact to); }