| /******************************************************************************* |
| * Copyright (c) 2000, 2012 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.debug.ui.propertypages; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IWorkspaceRunnable; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.debug.internal.ui.SWTFactory; |
| import org.eclipse.jdt.core.IMember; |
| import org.eclipse.jdt.debug.core.IJavaBreakpoint; |
| import org.eclipse.jdt.debug.core.IJavaLineBreakpoint; |
| import org.eclipse.jdt.debug.core.IJavaMethodBreakpoint; |
| import org.eclipse.jdt.debug.core.IJavaWatchpoint; |
| import org.eclipse.jdt.debug.ui.breakpoints.JavaBreakpointConditionEditor; |
| import org.eclipse.jdt.internal.debug.core.breakpoints.JavaClassPrepareBreakpoint; |
| import org.eclipse.jdt.internal.debug.core.breakpoints.JavaExceptionBreakpoint; |
| import org.eclipse.jdt.internal.debug.core.breakpoints.JavaLineBreakpoint; |
| import org.eclipse.jdt.internal.debug.core.breakpoints.JavaMethodBreakpoint; |
| import org.eclipse.jdt.internal.debug.core.breakpoints.JavaWatchpoint; |
| import org.eclipse.jdt.internal.debug.ui.BreakpointUtils; |
| import org.eclipse.jdt.internal.debug.ui.IJavaDebugHelpContextIds; |
| import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; |
| import org.eclipse.jdt.internal.debug.ui.breakpoints.AbstractJavaBreakpointEditor; |
| import org.eclipse.jdt.internal.debug.ui.breakpoints.CompositeBreakpointEditor; |
| import org.eclipse.jdt.internal.debug.ui.breakpoints.ExceptionBreakpointEditor; |
| import org.eclipse.jdt.internal.debug.ui.breakpoints.MethodBreakpointEditor; |
| import org.eclipse.jdt.internal.debug.ui.breakpoints.StandardJavaBreakpointEditor; |
| import org.eclipse.jdt.internal.debug.ui.breakpoints.WatchpointEditor; |
| import org.eclipse.jdt.ui.JavaElementLabelProvider; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.ShellEvent; |
| import org.eclipse.swt.events.ShellListener; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Text; |
| import org.eclipse.ui.IPropertyListener; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.dialogs.PropertyPage; |
| import org.eclipse.ui.model.IWorkbenchAdapter; |
| |
| /** |
| * Property page for configuring IJavaBreakpoints. |
| */ |
| public class JavaBreakpointPage extends PropertyPage { |
| |
| protected JavaElementLabelProvider fJavaLabelProvider= new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT); |
| protected Button fEnabledButton; |
| protected List<String> fErrorMessages= new ArrayList<String>(); |
| protected String fPrevMessage = null; |
| private AbstractJavaBreakpointEditor fEditor; |
| |
| /** |
| * Attribute used to indicate that a breakpoint should be deleted |
| * when cancel is pressed. |
| */ |
| public static final String ATTR_DELETE_ON_CANCEL = JDIDebugUIPlugin.getUniqueIdentifier() + ".ATTR_DELETE_ON_CANCEL"; //$NON-NLS-1$ |
| |
| /** |
| * Constant for the empty string |
| */ |
| protected static final String EMPTY_STRING = ""; //$NON-NLS-1$ |
| |
| /** |
| * Store the breakpoint properties. |
| * @see org.eclipse.jface.preference.IPreferencePage#performOk() |
| */ |
| @Override |
| public boolean performOk() { |
| IWorkspaceRunnable wr = new IWorkspaceRunnable() { |
| public void run(IProgressMonitor monitor) throws CoreException { |
| IJavaBreakpoint breakpoint = getBreakpoint(); |
| boolean delOnCancel = breakpoint.getMarker().getAttribute(ATTR_DELETE_ON_CANCEL) != null; |
| if (delOnCancel) { |
| // if this breakpoint is being created, remove the "delete on cancel" attribute |
| // and register with the breakpoint manager |
| breakpoint.getMarker().setAttribute(ATTR_DELETE_ON_CANCEL, (String)null); |
| breakpoint.setRegistered(true); |
| } |
| doStore(); |
| } |
| }; |
| try { |
| ResourcesPlugin.getWorkspace().run(wr, null, 0, null); |
| } |
| catch (CoreException e) { |
| JDIDebugUIPlugin.statusDialog(e.getStatus()); |
| JDIDebugUIPlugin.log(e); |
| } |
| return super.performOk(); |
| } |
| |
| /** |
| * Adds the given error message to the errors currently displayed on this page. |
| * The page displays the most recently added error message. |
| * Clients should retain messages that are passed into this method as the |
| * message should later be passed into removeErrorMessage(String) to clear the error. |
| * This method should be used instead of setErrorMessage(String). |
| * @param message the error message to display on this page. |
| */ |
| protected void addErrorMessage(String message) { |
| fErrorMessages.remove(message); |
| fErrorMessages.add(message); |
| setErrorMessage(message); |
| setValid(message == null); |
| } |
| |
| /** |
| * Removes the given error message from the errors currently displayed on this page. |
| * When an error message is removed, the page displays the error that was added |
| * before the given message. This is akin to popping the message from a stack. |
| * Clients should call this method instead of setErrorMessage(null). |
| * @param message the error message to clear |
| */ |
| protected void removeErrorMessage(String message) { |
| fErrorMessages.remove(message); |
| if (fErrorMessages.isEmpty()) { |
| addErrorMessage(null); |
| } else { |
| addErrorMessage(fErrorMessages.get(fErrorMessages.size() - 1)); |
| } |
| } |
| |
| /** |
| * Stores the values configured in this page. This method |
| * should be called from within a workspace runnable to |
| * reduce the number of resource deltas. |
| * @throws CoreException if an exception occurs |
| */ |
| protected void doStore() throws CoreException { |
| IJavaBreakpoint breakpoint = getBreakpoint(); |
| storeEnabled(breakpoint); |
| if (fEditor.isDirty()) { |
| fEditor.doSave(); |
| } |
| } |
| |
| /** |
| * Stores the value of the enabled state in the breakpoint. |
| * @param breakpoint the breakpoint to update |
| * @throws CoreException if an exception occurs while setting |
| * the enabled state |
| */ |
| private void storeEnabled(IJavaBreakpoint breakpoint) throws CoreException { |
| breakpoint.setEnabled(fEnabledButton.getSelection()); |
| } |
| |
| /** |
| * Creates the labels and editors displayed for the breakpoint. |
| * @see org.eclipse.jface.preference.PreferencePage#createContents(org.eclipse.swt.widgets.Composite) |
| */ |
| @Override |
| protected Control createContents(Composite parent) { |
| noDefaultAndApplyButton(); |
| Composite mainComposite = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, GridData.FILL_HORIZONTAL, 0, 0); |
| createLabels(mainComposite); |
| createLabel(mainComposite, ""); //$NON-NLS-1$ // spacer |
| createEnabledButton(mainComposite); |
| createTypeSpecificEditors(mainComposite); |
| setValid(true); |
| // if this breakpoint is being created, change the shell title to indicate 'creation' |
| try { |
| if (getBreakpoint().getMarker().getAttribute(ATTR_DELETE_ON_CANCEL) != null) { |
| getShell().addShellListener(new ShellListener() { |
| public void shellActivated(ShellEvent e) { |
| Shell shell = (Shell)e.getSource(); |
| shell.setText(NLS.bind(PropertyPageMessages.JavaBreakpointPage_10, new String[]{getName(getBreakpoint())})); |
| shell.removeShellListener(this); |
| } |
| public void shellClosed(ShellEvent e) { |
| } |
| public void shellDeactivated(ShellEvent e) { |
| } |
| public void shellDeiconified(ShellEvent e) { |
| } |
| public void shellIconified(ShellEvent e) { |
| } |
| }); |
| } |
| } catch (CoreException e) { |
| } |
| return mainComposite; |
| } |
| |
| /** |
| * Returns the name of the given element. |
| * |
| * @param element the element |
| * @return the name of the element |
| */ |
| private String getName(IAdaptable element) { |
| IWorkbenchAdapter adapter = (IWorkbenchAdapter) element.getAdapter(IWorkbenchAdapter.class); |
| if (adapter != null) { |
| return adapter.getLabel(element); |
| } |
| return EMPTY_STRING; |
| } |
| |
| /** |
| * Creates the labels displayed for the breakpoint. |
| * @param parent the parent composite |
| */ |
| protected void createLabels(Composite parent) { |
| Composite labelComposite = SWTFactory.createComposite(parent, parent.getFont(), 2, 1, GridData.FILL_HORIZONTAL, 0, 0); |
| try { |
| String typeName = ((IJavaBreakpoint) getElement()).getTypeName(); |
| if (typeName != null) { |
| createLabel(labelComposite, PropertyPageMessages.JavaBreakpointPage_3); |
| Text text = SWTFactory.createText(labelComposite, SWT.READ_ONLY, 1, typeName); |
| text.setBackground(parent.getBackground()); |
| } |
| createTypeSpecificLabels(labelComposite); |
| } catch (CoreException ce) { |
| JDIDebugUIPlugin.log(ce); |
| } |
| } |
| |
| /** |
| * Creates the button to toggle enablement of the breakpoint |
| * @param parent the parent composite |
| */ |
| protected void createEnabledButton(Composite parent) { |
| fEnabledButton = createCheckButton(parent, PropertyPageMessages.JavaBreakpointPage_5); |
| try { |
| fEnabledButton.setSelection(getBreakpoint().isEnabled()); |
| } |
| catch(CoreException ce) { |
| JDIDebugUIPlugin.log(ce); |
| } |
| } |
| |
| /** |
| * Returns the breakpoint that this preference page configures |
| * @return the breakpoint this page configures |
| */ |
| protected IJavaBreakpoint getBreakpoint() { |
| return (IJavaBreakpoint) getElement(); |
| } |
| |
| /** |
| * Allows subclasses to add type specific labels to the common Java |
| * breakpoint page. |
| * @param parent the parent composite |
| */ |
| protected void createTypeSpecificLabels(Composite parent) { |
| // Line number |
| IJavaBreakpoint jb = getBreakpoint(); |
| if (jb instanceof IJavaLineBreakpoint) { |
| IJavaLineBreakpoint breakpoint = (IJavaLineBreakpoint) jb; |
| StringBuffer lineNumber = new StringBuffer(4); |
| try { |
| int lNumber = breakpoint.getLineNumber(); |
| if (lNumber > 0) { |
| lineNumber.append(lNumber); |
| } |
| } catch (CoreException ce) { |
| JDIDebugUIPlugin.log(ce); |
| } |
| if (lineNumber.length() > 0) { |
| createLabel(parent, PropertyPageMessages.JavaLineBreakpointPage_2); |
| Text text = SWTFactory.createText(parent, SWT.READ_ONLY, 1, lineNumber.toString()); |
| text.setBackground(parent.getBackground()); |
| } |
| // Member |
| try { |
| IMember member = BreakpointUtils.getMember(breakpoint); |
| if (member == null) { |
| return; |
| } |
| String label = PropertyPageMessages.JavaLineBreakpointPage_3; |
| if (breakpoint instanceof IJavaMethodBreakpoint) { |
| label = PropertyPageMessages.JavaLineBreakpointPage_4; |
| } else if (breakpoint instanceof IJavaWatchpoint) { |
| label = PropertyPageMessages.JavaLineBreakpointPage_5; |
| } |
| createLabel(parent, label); |
| Text text = SWTFactory.createText(parent, SWT.READ_ONLY, 1, fJavaLabelProvider.getText(member)); |
| text.setBackground(parent.getBackground()); |
| } |
| catch (CoreException exception) {JDIDebugUIPlugin.log(exception);} |
| } |
| } |
| |
| /** |
| * Allows subclasses to add type specific editors to the common Java |
| * breakpoint page. |
| * @param parent the parent composite |
| */ |
| protected void createTypeSpecificEditors(Composite parent) { |
| try { |
| String type = getBreakpoint().getMarker().getType(); |
| if (JavaClassPrepareBreakpoint.JAVA_CLASS_PREPARE_BREAKPOINT.equals(type)) { |
| setTitle(PropertyPageMessages.JavaBreakpointPage_11); |
| fEditor = new StandardJavaBreakpointEditor(); |
| } else if (JavaLineBreakpoint.JAVA_LINE_BREAKPOINT.equals(type)) { |
| setTitle(PropertyPageMessages.JavaLineBreakpointPage_18); |
| fEditor = new CompositeBreakpointEditor(new AbstractJavaBreakpointEditor[] |
| {new StandardJavaBreakpointEditor(), new JavaBreakpointConditionEditor(null)}); |
| } else if (JavaExceptionBreakpoint.JAVA_EXCEPTION_BREAKPOINT.equals(type)) { |
| setTitle(PropertyPageMessages.JavaExceptionBreakpointPage_5); |
| fEditor = new ExceptionBreakpointEditor(); |
| } else if (JavaWatchpoint.JAVA_WATCHPOINT.equals(type)) { |
| setTitle(PropertyPageMessages.JavaLineBreakpointPage_19); |
| fEditor = new WatchpointEditor(); |
| } else if (JavaMethodBreakpoint.JAVA_METHOD_BREAKPOINT.equals(type)) { |
| setTitle(PropertyPageMessages.JavaLineBreakpointPage_20); |
| fEditor = new CompositeBreakpointEditor(new AbstractJavaBreakpointEditor[] |
| {new MethodBreakpointEditor(), new JavaBreakpointConditionEditor(null)}); |
| } else { |
| // use standard editor for any other kind of breakpoint (@see bug 325161) |
| fEditor = new StandardJavaBreakpointEditor(); |
| } |
| fEditor.createControl(parent); |
| fEditor.addPropertyListener(new IPropertyListener() { |
| public void propertyChanged(Object source, int propId) { |
| IStatus status = fEditor.getStatus(); |
| if (status.isOK()) { |
| if (fPrevMessage != null) { |
| removeErrorMessage(fPrevMessage); |
| fPrevMessage = null; |
| } |
| } else { |
| fPrevMessage = status.getMessage(); |
| addErrorMessage(fPrevMessage); |
| } |
| } |
| }); |
| fEditor.setInput(getBreakpoint()); |
| } catch (CoreException e) { |
| setErrorMessage(e.getMessage()); |
| } |
| } |
| |
| /** |
| * Creates a fully configured text editor with the given initial value |
| * @param parent the parent composite |
| * @param initialValue the initial {@link String} value |
| * @return the configured text editor |
| */ |
| protected Text createText(Composite parent, String initialValue) { |
| return SWTFactory.createText(parent, SWT.SINGLE | SWT.BORDER, 1, initialValue); |
| } |
| |
| /** |
| * Creates a fully configured check button with the given text. |
| * @param parent the parent composite |
| * @param text the label of the returned check button |
| * @return a fully configured check button |
| */ |
| protected Button createCheckButton(Composite parent, String text) { |
| return SWTFactory.createCheckButton(parent, text, null, false, 1); |
| } |
| |
| /** |
| * Creates a fully configured label with the given text. |
| * @param parent the parent composite |
| * @param text the test of the returned label |
| * @return a fully configured label |
| */ |
| protected Label createLabel(Composite parent, String text) { |
| return SWTFactory.createLabel(parent, text, 1); |
| } |
| |
| /** |
| * Creates a fully configured radio button with the given text. |
| * @param parent the parent composite |
| * @param text the label of the returned radio button |
| * @return a fully configured radio button |
| */ |
| protected Button createRadioButton(Composite parent, String text) { |
| return SWTFactory.createRadioButton(parent, text, 1); |
| } |
| |
| /** |
| * Check to see if the breakpoint should be deleted. |
| * @return <code>true</code> if the page was canceled, <code>false</code> othewise |
| */ |
| @Override |
| public boolean performCancel() { |
| try { |
| if (getBreakpoint().getMarker().getAttribute(ATTR_DELETE_ON_CANCEL) != null) { |
| // if this breakpoint is being created, delete on cancel |
| getBreakpoint().delete(); |
| } |
| } catch (CoreException e) { |
| JDIDebugUIPlugin.statusDialog(PropertyPageMessages.JavaBreakpointPage_9, e.getStatus()); |
| } |
| return super.performCancel(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jface.preference.PreferencePage#createControl(org.eclipse.swt.widgets.Composite) |
| */ |
| @Override |
| public void createControl(Composite parent) { |
| super.createControl(parent); |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IJavaDebugHelpContextIds.JAVA_BREAKPOINT_PROPERTY_PAGE); |
| } |
| } |