|
From: <caw...@us...> - 2007-08-23 18:18:48
|
Revision: 3060
http://rubyeclipse.svn.sourceforge.net/rubyeclipse/?rev=3060&view=rev
Author: cawilliams
Date: 2007-08-23 11:18:47 -0700 (Thu, 23 Aug 2007)
Log Message:
-----------
first stab at implementing #4928 - add support for interacting at breakpoint.
Add Display view which allows users to type in Ruby code and execute/inspect the results
Modified Paths:
--------------
trunk/org.rubypeople.rdt.debug.ui/plugin.properties
trunk/org.rubypeople.rdt.debug.ui/plugin.xml
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/debug/ui/RdtDebugUiConstants.java
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/RdtDebugUiPlugin.java
Added Paths:
-----------
trunk/org.rubypeople.rdt.debug.ui/icons/full/dtool16/disp_sbook.gif
trunk/org.rubypeople.rdt.debug.ui/icons/full/etool16/
trunk/org.rubypeople.rdt.debug.ui/icons/full/etool16/disp_sbook.gif
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/EvaluationContextManager.java
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/JDISourceViewer.java
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ActionMessages.java
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ActionMessages.properties
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/EvaluateAction.java
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ExecuteAction.java
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/display/
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/display/DataDisplay.java
trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/display/DisplayView.java
Added: trunk/org.rubypeople.rdt.debug.ui/icons/full/dtool16/disp_sbook.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.debug.ui/icons/full/dtool16/disp_sbook.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: trunk/org.rubypeople.rdt.debug.ui/icons/full/etool16/disp_sbook.gif
===================================================================
(Binary files differ)
Property changes on: trunk/org.rubypeople.rdt.debug.ui/icons/full/etool16/disp_sbook.gif
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: trunk/org.rubypeople.rdt.debug.ui/plugin.properties
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/plugin.properties 2007-08-23 18:18:29 UTC (rev 3059)
+++ trunk/org.rubypeople.rdt.debug.ui/plugin.properties 2007-08-23 18:18:47 UTC (rev 3060)
@@ -27,3 +27,7 @@
modifyCatchpoint.label=Ruby Exception Breakpoint
modifyCatchpoint.tooltip=Define a ruby exception breakpoint
+displayViewName=Display
+
+Execute.label=E&xecute
+Execute.tooltip=Evaluate the Selected Text
\ No newline at end of file
Modified: trunk/org.rubypeople.rdt.debug.ui/plugin.xml
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/plugin.xml 2007-08-23 18:18:29 UTC (rev 3059)
+++ trunk/org.rubypeople.rdt.debug.ui/plugin.xml 2007-08-23 18:18:47 UTC (rev 3060)
@@ -1,8 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
-
- <extension point="org.eclipse.ui.preferencePages">
+ <extension point="org.eclipse.ui.views">
+ <view
+ name="%displayViewName"
+ icon="$nl$/icons/full/etool16/disp_sbook.gif"
+ category="org.eclipse.debug.ui"
+ class="org.rubypeople.rdt.internal.debug.ui.display.DisplayView"
+ id="org.rubypeople.rdt.debug.ui.DisplayView">
+ </view>
+ </extension>
+ <extension point="org.eclipse.ui.preferencePages">
<page name="%PreferencePage.RubyInterpreter.name"
category="org.rubypeople.rdt.ui.preferences.PreferencePageRubyBase"
class="org.rubypeople.rdt.internal.debug.ui.preferences.RubyInterpreterPreferencePage"
@@ -91,6 +99,33 @@
toolbarPath="rdtExceptions"
tooltip="%modifyCatchpoint.tooltip"/>
</viewContribution>
+ <viewContribution
+ id="org.rubypeople.rdt.debug.ui.DisplayViewActions"
+ targetID="org.rubypeople.rdt.debug.ui.DisplayView">
+ <action
+ toolbarPath="evaluationGroup"
+ id="org.rubypeople.rdt.debug.ui.displayViewToolbar.Execute"
+ hoverIcon="$nl$/icons/full/etool16/run_sbook.gif"
+ class="org.rubypeople.rdt.internal.debug.ui.actions.ExecuteAction"
+ disabledIcon="$nl$/icons/full/dtool16/run_sbook.gif"
+ enablesFor="+"
+ icon="$nl$/icons/full/etool16/run_sbook.gif"
+ helpContextId="execute_action_context"
+ label="%Execute.label"
+ tooltip="%Execute.tooltip">
+ <enablement>
+ <and>
+ <systemProperty
+ name="org.rubypeople.rdt.debug.ui.debuggerActive"
+ value="true">
+ </systemProperty>
+ <objectClass
+ name="org.eclipse.jface.text.ITextSelection">
+ </objectClass>
+ </and>
+ </enablement>
+ </action>
+ </viewContribution>
</extension>
<extension point="org.eclipse.ui.contexts">
<context name="Debugging Ruby" description="Debugging Ruby programs"
@@ -283,4 +318,30 @@
</action>
</actionSet>
</extension>
-</plugin>
\ No newline at end of file
+ <extension
+ point="org.eclipse.ui.perspectiveExtensions">
+ <perspectiveExtension targetID="org.eclipse.debug.ui.DebugPerspective">
+ <view
+ id="org.rubypeople.rdt.debug.ui.DisplayView"
+ relationship="stack"
+ relative="org.eclipse.ui.console.ConsoleView"
+ visible="false"/>
+ <viewShortcut id="org.rubypeople.rdt.debug.ui.DisplayView"/>
+ <view
+ id="org.rubypeople.rdt.ui.TypeHierarchy"
+ relationship="stack"
+ relative="org.eclipse.debug.ui.DebugView"
+ visible="false"/>
+ <view
+ id="org.eclipse.search.SearchResultView"
+ relationship="stack"
+ relative="org.eclipse.ui.console.ConsoleView"
+ visible="false"/>
+ <view
+ id="org.rubypeople.rdt.ui.ViewRubyResources"
+ relationship="stack"
+ relative="org.eclipse.debug.ui.DebugView"
+ visible="false"/>
+ </perspectiveExtension>
+ </extension>
+</plugin>
Modified: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/debug/ui/RdtDebugUiConstants.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/debug/ui/RdtDebugUiConstants.java 2007-08-23 18:18:29 UTC (rev 3059)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/debug/ui/RdtDebugUiConstants.java 2007-08-23 18:18:47 UTC (rev 3060)
@@ -8,4 +8,14 @@
public static final String SHOW_CONSTANTS_PREFERENCE = RdtDebugUiPlugin.PLUGIN_ID + ".showConstants";
public static final String EVALUATION_EXPRESSIONS_PREFERENCE = RdtDebugUiPlugin.PLUGIN_ID + ".evaluationExpressions";
public static final int INTERNAL_ERROR = 0;
+
+ /**
+ * Identifier for a group of evaluation actions in a menu (value <code>"evaluationGroup"</code>).
+ */
+ public static final String EVALUATION_GROUP= "evaluationGroup"; //$NON-NLS-1$
+
+ /**
+ * Display view identifier (value <code>"org.rubypeople.rdt.debug.ui.DisplayView"</code>).
+ */
+ public static final String ID_DISPLAY_VIEW= RdtDebugUiPlugin.PLUGIN_ID + ".DisplayView"; //$NON-NLS-1$
}
Added: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/EvaluationContextManager.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/EvaluationContextManager.java (rev 0)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/EvaluationContextManager.java 2007-08-23 18:18:47 UTC (rev 3060)
@@ -0,0 +1,211 @@
+package org.rubypeople.rdt.internal.debug.ui;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.debug.internal.ui.contexts.DebugContextManager;
+import org.eclipse.debug.internal.ui.contexts.provisional.IDebugContextListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWindowListener;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.rubypeople.rdt.internal.debug.core.model.RubyStackFrame;
+import org.rubypeople.rdt.internal.debug.core.model.RubyThread;
+
+public class EvaluationContextManager implements IDebugContextListener, IWindowListener {
+
+ private static EvaluationContextManager fgManager;
+
+ /**
+ * System property indicating a stack frame is selected in the debug view with an
+ * <code>IJavaStackFrame</code> adapter.
+ */
+ private static final String DEBUGGER_ACTIVE = RdtDebugUiPlugin.getUniqueIdentifier() + ".debuggerActive"; //$NON-NLS-1$
+ /**
+ * System property indicating an element is selected in the debug view that is
+ * an instanceof <code>RubyStackFrame</code> or <code>RubyThread</code>.
+ */
+ private static final String INSTANCE_OF_IRUBY_STACK_FRAME = RdtDebugUiPlugin.getUniqueIdentifier() + ".instanceof.RubyStackFrame"; //$NON-NLS-1$
+
+
+ private Map fContextsByPage = null;
+ private IWorkbenchWindow fActiveWindow;
+
+ private EvaluationContextManager() {
+ DebugContextManager.getDefault().addDebugContextListener(this);
+ }
+
+ public static RubyStackFrame getEvaluationContext(IWorkbenchPart part) {
+ IWorkbenchPage page = part.getSite().getPage();
+ RubyStackFrame frame = getContext(page);
+ if (frame == null) {
+ return getEvaluationContext(page.getWorkbenchWindow());
+ }
+ return frame;
+ }
+
+ public static RubyStackFrame getEvaluationContext(IWorkbenchWindow window) {
+ List alreadyVisited= new ArrayList();
+ if (window == null) {
+ window = fgManager.fActiveWindow;
+ }
+ return getEvaluationContext(window, alreadyVisited);
+ }
+
+ private static RubyStackFrame getEvaluationContext(IWorkbenchWindow window, List alreadyVisited) {
+ IWorkbenchPage activePage = window.getActivePage();
+ RubyStackFrame frame = null;
+ if (activePage != null) {
+ frame = getContext(activePage);
+ }
+ if (frame == null) {
+ IWorkbenchPage[] pages = window.getPages();
+ for (int i = 0; i < pages.length; i++) {
+ if (activePage != pages[i]) {
+ frame = getContext(pages[i]);
+ if (frame != null) {
+ return frame;
+ }
+ }
+ }
+
+ alreadyVisited.add(window);
+
+ IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
+ for (int i = 0; i < windows.length; i++) {
+ if (!alreadyVisited.contains(windows[i])) {
+ frame = getEvaluationContext(windows[i], alreadyVisited);
+ if (frame != null) {
+ return frame;
+ }
+ }
+ }
+ return null;
+ }
+ return frame;
+ }
+
+ private static RubyStackFrame getContext(IWorkbenchPage page) {
+ if (fgManager != null) {
+ if (fgManager.fContextsByPage != null) {
+ return (RubyStackFrame)fgManager.fContextsByPage.get(page);
+ }
+ }
+ return null;
+ }
+
+ public void contextActivated(ISelection selection, IWorkbenchPart part) {
+ if (part != null) {
+ IWorkbenchPage page = part.getSite().getPage();
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection ss = (IStructuredSelection)selection;
+ if (ss.size() == 1) {
+ Object element = ss.getFirstElement();
+ if (element instanceof IAdaptable) {
+ RubyStackFrame frame = (RubyStackFrame)((IAdaptable)element).getAdapter(RubyStackFrame.class);
+ boolean instOf = element instanceof RubyStackFrame || element instanceof RubyThread;
+ if (frame != null) {
+ // do not consider scrapbook frames
+// if (frame.getLaunch().getAttribute(ScrapbookLauncher.SCRAPBOOK_LAUNCH) == null) {
+ setContext(page, frame, instOf);
+ return;
+// }
+ }
+ }
+ }
+ }
+ // no context in the given view
+ removeContext(page);
+ }
+ }
+
+ public void contextChanged(ISelection selection, IWorkbenchPart part) {
+ }
+
+ /**
+ * Sets the evaluation context for the given page, and notes that
+ * a valid execution context exists.
+ *
+ * @param page
+ * @param frame
+ */
+ private void setContext(IWorkbenchPage page, RubyStackFrame frame, boolean instOf) {
+ if (fContextsByPage == null) {
+ fContextsByPage = new HashMap();
+ }
+ fContextsByPage.put(page, frame);
+ System.setProperty(DEBUGGER_ACTIVE, "true"); //$NON-NLS-1$
+ if (instOf) {
+ System.setProperty(INSTANCE_OF_IRUBY_STACK_FRAME, "true"); //$NON-NLS-1$
+ } else {
+ System.setProperty(INSTANCE_OF_IRUBY_STACK_FRAME, "false"); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Removes an evaluation context for the given page, and determines if
+ * any valid execution context remain.
+ *
+ * @param page
+ */
+ private void removeContext(IWorkbenchPage page) {
+ if (fContextsByPage != null) {
+ fContextsByPage.remove(page);
+ if (fContextsByPage.isEmpty()) {
+ System.setProperty(DEBUGGER_ACTIVE, "false"); //$NON-NLS-1$
+ System.setProperty(INSTANCE_OF_IRUBY_STACK_FRAME, "false"); //$NON-NLS-1$
+ }
+ }
+ }
+
+ public static void startup() {
+ Runnable r = new Runnable() {
+ public void run() {
+ if (fgManager == null) {
+ fgManager = new EvaluationContextManager();
+ IWorkbench workbench = PlatformUI.getWorkbench();
+ IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
+ for (int i = 0; i < windows.length; i++) {
+ fgManager.windowOpened(windows[i]);
+ }
+ workbench.addWindowListener(fgManager);
+ fgManager.fActiveWindow = workbench.getActiveWorkbenchWindow();
+ }
+ }
+ };
+ RdtDebugUiPlugin.getStandardDisplay().asyncExec(r);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void windowActivated(IWorkbenchWindow window) {
+ fActiveWindow = window;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void windowClosed(IWorkbenchWindow window) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void windowDeactivated(IWorkbenchWindow window) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow)
+ */
+ public void windowOpened(IWorkbenchWindow window) {
+ }
+
+}
Property changes on: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/EvaluationContextManager.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/JDISourceViewer.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/JDISourceViewer.java (rev 0)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/JDISourceViewer.java 2007-08-23 18:18:47 UTC (rev 3060)
@@ -0,0 +1,359 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.debug.ui;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.source.IVerticalRuler;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.swt.custom.BidiSegmentEvent;
+import org.eclipse.swt.custom.BidiSegmentListener;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.texteditor.AbstractTextEditor;
+import org.rubypeople.rdt.internal.debug.ui.display.DisplayViewerConfiguration;
+import org.rubypeople.rdt.internal.ui.text.IRubyPartitions;
+
+/**
+ * A source viewer configured to display Java source. This
+ * viewer obeys the font and color preferences specified in
+ * the Java UI plugin.
+ */
+public class JDISourceViewer extends SourceViewer implements IPropertyChangeListener {
+
+ private Font fFont;
+ private Color fBackgroundColor;
+ private Color fForegroundColor;
+ private IPreferenceStore fStore;
+ private DisplayViewerConfiguration fConfiguration;
+
+ public JDISourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
+ super(parent, ruler, styles);
+ StyledText text= this.getTextWidget();
+ text.addBidiSegmentListener(new BidiSegmentListener() {
+ public void lineGetSegments(BidiSegmentEvent event) {
+ try {
+ event.segments= getBidiLineSegments(event.lineOffset);
+ } catch (BadLocationException x) {
+ // ignore
+ }
+ }
+ });
+ }
+
+ /**
+ * Updates the viewer's font to match the preferences.
+ */
+ private void updateViewerFont() {
+ IPreferenceStore store= getPreferenceStore();
+ if (store != null) {
+ FontData data= null;
+ if (store.contains(JFaceResources.TEXT_FONT) && !store.isDefault(JFaceResources.TEXT_FONT)) {
+ data= PreferenceConverter.getFontData(store, JFaceResources.TEXT_FONT);
+ } else {
+ data= PreferenceConverter.getDefaultFontData(store, JFaceResources.TEXT_FONT);
+ }
+ if (data != null) {
+ Font font= new Font(getTextWidget().getDisplay(), data);
+ applyFont(font);
+ if (getFont() != null) {
+ getFont().dispose();
+ }
+ setFont(font);
+ return;
+ }
+ }
+ // if all the preferences failed
+ applyFont(JFaceResources.getTextFont());
+ }
+
+ /**
+ * Sets the current font.
+ *
+ * @param font the new font
+ */
+ private void setFont(Font font) {
+ fFont= font;
+ }
+
+ /**
+ * Returns the current font.
+ *
+ * @return the current font
+ */
+ private Font getFont() {
+ return fFont;
+ }
+
+ /**
+ * Sets the font for the given viewer sustaining selection and scroll position.
+ *
+ * @param font the font
+ */
+ private void applyFont(Font font) {
+ IDocument doc= getDocument();
+ if (doc != null && doc.getLength() > 0) {
+ Point selection= getSelectedRange();
+ int topIndex= getTopIndex();
+
+ StyledText styledText= getTextWidget();
+ styledText.setRedraw(false);
+
+ styledText.setFont(font);
+ setSelectedRange(selection.x , selection.y);
+ setTopIndex(topIndex);
+
+ styledText.setRedraw(true);
+ } else {
+ getTextWidget().setFont(font);
+ }
+ }
+
+ /**
+ * Updates the given viewer's colors to match the preferences.
+ */
+ public void updateViewerColors() {
+ IPreferenceStore store= getPreferenceStore();
+ if (store != null) {
+ StyledText styledText= getTextWidget();
+ Color color= store.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT)
+ ? null
+ : createColor(store, AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND, styledText.getDisplay());
+ styledText.setForeground(color);
+ if (getForegroundColor() != null) {
+ getForegroundColor().dispose();
+ }
+ setForegroundColor(color);
+
+ color= store.getBoolean(AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)
+ ? null
+ : createColor(store, AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND, styledText.getDisplay());
+ styledText.setBackground(color);
+ if (getBackgroundColor() != null) {
+ getBackgroundColor().dispose();
+ }
+ setBackgroundColor(color);
+ }
+ }
+
+ /**
+ * Creates a color from the information stored in the given preference store.
+ * Returns <code>null</code> if there is no such information available.
+ */
+ private Color createColor(IPreferenceStore store, String key, Display display) {
+ RGB rgb= null;
+ if (store.contains(key)) {
+ if (store.isDefault(key)) {
+ rgb= PreferenceConverter.getDefaultColor(store, key);
+ } else {
+ rgb= PreferenceConverter.getColor(store, key);
+ }
+ if (rgb != null) {
+ return new Color(display, rgb);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the current background color.
+ *
+ * @return the current background color
+ */
+ protected Color getBackgroundColor() {
+ return fBackgroundColor;
+ }
+
+ /**
+ * Sets the current background color.
+ *
+ * @param backgroundColor the new background color
+ */
+ protected void setBackgroundColor(Color backgroundColor) {
+ fBackgroundColor = backgroundColor;
+ }
+
+ /**
+ * Returns the current foreground color.
+ *
+ * @return the current foreground color
+ */
+ protected Color getForegroundColor() {
+ return fForegroundColor;
+ }
+
+ /**
+ * Sets the current foreground color.
+ *
+ * @param foregroundColor the new foreground color
+ */
+ protected void setForegroundColor(Color foregroundColor) {
+ fForegroundColor = foregroundColor;
+ }
+
+ /**
+ * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
+ */
+ public void propertyChange(PropertyChangeEvent event) {
+ IContentAssistant assistant= getContentAssistant();
+// if (assistant instanceof ContentAssistant) {
+// JDIContentAssistPreference.changeConfiguration((ContentAssistant) assistant, event);
+// }
+ String property= event.getProperty();
+
+ if (JFaceResources.TEXT_FONT.equals(property)) {
+ updateViewerFont();
+ }
+ if (AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND.equals(property) || AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT.equals(property) ||
+ AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND.equals(property) || AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property)) {
+ updateViewerColors();
+ }
+ if (fConfiguration != null) {
+ if (fConfiguration.affectsTextPresentation(event)) {
+ fConfiguration.handlePropertyChangeEvent(event);
+ invalidateTextPresentation();
+ }
+ }
+ }
+
+ /**
+ * Returns the current content assistant.
+ *
+ * @return the current content assistant
+ */
+ public IContentAssistant getContentAssistant() {
+ return fContentAssistant;
+ }
+
+ /**
+ * Returns a segmentation of the line of the given document appropriate for bidi rendering.
+ * The default implementation returns only the string literals of a Ruby code line as segments.
+ *
+ * @param document the document
+ * @param lineOffset the offset of the line
+ * @return the line's bidi segmentation
+ * @throws BadLocationException in case lineOffset is not valid in document
+ */
+ protected int[] getBidiLineSegments(int lineOffset) throws BadLocationException {
+ IDocument document= getDocument();
+ if (document == null) {
+ return null;
+ }
+ IRegion line= document.getLineInformationOfOffset(lineOffset);
+ ITypedRegion[] linePartitioning= document.computePartitioning(lineOffset, line.getLength());
+
+ List segmentation= new ArrayList();
+ for (int i= 0; i < linePartitioning.length; i++) {
+ if (IRubyPartitions.RUBY_STRING.equals(linePartitioning[i].getType()))
+ segmentation.add(linePartitioning[i]);
+ }
+
+
+ if (segmentation.size() == 0)
+ return null;
+
+ int size= segmentation.size();
+ int[] segments= new int[size * 2 + 1];
+
+ int j= 0;
+ for (int i= 0; i < size; i++) {
+ ITypedRegion segment= (ITypedRegion) segmentation.get(i);
+
+ if (i == 0)
+ segments[j++]= 0;
+
+ int offset= segment.getOffset() - lineOffset;
+ if (offset > segments[j - 1])
+ segments[j++]= offset;
+
+ if (offset + segment.getLength() >= line.getLength())
+ break;
+
+ segments[j++]= offset + segment.getLength();
+ }
+
+ if (j < segments.length) {
+ int[] result= new int[j];
+ System.arraycopy(segments, 0, result, 0, j);
+ segments= result;
+ }
+
+ return segments;
+ }
+
+ /**
+ * Disposes the system resources currently in use by this viewer.
+ */
+ public void dispose() {
+ if (getFont() != null) {
+ getFont().dispose();
+ setFont(null);
+ }
+ if (getBackgroundColor() != null) {
+ getBackgroundColor().dispose();
+ setBackgroundColor(null);
+ }
+ if (getForegroundColor() != null) {
+ getForegroundColor().dispose();
+ setForegroundColor(null);
+ }
+ if (fStore != null) {
+ fStore.removePropertyChangeListener(this);
+ fStore = null;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.text.source.SourceViewer#configure(org.eclipse.jface.text.source.SourceViewerConfiguration)
+ */
+ public void configure(SourceViewerConfiguration configuration) {
+ super.configure(configuration);
+ if (fStore != null) {
+ fStore.removePropertyChangeListener(this);
+ fStore = null;
+ }
+ if (configuration instanceof DisplayViewerConfiguration) {
+ fConfiguration = (DisplayViewerConfiguration) configuration;
+ fStore = fConfiguration.getTextPreferenceStore();
+ fStore.addPropertyChangeListener(this);
+ }
+ updateViewerFont();
+ updateViewerColors();
+ }
+
+ /**
+ * Returns the preference store used to configure this source viewer or
+ * <code>null</code> if none;
+ */
+ private IPreferenceStore getPreferenceStore() {
+ return fStore;
+ }
+
+}
Property changes on: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/JDISourceViewer.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/RdtDebugUiPlugin.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/RdtDebugUiPlugin.java 2007-08-23 18:18:29 UTC (rev 3059)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/RdtDebugUiPlugin.java 2007-08-23 18:18:47 UTC (rev 3060)
@@ -6,7 +6,9 @@
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.internal.ui.ImageDescriptorRegistry;
+import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.plugin.AbstractUIPlugin;
@@ -15,6 +17,8 @@
import org.rubypeople.rdt.debug.ui.RdtDebugUiConstants;
import org.rubypeople.rdt.internal.debug.core.model.RubyVariable;
import org.rubypeople.rdt.internal.debug.ui.evaluation.EvaluationExpressionModel;
+import org.rubypeople.rdt.ui.PreferenceConstants;
+import org.rubypeople.rdt.ui.text.RubyTextTools;
public class RdtDebugUiPlugin extends AbstractUIPlugin implements RdtDebugUiConstants {
@@ -24,6 +28,7 @@
private EvaluationExpressionModel evaluationExpressionModel;
private ImageDescriptorRegistry fImageDescriptorRegistry;
+ private RubyTextTools fTextTools;
public RdtDebugUiPlugin() {
super();
@@ -35,7 +40,11 @@
}
public static IWorkbenchPage getActivePage() {
- return RdtDebugUiPlugin.getActiveWorkbenchWindow().getActivePage();
+ IWorkbenchWindow w = getActiveWorkbenchWindow();
+ if (w != null) {
+ return w.getActivePage();
+ }
+ return null;
}
public static RdtDebugUiPlugin getDefault() {
@@ -60,6 +69,7 @@
ActionFilterAdapterFactory actionFilterAdapterFactory= new ActionFilterAdapterFactory();
manager.registerAdapters(actionFilterAdapterFactory, RubyVariable.class);
new CodeReloader();
+ EvaluationContextManager.startup();
}
@Override
@@ -107,4 +117,35 @@
return getDefault().fImageDescriptorRegistry;
}
+ public RubyTextTools getRubyTextTools() {
+ if (fTextTools == null) {
+ fTextTools = new RubyTextTools(PreferenceConstants.getPreferenceStore());
+ }
+ return fTextTools;
+ }
+
+ /**
+ * Returns the active workbench shell or <code>null</code> if none
+ *
+ * @return the active workbench shell or <code>null</code> if none
+ */
+ public static Shell getActiveWorkbenchShell() {
+ IWorkbenchWindow window = getActiveWorkbenchWindow();
+ if (window != null) {
+ return window.getShell();
+ }
+ return null;
+ }
+
+ /**
+ * Utility method with conventions
+ */
+ public static void errorDialog(String message, Throwable t) {
+ log(t);
+ Shell shell = getActiveWorkbenchShell();
+ if (shell != null) {
+ IStatus status= new Status(IStatus.ERROR, getUniqueIdentifier(), RdtDebugUiConstants.INTERNAL_ERROR, "Error logged from RDT Debug UI: ", t); //$NON-NLS-1$
+ ErrorDialog.openError(shell, "Error", message, status);
+ }
+ }
}
Added: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ActionMessages.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ActionMessages.java (rev 0)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ActionMessages.java 2007-08-23 18:18:47 UTC (rev 3060)
@@ -0,0 +1,26 @@
+package org.rubypeople.rdt.internal.debug.ui.actions;
+
+import org.eclipse.osgi.util.NLS;
+
+public class ActionMessages extends NLS {
+ private static final String BUNDLE_NAME = "org.rubypeople.rdt.internal.debug.ui.actions.ActionMessages";//$NON-NLS-1$
+
+ public static String Evaluate_error_message_direct_exception;
+ public static String Evaluate_error_message_exception_pattern;
+ public static String Evaluate_error_message_src_context;
+ public static String Evaluate_error_message_stack_frame_context;
+ public static String Evaluate_error_message_wrapped_exception;
+ public static String Evaluate_error_problem_append_pattern;
+ public static String Evaluate_error_title_eval_problems;
+ public static String EvaluateAction_Cannot_open_Display_view;
+ public static String EvaluateAction__evaluation_failed__1;
+ public static String EvaluateAction__evaluation_failed__Reason;
+ public static String EvaluateAction_Thread_not_suspended___unable_to_perform_evaluation__1;
+ public static String EvaluateAction_Cannot_perform_nested_evaluations__1;
+
+ static {
+ // load message values from bundle file
+ NLS.initializeMessages(BUNDLE_NAME, ActionMessages.class);
+ }
+
+}
Property changes on: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ActionMessages.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ActionMessages.properties
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ActionMessages.properties (rev 0)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ActionMessages.properties 2007-08-23 18:18:47 UTC (rev 3060)
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2000, 2006 IBM Corporation and others.
+# 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:
+# IBM Corporation - initial API and implementation
+###############################################################################
+
+Evaluate_error_message_direct_exception=An exception occurred: {0}
+Evaluate_error_message_exception_pattern={0} - {1}
+Evaluate_error_message_src_context=Unable to evaluate the selected expression:\n\nTo perform an evaluation, an expression must be compiled in the context of a Ruby project's build path. The current execution context is not associated with a Ruby project in the workspace.
+Evaluate_error_message_stack_frame_context=A stack frame must be selected to provide a context for an evaluation.
+Evaluate_error_message_wrapped_exception=An exception occurred: {0}
+Evaluate_error_problem_append_pattern={0}\n{1}
+Evaluate_error_title_eval_problems=Error Evaluating
+EvaluateAction_Cannot_open_Display_view=Cannot open Display View
+EvaluateAction__evaluation_failed__1=(evaluation failed)
+EvaluateAction__evaluation_failed__Reason=Evaluation failed. Reason(s):\n{0}
+EvaluateAction_Thread_not_suspended___unable_to_perform_evaluation__1=Thread not suspended - unable to perform evaluation.
+EvaluateAction_Cannot_perform_nested_evaluations__1=Cannot perform nested evaluations.
\ No newline at end of file
Property changes on: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ActionMessages.properties
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/EvaluateAction.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/EvaluateAction.java (rev 0)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/EvaluateAction.java 2007-08-23 18:18:47 UTC (rev 3060)
@@ -0,0 +1,770 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.rubypeople.rdt.internal.debug.ui.actions;
+
+
+
+import java.lang.reflect.InvocationTargetException;
+import java.text.MessageFormat;
+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.core.ILaunch;
+import org.eclipse.debug.core.model.ISourceLocator;
+import org.eclipse.debug.core.model.IStackFrame;
+import org.eclipse.debug.core.model.IThread;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugModelPresentation;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.IDebugView;
+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.swt.custom.StyledText;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorActionDelegate;
+import org.eclipse.ui.IEditorInput;
+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.rubypeople.rdt.core.IRubyElement;
+import org.rubypeople.rdt.core.IRubyProject;
+import org.rubypeople.rdt.core.RubyCore;
+import org.rubypeople.rdt.debug.ui.RdtDebugUiConstants;
+import org.rubypeople.rdt.internal.debug.core.RdtDebugCorePlugin;
+import org.rubypeople.rdt.internal.debug.core.RubyDebuggerProxy;
+import org.rubypeople.rdt.internal.debug.core.model.IEvaluationResult;
+import org.rubypeople.rdt.internal.debug.core.model.RubyProcessingException;
+import org.rubypeople.rdt.internal.debug.core.model.RubyStackFrame;
+import org.rubypeople.rdt.internal.debug.core.model.RubyValue;
+import org.rubypeople.rdt.internal.debug.core.model.RubyVariable;
+import org.rubypeople.rdt.internal.debug.ui.EvaluationContextManager;
+import org.rubypeople.rdt.internal.debug.ui.RdtDebugUiPlugin;
+import org.rubypeople.rdt.internal.debug.ui.RubySourceLocator.SourceElement;
+import org.rubypeople.rdt.internal.debug.ui.display.IDataDisplay;
+import org.rubypeople.rdt.internal.debug.ui.display.RubyInspectExpression;
+import org.rubypeople.rdt.internal.ui.text.RubyWordFinder;
+
+
+/**
+ * Action to do simple code evaluation. The evaluation
+ * is done in the UI thread and the expression and result are
+ * displayed using the IDataDisplay.
+ */
+public abstract class EvaluateAction implements IWorkbenchWindowActionDelegate, IObjectActionDelegate, IEditorActionDelegate, IPartListener, IViewActionDelegate {
+
+ private IAction fAction;
+ private IWorkbenchPart fTargetPart;
+ private IWorkbenchWindow fWindow;
+ private Object fSelection;
+ private IRegion fRegion;
+
+ /**
+ * Is the action waiting for an evaluation.
+ */
+ private boolean fEvaluating;
+
+ /**
+ * The new target part to use with the evaluation completes.
+ */
+ private IWorkbenchPart fNewTargetPart= null;
+
+ /**
+ * Used to resolve editor input for selected stack frame
+ */
+ private IDebugModelPresentation fPresentation;
+
+ public EvaluateAction() {
+ super();
+ }
+
+ /**
+ * Returns the 'object' context for this evaluation,
+ * or <code>null</code> if none. If the evaluation is being performed
+ * in the context of the variables view/inspector. Then
+ * perform the evaluation in the context of the
+ * selected value.
+ *
+ * @return Ruby object or <code>null</code>
+ */
+ protected RubyValue getObjectContext() {
+ IWorkbenchPage page= RdtDebugUiPlugin.getActivePage();
+ if (page != null) {
+ IWorkbenchPart activePart= page.getActivePart();
+ if (activePart != null) {
+ IDebugView a = (IDebugView)activePart.getAdapter(IDebugView.class);
+ if (a != null) {
+ if (a.getViewer() != null) {
+ ISelection s = a.getViewer().getSelection();
+ if (s instanceof IStructuredSelection) {
+ IStructuredSelection structuredSelection = (IStructuredSelection)s;
+ if (structuredSelection.size() == 1) {
+ Object selection= structuredSelection.getFirstElement();
+ if (selection instanceof RubyVariable) {
+ RubyVariable var = (RubyVariable)selection;
+ // if 'this' is selected, use stack frame context
+// try {
+ if (!var.getName().equals("this")) { //$NON-NLS-1$
+ IValue value= var.getValue();
+ if (value instanceof RubyValue) {
+ return (RubyValue)value;
+ }
+ }
+// } catch (DebugException e) {
+// RdtDebugUiPlugin.log(e);
+// }
+ } else if (selection instanceof RubyInspectExpression) {
+ IValue value= ((RubyInspectExpression)selection).getValue();
+ if (value instanceof RubyValue) {
+ return (RubyValue)value;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Finds the currently selected stack frame in the UI.
+ * Stack frames from a scrapbook launch are ignored.
+ */
+ protected RubyStackFrame getStackFrameContext() {
+ IWorkbenchPart part = getTargetPart();
+ RubyStackFrame frame = null;
+ if (part == null) {
+ frame = EvaluationContextManager.getEvaluationContext(getWindow());
+ } else {
+ frame = EvaluationContextManager.getEvaluationContext(part);
+ }
+ return frame;
+ }
+
+ /**
+ * @see IEvaluationListener#evaluationComplete(IEvaluationResult)
+ */
+ public void evaluationComplete(final IEvaluationResult result) {
+ // if plug-in has shutdown, ignore - see bug# 8693
+ if (RdtDebugUiPlugin.getDefault() == null) {
+ return;
+ }
+
+ final IValue value= result.getValue();
+ if (result.hasErrors() || value != null) {
+ final Display display= RdtDebugUiPlugin.getStandardDisplay();
+ if (display.isDisposed()) {
+ return;
+ }
+ displayResult(result);
+ }
+ }
+
+ protected void evaluationCleanup() {
+ setEvaluating(false);
+ setTargetPart(fNewTargetPart);
+ }
+ /**
+ * Display the given evaluation result.
+ */
+ abstract protected void displayResult(IEvaluationResult result);
+
+ protected void run() {
+ // eval in context of object or stack frame
+ final RubyValue object = getObjectContext();
+ final RubyStackFrame stackFrame= getStackFrameContext();
+ if (stackFrame == null) {
+ reportError(ActionMessages.Evaluate_error_message_stack_frame_context);
+ return;
+ }
+
+ // check for nested evaluation
+ IThread thread = (IThread)stackFrame.getThread();
+// if (thread.isPerformingEvaluation()) {
+// reportError(ActionMessages.EvaluateAction_Cannot_perform_nested_evaluations__1);
+// return;
+// }
+
+ setNewTargetPart(getTargetPart());
+
+ IRunnableWithProgress runnable = new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+ if (stackFrame.isSuspended()) {
+ IRubyElement javaElement= getRubyElement(stackFrame);
+ if (javaElement != null) {
+ IRubyProject project = javaElement.getRubyProject();
+ try {
+ Object selection= getSelectedObject();
+ if (!(selection instanceof String)) {
+ return;
+ }
+ String expression= (String)selection;
+ setEvaluating(true);
+ RubyDebuggerProxy proxy = stackFrame.getRubyDebuggerProxy();
+ IEvaluationResult result = proxy.evaluate(stackFrame, expression);
+ evaluationComplete(result);
+ return;
+ } catch (RubyProcessingException e) {
+ throw new InvocationTargetException(e, getExceptionMessage(e));
+ }
+ }
+ throw new InvocationTargetException(null, ActionMessages.Evaluate_error_message_src_context);
+ }
+ // thread not suspended
+ throw new InvocationTargetException(null, ActionMessages.EvaluateAction_Thread_not_suspended___unable_to_perform_evaluation__1);
+ }
+ };
+
+ IWorkbench workbench = RdtDebugUiPlugin.getDefault().getWorkbench();
+ try {
+ 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) {
+ }
+ }
+
+ protected IRubyElement getRubyElement(IStackFrame stackFrame) {
+
+ // Get the corresponding element.
+ ILaunch launch = stackFrame.getLaunch();
+ if (launch == null) {
+ return null;
+ }
+ ISourceLocator locator= launch.getSourceLocator();
+ if (locator == null)
+ return null;
+
+ Object sourceElement = locator.getSourceElement(stackFrame);
+ if (sourceElement instanceof SourceElement) {
+ SourceElement element = (SourceElement) sourceElement;
+ if (element.isExternal()) {
+ // FIXME We need to track the file to a project that contains it in an external source folder!
+ return null;
+ } else {
+ IRubyProject project = RubyCore.create((element.getWorkspaceFile()).getProject());
+ if (project.exists()) {
+ return project;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Updates the enabled state of the action that this is a
+ * delegate for.
+ */
+ protected void update() {
+ IAction action= getAction();
+ if (action != null) {
+ resolveSelectedObject();
+ }
+ }
+
+ /**
+ * Resolves the selected object in the target part, or <code>null</code>
+ * if there is no selection.
+ */
+ protected void resolveSelectedObject() {
+ Object selectedObject= null;
+ fRegion = null;
+ ISelection selection= getTargetSelection();
+ if (selection instanceof ITextSelection) {
+ ITextSelection ts = (ITextSelection)selection;
+ String text= ts.getText();
+ if (textHasContent(text)) {
+ selectedObject= text;
+ fRegion = new Region(ts.getOffset(), ts.getLength());
+ } else if (getTargetPart() instanceof IEditorPart) {
+ IEditorPart editor= (IEditorPart)getTargetPart();
+ if (editor instanceof ITextEditor) {
+ selectedObject = resolveSelectedObjectUsingToken(selectedObject, ts, editor);
+ }
+ }
+ } else if (selection instanceof IStructuredSelection) {
+ if (!selection.isEmpty()) {
+ if (getTargetPart().getSite().getId().equals(IDebugUIConstants.ID_DEBUG_VIEW)) {
+ //work on the editor selection
+ IEditorPart editor= getTargetPart().getSite().getPage().getActiveEditor();
+ setTargetPart(editor);
+ selection= getTargetSelection();
+ if (selection instanceof ITextSelection) {
+ ITextSelection ts = (ITextSelection)selection;
+ String text= ts.getText();
+ if (textHasContent(text)) {
+ selectedObject= text;
+ } else if (editor instanceof ITextEditor) {
+ selectedObject= resolveSelectedObjectUsingToken(selectedObject, ts, editor);
+ }
+ }
+ } else {
+ IStructuredSelection ss= (IStructuredSelection)selection;
+ Iterator elements = ss.iterator();
+ while (elements.hasNext()) {
+ if (!(elements.next() instanceof RubyVariable)) {
+ setSelectedObject(null);
+ return;
+ }
+ }
+ selectedObject= ss;
+ }
+ }
+ }
+ setSelectedObject(selectedObject);
+ }
+
+ private Object resolveSelectedObjectUsingToken(Object selectedObject, ITextSelection ts, IEditorPart editor) {
+ ITextEditor textEditor= (ITextEditor) editor;
+ IDocument doc= textEditor.getDocumentProvider().getDocument(editor.getEditorInput());
+ fRegion= RubyWordFinder.findWord(doc, ts.getOffset());
+ if (fRegion != null) {
+ try {
+ selectedObject= doc.get(fRegion.getOffset(), fRegion.getLength());
+ } catch (BadLocationException e) {
+ }
+ }
+ return selectedObject;
+ }
+
+ protected ISelection getTargetSelection() {
+ IWorkbenchPart part = getTargetPart();
+ if (part != null) {
+ ISelectionProvider provider = part.getSite().getSelectionProvider();
+ if (provider != null) {
+ return provider.getSelection();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Resolve an editor input from the source element of the stack frame
+ * argument, and return whether it's equal to the editor input for the
+ * editor that owns this action.
+ */
+ protected boolean compareToEditorInput(IStackFrame stackFrame) {
+ ILaunch launch = stackFrame.getLaunch();
+ if (launch == null) {
+ return false;
+ }
+ ISourceLocator locator= launch.getSourceLocator();
+ if (locator == null) {
+ return false;
+ }
+ Object sourceElement = locator.getSourceElement(stackFrame);
+ if (sourceElement == null) {
+ return false;
+ }
+ IEditorInput sfEditorInput= getDebugModelPresentation().getEditorInput(sourceElement);
+ if (getTargetPart() instanceof IEditorPart) {
+ return ((IEditorPart)getTargetPart()).getEditorInput().equals(sfEditorInput);
+ }
+ return false;
+ }
+
+ protected Shell getShell() {
+ if (getTargetPart() != null) {
+ return getTargetPart().getSite().getShell();
+ }
+ return RdtDebugUiPlugin.getActiveWorkbenchShell();
+ }
+
+ protected IDataDisplay getDataDisplay() {
+ IDataDisplay display= getDirectDataDisplay();
+ if (display != null) {
+ return display;
+ }
+ IWorkbenchPage page= RdtDebugUiPlugin.getActivePage();
+ if (page != null) {
+ IWorkbenchPart activePart= page.getActivePart();
+ if (activePart != null) {
+ IViewPart view = page.findView(RdtDebugUiConstants.ID_DISPLAY_VIEW);
+ if (view == null) {
+ try {
+ view= page.showView(RdtDebugUiConstants.ID_DISPLAY_VIEW);
+ } catch (PartInitException e) {
+ RdtDebugUiPlugin.errorDialog(ActionMessages.EvaluateAction_Cannot_open_Display_view, e);
+ } finally {
+ page.activate(activePart);
+ }
+ }
+ if (view != null) {
+ page.bringToTop(view);
+ return (IDataDisplay)view.getAdapter(IDataDisplay.class);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ protected IDataDisplay getDirectDataDisplay() {
+ IWorkbenchPart part= getTargetPart();
+ if (part != null) {
+ IDataDisplay display= (IDataDisplay)part.getAdapter(IDataDisplay.class);
+ if (display != null) {
+ IWorkbenchPage page= RdtDebugUiPlugin.getActivePage();
+ if (page != null) {
+ IWorkbenchPart activePart= page.getActivePart();
+ if (activePart != null) {
+ if (activePart != part) {
+ page.activate(part);
+ }
+ }
+ }
+ return display;
+ }
+ }
+ IWorkbenchPage page= RdtDebugUiPlugin.getActivePage();
+ if (page != null) {
+ IWorkbenchPart activePart= page.getActivePart();
+ if (activePart != null) {
+ IDataDisplay display= (IDataDisplay)activePart.getAdapter(IDataDisplay.class);
+ if (display != null) {
+ return display;
+ }
+ }
+ }
+ return null;
+ }
+
+ protected 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;
+ }
+
+ /**
+ * Displays a failed evaluation message in the data display.
+ */
+ protected void reportErrors(IEvaluationResult result) {
+ String message= getErrorMessage(result);
+ reportError(message);
+ }
+
+ protected void reportError(String message) {
+ IDataDisplay dataDisplay= getDirectDataDisplay();
+ if (dataDisplay != null) {
+ if (message.length() != 0) {
+ dataDisplay.displayExpressionValue(MessageFormat.format(ActionMessages.EvaluateAction__evaluation_failed__Reason, new String[] {format(message)}));
+ } else {
+ dataDisplay.displayExpressionValue(ActionMessages.EvaluateAction__evaluation_failed__1);
+ }
+ } else {
+ Status status= new Status(IStatus.ERROR, RdtDebugUiPlugin.getUniqueIdentifier(), IStatus.ERROR, message, null);
+ ErrorDialog.openError(getShell(), ActionMessages.Evaluate_error_title_eval_problems, null, status);
+ }
+ }
+
+ private String format(String message) {
+ StringBuffer result= new StringBuffer();
+ int index= 0, pos;
+ while ((pos= message.indexOf('\n', index)) != -1) {
+ result.append("\t\t").append(message.substring(index, index= pos + 1)); //$NON-NLS-1$
+ }
+ if (index < message.length()) {
+ result.append("\t\t").append(message.substring(index)); //$NON-NLS-1$
+ }
+ return result.toString();
+ }
+
+ 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= MessageFormat.format(ActionMessages.Evaluate_error_message_direct_exception, new Object[] { exception.getClass() });
+ if (exception.getMessage() != null) {
+ message= MessageFormat.format(ActionMessages.Evaluate_error_message_exception_pattern, new Object[] { message, exception.getMessage() });
+ }
+ return message;
+ }
+
+ protected String getErrorMessage(IEvaluationResult result) {
+ String[] errors= result.getErrorMessages();
+ if (errors.length == 0) {
+ return getExceptionMessage(result.getException());
+ }
+ return getErrorMessage(errors);
+ }
+
+ protected 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= MessageFormat.format(ActionMessages.Evaluate_error_problem_append_pattern, new Object[] { message, msg });
+ }
+ }
+ return message;
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.ui.IActionDelegate#run(IAction)
+ */
+ public void run(IAction action) {
+ update();
+ run();
+ }
+
+ /* (non-Rubydoc)
+ * @see org.eclipse.ui.IActionDelegate#selectionChanged(IAction, ISelection)
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ setAction(action);
+ }
+
+ /**
+ * @see IWorkbenchWindowActionDelegate#dispose()
+ */
+ public void dispose() {
+ disposeDebugModelPresentation();
+ IWorkbenchWindow win = getWindow();
+ if (win != null) {
+ win.getPartService().removePartListener(this);
+ }
+ }
+
+ /**
+ * @see IWorkbenchWindowActionDelegate#init(IWorkbenchWindow)
+ */
+ public void init(IWorkbenchWindow window) {
+ setWindow(window);
+ IWorkbenchPage page= window.getActivePage();
+ if (page != null) {
+ setTargetPart(page.getActivePart());
+ }
+ window.getPartService().addPartListener(this);
+ update();
+ }
+
+ protected IAction getAction() {
+ return fAction;
+ }
+
+ protected void setAction(IAction action) {
+ fAction = action;
+ }
+
+ /**
+ * Returns a debug model presentation (creating one
+ * if necessary).
+ *
+ * @return debug model presentation
+ */
+ protected IDebugModelPresentation getDebugModelPresentation() {
+ if (fPresentation == null) {
+ fPresentation = DebugUITools.newDebugModelPresentation(RdtDebugCorePlugin.getPluginIdentifier());
+ }
+ return fPresentation;
+ }
+
+ /**
+ * Disposes this action's debug model presentation, if
+ * one was created.
+ */
+ protected void disposeDebugModelPresentation() {
+ if (fPresentation != null) {
+ fPresentation.dispose();
+ }
+ }
+
+ /**
+ * @see IEditorActionDelegate#setActiveEditor(IAction, IEditorPart)
+ */
+ public void setActiveEditor(IAction action, IEditorPart targetEditor) {
+ setAction(action);
+ setTargetPart(targetEditor);
+ }
+
+ /**
+ * @see IPartListener#partActivated(IWorkbenchPart)
+ */
+ public void partActivated(IWorkbenchPart part) {
+ setTargetPart(part);
+ }
+
+ /**
+ * @see IPartListener#partBroughtToTop(IWorkbenchPart)
+ */
+ public void partBroughtToTop(IWorkbenchPart part) {
+ }
+
+ /**
+ * @see IPartListener#partClosed(IWorkbenchPart)
+ */
+ public void partClosed(IWorkbenchPart part) {
+ if (part == getTargetPart()) {
+ setTargetPart(null);
+ }
+ if (part == getNewTargetPart()) {
+ setNewTargetPart(null);
+ }
+ }
+
+ /**
+ * @see IPartListener#partDeactivated(IWorkbenchPart)
+ */
+ public void partDeactivated(IWorkbenchPart part) {
+ }
+
+ /**
+ * @see IPartListener#partOpened(IWorkbenchPart)
+ */
+ public void partOpened(IWorkbenchPart part) {
+ }
+
+ /**
+ * @see IViewActionDelegate#init(IViewPart)
+ */
+ public void init(IViewPart view) {
+ setTargetPart(view);
+ }
+
+ protected IWorkbenchPart getTargetPart() {
+ return fTargetPart;
+ }
+
+ protected void setTargetPart(IWorkbenchPart part) {
+ if (isEvaluating()) {
+ //do not want to change the target part while evaluating
+ //see bug 8334
+ setNewTargetPart(part);
+ } else {
+ fTargetPart= part;
+ }
+ }
+
+ protected IWorkbenchWindow getWindow() {
+ return fWindow;
+ }
+
+ protected void setWindow(IWorkbenchWindow window) {
+ fWindow = window;
+ }
+
+ /**
+ * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
+ */
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ setAction(action);
+ setTargetPart(targetPart);
+ update();
+ }
+
+ protected Object getSelectedObject() {
+ return fSelection;
+ }
+
+ protected void setSelectedObject(Object selection) {
+ fSelection = selection;
+ }
+
+ protected IWorkbenchPart getNewTargetPart() {
+ return fNewTargetPart;
+ }
+
+ protected void setNewTargetPart(IWorkbenchPart newTargetPart) {
+ fNewTargetPart = newTargetPart;
+ }
+
+ protected boolean isEvaluating() {
+ return fEvaluating;
+ }
+
+ protected void setEvaluating(boolean evaluating) {
+ fEvaluating = evaluating;
+ }
+
+ /**
+ * Returns the selected text region, or <code>null</code> if none.
+ *
+ * @return
+ */
+ protected IRegion getRegion() {
+ return fRegion;
+ }
+
+ /**
+ * Computes an anchor point for a popup dialog on top of a text viewer.
+ *
+ * @param viewer
+ * @return desired anchor point
+ */
+ public static Point getPopupAnchor(ITextViewer viewer) {
+ StyledText textWidget = viewer.getTextWidget();
+ 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;
+ }
+}
Property changes on: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/EvaluateAction.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Added: trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ExecuteAction.java
===================================================================
--- trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ExecuteAction.java (rev 0)
+++ trunk/org.rubypeople.rdt.debug.ui/src/org/rubypeople/rdt/internal/debug/ui/actions/ExecuteAction.java 2007-08-23 18:18:47 UTC (rev 3060)
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanyi...
[truncated message content] |