/******************************************************************************* * Copyright (c) 2012, 2016 Red Hat Inc. 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: * Rastislav Wagner (Red Hat) * Patrick Tasse - Remove dialog parent shell *******************************************************************************/ package org.eclipse.swtbot.generator.jdt.editor; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jdt.ui.PreferenceConstants; import org.eclipse.jdt.ui.text.JavaSourceViewerConfiguration; import org.eclipse.jdt.ui.text.JavaTextTools; import org.eclipse.jface.dialogs.TitleAreaDialog; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jface.text.source.VerticalRuler; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ComboViewer; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CTabFolder; import org.eclipse.swt.custom.CTabItem; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.layout.RowLayout; 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.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.swt.widgets.ToolItem; import org.eclipse.swtbot.generator.SWTBotGeneratorPlugin; import org.eclipse.swtbot.generator.framework.GenerationRule; import org.eclipse.swtbot.generator.framework.Generator; import org.eclipse.swtbot.generator.framework.IRecorderDialog; import org.eclipse.swtbot.generator.jdt.editor.document.ClassDocument; import org.eclipse.swtbot.generator.jdt.editor.listener.AnnotationSelectionListener; import org.eclipse.swtbot.generator.jdt.editor.listener.ClassAnnotationSelectionListener; import org.eclipse.swtbot.generator.jdt.editor.listener.MethodSelectionListener; import org.eclipse.swtbot.generator.ui.BotGeneratorEventDispatcher; import org.eclipse.swtbot.generator.ui.BotGeneratorEventDispatcher.CodeGenerationListener; import org.eclipse.ui.plugin.AbstractUIPlugin; public class JDTRecorderDialog extends TitleAreaDialog implements IRecorderDialog{ private BotGeneratorEventDispatcher recorder; private List<Generator> availableGenerators; private Map<CTabItem, SourceViewer> tabViewer; private Map<CTabItem, ToolBar> tabToolBar; private CTabFolder classTabFolder; private Button recordPauseButton; private MethodSelectionListener methodListener; private List<Shell> ignoredShells; public static final String ID = "org.eclipse.swtbot.generator.dialog.jdt"; //$NON-NLS-1$ private Image wizban; private Image icon; /** * Create the dialog. * */ public JDTRecorderDialog() { super(null); ignoredShells = new ArrayList<Shell>(); this.tabViewer = new HashMap<CTabItem, SourceViewer>(); setShellStyle(SWT.CLOSE | SWT.MODELESS | SWT.BORDER | SWT.TITLE | SWT.RESIZE | SWT.MAX); setBlockOnOpen(false); this.tabToolBar = new HashMap<CTabItem, ToolBar>(); } @Override public void create() { this.wizban = AbstractUIPlugin.imageDescriptorFromPlugin(SWTBotGeneratorPlugin.PLUGIN_ID, "icons/swtbot_rec64.png").createImage(); //$NON-NLS-1$ this.icon = AbstractUIPlugin.imageDescriptorFromPlugin(SWTBotGeneratorPlugin.PLUGIN_ID, "icons/swtbot_rec16.png").createImage(); //$NON-NLS-1$ super.create(); getShell().setImage(this.icon); getShell().setText("SWTBot Test Recorder"); setMessage("This dialog will track the generated code while you're recording your UI scenario."); setTitle("SWTBot Test Recorder"); setTitleImage(this.wizban); ignoredShells.add(getShell()); } /** * Create contents of the dialog. * * @param parent */ @Override protected Control createDialogArea(Composite parent) { Composite container = (Composite) super.createDialogArea(parent); container.setLayout(new GridLayout(1, false)); container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); Composite generatorSelectionContainer = new Composite(container,SWT.NONE); generatorSelectionContainer.setLayout(new GridLayout(2, false)); Label selectorLabel = new Label(generatorSelectionContainer, SWT.NONE); selectorLabel.setText("Target Bot API:"); selectorLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false,false)); ComboViewer generatorSelectionCombo = new ComboViewer(generatorSelectionContainer); generatorSelectionCombo.setContentProvider(new ArrayContentProvider()); generatorSelectionCombo.setLabelProvider(new LabelProvider() { @Override public String getText(Object o) { return ((Generator) o).getLabel(); } }); generatorSelectionCombo.setInput(this.availableGenerators); generatorSelectionCombo.setSelection(new StructuredSelection(this.recorder.getCurrentGenerator())); generatorSelectionCombo.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { Generator newGenerator = (Generator) ((IStructuredSelection) event.getSelection()).getFirstElement(); recorder.setGenerator(newGenerator); updateAnnotationToolBar(); Image image = newGenerator.getImage(); if(image != null){ image = new Image(Display.getDefault(), image.getImageData().scaledTo(80,80)); setTitleImage(image); } else { setTitleImage(null); } } }); classTabFolder = new CTabFolder(container, SWT.CLOSE |SWT.BORDER); classTabFolder.setUnselectedCloseVisible(false); classTabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,true)); ToolBar addClassToolbar = new ToolBar(classTabFolder, SWT.HORIZONTAL); classTabFolder.setTopRight(addClassToolbar); ToolItem addClassItem = new ToolItem(addClassToolbar, SWT.NONE); addClassItem.setText("+"); addClassItem.setToolTipText("Add class"); addClassItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { openClassShell(); } }); createTabItem(classTabFolder, "RecordedTestCase"); classTabFolder.addSelectionListener(new SelectionAdapter() { public void widgetSelected(org.eclipse.swt.events.SelectionEvent event) { SourceViewer viewer = tabViewer.get(classTabFolder.getSelection()); ClassDocument doc = (ClassDocument) viewer.getDocument(); if (doc.getActiveMethod() == null) { recorder.setRecording(false); recordPauseButton.setText("Start Recording"); } updateAnnotationToolBar(); } }); Composite actionsComposite = new Composite(container, SWT.NONE); actionsComposite.setLayout(new RowLayout(SWT.HORIZONTAL)); recordPauseButton = new Button(actionsComposite, SWT.PUSH); recordPauseButton.setText("Start Recording"); final Button copyButton = new Button(actionsComposite, SWT.PUSH); copyButton.setText("Copy"); recordPauseButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (recorder.isRecording()) { recorder.setRecording(false); recordPauseButton.setText("Start Recording"); } else { SourceViewer viewer = tabViewer.get(classTabFolder.getSelection()); ClassDocument doc = (ClassDocument) viewer.getDocument(); if(doc.getActiveMethod() == null){ openMethodShell(true); } else { recorder.setRecording(true); recordPauseButton.setText("Pause"); } } } }); this.recorder.addListener(new CodeGenerationListener() { public void handleCodeGenerated(GenerationRule code) { SourceViewer viewer = tabViewer.get(classTabFolder.getSelection()); ClassDocument doc = (ClassDocument) viewer.getDocument(); doc.addGenerationRule(code); viewer.setTopIndex(((ClassDocument) viewer.getDocument()).getLastOffset()-4); } }); copyButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { final Clipboard cb = new Clipboard(Display.getDefault()); TextTransfer textTransfer = TextTransfer.getInstance(); SourceViewer viewer = tabViewer.get(classTabFolder.getSelection()); cb.setContents(new Object[] { viewer.getDocument().get() }, new Transfer[] { textTransfer }); cb.dispose(); } }); return container; } private void createTabItem(final CTabFolder tabFolder, String text) { CTabItem tabItem = new CTabItem(tabFolder, SWT.NONE); tabItem.setText(text); Composite composite = new Composite(tabFolder, SWT.NONE); GridLayout gridLayout = new GridLayout(); composite.setLayout(gridLayout); composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); ToolBar toolBar = new ToolBar(composite, SWT.HORIZONTAL); tabToolBar.put(tabItem, toolBar); RowLayout rLayout = new RowLayout(); rLayout.fill = true; rLayout.justify = true; toolBar.setLayout(rLayout); ToolItem tItem = new ToolItem(toolBar, SWT.PUSH); tItem.setText("Add method"); ToolItem methodItemDropDown = new ToolItem(toolBar, SWT.DROP_DOWN); methodItemDropDown.setText("No active method"); ToolItem annotationsToolItem = new ToolItem(toolBar, SWT.DROP_DOWN); annotationsToolItem.setText("Method annotation"); ToolItem annotationsClassToolItem = new ToolItem(toolBar, SWT.DROP_DOWN); annotationsClassToolItem.setText("Class annotation"); methodListener = new MethodSelectionListener(methodItemDropDown, recorder,tabViewer,classTabFolder,annotationsToolItem); methodItemDropDown.addSelectionListener(methodListener); tItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent arg0) { openMethodShell(false); } }); // create editor with syntax coloring final ClassDocument doc = new ClassDocument( text, this.recorder.getCurrentGenerator().getLabel().toUpperCase().contains("SWTBOT") ? "org.eclipse.swtbot.eclipse.finder.SWTBotEclipseTestCase" : null); final SourceViewer generatedCode = new SourceViewer(composite, new VerticalRuler(0), SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER); JavaSourceViewerConfiguration javaConf = new JavaSourceViewerConfiguration(JavaUI.getColorManager(), PreferenceConstants.getPreferenceStore(), null, null); generatedCode.configure(javaConf); JavaTextTools tools = new JavaTextTools(PreferenceConstants.getPreferenceStore()); tools.setupJavaDocumentPartitioner(doc); generatedCode.setDocument(doc); generatedCode.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); generatedCode.setEditable(false); tabItem.setControl(composite); tabFolder.setSelection(tabItem); tabViewer.put(tabItem, generatedCode); doc.setViewer(generatedCode); final AnnotationSelectionListener listenerAnnot = new AnnotationSelectionListener(annotationsToolItem, recorder,tabViewer,classTabFolder); annotationsToolItem.addSelectionListener(listenerAnnot); annotationsToolItem.setData(listenerAnnot); final ClassAnnotationSelectionListener listenerClassAnnot = new ClassAnnotationSelectionListener(annotationsClassToolItem, recorder,tabViewer,classTabFolder); annotationsClassToolItem.addSelectionListener(listenerClassAnnot); annotationsClassToolItem.setData(listenerClassAnnot); listenerAnnot.update(); } private void openClassShell(){ final AddClassDialog d = new AddClassDialog(getShell()); this.getShell().getDisplay().asyncExec(new Runnable() { public void run() { if(Window.OK == d.open()){ String classText = d.getClassName(); createTabItem(classTabFolder, classText); recorder.setRecording(false); recordPauseButton.setText("Start Recording"); } } }); } private void openMethodShell(final boolean fromStartButton){ SourceViewer viewer = tabViewer.get(classTabFolder.getSelection()); final ClassDocument doc = (ClassDocument) viewer.getDocument(); final AddMethodDialog d = new AddMethodDialog(getShell(), doc.getMethods()); this.getShell().getDisplay().asyncExec(new Runnable() { public void run() { if(Window.OK == d.open()){ String methodText = d.getMethodName(); doc.addMethod(methodText); methodListener.add(methodText); if(fromStartButton){ recorder.setRecording(true); recordPauseButton.setText("Pause"); } updateAnnotationToolBar(); } } }); } @Override protected Point getInitialSize() { return new Point(585, 650); } @Override public void createButtonsForButtonBar(Composite parent) { // Override to remove default buttons } public BotGeneratorEventDispatcher getRecorder() { return recorder; } public void setRecorder(BotGeneratorEventDispatcher recorder) { this.recorder = recorder; } public List<Generator> getAvailableGenerators() { return availableGenerators; } public void setAvailableGenerators(List<Generator> availableGenerators) { this.availableGenerators = availableGenerators; } public List<Shell> getIgnoredShells() { return ignoredShells; } public String getName() { return "JDT Dialog"; } public String getId() { return ID; } public void setRecording(boolean record){ recorder.setRecording(record); if(record){ recordPauseButton.setText("Pause"); } else { recordPauseButton.setText("Start Recording"); } } public String getGeneratedCodeText(){ SourceViewer viewer = tabViewer.get(classTabFolder.getSelection()); ClassDocument doc = (ClassDocument) viewer.getDocument(); return doc.get(); } private void updateAnnotationToolBar(){ ToolBar activeToolBar = tabToolBar.get(classTabFolder.getSelection()); for(ToolItem item: activeToolBar.getItems()){ if(item.getData() instanceof AnnotationSelectionListener){ ((AnnotationSelectionListener)item.getData()).addItems(recorder.getCurrentGenerator().createAnnotationRules()); ((AnnotationSelectionListener)item.getData()).update(); } else if(item.getData() instanceof ClassAnnotationSelectionListener){ ((ClassAnnotationSelectionListener)item.getData()).addItems(recorder.getCurrentGenerator().createAnnotationRules()); ((ClassAnnotationSelectionListener)item.getData()).update(); } } } @Override public boolean close() { this.wizban.dispose(); this.icon.dispose(); return super.close(); } }