X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scl.ui%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fui%2Fsearch%2FSCLSearchResultPage.java;fp=bundles%2Forg.simantics.scl.ui%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fui%2Fsearch%2FSCLSearchResultPage.java;h=ebc2cbf9ed9c3f144aa65168ef10711e8a83cda6;hb=b2561fc60dbe74e8c332025b61cae104f5ccfc66;hp=0000000000000000000000000000000000000000;hpb=60887e497000cd31f5e5f2008d681b8612a21d26;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/search/SCLSearchResultPage.java b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/search/SCLSearchResultPage.java new file mode 100644 index 000000000..ebc2cbf9e --- /dev/null +++ b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/search/SCLSearchResultPage.java @@ -0,0 +1,323 @@ +package org.simantics.scl.ui.search; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jface.viewers.AbstractTreeViewer; +import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider; +import org.eclipse.jface.viewers.DecorationContext; +import org.eclipse.jface.viewers.IBaseLabelProvider; +import org.eclipse.jface.viewers.IColorProvider; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.ILabelProviderListener; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.OpenEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.StyledString; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerComparator; +import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider.IStyledLabelProvider; +import org.eclipse.search.ui.text.AbstractTextSearchResult; +import org.eclipse.search.ui.text.AbstractTextSearchViewPage; +import org.eclipse.search.ui.text.Match; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.simantics.scl.compiler.module.debug.SymbolReference; +import org.simantics.scl.ui.editor2.OpenDeclaration; +import org.simantics.scl.ui.editor2.OpenSCLDefinition; + +public class SCLSearchResultPage extends AbstractTextSearchViewPage { + + private SCLSearchResultContentProvider contentProvider; + + public SCLSearchResultPage() { + setElementLimit(-1); + } + @Override + protected void elementsChanged(Object[] objects) { + if (contentProvider != null) + contentProvider.elementsChanged(objects); + } + + @Override + protected void clear() { + + } + + private static final ViewerComparator comparator = new ViewerComparator((o1, o2) -> o1.compareTo(o2)); + + @Override + protected void configureTreeViewer(TreeViewer viewer) { + viewer.setUseHashlookup(true); + contentProvider = new SCLSearchResultContentProvider(this); + viewer.setContentProvider(contentProvider); + viewer.setComparator(comparator); + viewer.setLabelProvider(contentProvider); + } + + @Override + protected void configureTableViewer(TableViewer viewer) { + viewer.setUseHashlookup(true); + contentProvider = new SCLSearchResultContentProvider(this); + viewer.setContentProvider(contentProvider); + viewer.setComparator(comparator); + viewer.setLabelProvider(contentProvider); + } + + @Override + protected void handleOpen(OpenEvent event) { + Object selection = ((StructuredSelection)event.getSelection()).getFirstElement(); + if (selection != null) { + SymbolReference reference = (SymbolReference) selection; + OpenSCLDefinition.openDefinition(reference.referrer.module, reference.referenceLocation); + } + } + + @Override + protected void showMatch(Match match, int currentOffset, int currentLength) throws PartInitException { + SymbolReference reference = (SymbolReference) match.getElement(); + OpenSCLDefinition.openDefinition(reference.referrer.module, reference.referenceLocation); + } + + public static class SCLSearchResultContentProvider extends DecoratingStyledCellLabelProvider implements ITreeContentProvider, ILabelProvider { + + private Map> fChildrenMap; + private AbstractTextSearchResult result; + private SCLSearchResultPage page; + + public SCLSearchResultContentProvider(SCLSearchResultPage sclSearchResultPage) { + super(new SCLSearchResultLabelProvider(), PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator(), DecorationContext.DEFAULT_CONTEXT); + this.page = sclSearchResultPage; + } + + @Override + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + initialize((AbstractTextSearchResult) newInput); + } + + protected void initialize(AbstractTextSearchResult result) { + this.result = result; + fChildrenMap= new HashMap<>(); + if (result != null) { + Object[] elements= result.getElements(); + for (int i= 0; i < elements.length; i++) { + if (getPage().getDisplayedMatchCount(elements[i]) > 0) { + insert(null, null, elements[i]); + } + } + } + } + + private AbstractTextSearchResult getSearchResult() { + return result; + } + + public SCLSearchResultPage getPage() { + return page; + } + + public void elementsChanged(Object[] updatedElements) { + if (getSearchResult() == null) + return; + + AbstractTreeViewer viewer= (AbstractTreeViewer) getPage().getViewer(); + + Set toRemove= new HashSet<>(); + Set toUpdate= new HashSet<>(); + Map> toAdd= new HashMap<>(); + for (int i= 0; i < updatedElements.length; i++) { + if (getPage().getDisplayedMatchCount(updatedElements[i]) > 0) + insert(toAdd, toUpdate, updatedElements[i]); + else + remove(toRemove, toUpdate, updatedElements[i]); + } + + viewer.remove(toRemove.toArray()); + for (Iterator iter= toAdd.keySet().iterator(); iter.hasNext();) { + Object parent= iter.next(); + HashSet children= (HashSet) toAdd.get(parent); + viewer.add(parent, children.toArray()); + } + for (Iterator elementsToUpdate= toUpdate.iterator(); elementsToUpdate.hasNext();) { + viewer.refresh(elementsToUpdate.next()); + } + } + + protected void insert(Map> toAdd, Set toUpdate, Object child) { + Object parent= getParent(child); + while (parent != null) { + if (insertChild(parent, child)) { + if (toAdd != null) + insertInto(parent, child, toAdd); + } else { + if (toUpdate != null) + toUpdate.add(parent); + return; + } + child= parent; + parent= getParent(child); + } + if (insertChild(getSearchResult(), child)) { + if (toAdd != null) + insertInto(getSearchResult(), child, toAdd); + } + } + + private boolean insertChild(Object parent, Object child) { + return insertInto(parent, child, fChildrenMap); + } + + private boolean insertInto(Object parent, Object child, Map> map) { + Set children= map.get(parent); + if (children == null) { + children= new HashSet<>(); + map.put(parent, children); + } + return children.add(child); + } + + protected void remove(Set toRemove, Set toUpdate, Object element) { + // precondition here: fResult.getMatchCount(child) <= 0 + + if (hasChildren(element)) { + if (toUpdate != null) + toUpdate.add(element); + } else { + if (getPage().getDisplayedMatchCount(element) == 0) { + fChildrenMap.remove(element); + Object parent= getParent(element); + if (parent != null) { + if (removeFromSiblings(element, parent)) { + remove(toRemove, toUpdate, parent); + } + } else { + if (removeFromSiblings(element, getSearchResult())) { + if (toRemove != null) + toRemove.add(element); + } + } + } else { + if (toUpdate != null) { + toUpdate.add(element); + } + } + } + } + + /** + * Tries to remove the given element from the list of stored siblings. + * + * @param element potential child + * @param parent potential parent + * @return returns true if it really was a remove (i.e. element was a child of parent). + */ + private boolean removeFromSiblings(Object element, Object parent) { + Set siblings= fChildrenMap.get(parent); + if (siblings != null) { + return siblings.remove(element); + } else { + return false; + } + } + + @Override + public Object[] getElements(Object inputElement) { + return getChildren(inputElement); + } + + @Override + public Object getParent(Object element) { + return null; + } + + protected final Object[] EMPTY_ARR= new Object[0]; + + @Override + public Object[] getChildren(Object parentElement) { + Set children= fChildrenMap.get(parentElement); + if (children == null) + return EMPTY_ARR; + int limit= getPage().getElementLimit().intValue(); + if (limit != -1 && limit < children.size()) { + Object[] limitedArray= new Object[limit]; + Iterator iterator= children.iterator(); + for (int i= 0; i < limit; i++) { + limitedArray[i]= iterator.next(); + } + return limitedArray; + } + + return children.toArray(); + } + + @Override + public boolean hasChildren(Object element) { + Set children= fChildrenMap.get(element); + return children != null && !children.isEmpty(); + } + + @Override + public String getText(Object element) { + SymbolReference ref = (SymbolReference) element; + return ref.referrer.toString(); + } + + } + + public static class SCLSearchResultLabelProvider implements ILabelProvider, IColorProvider, IStyledLabelProvider { + + @Override + public void addListener(ILabelProviderListener listener) { + + } + + @Override + public void dispose() { + + } + + @Override + public boolean isLabelProperty(Object element, String property) { + return true; + } + + @Override + public void removeListener(ILabelProviderListener listener) { + + } + + @Override + public StyledString getStyledText(Object element) { + SymbolReference ref = (SymbolReference) element; + return new StyledString(ref.referrer.toString()); //+ " " + ref.referred + " " + ref.referenceLocation); + } + + @Override + public Color getForeground(Object element) { + return null; + } + + @Override + public Color getBackground(Object element) { + return null; + } + + @Override + public Image getImage(Object element) { + return null; + } + + @Override + public String getText(Object element) { + return null; + } + + } +}