Re: [swtbot-dev] Workaround for Native Dialogs |
Hello co-testers, hello Ketan Padegaonkar, it's time to keep my promise and show you the code for the SWT replacements. I simply pasted them into the mail. You can use it under the same license terms, as SWTBot itself. If want the code in a more suitable form (zipped eclipse project...), drop me a mail. The first code is the core of this replacement - it is a static factory, that your application code can use to show dialogs. ===================== Code Listing NativeDialogFactory ====================================== /******************************************************************************* * Copyright (c) 2009 Jan Petranek. * 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 * *******************************************************************************/ import org.apache.log4j.Logger; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.MessageBox; import org.eclipse.swt.widgets.Shell; /** * The Class NativeDialogFactory is a configurable Dialog factory. * * By default, it handles user dialogs with native dialogs (SWT). * When the state is set to TESTING, it displays stand-in dialogs. * Those stand-ins may be way simpler than the native widgets, * but they are accessible by SWTBot. * * @author Jan Petranek */ public class NativeDialogFactory { /** The Log4j logger instance. */ static final Logger logger = Logger.getLogger(NativeDialogFactory.class); /** * The Enumeration DialogState, used to indicate the mode of operation. */ public enum OperationMode { /** The DEFAULT state, for normal operation. */ DEFAULT, /** The TESTING state, used to indicate SWTBot-Testing needs stand-in dialogs. */ TESTING }; /** The mode of operation. */ private static OperationMode mode = OperationMode.DEFAULT; /** * Sets the operation mode. * * @param state the desired operation mode */ public static void setMode(OperationMode mode) { NativeDialogFactory.mode = mode; } /** * Gets the operation mode. * * @return the current operation mode */ public static OperationMode getMode() { return mode; } /** * Shows a file selection dialog. * * In default mode, this displays a native file selection dialog. * In testing mode, a simple InputDialog is displayed, where the path can be entered as a String. * * @param shell the parent shell * @param text title for the file selection dialog * @param style the style of the file dialog, applies only to native dialogs (SWT.SAVE| SWT.OPEN | SWT.MULTI) * * @return a String with the selected file name. It is still up to the user to check, if the * filename is valid. When the user has aborted the file selection, this returns null. * */ public static String fileSelectionDialog(Shell shell, String text, int style) { switch (getMode()) { case DEFAULT: { // File standard dialog FileDialog fileDialog = new FileDialog(shell, style); fileDialog.setText(text); return fileDialog.open(); } case TESTING: { InputDialog fileDialog = new InputDialog(shell, text, "Select a file", "", new DummyInputValidator()); fileDialog.open(); return fileDialog.getValue(); } default: final String msg = "Reached default case in NativeDialogFactory.fileSelectionDialog, this is a bug, unknown state " + getMode(); logger.warn(msg); throw new RuntimeException(msg); } } /** * Show message box. * * In default mode, a native MessageBox is used. * In testing mode, we use a MessageDialog, showing the same title and message. * * @param messageText the text of the message * @param title the title * @param iconStyle the icon style * @param shell the parent shell */ public static void showMessageBox(Shell shell, String messageText, final String title, final int iconStyle) { if (shell == null) { logger .fatal("Shell not yet instantiated, cannot display error message"); } else { switch (getMode()) { case DEFAULT: { MessageBox messageBox = new MessageBox(shell, iconStyle); messageBox.setMessage(messageText); messageBox.setText(title); messageBox.open(); break; } case TESTING: { MessageDialog messagDialog = new MessageDialog(shell, title, null, messageText, iconStyle, new String[] { "OK" }, 0); messagDialog.open(); break; } default: final String msg = "Reached default case in NativeDialogFactory, this is a bug, unknown state " + getMode(); logger.warn(msg); throw new RuntimeException(msg); } } } } ================== END LISTING ============================================= Within the same package, I placed a basic Input validator, simply because the dialogs need one (100% SWT-Boilerplate code ;-) =================== LISTING DummyInputEvaluator ============================== import org.eclipse.jface.dialogs.IInputValidator; /** * The DummyInputValidator will accept any input. * * @author Jan Petranek * */ public class DummyInputValidator implements IInputValidator { /** * Always accepts the input. * * @param newText * text to accept * @return always returns null * @see org.eclipse.jface.dialogs.IInputValidator#isValid(java.lang.String) */ public String isValid(String newText) { return null; } } ================== END LISTING ============================================= The next snippet shows you how you can use the file selection dialog within your application code =================== LISTING SaveAsHandler ============================== public class SaveAsHandler extends AbstractHandler implements IHandler { public Object execute(ExecutionEvent event) throws ExecutionException { // File standard dialog String selected = NativeDialogFactory.fileSelectionDialog( SingletonHolder.getShell(), "Save as...", SWT.SAVE); if (selected == null) { logger.info("File selection aborted"); return null; } File file = new File(selected); // if the file exists, check for writeability if (!file.exists() || (file.exists() && file.canWrite())) { // whatever you do with the selected file ... ================== END LISTING ============================================= Last, but not least, a code snippet with the test code: =================== LISTING MyFirstTest ============================== @Test public void testSaveAsUsingMockDialog() throws Exception { // name of file where to save to String destinationFile = "/tmp/created.file"; // set the operation mode to testing NativeDialogFactory.setMode(NativeDialogFactory.OperationMode.TESTING); bot.menu("File").menu("Save As...").click(); // assert we see the Save As Dialog by checking the title: assertEquals("Dialog title for Save As Dialog", "Save as...", bot .activeShell().getText()); // enter the file name // our factory will use a simple dialog, where we can // set the file name into the text box bot.text().setText(destinationFile); // assert we see an "OK"-Button at position 0 and push it assertEquals("Button in File Dialog", "OK", bot.button(0).getText()); bot.button(0).click(); // check the message saying that our file was saved assertEquals("We should see a message saying the file was saved", "File saved", bot.activeShell().getText()); // assert we see an "OK"-Button at position 0 and push it assertEquals("Button in Message Dialog", "OK", bot.button(0).getText()); bot.button(0).click(); } ================== END LISTING ============================================= That's it for today, have a nice weekend, Jan Petranek