org.eclipse.jdt.internal.debug.ui.actions.ExpressionInputDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jdt.internal.debug.ui.actions.ExpressionInputDialog.java

Source

/*******************************************************************************
 *  Copyright (c) 2004, 2014 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 implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.debug.ui.actions;

import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.IHandler;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.internal.ui.SWTFactory;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.internal.debug.core.model.JDINullValue;
import org.eclipse.jdt.internal.debug.ui.IJavaDebugHelpContextIds;
import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
import org.eclipse.jdt.internal.debug.ui.JDISourceViewer;
import org.eclipse.jdt.internal.debug.ui.contentassist.CurrentFrameContext;
import org.eclipse.jdt.internal.debug.ui.contentassist.JavaDebugContentAssistProcessor;
import org.eclipse.jdt.internal.debug.ui.display.DisplayViewerConfiguration;
import org.eclipse.jdt.ui.text.IJavaPartitions;
import org.eclipse.jdt.ui.text.JavaTextTools;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.jface.resource.JFaceResources;
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.IUndoManager;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.TextViewerUndoManager;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.handlers.IHandlerActivation;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;

/**
 * A dialog which prompts the user to enter an expression for
 * evaluation.
 */
public class ExpressionInputDialog extends TrayDialog {

    protected IJavaVariable fVariable;
    protected String fResult = null;

    // Input area composite which acts as a placeholder for
    // input widgetry that is created/disposed dynamically.
    protected Composite fInputArea;
    // Source viewer widgets
    protected Composite fSourceViewerComposite;
    protected JDISourceViewer fSourceViewer;
    protected IContentAssistProcessor fCompletionProcessor;
    protected IDocumentListener fDocumentListener;
    protected IHandlerService fService;
    protected IHandlerActivation fActivation;
    //    protected HandlerSubmission fSubmission;
    // Text for error reporting
    protected Text fErrorText;

    /**
     * @param parentShell the shell to create the dialog in
     * @param variable the variable being edited
     */
    protected ExpressionInputDialog(Shell parentShell, IJavaVariable variable) {
        super(parentShell);
        setShellStyle(SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.RESIZE);
        fVariable = variable;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
     */
    @Override
    protected Control createDialogArea(Composite parent) {
        IWorkbench workbench = PlatformUI.getWorkbench();
        workbench.getHelpSystem().setHelp(parent, IJavaDebugHelpContextIds.EXPRESSION_INPUT_DIALOG);

        Composite composite = (Composite) super.createDialogArea(parent);

        // Create the composite which will hold the input widgetry
        fInputArea = createInputArea(composite);
        // Create the error reporting text area
        fErrorText = createErrorText(composite);
        // Create the source viewer after creating the error text so that any
        // necessary error messages can be set.
        populateInputArea(fInputArea);
        return composite;
    }

    /**
     * Returns the text widget for reporting errors
     * @param parent parent composite
     * @return the error text widget
     */
    protected Text createErrorText(Composite parent) {
        Text text = SWTFactory.createText(parent, SWT.READ_ONLY, 1, ""); //$NON-NLS-1$
        text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
        return text;
    }

    /**
     * Returns the composite that will be used to contain the
     * input widgetry.
     * @param composite the parent composite
     * @return the composite that will contain the input widgets
     */
    protected Composite createInputArea(Composite parent) {
        Composite composite = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, GridData.FILL_BOTH, 0, 0);
        Dialog.applyDialogFont(composite);
        return composite;
    }

    /**
     * Creates the appropriate widgetry in the input area. This
     * method is intended to be overridden by subclasses who wish
     * to use alternate input widgets.
     * @param parent parent composite
     */
    protected void populateInputArea(Composite parent) {
        fSourceViewerComposite = SWTFactory.createComposite(parent, parent.getFont(), 1, 1, GridData.FILL_BOTH, 0,
                0);

        String name = ActionMessages.ExpressionInputDialog_3;
        try {
            name = fVariable.getName();
        } catch (DebugException e) {
            JDIDebugUIPlugin.log(e);
        }

        SWTFactory.createWrapLabel(fSourceViewerComposite,
                NLS.bind(ActionMessages.ExpressionInputDialog_0, new String[] { name }), 1,
                convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH));

