| /******************************************************************************* |
| * Copyright (c) 2005, 2017 IBM Corporation and others. |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.dltk.debug.ui.breakpoints; |
| |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.dltk.core.DLTKCore; |
| import org.eclipse.dltk.core.IDLTKLanguageToolkit; |
| import org.eclipse.dltk.core.IScriptProject; |
| import org.eclipse.dltk.debug.core.model.IScriptBreakpoint; |
| import org.eclipse.dltk.debug.ui.DLTKDebugUILanguageManager; |
| import org.eclipse.dltk.debug.ui.DLTKDebugUIPlugin; |
| import org.eclipse.dltk.debug.ui.IDLTKDebugUILanguageToolkit; |
| import org.eclipse.dltk.debug.ui.IDLTKDebugUILanguageToolkit2; |
| import org.eclipse.dltk.debug.ui.breakpoints.IScriptBreakpointPropertyPageExtension.IScriptBreakpointPropertyPageExtensionEditor; |
| import org.eclipse.dltk.internal.ui.editor.ScriptSourceViewer; |
| import org.eclipse.dltk.ui.IDLTKUILanguageToolkit; |
| import org.eclipse.dltk.ui.text.ScriptSourceViewerConfiguration; |
| import org.eclipse.dltk.ui.util.SWTFactory; |
| import org.eclipse.dltk.utils.TextUtils; |
| import org.eclipse.jface.text.Document; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.KeyAdapter; |
| import org.eclipse.swt.events.KeyEvent; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Combo; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Group; |
| import org.eclipse.swt.widgets.Text; |
| import org.eclipse.ui.dialogs.PropertyPage; |
| |
| public class ScriptBreakpointPropertyPage extends PropertyPage { |
| |
| private static final int UPDATE_INITIAL = 0; |
| private static final int UPDATE_EXPRESSION_ENABLE = 1; |
| private static final int UPDATE_OTHER = 2; |
| |
| // Enabled |
| private Button enabledBreakpointButton; |
| |
| // Hit count checking |
| private Button hitCountCheckingButton; |
| private Combo hitConditionCombo; |
| private Text hitValueText; |
| |
| private IScriptBreakpointPropertyPageExtensionEditor extraEditor; |
| |
| // Expression |
| private ScriptSourceViewer expressionViewer; |
| private Button enableExpressionButton; |
| |
| // Simple access methods |
| protected boolean getBreakointEnableState() { |
| return enabledBreakpointButton.getSelection(); |
| } |
| |
| protected boolean getEnabledHitChecking() { |
| return hitCountCheckingButton.getSelection(); |
| } |
| |
| protected void setEnabledHitChecking(boolean state) { |
| hitCountCheckingButton.setSelection(state); |
| } |
| |
| // Hit value & condition |
| protected void setHitCondition(int condition) { |
| if (!hasOnlyGreaterOrEqualsHitCount()) { |
| hitConditionCombo.select(condition); |
| } |
| } |
| |
| protected int getHitCondition() { |
| if (!hasOnlyGreaterOrEqualsHitCount()) { |
| return getEnabledHitChecking() |
| ? hitConditionCombo.getSelectionIndex() |
| : -1; |
| } |
| return IScriptBreakpoint.HIT_CONDITION_GREATER_OR_EQUAL; |
| } |
| |
| protected void setHitValue(int value) { |
| hitValueText.setText(Integer.toString(value)); |
| } |
| |
| protected int getHitValue() { |
| return getEnabledHitChecking() |
| ? Integer.parseInt(hitValueText.getText()) |
| : -1; |
| } |
| |
| // Expression |
| protected void setExpression(String expression) { |
| expressionViewer.getDocument().set(expression); |
| } |
| |
| protected String getExpression() { |
| return expressionViewer.getDocument().get(); |
| } |
| |
| protected void setExpressionState(boolean state) { |
| enableExpressionButton.setSelection(state); |
| } |
| |
| protected boolean getExpressionState() { |
| return enableExpressionButton.getSelection(); |
| } |
| |
| // Static breakpoint information |
| protected void createLabels(Composite parent) throws CoreException { |
| IScriptBreakpoint breakpoint = getBreakpoint(); |
| |
| Composite labelComposite = SWTFactory.createComposite(parent, |
| parent.getFont(), 2, 1, GridData.FILL_HORIZONTAL); |
| |
| // Script language |
| SWTFactory.createLabel(labelComposite, BreakpointMessages.LanguageLabel, |
| 1); |
| SWTFactory.createLabel(labelComposite, BreakpointUtils |
| .getLanguageToolkit(breakpoint).getLanguageName(), 1); |
| |
| createLocationLabels(labelComposite); |
| |
| // Id |
| SWTFactory.createLabel(labelComposite, |
| BreakpointMessages.InternalIdLabel, 1); |
| |
| String[] engineIds = breakpoint.getIdentifiers(); |
| String engineIdText = (engineIds == null || engineIds.length == 0) |
| ? BreakpointMessages.InternalIdNotAvailableMessage |
| : TextUtils.join(engineIds, ','); |
| SWTFactory.createLabel(labelComposite, engineIdText, 1); |
| |
| // Hit count |
| if (hasHitCountAttribute()) { |
| SWTFactory.createLabel(labelComposite, |
| BreakpointMessages.HitCountLabel, 1); |
| |
| int hitCount = breakpoint.getHitCount(); |
| String hitCountText = hitCount == -1 |
| ? BreakpointMessages.HitCountNotAvailableMessage |
| : Integer.toString(hitCount); |
| SWTFactory.createLabel(labelComposite, hitCountText, 1); |
| } |
| |
| // from debugging engine |
| |
| createTypeSpecificLabels(labelComposite); |
| } |
| |
| protected void createLocationLabels(Composite parent) throws CoreException { |
| // Resource name |
| String resourceName = getBreakpointResourceName(); |
| if (resourceName != null && resourceName.length() > 0) { |
| SWTFactory.createLabel(parent, getBreakpointLocationLabel(), 1); |
| SWTFactory.createLabel(parent, resourceName, 1); |
| } |
| } |
| |
| /** |
| * Returns the label text for the location field |
| * |
| * @return |
| */ |
| protected String getBreakpointLocationLabel() { |
| return BreakpointMessages.FileLabel; |
| } |
| |
| /** |
| * Returns the value for the location field |
| * |
| * @return |
| * @throws CoreException |
| */ |
| protected String getBreakpointResourceName() throws CoreException { |
| return getBreakpoint().getResourceName(); |
| } |
| |
| protected void createTypeSpecificLabels(Composite parent) |
| throws CoreException { |
| // Nothing to do here |
| } |
| |
| // Breakpoint information |
| protected void createButtons(Composite parent) throws CoreException { |
| Composite buttonsComposite = SWTFactory.createComposite(parent, |
| parent.getFont(), 1, 1, GridData.FILL_HORIZONTAL); |
| |
| enabledBreakpointButton = SWTFactory.createCheckButton(buttonsComposite, |
| BreakpointMessages.EnabledLabel, null, false, 1); |
| |
| createTypeSpecificButtons(buttonsComposite); |
| } |
| |
| protected void createTypeSpecificButtons(Composite parent) { |
| |
| } |
| |
| protected void createHitCountEditor(Composite parent) { |
| Composite hitCountComposite = SWTFactory.createComposite(parent, |
| parent.getFont(), 4, 1, GridData.FILL_HORIZONTAL); |
| |
| // Hit count checking |
| hitCountCheckingButton = SWTFactory.createCheckButton(hitCountComposite, |
| BreakpointMessages.BreakWhenHitCountLabel, null, false, 1); |
| |
| hitCountCheckingButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| updateControlsState(UPDATE_OTHER); |
| } |
| }); |
| |
| if (!hasOnlyGreaterOrEqualsHitCount()) { |
| hitConditionCombo = new Combo(hitCountComposite, SWT.READ_ONLY); |
| |
| // Hit condition |
| hitConditionCombo.add(BreakpointMessages.HitConditionGreaterOrEqual, |
| IScriptBreakpoint.HIT_CONDITION_GREATER_OR_EQUAL); |
| |
| hitConditionCombo.add(BreakpointMessages.HitConditionEqual, |
| IScriptBreakpoint.HIT_CONDITION_EQUAL); |
| |
| hitConditionCombo.add(BreakpointMessages.HitConditionMultiple, |
| IScriptBreakpoint.HIT_CONDITION_MULTIPLE); |
| |
| hitConditionCombo |
| .select(IScriptBreakpoint.HIT_CONDITION_GREATER_OR_EQUAL); |
| |
| hitConditionCombo.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| updateControlsState(UPDATE_OTHER); |
| } |
| }); |
| |
| hitConditionCombo.setData(new GridData()); |
| } |
| |
| // Hit value |
| hitValueText = new Text(hitCountComposite, SWT.BORDER); |
| hitValueText |
| .setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); |
| |
| hitValueText.addKeyListener(new KeyAdapter() { |
| @Override |
| public void keyReleased(KeyEvent e) { |
| updateControlsState(UPDATE_OTHER); |
| } |
| }); |
| |
| SWTFactory.createLabel(hitCountComposite, BreakpointMessages.HitsLabel, |
| 1); |
| } |
| |
| protected void createExpressionEditor(Composite parent) { |
| Group group = new Group(parent, SWT.NONE); |
| group.setLayout(new GridLayout(1, false)); |
| group.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| |
| enableExpressionButton = new Button(group, SWT.CHECK); |
| enableExpressionButton.setText(BreakpointMessages.UseConditionLabel); |
| enableExpressionButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| updateControlsState(UPDATE_EXPRESSION_ENABLE); |
| } |
| }); |
| |
| IDLTKUILanguageToolkit toolkit = BreakpointUtils |
| .getUILanguageToolkit(getBreakpoint()); |
| |
| expressionViewer = new ScriptSourceViewer(group, null, null, false, |
| SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL, |
| toolkit.getPreferenceStore()); |
| |
| IDocument document = new Document(); |
| |
| toolkit.getTextTools().setupDocumentPartitioner(document, |
| toolkit.getPartitioningId()); |
| |
| ScriptSourceViewerConfiguration config = toolkit |
| .createSourceViewerConfiguration(); |
| |
| expressionViewer.configure(config); |
| expressionViewer.setDocument(document); |
| |
| expressionViewer.getControl() |
| .setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| |
| } |
| |
| protected IScriptBreakpoint getBreakpoint() { |
| return (IScriptBreakpoint) getElement(); |
| } |
| |
| @Override |
| protected Control createContents(Composite parent) { |
| noDefaultAndApplyButton(); |
| Composite composite = SWTFactory.createComposite(parent, |
| parent.getFont(), 1, 1, GridData.FILL_BOTH); |
| |
| try { |
| createLabels(composite); |
| createButtons(composite); |
| |
| if (hasHitCountEditor()) { |
| createHitCountEditor(composite); |
| } |
| |
| if (hasExpressionEditor()) { |
| createExpressionEditor(composite); |
| } |
| |
| IScriptBreakpointPropertyPageExtension extension = getBreakpointPropertyPageExtension(); |
| if (extension != null) { |
| extraEditor = extension |
| .createExtraPropertyEditor(getBreakpoint()); |
| } |
| |
| loadValues(); |
| updateControlsState(UPDATE_INITIAL); |
| } catch (CoreException e) { |
| DLTKDebugUIPlugin.log(e); |
| } |
| |
| return composite; |
| } |
| |
| protected IScriptBreakpointPropertyPageExtension getBreakpointPropertyPageExtension() { |
| IScriptBreakpoint breakpoint = getBreakpoint(); |
| IMarker marker = breakpoint.getMarker(); |
| if (marker != null) { |
| IProject project = marker.getResource().getProject(); |
| IScriptProject scriptProject = DLTKCore.create(project); |
| IDLTKLanguageToolkit toolkit = scriptProject.getLanguageToolkit(); |
| if (toolkit != null) { |
| IDLTKDebugUILanguageToolkit debugUILanguageToolkit = DLTKDebugUILanguageManager |
| .getLanguageToolkit(toolkit.getNatureId()); |
| if (debugUILanguageToolkit != null |
| && debugUILanguageToolkit instanceof IDLTKDebugUILanguageToolkit2) { |
| { |
| return ((IDLTKDebugUILanguageToolkit2) debugUILanguageToolkit) |
| .getBreakpointPropertyPageExtension(); |
| } |
| } |
| } |
| } |
| return null; |
| } |
| |
| protected boolean hasHitCountAttribute() { |
| return true; |
| } |
| |
| protected boolean hasHitCountEditor() { |
| IScriptBreakpointPropertyPageExtension extension = getBreakpointPropertyPageExtension(); |
| if (extension != null) { |
| return extension.hasHitCountEditor(getBreakpoint()); |
| } |
| return true; |
| } |
| |
| protected boolean hasOnlyGreaterOrEqualsHitCount() { |
| IScriptBreakpointPropertyPageExtension extension = getBreakpointPropertyPageExtension(); |
| if (extension != null) { |
| return extension.hasOnlyGreaterOrEqualsHitCount(getBreakpoint()); |
| } |
| return false; |
| } |
| |
| protected boolean hasExpressionEditor() { |
| IScriptBreakpointPropertyPageExtension extension = getBreakpointPropertyPageExtension(); |
| if (extension != null) { |
| return extension.hasExpressionEditor(getBreakpoint()); |
| } |
| return true; |
| } |
| |
| protected void loadValues() throws CoreException { |
| IScriptBreakpoint breakpoint = getBreakpoint(); |
| |
| // Enabled |
| enabledBreakpointButton.setSelection(breakpoint.isEnabled()); |
| |
| // Hit conditions |
| if (hasHitCountEditor()) { |
| |
| final int hitValue = breakpoint.getHitValue(); |
| if (hitValue != -1) { |
| setHitValue(hitValue); |
| setHitCondition(breakpoint.getHitCondition()); |
| setEnabledHitChecking(true); |
| } else { |
| setEnabledHitChecking(false); |
| } |
| } |
| |
| // Expression |
| if (hasExpressionEditor()) { |
| setExpressionState(breakpoint.getExpressionState()); |
| setExpression(breakpoint.getExpression()); |
| } |
| if (extraEditor != null) { |
| extraEditor.loadContents(breakpoint); |
| } |
| } |
| |
| protected void saveValues() throws CoreException { |
| IScriptBreakpoint breakpoint = getBreakpoint(); |
| |
| breakpoint.setEnabled(getBreakointEnableState()); |
| |
| if (hasHitCountEditor()) { |
| breakpoint.setHitValue(getHitValue()); |
| breakpoint.setHitCondition(getHitCondition()); |
| } |
| |
| if (hasExpressionEditor()) { |
| breakpoint.setExpression(getExpression()); |
| breakpoint.setExpressionState(getExpressionState()); |
| } |
| if (extraEditor != null) { |
| extraEditor.saveContents(breakpoint); |
| } |
| } |
| |
| protected void updateControlsState(int mode) { |
| // Hit count |
| if (hasHitCountEditor()) { |
| boolean hitChecking = hitCountCheckingButton.getSelection(); |
| if (!hasOnlyGreaterOrEqualsHitCount()) { |
| hitConditionCombo.setEnabled(hitChecking); |
| } |
| hitValueText.setEnabled(hitChecking); |
| } |
| |
| // Expression |
| if (hasExpressionEditor()) { |
| boolean expressionEnabled = enableExpressionButton.getSelection(); |
| Control control = expressionViewer.getControl(); |
| control.setEnabled(expressionEnabled); |
| if (expressionEnabled) { |
| expressionViewer.initializeViewerColors(); |
| if (mode == UPDATE_EXPRESSION_ENABLE) { |
| expressionViewer.getTextWidget().setFocus(); |
| } |
| } else { |
| Color color = expressionViewer.getControl().getDisplay() |
| .getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); |
| expressionViewer.getTextWidget().setBackground(color); |
| } |
| } |
| |
| validateValues(); |
| } |
| |
| protected void validateValues() { |
| boolean valid = true; |
| String errorMessage = null; |
| |
| if (hasHitCountEditor()) { |
| if (getEnabledHitChecking()) { |
| try { |
| getHitValue(); |
| } catch (NumberFormatException e) { |
| valid = false; |
| errorMessage = BreakpointMessages.InvalidNumberOfHits; |
| } |
| } |
| } |
| |
| setValid(valid); |
| setErrorMessage(errorMessage); |
| } |
| |
| @Override |
| public boolean performOk() { |
| try { |
| ResourcesPlugin.getWorkspace().run(monitor -> { |
| saveValues(); |
| DebugPlugin.getDefault().getBreakpointManager() |
| .fireBreakpointChanged(getBreakpoint()); |
| }, null, 0, null); |
| } catch (CoreException e) { |
| DebugPlugin.log(e); |
| } |
| |
| return super.performOk(); |
| } |
| } |