/******************************************************************************* * Copyright (c) 2000, 2017 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<>(); 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 CompositeBreakpointEditor(new AbstractJavaBreakpointEditor[] { new WatchpointEditor(), new JavaBreakpointConditionEditor(null) }); } 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); } }