package org.lejos.ev3.ldt.launch; import java.util.ArrayList; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.search.IJavaSearchScope; import org.eclipse.jdt.core.search.SearchEngine; import org.eclipse.jdt.debug.ui.launchConfigurations.JavaLaunchTab; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.jdt.ui.ISharedImages; import org.eclipse.jdt.ui.JavaElementLabelProvider; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; 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.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ElementListSelectionDialog; import org.lejos.ev3.ldt.LeJOSEV3Nature; import org.lejos.ev3.ldt.util.LeJOSEV3Util; public class LaunchEV3MainTab extends JavaLaunchTab { private static class LabelText { Label label; Text text; Color textBackground; public LabelText(Composite parent, String labelText, ModifyListener updater) { GridLayout gl = new GridLayout(2, false); Composite c = new Composite(parent, SWT.NONE); c.setFont(parent.getFont()); c.setLayout(gl); label = new Label(c, SWT.NONE); label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); label.setFont(c.getFont()); label.setText(labelText); GridData gd = new GridData(GridData.FILL_HORIZONTAL); gd.minimumWidth = 100; text = new Text(c, SWT.SINGLE | SWT.BORDER); text.setLayoutData(gd); text.setFont(c.getFont()); text.addModifyListener(updater); textBackground = text.getBackground(); } void setEnabled(boolean b) { this.label.setEnabled(b); this.text.setEditable(b); this.text.setBackground(b ? this.textBackground : this.label.getBackground()); } } private Text projectText; private Text mainClassText; private Button projectSearch; private Button mainClassSearch; private Button normalUseDefaults; private Button normalRun; private Button debugUseDefaults; private Button debugRun; private Button debugMonitorNormal; private Button targetUseDefaults; private Button targetConnectByName; private LabelText targetBrickName; private Button debugMonitorJdwp; private static IWorkspaceRoot getRoot() { return ResourcesPlugin.getWorkspace().getRoot(); } private static IJavaProject[] getLejosProjects() throws CoreException { IProject[] projects = getRoot().getProjects(); ArrayList<IJavaProject> projects2 = new ArrayList<IJavaProject>(); for (IProject p : projects) if (p.exists() && p.isOpen() && p.getProject().isNatureEnabled(LeJOSEV3Nature.ID)) projects2.add(JavaCore.create(p)); return projects2.toArray(new IJavaProject[projects2.size()]); } private void handleProjectButtonSelected() { ILabelProvider labelProvider= new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT); ElementListSelectionDialog dialog= new ElementListSelectionDialog(getShell(), labelProvider); dialog.setTitle("Select Project"); dialog.setMessage("Select a LeJOS Project"); try { dialog.setElements(getLejosProjects()); } catch (CoreException jme) { LeJOSEV3Util.log(jme); } IJavaProject javaProject= getJavaProject(); if (javaProject != null) dialog.setInitialSelections(new Object[] { javaProject }); if (dialog.open() == Window.OK) { IJavaProject project = (IJavaProject) dialog.getFirstResult(); projectText.setText(project.getElementName()); } } private IProject getProject() { String name = projectText.getText().trim(); if (name.length() <= 0) return null; return getRoot().getProject(name); } private IJavaProject getJavaProject() { return JavaCore.create(getProject()); } private void handleSearchButtonSelected() { IJavaProject project = getJavaProject(); IJavaElement[] elements; try { if (project != null && project.exists() && project.isOpen()) elements = new IJavaElement[] { project }; else elements = getLejosProjects(); } catch (CoreException e) { LeJOSEV3Util.log(e); elements = new IJavaElement[]{}; } int constraints = IJavaSearchScope.SOURCES; // constraints |= IJavaSearchScope.APPLICATION_LIBRARIES; IJavaSearchScope searchScope = SearchEngine.createJavaSearchScope(elements, constraints); MainMethodSearchHelper engine = new MainMethodSearchHelper(); ArrayList<IType> result = new ArrayList<IType>(); try { engine.searchMainMethods(getLaunchConfigurationDialog(), searchScope, result); } catch (CoreException e) { setErrorMessage(e.getMessage()); return; } catch (InterruptedException e) { setErrorMessage(e.getMessage()); return; } MainTypeSelectDialog mtsd = new MainTypeSelectDialog(getShell(), result, "Select Main Class"); IType type = mtsd.openAndGetResult(); if (type == null) return; projectText.setText(type.getJavaProject().getElementName()); mainClassText.setText(type.getFullyQualifiedName()); } private void createProjectEditor(Composite parent, ModifyListener updater) { Group g = newGroup(parent, 2, "&Project:"); Text t = new Text(g, SWT.SINGLE | SWT.BORDER); t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); t.setFont(g.getFont()); projectText = t; projectText.addModifyListener(updater); projectSearch = createPushButton(g, "&Browse...", null); projectSearch.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleProjectButtonSelected(); } }); } private void createMainTypeEditor(Composite parent, ModifyListener updater) { Group g = newGroup(parent, 2, "&Main Class:"); Text t = new Text(g, SWT.SINGLE | SWT.BORDER); t.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); t.setFont(g.getFont()); mainClassText = t; mainClassText.addModifyListener(updater); mainClassSearch = createPushButton(g, "&Search...", null); mainClassSearch.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleSearchButtonSelected(); } }); } @Override public Image getImage() { return JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_CLASS); } public String getName() { return "Main"; } public void createControl(Composite parent) { Composite comp = new Composite(parent, SWT.NONE); comp.setFont(parent.getFont()); GridLayout gl = new GridLayout(1, false); gl.verticalSpacing = 0; comp.setLayout(gl); GridData gd = new GridData(GridData.FILL_BOTH); gd.horizontalSpan = 1; comp.setLayoutData(gd); ModifyListener updater = new ModifyListener() { public void modifyText(ModifyEvent e) { //TODO display error, if project is not a leJOS project updateLaunchConfigurationDialog(); } }; SelectionListener updater2 = new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { updateLaunchConfigurationDialog(); updateEnabledDisabled(); } }; createProjectEditor(comp, updater); createVerticalSpacer(comp, 1); createMainTypeEditor(comp, updater); createVerticalSpacer(comp, 1); createOptionEditor(comp, updater, updater2); setControl(comp); } private void updateEnabledDisabled() { boolean e = !this.targetUseDefaults.getSelection(); this.targetConnectByName.setEnabled(e); this.targetBrickName.setEnabled(e); e = !this.normalUseDefaults.getSelection(); this.normalRun.setEnabled(e); e = !this.debugUseDefaults.getSelection(); this.debugRun.setEnabled(e); this.debugMonitorNormal.setEnabled(e); this.debugMonitorJdwp.setEnabled(e); } private Group newGroup(Composite p, int cols, String text) { Group g = new Group(p, SWT.NONE); g.setLayout(new GridLayout(cols, false)); g.setText(text); g.setFont(p.getFont()); GridData gd1 = new GridData(GridData.FILL_HORIZONTAL); g.setLayoutData(gd1); return g; } private void createOptionEditor(Composite parent, ModifyListener updater2, SelectionListener updater) { GridData gd = new GridData(); gd.horizontalSpan = 2; Group g = newGroup(parent, 2, "Target EV3:"); this.targetUseDefaults = createCheckButton(g, "Use &defaults from Preferences"); Composite c = new Composite(g, SWT.NONE); c.setLayout(new GridLayout(3, false)); c.setLayoutData(gd); this.targetConnectByName = createCheckButton(g, "Connect to name"); this.targetBrickName = new LabelText(g, "Name", updater2); this.targetUseDefaults.addSelectionListener(updater); this.targetConnectByName.addSelectionListener(updater); this.targetUseDefaults.setLayoutData(gd); createVerticalSpacer(parent, 1); g = newGroup(parent, 2, "When in run mode:"); this.normalUseDefaults = createCheckButton(g, "Use &defaults from Preferences"); this.normalRun = createCheckButton(g, "&Run program after upload"); this.normalUseDefaults.addSelectionListener(updater); this.normalRun.addSelectionListener(updater); this.normalUseDefaults.setLayoutData(gd); createVerticalSpacer(parent, 1); g = newGroup(parent, 2, "When in debug mode:"); this.debugUseDefaults = createCheckButton(g, "Use &defaults from Preferences"); this.debugRun = createCheckButton(g, "&Run program after upload"); this.debugUseDefaults.addSelectionListener(updater); this.debugRun.addSelectionListener(updater); this.debugUseDefaults.setLayoutData(gd); this.debugMonitorNormal = createRadioButton(g, "Normal Debug Monitor"); this.debugMonitorJdwp = createRadioButton(g, "Remote Debug Monitor (will start eclipse debugger)"); this.debugMonitorJdwp.setLayoutData(gd); this.debugMonitorNormal.addSelectionListener(updater); this.debugMonitorJdwp.addSelectionListener(updater); } public void setDefaults(ILaunchConfigurationWorkingCopy config) { IJavaElement context = getContext(); if (context != null) initializeJavaProject(context, config); else config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); if (context instanceof IMember) { IMember member = (IMember)context; if (member.isBinary()) context = member.getClassFile(); else context = member.getCompilationUnit(); } if (context instanceof ICompilationUnit || context instanceof IClassFile) { IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[]{ context }, false); ArrayList<IType> result = new ArrayList<IType>(); MainMethodSearchHelper helper = new MainMethodSearchHelper(); try { helper.searchMainMethods(getLaunchConfigurationDialog(), scope, result); } catch (InterruptedException e) { LeJOSEV3Util.log(e); } catch (CoreException e) { LeJOSEV3Util.log(e); } if (!result.isEmpty()) { // Simply grab the first main type found in the searched element IType mainType = result.get(0); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, mainType.getFullyQualifiedName()); // JDT uses mainType.getTypeQualifiedName('$'), but that is not consistent with the launch short cut String name = getLaunchConfigurationDialog().generateName(mainType.getTypeQualifiedName('.')); config.rename(name); } } } @Override public boolean isValid(ILaunchConfiguration config) { setErrorMessage(null); setMessage(null); String pname = projectText.getText().trim(); if (pname.length() <= 0) { setErrorMessage("Project not specified"); return false; } IWorkspace workspace = ResourcesPlugin.getWorkspace(); IStatus status = workspace.validateName(pname, IResource.PROJECT); if (!status.isOK()) { setErrorMessage("Illegal project name: "+pname); return false; } IProject project= workspace.getRoot().getProject(pname); if (!project.exists()) { setErrorMessage("Project "+pname+" does not exist"); return false; } if (!project.isOpen()) { setErrorMessage("Project "+pname+" is closed"); return false; } String mname = mainClassText.getText().trim(); if (mname.length() <= 0) { setErrorMessage("Main type not specified"); return false; } return true; } public void performApply(ILaunchConfigurationWorkingCopy config) { config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, projectText.getText().trim()); config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, mainClassText.getText().trim()); this.updateMappedResource(config); } private static IResource getMainResource(ILaunchConfiguration candidate) throws CoreException { String pname = candidate.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, ""); if (pname.length() > 0) { IProject project = getRoot().getProject(pname); String mname = candidate.getAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, ""); if (mname.length() > 0) { if (project != null && project.exists() && project.isOpen()) { IJavaProject jproject = JavaCore.create(project); if (jproject != null && jproject.exists() && jproject.isOpen()) { // replace $ with . for nested classes IType type = jproject.findType(mname.replace('$', '.')); if (type != null) { return type.getUnderlyingResource(); } } } } return project; } return null; } private void updateMappedResource(ILaunchConfigurationWorkingCopy config) { try { IResource resource = getMainResource(config); IResource[] resources; if (resource == null) resources = null; else resources = new IResource[] { resource }; config.setMappedResources(resources); } catch (CoreException ce) { setErrorMessage(ce.getMessage()); } } @Override public void initializeFrom(ILaunchConfiguration config) { super.initializeFrom(config); projectText.setText(extractConfigValue(config, IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, "")); mainClassText.setText(extractConfigValue(config, IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, "")); updateEnabledDisabled(); } private boolean extractConfigBool(ILaunchConfiguration config, String key, boolean def) { boolean r; try { r = config.getAttribute(key, def); } catch (CoreException ce) { setErrorMessage(ce.getMessage()); r = def; } return r; } private String extractConfigValue(ILaunchConfiguration config, String key, String def) { String r; try { r = config.getAttribute(key, def); } catch (CoreException ce) { setErrorMessage(ce.getMessage()); r = def; } return r; } }