aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator
diff options
context:
space:
mode:
authorDamian Minkov <damencho@jitsi.org>2012-08-17 08:43:13 +0000
committerDamian Minkov <damencho@jitsi.org>2012-08-17 08:43:13 +0000
commitd100493139446a9fc27e40932b1bb9dabd1e0a8f (patch)
treebd4e3daac0c8923d0622967654373f32bf7f43ff /src/net/java/sip/communicator
parent5012fc910a3cfe22d82ba13125c394e0555e9a5c (diff)
downloadjitsi-d100493139446a9fc27e40932b1bb9dabd1e0a8f.zip
jitsi-d100493139446a9fc27e40932b1bb9dabd1e0a8f.tar.gz
jitsi-d100493139446a9fc27e40932b1bb9dabd1e0a8f.tar.bz2
Adds get/set data to SourceContacts. Moves custom buttons to ExternalContactSource. Adds listener to refresh contact sources.
Diffstat (limited to 'src/net/java/sip/communicator')
-rw-r--r--src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java4
-rw-r--r--src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java127
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java2
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java3
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/ExternalContactSource.java308
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java249
-rw-r--r--src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java2
-rw-r--r--src/net/java/sip/communicator/service/contactsource/SourceContact.java32
-rw-r--r--src/net/java/sip/communicator/service/contactsource/contactsource.manifest.mf1
-rw-r--r--src/net/java/sip/communicator/util/DataObject.java139
10 files changed, 519 insertions, 348 deletions
diff --git a/src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java b/src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java
index d2ff179..9144727 100644
--- a/src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java
+++ b/src/net/java/sip/communicator/impl/callhistory/CallHistorySourceContact.java
@@ -20,7 +20,9 @@ import net.java.sip.communicator.util.*;
*
* @author Yana Stamcheva
*/
-public class CallHistorySourceContact implements SourceContact
+public class CallHistorySourceContact
+ extends DataObject
+ implements SourceContact
{
/**
* The parent <tt>CallHistoryContactSource</tt>, where this contact is
diff --git a/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java b/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java
index 1397b36..8b1573d 100644
--- a/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java
+++ b/src/net/java/sip/communicator/impl/contactlist/MetaContactImpl.java
@@ -23,6 +23,7 @@ import org.jitsi.service.fileaccess.*;
* @author Lubomir Marinov
*/
public class MetaContactImpl
+ extends DataObject
implements MetaContact
{
/**
@@ -121,22 +122,6 @@ public class MetaContactImpl
};
/**
- * The user-specific key-value associations stored in this instance.
- * <p>
- * Like the Widget implementation of Eclipse SWT, the storage type takes
- * into account that there are likely to be many
- * <code>MetaContactImpl</code> instances and <code>Map</code>s are thus
- * likely to impose increased memory use. While an array may very well
- * perform worse than a <code>Map</code> with respect to search, the
- * mechanism of user-defined key-value associations explicitly states that
- * it is not guaranteed to be optimized for any particular use and only
- * covers the most basic cases and performance-savvy code will likely
- * implement a more optimized solution anyway.
- * </p>
- */
- private Object[] data;
-
- /**
* Creates new meta contact with a newly generated meta contact UID.
*/
MetaContactImpl()
@@ -1251,98 +1236,6 @@ public class MetaContactImpl
}
/**
- * Implements {@link MetaContact#getData(Object)}. Gets the user data
- * associated with this instance and a specific key.
- *
- * @param key the key of the user data associated with this instance to be
- * retrieved
- * @return an <tt>Object</tt> which represents the value associated with
- * this instance and the specified <tt>key</tt>; <tt>null</tt> if no
- * association with the specified <tt>key</tt> exists in this instance
- * @see MetaContact#getData(Object)
- */
- public Object getData(Object key)
- {
- if (key == null)
- throw new NullPointerException("key");
-
- int index = dataIndexOf(key);
-
- return (index == -1) ? null : data[index + 1];
- }
-
- /**
- * Implements {@link MetaContact#setData(Object, Object)}. Sets a
- * user-specific association in this instance in the form of a key-value
- * pair. If the specified <tt>key</tt> is already associated in this
- * instance with a value, the existing value is overwritten with the
- * specified <tt>value</tt>.
- * <p>
- * The user-defined association created by this method and stored in this
- * instance is not serialized by this instance and is thus only meant for
- * runtime use.
- * </p>
- * <p>
- * The storage of the user data is implementation-specific and is thus not
- * guaranteed to be optimized for execution time and memory use.
- * </p>
- *
- * @param key the key to associate in this instance with the specified value
- * @param value the value to be associated in this instance with the
- * specified <tt>key</tt>
- * @see MetaContact#setData(Object, Object)
- */
- public void setData(Object key, Object value)
- {
- if (key == null)
- throw new NullPointerException("key");
-
- int index = dataIndexOf(key);
-
- if (index == -1)
- {
-
- /*
- * If value is null, remove the association with key (or just don't
- * add it).
- */
- if (data == null)
- {
- if (value != null)
- data = new Object[] { key, value };
- }
- else if (value == null)
- {
- int length = data.length - 2;
-
- if (length > 0)
- {
- Object[] newData = new Object[length];
-
- System.arraycopy(data, 0, newData, 0, index);
- System.arraycopy(
- data, index + 2, newData, index, length - index);
- data = newData;
- }
- else
- data = null;
- }
- else
- {
- int length = data.length;
- Object[] newData = new Object[length + 2];
-
- System.arraycopy(data, 0, newData, 0, length);
- data = newData;
- data[length++] = key;
- data[length++] = value;
- }
- }
- else
- data[index + 1] = value;
- }
-
- /**
* Updates the capabilities for the given contact.
*
* @param contact the <tt>Contact</tt>, which capabilities have changed
@@ -1432,24 +1325,6 @@ public class MetaContactImpl
}
/**
- * Determines the index in <code>#data</code> of a specific key.
- *
- * @param key
- * the key to retrieve the index in <code>#data</code> of
- * @return the index in <code>#data</code> of the specified <code>key</code>
- * if it is contained; <tt>-1</tt> if <code>key</code> is not
- * contained in <code>#data</code>
- */
- private int dataIndexOf(Object key)
- {
- if (data != null)
- for (int index = 0; index < data.length; index += 2)
- if (key.equals(data[index]))
- return index;
- return -1;
- }
-
- /**
* Gets the sync lock for use when modifying {@link #parentGroup}.
*
* @return the sync lock for use when modifying {@link #parentGroup}
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java
index c66bb8f..aa36661 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java
@@ -251,6 +251,8 @@ public class SearchFilter
false,
true);
}
+ else
+ ExternalContactSource.removeUIContact(sourceContact);
}
/**
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java
index c7fd377..29c9b71 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java
@@ -195,7 +195,10 @@ public class TreeContactList
sourceUI.getUIGroup(), false);
}
else
+ {
+ ExternalContactSource.removeUIContact(sourceContact);
uiContact = null;
+ }
}
/**
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/ExternalContactSource.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/ExternalContactSource.java
index afa0ee9..d60a214 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/ExternalContactSource.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/ExternalContactSource.java
@@ -8,8 +8,18 @@ package net.java.sip.communicator.impl.gui.main.contactlist.contactsource;
import javax.swing.*;
+import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.main.contactlist.*;
import net.java.sip.communicator.service.contactsource.*;
+import net.java.sip.communicator.service.customcontactactions.*;
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.util.swing.*;
+import org.osgi.framework.*;
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.util.List;
/**
* The <tt>ExternalContactSource</tt> is the UI abstraction of the
@@ -20,6 +30,13 @@ import net.java.sip.communicator.service.contactsource.*;
public class ExternalContactSource
{
/**
+ * The data key of the SourceContactDescriptor object used to store a
+ * reference to this object in its corresponding Sourcecontact.
+ */
+ public static final String UI_CONTACT_DATA_KEY
+ = SourceUIContact.class.getName() + ".uiContactDescriptor";
+
+ /**
* The <tt>SourceUIGroup</tt> containing all contacts from this source.
*/
private final SourceUIGroup sourceUIGroup;
@@ -30,6 +47,17 @@ public class ExternalContactSource
private final ContactSourceService contactSource;
/**
+ * The current custom action contact.
+ */
+ private static SourceContact customActionContact;
+
+ /**
+ * The list of action buttons for this source contact.
+ */
+ private static Map<ContactAction<SourceContact>, SIPCommButton>
+ customActionButtons;
+
+ /**
* Creates an <tt>ExternalContactSource</tt> based on the given
* <tt>ContactSourceService</tt>.
*
@@ -75,7 +103,222 @@ public class ExternalContactSource
*/
public UIContact createUIContact(SourceContact sourceContact)
{
- return new SourceUIContact(sourceContact, sourceUIGroup);
+ SourceUIContact descriptor
+ = new SourceUIContact(sourceContact, sourceUIGroup);
+
+ sourceContact.setData(UI_CONTACT_DATA_KEY, descriptor);
+
+ return descriptor;
+ }
+
+ /**
+ * Removes the <tt>UIContact</tt> from the given <tt>sourceContact</tt>.
+ * @param sourceContact the <tt>SourceContact</tt>, which corresponding UI
+ * contact we would like to remove
+ */
+ public static void removeUIContact(SourceContact sourceContact)
+ {
+ sourceContact.setData(UI_CONTACT_DATA_KEY, null);
+ }
+
+ /**
+ * Returns the <tt>UIContact</tt> corresponding to the given
+ * <tt>SourceContact</tt>.
+ * @param sourceContact the <tt>SourceContact</tt>, which corresponding UI
+ * contact we're looking for
+ * @return the <tt>UIContact</tt> corresponding to the given
+ * <tt>MetaContact</tt>
+ */
+ public static UIContact getUIContact(SourceContact sourceContact)
+ {
+ return (UIContact) sourceContact.getData(UI_CONTACT_DATA_KEY);
+ }
+
+ /**
+ * Returns all custom action buttons for this meta contact.
+ *
+ * @return a list of all custom action buttons for this meta contact
+ */
+ public static Collection<SIPCommButton> getContactCustomActionButtons(
+ final SourceContact sourceContact)
+ {
+ customActionContact = sourceContact;
+
+ if (customActionButtons == null)
+ initCustomActionButtons();
+
+ Iterator<ContactAction<SourceContact>> customActionsIter
+ = customActionButtons.keySet().iterator();
+
+ Collection<SIPCommButton> availableCustomActionButtons
+ = new LinkedList<SIPCommButton>();
+
+ while (customActionsIter.hasNext())
+ {
+ ContactAction<SourceContact> contactAction
+ = customActionsIter.next();
+
+ SIPCommButton actionButton = customActionButtons.get(contactAction);
+
+ if (isContactActionVisible( contactAction,
+ sourceContact))
+ {
+ availableCustomActionButtons.add(actionButton);
+ }
+ }
+
+ return availableCustomActionButtons;
+ }
+
+ /**
+ * Indicates if the given <tt>ContactAction</tt> should be visible for the
+ * given <tt>SourceContact</tt>.
+ *
+ * @param contactAction the <tt>ContactAction</tt> to verify
+ * if the given action should be visible
+ * @return <tt>true</tt> if the given <tt>ContactAction</tt> is visible for
+ * the given <tt>SourceContact</tt>, <tt>false</tt> - otherwise
+ */
+ private static boolean isContactActionVisible(
+ ContactAction<SourceContact> contactAction,
+ SourceContact contact)
+ {
+ if (contactAction.isVisible(contact))
+ return true;
+
+ return false;
+ }
+
+ /**
+ * Initializes custom action buttons for this contact source.
+ */
+ private static void initCustomActionButtons()
+ {
+ customActionButtons = new LinkedHashMap
+ <ContactAction<SourceContact>, SIPCommButton>();
+
+ CustomContactActionsChangeListener changeListener
+ = new CustomContactActionsChangeListener();
+
+ for (CustomContactActionsService<SourceContact> ccas
+ : getContactActionsServices())
+ {
+ ccas.addCustomContactActionsListener(changeListener);
+
+ Iterator<ContactAction<SourceContact>> actionIterator
+ = ccas.getCustomContactActions();
+
+ while (actionIterator!= null && actionIterator.hasNext())
+ {
+ final ContactAction<SourceContact> ca = actionIterator.next();
+
+ SIPCommButton actionButton = customActionButtons.get(ca);
+
+ if (actionButton == null)
+ {
+ actionButton = new SIPCommButton(
+ new ImageIcon(ca.getIcon()).getImage(),
+ new ImageIcon(ca.getPressedIcon()).getImage(),
+ null);
+
+ actionButton.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent e)
+ {
+ List<UIContactDetail> contactDetails
+ = SourceUIContact.getContactDetails(
+ customActionContact);
+ contactDetails.add(
+ new SourceUIContact.SourceContactDetail(
+ customActionContact.getDisplayName(),
+ customActionContact));
+
+ UIContactDetailCustomAction contactAction
+ = new UIContactDetailCustomAction(ca);
+
+ if (contactDetails.size() > 1)
+ {
+ ChooseUIContactDetailPopupMenu
+ detailsPopupMenu
+ = new ChooseUIContactDetailPopupMenu(
+ (JButton) e.getSource(),
+ contactDetails,
+ contactAction);
+
+ detailsPopupMenu.showPopupMenu();
+ }
+ else if (contactDetails.size() == 1)
+ {
+ JButton button = (JButton) e.getSource();
+ Point location = new Point(button.getX(),
+ button.getY() + button.getHeight());
+
+ SwingUtilities.convertPointToScreen(
+ location, GuiActivator.getContactList());
+
+ location.y = location.y
+ + GuiActivator.getContactList()
+ .getPathBounds(
+ GuiActivator.getContactList()
+ .getSelectionPath()).y;
+
+ contactAction.actionPerformed(
+ contactDetails.get(0),
+ location.x,
+ location.y);
+ }
+ }
+ });
+
+ customActionButtons.put(ca, actionButton);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns a list of all custom contact action services.
+ *
+ * @return a list of all custom contact action services.
+ */
+ @SuppressWarnings ("unchecked")
+ private static List<CustomContactActionsService<SourceContact>>
+ getContactActionsServices()
+ {
+ List<CustomContactActionsService<SourceContact>>
+ contactActionsServices
+ = new ArrayList<CustomContactActionsService
+ <SourceContact>>();
+
+ ServiceReference[] serRefs = null;
+ try
+ {
+ // get all registered provider factories
+ serRefs
+ = GuiActivator.bundleContext.getServiceReferences(
+ CustomContactActionsService.class.getName(), null);
+ }
+ catch (InvalidSyntaxException e)
+ {}
+
+ if (serRefs != null)
+ {
+ for (ServiceReference serRef : serRefs)
+ {
+ CustomContactActionsService<?> customActionService
+ = (CustomContactActionsService<?>)
+ GuiActivator.bundleContext.getService(serRef);
+
+ if (customActionService.getContactSourceClass()
+ .equals(SourceContact.class))
+ {
+ contactActionsServices.add(
+ (CustomContactActionsService<SourceContact>)
+ customActionService);
+ }
+ }
+ }
+ return contactActionsServices;
}
/**
@@ -209,4 +452,67 @@ public class ExternalContactSource
return null;
}
}
+
+ /**
+ * Listens for updates on actions and when received update the source contact.
+ */
+ private static class CustomContactActionsChangeListener
+ implements CustomContactActionsListener
+ {
+ /**
+ * Update for custom action has occurred.
+ * @param event the event containing the source which was updated.
+ */
+ public void updated(CustomContactActionsEvent event)
+ {
+ if(!(event.getSource() instanceof SourceContact))
+ return;
+
+ ContactNode contactNode
+ = getUIContact((SourceContact)event.getSource()).getContactNode();
+
+ if (contactNode != null)
+ GuiActivator.getContactList().nodeChanged(contactNode);
+ }
+ }
+
+ /**
+ * An implementation of <tt>UIContactDetail</tt> for a custom action.
+ */
+ private static class UIContactDetailCustomAction
+ implements UIContactDetailAction
+ {
+ /**
+ * The contact action.
+ */
+ private final ContactAction<SourceContact> contactAction;
+
+ /**
+ * Creates an instance of <tt>UIContactDetailCustomAction</tt>.
+ */
+ public UIContactDetailCustomAction(
+ ContactAction<SourceContact> contactAction)
+ {
+ this.contactAction = contactAction;
+ }
+
+ /**
+ * Performs the action on button click.
+ */
+ public void actionPerformed(UIContactDetail contactDetail, int x, int y)
+ {
+ try
+ {
+ contactAction.actionPerformed(
+ (SourceContact) contactDetail.getDescriptor(), x, y);
+ }
+ catch (OperationFailedException e)
+ {
+ new ErrorDialog(null,
+ GuiActivator.getResources()
+ .getI18NString("service.gui.ERROR"),
+ e.getMessage());
+ }
+ }
+ }
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java
index 4d9c6b1..0098beb 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/SourceUIContact.java
@@ -7,7 +7,6 @@
package net.java.sip.communicator.impl.gui.main.contactlist.contactsource;
import java.awt.*;
-import java.awt.event.*;
import java.util.*;
import java.util.List;
@@ -55,12 +54,6 @@ public class SourceUIContact
private final List<String> searchStrings = new LinkedList<String>();
/**
- * The list of action buttons for this source contact.
- */
- private Map<ContactAction<SourceContact>, SIPCommButton>
- customActionButtons;
-
- /**
* Creates an instance of <tt>SourceUIContact</tt> by specifying the
* <tt>SourceContact</tt>, on which this abstraction is based and the
* parent <tt>UIGroup</tt>.
@@ -203,6 +196,18 @@ public class SourceUIContact
*/
public List<UIContactDetail> getContactDetails()
{
+ return getContactDetails(sourceContact);
+ }
+
+ /**
+ * Returns a list of all contained <tt>UIContactDetail</tt>s.
+ *
+ * @param sourceContact the source contact we get details from.
+ * @return a list of all contained <tt>UIContactDetail</tt>s
+ */
+ public static List<UIContactDetail> getContactDetails(
+ SourceContact sourceContact)
+ {
List<UIContactDetail> resultList
= new LinkedList<UIContactDetail>();
@@ -213,7 +218,7 @@ public class SourceUIContact
{
ContactDetail detail = details.next();
- resultList.add(new SourceContactDetail(detail, null));
+ resultList.add(new SourceContactDetail(detail, null, sourceContact));
}
return resultList;
}
@@ -244,7 +249,8 @@ public class SourceUIContact
if ((supportedOperationSets != null)
&& supportedOperationSets.contains(opSetClass))
{
- resultList.add(new SourceContactDetail(detail, opSetClass));
+ resultList.add(new SourceContactDetail(
+ detail, opSetClass, sourceContact));
}
}
return resultList;
@@ -277,13 +283,15 @@ public class SourceUIContact
public void setContactNode(ContactNode contactNode)
{
this.contactNode = contactNode;
+ if (contactNode == null)
+ ExternalContactSource.removeUIContact(sourceContact);
}
/**
* The implementation of the <tt>UIContactDetail</tt> interface for the
* external source <tt>ContactDetail</tt>s.
*/
- private class SourceContactDetail extends UIContactDetail
+ protected static class SourceContactDetail extends UIContactDetail
{
/**
* Creates an instance of <tt>SourceContactDetail</tt> by specifying
@@ -294,7 +302,8 @@ public class SourceUIContact
* preferred protocol provider
*/
public SourceContactDetail( ContactDetail detail,
- Class<? extends OperationSet> opSetClass)
+ Class<? extends OperationSet> opSetClass,
+ SourceContact sourceContact)
{
super( detail.getContactAddress(),
detail.getContactAddress(),
@@ -324,8 +333,10 @@ public class SourceUIContact
* for it.
*
* @param displayName the display name
+ * @param sourceContact the source contact
*/
- public SourceContactDetail(String displayName)
+ public SourceContactDetail(String displayName,
+ SourceContact sourceContact)
{
super( displayName,
displayName,
@@ -461,218 +472,16 @@ public class SourceUIContact
}
/**
- * Returns all custom action buttons for this meta contact.
+ * Returns all custom action buttons for this notification contact.
*
- * @return a list of all custom action buttons for this meta contact
+ * @return a list of all custom action buttons for this notification contact
*/
public Collection<SIPCommButton> getContactCustomActionButtons()
{
- if (customActionButtons == null)
- initCustomActionButtons();
-
- Iterator<ContactAction<SourceContact>> customActionsIter
- = customActionButtons.keySet().iterator();
-
- Collection<SIPCommButton> availableCustomActionButtons
- = new LinkedList<SIPCommButton>();
-
- while (customActionsIter.hasNext())
- {
- ContactAction<SourceContact> contactAction
- = customActionsIter.next();
-
- SIPCommButton actionButton = customActionButtons.get(contactAction);
-
- if (isContactActionVisible( contactAction,
- sourceContact))
- {
- availableCustomActionButtons.add(actionButton);
- }
- }
-
- return availableCustomActionButtons;
- }
-
- /**
- * Indicates if the given <tt>ContactAction</tt> should be visible for the
- * given <tt>SourceContact</tt>.
- *
- * @param contactAction the <tt>ContactAction</tt> to verify
- * if the given action should be visible
- * @return <tt>true</tt> if the given <tt>ContactAction</tt> is visible for
- * the given <tt>SourceContact</tt>, <tt>false</tt> - otherwise
- */
- private static boolean isContactActionVisible(
- ContactAction<SourceContact> contactAction,
- SourceContact contact)
- {
- if (contactAction.isVisible(contact))
- return true;
-
- return false;
- }
-
- /**
- * Initializes custom action buttons for this contact source.
- */
- private void initCustomActionButtons()
- {
- customActionButtons = new LinkedHashMap
- <ContactAction<SourceContact>, SIPCommButton>();
-
- for (CustomContactActionsService<SourceContact> ccas
- : getContactActionsServices())
- {
- Iterator<ContactAction<SourceContact>> actionIterator
- = ccas.getCustomContactActions();
-
- while (actionIterator!= null && actionIterator.hasNext())
- {
- final ContactAction<SourceContact> ca = actionIterator.next();
-
- SIPCommButton actionButton = customActionButtons.get(ca);
-
- if (actionButton == null)
- {
- actionButton = new SIPCommButton(
- new ImageIcon(ca.getIcon()).getImage(),
- new ImageIcon(ca.getPressedIcon()).getImage(),
- null);
-
- actionButton.addActionListener(new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- List<UIContactDetail> contactDetails
- = getContactDetails();
- contactDetails.add(new SourceContactDetail(
- sourceContact.getDisplayName()));
-
- UIContactDetailCustomAction contactAction
- = new UIContactDetailCustomAction(ca);
-
- if (contactDetails.size() > 1)
- {
- ChooseUIContactDetailPopupMenu
- detailsPopupMenu
- = new ChooseUIContactDetailPopupMenu(
- (JButton) e.getSource(),
- contactDetails,
- contactAction);
-
- detailsPopupMenu.showPopupMenu();
- }
- else if (contactDetails.size() == 1)
- {
- JButton button = (JButton) e.getSource();
- Point location = new Point(button.getX(),
- button.getY() + button.getHeight());
-
- SwingUtilities.convertPointToScreen(
- location, GuiActivator.getContactList());
-
- location.y = location.y
- + GuiActivator.getContactList()
- .getPathBounds(
- GuiActivator.getContactList()
- .getSelectionPath()).y;
-
- contactAction.actionPerformed(
- contactDetails.get(0),
- location.x,
- location.y);
- }
- }
- });
-
- customActionButtons.put(ca, actionButton);
- }
- }
- }
- }
-
- /**
- * Returns a list of all custom contact action services.
- *
- * @return a list of all custom contact action services.
- */
- @SuppressWarnings ("unchecked")
- private static List<CustomContactActionsService<SourceContact>>
- getContactActionsServices()
- {
- List<CustomContactActionsService<SourceContact>>
- contactActionsServices
- = new ArrayList<CustomContactActionsService
- <SourceContact>>();
-
- ServiceReference[] serRefs = null;
- try
- {
- // get all registered provider factories
- serRefs
- = GuiActivator.bundleContext.getServiceReferences(
- CustomContactActionsService.class.getName(), null);
- }
- catch (InvalidSyntaxException e)
- {}
-
- if (serRefs != null)
- {
- for (ServiceReference serRef : serRefs)
- {
- CustomContactActionsService<?> customActionService
- = (CustomContactActionsService<?>)
- GuiActivator.bundleContext.getService(serRef);
-
- if (customActionService.getContactSourceClass()
- .equals(SourceContact.class))
- {
- contactActionsServices.add(
- (CustomContactActionsService<SourceContact>)
- customActionService);
- }
- }
- }
- return contactActionsServices;
- }
+ if (sourceContact != null)
+ return ExternalContactSource
+ .getContactCustomActionButtons(sourceContact);
- /**
- * An implementation of <tt>UIContactDetail</tt> for a custom action.
- */
- private static class UIContactDetailCustomAction
- implements UIContactDetailAction
- {
- /**
- * The contact action.
- */
- private final ContactAction<SourceContact> contactAction;
-
- /**
- * Creates an instance of <tt>UIContactDetailCustomAction</tt>.
- */
- public UIContactDetailCustomAction(
- ContactAction<SourceContact> contactAction)
- {
- this.contactAction = contactAction;
- }
-
- /**
- * Performs the action on button click.
- */
- public void actionPerformed(UIContactDetail contactDetail, int x, int y)
- {
- try
- {
- contactAction.actionPerformed(
- (SourceContact) contactDetail.getDescriptor(), x, y);
- }
- catch (OperationFailedException e)
- {
- new ErrorDialog(null,
- GuiActivator.getResources()
- .getI18NString("service.gui.ERROR"),
- e.getMessage());
- }
- }
+ return null;
}
}
diff --git a/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java b/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java
index cf84e06..ab382ee 100644
--- a/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java
+++ b/src/net/java/sip/communicator/service/contactsource/GenericSourceContact.java
@@ -9,6 +9,7 @@ package net.java.sip.communicator.service.contactsource;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.util.*;
/**
* Implements a generic <tt>SourceContact</tt> for the purposes of the support
@@ -17,6 +18,7 @@ import net.java.sip.communicator.service.protocol.*;
* @author Lyubomir Marinov
*/
public class GenericSourceContact
+ extends DataObject
implements SourceContact
{
/**
diff --git a/src/net/java/sip/communicator/service/contactsource/SourceContact.java b/src/net/java/sip/communicator/service/contactsource/SourceContact.java
index 9d4536e..d013d7f 100644
--- a/src/net/java/sip/communicator/service/contactsource/SourceContact.java
+++ b/src/net/java/sip/communicator/service/contactsource/SourceContact.java
@@ -91,4 +91,36 @@ public interface SourceContact
* @return the byte array of the image or null if no image is available
*/
public byte[] getImage();
+
+ /**
+ * Gets the user data associated with this instance and a specific key.
+ *
+ * @param key the key of the user data associated with this instance to be
+ * retrieved
+ * @return an <tt>Object</tt> which represents the value associated with
+ * this instance and the specified <tt>key</tt>; <tt>null</tt> if no
+ * association with the specified <tt>key</tt> exists in this instance
+ */
+ public Object getData(Object key);
+
+ /**
+ * Sets a user-specific association in this instance in the form of a
+ * key-value pair. If the specified <tt>key</tt> is already associated in
+ * this instance with a value, the existing value is overwritten with the
+ * specified <tt>value</tt>.
+ * <p>
+ * The user-defined association created by this method and stored in this
+ * instance is not serialized by this instance and is thus only meant for
+ * runtime use.
+ * </p>
+ * <p>
+ * The storage of the user data is implementation-specific and is thus not
+ * guaranteed to be optimized for execution time and memory use.
+ * </p>
+ *
+ * @param key the key to associate in this instance with the specified value
+ * @param value the value to be associated in this instance with the
+ * specified <tt>key</tt>
+ */
+ public void setData(Object key, Object value);
}
diff --git a/src/net/java/sip/communicator/service/contactsource/contactsource.manifest.mf b/src/net/java/sip/communicator/service/contactsource/contactsource.manifest.mf
index 7b06df7..4ae0097 100644
--- a/src/net/java/sip/communicator/service/contactsource/contactsource.manifest.mf
+++ b/src/net/java/sip/communicator/service/contactsource/contactsource.manifest.mf
@@ -4,5 +4,6 @@ Bundle-Vendor: jitsi.org
Bundle-Version: 0.0.1
System-Bundle: yes
Import-Package: org.osgi.framework,
+ net.java.sip.communicator.util,
net.java.sip.communicator.service.protocol
Export-Package: net.java.sip.communicator.service.contactsource
diff --git a/src/net/java/sip/communicator/util/DataObject.java b/src/net/java/sip/communicator/util/DataObject.java
new file mode 100644
index 0000000..21c5903
--- /dev/null
+++ b/src/net/java/sip/communicator/util/DataObject.java
@@ -0,0 +1,139 @@
+/*
+ * 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.util;
+
+/**
+ * Object which can store user specific key-values.
+ *
+ * @author Damian Minkov
+ */
+public class DataObject
+{
+ /**
+ * The user-specific key-value associations stored in this instance.
+ * <p>
+ * Like the Widget implementation of Eclipse SWT, the storage type takes
+ * into account that there are likely to be many
+ * <code>DataObject</code> instances and <code>Map</code>s are thus
+ * likely to impose increased memory use. While an array may very well
+ * perform worse than a <code>Map</code> with respect to search, the
+ * mechanism of user-defined key-value associations explicitly states that
+ * it is not guaranteed to be optimized for any particular use and only
+ * covers the most basic cases and performance-savvy code will likely
+ * implement a more optimized solution anyway.
+ * </p>
+ */
+ private Object[] data;
+
+ /**
+ * Gets the user data
+ * associated with this instance and a specific key.
+ *
+ * @param key the key of the user data associated with this instance to be
+ * retrieved
+ * @return an <tt>Object</tt> which represents the value associated with
+ * this instance and the specified <tt>key</tt>; <tt>null</tt> if no
+ * association with the specified <tt>key</tt> exists in this instance
+ */
+ public Object getData(Object key)
+ {
+ if (key == null)
+ throw new NullPointerException("key");
+
+ int index = dataIndexOf(key);
+
+ return (index == -1) ? null : data[index + 1];
+ }
+
+ /**
+ * Determines the index in <code>#data</code> of a specific key.
+ *
+ * @param key
+ * the key to retrieve the index in <code>#data</code> of
+ * @return the index in <code>#data</code> of the specified <code>key</code>
+ * if it is contained; <tt>-1</tt> if <code>key</code> is not
+ * contained in <code>#data</code>
+ */
+ private int dataIndexOf(Object key)
+ {
+ if (data != null)
+ for (int index = 0; index < data.length; index += 2)
+ if (key.equals(data[index]))
+ return index;
+ return -1;
+ }
+
+ /**
+ * Sets a
+ * user-specific association in this instance in the form of a key-value
+ * pair. If the specified <tt>key</tt> is already associated in this
+ * instance with a value, the existing value is overwritten with the
+ * specified <tt>value</tt>.
+ * <p>
+ * The user-defined association created by this method and stored in this
+ * instance is not serialized by this instance and is thus only meant for
+ * runtime use.
+ * </p>
+ * <p>
+ * The storage of the user data is implementation-specific and is thus not
+ * guaranteed to be optimized for execution time and memory use.
+ * </p>
+ *
+ * @param key the key to associate in this instance with the specified value
+ * @param value the value to be associated in this instance with the
+ * specified <tt>key</tt>
+ */
+ public void setData(Object key, Object value)
+ {
+ if (key == null)
+ throw new NullPointerException("key");
+
+ int index = dataIndexOf(key);
+
+ if (index == -1)
+ {
+
+ /*
+ * If value is null, remove the association with key (or just don't
+ * add it).
+ */
+ if (data == null)
+ {
+ if (value != null)
+ data = new Object[] { key, value };
+ }
+ else if (value == null)
+ {
+ int length = data.length - 2;
+
+ if (length > 0)
+ {
+ Object[] newData = new Object[length];
+
+ System.arraycopy(data, 0, newData, 0, index);
+ System.arraycopy(
+ data, index + 2, newData, index, length - index);
+ data = newData;
+ }
+ else
+ data = null;
+ }
+ else
+ {
+ int length = data.length;
+ Object[] newData = new Object[length + 2];
+
+ System.arraycopy(data, 0, newData, 0, length);
+ data = newData;
+ data[length++] = key;
+ data[length++] = value;
+ }
+ }
+ else
+ data[index + 1] = value;
+ }
+}