        fSourceViewer = new JDISourceViewer(fSourceViewerComposite, null, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
        fSourceViewer.setInput(fSourceViewerComposite);
        configureSourceViewer();
        fSourceViewer.doOperation(ITextOperationTarget.SELECT_ALL);
    }

    /**
     * Sets the visibility of the source viewer and the exclude attribute of its layout.
     * @param value If <code>true</code>, the viewer will be visible, if <code>false</code>, the viewer will be hidden.
     */
    protected void setSourceViewerVisible(boolean value) {
        if (fSourceViewerComposite != null) {
            fSourceViewerComposite.setVisible(value);
            GridData data = (GridData) fSourceViewerComposite.getLayoutData();
            data.exclude = !value;
            if (value) {
                fSourceViewer.getDocument().addDocumentListener(fDocumentListener);
                activateHandler();
            } else if (fActivation != null) {
                fSourceViewer.getDocument().removeDocumentListener(fDocumentListener);
                fService.deactivateHandler(fActivation);
            }
        }
    }

    /**
     * Initializes the source viewer. This method is based on code in BreakpointConditionEditor.
     */
    private void configureSourceViewer() {
        JavaTextTools tools = JDIDebugUIPlugin.getDefault().getJavaTextTools();
        IDocument document = new Document();
        tools.setupJavaDocumentPartitioner(document, IJavaPartitions.JAVA_PARTITIONING);
        fSourceViewer.configure(new DisplayViewerConfiguration() {
            @Override
            public IContentAssistProcessor getContentAssistantProcessor() {
                return getCompletionProcessor();
            }
        });
        fSourceViewer.setEditable(true);
        fSourceViewer.setDocument(document);
        final IUndoManager undoManager = new TextViewerUndoManager(10);
        fSourceViewer.setUndoManager(undoManager);
        undoManager.connect(fSourceViewer);

        fSourceViewer.getTextWidget().setFont(JFaceResources.getTextFont());

        Control control = fSourceViewer.getControl();
        GridData gd = new GridData(GridData.FILL_BOTH);
        control.setLayoutData(gd);

        gd = (GridData) fSourceViewer.getControl().getLayoutData();
        gd.heightHint = convertHeightInCharsToPixels(10);
        gd.widthHint = convertWidthInCharsToPixels(40);
        document.set(getInitialText(fVariable));

        fDocumentListener = new IDocumentListener() {
            public void documentAboutToBeChanged(DocumentEvent event) {
            }

            public void documentChanged(DocumentEvent event) {
                refreshValidState(fSourceViewer);
            }
        };
        fSourceViewer.getDocument().addDocumentListener(fDocumentListener);

        activateHandler();
    }

    /**
     * Activates the content assist handler.
     */
    private void activateHandler() {
        IHandler handler = new AbstractHandler() {
            public Object execute(ExecutionEvent event) throws org.eclipse.core.commands.ExecutionException {
                fSourceViewer.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
                return null;
            }
        };
        IWorkbench workbench = PlatformUI.getWorkbench();
        fService = (IHandlerService) workbench.getAdapter(IHandlerService.class);
        fActivation = fService.activateHandler(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS, handler);
    }

    /**
     * Returns the text that should be shown in the source viewer upon
     * initialization. The text should be presented in such a way that
     * it can be used as an evaluation expression which will return the
     * current value.
     * @param variable the variable
     * @return the initial text to display in the source viewer or <code>null</code>
     *  if none.
     */
    protected String getInitialText(IJavaVariable variable) {
        try {
            String signature = variable.getSignature();
            if (signature.equals("Ljava/lang/String;")) { //$NON-NLS-1$
                IValue value = variable.getValue();
                if (!(value instanceof JDINullValue)) {
                    String currentValue = value.getValueString();
                    StringBuffer buffer = new StringBuffer(currentValue.length());
                    buffer.append('"'); // Surround value in quotes
                    char[] chars = currentValue.toCharArray();
                    for (int i = 0; i < chars.length; i++) {
                        char c = chars[i];
                        if (c == '\b') {
                            buffer.append("\\b"); //$NON-NLS-1$
                        } else if (c == '\t') {
                            buffer.append("\\t"); //$NON-NLS-1$
                        } else if (c == '\n') {
                            buffer.append("\\n"); //$NON-NLS-1$
                        } else if (c == '\f') {
                            buffer.append("\\f"); //$NON-NLS-1$
                        } else if (c == '\r') {
                            buffer.append("\\r"); //$NON-NLS-1$
                        } else if (c == '"') {
                            buffer.append("\\\""); //$NON-NLS-1$
                        } else if (c == '\'') {
                            buffer.append("\\\'"); //$NON-NLS-1$
                        } else if (c == '\\') {
                            buffer.append("\\\\"); //$NON-NLS-1$
                        } else {
                            buffer.append(c);
                        }
                    }
                    buffer.append('"'); // Surround value in quotes
                    return buffer.toString();
                }
            }
        } catch (DebugException e) {
        }
        return null;
    }

