blob: 6942df7dcc2c32a52e3667aaa45d5b2fede1cc3e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2016 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 Button fTriggerPointButton; protected Button fTriggerPointButtonActive;
*/
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() {
@Override
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();
// storeTriggerPoint(breakpoint);
// storeTriggerPointActive(breakpoint);
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
Composite composite = SWTFactory.createComposite(mainComposite, parent.getFont(), 4, 1, 0, 0, 0);
createEnabledButton(composite);
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() {
@Override
public void shellActivated(ShellEvent e) {
Shell shell = (Shell)e.getSource();
shell.setText(NLS.bind(PropertyPageMessages.JavaBreakpointPage_10, new String[]{getName(getBreakpoint())}));
shell.removeShellListener(this);
}
@Override
public void shellClosed(ShellEvent e) {
}
@Override
public void shellDeactivated(ShellEvent e) {
}
@Override
public void shellDeiconified(ShellEvent e) {
}
@Override
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 = 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() {
@Override
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);
}
}