/** * Copyright (c) 20015 by Brainwy Software Ltda. All Rights Reserved. * Licensed under the terms of the Eclipse Public License (EPL). * Please see the license.txt included with this distribution for details. * Any modifications to this file must keep this entire header intact. */ package org.python.pydev.shared_ui.search; import java.util.HashMap; import java.util.Map; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.search.ui.text.AbstractTextSearchResult; import org.eclipse.search.ui.text.Match; import org.python.pydev.shared_core.log.Log; import org.python.pydev.shared_core.structure.TreeNode; import org.python.pydev.shared_core.structure.TreeNodeContentProvider; public abstract class AbstractSearchIndexTreeContentProvider extends TreeNodeContentProvider implements ITreeContentProvider, ISearchIndexContentProvider { protected TreeNode<Object> root; protected Map<Object, TreeNode<?>> elementToTreeNode = new HashMap<>(); protected TreeViewer viewer; protected AbstractTextSearchResult fResult; public int groupWith = 0; public AbstractSearchIndexTreeContentProvider(TreeViewer viewer) { this.viewer = viewer; } @Override public void setGroupWith(int groupWith) { if (this.groupWith == groupWith) { return; } this.groupWith = groupWith; // Pretend the input changed (as the whole structure changed). this.inputChanged(this.viewer, null, fResult); this.clearFilterCaches(); // And at last, ask for a refresh! this.viewer.refresh(); } protected void clearFilterCaches() { ViewerFilter[] filters = this.viewer.getFilters(); if (filters != null) { for (ViewerFilter viewerFilter : filters) { if (viewerFilter instanceof AbstractSearchResultsViewerFilter) { AbstractSearchResultsViewerFilter filter = (AbstractSearchResultsViewerFilter) viewerFilter; filter.clearCache(); } } } } public int getGroupWith() { return groupWith; } @Override public void dispose() { super.dispose(); } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { elementToTreeNode.clear(); if (newInput instanceof AbstractTextSearchResult) { AbstractTextSearchResult abstractTextSearchResult = (AbstractTextSearchResult) newInput; this.fResult = abstractTextSearchResult; root = new TreeNode<>(null, newInput); Object[] elements = abstractTextSearchResult.getElements(); int elementsLen = elements.length; for (int i = 0; i < elementsLen; i++) { Object object = elements[i]; Match[] matches = abstractTextSearchResult.getMatches(object); int matchesLen = matches.length; for (int j = 0; j < matchesLen; j++) { Match match = matches[j]; if (match instanceof ICustomMatch) { ICustomMatch moduleMatch = (ICustomMatch) match; obtainTeeNodeElement(moduleMatch.getLineElement()); } else { Log.log("Expecting ICustomMatch. Found:" + match.getClass() + " - " + match); } } } } else { this.clear(); } } @Override public Object[] getElements(Object inputElement) { return getChildren(root); } @Override public void elementsChanged(Object[] updatedElements) { for (int i = 0; i < updatedElements.length; i++) { Object object = updatedElements[i]; int matchCount; if (object instanceof ICustomLineElement) { ICustomLineElement iCustomLineElement = (ICustomLineElement) object; matchCount = iCustomLineElement.getNumberOfMatches(fResult); } else { matchCount = fResult.getMatchCount(updatedElements[i]); } if (matchCount > 0) { obtainTeeNodeElement(object); } else { TreeNode<?> treeNode = this.elementToTreeNode.get(object); if (treeNode != null) { Object parent = treeNode.getParent(); treeNode.detachFromParent(); if (parent instanceof TreeNode<?>) { checkClearParentTree((TreeNode<?>) parent); } } } } this.viewer.refresh(); } private void checkClearParentTree(TreeNode<?> treeNode) { if (!treeNode.hasChildren()) { Object parent = treeNode.getParent(); treeNode.detachFromParent(); if (parent instanceof TreeNode<?>) { checkClearParentTree((TreeNode<?>) parent); } } } @Override public void clear() { root = new TreeNode<Object>(null, null); this.elementToTreeNode.clear(); this.clearFilterCaches(); this.viewer.refresh(); } /** * Subclasses should override to actually create the structure */ protected abstract TreeNode<?> obtainTeeNodeElement(final Object object); }