/* * #%~ * org.overture.ide.debug * %% * Copyright (C) 2008 - 2014 Overture * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #~% */ package org.overture.ide.debug.ui.actions; import java.lang.reflect.InvocationTargetException; import java.util.Iterator; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugModelPresentation; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.Region; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorActionDelegate; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IObjectActionDelegate; import org.eclipse.ui.IPartListener; import org.eclipse.ui.IViewActionDelegate; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.IWorkbenchWindowActionDelegate; import org.eclipse.ui.PartInitException; import org.eclipse.ui.texteditor.ITextEditor; import org.overture.ide.debug.core.VdmDebugPlugin; import org.overture.ide.debug.core.model.IVdmStackFrame; import org.overture.ide.debug.core.model.IVdmValue; import org.overture.ide.debug.core.model.IVdmVariable; import org.overture.ide.debug.core.model.eval.IVdmEvaluationEngine; import org.overture.ide.debug.core.model.eval.IVdmEvaluationListener; import org.overture.ide.debug.core.model.eval.IVdmEvaluationResult; import org.overture.ide.debug.ui.VdmEvaluationContextManager; import org.overture.ide.debug.utils.VdmWordFinder; import org.overture.ide.ui.editor.core.VdmEditor; public class VdmEvaluationAction implements IWorkbenchWindowActionDelegate, IObjectActionDelegate, IPartListener, IVdmEvaluationListener, IEditorActionDelegate, IViewActionDelegate { private static class ObjectResolver { private IWorkbenchPart part; private IRegion region; protected static ISelection getSelection(IWorkbenchPart part) { if (part != null) { ISelectionProvider provider = part.getSite().getSelectionProvider(); if (provider != null) { return provider.getSelection(); } } return null; } protected static boolean textHasContent(String text) { if (text != null) { int length = text.length(); if (length > 0) { for (int i = 0; i < length; i++) { if (Character.isLetterOrDigit(text.charAt(i))) { return true; } } } } return false; } protected Object resolveTextSelection(ITextSelection selection) { String text = selection.getText(); if (textHasContent(text)) { region = new Region(selection.getOffset(), selection.getLength()); return text; } else if (part instanceof IEditorPart) { IEditorPart editor = (IEditorPart) part; if (editor instanceof ITextEditor) { ITextEditor textEditor = (ITextEditor) editor; IDocument doc = textEditor.getDocumentProvider().getDocument(editor.getEditorInput()); region = VdmWordFinder.findWord(doc, selection.getOffset()); if (region != null) { try { return doc.get(region.getOffset(), region.getLength()); } catch (BadLocationException e) { } } } } return null; } protected Object resolveStructuredSelection( IStructuredSelection selection) { if (!selection.isEmpty()) { if (part.getSite().getId().equals(IDebugUIConstants.ID_DEBUG_VIEW)) { IEditorPart editor = part.getSite().getPage().getActiveEditor(); ISelection newSelection = getSelection(editor); if (newSelection instanceof ITextSelection) { return resolveTextSelection((ITextSelection) newSelection); } } else { Iterator<?> elements = selection.iterator(); while (elements.hasNext()) { Object element = elements.next(); if (!(element instanceof IVdmVariable)) { return null; } } return selection; } } return null; } public ObjectResolver(IWorkbenchPart part) { this.part = part; } public Object resolveSelectedObject() { ISelection selection = getSelection(part); if (selection instanceof ITextSelection) { return resolveTextSelection((ITextSelection) selection); } else if (selection instanceof IStructuredSelection) { return resolveStructuredSelection((IStructuredSelection) selection); } return null; } // public IRegion getRegion() // { // return region; // } } private IWorkbenchWindow window; private IWorkbenchPart part; private IAction action; private Object selectedObject; private boolean evaluation; protected static IDebugModelPresentation getDebugModelPresentation( String identifier) { return DebugUITools.newDebugModelPresentation(identifier); } private void setWindow(IWorkbenchWindow window) { this.window = window; } protected IWorkbenchWindow getWindow() { return this.window; } private void setPart(IWorkbenchPart part) { this.part = part; } protected IWorkbenchPart getPart() { return this.editor != null ? this.editor : this.part; } private void setAction(IAction action) { this.action = action; } protected IAction getAction() { return action; } private void setSelectedObject(Object object) { this.selectedObject = object; } protected Object getSelectedObject() { return this.selectedObject; } private void setEvaluating(boolean evaluation) { this.evaluation = evaluation; } protected boolean isEvaluating() { return this.evaluation; } protected void evaluationCleanup() { setEvaluating(false); // setTargetPart(fNewTargetPart); } private VdmEditor editor; private void setEditor(VdmEditor editor) { this.editor = editor; } protected VdmEditor getEditor() { return this.editor; } // IWorkbenchWindowActionDelegate public void init(IWorkbenchWindow window) { setWindow(window); IWorkbenchPage page = window.getActivePage(); if (page != null) { setPart(page.getActivePart()); } window.getPartService().addPartListener(this); update(); } public void dispose() { // disposeDebugModelPresentation(); IWorkbenchWindow window = getWindow(); if (window != null) { window.getPartService().removePartListener(this); } } // IObjectActionDelegate public void setActivePart(IAction action, IWorkbenchPart targetPart) { setAction(action); setPart(targetPart); update(); } // IActionDelegate public void run(IAction action) { update(); run(); } public void selectionChanged(IAction action, ISelection selection) { setAction(action); } // IPartListener public void partActivated(IWorkbenchPart part) { setPart(part); } public void partBroughtToTop(IWorkbenchPart part) { } public void partClosed(IWorkbenchPart part) { if (part == getPart()) { setPart(null); } } public void partDeactivated(IWorkbenchPart part) { } public void partOpened(IWorkbenchPart part) { } // Other stuff protected void update() { IAction action = getAction(); if (action != null) { ObjectResolver or = new ObjectResolver(getPart()); setSelectedObject(or.resolveSelectedObject()); } } protected void showExpressionView() { if (getPart().getSite().getId().equals(IDebugUIConstants.ID_EXPRESSION_VIEW)) { return; } IWorkbenchPage page = VdmDebugPlugin.getActivePage(); if (page != null) { IViewPart part = page.findView(IDebugUIConstants.ID_EXPRESSION_VIEW); if (part == null) { try { page.showView(IDebugUIConstants.ID_EXPRESSION_VIEW); } catch (PartInitException e) { // reportError(e.getStatus().getMessage()); } } else { page.bringToTop(part); } } } public static StyledText getStyledText(IWorkbenchPart part) { ITextViewer viewer = (ITextViewer) part.getAdapter(ITextViewer.class); StyledText textWidget = null; if (viewer == null) { Control control = (Control) part.getAdapter(Control.class); if (control instanceof StyledText) { textWidget = (StyledText) control; } } else { textWidget = viewer.getTextWidget(); } return textWidget; } public static Point getPopupAnchor(StyledText textWidget) { if (textWidget != null) { Point docRange = textWidget.getSelectionRange(); int midOffset = docRange.x + docRange.y / 2; Point point = textWidget.getLocationAtOffset(midOffset); point = textWidget.toDisplay(point); GC gc = new GC(textWidget); gc.setFont(textWidget.getFont()); int height = gc.getFontMetrics().getHeight(); gc.dispose(); point.y += height; return point; } return null; } protected Shell getShell() { if (getPart() != null) { return getPart().getSite().getShell(); } return VdmDebugPlugin.getActiveWorkbenchShell(); } protected IVdmStackFrame getStackFrameContext() { IWorkbenchPart part = getPart(); IVdmStackFrame frame = null; if (part == null) { frame = VdmEvaluationContextManager.getEvaluationContext(getWindow()); } else { frame = VdmEvaluationContextManager.getEvaluationContext(part); } return frame; } protected void run() { final IVdmStackFrame stackFrame = getStackFrameContext(); if (stackFrame == null) { reportError("VdmEvaluationAction_cannotGetStackFrame"); return; } // setNewTargetPart(getTargetPart()); // Preparing runnable IRunnableWithProgress runnable = new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { if (stackFrame.isSuspended()) { Object selection = getSelectedObject(); if (!(selection instanceof String)) { return; } String expression = (String) selection; IVdmEvaluationEngine engine = stackFrame.getVdmThread().getEvaluationEngine(); setEvaluating(true); engine.asyncEvaluate(expression, stackFrame, VdmEvaluationAction.this); } else { throw new InvocationTargetException(null, "VdmEvaluationAction_threadIsNotSuspended"); } } }; // Run try { IWorkbench workbench = VdmDebugPlugin.getDefault().getWorkbench(); workbench.getProgressService().busyCursorWhile(runnable); } catch (InvocationTargetException e) { evaluationCleanup(); String message = e.getMessage(); if (message == null) { message = e.getClass().getName(); if (e.getCause() != null) { message = e.getCause().getClass().getName(); if (e.getCause().getMessage() != null) { message = e.getCause().getMessage(); } } } reportError(message); } catch (InterruptedException e) { } } // Error reporting public static String getExceptionMessage(Throwable exception) { if (exception instanceof CoreException) { CoreException ce = (CoreException) exception; Throwable throwable = ce.getStatus().getException(); if (throwable instanceof CoreException) { // Traverse nested CoreExceptions return getExceptionMessage(throwable); } return ce.getStatus().getMessage(); } String message = NLS.bind("Messages.VdmEvaluationAction_anExceptionOccurred", exception.getClass()); if (exception.getMessage() != null) { message = NLS.bind("Messages.VdmEvaluationAction_anExceptionOccurred2", message, exception.getMessage()); } return message; } protected static String getErrorMessage(IVdmEvaluationResult result) { String[] errors = result.getErrorMessages(); if (errors.length == 0) { return getExceptionMessage(result.getException()); } return getErrorMessage(errors); } protected static String getErrorMessage(String[] errors) { String message = ""; //$NON-NLS-1$ for (int i = 0; i < errors.length; i++) { String msg = errors[i]; if (i == 0) { message = msg; } else { message = NLS.bind("Messages.VdmEvaluationAction_errorMessage, message", msg); } } return message; } protected void reportErrors(IVdmEvaluationResult result) { String message = getErrorMessage(result); reportError(message); } protected void reportError(String message) { Status status = new Status(IStatus.ERROR, VdmDebugPlugin.PLUGIN_ID, IStatus.ERROR, message, null); ErrorDialog.openError(getShell(), "Messages.VdmEvaluationAction_errorEvaluating", null, status); } // IVdmEvaluationListener public void evaluationComplete(IVdmEvaluationResult result) { // if plug-in has shutdown, ignore - see bug# 8693 if (VdmDebugPlugin.getDefault() == null) { return; } final IVdmValue value = result.getValue(); if (result.hasErrors() || value != null) { final Display display = VdmDebugPlugin.getStandardDisplay(); if (display.isDisposed()) { return; } // Each action should implement this method for own purposes displayResult(result); } } protected void displayResult(IVdmEvaluationResult result) { // Nothing by default } // IEditorActionDelegate public void setActiveEditor(IAction action, IEditorPart targetEditor) { if (targetEditor instanceof VdmEditor) { setEditor((VdmEditor) targetEditor); } else { setEditor(null); } } // IViewActionDelegate public void init(IViewPart view) { setPart(view); } }