org.eclipse.nebula.widgets.nattable.edit.config.DialogErrorHandling.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.nebula.widgets.nattable.edit.config.DialogErrorHandling.java

Source

/*******************************************************************************
 * Copyright (c) 2012, 2013 Original authors 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:
 *     Original authors and others - initial API and implementation
 ******************************************************************************/
package org.eclipse.nebula.widgets.nattable.edit.config;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.nebula.widgets.nattable.Messages;
import org.eclipse.nebula.widgets.nattable.data.convert.ConversionFailedException;
import org.eclipse.nebula.widgets.nattable.data.validate.ValidationFailedException;
import org.eclipse.nebula.widgets.nattable.edit.editor.AbstractEditErrorHandler;
import org.eclipse.nebula.widgets.nattable.edit.editor.ICellEditor;
import org.eclipse.nebula.widgets.nattable.edit.editor.IEditErrorHandler;
import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer.MoveDirectionEnum;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

/**
 * Strategy class for conversion/validation failures.
 * If the entered value is not valid, a warning dialog with the corresponding error message
 * will show up. The warning dialog gives the opportunity to discard the invalid input or
 * change it, which will cause the editor to stay open. 
 * Only handles errors on commit.
 * 
 * @author Dirk Fauth
 */
public class DialogErrorHandling extends AbstractEditErrorHandler {

    /**
     * The {@link ICellEditor} for which this {@link DialogErrorHandling} is activated.
     * Needed so it is possible to operate on it dependent on the users choice.
     */
    protected ICellEditor editor;
    /**
     * Flag to configure if this dialog allows to commit invalid data.
     * This is necessary to implement cross validation in NatTable by using dialogs to
     * tell the user what is wrong.
     * By default this value is set to <code>false</code> as cross validation is not
     * the default validation use case.
     */
    protected boolean allowCommit = false;
    /**
     * The shell title that will be used if there is no conversion or validation shell title configured.
     */
    private String failureShellTitle = Messages.getString("DialogErrorHandlingStrategy.failureTitle"); //$NON-NLS-1$
    /**
     * The shell title that will be used in case this {@link DialogErrorHandling} is called to handle
     * a {@link ConversionFailedException}.
     */
    private String conversionFailureShellTitle = Messages
            .getString("DialogErrorHandlingStrategy.conversionFailureTitle"); //$NON-NLS-1$
    /**
     * The shell title that will be used in case this {@link DialogErrorHandling} is called to handle
     * a {@link ValidationFailedException}.
     */
    private String validationFailureShellTitle = Messages
            .getString("DialogErrorHandlingStrategy.validationFailureTitle"); //$NON-NLS-1$
    /**
     * The text on the button for changing the entered value.
     */
    private String changeButtonLabel = Messages.getString("DialogErrorHandlingStrategy.warningDialog.changeButton"); //$NON-NLS-1$
    /**
     * The text on the button to discard the entered value.
     */
    private String discardButtonLabel = Messages
            .getString("DialogErrorHandlingStrategy.warningDialog.discardButton"); //$NON-NLS-1$
    /**
     * The text on the button to commit the entered invalid value. Needed to support cross validation.
     */
    private String commitButtonLabel = Messages.getString("DialogErrorHandlingStrategy.warningDialog.commitButton"); //$NON-NLS-1$

    /**
     * Create a new {@link DialogErrorHandling} with no underlying {@link IEditErrorHandler}
     * that does not support cross validation.
     */
    public DialogErrorHandling() {
        this(null, false);
    }

    /**
     * Create a new {@link DialogErrorHandling} with no underlying {@link IEditErrorHandler}
     * that gives the opportunity to configure the error handling for cross validation.
     * @param allowCommit Flag to configure if this dialog allows to commit invalid data.
     *          If this parameter is set to <code>true</code>, an additional button for committing
     *          the invalid data will be provided within the dialog.
     */
    public DialogErrorHandling(boolean allowCommit) {
        this(null, allowCommit);

    }

    /**
     * Create a new {@link DialogErrorHandling} using the given {@link IEditErrorHandler} as
     * the underlying to allow chaining of error handling. Using this constructor there is
     * no cross validation support.
     * @param underlyingErrorHandler The underlying {@link IEditErrorHandler}
     */
    public DialogErrorHandling(IEditErrorHandler underlyingErrorHandler) {
        this(underlyingErrorHandler, false);
    }

    /**
     * Create a new {@link DialogErrorHandling} using the given {@link IEditErrorHandler} as
     * the underlying to allow chaining of error handling.
     * @param underlyingErrorHandler The underlying {@link IEditErrorHandler}
     * @param allowCommit Flag to configure if this dialog allows to commit invalid data.
     *          If this parameter is set to <code>true</code>, an additional button for committing
     *          the invalid data will be provided within the dialog.
     */
    public DialogErrorHandling(IEditErrorHandler underlyingErrorHandler, boolean allowCommit) {
        super(underlyingErrorHandler);
        this.allowCommit = allowCommit;
    }

