sysmodelmgr/com.symbian.smt.gui/src/com/symbian/smt/gui/smtwidgets/XmlFileSelectionDialog.java
changeset 0 522a326673b6
equal deleted inserted replaced
-1:000000000000 0:522a326673b6
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 package com.symbian.smt.gui.smtwidgets;
       
    17 
       
    18 import java.lang.reflect.InvocationTargetException;
       
    19 
       
    20 import org.eclipse.core.runtime.IProgressMonitor;
       
    21 import org.eclipse.jface.dialogs.Dialog;
       
    22 import org.eclipse.jface.dialogs.IDialogConstants;
       
    23 import org.eclipse.jface.dialogs.IInputValidator;
       
    24 import org.eclipse.jface.dialogs.MessageDialog;
       
    25 import org.eclipse.jface.dialogs.ProgressMonitorDialog;
       
    26 import org.eclipse.jface.operation.IRunnableWithProgress;
       
    27 import org.eclipse.jface.resource.StringConverter;
       
    28 import org.eclipse.swt.SWT;
       
    29 import org.eclipse.swt.events.ModifyEvent;
       
    30 import org.eclipse.swt.events.ModifyListener;
       
    31 import org.eclipse.swt.events.SelectionEvent;
       
    32 import org.eclipse.swt.events.SelectionListener;
       
    33 import org.eclipse.swt.layout.GridData;
       
    34 import org.eclipse.swt.layout.GridLayout;
       
    35 import org.eclipse.swt.widgets.Button;
       
    36 import org.eclipse.swt.widgets.Composite;
       
    37 import org.eclipse.swt.widgets.Control;
       
    38 import org.eclipse.swt.widgets.FileDialog;
       
    39 import org.eclipse.swt.widgets.Label;
       
    40 import org.eclipse.swt.widgets.Shell;
       
    41 import org.eclipse.swt.widgets.Text;
       
    42 import org.eclipse.ui.PlatformUI;
       
    43 
       
    44 /**
       
    45  * This dialog is adapted from Eclipse's InputDialog in order to accept the name
       
    46  * (local or URL) of an XML file. Validation of the XML also occurs.
       
    47  * 
       
    48  * @author barbararosi-schwartz
       
    49  * 
       
    50  */
       
    51 public class XmlFileSelectionDialog extends Dialog {
       
    52 
       
    53 	private static final String BROWSE_BUTTON = "Browse..."; //$NON-NLS-1$
       
    54 	private static final String EMPTY_STRING = ""; //$NON-NLS-1$
       
    55 
       
    56 	/**
       
    57 	 * Browse button widget.
       
    58 	 */
       
    59 	private Button browseButton;
       
    60 
       
    61 	/**
       
    62 	 * Cancel button widget.
       
    63 	 */
       
    64 	private Button cancelButton;
       
    65 
       
    66 	/**
       
    67 	 * Error message string.
       
    68 	 */
       
    69 	private String errorMessage;
       
    70 
       
    71 	/**
       
    72 	 * Error message label widget.
       
    73 	 */
       
    74 	private Text errorMessageText;
       
    75 
       
    76 	/**
       
    77 	 * The file extensions to filter on.
       
    78 	 */
       
    79 	private String[] extensionFilter;
       
    80 
       
    81 	/**
       
    82 	 * The message to display, or <code>null</code> if none.
       
    83 	 */
       
    84 	private String message;
       
    85 
       
    86 	/**
       
    87 	 * Ok button widget.
       
    88 	 */
       
    89 	private Button okButton;
       
    90 
       
    91 	/**
       
    92 	 * Input text widget.
       
    93 	 */
       
    94 	private Text inputText;
       
    95 
       
    96 	/**
       
    97 	 * The title of the dialog.
       
    98 	 */
       
    99 	private String title;
       
   100 
       
   101 	/**
       
   102 	 * The input m_validator, or <code>null</code> if none.
       
   103 	 */
       
   104 	private IXmlFileInputValidator validator;
       
   105 
       
   106 	/**
       
   107 	 * The input value; the empty string by default.
       
   108 	 */
       
   109 	private String inputValue = EMPTY_STRING;
       
   110 
       
   111 	/**
       
   112 	 * Creates an input dialog with OK and Cancel buttons. Note that the dialog
       
   113 	 * will have no visual representation (no widgets) until it is told to open.
       
   114 	 * <p>
       
   115 	 * Note that the <code>open</code> method blocks for input dialogs.
       
   116 	 * </p>
       
   117 	 * 
       
   118 	 * @param parentShell
       
   119 	 *            the parent shell, or <code>null</code> to create a top-level
       
   120 	 *            shell
       
   121 	 * @param dialogTitle
       
   122 	 *            the dialog title, or <code>null</code> if none
       
   123 	 * @param dialogMessage
       
   124 	 *            the dialog message, or <code>null</code> if none
       
   125 	 * @param initialValue
       
   126 	 *            the initial input value, or <code>null</code> if none
       
   127 	 *            (equivalent to the empty string)
       
   128 	 * @param extensionFilter
       
   129 	 *            the file extensions to filter on.
       
   130 	 * @param validator
       
   131 	 *            an input validator, or <code>null</code> if none
       
   132 	 */
       
   133 	public XmlFileSelectionDialog(Shell parentShell, String dialogTitle,
       
   134 			String dialogMessage, String initialValue,
       
   135 			String[] extensionFilter, IXmlFileInputValidator validator) {
       
   136 		super(parentShell);
       
   137 
       
   138 		this.title = dialogTitle;
       
   139 		message = dialogMessage;
       
   140 		this.extensionFilter = extensionFilter;
       
   141 
       
   142 		if (initialValue == null) {
       
   143 			inputValue = EMPTY_STRING;
       
   144 		} else {
       
   145 			inputValue = initialValue;
       
   146 		}
       
   147 
       
   148 		this.validator = validator;
       
   149 	}
       
   150 
       
   151 	/*
       
   152 	 * Method declared on Dialog.
       
   153 	 */
       
   154 	protected void buttonPressed(int buttonId) {
       
   155 		if (buttonId == IDialogConstants.OK_ID) {
       
   156 			inputValue = inputText.getText();
       
   157 		} else {
       
   158 			inputValue = null;
       
   159 		}
       
   160 
       
   161 		super.buttonPressed(buttonId);
       
   162 	}
       
   163 
       
   164 	/*
       
   165 	 * 
       
   166 	 * 
       
   167 	 * @see
       
   168 	 * org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets
       
   169 	 * .Shell)
       
   170 	 */
       
   171 	protected void configureShell(Shell shell) {
       
   172 		super.configureShell(shell);
       
   173 		if (title != null) {
       
   174 			shell.setText(title);
       
   175 		}
       
   176 	}
       
   177 
       
   178 	/*
       
   179 	 * 
       
   180 	 * 
       
   181 	 * @see
       
   182 	 * org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse
       
   183 	 * .swt.widgets.Composite)
       
   184 	 */
       
   185 	protected void createButtonsForButtonBar(Composite parent) {
       
   186 		// create OK and Cancel buttons by default
       
   187 		okButton = createButton(parent, IDialogConstants.OK_ID,
       
   188 				IDialogConstants.OK_LABEL, true);
       
   189 
       
   190 		cancelButton = createButton(parent, IDialogConstants.CANCEL_ID,
       
   191 				IDialogConstants.CANCEL_LABEL, false);
       
   192 
       
   193 		// do this here because setting the m_text will set enablement on the ok
       
   194 		// button
       
   195 		inputText.setFocus();
       
   196 		if (inputValue != null) {
       
   197 			inputText.setText(inputValue);
       
   198 			inputText.selectAll();
       
   199 		}
       
   200 	}
       
   201 
       
   202 	/*
       
   203 	 * Method declared on Dialog.
       
   204 	 */
       
   205 	protected Control createDialogArea(Composite parent) {
       
   206 		// create composite
       
   207 		Composite composite = (Composite) super.createDialogArea(parent);
       
   208 		GridLayout layout = (GridLayout) composite.getLayout();
       
   209 
       
   210 		layout.numColumns = 2;
       
   211 
       
   212 		// create message
       
   213 		if (message != null) {
       
   214 			Label label = new Label(composite, SWT.WRAP);
       
   215 			label.setText(message);
       
   216 
       
   217 			GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL,
       
   218 					GridData.VERTICAL_ALIGN_CENTER, true, true, 2, 1);
       
   219 
       
   220 			data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
       
   221 
       
   222 			label.setLayoutData(data);
       
   223 			label.setFont(parent.getFont());
       
   224 		}
       
   225 
       
   226 		inputText = new Text(composite, getInputTextStyle());
       
   227 
       
   228 		inputText.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL
       
   229 				| GridData.HORIZONTAL_ALIGN_FILL));
       
   230 		inputText.addModifyListener(new ModifyListener() {
       
   231 			public void modifyText(ModifyEvent e) {
       
   232 				validateInput();
       
   233 			}
       
   234 		});
       
   235 
       
   236 		browseButton = new Button(composite, SWT.PUSH);
       
   237 
       
   238 		browseButton.setText(BROWSE_BUTTON);
       
   239 		browseButton.addSelectionListener(new SelectionListener() {
       
   240 			public void widgetDefaultSelected(SelectionEvent event) {
       
   241 			}
       
   242 
       
   243 			public void widgetSelected(SelectionEvent event) {
       
   244 				FileDialog fd = new FileDialog(
       
   245 						PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), 
       
   246 						SWT.OPEN | SWT.APPLICATION_MODAL);
       
   247 				fd.setText("Select the desired resource file name");
       
   248 
       
   249 				if (extensionFilter != null) {
       
   250 					fd.setFilterExtensions(extensionFilter);
       
   251 				}
       
   252 
       
   253 				String selected = fd.open();
       
   254 
       
   255 				if (selected != null) {
       
   256 					inputText.setText(selected);
       
   257 				}
       
   258 			}
       
   259 		});
       
   260 
       
   261 		GridData gd = new GridData(GridData.GRAB_HORIZONTAL
       
   262 				| GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_VERTICAL
       
   263 				| GridData.VERTICAL_ALIGN_FILL);
       
   264 
       
   265 		gd.horizontalSpan = 2;
       
   266 		gd.minimumHeight = 40;
       
   267 		errorMessageText = new Text(composite, SWT.MULTI | SWT.READ_ONLY
       
   268 				| SWT.WRAP);
       
   269 
       
   270 		errorMessageText.setLayoutData(gd);
       
   271 		errorMessageText.setBackground(errorMessageText.getDisplay()
       
   272 				.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND));
       
   273 
       
   274 		// Set the error message text
       
   275 		setErrorMessage(errorMessage);
       
   276 
       
   277 		applyDialogFont(composite);
       
   278 		return composite;
       
   279 	}
       
   280 
       
   281 	/**
       
   282 	 * @return the cancelButton
       
   283 	 */
       
   284 	public Button getCancelButton() {
       
   285 		return cancelButton;
       
   286 	}
       
   287 
       
   288 	/**
       
   289 	 * Returns the style bits that should be used for the input text field.
       
   290 	 * Defaults to a single line entry. Subclasses may override.
       
   291 	 * 
       
   292 	 * @return the integer style bits that should be used when creating the
       
   293 	 *         input text
       
   294 	 */
       
   295 	protected int getInputTextStyle() {
       
   296 		return SWT.SINGLE | SWT.BORDER;
       
   297 	}
       
   298 
       
   299 	/**
       
   300 	 * Returns the ok button.
       
   301 	 * 
       
   302 	 * @return the ok button
       
   303 	 */
       
   304 	public Button getOkButton() {
       
   305 		return okButton;
       
   306 	}
       
   307 
       
   308 	/**
       
   309 	 * Returns the text area.
       
   310 	 * 
       
   311 	 * @return the text area
       
   312 	 */
       
   313 	public Text getText() {
       
   314 		return inputText;
       
   315 	}
       
   316 
       
   317 	/**
       
   318 	 * Returns the validator.
       
   319 	 * 
       
   320 	 * @return the validator
       
   321 	 */
       
   322 	protected IInputValidator getValidator() {
       
   323 		return validator;
       
   324 	}
       
   325 
       
   326 	/**
       
   327 	 * Returns the string typed into this input dialog.
       
   328 	 * 
       
   329 	 * @return the input string
       
   330 	 */
       
   331 	public String getValue() {
       
   332 		return inputValue;
       
   333 	}
       
   334 
       
   335 	/*
       
   336 	 * (non-Javadoc)
       
   337 	 * 
       
   338 	 * @see org.eclipse.jface.dialogs.Dialog#okPressed()
       
   339 	 */
       
   340 	@Override
       
   341 	protected void okPressed() {
       
   342 		IRunnableWithProgress op = new IRunnableWithProgress() {
       
   343 			String input = getValue();
       
   344 			String result;
       
   345 			
       
   346 			// Validation of the XML content does not happen here as an invalid XML
       
   347 			// file
       
   348 			// is deemed acceptable. It occurs as part of the update that takes
       
   349 			// place
       
   350 			// in the ManageResources class, which is also responsible for arranging
       
   351 			// for error markers to be placed on any invalid resource file or sys
       
   352 			// def file.
       
   353 			public void run(IProgressMonitor monitor) throws InvocationTargetException {
       
   354 				monitor.beginTask("Reading " + input, 2);
       
   355 				
       
   356 				try {
       
   357 					input = getValue();
       
   358 					
       
   359 					if (validator.isUrl(input)) {
       
   360 						result = validator.isUrlResourceReadable(input);
       
   361 					} else { // If file path is local
       
   362 						result = validator.isFileReadable(input);
       
   363 					}
       
   364 				} catch (InvalidPathException e) {
       
   365 					result = e.getMessage();
       
   366 				}
       
   367 
       
   368 				monitor.worked(1);
       
   369 				monitor.setTaskName("Checking validation");
       
   370 				setValidationError(result);
       
   371 				monitor.worked(1);
       
   372 				monitor.done();
       
   373 			}
       
   374 		};
       
   375 		
       
   376 		try {
       
   377 			new ProgressMonitorDialog(getShell()).run(true, false, op);
       
   378 		} catch (InterruptedException e) {
       
   379 			return;
       
   380 		} catch (InvocationTargetException e) {
       
   381 			Throwable realException = e.getTargetException();
       
   382 			MessageDialog.openError(getShell(), "Error", realException.getMessage());
       
   383 			return;
       
   384 		}
       
   385 		finally {
       
   386 			if (validationError != null) {
       
   387 				setErrorMessage(validationError);
       
   388 				setValidationError(null);
       
   389 				
       
   390 				return;
       
   391 			}
       
   392 		}
       
   393 		
       
   394 		super.okPressed();
       
   395 	}
       
   396 
       
   397 	private String validationError;
       
   398 	
       
   399 	private void setValidationError(String error) {
       
   400 		validationError = error;
       
   401 	}
       
   402 	
       
   403 	/**
       
   404 	 * Sets or clears the error message. If not <code>null</code>, the OK button
       
   405 	 * is disabled.
       
   406 	 * 
       
   407 	 * @param errorMessage
       
   408 	 *            the error message, or <code>null</code> to clear
       
   409 	 * @since 3.0
       
   410 	 */
       
   411 	public void setErrorMessage(String errorMessage) {
       
   412 		this.errorMessage = errorMessage;
       
   413 		if (errorMessageText != null && !errorMessageText.isDisposed()) {
       
   414 
       
   415 			errorMessageText
       
   416 					.setText(errorMessage == null ? "\n" : errorMessage); //$NON-NLS-1$
       
   417 
       
   418 			// Disable the error message text control if there is no error, or
       
   419 			// no error text (empty or whitespace only). Hide it also to avoid
       
   420 			// color change.
       
   421 			boolean hasError = errorMessage != null
       
   422 					&& (StringConverter.removeWhiteSpaces(errorMessage))
       
   423 							.length() > 0;
       
   424 			errorMessageText.setEnabled(hasError);
       
   425 			errorMessageText.setVisible(hasError);
       
   426 			errorMessageText.getParent().update();
       
   427 
       
   428 			// Access the ok button by id, in case clients have overridden
       
   429 			// button creation.
       
   430 			Control button = getButton(IDialogConstants.OK_ID);
       
   431 
       
   432 			if (button != null) {
       
   433 				button.setEnabled(errorMessage == null);
       
   434 			}
       
   435 		}
       
   436 	}
       
   437 
       
   438 	/**
       
   439 	 * Validates the input.
       
   440 	 * <p>
       
   441 	 * The default implementation of this framework method delegates the request
       
   442 	 * to the supplied input validator object; if it finds the input invalid,
       
   443 	 * the error message is displayed in the dialog's message line. This
       
   444 	 * hook method is called whenever the text changes in the input field.
       
   445 	 * </p>
       
   446 	 */
       
   447 	protected void validateInput() {
       
   448 		String errorMessage = null;
       
   449 		if (validator != null) {
       
   450 			errorMessage = validator.isValid(inputText.getText());
       
   451 		}
       
   452 		// It is important not to treat "" (blank error) the same as null
       
   453 		// (no error)
       
   454 		setErrorMessage(errorMessage);
       
   455 	}
       
   456 }