package org.iplantc.phyloviewer.viewer.client.render; import java.util.logging.Level; import java.util.logging.Logger; import org.iplantc.phyloviewer.client.tree.viewer.View; import org.iplantc.phyloviewer.shared.model.ITree; import org.iplantc.phyloviewer.shared.model.Node; import org.iplantc.phyloviewer.shared.model.Node.NodeListener; import org.iplantc.phyloviewer.shared.render.RenderPreferences; import org.iplantc.phyloviewer.viewer.client.model.RemoteNode; import org.iplantc.phyloviewer.viewer.client.services.SearchServiceAsyncImpl; import org.iplantc.phyloviewer.viewer.client.services.SearchService.SearchResult; import org.iplantc.phyloviewer.viewer.client.services.SearchServiceAsyncImpl.SearchResultListener; /** * Listens to a SearchServiceAsyncImpl for search results and highlights the ancestors of the result * nodes in the tree. Also listens to the nodes in a view's tree for new children and highlights them if * they are ancestors of the search result nodes. */ public class SearchHighlighter implements SearchResultListener, NodeListener { private View view; private ITree tree; private final SearchServiceAsyncImpl searchService; private RenderPreferences renderPreferences; public SearchHighlighter(SearchServiceAsyncImpl searchService) { this.searchService = searchService; searchService.addSearchResultListener(this); } public void dispose() { searchService.removeSearchResultListener(this); this.clear(); } public void setView(View view) { this.view = view; } public void setRenderPreferences(RenderPreferences renderPreferences) { this.renderPreferences = renderPreferences; } public void setTree(ITree tree) { clearNodeListener(); this.tree = tree; if(tree != null) { ((Node)tree.getRootNode()).addNodeListener(this); } } @Override public void handleSearchResult(SearchResult[] result, String query, int treeID) { if(renderPreferences != null) { renderPreferences.clearAllHighlights(); } if(tree != null) { highlightSubtree((RemoteNode)tree.getRootNode()); } Logger.getLogger("").log(Level.INFO, "Rendering: new set of search results were highlighted"); if(view != null) { view.requestRender(); } } @Override public void handleChildren(Node[] children) { if(children instanceof RemoteNode[] && searchService.getLastResult() != null && searchService.getLastResult().length > 0) { for(RemoteNode child : (RemoteNode[])children) { highlightSubtree(child); } Logger.getLogger("").log(Level.INFO, "Rendering: new nodes were fetched and highlighting was updated"); view.requestRender(); } } private void highlightSubtree(RemoteNode node) { node.addNodeListener(this); for(SearchResult result : searchService.getLastResult()) { if(node.subtreeContains(result.node)) { renderPreferences.highlightNode(node); renderPreferences.highlightBranch(node); } } if(node.getChildren() != null) { for(RemoteNode child : node.getChildren()) { highlightSubtree(child); } } } /** * Removes this listener from all of the nodes of the tree */ public void clear() { if(renderPreferences != null) { renderPreferences.clearAllHighlights(); } clearNodeListener(); } private void clearNodeListener() { if(tree != null) { Node root = (Node)tree.getRootNode(); if(root != null) { root.removeNodeListenerFromSubtree(this); } } } }