| /*=============================================================================# |
| # Copyright (c) 2014, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.r.ui.search; |
| |
| import java.util.ArrayList; |
| import java.util.Comparator; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.jface.viewers.TreePath; |
| import org.eclipse.jface.viewers.TreeViewer; |
| import org.eclipse.ui.views.navigator.ResourceComparator; |
| |
| import org.eclipse.statet.jcommons.collections.SortedArraySet; |
| import org.eclipse.statet.jcommons.collections.SortedListSet; |
| |
| import org.eclipse.statet.ecommons.workbench.search.ui.ExtTextSearchResult; |
| import org.eclipse.statet.ecommons.workbench.search.ui.LineElement; |
| import org.eclipse.statet.ecommons.workbench.search.ui.TextSearchResultTreeContentProvider; |
| |
| import org.eclipse.statet.ltk.model.core.element.SourceUnit; |
| import org.eclipse.statet.r.core.model.RSourceUnit; |
| |
| |
| public class RElementSearchResultTreeContentProvider extends TextSearchResultTreeContentProvider<RSourceUnit, RElementMatch> { |
| |
| |
| private static class LevelComparator extends ResourceComparator implements Comparator<Object> { |
| |
| |
| public LevelComparator() { |
| super(NAME); |
| } |
| |
| |
| @Override |
| public int compare(Object o1, Object o2) { |
| if (o1 instanceof SourceUnit) { |
| o1= ((SourceUnit)o1).getResource(); |
| } |
| if (o2 instanceof SourceUnit) { |
| o2= ((SourceUnit)o2).getResource(); |
| } |
| return compare(null, o1, o2); |
| } |
| |
| } |
| |
| |
| protected static final int BY_PROJECT= 1; |
| protected static final int BY_SOURCE_UNIT= 5; |
| |
| |
| private int level= BY_PROJECT; |
| |
| private final Map<Object, SortedListSet<Object>> levelChildren= new HashMap<>(); |
| |
| |
| public RElementSearchResultTreeContentProvider(final RElementSearchResultPage page, final TreeViewer viewer) { |
| super(page, viewer); |
| } |
| |
| |
| @Override |
| protected void reset() { |
| super.reset(); |
| this.levelChildren.clear(); |
| } |
| |
| public void setLevel(final int level) { |
| this.level= level; |
| clear(); |
| } |
| |
| @Override |
| protected int getElementLimit() { |
| if (this.level < BY_SOURCE_UNIT) { |
| return Integer.MAX_VALUE; |
| } |
| return super.getElementLimit(); |
| } |
| |
| @Override |
| public Object[] getElements(final Object inputElement) { |
| if (this.level < BY_SOURCE_UNIT) { |
| if (!this.active) { |
| final ExtTextSearchResult<RSourceUnit, RElementMatch> result= getInput(); |
| assert (inputElement == result); |
| if (result == null) { |
| return NO_ELEMENTS; |
| } |
| assert (this.levelChildren.isEmpty()); |
| |
| final RSourceUnit[] elements= result.getElements(); |
| for (int i= 0; i < elements.length; i++) { |
| doAdd(null, elements[i]); |
| } |
| this.active= true; |
| } |
| final SortedListSet<Object> children= this.levelChildren.get(null); |
| return (children != null) ? children.toArray() : NO_ELEMENTS; |
| } |
| return super.getElements(inputElement); |
| } |
| |
| @Override |
| public Object getParent(final Object element) { |
| if (element instanceof SourceUnit) { |
| if (this.level < BY_SOURCE_UNIT) { |
| final IFile file= (IFile)((SourceUnit)element).getResource(); |
| return file.getParent(); |
| } |
| } |
| if (element instanceof IResource) { |
| if (element instanceof IProject) { |
| return null; |
| } |
| return ((IResource) element).getParent(); |
| } |
| if (element instanceof LineElement) { |
| return ((LineElement<?>) element).getElement(); |
| } |
| return super.getParent(element); |
| } |
| |
| @Override |
| public Object[] getChildren(final Object parentElement) { |
| if (parentElement instanceof IResource) { |
| final SortedListSet<Object> children= this.levelChildren.get(parentElement); |
| return (children != null) ? children.toArray() : NO_ELEMENTS; |
| } |
| return super.getChildren(parentElement); |
| } |
| |
| @Override |
| public Object[] getShownMatches(final RElementMatch[] matches) { |
| final List<LineElement<?>> groups= new ArrayList<>(); |
| LineElement<?> lastGroup= null; |
| for (int i= 0; i < matches.length; i++) { |
| final LineElement<?> group= matches[i].getMatchGroup(); |
| if (group != lastGroup) { |
| groups.add(group); |
| lastGroup= group; |
| } |
| } |
| return groups.toArray(); |
| } |
| |
| |
| @Override |
| protected void addElement(final TreeViewer viewer, final RSourceUnit element, final int idx) { |
| if (this.level < BY_SOURCE_UNIT) { |
| doAdd(viewer, element); |
| } |
| else { |
| super.addElement(viewer, element, idx); |
| } |
| } |
| |
| protected void doAdd(final TreeViewer viewer, final Object element) { |
| final Object parent= getParent(element); |
| SortedListSet<Object> children= this.levelChildren.get(parent); |
| if (children == null) { |
| if (parent != null) { |
| doAdd(viewer, parent); |
| } |
| children= new SortedArraySet<>(NO_ELEMENTS, new LevelComparator()); |
| this.levelChildren.put(parent, children); |
| } |
| final int idx; |
| if ((idx= children.addE(element)) >= 0) { |
| if (viewer != null) { |
| viewer.insert((parent != null) ? parent : TreePath.EMPTY, element, idx); |
| } |
| } |
| } |
| |
| @Override |
| protected void removeElement(final TreeViewer viewer, final RSourceUnit element, final int idx) { |
| if (this.level < BY_SOURCE_UNIT) { |
| doRemove(viewer, element); |
| } |
| else { |
| super.removeElement(viewer, element, idx); |
| } |
| } |
| |
| protected void doRemove(final TreeViewer viewer, final Object element) { |
| final Object parent= getParent(element); |
| final SortedListSet<Object> children= this.levelChildren.get(parent); |
| if (children == null) { |
| return; |
| } |
| if (children.removeE(element) >= 0) { |
| if (children.isEmpty() && parent != null) { |
| doRemove(viewer, parent); |
| } |
| else if (viewer != null) { |
| viewer.remove(element); |
| } |
| } |
| } |
| |
| } |