From e59acc97709dbca7562175a80d94f3f10f938386 Mon Sep 17 00:00:00 2001 From: Yana Stamcheva Date: Mon, 10 May 2010 20:30:14 +0000 Subject: [PATCH] Results from a MetaContactList filtering are now returned as events. --- .../callhistory/CallHistoryContactSource.java | 2 +- .../main/contactlist/CallHistoryFilter.java | 96 +- .../main/contactlist/ContactListFilter.java | 6 +- .../contactlist/ContactListSourceFilter.java | 7 +- .../contactlist/ContactListTreeModel.java | 49 +- .../gui/main/contactlist/FilterQuery.java | 5 +- .../impl/gui/main/contactlist/GroupNode.java | 122 +- .../contactlist/MetaContactQueryListener.java | 32 + .../gui/main/contactlist/PresenceFilter.java | 39 +- .../gui/main/contactlist/SearchFilter.java | 37 +- .../gui/main/contactlist/TreeContactList.java | 1051 +++++++---------- .../contactsource/MetaContactListSource.java | 77 +- 12 files changed, 634 insertions(+), 889 deletions(-) create mode 100644 src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactQueryListener.java diff --git a/src/net/java/sip/communicator/impl/callhistory/CallHistoryContactSource.java b/src/net/java/sip/communicator/impl/callhistory/CallHistoryContactSource.java index 5ab358346..7648be65b 100644 --- a/src/net/java/sip/communicator/impl/callhistory/CallHistoryContactSource.java +++ b/src/net/java/sip/communicator/impl/callhistory/CallHistoryContactSource.java @@ -44,7 +44,7 @@ public ContactQuery queryContactSource(String queryString) if (queryString != null && queryString.length() > 0) return new CallHistoryContactQuery( CallHistoryActivator.getCallHistoryService() - .findByPeer(queryString, 100)); + .findByPeer(queryString, 50)); else return new CallHistoryContactQuery( CallHistoryActivator.getCallHistoryService() diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/CallHistoryFilter.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/CallHistoryFilter.java index 014a061ca..565de912f 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/CallHistoryFilter.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/CallHistoryFilter.java @@ -19,20 +19,13 @@ * @author Yana Stamcheva */ public class CallHistoryFilter - implements ContactListFilter, - ContactQueryListener + implements ContactListFilter { /** * This class logger. */ private final Logger logger = Logger.getLogger(CallHistoryFilter.class); - /** - * The ContactListTreeModel, where the results of this filter are - * stored - */ - private ContactListTreeModel resultTreeModel; - /** * The current ContactQuery. */ @@ -40,16 +33,11 @@ public class CallHistoryFilter /** * Applies this filter and stores the result in the given treeModel. - * - * @param treeModel the ContactListTreeModel, where the results - * of this filter are stored */ - public void applyFilter(ContactListTreeModel treeModel) + public void applyFilter() { logger.debug("Call history filter applied."); - this.resultTreeModel = treeModel; - Collection contactSources = TreeContactList.getContactSources(); @@ -69,15 +57,36 @@ public void applyFilter(ContactListTreeModel treeModel) this.addMatching( currentQuery.getQueryResults(), contactSource); - currentQuery.addContactQueryListener(this); + currentQuery.addContactQueryListener(GuiActivator.getContactList()); } } + /** + * Indicates if the given uiContact is matching this filter. + * @param uiContact the UIContact to check for match + * @return true if the given uiContact is matching this + * filter, false otherwise + */ public boolean isMatching(UIContact uiContact) { + Object descriptor = uiContact.getDescriptor(); + + if (descriptor instanceof SourceContact) + { + SourceContact sourceContact = (SourceContact) descriptor; + + if ((sourceContact.getContactSource().getIdentifier() + .equals(ContactSourceService.CALL_HISTORY))) + return true; + } return false; } + /** + * No group could match this filter. + * @param uiGroup the UIGroup to check for match + * @return false to indicate that no group could match this filter + */ public boolean isMatching(UIGroup uiGroup) { return false; @@ -96,62 +105,13 @@ private void addMatching( List sourceContacts, while (contactsIter.hasNext()) { - addHistoryContact(contactsIter.next(), uiSource); + GuiActivator.getContactList() + .addContact(uiSource.createUIContact(contactsIter.next()), + uiSource.getUIGroup(), + false); } } - /** - * Indicates that a contact has been received for a query. - * @param event the ContactReceivedEvent that notified us - */ - public void contactReceived(ContactReceivedEvent event) - { - synchronized (resultTreeModel) - { - ExternalContactSource sourceUI - = TreeContactList.getContactSource( - event.getQuerySource().getContactSource()); - - addHistoryContact(event.getContact(), sourceUI); - } - } - - /** - * Indicates that the query status has changed. - * @param event the ContactQueryStatusEvent 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 given sourceContact to the contact list. - * @param sourceContact the SourceContact to add - * @param uiSource the UI adapter for the original contact source - */ - private void addHistoryContact( SourceContact sourceContact, - ExternalContactSource uiSource) - { - GuiActivator.getContactList() - .addContact(resultTreeModel, - uiSource.createUIContact(sourceContact), - uiSource.getUIGroup(), - false, - false); - } - /** * Stops this filter current queries. */ diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListFilter.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListFilter.java index 3cd9156fb..e3c2e749c 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListFilter.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListFilter.java @@ -33,11 +33,9 @@ public interface ContactListFilter public boolean isMatching(UIGroup uiGroup); /** - * Applies this filter to any interested sources and stores the result in - * the given treeModel. - * @param treeModel the ContactListTreeModel to store the result in + * Applies this filter to any interested sources */ - public void applyFilter(ContactListTreeModel treeModel); + public void applyFilter(); /** * Stops this filter current queries. 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 index 5fc29f116..bbd7fc96d 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListSourceFilter.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListSourceFilter.java @@ -20,16 +20,13 @@ public interface ContactListSourceFilter extends ContactListFilter { /** - * Applies this filter to the given contactSource and stores the - * result in the given treeModel. + * Applies this filter to the given contactSource. * * @param contactSource the ExternalContactSource to apply the * filter to - * @param treeModel the ContactListTreeModel storing the results * @return the ContactQuery that tracks this filter */ - public ContactQuery applyFilter(ExternalContactSource contactSource, - ContactListTreeModel treeModel); + public ContactQuery applyFilter(ExternalContactSource contactSource); /** * Returns the list of current ExternalContactSources this filter diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeModel.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeModel.java index b1069a236..1a1a4bc6f 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeModel.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeModel.java @@ -56,39 +56,42 @@ public ContactNode findFirstContactNode() } /** - * Clears all dependencies in the abstraction path (i.e. GroupNode - UIGroup - * - MetaContactGroup or ContactNode - UIContact - SourceContact). + * Removes all nodes except the root node and clears all dependencies. */ - public void clearDependencies() + public void clear() { - clearDependencies(rootGroupNode); + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + int childCount = rootGroupNode.getChildCount(); + int[] removedIndexs = new int[childCount]; + Object[] removedNodes = new Object[childCount]; + for (int i = 0; i < childCount; i ++) + { + removedIndexs[i] = i; + removedNodes[i] = rootGroupNode.getChildAt(i); + } + rootGroupNode.clear(); + nodesWereRemoved(rootGroupNode, removedIndexs, removedNodes); + } + }); } /** - * Clears all dependencies for all children in the given groupNode - * (i.e. GroupNode - UIGroup - MetaContactGroup or ContactNode - UIContact - * - SourceContact). - * @param groupNode the TreeNode in which we clear dependencies + * Invoke this method after you've changed how node is to be + * represented in the tree. + * @param node the node that has changed */ - private void clearDependencies(TreeNode groupNode) + public void nodeChanged(final TreeNode node) { - for (int i = 0; i < groupNode.getChildCount(); i ++) + SwingUtilities.invokeLater(new Runnable() { - TreeNode treeNode = groupNode.getChildAt(i); - - if (treeNode instanceof ContactNode) + public void run() { - ((ContactNode) treeNode).getContactDescriptor() - .setContactNode(null); + ContactListTreeModel.super.nodeChanged(node); } - else if (treeNode instanceof GroupNode) - { - ((GroupNode) treeNode).getGroupDescriptor() - .setGroupNode(null); - - clearDependencies(treeNode); - } - } + }); } /** 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 index 33760432e..f5b414be5 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/FilterQuery.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/FilterQuery.java @@ -16,7 +16,7 @@ * @author Yana Stamcheva */ public class FilterQuery - implements ContactQueryListener + implements ContactQueryListener { /** * A listener, which is notified when this query finishes. @@ -138,6 +138,5 @@ public void queryStatusChanged(ContactQueryStatusEvent event) fireFilterQueryEvent(); } - public void contactReceived(ContactReceivedEvent event) - {} + public void contactReceived(ContactReceivedEvent event) {} } diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/GroupNode.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/GroupNode.java index 2882dadef..be7030f6d 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/GroupNode.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/GroupNode.java @@ -8,6 +8,7 @@ import java.util.*; +import javax.swing.*; import javax.swing.tree.*; /** @@ -69,7 +70,10 @@ public ContactNode addContact(UIContact uiContact) ContactNode contactNode = new ContactNode(uiContact); uiContact.setContactNode(contactNode); - this.add(contactNode); + add(contactNode); + + fireNodeInserted(getIndex(contactNode)); + return contactNode; } @@ -77,23 +81,20 @@ public ContactNode addContact(UIContact uiContact) * Creates a ContactNode for the given uiContact, * adds it to this group and performs a sort at the end. * @param uiContact the UIContact to add - * @param isRefreshView indicates if the view should be refreshed * @return the created ContactNode */ @SuppressWarnings("unchecked") - public ContactNode sortedAddContact(UIContact uiContact, - boolean isRefreshView) + public ContactNode sortedAddContact(UIContact uiContact) { ContactNode contactNode = new ContactNode(uiContact); uiContact.setContactNode(contactNode); - this.add(contactNode); + add(contactNode); // TODO: Optimize! Collections.sort(children, nodeComparator); - if (isRefreshView) - this.fireNodeInserted(getIndex(contactNode)); + fireNodeInserted(getIndex(contactNode)); return contactNode; } @@ -105,14 +106,15 @@ public ContactNode sortedAddContact(UIContact uiContact, */ public void removeContact(UIContact uiContact) { - ContactNode contactNode = findContactNode(uiContact); + final ContactNode contactNode = uiContact.getContactNode(); if (contactNode != null) { int index = getIndex(contactNode); - // We remove the node directly from the list, thus skipping all the - // checks verifying if the node belongs to this parent. + // We remove the node directly from the list, thus skipping all + // the checks verifying if the node belongs to this parent. children.removeElementAt(index); + contactNode.setParent(null); uiContact.setContactNode(null); uiContact = null; @@ -132,7 +134,10 @@ public GroupNode addContactGroup(UIGroup uiGroup) GroupNode groupNode = new GroupNode(treeModel, uiGroup); uiGroup.setGroupNode(groupNode); - this.add(groupNode); + add(groupNode); + + fireNodeInserted(getIndex(groupNode)); + return groupNode; } @@ -151,6 +156,7 @@ public void removeContactGroup(UIGroup uiGroup) // We remove the node directly from the list, thus skipping all the // checks verifying if the node belongs to this parent. children.removeElementAt(index); + groupNode.setParent(null); uiGroup.setGroupNode(null); @@ -158,49 +164,25 @@ public void removeContactGroup(UIGroup uiGroup) } } - /** - * Removes all of this node's children, setting their parents to null. - * If this node has no children, this method does nothing. - */ - public void removeAllChildren() - { - for (int i = getChildCount()-1; i >= 0; i--) - { - TreeNode treeNode = getChildAt(i); - - if (treeNode instanceof ContactNode) - ((ContactNode) treeNode).getContactDescriptor() - .setContactNode(null); - else if (treeNode instanceof GroupNode) - ((GroupNode) treeNode).getGroupDescriptor() - .setGroupNode(null); - - children.removeElementAt(i); - ((DefaultMutableTreeNode) treeNode).setParent(null); - } - } - /** * Creates a GroupNode for the given uiGroup, * adds it to this group node and performs a sort at the end. * @param uiGroup the UIGroup to add - * @param isRefreshView indicates if the view should be refreshed * @return the created GroupNode */ @SuppressWarnings("unchecked") - public GroupNode sortedAddContactGroup( UIGroup uiGroup, - boolean isRefreshView) + public GroupNode sortedAddContactGroup(UIGroup uiGroup) { GroupNode groupNode = new GroupNode(treeModel, uiGroup); + uiGroup.setGroupNode(groupNode); - this.add(groupNode); + add(groupNode); // TODO: Optimize! Collections.sort(children, nodeComparator); - if (isRefreshView) - this.fireNodeInserted(getIndex(groupNode)); + fireNodeInserted(getIndex(groupNode)); return groupNode; } @@ -214,30 +196,6 @@ public UIGroup getGroupDescriptor() return (UIGroup) getUserObject(); } - /** - * Finds the ContactNode corresponding to the given - * uiContact in the children of this node. - * @param uiContact the UIContact, which node we're looking for - * @return the corresponding ContactNode or null if no contact - * node was found - */ - @SuppressWarnings("unchecked") - public ContactNode findContactNode(UIContact uiContact) - { - Enumeration children = children(); - while(children.hasMoreElements()) - { - TreeNode treeNode = children.nextElement(); - if (treeNode instanceof ContactNode - && ((ContactNode) treeNode).getContactDescriptor() - .equals(uiContact)) - { - return (ContactNode) treeNode; - } - } - return null; - } - /** * Returns the index of this node in its parent group. * @return the index of this node in its parent group @@ -257,9 +215,15 @@ public void sort(ContactListTreeModel treeModel) { if (children != null) { - Collections.sort(children, nodeComparator); + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + Collections.sort(children, nodeComparator); - fireNodesChanged(); + fireNodesChanged(); + } + }); } } @@ -274,6 +238,34 @@ public boolean isCollapsed() return isCollapsed; } + /** + * Clears all dependencies for all children in the given groupNode + * (i.e. GroupNode - UIGroup - MetaContactGroup or ContactNode - UIContact + * - SourceContact). + */ + public void clear() + { + for (int i = 0; i < getChildCount(); i ++) + { + TreeNode treeNode = getChildAt(i); + + if (treeNode instanceof ContactNode) + { + ((ContactNode) treeNode).getContactDescriptor() + .setContactNode(null); + } + else if (treeNode instanceof GroupNode) + { + ((GroupNode) treeNode).getGroupDescriptor() + .setGroupNode(null); + + ((GroupNode) treeNode).clear(); + } + } + if (children != null) + children.removeAllElements(); + } + /** * Notifies all interested listeners that a node has been inserted at the * given index. diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactQueryListener.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactQueryListener.java new file mode 100644 index 000000000..838c021d2 --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactQueryListener.java @@ -0,0 +1,32 @@ +/* + * 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 net.java.sip.communicator.service.contactlist.*; + +/** + * The MetaContactQueryListener listens for events coming from a + * MetaContactListService filtering. + * + * @author Yana Stamcheva + */ +public interface MetaContactQueryListener +{ + /** + * Indicates that a MetaContact has been received for a search in + * the MetaContactListService. + * @param metaContact the received MetaContact + */ + public void metaContactReceived(MetaContact metaContact); + + /** + * Indicates that a MetaGroup has been received from a search in + * the MetaContactListService. + * @param metaGroup the MetaGroup that has been received + */ + public void metaGroupReceived(MetaContactGroup metaGroup); +} 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 a13674f50..5fbf9e56d 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 @@ -50,16 +50,14 @@ public PresenceFilter() /** * Applies this filter. This filter is applied over the * MetaContactListService. - * @param treeModel the model to which we should add the results from the - * filtering operation */ - public void applyFilter(ContactListTreeModel treeModel) + public void applyFilter() { logger.debug("Presence filter applied."); isFiltering = true; - addMatching(GuiActivator.getContactListService().getRoot(), treeModel); + addMatching(GuiActivator.getContactListService().getRoot()); isFiltering = false; } @@ -165,11 +163,8 @@ private boolean isContactOnline(MetaContact contact) * matching the current filter and not contained in the contact list. * @param metaGroup the MetaContactGroup, which matching contacts * to add - * @param resultTreeModel the ContactListTreeModel, where results - * should be added */ - private void addMatching( MetaContactGroup metaGroup, - ContactListTreeModel resultTreeModel) + private void addMatching(MetaContactGroup metaGroup) { Iterator childContacts = metaGroup.getChildContacts(); @@ -179,26 +174,7 @@ private void addMatching( MetaContactGroup metaGroup, if(isMatching(metaContact)) { - MetaContactGroup parentGroup - = metaContact.getParentMetaContactGroup(); - - UIGroup uiGroup = null; - if (!MetaContactListSource.isRootGroup(parentGroup)) - { - uiGroup = MetaContactListSource - .getUIGroup(parentGroup); - - if (uiGroup == null) - uiGroup = MetaContactListSource - .createUIGroup(parentGroup); - } - - GuiActivator.getContactList().addContact( - resultTreeModel, - MetaContactListSource.createUIContact(metaContact), - uiGroup, - true, - false); + MetaContactListSource.fireQueryEvent(metaContact); } } @@ -210,12 +186,9 @@ private void addMatching( MetaContactGroup metaGroup, if (subgroup.countChildContacts() == 0 && subgroup.countSubgroups() == 0 && isMatching(subgroup)) - GuiActivator.getContactList().addGroup( - resultTreeModel, - MetaContactListSource.createUIGroup(subgroup), - false); + MetaContactListSource.fireQueryEvent(subgroup); else - addMatching(subgroup, resultTreeModel); + addMatching(subgroup); } } 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 9ac897e88..8fe363542 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 @@ -79,30 +79,26 @@ public SearchFilter() } /** - * Applies this filter and stores the result in the given treeModel. - * @param treeModel the ContactListTreeModel, in which we store - * results + * Applies this filter to the default contact source. */ - public void applyFilter(ContactListTreeModel treeModel) + public void applyFilter() { logger.debug("Search filter applied on default source"); if (searchSourceType == DEFAULT_SOURCE) + { // First add the MetaContactListSource - mclSource.filter(filterPattern, treeModel); + mclSource.filter(filterPattern); + } } /** - * Applies this filter to the given contactSource and stores the - * result in the given treeModel. + * Applies this filter to the given contactSource. * * @param contactSource the ExternalContactSource to apply the * filter to - * @param treeModel the ContactListTreeModel in which the results - * are stored * @return the ContactQuery that tracks this filter */ - public ContactQuery applyFilter(ExternalContactSource contactSource, - ContactListTreeModel treeModel) + public ContactQuery applyFilter(ExternalContactSource contactSource) { logger.debug("Search filter applied on source: " + contactSource.getContactSourceService()); @@ -119,7 +115,7 @@ public ContactQuery applyFilter(ExternalContactSource contactSource, contactQuery = sourceService.queryContactSource(filterString); // Add first available results. - this.addMatching(contactQuery.getQueryResults(), treeModel); + this.addMatching(contactQuery.getQueryResults()); currentQueries.add(contactQuery); contactQuery.addContactQueryListener(GuiActivator.getContactList()); @@ -228,28 +224,23 @@ private boolean isMatching(String text) } /** - * Adds the list of sourceContacts in the given treeModel. + * Adds the list of sourceContacts to the contact list. * @param sourceContacts the list of SourceContacts to add - * @param treeModel the ContactListTreeModel, where the contacts - * are added */ - private void addMatching( List sourceContacts, - ContactListTreeModel treeModel) + private void addMatching( List sourceContacts) { Iterator contactsIter = sourceContacts.iterator(); while (contactsIter.hasNext()) { - addSourceContact(contactsIter.next(), treeModel); + addSourceContact(contactsIter.next()); } } /** - * Adds the given sourceContact to the result tree model. + * Adds the given sourceContact to the contact list. * @param sourceContact the SourceContact to add - * @param treeModel the ContactListTreeModel storing the result */ - private void addSourceContact( SourceContact sourceContact, - ContactListTreeModel treeModel) + private void addSourceContact( SourceContact sourceContact) { ContactSourceService contactSource = sourceContact.getContactSource(); @@ -264,10 +255,8 @@ private void addSourceContact( SourceContact sourceContact, || isMatching(sourceContact)) { GuiActivator.getContactList().addContact( - treeModel, sourceUI.createUIContact(sourceContact), sourceUI.getUIGroup(), - false, 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 7988835e2..e1f8c775f 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 @@ -38,6 +38,7 @@ public class TreeContactList implements MetaContactListListener, ContactPresenceStatusListener, ContactQueryListener, + MetaContactQueryListener, MouseListener, MouseMotionListener, TreeExpansionListener @@ -113,19 +114,6 @@ public class TreeContactList private static final Collection contactSources = new LinkedList(); - /** - * Indicates if we're currently filtering the tree model. If there's an - * ongoing filtering this variable would be set to true, otherwise the value - * would be false. This variable is needed because the actual filtering is - * done in a separate thread. - */ - private boolean isFiltering = false; - - /** - * The object locking the filter. - */ - private final Object filterLock = new Object(); - /** * The filter query used to track advanced source filtering. */ @@ -150,6 +138,8 @@ public TreeContactList() treeModel = new ContactListTreeModel(); + setTreeModel(treeModel); + // We hide the root node as it doesn't represent a real group. if (isRootVisible()) setRootVisible(false); @@ -157,6 +147,8 @@ public TreeContactList() this.initKeyActions(); this.initContactSources(); + + MetaContactListSource.setMetaContactQueryListener(this); } /** @@ -166,38 +158,25 @@ public TreeContactList() */ public void childContactsReordered(MetaContactGroupEvent evt) { - final MetaContactGroup metaGroup = evt.getSourceMetaContactGroup(); + MetaContactGroup metaGroup = evt.getSourceMetaContactGroup(); - SwingUtilities.invokeLater(new Runnable() + UIGroup uiGroup = null; + if (!MetaContactListSource.isRootGroup(metaGroup)) { - 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) - { - UIGroup uiGroup = null; - if (!MetaContactListSource.isRootGroup(metaGroup)) - { - uiGroup = MetaContactListSource.getUIGroup(metaGroup); - } - else - { - uiGroup = treeModel.getRoot().getGroupDescriptor(); - } + uiGroup = MetaContactListSource.getUIGroup(metaGroup); + } + else + { + uiGroup = treeModel.getRoot().getGroupDescriptor(); + } - if (uiGroup != null) - { - GroupNode groupNode = uiGroup.getGroupNode(); + if (uiGroup != null) + { + GroupNode groupNode = uiGroup.getGroupNode(); - if (groupNode != null) - groupNode.sort(treeModel); - } - } - } - }); + if (groupNode != null) + groupNode.sort(treeModel); + } } /** @@ -210,39 +189,26 @@ public void metaContactAdded(final MetaContactEvent evt) final MetaContact metaContact = evt.getSourceMetaContact(); final MetaContactGroup parentGroup = evt.getParentGroup(); - SwingUtilities.invokeLater(new Runnable() + UIContact uiContact + = MetaContactListSource.createUIContact(metaContact); + + if (currentFilter.isMatching(uiContact)) { - public void run() + UIGroup uiGroup = null; + if (!MetaContactListSource.isRootGroup(parentGroup)) { - // 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) - { - UIContact uiContact - = MetaContactListSource.createUIContact(metaContact); + uiGroup = MetaContactListSource + .getUIGroup(parentGroup); - if (currentFilter.isMatching(uiContact)) - { - UIGroup uiGroup = null; - if (!MetaContactListSource.isRootGroup(parentGroup)) - { - uiGroup = MetaContactListSource - .getUIGroup(parentGroup); - - if (uiGroup == null) - uiGroup = MetaContactListSource - .createUIGroup(parentGroup); - } - - addContact(uiContact, uiGroup); - } - else - MetaContactListSource.removeUIContact(metaContact); - } + if (uiGroup == null) + uiGroup = MetaContactListSource + .createUIGroup(parentGroup); } - }); + + addContact(uiContact, uiGroup, true); + } + else + MetaContactListSource.removeUIContact(metaContact); } /** @@ -254,26 +220,13 @@ public void metaContactGroupAdded(MetaContactGroupEvent evt) { final MetaContactGroup metaGroup = evt.getSourceMetaContactGroup(); - 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) - { - UIGroup uiGroup - = MetaContactListSource.createUIGroup(metaGroup); + UIGroup uiGroup + = MetaContactListSource.createUIGroup(metaGroup); - if (currentFilter.isMatching(uiGroup)) - addGroup(uiGroup); - else - MetaContactListSource.removeUIGroup(metaGroup); - } - } - }); + if (currentFilter.isMatching(uiGroup)) + addGroup(uiGroup); + else + MetaContactListSource.removeUIGroup(metaGroup); } /** @@ -285,29 +238,16 @@ public void metaContactGroupModified(MetaContactGroupEvent evt) { final MetaContactGroup metaGroup = evt.getSourceMetaContactGroup(); - 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) - { - UIGroup uiGroup - = MetaContactListSource.getUIGroup(metaGroup); + UIGroup uiGroup + = MetaContactListSource.getUIGroup(metaGroup); - if (uiGroup != null) - { - GroupNode groupNode = uiGroup.getGroupNode(); + if (uiGroup != null) + { + GroupNode groupNode = uiGroup.getGroupNode(); - if (groupNode != null) - treeModel.nodeChanged(groupNode); - } - } - } - }); + if (groupNode != null) + treeModel.nodeChanged(groupNode); + } } /** @@ -318,25 +258,12 @@ public void run() */ public void metaContactGroupRemoved(final MetaContactGroupEvent evt) { - 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) - { - UIGroup uiGroup - = MetaContactListSource.getUIGroup( - evt.getSourceMetaContactGroup()); + UIGroup uiGroup + = MetaContactListSource.getUIGroup( + evt.getSourceMetaContactGroup()); - if (uiGroup != null) - removeGroup(uiGroup); - } - } - }); + if (uiGroup != null) + removeGroup(uiGroup); } /** @@ -346,31 +273,18 @@ public void run() */ public void metaContactModified(final MetaContactModifiedEvent evt) { - 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) - { - UIContact uiContact - = MetaContactListSource.getUIContact( - evt.getSourceMetaContact()); + UIContact uiContact + = MetaContactListSource.getUIContact( + evt.getSourceMetaContact()); - if (uiContact != null) - { - ContactNode contactNode - = uiContact.getContactNode(); + if (uiContact != null) + { + ContactNode contactNode + = uiContact.getContactNode(); - if (contactNode != null) - treeModel.nodeChanged(contactNode); - } - } - } - }); + if (contactNode != null) + treeModel.nodeChanged(contactNode); + } } /** @@ -384,56 +298,43 @@ public void metaContactMoved(final MetaContactMovedEvent evt) final MetaContactGroup oldParent = evt.getOldParent(); final MetaContactGroup newParent = evt.getNewParent(); - 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) - { - UIContact uiContact - = MetaContactListSource.getUIContact(metaContact); + UIContact uiContact + = MetaContactListSource.getUIContact(metaContact); - if (uiContact == null) - return; + if (uiContact == null) + return; - UIGroup oldUIGroup = null; - if (!MetaContactListSource.isRootGroup(oldParent)) - { - oldUIGroup = MetaContactListSource.getUIGroup(oldParent); - } - else - { - oldUIGroup = treeModel.getRoot().getGroupDescriptor(); - } + UIGroup oldUIGroup = null; + if (!MetaContactListSource.isRootGroup(oldParent)) + { + oldUIGroup = MetaContactListSource.getUIGroup(oldParent); + } + else + { + oldUIGroup = treeModel.getRoot().getGroupDescriptor(); + } - if (oldUIGroup != null) - removeContact(uiContact); + if (oldUIGroup != null) + removeContact(uiContact); - // Add the contact to the new place. - uiContact = MetaContactListSource.createUIContact( - evt.getSourceMetaContact()); + // Add the contact to the new place. + uiContact = MetaContactListSource.createUIContact( + evt.getSourceMetaContact()); - UIGroup newUIGroup = null; - if (!MetaContactListSource.isRootGroup(newParent)) - { - newUIGroup = MetaContactListSource.getUIGroup(newParent); + UIGroup newUIGroup = null; + if (!MetaContactListSource.isRootGroup(newParent)) + { + newUIGroup = MetaContactListSource.getUIGroup(newParent); - if (newUIGroup == null) - newUIGroup - = MetaContactListSource.createUIGroup(newParent); - } + if (newUIGroup == null) + newUIGroup + = MetaContactListSource.createUIGroup(newParent); + } - if (currentFilter.isMatching(uiContact)) - addContact(treeModel, uiContact, newUIGroup, true, true); - else - MetaContactListSource.removeUIContact(metaContact); - } - } - }); + if (currentFilter.isMatching(uiContact)) + addContact(uiContact, newUIGroup, true); + else + MetaContactListSource.removeUIContact(metaContact); } /** @@ -444,24 +345,11 @@ public void run() */ public void metaContactRemoved(final MetaContactEvent evt) { - 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) - { - UIContact uiContact = MetaContactListSource.getUIContact( - evt.getSourceMetaContact()); + UIContact uiContact = MetaContactListSource.getUIContact( + evt.getSourceMetaContact()); - if (uiContact != null) - removeContact(uiContact); - } - } - }); + if (uiContact != null) + removeContact(uiContact); } /** @@ -471,30 +359,17 @@ public void run() */ public void metaContactRenamed(final MetaContactRenamedEvent evt) { - 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) - { - UIContact uiContact - = MetaContactListSource.getUIContact( - evt.getSourceMetaContact()); + UIContact uiContact + = MetaContactListSource.getUIContact( + evt.getSourceMetaContact()); - if (uiContact != null) - { - ContactNode contactNode = uiContact.getContactNode(); + if (uiContact != null) + { + ContactNode contactNode = uiContact.getContactNode(); - if (contactNode != null) - treeModel.nodeChanged(contactNode); - } - } - } - }); + if (contactNode != null) + treeModel.nodeChanged(contactNode); + } } /** @@ -504,30 +379,17 @@ public void run() */ public void metaContactAvatarUpdated(final MetaContactAvatarUpdateEvent evt) { - 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) - { - UIContact uiContact - = MetaContactListSource.getUIContact( - evt.getSourceMetaContact()); + UIContact uiContact + = MetaContactListSource.getUIContact( + evt.getSourceMetaContact()); - if (uiContact != null) - { - ContactNode contactNode = uiContact.getContactNode(); + if (uiContact != null) + { + ContactNode contactNode = uiContact.getContactNode(); - if (contactNode != null) - treeModel.nodeChanged(contactNode); - } - } - } - }); + if (contactNode != null) + treeModel.nodeChanged(contactNode); + } } /** @@ -540,49 +402,36 @@ public void protoContactAdded(ProtoContactEvent evt) { final MetaContact metaContact = evt.getNewParent(); - SwingUtilities.invokeLater(new Runnable() + UIContact parentUIContact + = MetaContactListSource.getUIContact(metaContact); + + if (parentUIContact == null) { - public void run() + UIContact uiContact + = MetaContactListSource.createUIContact(metaContact); + + if (currentFilter.isMatching(uiContact)) { - // 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) + MetaContactGroup parentGroup + = metaContact.getParentMetaContactGroup(); + + UIGroup uiGroup = null; + if (!MetaContactListSource + .isRootGroup(parentGroup)) { - UIContact parentUIContact - = MetaContactListSource.getUIContact(metaContact); + uiGroup = MetaContactListSource + .getUIGroup(parentGroup); - if (parentUIContact == null) - { - UIContact uiContact - = MetaContactListSource.createUIContact(metaContact); - - if (currentFilter.isMatching(uiContact)) - { - MetaContactGroup parentGroup - = metaContact.getParentMetaContactGroup(); - - UIGroup uiGroup = null; - if (!MetaContactListSource - .isRootGroup(parentGroup)) - { - uiGroup = MetaContactListSource - .getUIGroup(parentGroup); - - if (uiGroup == null) - uiGroup = MetaContactListSource - .createUIGroup(parentGroup); - } - - addContact(uiContact, uiGroup); - } - else - MetaContactListSource.removeUIContact(metaContact); - } + if (uiGroup == null) + uiGroup = MetaContactListSource + .createUIGroup(parentGroup); } + + addContact(uiContact, uiGroup, true); } - }); + else + MetaContactListSource.removeUIContact(metaContact); + } } public void protoContactModified(ProtoContactEvent evt) {} @@ -598,60 +447,47 @@ public void protoContactMoved(ProtoContactEvent evt) final MetaContact oldParent = evt.getOldParent(); final MetaContact newParent = evt.getNewParent(); - SwingUtilities.invokeLater(new Runnable() + UIContact oldUIContact + = MetaContactListSource.getUIContact(oldParent); + + // Remove old parent if not matching. + if (oldUIContact != null + && !currentFilter.isMatching(oldUIContact)) { - 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) - { - UIContact oldUIContact - = MetaContactListSource.getUIContact(oldParent); + removeContact(oldUIContact); + } - // Remove old parent if not matching. - if (oldUIContact != null - && !currentFilter.isMatching(oldUIContact)) - { - removeContact(oldUIContact); - } + // Add new parent if matching. + UIContact newUIContact + = MetaContactListSource.getUIContact(newParent); - // Add new parent if matching. - UIContact newUIContact - = MetaContactListSource.getUIContact(newParent); + if (newUIContact == null) + { + newUIContact + = MetaContactListSource.createUIContact(newParent); - if (newUIContact == null) - { - newUIContact - = MetaContactListSource.createUIContact(newParent); - - if (currentFilter.isMatching(newUIContact)) - { - MetaContactGroup parentGroup - = newParent.getParentMetaContactGroup(); - - UIGroup uiGroup = null; - if (!MetaContactListSource - .isRootGroup(parentGroup)) - { - uiGroup = MetaContactListSource - .getUIGroup(parentGroup); - - if (uiGroup == null) - uiGroup = MetaContactListSource - .createUIGroup(parentGroup); - } - - addContact(newUIContact, uiGroup); - } - else - MetaContactListSource.removeUIContact(newParent); - } + if (currentFilter.isMatching(newUIContact)) + { + MetaContactGroup parentGroup + = newParent.getParentMetaContactGroup(); + + UIGroup uiGroup = null; + if (!MetaContactListSource + .isRootGroup(parentGroup)) + { + uiGroup = MetaContactListSource + .getUIGroup(parentGroup); + + if (uiGroup == null) + uiGroup = MetaContactListSource + .createUIGroup(parentGroup); } + + addContact(newUIContact, uiGroup, true); } - }); + else + MetaContactListSource.removeUIContact(newParent); + } } /** @@ -664,24 +500,11 @@ public void protoContactRemoved(ProtoContactEvent evt) { final MetaContact oldParent = evt.getOldParent(); - 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) - { - UIContact oldUIContact - = MetaContactListSource.getUIContact(oldParent); + UIContact oldUIContact + = MetaContactListSource.getUIContact(oldParent); - if (oldUIContact != null) - removeContact(oldUIContact); - } - } - }); + if (oldUIContact != null) + removeContact(oldUIContact); } /** @@ -692,40 +515,67 @@ public void contactReceived(ContactReceivedEvent event) { final SourceContact sourceContact = event.getContact(); - SwingUtilities.invokeLater(new Runnable() + ContactSourceService contactSource + = sourceContact.getContactSource(); + + ExternalContactSource sourceUI + = TreeContactList.getContactSource(contactSource); + + if (sourceUI == null) + return; + + UIContact uiContact + = sourceUI.createUIContact(sourceContact); + + // ExtendedContactSourceService has already matched the + // SourceContact over the pattern + if((contactSource instanceof ExtendedContactSourceService) + || currentFilter.isMatching(uiContact)) { - 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(); + addContact(uiContact, sourceUI.getUIGroup(), false); + } + else + uiContact = null; + } - ExternalContactSource sourceUI - = TreeContactList.getContactSource(contactSource); + /** + * Indicates that a MetaContact has been received for a search in + * the MetaContactListService. + * @param metaContact the received MetaContact + */ + public void metaContactReceived(MetaContact metaContact) + { + MetaContactGroup parentGroup = metaContact.getParentMetaContactGroup(); - if (sourceUI == null) - return; + if (filterQuery != null) + filterQuery.setSucceeded(true); - UIContact uiContact - = sourceUI.createUIContact(sourceContact); + UIGroup uiGroup = null; + if (!MetaContactListSource.isRootGroup(parentGroup)) + { + uiGroup = MetaContactListSource + .getUIGroup(parentGroup); - // ExtendedContactSourceService has already matched the - // SourceContact over the pattern - if((contactSource instanceof ExtendedContactSourceService) - || currentFilter.isMatching(uiContact)) - { - addContact(uiContact, sourceUI.getUIGroup()); - } - else - uiContact = null; - } - } - }); + if (uiGroup == null) + uiGroup = MetaContactListSource + .createUIGroup(parentGroup); + } + + GuiActivator.getContactList().addContact( + MetaContactListSource.createUIContact(metaContact), + uiGroup, + true); + } + + /** + * Indicates that a MetaGroup has been received from a search in + * the MetaContactListService. + * @param metaGroup the MetaGroup that has been received + */ + public void metaGroupReceived(MetaContactGroup metaGroup) + { + GuiActivator.getContactList().addGroup( + MetaContactListSource.createUIGroup(metaGroup)); } /** @@ -775,37 +625,30 @@ public void deactivateAll() */ public void setActiveContact(MetaContact metaContact, boolean isActive) { - // 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) - { - UIContact uiContact - = MetaContactListSource.getUIContact(metaContact); + UIContact uiContact + = MetaContactListSource.getUIContact(metaContact); - if (uiContact == null) - return; + if (uiContact == null) + return; - ContactNode contactNode = uiContact.getContactNode(); + ContactNode contactNode = uiContact.getContactNode(); - if (contactNode != null) - { - contactNode.setActive(isActive); + if (contactNode != null) + { + contactNode.setActive(isActive); - if (isActive) - { - activeContacts.add(contactNode); + if (isActive) + { + activeContacts.add(contactNode); // SystrayService stray = GuiActivator.getSystrayService(); // // if (stray != null) // stray.setSystrayIcon(SystrayService.ENVELOPE_IMG_TYPE); - } - else - activeContacts.remove(contactNode); - - treeModel.nodeChanged(contactNode); } + else + activeContacts.remove(contactNode); + + treeModel.nodeChanged(contactNode); } } @@ -828,30 +671,26 @@ public boolean isContactActive(UIContact contact) /** * Adds the given contact to this list. * @param contact the UIContact to add - * @param group the parent UIGroup to add to - */ - public void addContact(UIContact contact, UIGroup group) - { - addContact(treeModel, contact, group, true, true); - } - - /** - * Adds the given contact to this list. - * @param treeModel the ContactListTreeModel, to which this contact - * should be added - * @param contact the UIContact to add * @param group the UIGroup to add to * @param isSorted indicates if the contact should be sorted regarding to * the GroupNode policy - * @param isRefreshView indicates if the view should be refreshed after - * adding the contact - */ - public void addContact( ContactListTreeModel treeModel, - UIContact contact, - UIGroup group, - boolean isSorted, - boolean isRefreshView) + */ + public void addContact( final UIContact contact, + final UIGroup group, + final boolean isSorted) { + if (!SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + addContact(contact, group, isSorted); + } + }); + return; + } + GroupNode groupNode; if (group == null) groupNode = treeModel.getRoot(); @@ -860,20 +699,23 @@ public void addContact( ContactListTreeModel treeModel, groupNode = group.getGroupNode(); if (groupNode == null) - groupNode = addGroup(treeModel, group, isRefreshView); + { + GroupNode parentNode = treeModel.getRoot(); + + groupNode = parentNode.sortedAddContactGroup(group); + } } contact.setParentGroup(groupNode.getGroupDescriptor()); if (isSorted) - groupNode.sortedAddContact(contact, isRefreshView); + groupNode.sortedAddContact(contact); else groupNode.addContact(contact); if ((!currentFilter.equals(presenceFilter) - || !groupNode.isCollapsed()) - && isRefreshView) - this.expandGroup(treeModel, groupNode); + || !groupNode.isCollapsed())) + this.expandGroup(groupNode); } /** @@ -881,8 +723,20 @@ public void addContact( ContactListTreeModel treeModel, * this list. * @param contact the UIContact to remove */ - public void removeContact(UIContact contact) + public void removeContact(final UIContact contact) { + if (!SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + removeContact(contact); + } + }); + return; + } + UIGroup parentGroup = contact.getParentGroup(); if (parentGroup == null) @@ -907,42 +761,46 @@ public void removeContact(UIContact contact) /** * Adds the given group to this list. * @param group the UIGroup to add - * @return the created GroupNode corresponding to the group */ - public GroupNode addGroup(UIGroup group) + public void addGroup(final UIGroup group) { - return addGroup(treeModel, group, true); - } + if (!SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + addGroup(group); + } + }); + return; + } - /** - * Adds the given group to this list. - * @param treeModel the ContactListTreeModel, to which the given - * group should be added - * @param group the UIGroup to add - * @param isRefreshView indicates if the view should be refreshed after - * adding the group - * @return the created GroupNode corresponding to the group - */ - public GroupNode addGroup( ContactListTreeModel treeModel, - UIGroup group, - boolean isRefreshView) - { GroupNode parentNode = treeModel.getRoot(); - GroupNode groupNode = parentNode - .sortedAddContactGroup(group, isRefreshView); - - expandPath(new TreePath(treeModel.getRoot().getPath())); + parentNode.sortedAddContactGroup(group); - return groupNode; + expandGroup(treeModel.getRoot()); } /** * Removes the given group and its children from the list. * @param group the UIGroup to remove */ - private void removeGroup(UIGroup group) + private void removeGroup(final UIGroup group) { + if (!SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + removeGroup(group); + } + }); + return; + } + UIGroup parentGroup = group.getParentGroup(); GroupNode parentGroupNode @@ -1002,7 +860,6 @@ public void setGroupClickConsumed(boolean isGroupClickConsumed) */ public void stopFiltering() { - this.isFiltering = false; currentFilter.stopFilter(); if (filterQuery != null) @@ -1014,7 +871,7 @@ public void stopFiltering() */ public void applyDefaultFilter() { - MainFrame mainFrame = GuiActivator.getUIService().getMainFrame(); + final MainFrame mainFrame = GuiActivator.getUIService().getMainFrame(); String currentSearchText = mainFrame.getCurrentSearchText(); if (currentSearchText != null @@ -1022,21 +879,32 @@ public void applyDefaultFilter() { // The clear will automatically apply the default filter after // the remove text event is triggered! - mainFrame.clearCurrentSearchText(); + if (!SwingUtilities.isEventDispatchThread()) + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + mainFrame.clearCurrentSearchText(); + } + }); + else + mainFrame.clearCurrentSearchText(); } else - applyFilter(defaultFilter, new ContactListTreeModel(), null); + { + treeModel.clear(); + applyFilter(defaultFilter, null); + } } /** * Applies the given filter. * @param filter the ContactListFilter to apply. - * @return true if the filter has any matches, false - * otherwise */ - public boolean applyFilter(ContactListFilter filter) + public void applyFilter(ContactListFilter filter) { - return applyFilter(filter, new ContactListTreeModel(), null); + treeModel.clear(); + applyFilter(filter, null); } /** @@ -1047,13 +915,13 @@ public boolean applyFilter(ContactListFilter filter) */ public FilterQuery applyFilter(final ContactListSourceFilter filter) { - final ContactListTreeModel tempTreeModel = new ContactListTreeModel(); - filterQuery = new FilterQuery(); + treeModel.clear(); + // If the filter has a default contact source, we apply it first. if (filter.hasDefaultSource()) - filterQuery.setSucceeded(applyFilter(filter, tempTreeModel, null)); + applyFilter(filter, null); Iterator filterSources = filter.getContactSources().iterator(); @@ -1066,19 +934,7 @@ public FilterQuery applyFilter(final ContactListSourceFilter filter) if (filterQuery.isCanceled()) return filterQuery; - new Thread() - { - public void run() - { - boolean isSucceeded - = applyFilter( filter, - tempTreeModel, - filterSource); - - if (!filterQuery.isSucceeded() && isSucceeded) - filterQuery.setSucceeded(true); - } - }.start(); + applyFilter(filter, filterSource); } return filterQuery; } @@ -1087,88 +943,43 @@ public void run() * Applies the given filter 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 ExternalContactSource to apply the * filter to - * @return true to indicate that the filter has found a match, - * false if no matches were found and the contact list is then - * empty. */ - private boolean applyFilter(ContactListFilter filter, - ContactListTreeModel tempTreeModel, - ExternalContactSource contactSource) + private void applyFilter( final ContactListFilter filter, + final ExternalContactSource contactSource) { - // We set the isFiltering to true to indicate that we're currently - // filtering. - isFiltering = true; - - if (currentFilter == null || !currentFilter.equals(filter)) - this.currentFilter = filter; - - // 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. - synchronized (filterLock) + // If we're in the event dispatch thread we move to another thread + // for the filtering. + if (SwingUtilities.isEventDispatchThread()) { - treeModel.clearDependencies(); - - // 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) + new Thread() { - ContactQuery contactQuery - = ((ContactListSourceFilter) currentFilter) - .applyFilter(contactSource, tempTreeModel); - - filterQuery.addContactQuery(contactQuery); - } - else - currentFilter.applyFilter(tempTreeModel); - - treeModel = tempTreeModel; + public void run() + { + applyFilter(filter, contactSource); + } + }.start(); + return; } - // If in the mean time someone has stopped filtering we return here. - if (!isFiltering) - { - return (treeModel.getChildCount(treeModel.getRoot()) > 0); - } + if (currentFilter == null || !currentFilter.equals(filter)) + this.currentFilter = filter; - SwingUtilities.invokeLater(new Runnable() + // 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) { - public void run() - { - // Set the updated treeModel to the tree component. - setTreeModel(treeModel); - - // Refresh the view. - treeModel.reload(); - - // Expand all rows. Should be done only after the new model - // is visible to have effect. - expandAllRows(); + ContactQuery contactQuery + = ((ContactListSourceFilter) currentFilter) + .applyFilter(contactSource); - // We should explicitly re-validate the whole tree as we - // changed its model. - revalidate(); - repaint(); - } - }); - - // We set the isFiltering to false to indicate that we finished - // filtering. - isFiltering = false; - - boolean hasResults = false; - - // As we update the tree in the swing thread, we should check the - // temporary model here in order to given correct results. - if (tempTreeModel.getChildCount(tempTreeModel.getRoot()) > 0) - hasResults = true; - - return hasResults; + filterQuery.addContactQuery(contactQuery); + } + else + currentFilter.applyFilter(); } /** @@ -1199,17 +1010,10 @@ public void selectFirstContact() { 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) - { - ContactNode contactNode = treeModel.findFirstContactNode(); + ContactNode contactNode = treeModel.findFirstContactNode(); - if (contactNode != null) - setSelectionPath(new TreePath(contactNode.getPath())); - } + if (contactNode != null) + setSelectionPath(new TreePath(contactNode.getPath())); } }); } @@ -1269,41 +1073,27 @@ protected void fireContactListEvent( /** * Expands the given group node. - * @param treeModel the treeModel in which we expand the group * @param groupNode the group node to expand */ - private void expandGroup( ContactListTreeModel treeModel, - GroupNode groupNode) + private void expandGroup(GroupNode groupNode) { - TreePath path = new TreePath(treeModel.getPathToRoot(groupNode)); + final TreePath path = new TreePath(treeModel.getPathToRoot(groupNode)); if (!isExpanded(path)) - expandPath(path); - } - - /** - * Expands all rows if the current filter is the SearchFilter and - * expands only "not collapsed" groups for any other filter. - */ - private void expandAllRows() - { - for (int i = 0; i < getRowCount(); i++) - { - TreePath treePath = getPathForRow(i); - - Object c = treePath.getLastPathComponent(); - - GroupNode groupNode = null; - if (!(c instanceof GroupNode)) - continue; + if (!SwingUtilities.isEventDispatchThread()) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + expandPath(path); + } + }); + } else - groupNode = (GroupNode) c; - - if (groupNode != null - && (currentFilter.equals(searchFilter) - || !groupNode.isCollapsed())) - expandRow(i); - } + { + expandPath(path); + } } /** @@ -1628,7 +1418,7 @@ public void actionPerformed(ActionEvent e) GroupNode groupNode = (GroupNode) selectionPath.getLastPathComponent(); - expandGroup(treeModel, groupNode); + expandGroup(groupNode); } }}); @@ -1840,56 +1630,43 @@ public void contactPresenceStatusChanged( || (evt.getOldStatus() == evt.getNewStatus())) return; - SwingUtilities.invokeLater(new Runnable() + UIContact uiContact + = MetaContactListSource.getUIContact(metaContact); + + if (uiContact == null) { - public void run() + uiContact = MetaContactListSource + .createUIContact(metaContact); + + if (currentFilter.isMatching(uiContact)) { - // 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) + MetaContactGroup parentGroup + = metaContact.getParentMetaContactGroup(); + + UIGroup uiGroup = null; + if (!MetaContactListSource.isRootGroup(parentGroup)) { - UIContact uiContact - = MetaContactListSource.getUIContact(metaContact); + uiGroup = MetaContactListSource + .getUIGroup(parentGroup); - if (uiContact == null) - { - uiContact = MetaContactListSource - .createUIContact(metaContact); - - if (currentFilter.isMatching(uiContact)) - { - MetaContactGroup parentGroup - = metaContact.getParentMetaContactGroup(); - - UIGroup uiGroup = null; - if (!MetaContactListSource.isRootGroup(parentGroup)) - { - uiGroup = MetaContactListSource - .getUIGroup(parentGroup); - - if (uiGroup == null) - uiGroup = MetaContactListSource - .createUIGroup(parentGroup); - } - - addContact(uiContact, uiGroup); - } - else - MetaContactListSource - .removeUIContact(metaContact); - } - else - { - if (!currentFilter.isMatching(uiContact)) - removeContact(uiContact); - else - treeModel - .nodeChanged(uiContact.getContactNode()); - } + if (uiGroup == null) + uiGroup = MetaContactListSource + .createUIGroup(parentGroup); } + + addContact(uiContact, uiGroup, true); } - }); + else + MetaContactListSource + .removeUIContact(metaContact); + } + else + { + if (!currentFilter.isMatching(uiContact)) + removeContact(uiContact); + else + treeModel + .nodeChanged(uiContact.getContactNode()); + } } } diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/MetaContactListSource.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/MetaContactListSource.java index 3efe09cfd..9943f7528 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/MetaContactListSource.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/contactsource/MetaContactListSource.java @@ -44,6 +44,12 @@ public class MetaContactListSource */ private boolean isFiltering = false; + /** + * The MetaContactQueryListener listens for MetaContacts + * and MetaGroups received as a result of a filtering. + */ + private static MetaContactQueryListener queryListener; + /** * Returns the UIContact corresponding to the given * MetaContact. @@ -144,15 +150,12 @@ public void stopFiltering() * filterPattern and stores the result in the given * treeModel. * @param filterPattern the pattern to filter through - * @param treeModel the ContactListTreeModel, in which we store - * the results */ - public void filter(Pattern filterPattern, ContactListTreeModel treeModel) + public void filter(Pattern filterPattern) { isFiltering = true; - filter(filterPattern, treeModel, - GuiActivator.getContactListService().getRoot()); + filter(filterPattern, GuiActivator.getContactListService().getRoot()); isFiltering = false; } @@ -162,12 +165,9 @@ public void filter(Pattern filterPattern, ContactListTreeModel treeModel) * given filterPattern and stores the result in the given * treeModel. * @param filterPattern the pattern to filter through - * @param treeModel the ContactListTreeModel, in which we store - * the results * @param parentGroup the MetaContactGroup to filter */ private void filter(Pattern filterPattern, - ContactListTreeModel treeModel, MetaContactGroup parentGroup) { Iterator childContacts = parentGroup.getChildContacts(); @@ -178,23 +178,7 @@ private void filter(Pattern filterPattern, if (isMatching(filterPattern, metaContact)) { - UIGroup uiGroup = null; - if (!MetaContactListSource.isRootGroup(parentGroup)) - { - uiGroup = MetaContactListSource - .getUIGroup(parentGroup); - - if (uiGroup == null) - uiGroup = MetaContactListSource - .createUIGroup(parentGroup); - } - - GuiActivator.getContactList().addContact( - treeModel, - MetaContactListSource.createUIContact(metaContact), - uiGroup, - true, - false); + fireQueryEvent(metaContact); } } @@ -203,7 +187,7 @@ private void filter(Pattern filterPattern, { MetaContactGroup subgroup = subgroups.next(); - filter(filterPattern, treeModel, subgroup); + filter(filterPattern, subgroup); } } @@ -267,4 +251,45 @@ public boolean isMatching(Pattern filterPattern, MetaContactGroup metaGroup) } return false; } + + /** + * Sets the given MetaContactQueryListener to listen for query + * events coming from MetaContactListService filtering. + * @param l the MetaContactQueryListener to set + */ + public static void setMetaContactQueryListener(MetaContactQueryListener l) + { + queryListener = l; + } + + /** + * Returns the currently registered MetaContactQueryListener. + * @return the currently registered MetaContactQueryListener + */ + public static MetaContactQueryListener getMetaContactQueryListener() + { + return queryListener; + } + + /** + * Notifies the MetaContactQueryListener that a new + * MetaContact has been received as a result of a search. + * @param metaContact the received MetaContact + */ + public static void fireQueryEvent(MetaContact metaContact) + { + if (queryListener != null) + queryListener.metaContactReceived(metaContact); + } + + /** + * Notifies the MetaContactQueryListener that a new + * MetaGroup has been received as a result of a search. + * @param metaGroup the received MetaGroup + */ + public static void fireQueryEvent(MetaContactGroup metaGroup) + { + if (queryListener != null) + queryListener.metaGroupReceived(metaGroup); + } }