diff --git a/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java b/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java
index cbead6e9a..6f490a7c6 100644
--- a/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java
+++ b/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java
@@ -272,6 +272,72 @@ public Contact getDefaultContact()
return defaultContact;
}
+ /**
+ * Returns a default contact for a specific operation (call,
+ * file transfert, IM ...)
+ *
+ * @param operationSet the operation for which the default contact is needed
+ * @return the default contact for the specified operation.
+ */
+ public Contact getDefaultContact(Class operationSet)
+ {
+ Contact defaultOpSetContact = null;
+ try
+ {
+ // if the current default contact supports the requested information
+ // we use it
+ if (getDefaultContact().getProtocolProvider()
+ .getOperationSet(Class.forName(operationSet.getName()))
+ != null)
+ {
+ defaultOpSetContact = getDefaultContact();
+ }
+ else
+ {
+ for (int i = 0; i < this.protoContacts.size(); i++)
+ {
+ PresenceStatus currentStatus = null;
+ Contact protoContact = (Contact)this.protoContacts.get(i);
+
+ // we filter to care only about contact which support
+ // the needed opset.
+ if (protoContact.getProtocolProvider()
+ .getOperationSet(
+ Class.forName(operationSet.getName())) != null)
+ {
+ PresenceStatus contactStatus
+ = protoContact.getPresenceStatus();
+
+ if (currentStatus != null)
+ {
+ if (currentStatus.getStatus()
+ < contactStatus.getStatus())
+ {
+ currentStatus = contactStatus;
+ defaultOpSetContact = protoContact;
+ }
+ }
+ else
+ {
+ currentStatus = contactStatus;
+ defaultOpSetContact = protoContact;
+ }
+ }
+ }
+ }
+ }
+ catch (ClassNotFoundException ex)
+ {
+ logger.info("cannot find a default " + operationSet.getName()
+ + " contact for "
+ + this, ex);
+ }
+ finally
+ {
+ return defaultOpSetContact;
+ }
+ }
+
/**
* Returns a String identifier (the actual contents is left to
* implementations) that uniquely represents this MetaContact in
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java b/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java
index 0bd384efa..1ad468d48 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallManager.java
@@ -443,18 +443,9 @@ public void updateCallAccountStatus(ProtocolProviderService pps)
*/
private Contact getTelephonyContact(MetaContact metaContact)
{
- Iterator i = metaContact.getContacts();
- while (i.hasNext())
- {
- Contact contact = (Contact) i.next();
-
- OperationSetBasicTelephony telephony = mainFrame
- .getTelephonyOpSet(contact.getProtocolProvider());
+ return metaContact.getDefaultContact(
+ OperationSetBasicTelephony.class);
- if (telephony != null)
- return contact;
- }
- return null;
}
/**
@@ -757,6 +748,19 @@ public void createCall(String contact)
new CreateCallThread(contact, callPanel).start();
}
+ /**
+ * Call the specified contact.
+ * @param contact the contact to call.
+ */
+ public void createCall(Contact contact)
+ {
+ CallPanel callPanel = new CallPanel(this, contact);
+
+ mainFrame.addCallPanel(callPanel);
+
+ new CreateCallThread(contact, callPanel).start();
+ }
+
/**
* Creates a call to the given list of contacts.
*
@@ -784,6 +788,8 @@ private class CreateCallThread
String stringContact;
OperationSetBasicTelephony telephony;
+
+ Contact contact;
public CreateCallThread(String contact, CallPanel callPanel)
{
@@ -803,6 +809,15 @@ public CreateCallThread(Vector contacts, CallPanel callPanel)
telephony = mainFrame.getTelephonyOpSet(selectedCallProvider);
}
+ public CreateCallThread(Contact contact, CallPanel callPanel)
+ {
+ this.contact = contact;
+ this.callPanel = callPanel;
+
+ if (selectedCallProvider != null)
+ telephony = mainFrame.getTelephonyOpSet(selectedCallProvider);
+ }
+
public void run()
{
if (telephony == null)
@@ -810,7 +825,44 @@ public void run()
Call createdCall = null;
- if (contacts != null)
+ if (contact != null)
+ {
+ try
+ {
+ createdCall = telephony.createCall(contact);
+ }
+ catch (OperationFailedException e)
+ {
+ logger.error("The call could not be created: " + e);
+
+ // well, what if we try with the contact own telephony
+ // if it's different
+ OperationSetBasicTelephony tel
+ = (OperationSetBasicTelephony) contact.getProtocolProvider()
+ .getOperationSet(OperationSetBasicTelephony.class);
+
+ if (tel != telephony)
+ logger.info("perpahps it would be better to use "
+ + "the contact own telephony " + tel);
+
+ callPanel.getParticipantPanel(contact.getDisplayName())
+ .setState(e.getMessage());
+
+ removeCallPanelWait(callPanel);
+ }
+
+ // If the call is successfully created we set the created
+ // Call instance to the already existing CallPanel and we
+ // add this call to the active calls.
+ if (createdCall != null)
+ {
+ callPanel.setCall(createdCall,
+ GuiCallParticipantRecord.OUTGOING_CALL);
+
+ activeCalls.put(createdCall, callPanel);
+ }
+ }
+ else if (contacts != null)
{
Contact contact = (Contact) contacts.get(0);
diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
index e4ae2fb37..557a591b1 100644
--- a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java
@@ -70,7 +70,23 @@ public CallPanel(CallManager callManager, Call call, String callType)
this.getViewport().add(mainPanel);
}
-
+
+ public CallPanel(CallManager callManager, Contact contact)
+ {
+ this.callManager = callManager;
+
+ this.mainPanel.setBorder(
+ BorderFactory.createEmptyBorder(20, 10, 20, 10));
+
+ this.title = contact.getDisplayName();
+
+ this.mainPanel.setLayout(new BorderLayout());
+
+ this.addCallParticipant(contact.getDisplayName(), callType);
+
+ this.getViewport().add(mainPanel);
+ }
+
/**
* Creates an instance of CallPanel for the given call and call type.
* @param callManager the CallManager that manages this panel
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatContactPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatContactPanel.java
index 684bf30ff..2b3f7e63a 100644
--- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatContactPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatContactPanel.java
@@ -16,8 +16,10 @@
import net.java.sip.communicator.impl.gui.customcontrols.*;
import net.java.sip.communicator.impl.gui.i18n.*;
import net.java.sip.communicator.impl.gui.lookandfeel.*;
+import net.java.sip.communicator.impl.gui.main.call.*;
import net.java.sip.communicator.impl.gui.main.chat.conference.*;
import net.java.sip.communicator.impl.gui.utils.*;
+import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.protocol.*;
/**
@@ -126,8 +128,31 @@ public ChatContactPanel(ChatPanel chatPanel, ChatContact contact)
this.add(mainPanel, BorderLayout.CENTER);
// Disabled all unused buttons.
- this.callButton.setEnabled(false);
- this.sendFileButton.setEnabled(false);
+
+ ProtocolProviderService pps = chatContact.getProtocolProvider();
+
+ if (chatContact.getSourceContact() instanceof Contact)
+ {
+ Contact c = (Contact) chatContact.getSourceContact();
+ MetaContact m = chatPanel.getChatWindow().getMainFrame()
+ .getContactList().findMetaContactByContact(c);
+
+ if (m.getDefaultContact(OperationSetBasicTelephony.class)
+ == null)
+ this.callButton.setEnabled(false);
+
+ if (m.getDefaultContact(OperationSetFileTransfer.class)
+ == null)
+ this.sendFileButton.setEnabled(false);
+ }
+ else
+ {
+ if (pps.getOperationSet(OperationSetBasicTelephony.class) == null)
+ this.callButton.setEnabled(false);
+
+ if (pps.getOperationSet(OperationSetFileTransfer.class) == null)
+ this.sendFileButton.setEnabled(false);
+ }
//Load the contact photo.
new Thread()
@@ -151,9 +176,6 @@ public void run()
}
}.start();
- ProtocolProviderService pps
- = chatContact.getProtocolProvider();
-
Object contactInfoOpSet
= pps.getOperationSet(OperationSetWebContactInfo.class);
@@ -215,9 +237,33 @@ public void actionPerformed(ActionEvent evt)
{
JButton button = (JButton) evt.getSource();
+ // first, see if the contact with which we chat supports telephony
+ // and call that one. If he don't, we look for the default
+ // telephony contact in its enclosing metacontact
if(button.getName().equals("call"))
{
- //TODO: Implement the call functionality.
+ CallManager cm =
+ chatPanel.getChatWindow().getMainFrame().getCallManager();
+ Object o = chatContact.getSourceContact();
+
+ OperationSetBasicTelephony opSetBT
+ = (OperationSetBasicTelephony) chatContact.getProtocolProvider()
+ .getOperationSet(OperationSetBasicTelephony.class);
+
+ if (opSetBT != null)
+ {
+ if (o instanceof Contact)
+ cm.createCall((Contact)chatContact.getSourceContact());
+ else // hope an appropriate telephony will be used.
+ cm.createCall(((ChatRoomMember) o).getContactAddress());
+ }
+ else if (o instanceof Contact)
+ {
+ MetaContact m = chatPanel.getChatWindow().getMainFrame()
+ .getContactList().findMetaContactByContact((Contact)o);
+ cm.createCall(
+ m.getDefaultContact(OperationSetBasicTelephony.class));
+ }
}
else if(button.getName().equals("info"))
{
diff --git a/src/net/java/sip/communicator/impl/gui/main/chat/ChatSendPanel.java b/src/net/java/sip/communicator/impl/gui/main/chat/ChatSendPanel.java
index 269582405..e4de8d37d 100755
--- a/src/net/java/sip/communicator/impl/gui/main/chat/ChatSendPanel.java
+++ b/src/net/java/sip/communicator/impl/gui/main/chat/ChatSendPanel.java
@@ -99,16 +99,31 @@ public void setStatusMessage(String statusMessage)
{
int stringWidth = GuiUtils.getStringWidth(statusLabel, statusMessage);
- while (stringWidth > statusPanel.getWidth() - 10) {
- if (statusMessage.endsWith("...")) {
- statusMessage = statusMessage.substring(0,
- statusMessage.indexOf("...") - 1).concat("...");
- }
- else {
- statusMessage = statusMessage.substring(0,
- statusMessage.length() - 3).concat("...");
+ int dot3 = GuiUtils.getStringWidth(statusLabel, "... ");
+
+ // first, we avoid to loop if it is useless.
+ if (dot3 >= statusPanel.getWidth())
+ {
+ if (stringWidth > dot3)
+ statusMessage = "...";
+ }
+ else
+ {
+ while ((stringWidth > (statusPanel.getWidth() - dot3))
+ && (statusMessage != "..."))
+ {
+ if (statusMessage.endsWith("..."))
+ {
+ statusMessage = statusMessage.substring(0,
+ statusMessage.indexOf("...") - 1).concat("...");
+ }
+ else
+ {
+ statusMessage = statusMessage.substring(0,
+ statusMessage.length() - 3).concat("...");
+ }
+ stringWidth = GuiUtils.getStringWidth(statusLabel, statusMessage);
}
- stringWidth = GuiUtils.getStringWidth(statusLabel, statusMessage);
}
statusLabel.setText(statusMessage);
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java
index 7e62fdfe4..44a5835c0 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java
@@ -639,8 +639,9 @@ else if ((e.getModifiers() & InputEvent.BUTTON1_MASK) != 0)
contactRightButtonMenu.setInvoker(this);
- contactRightButtonMenu.setLocation(selectedCellPoint.x,
- selectedCellPoint.y + renderer.getHeight());
+ Point p = new Point(e.getPoint());
+ SwingUtilities.convertPointToScreen(p, this);
+ contactRightButtonMenu.setLocation(p);
contactRightButtonMenu.setVisible(true);
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactRightButtonMenu.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactRightButtonMenu.java
index fd6ac10a8..d83ec7afb 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactRightButtonMenu.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactRightButtonMenu.java
@@ -57,7 +57,10 @@ public class ContactRightButtonMenu
private I18NString removeContactString
= Messages.getI18NString("removeContact");
-
+
+ private I18NString callString
+ = Messages.getI18NString("call");
+
private I18NString sendMessageString
= Messages.getI18NString("sendMessage");
@@ -85,6 +88,10 @@ public class ContactRightButtonMenu
private SIPCommMenu removeContactMenu
= new SIPCommMenu(removeContactString.getText());
+ private JMenuItem callItem = new JMenuItem(
+ callString.getText(),
+ new ImageIcon(ImageLoader.getImage(ImageLoader.CALL_16x16_ICON)));
+
private JMenuItem sendMessageItem = new JMenuItem(
sendMessageString.getText(),
new ImageIcon(ImageLoader.getImage(ImageLoader.SEND_MESSAGE_16x16_ICON)));
@@ -284,6 +291,7 @@ private void init() {
}
this.add(sendMessageItem);
+ this.add(callItem);
this.add(sendFileItem);
this.addSeparator();
@@ -308,6 +316,7 @@ private void init() {
this.initPluginComponents();
this.sendMessageItem.setName("sendMessage");
+ this.callItem.setName("call");
this.sendFileItem.setName("sendFile");
this.moveToMenu.setName("moveToGroup");
this.addSubcontactMenu.setName("addSubcontact");
@@ -316,13 +325,22 @@ private void init() {
this.userInfoMenu.setName("userInfo");
this.sendMessageItem.addActionListener(this);
+ this.callItem.addActionListener(this);
this.sendFileItem.addActionListener(this);
this.renameContactItem.addActionListener(this);
this.viewHistoryItem.addActionListener(this);
this.userInfoMenu.addActionListener(this);
// Disable all menu items that do nothing.
- this.sendFileItem.setEnabled(false);
+ if (contactItem.getDefaultContact(OperationSetFileTransfer.class)
+ == null)
+ this.sendFileItem.setEnabled(false);
+ if (contactItem.getDefaultContact(OperationSetBasicTelephony.class)
+ == null)
+ this.callItem.setEnabled(false);
+ if (contactItem.getDefaultContact(OperationSetBasicInstantMessaging.class)
+ == null)
+ this.sendMessageItem.setEnabled(false);
}
private void initPluginComponents()
@@ -350,6 +368,7 @@ private void initPluginComponents()
private void initMnemonics()
{
this.sendMessageItem.setMnemonic(sendMessageString.getMnemonic());
+ this.callItem.setMnemonic(sendMessageString.getMnemonic());
this.sendFileItem.setMnemonic(sendFileString.getMnemonic());
this.moveToMenu.setMnemonic(moveToString.getMnemonic());
this.addSubcontactMenu.setMnemonic(addSubcontactString.getMnemonic());
@@ -369,6 +388,7 @@ public void actionPerformed(ActionEvent e){
JMenuItem menuItem = (JMenuItem) e.getSource();
String itemName = menuItem.getName();
String itemText = menuItem.getText();
+ Contact cont = null;
if (itemName.startsWith(addSubcontactPrefix)) {
@@ -396,6 +416,19 @@ else if (itemName.equalsIgnoreCase("sendMessage"))
SwingUtilities.invokeLater(clistPanel.new RunMessageWindow(
contactItem));
}
+ else if (itemName.equalsIgnoreCase("call"))
+ {
+ cont = contactItem.getDefaultContact(
+ OperationSetBasicTelephony.class);
+ if (cont != null)
+ {
+ Vector v = new Vector();
+ v.add(cont);
+ mainFrame.getCallManager().createCall(v);
+ // wow, it's really tricky, I wonder there isn't a simple method
+ // CallManager#createCall(Contact contact);
+ }
+ }
else if (itemName.equalsIgnoreCase("sendFile"))
{
// disabled
diff --git a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
index 21c5a617a..ccd413bb3 100644
--- a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
+++ b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java
@@ -768,6 +768,13 @@ public class ImageLoader {
public static final ImageID SEND_MESSAGE_16x16_ICON
= new ImageID("SEND_MESSAGE_16x16_ICON");
+ /**
+ * Call 16x16 image.
+ * //TODO : change to an appropriate logo
+ */
+ public static final ImageLoader.ImageID CALL_16x16_ICON
+ = new ImageID("SIP_COMMUNICATOR_LOGO");
+
/**
* Delete 16x16 image.
*/
@@ -933,6 +940,7 @@ public class ImageLoader {
public static final ImageID SMILEY12 = new ImageID("SMILEY12");
+
/**
* Load default smilies pack.
*
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
index 7a55758f6..3ab551539 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetBasicTelephonyJabberImpl.java
@@ -107,12 +107,9 @@ public void registrationStateChanged(RegistrationStateChangeEvent evt)
{
if ((evt.getNewState() == RegistrationState.REGISTERED))
{
- // NOTE: a null stun server is provided here _intentionally_
- // it may cause some exceptions, it's temporary
- logger.warn("warning: we will use a null stun server ***");
transportManager = new ICETransportManager(
protocolProvider.getConnection(),
- null, 3478);
+ "stun.iptel.org", 3478);
jingleManager = new JingleManager(
protocolProvider.getConnection(),
@@ -598,11 +595,7 @@ public void beforeChange(JingleNegotiator.State oldState
, JingleNegotiator.State newState)
throws JingleNegotiator.JingleException
{
- if (newState instanceof IncomingJingleSession.Accepting)
- {}
- else if (newState instanceof IncomingJingleSession.Pending)
- {}
- else if (newState instanceof IncomingJingleSession.Active)
+ if (newState instanceof IncomingJingleSession.Active)
{
JingleSession session = (JingleSession) newState.getNegotiator();
@@ -650,22 +643,6 @@ else if (newState instanceof OutgoingJingleSession.Active)
}
callParticipant.setState(CallParticipantState.CONNECTED);
}
-// else if (newState instanceof MediaNegotiator.Inviting)
-// {}
-// else if (newState instanceof MediaNegotiator.Pending)
-// {}
-// else if (newState instanceof MediaNegotiator.Accepting)
-// {}
-// else if (newState instanceof MediaNegotiator.Active)
-// {}
-// else if (newState instanceof TransportNegotiator.Inviting)
-// {}
-// else if (newState instanceof TransportNegotiator.Pending)
-// {}
-// else if (newState instanceof TransportNegotiator.Accepting)
-// {}
-// else if (newState instanceof TransportNegotiator.Active)
-// {}
if ((newState == null) && (oldState != null))
{ //hanging
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java
index 52d854c94..d05cd313d 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/OperationSetMultiUserChatJabberImpl.java
@@ -266,6 +266,11 @@ public ChatRoom findRoom(String roomName)
//make sure we are connected and multichat is supported.
assertSupportedAndConnected();
+// return (ChatRoom)chatRoomCache.get(roomName);
+
+// XXX is the following behaviour correct ? in the test if finding
+// an unexisting room return anything other than null, the test fails.
+
//first check whether we have already initialized the room.
ChatRoom room = (ChatRoom)chatRoomCache.get(roomName);
diff --git a/src/net/java/sip/communicator/service/contactlist/MetaContact.java b/src/net/java/sip/communicator/service/contactlist/MetaContact.java
index 8330f6f44..09a23272e 100644
--- a/src/net/java/sip/communicator/service/contactlist/MetaContact.java
+++ b/src/net/java/sip/communicator/service/contactlist/MetaContact.java
@@ -30,6 +30,15 @@ public interface MetaContact extends Comparable
*/
public Contact getDefaultContact();
+ /**
+ * Returns the default protocol specific Contact to use with this
+ * MetaContact for a precise operation (IM, call, ...).
+ *
+ * @param operationSet the operation for which the default contact is needed
+ * @return the default contact for the specified operation.
+ */
+ public Contact getDefaultContact(Class operationSet);
+
/**
* Returns a java.util.Iterator with all protocol specific
* Contacts encapsulated by this MetaContact.