package com.gorillalogic.monkeyconsole.editors.utils; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.Date; import java.util.List; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceDialog; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; 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.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Link; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import org.eclipse.swt.widgets.ToolTip; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.browser.IWebBrowser; import org.eclipse.ui.dialogs.PreferencesUtil; import org.eclipse.ui.forms.events.ExpansionEvent; import org.eclipse.ui.forms.events.IExpansionListener; import org.eclipse.ui.forms.widgets.Form; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ImageHyperlink; import org.eclipse.ui.forms.widgets.Section; import swing2swt.layout.BorderLayout; import swing2swt.layout.FlowLayout; import com.gorillalogic.cloud.ideversion.TaskConstants; import com.gorillalogic.monkeyconsole.editors.utils.devicematrixtable.tree.AndroidVersion; import com.gorillalogic.monkeyconsole.editors.utils.devicematrixtable.tree.DeviceMatrixTreeViewContentProvider; import com.gorillalogic.monkeyconsole.editors.utils.devicematrixtable.tree.DeviceMatrixTreeViewLableProvider; import com.gorillalogic.monkeyconsole.editors.utils.devicematrixtable.tree.DeviceMatrixTreeViewModel; import com.gorillalogic.monkeyconsole.editors.utils.devicematrixtable.tree.Resolution; import com.gorillalogic.monkeyconsole.plugin.FoneMonkeyPlugin; import com.gorillalogic.monkeyconsole.preferences.PreferenceConstants; public class RunInCloudDialog extends TitleAreaDialogStyledTextMessage { public IPreferenceStore preferenceStore; private Text apkFileNameText; private CheckboxTreeViewer deviceMatrixViewer; private String jobName; private String apkName; private String thinktime; private String timeout; private String jobType = TaskConstants.ANDROID; private List<String> deviceMatrixString; Button btnSelectAll; private Tree tree; Button btnBrowseForApp; private String scriptName = ""; Composite grpIos; Composite grpAndroid; private final FormToolkit formToolkit = new FormToolkit(Display.getDefault()); private Text usernameTXT; private Text passwordTXT; Label lblYourApk; Form form; Button radioAndroidDev; Button radioIosDev; Shell shellLocal; Section sctnAdvanced; private Text scriptNameTXT; private Text jobNameTXT; private Text thinktimeTXT; private Text timeoutTXT; Button btnSubmit; Composite mainContentPanel; Section sctnPicker; ToolTip tip; private final ViewerFilter iosOnlyDevOnly = new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { if (element instanceof AndroidVersion) { AndroidVersion ver = (AndroidVersion) element; if (ver.getName().contains("iOS")) { for (Resolution res : ver.getTodos()) { if (res.getParam().contains("(Device)")) { // if any params are device, return true return true; } } } } else if (element instanceof Resolution) { // only return true if device return ((Resolution) element).getParam().contains("(Device)"); } return false; } }; private final ViewerFilter androidOnlyDevOnly = new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { if (element instanceof AndroidVersion) { if (((AndroidVersion) element).getName().contains("iOS") || !((AndroidVersion) element).getName().contains("Android Device")) return false; else return true; } else { if (((AndroidVersion) parentElement).getName().contains("iOS")) return false; else return true; } } }; public RunInCloudDialog(Shell parentShell, String scriptName) { super(parentShell); this.scriptName = scriptName; } public String mineUserData() { return "username=" + this.preferenceStore.getString(PreferenceConstants.P_CLOUDUSR); } @Override public void create() { super.create(); // Set the title setTitle("Submit " + scriptName + " to CloudMonkey Appliance:"); // Set the message setMessage("The CloudMonkey Appliance runs your MonkeyTalk scripts across many devices." + " \n Upload your app and tests, and we'll do the rest." + " <a>Learn More</a>", IMessageProvider.INFORMATION); this.getMessageLabel().addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { if (event.text.equalsIgnoreCase("Learn More")) { IWebBrowser browser; try { CloudServices.logEventAsync( LoggedCloudEventTypes.RUNCLOUD_LEARN_MORE_PRESSED.toString(), mineUserData().toString(), new Date()); browser = PlatformUI.getWorkbench().getBrowserSupport() .createBrowser("Job 1"); browser.openURL(new URL(CloudServices.learnMoreUrl)); } catch (PartInitException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } setReturnCode(CANCEL); close(); } else if (event.text.equalsIgnoreCase("Preferences")) { PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(null, "com.gorillalogic.monkeyconsole.preferences.FonemonkeyPreferencePage", null, null); dialog.open(); } } }); } @Override protected Control createDialogArea(Composite parent) { preferenceStore = FoneMonkeyPlugin.getDefault().getPreferenceStore(); this.shellLocal = parent.getShell(); parent.getShell().setSize(570, 625); this.setHelpAvailable(false); parent.setLayout(new BorderLayout()); mainContentPanel = new Composite(parent, SWT.NONE); mainContentPanel.setLayoutData(BorderLayout.CENTER); mainContentPanel.setLayout(new BorderLayout(0, 0)); Composite composite_3 = new Composite(mainContentPanel, SWT.NONE); composite_3.setLayoutData(BorderLayout.NORTH); composite_3.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); radioAndroidDev = new Button(composite_3, SWT.RADIO); radioAndroidDev.setSelection(true); radioAndroidDev.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { form.setText("Android Job Submission"); lblYourApk.setText("Your apk:"); tip.setMessage("Enter the path to your MonkeyTalk-enabled application. " + "This is the .apk file stored in the bin folder of your Android project."); apkFileNameText.setText(preferenceStore.getString(PreferenceConstants.C_APKNAME)); btnSelectAll.setSelection(false); ViewerFilter[] l = deviceMatrixViewer.getFilters(); for (int i = 0; i < l.length; i++) { deviceMatrixViewer.removeFilter(l[i]); } deviceMatrixViewer.addFilter(androidOnlyDevOnly); // trick tree into populating all items deviceMatrixViewer.expandAll(); deviceMatrixViewer.collapseAll(); } }); radioAndroidDev.setText("Android Devices"); radioIosDev = new Button(composite_3, SWT.RADIO); radioIosDev.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { form.setText("iOS Job Submission"); lblYourApk.setText("Your app"); tip.setMessage("Enter the path to your MonkeyTalk-enabled application. " + "This is the \".ipa\" file that is created to deploy your app. " + "The app must be provisioned for the CloudMonkey devices and deployment."); apkFileNameText.setText(preferenceStore.getString(PreferenceConstants.C_APPNAME)); btnSelectAll.setSelection(false); ViewerFilter[] l = deviceMatrixViewer.getFilters(); for (int i = 0; i < l.length; i++) { deviceMatrixViewer.removeFilter(l[i]); } deviceMatrixViewer.addFilter(iosOnlyDevOnly); // trick tree into populating all items deviceMatrixViewer.expandAll(); deviceMatrixViewer.collapseAll(); } }); radioIosDev.setText("iOS Devices"); Composite acceptTermsPanel = new Composite(mainContentPanel, SWT.NONE); acceptTermsPanel.setLayoutData(BorderLayout.SOUTH); acceptTermsPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); Link link = new Link(acceptTermsPanel, SWT.NONE); link.setText("By submitting your tests to the CloudMonkey service,\nyou agree to accept the CloudMonkey <a>Terms of Service</a>"); link.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { IWebBrowser browser; try { browser = PlatformUI.getWorkbench().getBrowserSupport().createBrowser("Job 1"); browser.openURL(new URL(CloudServices.acceptTermsUrl)); } catch (PartInitException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } setReturnCode(CANCEL); close(); } }); form = formToolkit.createForm(mainContentPanel); form.setLayoutData(BorderLayout.CENTER); formToolkit.paintBordersFor(form); form.setText("Android Configuration"); sctnPicker = formToolkit .createSection(form.getBody(), Section.EXPANDED | Section.TITLE_BAR); sctnPicker.setBounds(0, 0, 570, 350); sctnPicker.setEnabled(true); formToolkit.paintBordersFor(sctnPicker); sctnPicker.setText("Picker"); Composite composite_5 = new Composite(sctnPicker, SWT.NONE); formToolkit.adapt(composite_5); formToolkit.paintBordersFor(composite_5); sctnPicker.setClient(composite_5); composite_5.setLayout(new BorderLayout(0, 0)); deviceMatrixViewer = new CheckboxTreeViewer(composite_5, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); deviceMatrixViewer.setContentProvider(new DeviceMatrixTreeViewContentProvider()); deviceMatrixViewer.setLabelProvider(new DeviceMatrixTreeViewLableProvider()); // Provide the input to the ContentProvider deviceMatrixViewer.setInput(new DeviceMatrixTreeViewModel()); // trick tree into populating all items deviceMatrixViewer.expandAll(); deviceMatrixViewer.collapseAll(); tree = (Tree) deviceMatrixViewer.getControl(); tree.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { TreeItem item = (TreeItem) e.item; item.setExpanded(true); if (item.getItemCount() > 0) { for (int y = 0; y < item.getItems().length; y++) { item.getItems()[y].setChecked(item.getChecked()); } } } }); deviceMatrixViewer.addFilter(androidOnlyDevOnly); formToolkit.adapt(tree); formToolkit.paintBordersFor(tree); btnSelectAll = new Button(composite_5, SWT.CHECK); btnSelectAll.setLayoutData(BorderLayout.SOUTH); formToolkit.adapt(btnSelectAll, true, true); btnSelectAll.setText("Select All"); btnSelectAll.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent theEvent) { boolean setChecked = ((Button) (theEvent.widget)).getSelection(); deviceMatrixViewer.expandAll(); for (int i = 0; i < tree.getItems().length; i++) { TreeItem item = tree.getItem(i); if (item.getData() instanceof AndroidVersion) { item.setChecked(setChecked); for (int y = 0; y < item.getItems().length; y++) { item.getItems()[y].setChecked(setChecked); } } } } }); Composite composite_7 = new Composite(composite_5, SWT.NONE); composite_7.setLayoutData(BorderLayout.NORTH); formToolkit.adapt(composite_7); formToolkit.paintBordersFor(composite_7); composite_7.setLayout(new GridLayout(4, false)); lblYourApk = new Label(composite_7, SWT.NONE); formToolkit.adapt(lblYourApk, true, true); lblYourApk.setText("Your APK"); apkFileNameText = new Text(composite_7, SWT.BORDER); GridData gd_text_6 = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1); gd_text_6.widthHint = 330; apkFileNameText.setLayoutData(gd_text_6); apkFileNameText.setText(preferenceStore.getString(PreferenceConstants.C_APKNAME)); formToolkit.adapt(apkFileNameText, true, true); btnBrowseForApp = new Button(composite_7, SWT.NONE); btnBrowseForApp.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { } }); formToolkit.adapt(btnBrowseForApp, true, true); btnBrowseForApp.setText("Browse..."); btnBrowseForApp.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { } public void widgetSelected(SelectionEvent e) { tip.setVisible(false); FileDialog dlg = new FileDialog(btnBrowseForApp.getShell(), SWT.OPEN); // Set the file extension filter based on Android/iOS selection String[] filterExtensions = new String[1]; if(radioIosDev.getSelection()) { filterExtensions[0] = "ipa"; } else { filterExtensions[0] = "apk"; } dlg.setFilterExtensions(filterExtensions); dlg.setText("Open"); String path = dlg.open(); if (path == null) return; apkFileNameText.setText(path); } }); ImageHyperlink browseHelpImage = new ImageHyperlink(composite_7, SWT.CENTER); // imageHyperLink.setBackgroundImage(section.getBackgroundImage()); browseHelpImage.setToolTipText("Click me for help"); browseHelpImage.setImage(JFaceResources.getImage(Dialog.DLG_IMG_HELP)); tip = new ToolTip(composite_7.getShell(), SWT.BALLOON); tip.setMessage("Enter the path to your MonkeyTalk-enabled application. This is the .apk file stored in the bin folder of your Android project."); browseHelpImage.addFocusListener(new FocusListener() { @Override public void focusGained(FocusEvent arg0) { } @Override public void focusLost(FocusEvent arg0) { tip.setVisible(false); } }); browseHelpImage.addMouseListener(new MouseListener() { @Override public void mouseDoubleClick(MouseEvent arg0) { } @Override public void mouseDown(MouseEvent arg0) { if (tip.isVisible()) { tip.setVisible(false); return; } Text actionWidget = (Text) apkFileNameText; Point loc = actionWidget.toDisplay(actionWidget.getLocation()); tip.setLocation(loc.x - actionWidget.getBorderWidth(), loc.y); tip.setVisible(true); } @Override public void mouseUp(MouseEvent arg0) { } }); sctnPicker.setExpanded(true); sctnPicker.redraw(); sctnAdvanced = formToolkit.createSection(form.getBody(), Section.TWISTIE | Section.TITLE_BAR); sctnAdvanced.setText("Advanced"); sctnAdvanced.addExpansionListener(new IExpansionListener() { public void expansionStateChanged(ExpansionEvent ee) { if (ee.getState()) { sctnPicker.setBounds(0, 0, 570, 200); sctnAdvanced.setBounds(0, 260, 570, 100); } else { sctnPicker.setBounds(0, 0, 570, 350); sctnAdvanced.setBounds(0, 350, 570, 25); } } public void expansionStateChanging(ExpansionEvent arg0) { } }); sctnAdvanced.setBounds(0, 350, 570, 25); formToolkit.paintBordersFor(sctnAdvanced); Composite composite_6 = new Composite(sctnAdvanced, SWT.NONE); formToolkit.adapt(composite_6); formToolkit.paintBordersFor(composite_6); sctnAdvanced.setClient(composite_6); composite_6.setLayout(new BorderLayout(0, 0)); Group grpCloudmonkeyJobPreferences = new Group(composite_6, SWT.NONE); grpCloudmonkeyJobPreferences.setLayoutData(BorderLayout.NORTH); grpCloudmonkeyJobPreferences.setText("CloudMonkey Job Preferences"); formToolkit.adapt(grpCloudmonkeyJobPreferences); formToolkit.paintBordersFor(grpCloudmonkeyJobPreferences); grpCloudmonkeyJobPreferences.setLayout(new GridLayout(4, false)); Label lblScriptToRun = new Label(grpCloudmonkeyJobPreferences, SWT.NONE); lblScriptToRun.setText("Script to Run:"); scriptNameTXT = new Text(grpCloudmonkeyJobPreferences, SWT.BORDER); scriptNameTXT.setText(scriptName); scriptNameTXT.setLayoutData(new GridData(100, 15)); formToolkit.adapt(scriptNameTXT, true, true); Label lblThinktime = new Label(grpCloudmonkeyJobPreferences, SWT.NONE); lblThinktime.setText("Thinktime:"); thinktimeTXT = new Text(grpCloudmonkeyJobPreferences, SWT.BORDER); thinktimeTXT.setText(FoneMonkeyPlugin.getDefault().getPreferenceStore() .getString(PreferenceConstants.P_THINKTIME)); thinktimeTXT.setLayoutData(new GridData(100, 15)); formToolkit.adapt(thinktimeTXT, true, true); Label lblJobName = new Label(grpCloudmonkeyJobPreferences, SWT.NONE); lblJobName.setText("Job Name:"); lblJobName.setVisible(false); jobNameTXT = new Text(grpCloudmonkeyJobPreferences, SWT.BORDER); jobNameTXT.setText(scriptName); jobNameTXT.setLayoutData(new GridData(100, 15)); jobNameTXT.setVisible(false); formToolkit.adapt(jobNameTXT, true, true); Label lblTimeout = new Label(grpCloudmonkeyJobPreferences, SWT.NONE); lblTimeout.setText("Timeout:"); timeoutTXT = new Text(grpCloudmonkeyJobPreferences, SWT.BORDER); timeoutTXT.setText(FoneMonkeyPlugin.getDefault().getPreferenceStore() .getString(PreferenceConstants.P_DEFAULTTIMEOUT)); timeoutTXT.setLayoutData(new GridData(100, 15)); formToolkit.adapt(timeoutTXT, true, true); Composite composite_1 = new Composite(parent, SWT.NONE); composite_1.setLayoutData(BorderLayout.SOUTH); composite_1.setLayout(new FlowLayout()); btnSubmit = new Button(composite_1, SWT.NONE); btnSubmit.setText("Submit to CloudMonkey"); btnSubmit.setData(new Integer(OK)); btnSubmit.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { if (isValidInput()) { okPressed(); } } }); Shell shell = parent.getShell(); if (shell != null) { shell.setDefaultButton(btnSubmit); } Button btnCancel = new Button(composite_1, SWT.NONE); btnCancel.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { } }); btnCancel.setText("Cancel"); btnCancel.setData(new Integer(CANCEL)); btnCancel.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { setReturnCode(CANCEL); close(); } }); parent.pack(); return parent; } @Override protected void createButtonsForButtonBar(Composite parent2) { // Don't do anything, we'll handle this in build contents because otherwise the layouts get // messy } private boolean isValidInput() { boolean valid = true; if (jobNameTXT.getText().length() == 0) { setErrorMessage("Please provide a Job Name"); valid = false; } if (deviceMatrixViewer.getCheckedElements().length == 0) { setErrorMessage("Please select at least one device to test on."); valid = false; } if (isOsConflict()) { setErrorMessage("Please select only iOS or Android configurations, not both"); valid = false; } if (apkFileNameText.getText().length() == 0) { setErrorMessage("Please provide a path to your application"); valid = false; } else if (!(new File(apkFileNameText.getText()).exists())) { setErrorMessage("The path to your applicaiton is invalid"); valid = false; } if (thinktimeTXT.getText().replaceAll("\\d+", "").length() > 0) { setErrorMessage("Default thinktime must be numeric"); valid = false; } if (timeoutTXT.getText().replaceAll("\\d+", "").length() > 0) { setErrorMessage("Default timeout must be numeric"); valid = false; } IPreferenceStore store = FoneMonkeyPlugin.getDefault().getPreferenceStore(); if (store.getString(PreferenceConstants.P_CLOUDUSR).trim().length() == 0 || store.getString(PreferenceConstants.P_CLOUDPASS).trim().length() == 0) { setErrorMessage("You have not provided a MonkeyCloud username and password in the MonkeyTalk <a>Preferences</a>."); valid = false; } return valid; } private boolean isOsConflict() { Object[] checked = deviceMatrixViewer.getCheckedElements(); boolean hasIos = false; boolean hasAndroid = false; for (int i = 0; i < checked.length; i++) { if (checked[i] instanceof Resolution) { Resolution a = (Resolution) checked[i]; String osVersion = a.getAndroidVersion(); if (osVersion != null && osVersion.startsWith(TaskConstants.IOS)) { hasIos = true; } else { hasAndroid = true; } } } return (hasIos && hasAndroid); } @Override protected boolean isResizable() { return true; } // Copy textFields because the UI gets disposed // and the Text Fields are not accessible any more. private void saveInput() { jobName = jobNameTXT.getText(); apkName = apkFileNameText.getText(); thinktime = thinktimeTXT.getText(); timeout = timeoutTXT.getText(); deviceMatrixString = new ArrayList<String>(); Object[] checked = deviceMatrixViewer.getCheckedElements(); for (int i = 0; i < checked.length; i++) { if (checked[i] instanceof Resolution) { Resolution a = (Resolution) checked[i]; deviceMatrixString.add(a.getParam()); String osVersion = a.getAndroidVersion(); if (osVersion != null && osVersion.startsWith(TaskConstants.IOS)) { jobType = TaskConstants.IOS; } } } if ((radioAndroidDev != null && radioAndroidDev.getSelection())) { FoneMonkeyPlugin.getDefault().getPreferenceStore() .setValue(PreferenceConstants.C_APKNAME, apkName); } if ((radioIosDev != null && radioIosDev.getSelection())) { FoneMonkeyPlugin.getDefault().getPreferenceStore() .setValue(PreferenceConstants.C_APPNAME, apkName); } if (usernameTXT != null) { FoneMonkeyPlugin.getDefault().getPreferenceStore() .setValue(PreferenceConstants.P_CLOUDUSR, usernameTXT.getText()); } if (passwordTXT != null) { FoneMonkeyPlugin.getDefault().getPreferenceStore() .setValue(PreferenceConstants.P_CLOUDPASS, passwordTXT.getText()); } } @Override protected void okPressed() { saveInput(); super.okPressed(); } public String getJobName() { return jobName; } public String getApkName() { return apkName; } public String getThinktime() { return thinktime; } public String getTimeout() { return timeout; } public List<String> getDeviceMatrixString() { return deviceMatrixString; } public String getJobType() { return jobType; } }