aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYana Stamcheva <yana@jitsi.org>2010-05-05 12:03:42 +0000
committerYana Stamcheva <yana@jitsi.org>2010-05-05 12:03:42 +0000
commit32656edcfc7b5cdacc642a3f333741eb135e2419 (patch)
tree0c44166bced2c0d876ec360e70dd1895cf4c0da8 /src
parent6007623e549ae18830a221178eedac125e867f41 (diff)
downloadjitsi-32656edcfc7b5cdacc642a3f333741eb135e2419.zip
jitsi-32656edcfc7b5cdacc642a3f333741eb135e2419.tar.gz
jitsi-32656edcfc7b5cdacc642a3f333741eb135e2419.tar.bz2
Search Filter: After filtering each source update the user interface (i.e. we don't wait until all the sources are filter before updating the ui)
Diffstat (limited to 'src')
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListSourceFilter.java46
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/FilterQuery.java110
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/FilterQueryListener.java29
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/PresenceFilter.java3
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/SearchField.java57
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/SearchFilter.java129
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/TreeContactList.java193
7 files changed, 447 insertions, 120 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListSourceFilter.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListSourceFilter.java
new file mode 100644
index 0000000..4b9bde9
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListSourceFilter.java
@@ -0,0 +1,46 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.gui.main.contactlist;
+
+import java.util.*;
+
+import net.java.sip.communicator.impl.gui.main.contactlist.contactsource.*;
+
+/**
+ * The <tt>ContactListSourceFilter</tt> is a <tt>ContactListFilter</tt> that
+ * allows to apply the filter to only one of its contact sources at a time.
+ *
+ * @author Yana Stamcheva
+ */
+public interface ContactListSourceFilter extends ContactListFilter
+{
+ /**
+ * Applies this filter to the given <tt>contactSource</tt> and stores the
+ * result in the given <tt>treeModel</tt>.
+ *
+ * @param contactSource the <tt>ExternalContactSource</tt> to apply the
+ * filter to
+ * @param treeModel the <tt>ContactListTreeModel</tt> storing the results
+ */
+ public void applyFilter(ExternalContactSource contactSource,
+ ContactListTreeModel treeModel);
+
+ /**
+ * Returns the list of current <tt>ExternalContactSource</tt>s this filter
+ * works with.
+ * @return the list of current <tt>ExternalContactSource</tt>s this filter
+ * works with
+ */
+ public Collection<ExternalContactSource> getContactSources();
+
+ /**
+ * Indicates if this filter contains a default source.
+ * @return <tt>true</tt> if this filter contains a default source,
+ * <tt>false</tt> otherwise
+ */
+ public boolean hasDefaultSource();
+}
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/FilterQuery.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/FilterQuery.java
new file mode 100644
index 0000000..0dedbc2
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/FilterQuery.java
@@ -0,0 +1,110 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.gui.main.contactlist;
+
+/**
+ * The <tt>FilterQuery</tt> gives information about a current filtering.
+ *
+ * @author Yana Stamcheva
+ */
+public class FilterQuery
+{
+ /**
+ * A listener, which is notified when this query finishes.
+ */
+ private FilterQueryListener filterQueryListener;
+
+ /**
+ * Indicates if the query succeeded, i.e. if the filter has returned any
+ * results.
+ */
+ private boolean isSucceeded = false;
+
+ /**
+ * Indicates if this query has been canceled.
+ */
+ private boolean isCanceled = false;
+
+ /**
+ * The number of results we're waiting for, before notifying interested
+ * <tt>filterQueryListener</tt> that the query has finished.
+ */
+ private int waitResults = 0;
+
+ /**
+ * Adds a wait result.
+ */
+ public void addWaitResult()
+ {
+ waitResults ++;
+ }
+
+ /**
+ * Removes a wait result. If no more results are waited then we notify
+ * interested listener that this query has finished.
+ */
+ public void removeWaitResult()
+ {
+ waitResults --;
+
+ if (waitResults == 0)
+ fireFilterQueryEvent();
+ }
+
+ /**
+ * Sets the <tt>isSucceeded</tt> property.
+ * @param isSucceeded indicates if this query has succeeded
+ */
+ public void setSucceeded(boolean isSucceeded)
+ {
+ this.isSucceeded = isSucceeded;
+ }
+
+ /**
+ * Indicates if this query has succeeded.
+ * @return <tt>true</tt> if this query has succeeded, <tt>false</tt> -
+ * otherwise
+ */
+ public boolean isSucceeded()
+ {
+ return isSucceeded;
+ }
+
+ public boolean isCanceled()
+ {
+ return isCanceled;
+ }
+
+ public void cancel()
+ {
+ isCanceled = true;
+ }
+
+ /**
+ * Sets the given <tt>FilterQueryListener</tt>.
+ * @param l the <tt>FilterQueryListener</tt> to set
+ */
+ public void setQueryListener(FilterQueryListener l)
+ {
+ filterQueryListener = l;
+ }
+
+ /**
+ * Notifies the <tt>FilterQueryListener</tt> of the result status of
+ * this query.
+ */
+ private void fireFilterQueryEvent()
+ {
+ if (filterQueryListener == null)
+ return;
+
+ if (isSucceeded)
+ filterQueryListener.filterQuerySucceeded(this);
+ else
+ filterQueryListener.filterQueryFailed(this);
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/FilterQueryListener.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/FilterQueryListener.java
new file mode 100644
index 0000000..98c1d66
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/FilterQueryListener.java
@@ -0,0 +1,29 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package net.java.sip.communicator.impl.gui.main.contactlist;
+
+/**
+ * The <tt>FilterQueryListener</tt> is notified when a filter query finishes.
+ *
+ * @author Yana Stamcheva
+ */
+public interface FilterQueryListener
+{
+ /**
+ * Indicates that the given <tt>query</tt> has finished with success, i.e.
+ * the filter has returned results.
+ * @param query the <tt>FilterQuery</tt>, where this listener is registered
+ */
+ public void filterQuerySucceeded(FilterQuery query);
+
+ /**
+ * Indicates that the given <tt>query</tt> has finished with failure, i.e.
+ * no results for the filter were found.
+ * @param query the <tt>FilterQuery</tt>, where this listener is registered
+ */
+ public void filterQueryFailed(FilterQuery query);
+}
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/PresenceFilter.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/PresenceFilter.java
index 3b8bc1f..25fafd6 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/PresenceFilter.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/PresenceFilter.java
@@ -51,8 +51,7 @@ public class PresenceFilter
{
isFiltering = true;
- addMatching(GuiActivator.getContactListService().getRoot(),
- treeModel);
+ addMatching(GuiActivator.getContactListService().getRoot(), treeModel);
isFiltering = false;
}
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchField.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchField.java
index eec1066..7f7d613 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchField.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/SearchField.java
@@ -20,7 +20,8 @@ import net.java.sip.communicator.util.swing.plaf.*;
*/
public class SearchField
extends SIPCommTextField
- implements TextFieldChangeListener
+ implements TextFieldChangeListener,
+ FilterQueryListener
{
private final Logger logger = Logger.getLogger(SearchField.class);
@@ -174,26 +175,11 @@ public class SearchField
if (filterString != null && filterString.length() > 0)
{
- boolean hasMatching
+ FilterQuery filterQuery
= contactList.applyFilter(TreeContactList.searchFilter);
- // If don't have matching contacts we enter the unknown contact
- // view.
- if (!hasMatching)
- {
- enableUnknownContactView(true);
- }
- // If the unknown contact view was previously enabled, but we
- // have found matching contacts we enter the normal view.
- else
- {
- if (!lastHasMatching)
- enableUnknownContactView(false);
-
- contactList.selectFirstContact();
- }
-
- lastHasMatching = hasMatching;
+ if (filterQuery != null)
+ filterQuery.setQueryListener(this);
}
else
{
@@ -218,4 +204,37 @@ public class SearchField
}
});
}
+
+ /**
+ * Indicates that the given <tt>query</tt> has finished with failure, i.e.
+ * no results for the filter were found.
+ * @param query the <tt>FilterQuery</tt>, where this listener is registered
+ */
+ public void filterQueryFailed(FilterQuery query)
+ {
+ /// If don't have matching contacts we enter the unknown contact
+ // view.
+ enableUnknownContactView(true);
+
+ lastHasMatching = false;
+ query.setQueryListener(null);
+ }
+
+ /**
+ * Indicates that the given <tt>query</tt> has finished with success, i.e.
+ * the filter has returned results.
+ * @param query the <tt>FilterQuery</tt>, where this listener is registered
+ */
+ public void filterQuerySucceeded(FilterQuery query)
+ {
+ // If the unknown contact view was previously enabled, but we
+ // have found matching contacts we enter the normal view.
+ if (!lastHasMatching)
+ enableUnknownContactView(false);
+
+ GuiActivator.getContactList().selectFirstContact();
+
+ lastHasMatching = true;
+ query.setQueryListener(null);
+ }
}
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 057148c..ef798c2 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
@@ -20,8 +20,7 @@ import net.java.sip.communicator.service.contactsource.*;
* @author Yana Stamcheva
*/
public class SearchFilter
- implements ContactListFilter,
- ContactQueryListener
+ implements ContactListSourceFilter
{
/**
* The default contact source search type.
@@ -44,12 +43,6 @@ public class SearchFilter
private Pattern filterPattern;
/**
- * The <tt>ContactListTreeModel</tt>, where results from the search
- * are added.
- */
- private ContactListTreeModel resultTreeModel;
-
- /**
* The <tt>MetaContactListSource</tt> to search in.
*/
private final MetaContactListSource mclSource;
@@ -85,31 +78,37 @@ public class SearchFilter
*/
public void applyFilter(ContactListTreeModel treeModel)
{
- resultTreeModel = treeModel;
-
- if (contactSources == null)
- contactSources = TreeContactList.getContactSources();
-
if (searchSourceType == DEFAULT_SOURCE)
// First add the MetaContactListSource
mclSource.filter(filterPattern, treeModel);
+ }
- for (ExternalContactSource contactSource : contactSources)
- {
- ContactSourceService sourceService
- = contactSource.getContactSourceService();
- if (sourceService instanceof ExtendedContactSourceService)
- currentQuery
- = ((ExtendedContactSourceService) sourceService)
- .queryContactSource(filterPattern);
- else
- currentQuery = sourceService.queryContactSource(filterString);
-
- // Add first available results.
- this.addMatching(currentQuery.getQueryResults());
-
- currentQuery.addContactQueryListener(this);
- }
+ /**
+ * Applies this filter to the given <tt>contactSource</tt> and stores the
+ * result in the given <tt>treeModel</tt>.
+ *
+ * @param contactSource the <tt>ExternalContactSource</tt> to apply the
+ * filter to
+ * @param treeModel the <tt>ContactListTreeModel</tt> in which the results
+ * are stored
+ */
+ public void applyFilter(ExternalContactSource contactSource,
+ ContactListTreeModel treeModel)
+ {
+ ContactSourceService sourceService
+ = contactSource.getContactSourceService();
+
+ if (sourceService instanceof ExtendedContactSourceService)
+ currentQuery
+ = ((ExtendedContactSourceService) sourceService)
+ .queryContactSource(filterPattern);
+ else
+ currentQuery = sourceService.queryContactSource(filterString);
+
+ // Add first available results.
+ this.addMatching(currentQuery.getQueryResults(), treeModel);
+
+ currentQuery.addContactQueryListener(GuiActivator.getContactList());
}
/**
@@ -202,55 +201,28 @@ public class SearchFilter
}
/**
- * Indicates that a contact has been received for a query.
- * @param event the <tt>ContactReceivedEvent</tt> that notified us
- */
- public void contactReceived(ContactReceivedEvent event)
- {
- synchronized (resultTreeModel)
- {
- addSourceContact(event.getContact());
- }
- }
-
- /**
- * Indicates that the status of a query has changed.
- * @param event the <tt>ContactQueryStatusEvent</tt> that notified us
- */
- public void queryStatusChanged(ContactQueryStatusEvent event)
- {
- int eventType = event.getEventType();
-
- // Remove the current query when it's stopped for some reason.
- // QUERY_COMPLETED, QUERY_COMPLETED, QUERY_ERROR
- currentQuery = null;
-
- if (eventType == ContactQueryStatusEvent.QUERY_ERROR)
- {
- //TODO: Show the error to the user??
- }
-
- event.getQuerySource().removeContactQueryListener(this);
- }
-
- /**
- * Adds the list of <tt>sourceContacts</tt> in the current result tree model.
+ * Adds the list of <tt>sourceContacts</tt> in the given <tt>treeModel</tt>.
* @param sourceContacts the list of <tt>SourceContact</tt>s to add
+ * @param treeModel the <tt>ContactListTreeModel</tt>, where the contacts
+ * are added
*/
- private void addMatching(List<SourceContact> sourceContacts)
+ private void addMatching( List<SourceContact> sourceContacts,
+ ContactListTreeModel treeModel)
{
Iterator<SourceContact> contactsIter = sourceContacts.iterator();
while (contactsIter.hasNext())
{
- addSourceContact(contactsIter.next());
+ addSourceContact(contactsIter.next(), treeModel);
}
}
/**
* Adds the given <tt>sourceContact</tt> to the result tree model.
* @param sourceContact the <tt>SourceContact</tt> to add
+ * @param treeModel the <tt>ContactListTreeModel</tt> storing the result
*/
- private void addSourceContact(SourceContact sourceContact)
+ private void addSourceContact( SourceContact sourceContact,
+ ContactListTreeModel treeModel)
{
ContactSourceService contactSource
= sourceContact.getContactSource();
@@ -263,12 +235,14 @@ public class SearchFilter
// SourceContact over the pattern
&& (contactSource instanceof ExtendedContactSourceService)
|| isMatching(sourceContact))
+ {
GuiActivator.getContactList().addContact(
- resultTreeModel,
+ treeModel,
sourceUI.getUIContact(sourceContact),
sourceUI.getUIGroup(),
- true,
+ false,
false);
+ }
}
/**
@@ -299,4 +273,25 @@ public class SearchFilter
}
}
}
+
+ public Collection<ExternalContactSource> getContactSources()
+ {
+ if (contactSources == null)
+ contactSources = TreeContactList.getContactSources();
+
+ return contactSources;
+ }
+
+ /**
+ * Indicates if this filter contains a default source.
+ * @return <tt>true</tt> if this filter contains a default source,
+ * <tt>false</tt> otherwise
+ */
+ public boolean hasDefaultSource()
+ {
+ if (searchSourceType == DEFAULT_SOURCE)
+ return true;
+ else
+ return false;
+ }
}
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 4d5c4c4..c4d2881 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
@@ -36,6 +36,7 @@ public class TreeContactList
extends DefaultTreeContactList
implements MetaContactListListener,
ContactPresenceStatusListener,
+ ContactQueryListener,
MouseListener,
MouseMotionListener,
TreeExpansionListener
@@ -52,13 +53,6 @@ public class TreeContactList
private ContactListTreeModel treeModel;
/**
- * The temporary tree model is used to collect the results from a filter
- * operation. This is used in order to separate search and filter matching
- * operations from the UI refresh operations.
- */
- private ContactListTreeModel tempTreeModel;
-
- /**
* The right button menu.
*/
private JPopupMenu rightButtonMenu;
@@ -132,6 +126,11 @@ public class TreeContactList
private final Object filterLock = new Object();
/**
+ * The filter query used to track advanced source filtering.
+ */
+ FilterQuery filterQuery;
+
+ /**
* Creates the <tt>TreeContactList</tt>.
*/
public TreeContactList()
@@ -173,7 +172,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -215,7 +214,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -259,7 +258,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -290,7 +289,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -323,7 +322,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -351,7 +350,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -389,7 +388,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -449,7 +448,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -476,7 +475,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -509,7 +508,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -545,7 +544,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -603,7 +602,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -669,7 +668,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -685,6 +684,65 @@ public class TreeContactList
}
/**
+ * Indicates that a contact has been received for a query.
+ * @param event the <tt>ContactReceivedEvent</tt> that notified us
+ */
+ public void contactReceived(ContactReceivedEvent event)
+ {
+ final SourceContact sourceContact = event.getContact();
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ // We synchronize the matching and all MetaContactListener
+ // events on the filterLock in order to prevent modification
+ // to be done on the actual treeModel while we're working with
+ // the temporary model.
+ synchronized (filterLock)
+ {
+ ContactSourceService contactSource
+ = sourceContact.getContactSource();
+
+ ExternalContactSource sourceUI
+ = TreeContactList.getContactSource(contactSource);
+
+ UIContact uiContact = sourceUI.getUIContact(sourceContact);
+
+ if (sourceUI == null)
+ return;
+
+ // ExtendedContactSourceService has already matched the
+ // SourceContact over the pattern
+ if((contactSource instanceof ExtendedContactSourceService)
+ || currentFilter.isMatching(uiContact))
+ {
+ addContact(uiContact, sourceUI.getUIGroup());
+ }
+ else
+ uiContact = null;
+ }
+ }
+ });
+ }
+
+ /**
+ * Indicates that the status of a query has changed.
+ * @param event the <tt>ContactQueryStatusEvent</tt> that notified us
+ */
+ public void queryStatusChanged(ContactQueryStatusEvent event)
+ {
+ int eventType = event.getEventType();
+
+ if (eventType == ContactQueryStatusEvent.QUERY_ERROR)
+ {
+ //TODO: Show the error to the user??
+ }
+
+ event.getQuerySource().removeContactQueryListener(this);
+ }
+
+ /**
* Returns the right button menu opened over the contact list.
*
* @return the right button menu opened over the contact list
@@ -716,7 +774,7 @@ public class TreeContactList
public void setActiveContact(MetaContact metaContact, boolean isActive)
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -944,6 +1002,9 @@ public class TreeContactList
{
currentFilter.stopFilter();
this.isFiltering = false;
+
+ if (filterQuery != null)
+ filterQuery.cancel();
}
/**
@@ -954,18 +1015,81 @@ public class TreeContactList
*/
public boolean applyDefaultFilter()
{
- return applyFilter(defaultFilter);
+ return applyFilter(defaultFilter, new ContactListTreeModel(), null);
+ }
+
+ /**
+ * Applies the given <tt>filter</tt>.
+ * @param filter the <tt>ContactListFilter</tt> to apply.
+ * @return <tt>true</tt> if the filter has any matches, <tt>false</tt>
+ * otherwise
+ */
+ public boolean applyFilter(ContactListFilter filter)
+ {
+ return applyFilter(filter, new ContactListTreeModel(), null);
+ }
+
+ /**
+ * Applies the given <tt>ContactListSourceFilter</tt>.
+ * @param filter the <tt>ContactListSourceFilter</tt> to apply
+ * @return the <tt>FilterQuery</tt> through which the filter could be
+ * tracked
+ */
+ public FilterQuery applyFilter(final ContactListSourceFilter filter)
+ {
+ final ContactListTreeModel tempTreeModel = new ContactListTreeModel();
+
+ filterQuery = new FilterQuery();
+
+ // If the filter has a default contact source, we apply it first.
+ if (filter.hasDefaultSource())
+ filterQuery.setSucceeded(applyFilter(filter, tempTreeModel, null));
+
+ Iterator<ExternalContactSource> filterSources
+ = filter.getContactSources().iterator();
+
+ // Then we apply the filter on all its contact sources.
+ while (filterSources.hasNext())
+ {
+ final ExternalContactSource filterSource = filterSources.next();
+
+ if (filterQuery.isCanceled())
+ return filterQuery;
+
+ filterQuery.addWaitResult();
+ new Thread()
+ {
+ public void run()
+ {
+ boolean isSucceeded
+ = applyFilter( filter,
+ tempTreeModel,
+ filterSource);
+
+ if (!filterQuery.isSucceeded() && isSucceeded)
+ filterQuery.setSucceeded(true);
+
+ filterQuery.removeWaitResult();
+ }
+ }.start();
+ }
+ return filterQuery;
}
/**
* Applies the given <tt>filter</tt> and changes the content of the
* contact list according to it.
* @param filter the new filter to set
+ * @param tempTreeModel the treeModel, where the filter results are stored
+ * @param contactSource the <tt>ExternalContactSource</tt> to apply the
+ * filter to
* @return <tt>true</tt> to indicate that the filter has found a match,
* <tt>false</tt> if no matches were found and the contact list is then
* empty.
*/
- public boolean applyFilter(ContactListFilter filter)
+ private boolean applyFilter(ContactListFilter filter,
+ ContactListTreeModel tempTreeModel,
+ ExternalContactSource contactSource)
{
// We set the isFiltering to true to indicate that we're currently
// filtering.
@@ -974,8 +1098,6 @@ public class TreeContactList
if (currentFilter == null || !currentFilter.equals(filter))
this.currentFilter = filter;
- tempTreeModel = new ContactListTreeModel();
-
// We synchronize the matching and all MetaContactListener events on
// the searchTreeModel in order to prevent modification to be done on
// the actual treeModel while we're working with the temporary model.
@@ -983,7 +1105,15 @@ public class TreeContactList
{
treeModel.clearDependencies();
- currentFilter.applyFilter(tempTreeModel);
+ // If we have a specific contact source and we're dealing with
+ // a ContactListSourceFilter then we would apply the filter only
+ // to this source.
+ if (contactSource != null
+ && filter instanceof ContactListSourceFilter)
+ ((ContactListSourceFilter) currentFilter)
+ .applyFilter(contactSource, tempTreeModel);
+ else
+ currentFilter.applyFilter(tempTreeModel);
treeModel = tempTreeModel;
}
@@ -1026,8 +1156,6 @@ public class TreeContactList
if (tempTreeModel.getChildCount(tempTreeModel.getRoot()) > 0)
hasResults = true;
- tempTreeModel = null;
-
return hasResults;
}
@@ -1060,7 +1188,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent modification
+ // events on the filterLock in order to prevent modification
// to be done on the actual treeModel while we're working with
// the temporary model.
synchronized (filterLock)
@@ -1668,8 +1796,9 @@ public class TreeContactList
switch (event.getType())
{
case ServiceEvent.REGISTERED:
- contactSources.add(
- new ExternalContactSource((ContactSourceService) service));
+ ExternalContactSource contactSource
+ = new ExternalContactSource((ContactSourceService) service);
+ contactSources.add(contactSource);
break;
case ServiceEvent.UNREGISTERING:
ExternalContactSource cSource
@@ -1704,7 +1833,7 @@ public class TreeContactList
public void run()
{
// We synchronize the matching and all MetaContactListener
- // events on the tempTreeModel in order to prevent
+ // events on the filterLock in order to prevent
// modification to be done on the actual treeModel while
// we're working with the temporary model.
synchronized (filterLock)