/******************************************************************************* * 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.eclipse.ui.viewers; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.ITypeHierarchy; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.action.IAction; import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSource; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.DragSourceListener; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.texteditor.AbstractTextEditor; import com.windowtester.codegen.assembly.unit.ImportUnit; import com.windowtester.eclipse.ui.jdt.analysis.util.TypeHierarchyCache; import com.windowtester.runtime.swing.UITestCaseSwing; import com.windowtester.runtime.swt.UITestCaseSWT; import com.windowtester.runtime.swt.internal.finder.eclipse.editors.EditorFinder; @SuppressWarnings("restriction") public class EventSequenceDNDSupport { //private static final String SNIPPET_TEST_NAME = "Snippet"; public EventSequenceSnippetBuilder builder; private static class DragAdapter implements DragSourceListener { private static final String UICONTEXT_ACCESSOR = "getUI"; private static final String[] UICONTEXT_ACCESSOR_PARAMS = null; private final EventSequenceTreeViewer viewer; private String generated; private StyledText editorWidget; private EventSequenceSnippetBuilder builder; private TypeHierarchyCache hierarchy = new TypeHierarchyCache(); public DragAdapter(EventSequenceTreeViewer viewer) { this.viewer = viewer; } public void dragFinished(DragSourceEvent event) { try { doDragFinished(event); } catch (Throwable th) { th.printStackTrace(); //ignore and move on } } private void doDragFinished(DragSourceEvent event) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, JavaModelException { if (!currentEditorSelectionMatchesDragContents()) return; addImports(); updateInsertedContentsIfNecessary(); formatInsertedContents(); } private void formatInsertedContents() { AbstractTextEditor editor = getTextEditor(); if (editor == null) return; IAction action = editor.getAction("Format"); //NOTE: this action is registered in the Java editor if (action == null) return; action.run(); } private void updateInsertedContentsIfNecessary() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { IJavaElement insertHost = getJavaElementAtInsertOffset(); if (insertHost == null) return; if (insertHost instanceof IMethod) { insertMethodSnippet(); return; } if (!hostProvidesContext()) insertParameterizedMethod(); } private void insertParameterizedMethod() { editorWidget.insert(builder.getParameterizedMethod()); } private boolean hostProvidesContext() { ICompilationUnit cu = getCompilationUnit(); IType primaryType = cu.findPrimaryType(); ITypeHierarchy th = hierarchy.getTypeHierarchy(primaryType, primaryType.getJavaProject()); IType[] types = th.getAllSupertypes(primaryType); for (int i = 0; i < types.length; i++) { IType type = types[i]; // try { // IMethod[] methods = type.getMethods(); // for (int j = 0; j < methods.length; j++) { // if (methods[j].getElementName().equals(UICONTEXT_ACCESSOR)) // return true; // } // } catch (JavaModelException e) { // e.printStackTrace(); // } IMethod method = type.getMethod(UICONTEXT_ACCESSOR, UICONTEXT_ACCESSOR_PARAMS); //System.out.println("method: " + method + " exists: " + method.exists()); if (method != null && method.exists()) return true; } return false; } private void insertMethodSnippet() { editorWidget.insert(builder.getMethodSnippet()); } private void addImports() throws JavaModelException { ICompilationUnit cu = getCompilationUnit(); if (cu == null) return; addImportsTo(cu); } private void addImportsTo(ICompilationUnit cu) throws JavaModelException { ImportUnit[] imports = builder.getImports(); for (int i = 0; i < imports.length; i++) { if (skippedImport(imports[i])) continue; cu.createImport(imports[i].getName(), null, null); } } private boolean skippedImport(ImportUnit importUnit) { String name = importUnit.getName(); if (name == null) return true; if (name.equals(UITestCaseSWT.class.getName())) return true; if (name.equals(UITestCaseSwing.class.getName())) return true; return false; } private ICompilationUnit getCompilationUnit() { IJavaElement je = getEditorInputJavaElement(); return getCompilationUnitFor(je); } private ICompilationUnit getCompilationUnitFor(IJavaElement je) { if (je == null) return null; if (je instanceof ICompilationUnit) return (ICompilationUnit)je; if (je instanceof IMember) return ((IMember)je).getCompilationUnit(); return getCompilationUnitFor(je.getParent()); } private IJavaElement getJavaElementAtInsertOffset() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { int offset = editorWidget.getCaretOffset(); //System.out.println("widget offset: " + offset); ISourceViewer editorSourceViewer = getEditorSourceViewer(); if (editorSourceViewer instanceof ITextViewerExtension5) { offset = ((ITextViewerExtension5)editorSourceViewer).widgetOffset2ModelOffset(offset); //System.out.println("model offset: " + offset); } //IJavaElement je = getEditorInputJavaElement(); //System.out.println("editor element handle: " + je.getHandleIdentifier()); Method m = JavaEditor.class.getDeclaredMethod("getElementAt", new Class[]{int.class}); if (m == null) return null; m.setAccessible(true); AbstractTextEditor editor = getTextEditor(); if (editor == null) return null; IJavaElement insertHost = (IJavaElement) m.invoke(editor, new Object[]{new Integer(offset)}); return insertHost; } public ISourceViewer getEditorSourceViewer() { AbstractTextEditor editor = getTextEditor(); if (editor == null) return null; Method m; try { m = JavaEditor.class.getDeclaredMethod("getViewer", (Class[])null); if (m == null) return null; m.setAccessible(true); return (ISourceViewer) m.invoke(editor, (Object[])null); } catch (SecurityException e) { } catch (NoSuchMethodException e) { } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } return null; } private IJavaElement getEditorInputJavaElement() { AbstractTextEditor editor = getTextEditor(); if (editor == null) return null; return JavaUI.getEditorInputJavaElement(editor.getEditorInput()); } private boolean currentEditorSelectionMatchesDragContents() throws SecurityException, IllegalArgumentException, NoSuchMethodException, IllegalAccessException, InvocationTargetException { editorWidget = getCurrentEditorTextWidget(); if (editorWidget == null) return false; String selectionText = editorWidget.getSelectionText(); return matches(generated, selectionText); } private boolean matches(String expected, String actual) { if (expected == null || actual == null) return false; return expected.compareToIgnoreCase(actual) == 0; } private StyledText getCurrentEditorTextWidget() throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException { AbstractTextEditor textEditor = getTextEditor(); if (textEditor == null) return null; Method method = AbstractTextEditor.class.getDeclaredMethod("getSourceViewer", (Class[])null); method.setAccessible(true); ISourceViewer viewer = (ISourceViewer) method.invoke(textEditor, (Object[])null); if (viewer == null) return null; return viewer.getTextWidget(); } private AbstractTextEditor getTextEditor() { IEditorPart editor = EditorFinder.getActiveEditorPartNoRetries(); if (!(editor instanceof AbstractTextEditor)) return null; AbstractTextEditor textEditor = (AbstractTextEditor)editor; if (editor == null) return null; return textEditor; } public void dragSetData(DragSourceEvent event) { //System.out.println("set: " + event); try { builder = new EventSequenceSnippetBuilder(viewer.getSelection()); generated = builder.getMainMethodString(); event.data = generated; } catch(Throwable t) { t.printStackTrace(); } } public void dragStart(DragSourceEvent event) { event.doit = viewer.getSelection().length != 0; } } EventSequenceSnippetBuilder snippetBuilder; public static void addTo(EventSequenceTreeViewer viewer) { // int ops = DND.DROP_MOVE | DND.DROP_COPY; Transfer[] transfers = new Transfer[] { TextTransfer.getInstance() }; // viewer.getTreeViewer().addDragSupport(ops, transfers, new DragAdapter // (viewer)); // TreeViewer treeViewer = viewer.getTreeViewer(); DragSource source = new DragSource(treeViewer.getControl(), DND.DROP_COPY); source.setTransfer(transfers); source.addDragListener(new DragAdapter(viewer)); } }