    /**
     * {@inheritDoc}
     * After the error is handled by its underlying {@link IEditErrorHandler},
     * a dialog will be opened showing the error message to the user, giving the
     * opportunity to decide if the entered value should be discarded or if the
     * editor should stay open so the value can be modified.
     */
    @Override
    public void displayError(ICellEditor cellEditor, Exception e) {
        super.displayError(cellEditor, e);
        this.editor = cellEditor;

        String shellTitle = failureShellTitle;
        if (e instanceof ConversionFailedException && conversionFailureShellTitle != null) {
            shellTitle = conversionFailureShellTitle;
        } else if (e instanceof ValidationFailedException && validationFailureShellTitle != null) {
            shellTitle = validationFailureShellTitle;
        }
        showWarningDialog(e.getLocalizedMessage(), shellTitle);
    }

    /**
     * Shows a warning dialog if the conversion or the validation returned an error message.
     * Otherwise nothing happens.
     */
    protected void showWarningDialog(String dialogMessage, String dialogTitle) {
        if (!isWarningDialogActive()) {
            //conversion/validation failed - so open dialog with error message

            if (dialogMessage != null) {
                String[] buttonLabels = this.allowCommit
                        ? new String[] { changeButtonLabel, discardButtonLabel, commitButtonLabel }
                        : new String[] { changeButtonLabel, discardButtonLabel };
                MessageDialog warningDialog = new MessageDialog(Display.getCurrent().getActiveShell(), dialogTitle,
                        null, dialogMessage, MessageDialog.WARNING, buttonLabels, 0);

                //if discard was selected close the editor
                int returnCode = warningDialog.open();
                if (returnCode == 1) {
                    this.editor.close();
                }
                //if commit was selected, commit the value by skipping the validation
                else if (returnCode == 2) {
                    this.editor.commit(MoveDirectionEnum.NONE, true, true);
                }
            }
        }
    }

    /**
     * Checks if the current active Shell is a conversion/validation failure warning dialog.
     * As a Shell has not id it is checked if the Shell title is for conversion or validation
     * failure in localized format.
     * @return <code>true</code> if a warning dialog is active
     */
    protected boolean isWarningDialogActive() {
        //check if the current active shell is a conversion or validation failure warning dialog
        Shell control = Display.getCurrent().getActiveShell();
        if (control != null && (conversionFailureShellTitle.equals(control.getText())
                || validationFailureShellTitle.equals(control.getText())
                || failureShellTitle.equals(control.getText()))) {
            return true;
        }
        return false;
    }

    /**
     * @return The shell title that will be used if there is no conversion or validation shell 
     *          title configured.
     */
    public String getFailureShellTitle() {
        return failureShellTitle;
    }

    /**
     * @param failureShellTitle The shell title that should be used if there is no conversion or 
     *          validation shell title configured.
     */
    public void setFailureShellTitle(String failureShellTitle) {
        this.failureShellTitle = failureShellTitle;
    }

    /**
     * @return The shell title that will be used in case this {@link DialogErrorHandling} is called 
     *          to handle a {@link ConversionFailedException}.
     */
    public String getConversionFailureShellTitle() {
        return conversionFailureShellTitle;
    }

    /**
     * @param conversionFailureShellTitle The shell title that should be used in case this 
     *          {@link DialogErrorHandling} is called to handle a {@link ConversionFailedException}.
     */
    public void setConversionFailureShellTitle(String conversionFailureShellTitle) {
        this.conversionFailureShellTitle = conversionFailureShellTitle;
    }

    /**
     * @return The shell title that will be used in case this {@link DialogErrorHandling} is called to handle
     *          a {@link ValidationFailedException}.
     */
    public String getValidationFailureShellTitle() {
        return validationFailureShellTitle;
    }

    /**
     * @param validationFailureShellTitle The shell title that should be used in case this 
     *          {@link DialogErrorHandling} is called to handle a {@link ValidationFailedException}.
     */
    public void setValidationFailureShellTitle(String validationFailureShellTitle) {
        this.validationFailureShellTitle = validationFailureShellTitle;
    }

    /**
     * @return The text on the button for changing the entered value.
     */
    public String getChangeButtonLabel() {
        return changeButtonLabel;
    }

    /**
     * @param changeButtonLabel The text on the button for changing the entered value.
     */
    public void setChangeButtonLabel(String changeButtonLabel) {
        this.changeButtonLabel = changeButtonLabel;
    }

    /**
     * @return The text on the button to discard the entered value.
     */
    public String getDiscardButtonLabel() {
        return discardButtonLabel;
    }

    /**
     * @param discardButtonLabel The text on the button to discard the entered value.
     */
    public void setDiscardButtonLabel(String discardButtonLabel) {
        this.discardButtonLabel = discardButtonLabel;
    }

}