| /******************************************************************************* |
| * Copyright (c) 2016 Dirk Fauth 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: |
| * Dirk Fauth <dirk.fauth@googlemail.com> - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.nebula.widgets.nattable.ui; |
| |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.layout.GridDataFactory; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.layout.GridLayout; |
| 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; |
| |
| /** |
| * Dialog that can be used to show an error with an additional stacktrace. |
| * |
| * @since 1.5 |
| */ |
| public class ExceptionDialog extends Dialog { |
| |
| private static final Log LOG = LogFactory.getLog(ExceptionDialog.class); |
| |
| private String title; |
| private String message; |
| private Exception exception; |
| |
| private Button detailsButton; |
| private Text exceptionText; |
| |
| private boolean exceptionAreaCreated = false; |
| |
| protected ExceptionDialog(Shell parentShell, String title, String message, Exception exception) { |
| super(parentShell); |
| |
| this.title = title; |
| this.message = message != null ? message : exception.getLocalizedMessage(); |
| this.exception = exception; |
| } |
| |
| @Override |
| protected Control createDialogArea(Composite parent) { |
| Composite composite = new Composite(parent, SWT.NONE); |
| GridLayout layout = new GridLayout(); |
| layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); |
| layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); |
| layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); |
| layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); |
| layout.numColumns = 2; |
| composite.setLayout(layout); |
| GridDataFactory.fillDefaults().grab(true, false).applyTo(composite); |
| createMessageArea(composite); |
| |
| return composite; |
| } |
| |
| protected Control createMessageArea(Composite composite) { |
| // create composite |
| // create image |
| Image image = getParentShell().getDisplay().getSystemImage(SWT.ICON_ERROR); |
| Label imageLabel = new Label(composite, SWT.NULL); |
| image.setBackground(imageLabel.getBackground()); |
| imageLabel.setImage(image); |
| GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.BEGINNING).applyTo(imageLabel); |
| |
| // create message |
| if (this.message != null) { |
| Label messageLabel = new Label(composite, SWT.WRAP); |
| messageLabel.setText(this.message); |
| GridDataFactory |
| .fillDefaults() |
| .align(SWT.FILL, SWT.CENTER) |
| .grab(true, false) |
| .hint(convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH), SWT.DEFAULT) |
| .applyTo(messageLabel); |
| } |
| |
| return composite; |
| } |
| |
| @Override |
| protected void createButtonsForButtonBar(Composite parent) { |
| // create OK and Details buttons |
| createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); |
| if (this.exception != null) { |
| this.detailsButton = createButton(parent, IDialogConstants.DETAILS_ID, IDialogConstants.SHOW_DETAILS_LABEL, false); |
| } |
| } |
| |
| @Override |
| protected void buttonPressed(int id) { |
| if (id == IDialogConstants.DETAILS_ID) { |
| // was the details button pressed? |
| toggleDetailsArea(); |
| } else { |
| super.buttonPressed(id); |
| } |
| } |
| |
| private void toggleDetailsArea() { |
| boolean opened = false; |
| Point windowSize = getShell().getSize(); |
| if (this.exceptionAreaCreated) { |
| this.exceptionText.dispose(); |
| this.exceptionAreaCreated = false; |
| this.detailsButton.setText(IDialogConstants.SHOW_DETAILS_LABEL); |
| opened = false; |
| } else { |
| this.exceptionText = createExceptionText((Composite) getContents()); |
| this.detailsButton.setText(IDialogConstants.HIDE_DETAILS_LABEL); |
| getContents().getShell().layout(); |
| opened = true; |
| } |
| Point newSize = getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT); |
| int diffY = newSize.y - windowSize.y; |
| // increase the dialog height if details were opened and such increase |
| // is necessary |
| // decrease the dialog height if details were closed and empty space |
| // appeared |
| if ((opened && diffY > 0) || (!opened && diffY < 0)) { |
| getShell().setSize(new Point(windowSize.x, windowSize.y + (diffY))); |
| } |
| } |
| |
| private Text createExceptionText(Composite parent) { |
| Text exceptionText = new Text(parent, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); |
| GridDataFactory |
| .fillDefaults() |
| .grab(true, true) |
| .span(2, 1) |
| .applyTo(exceptionText); |
| |
| StringWriter sw = new StringWriter(); |
| PrintWriter pw = new PrintWriter(sw); |
| try { |
| this.exception.printStackTrace(pw); |
| exceptionText.setText(sw.toString()); |
| } finally { |
| try { |
| sw.close(); |
| pw.close(); |
| } catch (IOException e) { |
| LOG.error("Closing stream failed", e); //$NON-NLS-1$ |
| } |
| } |
| this.exceptionAreaCreated = true; |
| return exceptionText; |
| } |
| |
| /** |
| * Opens an error dialog to display the given error. |
| * |
| * @param parentShell |
| * the parent shell of the dialog, or <code>null</code> if none |
| * @param title |
| * the title to use for this dialog, or <code>null</code> to |
| * indicate that the default title should be used |
| * @param exception |
| * the error to show to the user |
| * @return the code of the button that was pressed that resulted in this |
| * dialog closing. This will be <code>Dialog.OK</code> if the OK |
| * button was pressed, or <code>Dialog.CANCEL</code> if this |
| * dialog's close window decoration or the ESC key was used. |
| */ |
| public static int open(Shell parentShell, String title, Exception exception) { |
| return open(parentShell, title, exception.getLocalizedMessage(), exception); |
| } |
| |
| /** |
| * Opens an error dialog to display the given error. |
| * |
| * @param parentShell |
| * the parent shell of the dialog, or <code>null</code> if none |
| * @param title |
| * the title to use for this dialog, or <code>null</code> to |
| * indicate that the default title should be used |
| * @param message |
| * the message to show in this dialog, or <code>null</code> to |
| * indicate that the error's message should be shown as the |
| * primary message |
| * @param exception |
| * the error to show to the user |
| * @return the code of the button that was pressed that resulted in this |
| * dialog closing. This will be <code>Dialog.OK</code> if the OK |
| * button was pressed, or <code>Dialog.CANCEL</code> if this |
| * dialog's close window decoration or the ESC key was used. |
| */ |
| public static int open(Shell parentShell, String title, String message, Exception exception) { |
| ExceptionDialog dialog = new ExceptionDialog(parentShell, title, message, exception); |
| return dialog.open(); |
| } |
| |
| @Override |
| protected boolean isResizable() { |
| return true; |
| } |
| |
| @Override |
| protected void configureShell(Shell newShell) { |
| super.configureShell(newShell); |
| newShell.setText(this.title); |
| newShell.setImage(getParentShell().getDisplay().getSystemImage(SWT.ICON_ERROR)); |
| } |
| } |