    /**
    * Return the completion processor associated with this viewer.
    * @return DisplayConditionCompletionProcessor
    */
    protected IContentAssistProcessor getCompletionProcessor() {
        if (fCompletionProcessor == null) {
            fCompletionProcessor = new JavaDebugContentAssistProcessor(new CurrentFrameContext());
        }
        return fCompletionProcessor;
    }

    /**
     * @see org.eclipse.jface.preference.FieldEditor#refreshValidState()
     */
    protected void refreshValidState(TextViewer viewer) {
        String errorMessage = null;
        if (viewer != null) {
            String text = viewer.getDocument().get();
            boolean valid = text != null && text.trim().length() > 0;
            if (!valid) {
                errorMessage = ActionMessages.ExpressionInputDialog_1;
            }
        }
        setErrorMessage(errorMessage);
    }

    protected void refreshValidState() {
        refreshValidState(fSourceViewer);
    }

    /**
     * Sets the error message to display to the user. <code>null</code>
     * is the same as the empty string.
     * @param message the error message to display to the user or
     *  <code>null</code> if the error message should be cleared
     */
    protected void setErrorMessage(String message) {
        if (message == null) {
            message = ""; //$NON-NLS-1$
        }
        fErrorText.setText(message);
        getButton(IDialogConstants.OK_ID).setEnabled(message.length() == 0);
    }

    /**
     * Persist the dialog size and store the user's input on OK is pressed.
     */
    @Override
    protected void okPressed() {
        fResult = getText();
        super.okPressed();
    }

    /**
     * Returns the text that is currently displayed in the source viewer.
     * @return the text that is currently displayed in the source viewer
     */
    protected String getText() {
        return fSourceViewer.getDocument().get();
    }

    /**
     * Returns the text entered by the user or <code>null</code> if the user cancelled.
     * 
     * @return the text entered by the user or <code>null</code> if the user cancelled
     */
    public String getResult() {
        return fResult;
    }

    /**
     * Initializes the dialog shell with a title.
     */
    @Override
    protected void configureShell(Shell newShell) {
        super.configureShell(newShell);
        newShell.setText(ActionMessages.ExpressionInputDialog_2);
    }

    /**
     * Override method to initialize the enablement of the OK button after
     * it is created.
     */
    @Override
    protected void createButtonsForButtonBar(Composite parent) {
        super.createButtonsForButtonBar(parent);
        //do this here because setting the text will set enablement on the ok
        // button
        refreshValidState();
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.window.Window#close()
     */
    @Override
    public boolean close() {
        if (fActivation != null) {
            fService.deactivateHandler(fActivation);
        }
        if (fSourceViewer != null) {
            fSourceViewer.getDocument().removeDocumentListener(fDocumentListener);
            fSourceViewer.dispose();
            fSourceViewer = null;
        }
        if (fSourceViewerComposite != null) {
            fSourceViewerComposite.dispose();
            fSourceViewerComposite = null;
        }
        fDocumentListener = null;
        fCompletionProcessor = null;
        return super.close();
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.Dialog#getDialogBoundsSettings()
     */
    @Override
    protected IDialogSettings getDialogBoundsSettings() {
        IDialogSettings settings = JDIDebugUIPlugin.getDefault().getDialogSettings();
        IDialogSettings section = settings.getSection(getDialogSettingsSectionName());
        if (section == null) {
            section = settings.addNewSection(getDialogSettingsSectionName());
        }
        return section;
    }

    /**
     * @return the name to use to save the dialog settings
     */
    protected String getDialogSettingsSectionName() {
        return "EXPRESSION_INPUT_DIALOG"; //$NON-NLS-1$
    }
}