/******************************************************************************* * Copyright (c) 2009, 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.debug.ui.breakpoints; import java.util.HashMap; import java.util.Map; import java.util.Stack; import java.util.regex.Pattern; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.IHandler; import org.eclipse.core.commands.operations.IUndoContext; import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.internal.ui.SWTFactory; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IField; import org.eclipse.jdt.core.ISourceRange; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.debug.core.IJavaLineBreakpoint; import org.eclipse.jdt.debug.core.IJavaWatchpoint; import org.eclipse.jdt.internal.debug.ui.BreakpointUtils; import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin; import org.eclipse.jdt.internal.debug.ui.JDISourceViewer; import org.eclipse.jdt.internal.debug.ui.breakpoints.AbstractJavaBreakpointEditor; import org.eclipse.jdt.internal.debug.ui.contentassist.IJavaDebugContentAssistContext; import org.eclipse.jdt.internal.debug.ui.contentassist.JavaDebugContentAssistProcessor; import org.eclipse.jdt.internal.debug.ui.contentassist.TypeContext; import org.eclipse.jdt.internal.debug.ui.display.DisplayViewerConfiguration; import org.eclipse.jdt.internal.debug.ui.propertypages.PropertyPageMessages; import org.eclipse.jdt.ui.text.IJavaPartitions; import org.eclipse.jface.action.IAction; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.DialogSettings; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.fieldassist.FieldDecoration; import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.ITextViewerExtension6; import org.eclipse.jface.text.IUndoManager; import org.eclipse.jface.text.IUndoManagerExtension; import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.GridData; 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.ui.IPropertyListener; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchCommandConstants; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.handlers.IHandlerActivation; import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.operations.OperationHistoryActionHandler; import org.eclipse.ui.operations.RedoActionHandler; import org.eclipse.ui.operations.UndoActionHandler; import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds; import org.eclipse.ui.texteditor.ITextEditorActionConstants; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; /** * Controls to edit a breakpoint's conditional expression, condition enabled state, * and suspend policy (suspend when condition is <code>true</code> or when the value of the * conditional expression changes). * <p> * The controls are intended to be embedded in a composite provided by the client - for * example, in a dialog. Clients must call {@link #createControl(Composite)} as the first * life cycle method after instantiation. Clients may then call {@link #setInput(Object)} * with the breakpoint object to be displayed/edited. Changes are not applied to the * breakpoint until {@link #doSave()} is called. The method {@link #isDirty()} may be used * to determine if any changes have been made in the editor, and {@link #getStatus()} may * be used to determine if the editor settings are valid. Clients can register for * property change notification ({@link #addPropertyListener(IPropertyListener)}). The editor * will fire a property change each time a setting is modified. The same editor can be * used to display different breakpoints by calling {@link #setInput(Object)} with different * breakpoint objects. * </p> * * @since 3.5 */ public final class JavaBreakpointConditionEditor extends AbstractJavaBreakpointEditor { private Button fConditional; private Button fWhenTrue; private Button fWhenChange; private JDISourceViewer fViewer; private IContentAssistProcessor fCompletionProcessor; private IJavaLineBreakpoint fBreakpoint; private IHandlerService fHandlerService; private IHandler fContentAssistHandler; private IHandlerActivation fContentAssistActivation; private IHandler fUndoHandler; private IHandlerActivation fUndoActivation; private IHandler fRedoHandler; private IHandlerActivation fRedoActivation; private IDocumentListener fDocumentListener; private Combo fConditionHistory; private IDialogSettings fConditionHistoryDialogSettings; private boolean fReplaceConditionInHistory; private Map<IJavaLineBreakpoint, Stack<String>> fLocalConditionHistory; private int fSeparatorIndex; private IViewSite fBreakpointsViewSite; private IAction fViewUndoAction; private IAction fViewRedoAction; private OperationHistoryActionHandler fViewerUndoAction; private OperationHistoryActionHandler fViewerRedoAction; /** * Property id for breakpoint condition expression. */ public static final int PROP_CONDITION= 0x1001; /** * Property id for breakpoint condition enabled state. */ public static final int PROP_CONDITION_ENABLED= 0x1002; /** * Property id for breakpoint condition suspend policy. */ public static final int PROP_CONDITION_SUSPEND_POLICY= 0x1003; private static final int MAX_HISTORY_SIZE= 10; private static final String DS_SECTION_CONDITION_HISTORY= "conditionHistory"; //$NON-NLS-1$ private static final String DS_KEY_HISTORY_ENTRY_COUNT= "conditionHistoryEntryCount"; //$NON-NLS-1$ private static final String DS_KEY_HISTORY_ENTRY_PREFIX= "conditionHistoryEntry_"; //$NON-NLS-1$ private static final Pattern NEWLINE_PATTERN= Pattern.compile("\r\n|\r|\n"); //$NON-NLS-1$; /** * Creates a new Java breakpoint condition editor. */ public JavaBreakpointConditionEditor() { } /** * Creates a new Java breakpoint condition editor with a history drop-down list. * * @param dialogSettings the dialog settings for the condition history or <code>null</code> to * use the default settings (i.e. those used by JDT Debug) * @since 3.6 */ public JavaBreakpointConditionEditor(IDialogSettings dialogSettings) { fConditionHistoryDialogSettings= dialogSettings != null ? dialogSettings : DialogSettings.getOrCreateSection(JDIDebugUIPlugin.getDefault().getDialogSettings(), DS_SECTION_CONDITION_HISTORY); } /** * Adds the given property listener to this editor. Property changes * are reported on the breakpoint being edited. Property identifiers * are breakpoint attribute keys. * * @param listener listener */ @Override public void addPropertyListener(IPropertyListener listener) { super.addPropertyListener(listener); } /** * Removes the property listener from this editor. * * @param listener listener */ @Override public void removePropertyListener(IPropertyListener listener) { super.removePropertyListener(listener); } /** * Sets the breakpoint to editor or <code>null</code> if none. * * @param input breakpoint or <code>null</code> * @throws CoreException if unable to access breakpoint attributes */ @Override public void setInput(Object input) throws CoreException { try { boolean sameBreakpoint= fBreakpoint == input; suppressPropertyChanges(true); if (input instanceof IJavaLineBreakpoint) { setBreakpoint((IJavaLineBreakpoint)input); } else if (input instanceof IJavaWatchpoint) { setBreakpoint((IJavaWatchpoint) input); } else { setBreakpoint(null); } if (hasConditionHistory()) { if (!sameBreakpoint) { fReplaceConditionInHistory= false; } initializeConditionHistoryDropDown(); } } finally { suppressPropertyChanges(false); } } /** * Sets the breakpoint to edit. Has no effect if the breakpoint responds * <code>false</code> to {@link IJavaLineBreakpoint#supportsCondition()}. * The same editor can be used iteratively for different breakpoints. * * @param breakpoint the breakpoint to edit or <code>null</code> if none * @exception CoreException if unable to access breakpoint attributes */ private void setBreakpoint(IJavaLineBreakpoint breakpoint) throws CoreException { fBreakpoint = breakpoint; if (fDocumentListener != null) { fViewer.getDocument().removeDocumentListener(fDocumentListener); fDocumentListener = null; } fViewer.unconfigure(); IDocument document = new Document(); JDIDebugUIPlugin.getDefault().getJavaTextTools().setupJavaDocumentPartitioner(document, IJavaPartitions.JAVA_PARTITIONING); fViewer.setInput(document); String condition = null; IType type = null; boolean controlsEnabled = false; boolean conditionEnabled = false; boolean whenTrue = true; if (breakpoint != null) { controlsEnabled = true; if (breakpoint.supportsCondition()) { condition = breakpoint.getCondition(); conditionEnabled = breakpoint.isConditionEnabled(); whenTrue = breakpoint.isConditionSuspendOnTrue(); type = BreakpointUtils.getType(breakpoint); } } IJavaDebugContentAssistContext context = null; if (type == null || breakpoint == null) { context = new TypeContext(null, -1); } else { String source = null; ICompilationUnit compilationUnit = type.getCompilationUnit(); if (compilationUnit != null && compilationUnit.getJavaProject().getProject().exists()) { source = compilationUnit.getSource(); } else { IClassFile classFile = type.getClassFile(); if (classFile != null) { source = classFile.getSource(); } } int position= -1; if (breakpoint instanceof IJavaWatchpoint) { IField[] fields = type.getFields(); // Taking first field ISourceRange sourceRange = fields[0].getNameRange(); position = sourceRange.getOffset(); if (source != null && position != -1) { try { // to get offset of the first character of line in which field is defined int lineNumber = new Document(source).getLineOfOffset(position); position = new Document(source).getLineOffset(lineNumber); } catch (BadLocationException e) { // ignore, breakpoint line is out-of-date with the document } } } else { int lineNumber = breakpoint.getMarker().getAttribute(IMarker.LINE_NUMBER, -1); if (source != null && lineNumber != -1) { try { position = new Document(source).getLineOffset(lineNumber - 1); } catch (BadLocationException e) { // ignore, breakpoint line is out-of-date with the document } } } context = new TypeContext(type, position); } fCompletionProcessor = new JavaDebugContentAssistProcessor(context); document.set((condition == null ? "" : condition)); //$NON-NLS-1$ fViewer.configure(new DisplayViewerConfiguration() { @Override public IContentAssistProcessor getContentAssistantProcessor() { return fCompletionProcessor; } }); fDocumentListener = new IDocumentListener() { @Override public void documentAboutToBeChanged(DocumentEvent event) { } @Override public void documentChanged(DocumentEvent event) { setDirty(PROP_CONDITION); } }; fViewer.getDocument().addDocumentListener(fDocumentListener); fConditional.setEnabled(controlsEnabled); fConditional.setSelection(conditionEnabled); fWhenTrue.setSelection(whenTrue); fWhenChange.setSelection(!whenTrue); setEnabled(conditionEnabled && breakpoint != null && breakpoint.supportsCondition(), false); setDirty(false); checkIfUsedInBreakpointsView(); registerViewerUndoRedoActions(); } /** * Creates the condition editor widgets and returns the top level * control. * * @param parent composite to embed the editor controls in * @return top level control */ @Override public Control createControl(Composite parent) { Composite controls = SWTFactory.createComposite(parent, parent.getFont(), 2, 1, GridData.FILL_HORIZONTAL, 0, 0); fConditional = SWTFactory.createCheckButton(controls, processMnemonics(PropertyPageMessages.JavaBreakpointConditionEditor_0), null, false, 1); fConditional.setLayoutData(new GridData(SWT.BEGINNING, SWT.CENTER, false, false)); fConditional.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { boolean checked = fConditional.getSelection(); setEnabled(checked, true); setDirty(PROP_CONDITION_ENABLED); } }); Composite radios = SWTFactory.createComposite(controls, controls.getFont(), 2, 1, GridData.FILL_HORIZONTAL, 0, 0); fWhenTrue = SWTFactory.createRadioButton(radios, processMnemonics(PropertyPageMessages.JavaBreakpointConditionEditor_1)); fWhenTrue.setLayoutData(new GridData()); fWhenChange = SWTFactory.createRadioButton(radios, processMnemonics(PropertyPageMessages.JavaBreakpointConditionEditor_2)); fWhenChange.setLayoutData(new GridData()); fWhenTrue.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { setDirty(PROP_CONDITION_SUSPEND_POLICY); } }); fWhenChange.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { setDirty(PROP_CONDITION_SUSPEND_POLICY); } }); if (fConditionHistoryDialogSettings != null) { fLocalConditionHistory= new HashMap<>(); fConditionHistory= SWTFactory.createCombo(parent, SWT.DROP_DOWN | SWT.READ_ONLY, 1, null); initializeConditionHistoryDropDown(); fConditionHistory.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { int historyIndex= fConditionHistory.getSelectionIndex() - 1; if (historyIndex >= 0 && historyIndex != fSeparatorIndex) { fViewer.getDocument().set(getConditionHistory()[historyIndex]); } } }); GridData data= new GridData(GridData.FILL_HORIZONTAL); data.widthHint= 10; fConditionHistory.setLayoutData(data); fLocalConditionHistory= new HashMap<>(10); } fViewer = new JDISourceViewer(parent, null, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.LEFT_TO_RIGHT); fViewer.setEditable(false); ControlDecoration decoration = new ControlDecoration(fViewer.getControl(), SWT.TOP | SWT.LEFT); decoration.setShowOnlyOnFocus(true); FieldDecoration dec = FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_CONTENT_PROPOSAL); decoration.setImage(dec.getImage()); decoration.setDescriptionText(dec.getDescription()); GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); // set height/width hints based on font GC gc = new GC(fViewer.getTextWidget()); gc.setFont(fViewer.getTextWidget().getFont()); FontMetrics fontMetrics = gc.getFontMetrics(); gd.heightHint = Dialog.convertHeightInCharsToPixels(fontMetrics, 17); gd.widthHint = Dialog.convertWidthInCharsToPixels(fontMetrics, 40); gc.dispose(); fViewer.getControl().setLayoutData(gd); fContentAssistHandler= new AbstractHandler() { @Override public Object execute(ExecutionEvent event) throws org.eclipse.core.commands.ExecutionException { fViewer.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS); return null; } }; fUndoHandler= new AbstractHandler() { @Override public Object execute(ExecutionEvent event) throws org.eclipse.core.commands.ExecutionException { fViewer.doOperation(ITextOperationTarget.UNDO); return null; } }; fRedoHandler= new AbstractHandler() { @Override public Object execute(ExecutionEvent event) throws org.eclipse.core.commands.ExecutionException { fViewer.doOperation(ITextOperationTarget.REDO); return null; } }; fHandlerService = PlatformUI.getWorkbench().getAdapter(IHandlerService.class); fViewer.getControl().addFocusListener(new FocusAdapter() { @Override public void focusGained(FocusEvent e) { activateHandlers(); } @Override public void focusLost(FocusEvent e) { deactivateHandlers(); } }); parent.addDisposeListener(new DisposeListener() { @Override public void widgetDisposed(DisposeEvent e) { dispose(); } }); return parent; } /** * Disposes this editor and its controls. Once disposed, the editor can no * longer be used. */ @Override protected void dispose() { super.dispose(); deactivateHandlers(); if (fDocumentListener != null) { fViewer.getDocument().removeDocumentListener(fDocumentListener); } fViewer.dispose(); } /** * Gives focus to an appropriate control in the editor. */ @Override public void setFocus() { fViewer.getControl().setFocus(); } /** * Saves current settings to the breakpoint being edited. Has no * effect if a breakpoint is not currently being edited or if this * editor is not dirty. * * @exception CoreException if unable to update the breakpoint. */ @Override public void doSave() throws CoreException { if (fBreakpoint != null && isDirty()) { fBreakpoint.setCondition(fViewer.getDocument().get().trim()); fBreakpoint.setConditionEnabled(fConditional.getSelection()); fBreakpoint.setConditionSuspendOnTrue(fWhenTrue.getSelection()); setDirty(false); if (hasConditionHistory()) { updateConditionHistories(); } } } /** * Returns a status describing whether the condition editor is in * a valid state. Returns an OK status when all is good. For example, an error * status is returned when the conditional expression is empty but enabled. * * @return editor status. */ @Override public IStatus getStatus() { if (fBreakpoint != null && fBreakpoint.supportsCondition()) { if (fConditional.getSelection()) { if (fViewer.getDocument().get().trim().length() == 0) { return new Status(IStatus.ERROR, JDIDebugUIPlugin.getUniqueIdentifier(), PropertyPageMessages.BreakpointConditionEditor_1); } } } return Status.OK_STATUS; } /** * Returns whether the editor needs saving. * * @return whether the editor needs saving */ @Override public boolean isDirty() { return super.isDirty(); } /** * Sets whether mnemonics should be displayed in editor controls. * Only has an effect if set before {@link #createControl(Composite)} * is called. By default, mnemonics are displayed. * * @param mnemonics whether to display mnemonics */ @Override public void setMnemonics(boolean mnemonics) { super.setMnemonics(mnemonics); } private void activateHandlers() { fContentAssistActivation= fHandlerService.activateHandler(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, fContentAssistHandler); checkIfUsedInBreakpointsView(); if (fBreakpointsViewSite == null) { fUndoActivation= fHandlerService.activateHandler(IWorkbenchCommandConstants.EDIT_UNDO, fUndoHandler); fRedoActivation= fHandlerService.activateHandler(IWorkbenchCommandConstants.EDIT_REDO, fRedoHandler); } else { registerViewerUndoRedoActions(); } } private void deactivateHandlers() { if (fContentAssistActivation != null) { fHandlerService.deactivateHandler(fContentAssistActivation); fContentAssistActivation= null; } if (fUndoActivation != null) { fHandlerService.deactivateHandler(fUndoActivation); fUndoActivation= null; } if (fRedoActivation != null) { fHandlerService.deactivateHandler(fRedoActivation); fRedoActivation= null; } if (fBreakpointsViewSite != null) { fBreakpointsViewSite.getActionBars().setGlobalActionHandler(ITextEditorActionConstants.UNDO, fViewUndoAction); fBreakpointsViewSite.getActionBars().setGlobalActionHandler(ITextEditorActionConstants.REDO, fViewRedoAction); fBreakpointsViewSite.getActionBars().updateActionBars(); disposeViewerUndoRedoActions(); } } private void disposeViewerUndoRedoActions() { if (fViewerUndoAction != null) { fViewerUndoAction.dispose(); fViewerUndoAction= null; } if (fViewerRedoAction != null) { fViewerRedoAction.dispose(); fViewerRedoAction= null; } } /** * Enables controls based on whether the breakpoint's condition is enabled. * * @param enabled <code>true</code> if enabled, <code>false</code> otherwise * @param focus <code>true</code> if focus should be set, <code>false</code> otherwise */ private void setEnabled(boolean enabled, boolean focus) { fViewer.setEditable(enabled); fViewer.getTextWidget().setEnabled(enabled); fWhenChange.setEnabled(enabled); fWhenTrue.setEnabled(enabled); if (enabled) { fViewer.updateViewerColors(); if (focus) { setFocus(); } } else { Color color = fViewer.getControl().getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND); fViewer.getTextWidget().setBackground(color); } if (hasConditionHistory()) { fConditionHistory.setEnabled(enabled); } } /** * Returns the breakpoint being edited or <code>null</code> if none. * * @return breakpoint or <code>null</code> */ @Override public Object getInput() { return fBreakpoint; } /** * Tells whether this editor shows a condition history drop-down list. * * @return <code>true</code> if this editor shows a condition history drop-down list, * <code>false</code> otherwise */ private boolean hasConditionHistory() { return fConditionHistory != null; } /** * Initializes the condition history drop-down with values. */ private void initializeConditionHistoryDropDown() { fConditionHistory.setItems(getConditionHistoryLabels()); String userHint= PropertyPageMessages.JavaBreakpointConditionEditor_choosePreviousCondition; fConditionHistory.add(userHint, 0); fConditionHistory.setText(userHint); } /** * Returns the condition history labels for the current breakpoint. * * @return an array of strings containing the condition history labels */ private String[] getConditionHistoryLabels() { String[] conditions= getConditionHistory(); String[] labels= new String[conditions.length]; for (int i= 0; i < conditions.length; i++) { labels[i]= NEWLINE_PATTERN.matcher(conditions[i]).replaceAll(" "); //$NON-NLS-1$ } return labels; } /** * Returns the condition history entries for the current breakpoint. * * @return an array of strings containing the history of conditions */ private String[] getConditionHistory() { fSeparatorIndex= -1; // Get global history String[] globalItems= readConditionHistory(fConditionHistoryDialogSettings); // Get local history Stack<String> localHistory= fLocalConditionHistory.get(fBreakpoint); if (localHistory == null) { return globalItems; } // Create combined history int localHistorySize= Math.min(localHistory.size(), MAX_HISTORY_SIZE); String[] historyItems= new String[localHistorySize + globalItems.length + 1]; for (int i= 0; i < localHistorySize; i++) { historyItems[i]= localHistory.get(localHistory.size() - i - 1); } fSeparatorIndex= localHistorySize; historyItems[localHistorySize]= getSeparatorLabel(); System.arraycopy(globalItems, 0, historyItems, localHistorySize + 1, globalItems.length); return historyItems; } /** * Updates the local and global condition histories. */ private void updateConditionHistories() { String newItem= fViewer.getDocument().get(); if (newItem.length() == 0) { return; } // Update local history Stack<String> localHistory= fLocalConditionHistory.get(fBreakpoint); if (localHistory == null) { localHistory= new Stack<>(); fLocalConditionHistory.put(fBreakpoint, localHistory); } localHistory.remove(newItem); localHistory.push(newItem); // Update global history String[] globalItems= readConditionHistory(fConditionHistoryDialogSettings); if (globalItems.length > 0 && newItem.equals(globalItems[0])) { return; } if (!fReplaceConditionInHistory) { String[] tempItems= new String[globalItems.length + 1]; System.arraycopy(globalItems, 0, tempItems, 1, globalItems.length); globalItems= tempItems; } else if (globalItems.length == 0) { globalItems= new String[1]; } fReplaceConditionInHistory= true; globalItems[0]= newItem; storeConditionHistory(globalItems, fConditionHistoryDialogSettings); } /** * Reads the condition history from the given dialog settings. * * @param dialogSettings the dialog settings * @return the condition history */ private static String[] readConditionHistory(IDialogSettings dialogSettings) { int count= 0; try { count= dialogSettings.getInt(DS_KEY_HISTORY_ENTRY_COUNT); } catch (NumberFormatException ex) { // No history yet } count= Math.min(count, MAX_HISTORY_SIZE); String[] conditions= new String[count]; for (int i= 0; i < count; i++) { conditions[i]= dialogSettings.get(DS_KEY_HISTORY_ENTRY_PREFIX + i); } return conditions; } /** * Writes the given conditions into the given dialog settings. * * @param conditions an array of strings containing the conditions * @param dialogSettings the dialog settings */ private static void storeConditionHistory(String[] conditions, IDialogSettings dialogSettings) { int length= Math.min(conditions.length, MAX_HISTORY_SIZE); int count= 0; outer: for (int i= 0; i < length; i++) { for (int j= 0; j < i; j++) { if (conditions[i].equals(conditions[j])) { break outer; } } dialogSettings.put(DS_KEY_HISTORY_ENTRY_PREFIX + count, conditions[i]); count= count + 1; } dialogSettings.put(DS_KEY_HISTORY_ENTRY_COUNT, count); } /** * Returns the label for the history separator. * * @return the label for the history separator */ private String getSeparatorLabel() { int borderWidth= fConditionHistory.computeTrim(0, 0, 0, 0).width; Rectangle rect= fConditionHistory.getBounds(); int width= rect.width - borderWidth; GC gc= new GC(fConditionHistory); gc.setFont(fConditionHistory.getFont()); int fSeparatorWidth= gc.getAdvanceWidth('-'); String separatorLabel= PropertyPageMessages.JavaBreakpointConditionEditor_historySeparator; int fMessageLength= gc.textExtent(separatorLabel).x; gc.dispose(); StringBuffer dashes= new StringBuffer(); int chars= (((width - fMessageLength) / fSeparatorWidth) / 2) - 2; for (int i= 0; i < chars; i++) { dashes.append('-'); } StringBuffer result= new StringBuffer(); result.append(dashes); result.append(" " + separatorLabel + " "); //$NON-NLS-1$//$NON-NLS-2$ result.append(dashes); return result.toString().trim(); } private void registerViewerUndoRedoActions() { if (!fViewer.getTextWidget().isFocusControl()) { return; } disposeViewerUndoRedoActions(); IUndoContext undoContext= getUndoContext(); if (undoContext != null) { fViewerUndoAction= new UndoActionHandler(fBreakpointsViewSite, getUndoContext()); PlatformUI.getWorkbench().getHelpSystem().setHelp(fViewerUndoAction, IAbstractTextEditorHelpContextIds.UNDO_ACTION); fViewerUndoAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_UNDO); fViewerRedoAction= new RedoActionHandler(fBreakpointsViewSite, getUndoContext()); PlatformUI.getWorkbench().getHelpSystem().setHelp(fViewerRedoAction, IAbstractTextEditorHelpContextIds.REDO_ACTION); fViewerRedoAction.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_REDO); } fBreakpointsViewSite.getActionBars().setGlobalActionHandler(ITextEditorActionConstants.UNDO, fViewerUndoAction); fBreakpointsViewSite.getActionBars().setGlobalActionHandler(ITextEditorActionConstants.REDO, fViewerRedoAction); fBreakpointsViewSite.getActionBars().updateActionBars(); } /** * Returns this editor's viewer's undo manager undo context. * * @return the undo context or <code>null</code> if not available * @since 3.1 */ private IUndoContext getUndoContext() { IUndoManager undoManager= ((ITextViewerExtension6)fViewer).getUndoManager(); if (undoManager instanceof IUndoManagerExtension) { return ((IUndoManagerExtension)undoManager).getUndoContext(); } return null; } private void checkIfUsedInBreakpointsView() { if (fBreakpointsViewSite != null) { return; } IWorkbenchWindow activeWorkbenchWindow= PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (activeWorkbenchWindow != null && activeWorkbenchWindow.getActivePage() != null && activeWorkbenchWindow.getActivePage().getActivePart() != null) { IWorkbenchPartSite site= activeWorkbenchWindow.getActivePage().getActivePart().getSite(); if ("org.eclipse.debug.ui.BreakpointView".equals(site.getId())) { //$NON-NLS-1$ fBreakpointsViewSite= (IViewSite)site; fViewUndoAction= fBreakpointsViewSite.getActionBars().getGlobalActionHandler(ITextEditorActionConstants.UNDO); fViewRedoAction= fBreakpointsViewSite.getActionBars().getGlobalActionHandler(ITextEditorActionConstants.REDO); } } } }