diff options
author | Pawel Piech | 2008-09-25 03:20:15 +0000 |
---|---|---|
committer | Pawel Piech | 2008-09-25 03:20:15 +0000 |
commit | 6856eb8f9fea18057ccb49306160f6ecf563d429 (patch) | |
tree | 33868ad39addb26e9bd120bfe1c925121a892b01 | |
parent | b1129db4784956a69535c2a9849ef5be80b972a1 (diff) | |
download | eclipse.platform.debug-6856eb8f9fea18057ccb49306160f6ecf563d429.tar.gz eclipse.platform.debug-6856eb8f9fea18057ccb49306160f6ecf563d429.tar.xz eclipse.platform.debug-6856eb8f9fea18057ccb49306160f6ecf563d429.zip |
Bug 212316 - Allow multiple debuggers to create breakpoints using the same editor.
25 files changed, 1946 insertions, 104 deletions
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/IConfigurationElementConstants.java b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/IConfigurationElementConstants.java index 60a026590..b96e96dee 100644 --- a/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/IConfigurationElementConstants.java +++ b/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/IConfigurationElementConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2007 IBM Corporation and others. + * Copyright (c) 2006, 2008 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 @@ -317,4 +317,22 @@ public interface IConfigurationElementConstants { * <p>Equal to the word: <code>memento</code></p> */ public static final String MEMENTO = "memento"; //$NON-NLS-1$ + + /** + * The selection node name for a configuration element. + * <p>Equal to the word: <code>selection</code></p> + */ + public static final String SELECTION = "selection"; //$NON-NLS-1$ + + /** + * The debugContext node name for a configuration element. + * <p>Equal to the word: <code>debugContext</code></p> + */ + public static final String DEBUG_CONTEXT = "debugContext"; //$NON-NLS-1$ + + /** + * The editorInput node name for a configuration element. + * <p>Equal to the word: <code>editorInput</code></p> + */ + public static final String EDITOR_INPUT = "editorInput"; //$NON-NLS-1$ } diff --git a/org.eclipse.debug.examples.core/META-INF/MANIFEST.MF b/org.eclipse.debug.examples.core/META-INF/MANIFEST.MF index 543fdb418..03f4944c1 100644 --- a/org.eclipse.debug.examples.core/META-INF/MANIFEST.MF +++ b/org.eclipse.debug.examples.core/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Example Debug Core Plug-in Bundle-SymbolicName: org.eclipse.debug.examples.core;singleton:=true -Bundle-Version: 1.0.0 +Bundle-Version: 1.1.0 Bundle-Activator: org.eclipse.debug.examples.core.pda.DebugCorePlugin Require-Bundle: org.eclipse.core.runtime, org.eclipse.core.resources, diff --git a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java index c57a9d24a..b0ddd6433 100644 --- a/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java +++ b/org.eclipse.debug.examples.core/src/org/eclipse/debug/examples/core/pda/model/PDAVariable.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2008 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 @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Wind River Systems - added support for IToggleBreakpointsTargetFactory *******************************************************************************/ package org.eclipse.debug.examples.core.pda.model; @@ -100,7 +101,7 @@ public class PDAVariable extends PDADebugElement implements IVariable { * * @return the stack frame owning this variable */ - protected PDAStackFrame getStackFrame() { + public PDAStackFrame getStackFrame() { return fFrame; } diff --git a/org.eclipse.debug.examples.ui/META-INF/MANIFEST.MF b/org.eclipse.debug.examples.ui/META-INF/MANIFEST.MF index 68b76cbea..2770fb9da 100644 --- a/org.eclipse.debug.examples.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.debug.examples.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Example Debug UI Plug-in Bundle-SymbolicName: org.eclipse.debug.examples.ui;singleton:=true -Bundle-Version: 1.0.0 +Bundle-Version: 1.1.0 Bundle-Activator: org.eclipse.debug.examples.ui.pda.DebugUIPlugin Require-Bundle: org.eclipse.core.runtime, org.eclipse.core.resources, diff --git a/org.eclipse.debug.examples.ui/plugin.xml b/org.eclipse.debug.examples.ui/plugin.xml index 524c4ffa6..a755e78b2 100644 --- a/org.eclipse.debug.examples.ui/plugin.xml +++ b/org.eclipse.debug.examples.ui/plugin.xml @@ -284,4 +284,35 @@ </enablement> </detailFactories> </extension> + <extension point="org.eclipse.debug.ui.toggleBreakpointsTargetFactories"> + <toggleTargetFactory + id="org.eclipse.debug.examples.ui.pda.ToggleWatchpointsTargetFactory" + class="org.eclipse.debug.examples.ui.pda.breakpoints.PDAToggleWatchpointsTargetFactory"> + <enablement> + <!-- Test the active debug context. Enable only if the context is a PDA + element , or if there is no debug context (with a debug model) selected. --> + <with variable="debugContext"> + <iterate> + <or> + <test property="org.eclipse.debug.ui.getModelIdentifier" value="pda.debugModel"/> + <test property="org.eclipse.debug.ui.getModelIdentifier" value=""/> + </or> + </iterate> + </with> + <!-- If the debug context matches or if there is no active debug + context. Enable the breakpoint toggle for PDA's editor --> + <or> + <instanceof value="org.eclipse.debug.examples.ui.pda.editor.PDAEditor"/> + <with variable="selection"> + <count value="1"/> + <iterate> + <or> + <instanceof value="org.eclipse.debug.examples.core.pda.model.PDAVariable"/> + </or> + </iterate> + </with> + </or> + </enablement> + </toggleTargetFactory> + </extension> </plugin> diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDABreakpointAdapter.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDABreakpointAdapter.java index 38e8f8525..0f2639f7c 100644 --- a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDABreakpointAdapter.java +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDABreakpointAdapter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2007 IBM Corporation and others. + * Copyright (c) 2005, 2008 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 @@ -8,6 +8,7 @@ * Contributors: * IBM Corporation - initial API and implementation * Bjorn Freeman-Benson - initial API and implementation + * Wind River Systems - added support for IToggleBreakpointsTargetFactory *******************************************************************************/ package org.eclipse.debug.examples.ui.pda.breakpoints; @@ -110,23 +111,7 @@ public class PDABreakpointAdapter implements IToggleBreakpointsTargetExtension { IResource resource = (IResource) editorPart.getEditorInput().getAdapter(IResource.class); String var = variableAndFunctionName[0]; String fcn = variableAndFunctionName[1]; - // look for existing watchpoint to delete - IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(DebugCorePlugin.ID_PDA_DEBUG_MODEL); - for (int i = 0; i < breakpoints.length; i++) { - IBreakpoint breakpoint = breakpoints[i]; - if (breakpoint instanceof PDAWatchpoint && resource.equals(breakpoint.getMarker().getResource())) { - PDAWatchpoint watchpoint = (PDAWatchpoint)breakpoint; - String otherVar = watchpoint.getVariableName(); - String otherFcn = watchpoint.getFunctionName(); - if (otherVar.equals(var) && otherFcn.equals(fcn)) { - breakpoint.delete(); - return; - } - } - } - // create watchpoint - PDAWatchpoint watchpoint = new PDAWatchpoint(resource, lineNumber + 1, fcn, var, true, true); - DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(watchpoint); + toggleWatchpoint(resource, lineNumber, fcn, var, true, true); } } /* (non-Javadoc) @@ -136,6 +121,28 @@ public class PDABreakpointAdapter implements IToggleBreakpointsTargetExtension { return getVariableAndFunctionName(part, selection) != null; } + protected void toggleWatchpoint(IResource resource, int lineNumber, String fcn, String var, boolean access, + boolean modification) throws CoreException + { + // look for existing watchpoint to delete + IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(DebugCorePlugin.ID_PDA_DEBUG_MODEL); + for (int i = 0; i < breakpoints.length; i++) { + IBreakpoint breakpoint = breakpoints[i]; + if (breakpoint instanceof PDAWatchpoint && resource.equals(breakpoint.getMarker().getResource())) { + PDAWatchpoint watchpoint = (PDAWatchpoint)breakpoint; + String otherVar = watchpoint.getVariableName(); + String otherFcn = watchpoint.getFunctionName(); + if (otherVar.equals(var) && otherFcn.equals(fcn)) { + breakpoint.delete(); + return; + } + } + } + // create watchpoint + PDAWatchpoint watchpoint = new PDAWatchpoint(resource, lineNumber + 1, fcn, var, access, modification); + DebugPlugin.getDefault().getBreakpointManager().addBreakpoint(watchpoint); + } + /** * Returns the variable and function names at the current line, or <code>null</code> if none. * @@ -144,7 +151,7 @@ public class PDABreakpointAdapter implements IToggleBreakpointsTargetExtension { * @return the variable and function names at the current line, or <code>null</code> if none. * The array has two elements, the first is the variable name, the second is the function name. */ - private String[] getVariableAndFunctionName(IWorkbenchPart part, ISelection selection) { + protected String[] getVariableAndFunctionName(IWorkbenchPart part, ISelection selection) { ITextEditor editor = getEditor(part); if (editor != null && selection instanceof ITextSelection) { ITextSelection textSelection = (ITextSelection) selection; diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDAToggleWatchpointsTarget.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDAToggleWatchpointsTarget.java new file mode 100644 index 000000000..4c51afeb9 --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDAToggleWatchpointsTarget.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2008 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.ui.pda.breakpoints; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +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.core.runtime.jobs.Job; +import org.eclipse.debug.core.model.ISourceLocator; +import org.eclipse.debug.examples.core.pda.model.PDAStackFrame; +import org.eclipse.debug.examples.core.pda.model.PDAVariable; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.text.ITextSelection; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.progress.WorkbenchJob; +import org.eclipse.ui.texteditor.ITextEditor; + + +/** + * Adapter to create specialized watchpoints in PDA files and the variables views. + */ +public class PDAToggleWatchpointsTarget extends PDABreakpointAdapter { + + final private boolean fAccessModeEnabled; + final private boolean fModificationModeEnabled; + + PDAToggleWatchpointsTarget(boolean access, boolean modification) { + fAccessModeEnabled = access; + fModificationModeEnabled = modification; + } + + public boolean canToggleWatchpoints(IWorkbenchPart part, ISelection selection) { + if (super.canToggleWatchpoints(part, selection)) { + return true; + } else { + if (selection instanceof IStructuredSelection) { + IStructuredSelection ss = (IStructuredSelection)selection; + return ss.getFirstElement() instanceof PDAVariable; + } + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTarget#toggleWatchpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public void toggleWatchpoints(IWorkbenchPart part, ISelection selection) throws CoreException { + String[] variableAndFunctionName = getVariableAndFunctionName(part, selection); + + if (variableAndFunctionName != null && part instanceof ITextEditor && selection instanceof ITextSelection) { + // Selection inside text editor. Create a watchpoint based on + // current source line. + ITextEditor editorPart = (ITextEditor)part; + int lineNumber = ((ITextSelection)selection).getStartLine(); + IResource resource = (IResource) editorPart.getEditorInput().getAdapter(IResource.class); + String var = variableAndFunctionName[0]; + String fcn = variableAndFunctionName[1]; + toggleWatchpoint(resource, lineNumber, fcn, var, fAccessModeEnabled, fModificationModeEnabled); + } else if (selection instanceof IStructuredSelection && + ((IStructuredSelection)selection).getFirstElement() instanceof PDAVariable ) + { + // Selection is inside a variables view. Create a watchpoint + // using information from the variable. Retrieving information + // from the model requires performing source lookup which should be + // done on a background thread. + final PDAVariable var = (PDAVariable)((IStructuredSelection)selection).getFirstElement(); + final PDAStackFrame frame = var.getStackFrame(); + final Shell shell = part.getSite().getShell(); + + new Job("Toggle PDA Watchpoint") { + { setSystem(true); } + + protected IStatus run(IProgressMonitor monitor) { + try { + IFile file = getResource(var.getStackFrame()); + String varName = var.getName(); + int line = findLine(file, varName); + toggleWatchpoint(file, line, frame.getName(), varName, + fAccessModeEnabled, fModificationModeEnabled); + } catch (final CoreException e) { + // Need to switch back to the UI thread to show the error + // dialog. + new WorkbenchJob(shell.getDisplay(), "Toggle PDA Watchpoint") { + { setSystem(true); } + + public IStatus runInUIThread(IProgressMonitor monitor) { + ErrorDialog.openError(shell, "Failed to create PDA watchpoint", "Failed to create PDA watchpoint.\n", e.getStatus()); + return Status.OK_STATUS; + } + }.schedule(); + } + return Status.OK_STATUS; + } + }.schedule(); + } + } + + private IFile getResource(PDAStackFrame frame) { + ISourceLocator locator = frame.getLaunch().getSourceLocator(); + Object sourceElement = locator.getSourceElement(frame); + if (sourceElement instanceof IFile) { + return (IFile)sourceElement; + } + return null; + } + + private int findLine(IFile file, String var) throws CoreException { + BufferedReader reader = new BufferedReader(new InputStreamReader(file.getContents())); + + int lineNum = 0; + try { + while(true) { + String line = reader.readLine().trim(); + if (line.startsWith("var")) { + String varName = line.substring("var".length()).trim(); + if (varName.equals(var)) { + break; + } + } + lineNum++; + } + } catch (IOException e) { + // end of file reached and line wasn't found + return -1; + } finally { + try { + reader.close(); + } catch (IOException e) {} + } + return lineNum; + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension#toggleBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public void toggleBreakpoints(IWorkbenchPart part, ISelection selection) throws CoreException { + if (canToggleWatchpoints(part, selection)) { + toggleWatchpoints(part, selection); + } else { + toggleLineBreakpoints(part, selection); + } + } + + /* (non-Javadoc) + * @see org.eclipse.debug.ui.actions.IToggleBreakpointsTargetExtension#canToggleBreakpoints(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) + */ + public boolean canToggleBreakpoints(IWorkbenchPart part, ISelection selection) { + return canToggleLineBreakpoints(part, selection) || canToggleWatchpoints(part, selection); + } +} diff --git a/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDAToggleWatchpointsTargetFactory.java b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDAToggleWatchpointsTargetFactory.java new file mode 100644 index 000000000..9c9ebd9cc --- /dev/null +++ b/org.eclipse.debug.examples.ui/src/org/eclipse/debug/examples/ui/pda/breakpoints/PDAToggleWatchpointsTargetFactory.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.examples.ui.pda.breakpoints; + +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget; +import org.eclipse.debug.ui.actions.IToggleBreakpointsTargetFactory; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchPart; + +/** + * Toggle breakpoints target factory for creating PDA watchpoints. It allows the + * user the select the type of watchpoint that will be created when the watchpoint + * is toggles inside the editor or variables view. + */ +public class PDAToggleWatchpointsTargetFactory implements IToggleBreakpointsTargetFactory { + + private static final String TOGGLE_WATCHPOINT_TARGET_ACCESS = "org.eclipse.debug.examples.ui.pda.watchpoint_access"; + private static final String TOGGLE_WATCHPOINT_TARGET_MODIFICATION = "org.eclipse.debug.examples.ui.pda.watchpoint_modification"; + private static final String TOGGLE_WATCHPOINT_TARGET_BOTH = "org.eclipse.debug.examples.ui.pda.watchpoint_both"; + + private static Set TOGGLE_WATCHPOINTS_TARGETS = new LinkedHashSet(); + + private Map fToggleWatchpointTargets = new HashMap(3); + + static { + TOGGLE_WATCHPOINTS_TARGETS.add(TOGGLE_WATCHPOINT_TARGET_BOTH); + TOGGLE_WATCHPOINTS_TARGETS.add(TOGGLE_WATCHPOINT_TARGET_ACCESS); + TOGGLE_WATCHPOINTS_TARGETS.add(TOGGLE_WATCHPOINT_TARGET_MODIFICATION); + } + + public IToggleBreakpointsTarget createToggleTarget(String targetID) { + IToggleBreakpointsTarget target = (IToggleBreakpointsTarget)fToggleWatchpointTargets.get(targetID); + if (target == null) { + if (TOGGLE_WATCHPOINT_TARGET_BOTH.equals(targetID)) { + target = new PDAToggleWatchpointsTarget(true, true); + } else if (TOGGLE_WATCHPOINT_TARGET_ACCESS.equals(targetID)) { + target = new PDAToggleWatchpointsTarget(true, false); + } else if (TOGGLE_WATCHPOINT_TARGET_MODIFICATION.equals(targetID)) { + target = new PDAToggleWatchpointsTarget(false, true); + } else { + return null; + } + fToggleWatchpointTargets.put(targetID, target); + } + return target; + } + + public String getDefaultToggleTarget(IWorkbenchPart part, ISelection selection) { + return TOGGLE_WATCHPOINT_TARGET_BOTH; + } + + public Set getToggleTargets(IWorkbenchPart part, ISelection selection) { + return TOGGLE_WATCHPOINTS_TARGETS; + } + + public String getToggleTargetName(String targetID) { + if (TOGGLE_WATCHPOINT_TARGET_BOTH.equals(targetID)) { + return "Watchpoints (Read/Write)"; + } else if (TOGGLE_WATCHPOINT_TARGET_ACCESS.equals(targetID)) { + return "Watchpoints (Read)"; + } else if (TOGGLE_WATCHPOINT_TARGET_MODIFICATION.equals(targetID)) { + return "Watchpoints (Write)"; + } else { + return null; + } + } + + public String getToggleTargetDescription(String targetID) { + return getToggleTargetName(targetID); + } +} diff --git a/org.eclipse.debug.ui/plugin.properties b/org.eclipse.debug.ui/plugin.properties index dafef2663..6d942ed89 100644 --- a/org.eclipse.debug.ui/plugin.properties +++ b/org.eclipse.debug.ui/plugin.properties @@ -129,9 +129,11 @@ StringVariablePresentationsName=String Variable Presentations SuspendAction.label=&Suspend TerminateAction.label=&Terminate ToggleBreakpointAction.label=Toggle Brea&kpoint +ToggleBreakpointsTargetFactoriesExtension.name=Toggle Breakpoints Target Factories ToggleLineBreakpointAction.label=Toggle &Line Breakpoint ToggleMethodBreakpointAction.label=Toggle &Method Breakpoint ToggleWatchpointAction.label=Toggle &Watchpoint +BreakpointTypesMenu.label=B&reakpoint Types VariablesView.name=Variables VariableTextFontDefinition.label=Variable text font VariableTextFontDefinition.description=Font to use for the label text of entries in the Variables, Registers and Expression views as well as the Inspect Popup Dialog. diff --git a/org.eclipse.debug.ui/plugin.xml b/org.eclipse.debug.ui/plugin.xml index a747053db..733cc1460 100644 --- a/org.eclipse.debug.ui/plugin.xml +++ b/org.eclipse.debug.ui/plugin.xml @@ -20,6 +20,7 @@ <extension-point id="variableValueEditors" name="%VariableValueEditorsName" schema="schema/variableValueEditors.exsd"/> <extension-point id="launchConfigurationTabs" name="%LaunchConfigurationTabsExtension.name" schema="schema/launchConfigurationTabs.exsd"/> <extension-point id="detailPaneFactories" name="%DetailPaneFactoriesExtension.name" schema="schema/detailPaneFactories.exsd"/> + <extension-point id="toggleBreakpointsTargetFactories" name="%ToggleBreakpointsTargetFactoriesExtension.name" schema="schema/toggleBreakpointsTargetFactories.exsd"/> <!-- Extensions --> <extension @@ -540,6 +541,72 @@ </action> </actionSet> </extension> + + <!-- Command framework contribution for the main menu --> + <extension + point="org.eclipse.ui.menus"> + <menuContribution + locationURI="menu:org.eclipse.ui.main.menu?after=additions"> + <!-- Need to re-create the menu structure in the command framework + so that contributed commands will be placed correctly in menus --> + <menu + id="org.eclipse.ui.run" + label="%RunMenu.label"> + <separator name="stepGroup" visible="true"/> + <separator name="stepIntoGroup"/> + <separator name="stepOverGroup"/> + <separator name="stepReturnGroup"/> + <separator name="emptyStepGroup"/> + <separator name="relaunchGroup" visible="true"/> + <separator name="profileGroup" visible="true"/> + <separator name="runGroup" visible="true"/> + <separator name="debugGroup" visible="true"/> + <separator name="emptyLaunchGroup" visible="true"/> + <separator name="breakpointGroup" visible="true"/> + <separator name="lineBreakpointGroup"/> + <separator name="emptyBreakpointGroup"/> + </menu> + </menuContribution> + <menuContribution + locationURI="menu:org.eclipse.ui.run?after=breakpointGroup"> + <menu + id="breakpointTypes" + label="%BreakpointTypesMenu.label"> + <visibleWhen checkEnabled="false"> + <and> + <with variable="org.eclipse.core.runtime.Platform"> + <test property="org.eclipse.core.runtime.bundleState" + args="org.eclipse.debug.ui" + value="ACTIVE"/> + </with> + <with variable="activeContexts"> + <iterate operator="or"> + <equals value="org.eclipse.debug.ui.breakpointActionSet"/> + </iterate> + </with> + <systemTest + property="org.eclipse.debug.ui.breakpoints.toggleFactoriesUsed" + value="true"> + </systemTest> + </and> + </visibleWhen> + <dynamic + id="org.eclipse.debug.ui.actions.BreakpointTypesContribution" + class="org.eclipse.debug.internal.ui.actions.breakpoints.BreakpointTypesContribution"> + </dynamic> + </menu> + </menuContribution> + </extension> + + <extension point="org.eclipse.core.expressions.propertyTesters"> + <propertyTester + class="org.eclipse.debug.internal.ui.actions.breakpoints.BreakpointTypesPropertyTester" + id="org.eclipse.debug.ui.breakpointTypesProperties" + namespace="org.eclipse.debug.ui" + properties="getAvailableBreakpointType,areBreakpointTypesAvailable" + type="org.eclipse.core.runtime.IAdaptable"/> + </extension> + <extension point="org.eclipse.ui.viewActions"> <viewContribution diff --git a/org.eclipse.debug.ui/schema/toggleBreakpointsTargetFactories.exsd b/org.eclipse.debug.ui/schema/toggleBreakpointsTargetFactories.exsd new file mode 100644 index 000000000..66dfe261e --- /dev/null +++ b/org.eclipse.debug.ui/schema/toggleBreakpointsTargetFactories.exsd @@ -0,0 +1,163 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="org.eclipse.cdt.debug.ui" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appinfo> + <meta.schema plugin="org.eclipse.cdt.debug.ui" id="toggleBreakpointsTargetFactories" name="toggleBreakpointsTargetFactories"/> + </appinfo> + <documentation> + This extension point provides a mechanism for contributing breakpoint toggle action targets which can be registered for specific editors, debug models, or files. + </documentation> + </annotation> + + <include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/> + + <element name="extension"> + <annotation> + <appinfo> + <meta.element /> + </appinfo> + </annotation> + <complexType> + <sequence> + <element ref="toggleTargetFactory" minOccurs="1" maxOccurs="unbounded"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appinfo> + <meta.attribute translatable="true"/> + </appinfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="toggleTargetFactory"> + <annotation> + <documentation> + Element declaring a toggle breakpoints target factory. This element can optionally contain an enablement element which determines when this factory is going to be applicable. The evaluation context for the enablement expression includes: +(default variable) - the active workbench part of type IWorkbenchPart +"debugContext" - currently active debug context selection, of type List +"editorInput" - the editor input to the editor if the currently active part is an editor, of type IEditorInput +"selection" - the current selection in the active part, of type List + </documentation> + </annotation> + <complexType> + <sequence> + <element ref="enablement" minOccurs="0" maxOccurs="1"/> + </sequence> + <attribute name="id" type="string" use="required"> + <annotation> + <documentation> + Specifies a unique identifier for this breakpoint toggle target. + </documentation> + </annotation> + </attribute> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + Class implementing the IToggleBreakpointsTargetFactory interface. + </documentation> + <appinfo> + <meta.attribute kind="java" basedOn=":org.eclipse.debug.ui.actions.IToggleBreakpointsTargetFactory"/> + </appinfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appinfo> + <meta.section type="since"/> + </appinfo> + <documentation> + 3.5 + </documentation> + </annotation> + + <annotation> + <appinfo> + <meta.section type="examples"/> + </appinfo> + <documentation> + The following is an example of a breakpoint toggle target factory extension. + +<p> +<pre> + <extension point="org.eclipse.debug.ui.toggleBreakpointsTargetFactories"> + <toggleTargetFactory + id="com.example.ExampleBreakpointToggleTargetFactory" + class="com.example.BreakpointToggleTargetFactory"> + <enablement> + <!-- Test the active debug context. Enable only if the active context + is an element from "Example" debugger, or if there is no debug context + associated with the context element. Also enable if debug context is + empty --> + <with variable="debugContext"> + <iterate> + <or> + <test property="org.eclipse.debug.ui.getModelIdentifier" value="com.example.model"/> + <test property="org.eclipse.debug.ui.getModelIdentifier" value=""/> + </or> + </iterate> + </with> + <!-- If the debug context matches of if there isno active debug context. + Enable the breakpoint toggle for the "Example" editors --> + <instanceof value="com.example.Editor"/> + </enablement> + </toggleTargetFactory> + </extension> +</pre> +</p> + </documentation> + </annotation> + + <annotation> + <appinfo> + <meta.section type="apiInfo"/> + </appinfo> + <documentation> + Value of the attribute <b>class</b> must be a fully qualified name of a Java class that implements the interface <b>org.eclipse.debug.ui.actions.IToggleBreakpointsTargetFactory</b>. + </documentation> + </annotation> + + <annotation> + <appinfo> + <meta.section type="implementation"/> + </appinfo> + <documentation> + [Enter information about supplied implementation of this extension point.] + </documentation> + </annotation> + + <annotation> + <appinfo> + <meta.section type="copyright"/> + </appinfo> + <documentation> + Copyright (c) 2007 Wind River Systems and others.<br> +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 +<a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a> + </documentation> + </annotation> + +</schema> diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.java index 4eebb9e28..e1bcf099a 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.java @@ -215,4 +215,7 @@ public class ActionMessages extends NLS { public static String VirtualFindAction_0; public static String VirtualFindAction_1; + + public static String ToggleBreakpointsTargetManager_defaultToggleTarget_name; + public static String ToggleBreakpointsTargetManager_defaultToggleTarget_description; }
\ No newline at end of file diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.properties b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.properties index 53b28e508..9bc187757 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.properties +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ActionMessages.properties @@ -201,3 +201,6 @@ RunLastAction_3=Run the previously launched application OpenLaunchDialogAction_1={0} Configurations... VirtualFindAction_0=Error VirtualFindAction_1=Unable to locate {0} in viewer + +ToggleBreakpointsTargetManager_defaultToggleTarget_name = Default +ToggleBreakpointsTargetManager_defaultToggleTarget_description = Default
\ No newline at end of file diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/IToggleBreakpointsTargetManagerListener.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/IToggleBreakpointsTargetManagerListener.java new file mode 100644 index 000000000..ba0ca5f40 --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/IToggleBreakpointsTargetManagerListener.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.internal.ui.actions; + +/** + * Listener for changes in the preferred toggle targets in the toggle + * breakpoints target manager. This interface allows toggle breakpoint + * actions to update their enablement when the user changes the preferred + * toggle target settings. + * + * @see ToggleBreakpointsTargetManager + * @see IToggleBreakpointsTargetFactory + * @since 3.5 + */ +public interface IToggleBreakpointsTargetManagerListener { + + /** + * Called when the preferred toggle targets have changed. + */ + public void preferredTargetsChanged(); +} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/RetargetAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/RetargetAction.java index 089429d61..de147275b 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/RetargetAction.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/RetargetAction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 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 @@ -7,6 +7,7 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Wind River Systems - added support for IToggleBreakpointsTargetFactory *******************************************************************************/ package org.eclipse.debug.internal.ui.actions; @@ -60,7 +61,7 @@ public abstract class RetargetAction implements IWorkbenchWindowActionDelegate, * * @return the selection in the active part, possibly empty */ - private ISelection getTargetSelection() { + protected ISelection getTargetSelection() { if (fActivePart != null) { ISelectionProvider selectionProvider = fActivePart.getSite().getSelectionProvider(); if (selectionProvider != null) { @@ -70,6 +71,10 @@ public abstract class RetargetAction implements IWorkbenchWindowActionDelegate, return EMPTY_SELECTION; } + protected IWorkbenchPart getActivePart() { + return fActivePart; + } + /* (non-Javadoc) * @see org.eclipse.ui.IWorkbenchWindowActionDelegate#dispose() */ diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ToggleBreakpointsTargetManager.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ToggleBreakpointsTargetManager.java new file mode 100644 index 000000000..17884832f --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/ToggleBreakpointsTargetManager.java @@ -0,0 +1,717 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems 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 + * Wind River Systems - adapted to use with IToggleBreakpiontsTargetFactory extension + *******************************************************************************/ +package org.eclipse.debug.internal.ui.actions; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.Map.Entry; + +import org.eclipse.core.expressions.EvaluationContext; +import org.eclipse.core.expressions.EvaluationResult; +import org.eclipse.core.expressions.Expression; +import org.eclipse.core.expressions.ExpressionConverter; +import org.eclipse.core.expressions.ExpressionTagNames; +import org.eclipse.core.expressions.IEvaluationContext; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IAdapterManager; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExtensionPoint; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.internal.core.IConfigurationElementConstants; +import org.eclipse.debug.internal.ui.DebugUIPlugin; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget; +import org.eclipse.debug.ui.actions.IToggleBreakpointsTargetFactory; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.IWorkbenchPart; + +/** + * Organizes the toggle breakpoints target factories contributed through the + * extension point and keeps track of the toggle breakpoints target that + * the factories produce. The manager is accessed as a singleton through + * the <code>getDefault()</code> method. + * <p> + * The adapter mechanism for obtaining a toggle breakpoints target is + * still supported through a specialized toggle target factory. Targets + * contributed through this mechanism are labeled as "Default" in the UI. + * </p> + * + * @see IToggleBreakpointsTargetFactory + * @see IToggleBreakpointsTarget + * @see IToggleBreakpointsTargetExtension + * @since 3.5 + */ +public class ToggleBreakpointsTargetManager { + + /** + * Toggle breakpoints target ID which refers to a target contributed + * through the legacy adapter mechanism. + */ + public static String DEFAULT_TOGGLE_TARGET_ID = "default"; //$NON-NLS-1$ + + private static Set DEFAULT_TOGGLE_TARGET_ID_SET = new HashSet(); + static { + DEFAULT_TOGGLE_TARGET_ID_SET.add(DEFAULT_TOGGLE_TARGET_ID); + } + + /** + * Acts as a proxy between the toggle breakpoints target manager and the factories + * contributed to the extension point. Only loads information from the plug-in xml + * and only instantiates the specified factory if required (lazy loading). + */ + private static class ToggleTargetFactory implements IToggleBreakpointsTargetFactory { + + private IConfigurationElement fConfigElement; + private IToggleBreakpointsTargetFactory fFactory; + private Expression fEnablementExpression; + + public ToggleTargetFactory(IConfigurationElement configElement){ + fConfigElement = configElement; + } + + /** + * Returns the instantiated factory specified by the class property. + */ + private IToggleBreakpointsTargetFactory getFactory() { + if (fFactory != null) return fFactory; + try{ + Object obj = fConfigElement.createExecutableExtension(IConfigurationElementConstants.CLASS); + if(obj instanceof IToggleBreakpointsTargetFactory) { + fFactory = (IToggleBreakpointsTargetFactory)obj; + } else { + throw new CoreException(new Status(IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(), IDebugUIConstants.INTERNAL_ERROR, "org.eclipse.debug.ui.toggleBreakpointsTargetFactories extension failed to load breakpoint toggle target because the specified class does not implement org.eclipse.debug.ui.actions.IToggleBreakpointsTargetFactory. Class specified was: " + obj, null)); //$NON-NLS-1$ + } + } catch (CoreException e){ + DebugUIPlugin.log(e.getStatus()); + fFactory = null; + } + return fFactory; + } + + /** + * Checks if the enablement expression for the factory evaluates to true for the + * given part and selection. + */ + public boolean isEnabled(IWorkbenchPart part, ISelection selection) { + boolean enabled = false; + Expression expression = getEnablementExpression(); + if (expression != null) { + enabled = evalEnablementExpression(part, selection, expression); + } else { + enabled = true; + } + return enabled; + } + + /** + * Returns the active debug context given the active part. It is used + * in creating the evaluation context for the factories' enablement expression. + * @param part active part + * @return current active debug context + */ + private IStructuredSelection getDebugContext(IWorkbenchPart part) { + ISelection selection = DebugUITools.getDebugContextManager(). + getContextService(part.getSite().getWorkbenchWindow()).getActiveContext(); + if (selection instanceof IStructuredSelection) { + return (IStructuredSelection)selection; + } + return StructuredSelection.EMPTY; + } + + /** + * Evaluate the given expression within the given context and return + * the result. Returns <code>true</code> iff result is either TRUE. + * + * @param exp the enablement expression to evaluate or <code>null</code> + * @param context the context of the evaluation. Usually, the + * user's selection. + * @return the result of evaluating the expression + */ + private boolean evalEnablementExpression(IWorkbenchPart part, ISelection selection, Expression exp) { + if (exp != null){ + IEvaluationContext context = new EvaluationContext(null, part); + + List debugContextList = getDebugContext(part).toList(); + context.addVariable(IConfigurationElementConstants.DEBUG_CONTEXT, debugContextList); + + if (selection instanceof IStructuredSelection) { + List selectionList = ((IStructuredSelection)selection).toList(); + context.addVariable(IConfigurationElementConstants.SELECTION, selectionList); + } + + if (part instanceof IEditorPart) { + context.addVariable(IConfigurationElementConstants.EDITOR_INPUT, ((IEditorPart)part).getEditorInput()); + } + + try{ + EvaluationResult result = exp.evaluate(context); + if (result == EvaluationResult.TRUE){ + return true; + } + } catch (CoreException e){ + // Evaluation failed + } + } + return false; + } + + /** + * Returns an expression that represents the enablement logic for the + * breakpiont toggle target. + */ + private Expression getEnablementExpression(){ + if (fEnablementExpression == null) { + try{ + IConfigurationElement[] elements = fConfigElement.getChildren(ExpressionTagNames.ENABLEMENT); + IConfigurationElement enablement = elements.length > 0 ? elements[0] : null; + if (enablement != null) { + fEnablementExpression = ExpressionConverter.getDefault().perform(enablement); + } + } catch (CoreException e){ + DebugUIPlugin.log(e.getStatus()); + fEnablementExpression = null; + } + } + return fEnablementExpression; + } + + /** + * Instantiates the factory and asks it to produce the IToggleBreakpointsTarget + * for the given ID + */ + public IToggleBreakpointsTarget createToggleTarget(String targetID) { + IToggleBreakpointsTargetFactory factory = getFactory(); + if (factory != null) { + return factory.createToggleTarget(targetID); + } + return null; + } + + /** + * Instantiates the factory and asks it for the set of toggle target + * IDs that the factory can produce for the given part and selection. + */ + public Set getToggleTargets(IWorkbenchPart part, ISelection selection) { + IToggleBreakpointsTargetFactory factory = getFactory(); + if (factory != null) { + return factory.getToggleTargets(part, selection); + } + return Collections.EMPTY_SET; + } + + /** + * Instantiates the factory and asks it to produce the name of the toggle target + * for the given ID. + */ + public String getToggleTargetName(String targetID) { + IToggleBreakpointsTargetFactory factory = getFactory(); + if (factory != null) { + return factory.getToggleTargetName(targetID); + } + return null; + } + + /** + * Instantiates the factory and asks it to produce the description of the toggle + * target for the given ID. + */ + public String getToggleTargetDescription(String targetID) { + IToggleBreakpointsTargetFactory factory = getFactory(); + if (factory != null) { + return factory.getToggleTargetDescription(targetID); + } + return null; + } + + /** + * Instantiates the factory and asks it for the toggle tareget ID that + * the factory considers the default for the given part and selection. + */ + public String getDefaultToggleTarget(IWorkbenchPart part, ISelection selection) { + IToggleBreakpointsTargetFactory factory = getFactory(); + if (factory != null) { + return factory.getDefaultToggleTarget(part, selection); + } + return null; + } + } + + + /** + * Factory for toggle breakpoints targets contributed through the + * adapter mechanism. + */ + private static class ToggleBreakpointsTargetAdapterFactory implements IToggleBreakpointsTargetFactory { + + private IAdaptable getAdaptable(IWorkbenchPart part, ISelection selection) { + IAdaptable adaptable = null; + if (selection instanceof IStructuredSelection) { + IStructuredSelection ss = (IStructuredSelection)selection; + if (ss.getFirstElement() instanceof IAdaptable) { + adaptable = (IAdaptable) ss.getFirstElement(); + } + } else { + adaptable = part; + } + return adaptable; + } + + private boolean canGetToggleBreakpointsTarget(IAdaptable adaptable) { + if (adaptable != null) { + IToggleBreakpointsTarget adapter = (IToggleBreakpointsTarget) + adaptable.getAdapter(IToggleBreakpointsTarget.class); + if (adapter == null) { + IAdapterManager adapterManager = Platform.getAdapterManager(); + if (adapterManager.hasAdapter(adaptable, IToggleBreakpointsTarget.class.getName())) { + return true; + } + } else { + return true; + } + } + return false; + } + + /** + * Finds the toggle breakpoints target for the active part and selection. + * It first looks for the target using the factories registered using an + * extension point. If not found it uses the <code>IAdaptable</code> + * mechanism. + * @param part active part + * @param selection active selection in part + * @return The toggle breakpoints target, or <code>null</code> if not found. + */ + private IToggleBreakpointsTarget getToggleBreakpointsTarget(IAdaptable adaptable) { + if (adaptable != null) { + IToggleBreakpointsTarget adapter = (IToggleBreakpointsTarget) + adaptable.getAdapter(IToggleBreakpointsTarget.class); + if (adapter == null) { + // attempt to force load adapter + IAdapterManager adapterManager = Platform.getAdapterManager(); + if (adapterManager.hasAdapter(adaptable, IToggleBreakpointsTarget.class.getName())) { + adapter = (IToggleBreakpointsTarget) + adapterManager.loadAdapter(adaptable, IToggleBreakpointsTarget.class.getName()); + } + } + return adapter; + } + return null; + } + + /** + * Checks if there is an adaptable object for the given part and + * selection, and if there is, it checks whether an + * <code>IToggleBreakpointsTarget</code> can be obtained as an adapter. + */ + public boolean isEnabled(IWorkbenchPart part, ISelection selection) { + IAdaptable adaptable = getAdaptable(part, selection); + return adaptable != null && canGetToggleBreakpointsTarget(adaptable); + } + + /** + * Not implemented use {@link #createDefaultToggleTarget(IWorkbenchPart, ISelection)} + * instead. + */ + public IToggleBreakpointsTarget createToggleTarget(String targetID) { + return null; + } + + /** + * Returns a toggle target for the given part and selection, obtained + * through the adapter mechanism. + */ + public IToggleBreakpointsTarget createDefaultToggleTarget(IWorkbenchPart part, ISelection selection) { + IAdaptable adaptable = getAdaptable(part, selection); + return getToggleBreakpointsTarget(adaptable); + } + + public Set getToggleTargets(IWorkbenchPart part, ISelection selection) { + IAdaptable adaptable = getAdaptable(part, selection); + if (canGetToggleBreakpointsTarget(adaptable)) { + return DEFAULT_TOGGLE_TARGET_ID_SET; + } + return Collections.EMPTY_SET; + } + + public String getToggleTargetName(String targetID) { + return ActionMessages.ToggleBreakpointsTargetManager_defaultToggleTarget_name; + } + + public String getToggleTargetDescription(String targetID) { + return ActionMessages.ToggleBreakpointsTargetManager_defaultToggleTarget_description; + } + + public String getDefaultToggleTarget(IWorkbenchPart part, ISelection selection) { + return DEFAULT_TOGGLE_TARGET_ID; + } + } + + + /** + * Preference key for storing the preferred targets map. + * @see {@link #storePreferredTargets()} + * @see {@link #loadPreferredTargets()} + */ + public static final String PREF_TARGETS = "preferredTargets"; //$NON-NLS-1$ + + + /** + * There should only ever be once instance of this manager for the workbench. + */ + private static ToggleBreakpointsTargetManager fgSingleton; + + public static ToggleBreakpointsTargetManager getDefault(){ + if (fgSingleton == null) fgSingleton = new ToggleBreakpointsTargetManager(); + return fgSingleton; + } + + /** + * Maps the IDs of toggle breakpoint targets to their instances. The target + * IDs must be unique. + */ + private Map fKnownFactories; + + /** + * Maps a Set of target id's to the one target id that is preferred. + */ + private Map fPreferredTargets; + + /** + * Maps the IDs of toggle targets to the factory that can create them. + * There can currently only be one factory for a given toggle target. + */ + private Map fFactoriesByTargetID = new HashMap(); + + /** + * List of listeners to changes in the preferred toggle targets list. + */ + private ListenerList fChangedListners = new ListenerList(); + + /** + * Initializes the collection of known factories from extension point contributions. + */ + private void initializeFactories() { + fKnownFactories = new LinkedHashMap(); + fKnownFactories.put(DEFAULT_TOGGLE_TARGET_ID, new ToggleBreakpointsTargetAdapterFactory()); + IExtensionPoint ep = Platform.getExtensionRegistry().getExtensionPoint(DebugUIPlugin.getUniqueIdentifier(), IDebugUIConstants.EXTENSION_POINT_TOGGLE_BREAKPOINTS_TARGET_FACTORIES); + IConfigurationElement[] elements = ep.getConfigurationElements(); + for (int i= 0; i < elements.length; i++) { + String id = elements[i].getAttribute(IConfigurationElementConstants.ID); + if (id != null && id.length() != 0) { + if (fKnownFactories.containsKey(id)) { + DebugUIPlugin.log(new Status(IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(), IDebugUIConstants.INTERNAL_ERROR, "org.eclipse.debug.ui.toggleBreakpointsTargetFactory extension failed to load breakpoint toggle target because the specified id is already registered. Specified ID is: " + id, null)); //$NON-NLS-1$ + } else { + fKnownFactories.put(id, new ToggleTargetFactory(elements[i])); + } + } else { + DebugUIPlugin.log(new Status(IStatus.ERROR, DebugUIPlugin.getUniqueIdentifier(), IDebugUIConstants.INTERNAL_ERROR, "org.eclipse.debug.ui.toggleBreakpointsTargetFactory extension failed to load breakpoint toggle target because the specified id is empty.", null)); //$NON-NLS-1$ + } + } + + // If there are any factories contributed through the extension point, + // set a system property for use in enabling actions. + System.setProperty(IDebugUIConstants.SYS_PROP_BREAKPOINT_TOGGLE_FACTORIES_USED, + fKnownFactories.size() > 1 ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Returns the set of IToggleBreakpointsTargetFactory objects (they will be + * ToggleTargetFactory) that were contributed to the extension point and + * are enabled for the given part and selection (enabled if the factory + * does not have an enablement expression or if the enablement expression + * evaluates to true). + * + * @param part active part + * @param selection active selection in part + * @return The factories enabled for the part and selection or an empty + * collection. + */ + private Set getEnabledFactories(IWorkbenchPart part, ISelection selection) { + if (fKnownFactories == null) initializeFactories(); + + Set set = new LinkedHashSet(); + for (Iterator itr = fKnownFactories.keySet().iterator(); itr.hasNext(); ) { + String id = (String)itr.next(); + IToggleBreakpointsTargetFactory factory = (IToggleBreakpointsTargetFactory)fKnownFactories.get(id); + if (factory instanceof ToggleTargetFactory && + ((ToggleTargetFactory)factory).isEnabled(part, selection)) { + set.add(factory); + } else if (factory instanceof ToggleBreakpointsTargetAdapterFactory && + ((ToggleBreakpointsTargetAdapterFactory)factory).isEnabled(part, selection)) { + set.add(factory); + } + } + return set; + } + + /** + * Produces the set of IDs for all possible toggle targets that can be used for + * the given part and selection. + * + * @param factoriesToQuery The collection of factories to check + * @param part active part + * @param selection active selection in part + * @return Set of toggle target IDs or an empty set + */ + private Set getEnabledTargetIDs(Collection factoriesToQuery, IWorkbenchPart part, ISelection selection){ + Set idsForSelection = new LinkedHashSet(); + Iterator factoriesItr = factoriesToQuery.iterator(); + while (factoriesItr.hasNext()) { + IToggleBreakpointsTargetFactory factory = (IToggleBreakpointsTargetFactory) factoriesItr.next(); + Iterator targetIDsItr = factory.getToggleTargets(part, selection).iterator(); + while (targetIDsItr.hasNext()) { + String targetID = (String) targetIDsItr.next(); + fFactoriesByTargetID.put(targetID, factory); + idsForSelection.add(targetID); + } + } + return idsForSelection; + } + + /** + * Returns the set of <code>String</code> IDs of toggle breakpoint targets, + * which are enabled for the given active part and selection. The IDs can be used + * to create the {@link IToggleBreakpointsTarget} instance. + * @param part active part + * @param selection active selection in part + * @return Set of toggle target IDs or an empty set + */ + public Set getEnabledToggleBreakpointsTargetIDs(IWorkbenchPart part, ISelection selection) { + return getEnabledTargetIDs(getEnabledFactories(part, selection), part, selection); + } + + /** + * Returns the ID of the calculated preferred toggle breakpoints target for the + * given active part and selection. The returned ID is chosen based on factory + * enablement, whether the target is a default one, and on user choice. + * @param part active part + * @param selection active selection in part + * @return The toggle target IDs or null if none. + */ + public String getPreferredToggleBreakpointsTargetID(IWorkbenchPart part, ISelection selection) { + Set factories = getEnabledFactories(part, selection); + Set possibleIDs = getEnabledTargetIDs(factories, part, selection); + return chooseToggleTargetIDInSet(possibleIDs, factories, part, selection); + } + + /** + * Given the ID of toggle breakpoint target, this method will try to find the factory + * that creates it and return an instance of it. + * + * @param ID The ID of the requested toggle breakpoint target. + * @return The instantiated target or null + */ + public IToggleBreakpointsTarget getToggleBreakpointsTarget(IWorkbenchPart part, ISelection selection) { + String id = getPreferredToggleBreakpointsTargetID(part, selection); + IToggleBreakpointsTargetFactory factory = (IToggleBreakpointsTargetFactory)fFactoriesByTargetID.get(id); + if (factory != null) { + if (DEFAULT_TOGGLE_TARGET_ID.equals(id)) { + return ((ToggleBreakpointsTargetAdapterFactory)factory).createDefaultToggleTarget(part, selection); + } else { + return factory.createToggleTarget(id); + } + } + return null; + } + + /** + * Given the ID of a toggle breakpoints target, this method will try + * to find the factory that creates it and ask it for the name of it. + * + * @param ID The ID of the requested toggle breakpoint target. + * @return The name of the target. + */ + public String getToggleBreakpointsTargetName(String id) { + IToggleBreakpointsTargetFactory factory = (IToggleBreakpointsTargetFactory)fFactoriesByTargetID.get(id); + if (factory != null) { + return factory.getToggleTargetName(id); + } + return null; + } + + /** + * Given the ID of a toggle breakpoints target, this method will try + * to find the factory that creates it and ask it for the description of it. + * + * @param ID The ID of the requested toggle breakpoint target. + * @return The description of the target or null. + */ + public String getToggleBreakpointsTargetDescription(String id) { + IToggleBreakpointsTargetFactory factory = (IToggleBreakpointsTargetFactory)fFactoriesByTargetID.get(id); + if (factory != null) { + return factory.getToggleTargetDescription(id); + } + return null; + } + + /** + * Adds the given listener to the list of listeners notified when the preferred + * toggle breakpoints targets change. + * @param listener The listener to add. + */ + public void addChangedListener(IToggleBreakpointsTargetManagerListener listener) { + fChangedListners.add(listener); + } + + /** + * Removes the given listener from the list of listeners notified when the preferred + * toggle breakpoints targets change. + * @param listener The listener to add. + */ + public void removeChangedListener(IToggleBreakpointsTargetManagerListener listener) { + fChangedListners.remove(listener); + } + + /** + * Stores the map of preferred target IDs to the preference store in the format: + * + * Key1A,Key1B:Value1|Key2A,Key2B,Key2C:Value2| + * + * Where the sub keys (Key1A, Key1B, etc.) are the elements of the set used at the + * key in the mapping and the values are the associated String value in the mapping. + */ + private void storePreferredTargets() { + StringBuffer buffer= new StringBuffer(); + Iterator iter = fPreferredTargets.entrySet().iterator(); + while (iter.hasNext()) { + Entry entry = (Entry) iter.next(); + Iterator setIter = ((Set)entry.getKey()).iterator(); + while (setIter.hasNext()) { + String currentID = (String) setIter.next(); + buffer.append(currentID); + buffer.append(','); + } + buffer.deleteCharAt(buffer.length()-1); + buffer.append(':'); + buffer.append(entry.getValue()); + buffer.append('|'); + } + DebugUIPlugin.getDefault().getPluginPreferences().setValue(PREF_TARGETS, buffer.toString()); + } + + /** + * Loads the map of preferred target IDs from the preference store. + * + * @see #storePreferredTargets() + */ + private void loadPreferredTargets() { + fPreferredTargets = new HashMap(); + String preferenceValue = DebugUIPlugin.getDefault().getPluginPreferences().getString(PREF_TARGETS); + StringTokenizer entryTokenizer = new StringTokenizer(preferenceValue,"|"); //$NON-NLS-1$ + while (entryTokenizer.hasMoreTokens()){ + String token = entryTokenizer.nextToken(); + int valueStart = token.indexOf(':'); + StringTokenizer keyTokenizer = new StringTokenizer(token.substring(0,valueStart),","); //$NON-NLS-1$ + Set keys = new LinkedHashSet(); + while (keyTokenizer.hasMoreTokens()){ + keys.add(keyTokenizer.nextToken()); + } + fPreferredTargets.put(keys, token.substring(valueStart+1)); + } + } + + /** + * Adds or updates the mapping to set which target ID is preferred for a certain + * set of possible IDs. + * + * @param possibleIDs The set of possible IDs + * @param preferredID The preferred ID in the set. + */ + public void setPreferredTarget(Set possibleIDs, String preferredID) { + if (possibleIDs == null) return; + + if (fKnownFactories == null) initializeFactories(); + + if (fPreferredTargets == null){ + loadPreferredTargets(); + } + String currentKey = (String)fPreferredTargets.get(possibleIDs); + if (currentKey == null || !currentKey.equals(preferredID)){ + fPreferredTargets.put(possibleIDs, preferredID); + storePreferredTargets(); + firePreferredTargetsChanged(); + } + } + + /** + * Returns the preferred pane ID from the given set if the mapping has been set. + * + * @param possibleDetailsAreaIDs Set of possible pane IDs + * @return The preferred ID or null + */ + private String getUserPreferredTarget(Set possibleTargetIDs){ + if (fPreferredTargets == null){ + loadPreferredTargets(); + } + return (String)fPreferredTargets.get(possibleTargetIDs); + } + + /** + * Given a set of possible detail pane IDs, this method will determine which pane is + * preferred and should be used to display the selection. This method chooses a pane + * by storing previous choices and can be set using a context menu. + * + * @param possiblePaneIDs The set of possible detail pane IDs + * @return The preferred detail pane ID or null + */ + private String chooseToggleTargetIDInSet(Set possibleTargetIDs, Collection enabledFactories, IWorkbenchPart part, ISelection selection){ + if (possibleTargetIDs == null || possibleTargetIDs.isEmpty()){ + return null; + } + + String preferredID = getUserPreferredTarget(possibleTargetIDs); + + if (preferredID == null){ + // If there is no preferred pane already set, check the factories to see there is a default target + Iterator factoryIterator = enabledFactories.iterator(); + while (preferredID == null && factoryIterator.hasNext()) { + IToggleBreakpointsTargetFactory currentFactory = (IToggleBreakpointsTargetFactory) factoryIterator.next(); + preferredID = currentFactory.getDefaultToggleTarget(part, selection); + } + // If the factories don't have a default, just pick the first one. + if (preferredID == null) { + preferredID= (String)possibleTargetIDs.iterator().next(); + } + setPreferredTarget(possibleTargetIDs, preferredID); + } + + return preferredID; + } + + /** + * Notifies the change listeners that the preferred targets changed. + */ + private void firePreferredTargetsChanged() { + Object[] listeners = fChangedListners.getListeners(); + for (int i = 0; i < listeners.length; i++) { + ((IToggleBreakpointsTargetManagerListener)listeners[i]).preferredTargetsChanged(); + } + } + +} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/BreakpointTypesContribution.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/BreakpointTypesContribution.java new file mode 100644 index 000000000..4fa2d566a --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/BreakpointTypesContribution.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems 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: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.debug.internal.ui.actions.breakpoints; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.eclipse.debug.internal.ui.actions.ToggleBreakpointsTargetManager; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.ActionContributionItem; +import org.eclipse.jface.action.ContributionItem; +import org.eclipse.jface.action.IContributionItem; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.ui.IPartService; +import org.eclipse.ui.ISelectionService; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.actions.CompoundContributionItem; +import org.eclipse.ui.menus.IWorkbenchContribution; +import org.eclipse.ui.services.IServiceLocator; + +/** + * Dynamic menu contribution that shows available breakpoint types from + * toggleBreakpointsTargetFactories extension point. + * + * @since 3.5 + */ +public class BreakpointTypesContribution extends CompoundContributionItem implements IWorkbenchContribution { + + private class SelectTargetAction extends Action { + private final Set fPossibleIDs; + private final String fID; + SelectTargetAction(String name, Set possibleIDs, String ID) { + super(name, AS_RADIO_BUTTON); + fID = ID; + fPossibleIDs = possibleIDs; + } + + public void run() { + if (isChecked()) { + ToggleBreakpointsTargetManager.getDefault().setPreferredTarget(fPossibleIDs, fID); + } + } + } + + private IServiceLocator fServiceLocator; + + private static IContributionItem[] NO_BREAKPOINT_TYPES_CONTRIBUTION_ITEMS = new IContributionItem[] { + new ContributionItem() { + public void fill(Menu menu, int index) { + MenuItem item = new MenuItem(menu, SWT.NONE); + item.setEnabled(false); + item.setText(Messages.BreakpointTypesContribution_0); + } + + public boolean isEnabled() { + return false; + } + } + }; + + protected IContributionItem[] getContributionItems() { + IWorkbenchPart part = null; + ISelection selection = null; + + ISelectionService selectionService = + (ISelectionService)fServiceLocator.getService(ISelectionService.class); + if (selectionService != null) { + selection = selectionService.getSelection(); + } + IPartService partService = (IPartService)fServiceLocator.getService(IPartService.class); + if (partService != null) { + part = partService.getActivePart(); + } + + // If no part or selection, disable all. + if (part == null || selection == null) { + return NO_BREAKPOINT_TYPES_CONTRIBUTION_ITEMS; + } + + // Get breakpoint toggle target IDs. + ToggleBreakpointsTargetManager manager = ToggleBreakpointsTargetManager.getDefault(); + Set enabledIDs = manager.getEnabledToggleBreakpointsTargetIDs(part, selection); + String preferredId = manager.getPreferredToggleBreakpointsTargetID(part, selection); + + List actions = new ArrayList(enabledIDs.size()); + for (Iterator i = enabledIDs.iterator(); i.hasNext();) { + String id = (String) i.next(); + Action action = new SelectTargetAction(manager.getToggleBreakpointsTargetName(id), enabledIDs, id); + if (id.equals(preferredId)) { + action.setChecked(true); + } + actions.add(action); + } + + if ( enabledIDs.isEmpty() ) { + return NO_BREAKPOINT_TYPES_CONTRIBUTION_ITEMS; + } + + IContributionItem[] items = new IContributionItem[enabledIDs.size()]; + for (int i = 0; i < actions.size(); i++) { + items[i] = new ActionContributionItem((Action) actions.get(i)); + } + return items; + } + + public void initialize(IServiceLocator serviceLocator) { + fServiceLocator = serviceLocator; + } + +} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/Messages.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/Messages.java index ca6845893..3a6ed12df 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/Messages.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/Messages.java @@ -21,6 +21,8 @@ public class Messages extends NLS { public static String RetargetToggleBreakpointAction_0; public static String RetargetToggleLineBreakpointAction_0; public static String RetargetWatchpointAction_0; + public static String BreakpointTypesContribution_0; + public static String BreakpointTypesContribution_noBreakpointsActive_menuItem; static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, Messages.class); diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/Messages.properties b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/Messages.properties index 4d58ef129..0f9ace8ea 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/Messages.properties +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/Messages.properties @@ -12,3 +12,5 @@ RetargetMethodBreakpointAction_0=The operation is unavailable on the current sel RetargetToggleBreakpointAction_0=The operation is unavailable on the current selection. Please place the cursor in a valid location for a breakpoint. RetargetWatchpointAction_0=The operation is unavailable on the current selection. Please select or place the cursor on a field. RetargetToggleLineBreakpointAction_0=The operation is unavailable on the current selection. Please place the cursor on a valid line. +BreakpointTypesContribution_0=None Available +BreakpointTypesContribution_noBreakpointsActive_menuItem=No active breakpoints
\ No newline at end of file diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/RetargetBreakpointAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/RetargetBreakpointAction.java index ff7c2b530..ec5506511 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/RetargetBreakpointAction.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/RetargetBreakpointAction.java @@ -7,11 +7,20 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Wind River Systems - added support for IToggleBreakpointsTargetFactory *******************************************************************************/ package org.eclipse.debug.internal.ui.actions.breakpoints; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.debug.internal.ui.actions.IToggleBreakpointsTargetManagerListener; import org.eclipse.debug.internal.ui.actions.RetargetAction; +import org.eclipse.debug.internal.ui.actions.ToggleBreakpointsTargetManager; import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; /** @@ -19,12 +28,55 @@ import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget; * * @since 3.0 */ -public abstract class RetargetBreakpointAction extends RetargetAction { +public abstract class RetargetBreakpointAction extends RetargetAction implements IToggleBreakpointsTargetManagerListener { + private IAction fAction; + /* (non-Javadoc) * @see org.eclipse.debug.internal.ui.actions.RetargetAction#getAdapterClass() */ protected Class getAdapterClass() { return IToggleBreakpointsTarget.class; } + + protected Object getAdapter(IAdaptable adaptable) { + ToggleBreakpointsTargetManager manager = ToggleBreakpointsTargetManager.getDefault(); + return manager.getToggleBreakpointsTarget(getActivePart(), getTargetSelection()); + } + + public void init(IWorkbenchWindow window) { + super.init(window); + ToggleBreakpointsTargetManager.getDefault().addChangedListener(this); + } + + public void init(IAction action) { + super.init(action); + ToggleBreakpointsTargetManager.getDefault().addChangedListener(this); + } + + public void dispose() { + ToggleBreakpointsTargetManager.getDefault().removeChangedListener(this); + super.dispose(); + } + + public void selectionChanged(IAction action, ISelection selection) { + fAction = action; + super.selectionChanged(action, selection); + } + + public void preferredTargetsChanged() { + if (fAction != null) { + IWorkbenchPart activePart = getActivePart(); + if (activePart != null) { + ISelectionProvider provider = activePart.getSite().getSelectionProvider(); + if (provider != null) { + ISelection selection = provider.getSelection(); + // Force the toggle target to be refreshed. + super.clearPart(activePart); + super.partActivated(activePart); + super.selectionChanged(fAction, selection); + } + } + } + } } diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/ToggleBreakpointObjectActionDelegate.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/ToggleBreakpointObjectActionDelegate.java index 2b37e86ab..80b6533d6 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/ToggleBreakpointObjectActionDelegate.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/actions/breakpoints/ToggleBreakpointObjectActionDelegate.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2008 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 @@ -7,14 +7,13 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Wind River Systems - added support for IToggleBreakpointsTargetFactory *******************************************************************************/ package org.eclipse.debug.internal.ui.actions.breakpoints; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.core.runtime.IAdapterManager; -import org.eclipse.core.runtime.Platform; import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.internal.ui.actions.ToggleBreakpointsTargetManager; import org.eclipse.debug.ui.actions.IToggleBreakpointsTarget; import org.eclipse.jface.action.IAction; import org.eclipse.jface.viewers.ISelection; @@ -47,12 +46,8 @@ public abstract class ToggleBreakpointObjectActionDelegate implements IObjectAct * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction) */ public void run(IAction action) { - IAdaptable adaptable = (IAdaptable) fSelection.getFirstElement(); - IToggleBreakpointsTarget target = (IToggleBreakpointsTarget) adaptable.getAdapter(IToggleBreakpointsTarget.class); - if (target == null) { - IAdapterManager adapterManager = Platform.getAdapterManager(); - target = (IToggleBreakpointsTarget) adapterManager.loadAdapter(adaptable, IToggleBreakpointsTarget.class.getName()); - } + IToggleBreakpointsTarget target = + ToggleBreakpointsTargetManager.getDefault().getToggleBreakpointsTarget(fPart, fSelection); if (target != null) { try { performAction(target, fPart, fSelection); @@ -61,7 +56,7 @@ public abstract class ToggleBreakpointObjectActionDelegate implements IObjectAct } } } - + /** * Performs the operation specific to this action. * @@ -80,19 +75,9 @@ public abstract class ToggleBreakpointObjectActionDelegate implements IObjectAct if (selection instanceof IStructuredSelection) { IStructuredSelection ss = (IStructuredSelection) selection; this.fSelection = ss; - if (!ss.isEmpty()) { - Object object = ss.getFirstElement(); - if (object instanceof IAdaptable) { - IAdaptable adaptable = (IAdaptable) object; - IToggleBreakpointsTarget target = (IToggleBreakpointsTarget) adaptable.getAdapter(IToggleBreakpointsTarget.class); - if (target == null) { - IAdapterManager adapterManager = Platform.getAdapterManager(); - enabled = adapterManager.hasAdapter(adaptable, IToggleBreakpointsTarget.class.getName()); - } else { - enabled = true; - } - } - } + IToggleBreakpointsTarget target = + ToggleBreakpointsTargetManager.getDefault().getToggleBreakpointsTarget(fPart, fSelection); + enabled = target != null; } action.setEnabled(enabled); } diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/IDebugUIConstants.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/IDebugUIConstants.java index ccbe733c3..0e713f810 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/IDebugUIConstants.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/IDebugUIConstants.java @@ -1062,7 +1062,15 @@ public interface IDebugUIConstants { * @since 3.3 */ public static final String EXTENSION_POINT_DETAIL_FACTORIES = "detailPaneFactories"; //$NON-NLS-1$ - + + /** + * Simple identifier constant (value <code>"toggleBreakpointsTargetFactories"</code>) for the + * toggle breakpoint targets extension point. + * + * @since 3.5 + */ + public static final String EXTENSION_POINT_TOGGLE_BREAKPOINTS_TARGET_FACTORIES = "toggleBreakpointsTargetFactories"; //$NON-NLS-1$ + /** * Update policies extension point identifier (value * <code>"updatePolicies"</code> @@ -1197,4 +1205,13 @@ public interface IDebugUIConstants { * @since 3.2 */ public static final String IMG_OBJS_INSTRUCTION_POINTER = "IMG_OBJS_INSTRUCTION_POINTER"; //$NON-NLS-1$ + + /** + * A key for a system property that indicates whether there are toggle + * breakpoint factories registered in this installation. This can be used + * to trigger the UI to include menus related to breakpoint types. + * + * @since 3.5 + */ + public static final String SYS_PROP_BREAKPOINT_TOGGLE_FACTORIES_USED = "org.eclipse.debug.ui.breakpoints.toggleFactoriesUsed"; //$NON-NLS-1$ } diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/IToggleBreakpointsTargetFactory.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/IToggleBreakpointsTargetFactory.java new file mode 100644 index 000000000..29dcecabb --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/IToggleBreakpointsTargetFactory.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems 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 + * Wind River Systems - adapted to use with IToggleBreakpiontsTargetFactory extension + *******************************************************************************/ +package org.eclipse.debug.ui.actions; + +import java.util.Set; + +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchPart; + +/** + * A toggle breakpoints target factory creates one or more toggle breakpoint + * targets. The toggle breakpoints targets are used by toggle breakpoint actions + * to create breakpoints appropriate for the active editor, debug session, project, + * or selection. + * + * <p> + * Toggle breakpoints target factories are contributed via the + * <code>org.eclipse.debug.ui.toggleBreakpointsTargetFactories</code> + * extension point. Following is an example of a detail pane factory extension: + * <pre> + * <extension point="org.eclipse.debug.ui.toggleBreakpointsTargetFactories"> + * <toggleTargetFactory + * id="com.example.ExampleBreakpointToggleTargetFactory" + * class="com.example.BreakpointToggleTargetFactory"> + * <enablement> + * <!-- Test the active debug context. Enable only if the active context + * is an element from "Example" debugger, or if there is no debug context + * associated with the context element. Also enable if debug context is + * empty --> + * <with variable="debugContext"> + * <iterate> + * <or> + * <test property="org.eclipse.debug.ui.getModelIdentifier" value="com.example.model"/> + * <test property="org.eclipse.debug.ui.getModelIdentifier" value=""/> + * </or> + * </iterate> + * </with> + * <!-- If there is no active debug context. Enable the breakpoint toggle for + * the "Example" editors --> + * <instanceof value="com.example.Editor"/> + * </enablement> + * </toggleTargetFactory> + * </extension> + * </pre> + * </p> + * <p> + * <p> + * Clients contributing a toggle breakpoints target factory are intended to + * implement this interface. + * + * @see IToggleBreakpointsTarget + * @see IToggleBreakpointsTargetExtension + * @see ToggleBreakpointsTargetManager + * @since 3.5 + */ +public interface IToggleBreakpointsTargetFactory { + /** + * Returns all possible types of toggle breakpoints targets that this + * factory can create for the given selection and part, possibly empty. + * Toggle breakpoints targets are returned as a set of IDs. + * + * @param part The active part. + * @param selection The current selection + * @return Set of <code>String</code> IDs for possible toggle breakpoint + * targets, possibly empty + */ + public Set getToggleTargets(IWorkbenchPart part, ISelection selection); + + /** + * Returns the identifier of the default toggle breakpoints target to use + * for the given selection, or <code>null</code> if this factory has no + * preference. + * + * @param part The active part. + * @param selection The current selection + * @return a breakpoint toggle target identifier or <code>null</code> + */ + public String getDefaultToggleTarget(IWorkbenchPart part, ISelection selection); + + /** + * Creates and returns a toggle breakpoint target corresponding to the + * given identifier that this factory can produce (according to + * {@link #getToggleTargets}). + * + * @param targetID The id of the toggle target to be created + * @return toggle target or <code>null</code> if one could not be created + */ + public IToggleBreakpointsTarget createToggleTarget(String targetID); + + /** + * Returns a human readable name for the breakpoint toggle target associated with the + * given ID. Used to populate the context menu with meaningful names of the types of + * breakpoints created by the given target. + * + * @param targetID toggle breakpoints target identifier + * @return toggle target name + */ + public String getToggleTargetName(String targetID); + + /** + * Returns a description for the breakpoint toggle target associated with the + * given ID or <code>null</code> if none. + * + * @param targetID toggle breakpoints target identifier + * @return toggle target name or <code>null</code> if none + */ + public String getToggleTargetDescription(String targetID); + +} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/RulerBreakpointTypesActionDelegate.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/RulerBreakpointTypesActionDelegate.java new file mode 100644 index 000000000..7acd41ae9 --- /dev/null +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/RulerBreakpointTypesActionDelegate.java @@ -0,0 +1,243 @@ +/******************************************************************************* + * Copyright (c) 2005, 2008 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 + * Wind River Systems - adapted action to use for breakpoint types +******************************************************************************/ +package org.eclipse.debug.ui.actions; + +import java.util.Iterator; +import java.util.Set; + +import org.eclipse.debug.internal.ui.actions.ToggleBreakpointsTargetManager; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.ActionContributionItem; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuCreator; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.TextSelection; +import org.eclipse.jface.text.source.IVerticalRulerInfo; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.swt.events.MenuAdapter; +import org.eclipse.swt.events.MenuEvent; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; +import org.eclipse.ui.IEditorActionDelegate; +import org.eclipse.ui.IEditorPart; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; +import org.eclipse.ui.texteditor.ITextEditorExtension; + +/** + * Breakpoint ruler pop-up action that creates a sub-menu to select the currently + * active breakpoint type. This action delegate can be contributed to an editor + * with the <code>editorActions</code> extension point. The breakpoint types are + * calculated based on the toggle breakpoint target factories contributed through + * the <code>toggleBreakpointsTargetFactories</code> extension point. + * <p> + * Following is example plug-in XML used to contribute this action to an editor's + * vertical ruler context menu. It uses the <code>popupMenus</code> extension + * point, by referencing the ruler's context menu identifier in the + * <code>targetID</code> attribute. + * <pre> + * <extension point="org.eclipse.ui.popupMenus"> + * <viewerContribution + * targetID="example.rulerContextMenuId" + * id="example.RulerPopupActions"> + * <action + * label="Toggle Breakpoint" + * class="org.eclipse.debug.ui.actions.RulerBreakpointTypesActionDelegate" + * menubarPath="additions" + * id="example.rulerContextMenu.breakpointTypesAction"> + * </action> + * </viewerContribution> + * </pre> + * </p> + * <p> + * Clients may refer to this class as an action delegate in plug-in XML. This class + * is not intended to be subclassed. + * </p> + * @see ToggleBreakpointsTargetManager + * @see IToggleBreakpointsTargetFactory + * @noextend This class is not intended to be subclassed by clients. + * @since 3.5 + * + */ +public class RulerBreakpointTypesActionDelegate implements IEditorActionDelegate, IMenuListener, IMenuCreator { + private ITextEditor fEditor = null; + private IAction fCallerAction = null; + private IVerticalRulerInfo fRulerInfo; + private ISelection fSelection; + + /** + * The menu created by this action + */ + private Menu fMenu; + + private class SelectTargetAction extends Action { + private final Set fPossibleIDs; + private final String fID; + SelectTargetAction(String name, Set possibleIDs, String ID) { + super(name, AS_RADIO_BUTTON); + fID = ID; + fPossibleIDs = possibleIDs; + } + + public void run() { + if (!isChecked()) { + ToggleBreakpointsTargetManager.getDefault().setPreferredTarget(fPossibleIDs, fID); + } + } + } + + + public void selectionChanged(IAction action, ISelection selection) { + // In the editor we're not using the selection. + } + + public void run(IAction action) { + // Do nothing, this is a pull-down menu. + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IEditorActionDelegate#setActiveEditor(org.eclipse.jface.action.IAction, org.eclipse.ui.IEditorPart) + */ + public void setActiveEditor(IAction callerAction, IEditorPart targetEditor) { + // Clean up old editor data. + if (fCallerAction != null) { + fCallerAction.setMenuCreator(null); + } + if (fEditor instanceof ITextEditorExtension) { + ((ITextEditorExtension) fEditor).removeRulerContextMenuListener(this); + } + fRulerInfo = null; + + // Set up new editor data. + fCallerAction = callerAction; + fCallerAction.setMenuCreator(this); + + fEditor= (ITextEditor)(targetEditor == null ? null : targetEditor.getAdapter(ITextEditor.class)); + + if (fEditor != null) { + if (fEditor instanceof ITextEditorExtension) { + ((ITextEditorExtension) fEditor).addRulerContextMenuListener(this); + } + + fRulerInfo= (IVerticalRulerInfo) fEditor.getAdapter(IVerticalRulerInfo.class); + } + + } + + public void dispose() { + if (fCallerAction != null) { + fCallerAction.setMenuCreator(null); + } + if (fEditor instanceof ITextEditorExtension) { + ((ITextEditorExtension) fEditor).removeRulerContextMenuListener(this); + } + fRulerInfo = null; + } + + public void menuAboutToShow(IMenuManager manager) { + fSelection = StructuredSelection.EMPTY; + if (fEditor != null && fRulerInfo != null) { + + IDocumentProvider provider = fEditor.getDocumentProvider(); + if (provider != null) { + IDocument document = provider.getDocument(fEditor.getEditorInput()); + int line = fRulerInfo.getLineOfLastMouseButtonActivity(); + if (line > -1) { + try { + IRegion region = document.getLineInformation(line); + fSelection = new TextSelection(document, region.getOffset(), 0); + } catch (BadLocationException e) {} + } + } + ToggleBreakpointsTargetManager toggleTargetManager = ToggleBreakpointsTargetManager.getDefault(); + Set enabledIDs = toggleTargetManager.getEnabledToggleBreakpointsTargetIDs(fEditor, fSelection); + fCallerAction.setEnabled(enabledIDs.size() > 0); + } else { + fCallerAction.setEnabled(false); + } + + } + + /** + * Sets this action's drop-down menu, disposing the previous menu. + * + * @param menu the new menu + */ + private void setMenu(Menu menu) { + if (fMenu != null) { + fMenu.dispose(); + } + fMenu = menu; + } + + public Menu getMenu(Menu parent) { + setMenu(new Menu(parent)); + fillMenu(fMenu); + initMenu(); + return fMenu; + } + + public Menu getMenu(Control parent) { + setMenu(new Menu(parent)); + fillMenu(fMenu); + initMenu(); + return fMenu; + } + + /** + * Fills the drop-down menu with enabled toggle breakpoint targets + * + * @param menu the menu to fill + */ + private void fillMenu(Menu menu) { + ToggleBreakpointsTargetManager manager = ToggleBreakpointsTargetManager.getDefault(); + Set enabledIDs = manager.getEnabledToggleBreakpointsTargetIDs(fEditor, fSelection); + String preferredId = manager.getPreferredToggleBreakpointsTargetID(fEditor, fSelection); + + for (Iterator itr = enabledIDs.iterator(); itr.hasNext();) { + String id = (String)itr.next(); + SelectTargetAction action= new SelectTargetAction(manager.getToggleBreakpointsTargetName(id), enabledIDs, id); + + if (id.equals(preferredId)){ + action.setChecked(true); + } + + ActionContributionItem item= new ActionContributionItem(action); + item.fill(menu, -1); + } + } + + /** + * Creates the menu for the action + */ + private void initMenu() { + // Add listener to re-populate the menu each time + // it is shown because of dynamic history list + fMenu.addMenuListener(new MenuAdapter() { + public void menuShown(MenuEvent e) { + Menu m = (Menu)e.widget; + MenuItem[] items = m.getItems(); + for (int i=0; i < items.length; i++) { + items[i].dispose(); + } + fillMenu(m); + } + }); + } + +} diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/ToggleBreakpointAction.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/ToggleBreakpointAction.java index 5d84476a1..33c5a97f8 100644 --- a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/ToggleBreakpointAction.java +++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/actions/ToggleBreakpointAction.java @@ -7,14 +7,15 @@ * * Contributors: * IBM Corporation - initial API and implementation + * Wind River Systems - added support for IToggleBreakpointsTargetFactory *******************************************************************************/ package org.eclipse.debug.ui.actions; import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IAdapterManager; -import org.eclipse.core.runtime.Platform; import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.internal.ui.actions.ActionMessages; +import org.eclipse.debug.internal.ui.actions.IToggleBreakpointsTargetManagerListener; +import org.eclipse.debug.internal.ui.actions.ToggleBreakpointsTargetManager; import org.eclipse.jface.action.Action; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; @@ -46,6 +47,11 @@ public class ToggleBreakpointAction extends Action implements IUpdate { private IWorkbenchPart fPart; private IDocument fDocument; private IVerticalRulerInfo fRulerInfo; + private IToggleBreakpointsTargetManagerListener fListener = new IToggleBreakpointsTargetManagerListener() { + public void preferredTargetsChanged() { + update(); + } + }; /** * Constructs a new action to toggle a breakpoint in the given @@ -63,6 +69,7 @@ public class ToggleBreakpointAction extends Action implements IUpdate { fPart = part; fDocument = document; fRulerInfo = rulerInfo; + ToggleBreakpointsTargetManager.getDefault().addChangedListener(fListener); } /* * (non-Javadoc) @@ -73,17 +80,7 @@ public class ToggleBreakpointAction extends Action implements IUpdate { if (document == null) { return; } - IToggleBreakpointsTarget adapter = (IToggleBreakpointsTarget) fPart.getAdapter(IToggleBreakpointsTarget.class); - if (adapter == null) { - // attempt to force load adapter - IAdapterManager manager = Platform.getAdapterManager(); - if (manager.hasAdapter(fPart, IToggleBreakpointsTarget.class.getName())) { - adapter = (IToggleBreakpointsTarget) manager.loadAdapter(fPart, IToggleBreakpointsTarget.class.getName()); - } - } - if (adapter == null) { - return; - } + int line = fRulerInfo.getLineOfLastMouseButtonActivity(); // Test if line is valid @@ -92,19 +89,25 @@ public class ToggleBreakpointAction extends Action implements IUpdate { try { ITextSelection selection = getTextSelection(document, line); - if (adapter instanceof IToggleBreakpointsTargetExtension) { - IToggleBreakpointsTargetExtension extension = (IToggleBreakpointsTargetExtension) adapter; + IToggleBreakpointsTarget toggleTarget = + ToggleBreakpointsTargetManager.getDefault().getToggleBreakpointsTarget(fPart, selection); + if (toggleTarget == null) { + return; + } + + if (toggleTarget instanceof IToggleBreakpointsTargetExtension) { + IToggleBreakpointsTargetExtension extension = (IToggleBreakpointsTargetExtension) toggleTarget; if (extension.canToggleBreakpoints(fPart, selection)) { extension.toggleBreakpoints(fPart, selection); return; } } - if (adapter.canToggleLineBreakpoints(fPart, selection)) { - adapter.toggleLineBreakpoints(fPart, selection); - } else if (adapter.canToggleWatchpoints(fPart, selection)) { - adapter.toggleWatchpoints(fPart, selection); - } else if (adapter.canToggleMethodBreakpoints(fPart, selection)) { - adapter.toggleMethodBreakpoints(fPart, selection); + if (toggleTarget.canToggleLineBreakpoints(fPart, selection)) { + toggleTarget.toggleLineBreakpoints(fPart, selection); + } else if (toggleTarget.canToggleWatchpoints(fPart, selection)) { + toggleTarget.toggleWatchpoints(fPart, selection); + } else if (toggleTarget.canToggleMethodBreakpoints(fPart, selection)) { + toggleTarget.toggleMethodBreakpoints(fPart, selection); } } catch (BadLocationException e) { reportException(e); @@ -130,6 +133,7 @@ public class ToggleBreakpointAction extends Action implements IUpdate { fDocument = null; fPart = null; fRulerInfo = null; + ToggleBreakpointsTargetManager.getDefault().removeChangedListener(fListener); } /** @@ -162,41 +166,39 @@ public class ToggleBreakpointAction extends Action implements IUpdate { public void update() { IDocument document= getDocument(); if (document != null) { - IToggleBreakpointsTarget adapter = (IToggleBreakpointsTarget) fPart.getAdapter(IToggleBreakpointsTarget.class); - if (adapter == null) { - // attempt to force load adapter - IAdapterManager manager = Platform.getAdapterManager(); - if (manager.hasAdapter(fPart, IToggleBreakpointsTarget.class.getName())) { - adapter = (IToggleBreakpointsTarget) manager.loadAdapter(fPart, IToggleBreakpointsTarget.class.getName()); - } - } - if (adapter != null) { - int line = fRulerInfo.getLineOfLastMouseButtonActivity(); - if (line > -1) { - try { - ITextSelection selection = getTextSelection(document, line); - if (adapter instanceof IToggleBreakpointsTargetExtension) { - IToggleBreakpointsTargetExtension extension = (IToggleBreakpointsTargetExtension) adapter; - if (extension.canToggleBreakpoints(fPart, selection)) { - setEnabled(true); - return; - } - } - if (adapter.canToggleLineBreakpoints(fPart, selection) | - adapter.canToggleWatchpoints(fPart, selection) | - adapter.canToggleMethodBreakpoints(fPart, selection)) { - setEnabled(true); - return; - } - } catch (BadLocationException e) { - reportException(e); - } - } + int line = fRulerInfo.getLineOfLastMouseButtonActivity(); + if (line > -1) { + try { + ITextSelection selection = getTextSelection(document, line); + + IToggleBreakpointsTarget adapter = + ToggleBreakpointsTargetManager.getDefault().getToggleBreakpointsTarget(fPart, selection); + if (adapter == null) { + setEnabled(false); + return; + } + if (adapter instanceof IToggleBreakpointsTargetExtension) { + IToggleBreakpointsTargetExtension extension = (IToggleBreakpointsTargetExtension) adapter; + if (extension.canToggleBreakpoints(fPart, selection)) { + setEnabled(true); + return; + } + } + if (adapter.canToggleLineBreakpoints(fPart, selection) | + adapter.canToggleWatchpoints(fPart, selection) | + adapter.canToggleMethodBreakpoints(fPart, selection)) + { + setEnabled(true); + return; + } + } catch (BadLocationException e) { + reportException(e); + } } } setEnabled(false); } - + /** * Determines the text selection for the breakpoint action. If clicking on the ruler inside * the highlighted text, return the text selection for the highlighted text. Otherwise, |