diff --git a/java/src/processing/mode/java/Debugger.java b/java/src/processing/mode/java/Debugger.java index 7b37a96f9..42fe46a7b 100644 --- a/java/src/processing/mode/java/Debugger.java +++ b/java/src/processing/mode/java/Debugger.java @@ -25,6 +25,10 @@ import com.sun.jdi.*; import com.sun.jdi.event.*; import com.sun.jdi.request.*; +import java.awt.Component; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; import java.io.*; import java.util.ArrayList; import java.util.HashMap; @@ -36,22 +40,31 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import javax.swing.JMenu; +import javax.swing.JMenuItem; import javax.swing.JTree; // needed for javadocs import javax.swing.tree.DefaultMutableTreeNode; +import processing.app.Language; import processing.app.Messages; import processing.app.RunnerListenerEdtAdapter; import processing.app.Sketch; import processing.app.SketchCode; +import processing.app.ui.Toolkit; import processing.mode.java.debug.*; import processing.mode.java.runner.Runner; public class Debugger { - /// editor window, acting as main view protected JavaEditor editor; + protected JMenu debugMenu; + protected JMenuItem debugItem; + protected boolean enabled; + + protected VariableInspector inspector; + /// the runtime, contains debuggee VM protected Runner runtime; @@ -97,9 +110,139 @@ public class Debugger { public Debugger(JavaEditor editor) { this.editor = editor; + inspector = new VariableInspector(editor); } + /** + * Creates the debug menu. Includes ActionListeners for the menu items. + * Intended for adding to the menu bar. + * + * @return The debug menu + */ + protected JMenu buildMenu() { + debugMenu = new JMenu(Language.text("menu.debug")); + JMenuItem item; + + debugItem = Toolkit.newJMenuItem(Language.text("menu.debug.enable"), 'D'); + debugItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + toggleEnabled(); + } + }); + debugMenu.add(debugItem); + debugMenu.addSeparator(); + + item = Toolkit.newJMenuItem(Language.text("menu.debug.continue"), KeyEvent.VK_U); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + //editor.handleContinue(); + continueDebug(); + } + }); + debugMenu.add(item); + item.setEnabled(false); + + item = Toolkit.newJMenuItemExt("menu.debug.step"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + //editor.handleStep(0); + stepOver(); + } + }); + debugMenu.add(item); + item.setEnabled(false); + + item = Toolkit.newJMenuItemExt("menu.debug.step_into"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + //handleStep(ActionEvent.SHIFT_MASK); + stepInto(); + } + }); + debugMenu.add(item); + item.setEnabled(false); + + item = Toolkit.newJMenuItemExt("menu.debug.step_out"); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + //handleStep(ActionEvent.ALT_MASK); + stepOut(); + } + }); + debugMenu.add(item); + item.setEnabled(false); + + debugMenu.addSeparator(); + + item = + Toolkit.newJMenuItem(Language.text("menu.debug.toggle_breakpoint"), 'B'); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Messages.log("Invoked 'Toggle Breakpoint' menu item"); + // TODO wouldn't getCaretLine() do the same thing with less effort? + toggleBreakpoint(editor.getCurrentLineID().lineIdx()); + } + }); + debugMenu.add(item); + item.setEnabled(false); + + return debugMenu; + } + + + void enableMenuItem(boolean enabled) { + debugItem.setEnabled(enabled); + } + + + boolean isEnabled() { + return enabled; + } + + + void toggleEnabled() { + enabled = !enabled; + + if (enabled) { + debugItem.setText(Language.text("menu.debug.disable")); + } else { + debugItem.setText(Language.text("menu.debug.enable")); + } + inspector.setVisible(enabled); + + for (Component item : debugMenu.getMenuComponents()) { + if (item instanceof JMenuItem && item != debugItem) { + item.setEnabled(enabled); + } + } + } + + + /* + public void handleStep(int modifiers) { + if (modifiers == 0) { + Messages.log("Invoked 'Step Over' menu item"); + stepOver(); + + } else if ((modifiers & ActionEvent.SHIFT_MASK) != 0) { + Messages.log("Invoked 'Step Into' menu item"); + stepInto(); + + } else if ((modifiers & ActionEvent.ALT_MASK) != 0) { + Messages.log("Invoked 'Step Out' menu item"); + stepOut(); + } + } + + + public void handleContinue() { + Messages.log("Invoked 'Continue' menu item"); + continueDebug(); + } + */ + + public VirtualMachine vm() { if (runtime != null) { return runtime.vm(); @@ -156,6 +299,11 @@ public class Debugger { } + public void dispose() { + inspector.dispose(); + } + + /** * Start a debugging session. Builds the sketch and launches a VM to run it. * VM starts suspended. Should produce a VMStartEvent. @@ -173,7 +321,7 @@ public class Debugger { editor.clearConsole(); // clear variable inspector (also resets expanded states) - editor.variableInspector().reset(); + inspector.reset(); // load edits into sketch obj, etc... editor.prepareRun(); @@ -227,7 +375,7 @@ public class Debugger { * VMDisconnectEvent. */ public synchronized void stopDebug() { - editor.variableInspector().lock(); + inspector.lock(); if (runtime != null) { Messages.log("closing runtime"); @@ -256,7 +404,7 @@ public class Debugger { /** Resume paused debugging session. Resumes VM. */ public synchronized void continueDebug() { editor.activateContinue(); - editor.variableInspector().lock(); + inspector.lock(); //editor.clearSelection(); //clearHighlight(); editor.clearCurrentLine(); @@ -279,7 +427,7 @@ public class Debugger { if (!isStarted()) { startDebug(); } else if (isPaused()) { - editor.variableInspector().lock(); + inspector.lock(); editor.activateStep(); // use global to mark that there is a step request pending @@ -884,7 +1032,6 @@ public class Debugger { // TODO: needs to be handled in a better way: log("call stack empty"); } else { - final VariableInspector vi = editor.variableInspector(); // first get data final List stackTrace = getStackTrace(t); final List locals = getLocals(t, 0); @@ -893,16 +1040,16 @@ public class Debugger { final List declaredThisFields = getThisFields(t, 0, false); final String thisName = thisName(t); // now update asynchronously - javax.swing.SwingUtilities.invokeLater(new Runnable() { + java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { //System.out.println("updating vi. from EDT: " + javax.swing.SwingUtilities.isEventDispatchThread()); - vi.updateCallStack(stackTrace, "Call Stack"); - vi.updateLocals(locals, "Locals at " + currentLocation); - vi.updateThisFields(thisFields, "Class " + thisName); - vi.updateDeclaredThisFields(declaredThisFields, "Class " + thisName); - vi.unlock(); // need to do this before rebuilding, otherwise we get these ... dots in the labels - vi.rebuild(); + inspector.updateCallStack(stackTrace, "Call Stack"); + inspector.updateLocals(locals, "Locals at " + currentLocation); + inspector.updateThisFields(thisFields, "Class " + thisName); + inspector.updateDeclaredThisFields(declaredThisFields, "Class " + thisName); + inspector.unlock(); // need to do this before rebuilding, otherwise we get these ... dots in the labels + inspector.rebuild(); } }); } diff --git a/java/src/processing/mode/java/JavaEditor.java b/java/src/processing/mode/java/JavaEditor.java index f38928089..10dc13ca2 100644 --- a/java/src/processing/mode/java/JavaEditor.java +++ b/java/src/processing/mode/java/JavaEditor.java @@ -74,12 +74,6 @@ public class JavaEditor extends Editor { protected LineHighlight currentLine; // where the debugger is suspended protected final String breakpointMarkerComment = " //<>//"; - protected JMenu debugMenu; - protected JMenuItem debugItem; - protected Debugger debugger; - protected boolean debugEnabled; - - protected VariableInspector inspector; protected JMenuItem inspectorItem; static final int ERROR_TAB_INDEX = 0; @@ -87,7 +81,9 @@ public class JavaEditor extends Editor { private boolean hasJavaTabs; private boolean javaTabWarned; - protected PreprocService preprocessingService; + protected PreprocService preprocService; + + protected Debugger debugger; private InspectMode inspect; private ShowUsage usage; @@ -108,7 +104,6 @@ public class JavaEditor extends Editor { jmode = (JavaMode) mode; debugger = new Debugger(this); - inspector = new VariableInspector(this); // set breakpoints from marker comments for (LineID lineID : stripBreakpointComments()) { @@ -136,19 +131,19 @@ public class JavaEditor extends Editor { box.add(textAndError); */ - preprocessingService = new PreprocService(this); + preprocService = new PreprocService(this); pdexEnabled = !hasJavaTabs(); - usage = new ShowUsage(this, preprocessingService); - inspect = new InspectMode(this, preprocessingService, usage); - rename = new Rename(this, preprocessingService, usage); + usage = new ShowUsage(this, preprocService); + inspect = new InspectMode(this, preprocService, usage); + rename = new Rename(this, preprocService, usage); if (SHOW_AST_VIEWER) { - astViewer = new ASTViewer(this, preprocessingService); + astViewer = new ASTViewer(this, preprocService); } - errorChecker = new ErrorChecker(this, preprocessingService); + errorChecker = new ErrorChecker(this, preprocService); for (SketchCode code : getSketch().getCode()) { Document document = code.getDocument(); @@ -198,9 +193,9 @@ public class JavaEditor extends Editor { boolean hasJavaTabsChanged = hasJavaTabs != newHasJavaTabs; hasJavaTabs = newHasJavaTabs; - if (preprocessingService != null) { + if (preprocService != null) { if (hasJavaTabsChanged) { - preprocessingService.handleHasJavaTabsChange(hasJavaTabs); + preprocService.handleHasJavaTabsChange(hasJavaTabs); pdexEnabled = !hasJavaTabs; if (!pdexEnabled) { usage.hide(); @@ -1194,28 +1189,6 @@ public class JavaEditor extends Editor { } - public void handleStep(int modifiers) { - if (modifiers == 0) { - Messages.log("Invoked 'Step Over' menu item"); - debugger.stepOver(); - - } else if ((modifiers & ActionEvent.SHIFT_MASK) != 0) { - Messages.log("Invoked 'Step Into' menu item"); - debugger.stepInto(); - - } else if ((modifiers & ActionEvent.ALT_MASK) != 0) { - Messages.log("Invoked 'Step Out' menu item"); - debugger.stepOut(); - } - } - - - public void handleContinue() { - Messages.log("Invoked 'Continue' menu item"); - debugger.continueDebug(); - } - - public void onRunnerExiting(Runner runner) { synchronized (runtimeLock) { if (this.runtime == runner) { @@ -1315,20 +1288,20 @@ public class JavaEditor extends Editor { @Override public void librariesChanged() { - preprocessingService.notifyLibrariesChanged(); + preprocService.notifyLibrariesChanged(); } @Override public void codeFolderChanged() { - preprocessingService.notifyCodeFolderChanged(); + preprocService.notifyCodeFolderChanged(); } @Override public void sketchChanged() { errorChecker.notifySketchChanged(); - preprocessingService.notifySketchChanged(); + preprocService.notifySketchChanged(); } @@ -1385,13 +1358,11 @@ public class JavaEditor extends Editor { public void dispose() { //System.out.println("window dispose"); // quit running debug session - if (debugEnabled) { + if (debugger.isEnabled()) { debugger.stopDebug(); } - if (inspector != null) { - inspector.dispose(); - } - preprocessingService.dispose(); + debugger.dispose(); + preprocService.dispose(); inspect.dispose(); usage.dispose(); @@ -1405,201 +1376,16 @@ public class JavaEditor extends Editor { } - /** - * Creates the debug menu. Includes ActionListeners for the menu items. - * Intended for adding to the menu bar. - * - * @return The debug menu - */ - protected JMenu buildDebugMenu() { - debugMenu = new JMenu(Language.text("menu.debug")); - JMenuItem item; - - // "use the debugger" sounds too colloquial, and "enable" sounds too technical -// enableDebug = -// Toolkit.newJCheckBoxMenuItem(Language.text("menu.debug.enable"), -// KeyEvent.VK_D); -// enableDebug = -// Toolkit.newJCheckBoxMenuItem(Language.text("menu.debug.enable"), -// KeyEvent.VK_D); - debugItem = Toolkit.newJMenuItem(Language.text("menu.debug.enable"), 'D'); -// enableDebug.setSelected(false); - debugItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { -// updateDebugToggle(); - toggleDebug(); - } - }); -// toggleDebugger.addChangeListener(new ChangeListener() { -// public void stateChanged(ChangeEvent e) { -// } -// }); - debugMenu.add(debugItem); - debugMenu.addSeparator(); - -// item = Toolkit.newJMenuItemAlt(Language.text("menu.debug.debug"), KeyEvent.VK_R); -// item.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// Logger.getLogger(JavaEditor.class.getName()).log(Level.INFO, "Invoked 'Debug' menu item"); -// debugger.startDebug(); -// } -// }); -// debugMenu.add(item); - - item = Toolkit.newJMenuItem(Language.text("menu.debug.continue"), KeyEvent.VK_U); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleContinue(); - } - }); - debugMenu.add(item); - item.setEnabled(false); - -// item = new JMenuItem(Language.text("menu.debug.stop")); -// item.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// Logger.getLogger(JavaEditor.class.getName()).log(Level.INFO, "Invoked 'Stop' menu item"); -// debugger.stopDebug(); -// } -// }); -// debugMenu.add(item); - - item = Toolkit.newJMenuItemExt("menu.debug.step"); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleStep(0); - } - }); - debugMenu.add(item); - item.setEnabled(false); - - item = Toolkit.newJMenuItemExt("menu.debug.step_into"); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleStep(ActionEvent.SHIFT_MASK); - } - }); - debugMenu.add(item); - item.setEnabled(false); - - item = Toolkit.newJMenuItemExt("menu.debug.step_out"); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleStep(ActionEvent.ALT_MASK); - } - }); - debugMenu.add(item); - item.setEnabled(false); - - debugMenu.addSeparator(); - - item = - Toolkit.newJMenuItem(Language.text("menu.debug.toggle_breakpoint"), 'B'); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Messages.log("Invoked 'Toggle Breakpoint' menu item"); - // TODO wouldn't getCaretLine() do the same thing with less effort? - toggleBreakpoint(getCurrentLineID().lineIdx()); - } - }); - debugMenu.add(item); - item.setEnabled(false); - - /* - inspectorItem = Toolkit.newJMenuItem(Language.text("menu.debug.show_variables"), 'Y'); - inspectorItem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - toggleVariableInspector(); - } - }); - debugMenu.add(inspectorItem); - inspectorItem.setEnabled(false); - */ - - /* - item = new JMenuItem(Language.text("menu.debug.list_breakpoints")); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Logger.getLogger(JavaEditor.class.getName()).log(Level.INFO, "Invoked 'List Breakpoints' menu item"); - debugger.listBreakpoints(); - } - }); - debugMenu.add(item); - - debugMenu.addSeparator(); - */ - - /* - item = new JMenuItem(Language.text("menu.debug.print_stack_trace")); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Logger.getLogger(JavaEditor.class.getName()).log(Level.INFO, "Invoked 'Print Stack Trace' menu item"); - debugger.printStackTrace(); - } - }); - debugMenu.add(item); - - item = new JMenuItem(Language.text("menu.debug.print_locals")); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Logger.getLogger(JavaEditor.class.getName()).log(Level.INFO, "Invoked 'Print Locals' menu item"); - debugger.printLocals(); - } - }); - debugMenu.add(item); - - item = new JMenuItem(Language.text("menu.debug.print_fields")); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Logger.getLogger(JavaEditor.class.getName()).log(Level.INFO, "Invoked 'Print This' menu item"); - debugger.printThis(); - } - }); - debugMenu.add(item); - - item = new JMenuItem(Language.text("menu.debug.print_source_location")); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Logger.getLogger(JavaEditor.class.getName()).log(Level.INFO, "Invoked 'Print Source' menu item"); - debugger.printSource(); - } - }); - debugMenu.add(item); - - item = new JMenuItem(Language.text("menu.debug.print_threads")); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Logger.getLogger(JavaEditor.class.getName()).log(Level.INFO, "Invoked 'Print Threads' menu item"); - debugger.printThreads(); - } - }); - debugMenu.add(item); - - debugMenu.addSeparator(); - */ - -// item = Toolkit.newJMenuItem(Language.text("menu.debug.toggle_variable_inspector"), KeyEvent.VK_I); -// item.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// Logger.getLogger(JavaEditor.class.getName()).log(Level.INFO, "Invoked 'Toggle Variable Inspector' menu item"); -// toggleVariableInspector(); -// } -// }); -// debugMenu.add(item); - - return debugMenu; - } - - @Override public boolean isDebuggerEnabled() { - return debugEnabled; + return debugger.isEnabled(); } @Override public JMenu buildModeMenu() { - return buildDebugMenu(); + //return buildDebugMenu(); + return debugger.buildMenu(); } @@ -1836,7 +1622,7 @@ public class JavaEditor extends Editor { public PreprocService getPreprocessingService() { - return preprocessingService; + return preprocService; } @@ -1849,7 +1635,7 @@ public class JavaEditor extends Editor { autoSave(); super.prepareRun(); downloadImports(); - preprocessingService.cancel(); + preprocService.cancel(); } @@ -2020,18 +1806,8 @@ public class JavaEditor extends Editor { } - /** - * Access variable inspector window. - * @return the variable inspector object - */ - public VariableInspector variableInspector() { - return inspector; - } - - protected void activateRun() { - debugItem.setEnabled(false); -// toolbar.activate(JavaToolbar.RUN); + debugger.enableMenuItem(false); toolbar.activateRun(); } @@ -2044,12 +1820,11 @@ public class JavaEditor extends Editor { */ public void deactivateRun() { toolbar.deactivateRun(); - debugItem.setEnabled(true); + debugger.enableMenuItem(true); } protected void activateDebug() { - //debugToolbar.activate(DebugToolbar.DEBUG); activateRun(); } @@ -2080,11 +1855,12 @@ public class JavaEditor extends Editor { public void toggleDebug() { - debugEnabled = !debugEnabled; +// debugEnabled = !debugEnabled; rebuildToolbar(); repaint(); // show/hide breakpoints in the gutter + /* if (debugEnabled) { debugItem.setText(Language.text("menu.debug.disable")); } else { @@ -2097,6 +1873,7 @@ public class JavaEditor extends Editor { item.setEnabled(debugEnabled); } } + */ } diff --git a/java/src/processing/mode/java/JavaToolbar.java b/java/src/processing/mode/java/JavaToolbar.java index 3d7d0dbb3..dc3f497d7 100644 --- a/java/src/processing/mode/java/JavaToolbar.java +++ b/java/src/processing/mode/java/JavaToolbar.java @@ -77,8 +77,17 @@ public class JavaToolbar extends EditorToolbar { Language.text("menu.debug.step_out")) { @Override public void actionPerformed(ActionEvent e) { - final int mask = ActionEvent.SHIFT_MASK | ActionEvent.ALT_MASK; - jeditor.handleStep(e.getModifiers() & mask); + Debugger d = jeditor.getDebugger(); + + final int modifiers = e.getModifiers() & + (ActionEvent.SHIFT_MASK | ActionEvent.ALT_MASK); + if (modifiers == 0) { + d.stepOver(); + } else if ((modifiers & ActionEvent.SHIFT_MASK) != 0) { + d.stepInto(); + } else if ((modifiers & ActionEvent.ALT_MASK) != 0) { + d.stepOut(); + } } }; outgoing.add(stepButton); @@ -88,7 +97,8 @@ public class JavaToolbar extends EditorToolbar { Language.text("menu.debug.continue")) { @Override public void actionPerformed(ActionEvent e) { - jeditor.handleContinue(); + //jeditor.handleContinue(); + jeditor.getDebugger().continueDebug(); } }; outgoing.add(continueButton);