/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package com.windowtester.runtime.gef.internal.finder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.IFigure;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.ui.palette.PaletteViewer;
import org.eclipse.ui.IEditorPart;
import com.windowtester.runtime.draw2d.internal.finder.Draw2DFinder;
import com.windowtester.runtime.draw2d.internal.matchers.FigureInstanceMatcher;
import com.windowtester.runtime.gef.internal.GEFEditPartReference;
import com.windowtester.runtime.gef.internal.IGEFEditPartMatcher;
import com.windowtester.runtime.gef.internal.IGEFEditPartReference;
import com.windowtester.runtime.gef.internal.IGEFFinder;
import com.windowtester.runtime.gef.internal.helpers.EditPartHelper;
import com.windowtester.runtime.gef.internal.helpers.EditorAccessor;
import com.windowtester.runtime.gef.internal.helpers.PaletteAccessor;
import com.windowtester.runtime.gef.internal.helpers.EditPartHelper.IEditPartVisitor;
import com.windowtester.runtime.swt.internal.finder.eclipse.editors.EditorFinder;
/**
* Basic finder utility for GEF.
*/
public class GEFFinder implements IGEFFinder {
static class MatchAccumulatingPartVisitor implements IEditPartVisitor {
private final IGEFEditPartMatcher _matcher;
private final List _matches = new ArrayList();
public MatchAccumulatingPartVisitor(IGEFEditPartMatcher matcher) {
_matcher = matcher;
}
public boolean visit(EditPart part) {
if (_matcher.matches(part))
_matches.add(part);
return true;
}
public EditPart[] getMatches() {
return (EditPart[]) _matches.toArray(new EditPart[]{});
}
}
private static final IGEFFinder DEFAULT = new GEFFinder();
public static IGEFFinder getDefault() {
return DEFAULT;
}
public EditPart[] findAllEditParts(GraphicalViewer viewer, IGEFEditPartMatcher matcher) {
MatchAccumulatingPartVisitor collector = new MatchAccumulatingPartVisitor(matcher);
accumulateViewerContents(viewer, collector);
accumulatePaletteContents(viewer, collector);
return collector.getMatches();
}
private void accumulatePaletteContents(GraphicalViewer viewer, MatchAccumulatingPartVisitor collector) {
PaletteViewer palette = getPalette(viewer);
if (palette == null)
return;
accumulate(palette.getContents(), collector);
}
private PaletteViewer getPalette(GraphicalViewer viewer) {
return PaletteAccessor.forViewer(viewer).getPalette();
}
public PaletteAccessor getPaletteForEditor(String editorId) {
GraphicalViewer viewer = findViewer(editorId);
if (viewer == null)
return null;
return PaletteAccessor.forViewer(viewer);
}
public PaletteAccessor findPaletteForActiveEditor() {
GraphicalViewer viewer = findViewerForActiveEditor();
return PaletteAccessor.forViewer(viewer);
}
public GraphicalViewer findViewerForActiveEditor() {
IEditorPart activeEditor = EditorFinder.getActiveEditor();
if (activeEditor == null)
return null;
return adaptToGraphicalViewer(activeEditor);
}
private void accumulateViewerContents(GraphicalViewer viewer, MatchAccumulatingPartVisitor collector) {
accumulate(viewer.getContents(), collector);
}
private void accumulate(EditPart contents, MatchAccumulatingPartVisitor collector) {
EditPartHelper.visit(contents, collector);
}
private static IGEFEditPartReference[] adaptPartsToLocators(EditPart[] parts) {
List locators = new ArrayList();
for (int i = 0; i < parts.length; i++) {
//TODO fix this icky downcast
locators.add(GEFEditPartReference.create((GraphicalEditPart)parts[i]));
}
return (IGEFEditPartReference[]) locators.toArray(new IGEFEditPartReference[]{});
}
public IGEFEditPartReference[] findAllEditPartReferences(GraphicalViewer viewer, IGEFEditPartMatcher matcher) {
return adaptPartsToLocators(findAllEditParts(viewer, matcher));
}
/* (non-Javadoc)
* @see com.windowtester.runtime.gef.IGEFFinder#findEditPart(org.eclipse.draw2d.IFigure)
*/
public EditPart findEditPart(final IFigure figure) {
EditPart[] parts = findAllEditParts(figure);
if (parts.length > 1)
throw new IllegalStateException("more than one edit part match");
if (parts.length == 0)
return null;
return parts[0];
}
/* (non-Javadoc)
* @see com.windowtester.runtime.gef.IGEFFinder#findAllEditParts(org.eclipse.draw2d.IFigure)
*/
public EditPart[] findAllEditParts(final IFigure figure) {
EditPart[] parts = findAllExactMatchEditParts(figure);
if (parts.length == 0)
parts = findMostExactMatchEditParts(figure);
return parts;
}
//TODO: FIX THIS! (should delegate to new edit part hierarchy abstraction)
//should return a singleton list
private EditPart[] findMostExactMatchEditParts(final IFigure figure) {
if (figure == null)
return new EditPart[]{};
EditPart[] parts = findAllEditParts(new IGEFEditPartMatcher() {
public boolean matches(EditPart part) {
if (!(part instanceof GraphicalEditPart))
return false;
IFigure partFigure = ((GraphicalEditPart)part).getFigure();
if (partFigure == null)
return false;
if (figure == partFigure)
return true;
return Draw2DFinder.getDefault().isContainedIn(figure, new FigureInstanceMatcher(partFigure));
}
});
return new EditPart[]{selectMostExact(parts)};
}
private EditPart selectMostExact(EditPart[] parts) {
for (int i = 0; i < parts.length; i++) {
EditPart candidate = parts[i];
boolean match = true;
for (int j=0; j < parts.length; ++j) {
EditPart otherPart = parts[j];
if (isDescendantOf(otherPart, candidate))
match = false;
}
if (match)
return candidate;
}
return null;
}
private boolean isDescendantOf(EditPart child, EditPart parent) {
//System.out.println("child: " + child + " parent: " + parent);
List children = parent.getChildren();
for (Iterator iter = children.iterator(); iter.hasNext();) {
EditPart part = (EditPart) iter.next();
if (child == part)
return true;
if (isDescendantOf(child, part))
return true;
}
return false;
}
public EditPart[] findAllExactMatchEditParts(final IFigure figure) {
return findAllEditParts(new IGEFEditPartMatcher() {
public boolean matches(EditPart part) {
if (!(part instanceof GraphicalEditPart))
return false;
return figure == ((GraphicalEditPart)part).getFigure();
}
});
}
//note this selects only GRAPHICAL edit parts
/* (non-Javadoc)
* @see com.windowtester.runtime.gef.IGEFFinder#findAllEditParts()
*/
public EditPart[] findAllEditParts() {
return findAllEditParts(new IGEFEditPartMatcher() {
public boolean matches(EditPart part) {
return part instanceof GraphicalEditPart;
}
});
}
/* (non-Javadoc)
* @see com.windowtester.runtime.gef.IGEFFinder#getFigure(org.eclipse.gef.EditPart)
*/
public IFigure getFigure(EditPart part) {
if (!(part instanceof GraphicalEditPart))
return null;
return ((GraphicalEditPart)part).getFigure();
}
/* (non-Javadoc)
* @see com.windowtester.runtime.gef.IGEFFinder#findAllEditParts(com.windowtester.runtime.gef.IGEFEditPartMatcher)
*/
public EditPart[] findAllEditParts(IGEFEditPartMatcher matcher) {
GraphicalViewer[] viewers = findAllViewers();
List parts = new ArrayList();
for (int i = 0; i < viewers.length; i++) {
EditPart[] matches = findAllEditParts(viewers[i], matcher);
for (int j = 0; j < matches.length; j++) {
parts.add(matches[j]);
}
}
return (EditPart[]) parts.toArray(new EditPart[]{});
}
public GraphicalViewer findViewer(String partNameOrPattern) {
IEditorPart editor = EditorFinder.getEditorPart(partNameOrPattern);
if (editor == null)
return null;
return adaptToGraphicalViewer(editor);
}
private GraphicalViewer adaptToGraphicalViewer(IEditorPart editor) {
return EditorAccessor.adaptToGraphicalViewer(editor);
}
public GraphicalViewer[] findAllViewers() {
IEditorPart[] parts = EditorFinder.getEditorParts(".*");
List viewers = new ArrayList();
for (int i = 0; i < parts.length; i++) {
if (parts[i] == null)
continue;
Object adapter = adaptToGraphicalViewer(parts[i]);
if (adapter != null)
viewers.add(adapter);
}
return (GraphicalViewer[]) viewers.toArray(new GraphicalViewer[]{});
}
// private Control[] collectAllControls(IUIContext ui) {
// IWidgetLocator[] found = ui.findAll(new WidgetMatcher(new IWidgetMatcher() {
// public boolean matches(Object widget) {
// return (Control.class.isAssignableFrom(widget.getClass()));
// }
// }));
// Control[] controls = new Control[found.length];
// for (int i = 0; i < controls.length; i++) {
// controls[i] = (Control) ((WidgetReference)found[i]).getWidget();
// }
// return controls;
// }
// class WidgetMatcher extends SWTWidgetLocator {
//
// private static final long serialVersionUID = 1L;
//
// private final IWidgetMatcher _matcher;
//
// public WidgetMatcher(IWidgetMatcher matcher) {
// super(Widget.class); //ignored
// _matcher = matcher;
// }
//
// @Override
// protected IWidgetMatcher buildMatcher() {
// return _matcher;
// }
// }
}