package io.sloeber.ui.core.launchconfig;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.internal.ui.SWTFactory;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.jface.viewers.LabelProvider;
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.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.Text;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import io.sloeber.core.api.LaunchConfiguration;
import io.sloeber.core.api.Sketch;
// SWTFactory is a restricted class. Nontheless it is very usefull.
@SuppressWarnings("restriction")
public class MainTab extends AbstractLaunchConfigurationTab {
Text project;
@Override
public void createControl(Composite parent) {
Composite comp = new Composite(parent, SWT.NONE);
setControl(comp);
comp.setLayout(new GridLayout(1, true));
comp.setFont(parent.getFont());
createProjectComponent(comp);
}
/**
* Creates the components to select a project.
*
* @param parent
* The parent composite
*/
private void createProjectComponent(Composite parent) {
Group group = SWTFactory.createGroup(parent, Messages.MainTab_Project, 2, 1, GridData.FILL_HORIZONTAL);
// Create text field
this.project = SWTFactory.createSingleText(group, 1);
this.project.addModifyListener(new ModifyListener() {
@SuppressWarnings("synthetic-access")
@Override
public void modifyText(ModifyEvent e) {
updateLaunchConfigurationDialog();
}
});
// Create browse button
createProjectSelectionButton(group, this.project);
}
/**
* Creates a button that will open a project selection dialog for Arduino
* projects. If a project has been selected via the button, the text field
* input will be changed accordingly.
*
* @param parent
* The parent composite
* @param text
* The text field that should adapt to the selected project
*/
private static void createProjectSelectionButton(Composite parent, Text text) {
Button browse = SWTFactory.createPushButton(parent, Messages.MainTab_browse, null);
browse.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
// Create a dialog with all projects in the workspace as
// possible selections.
ElementListSelectionDialog dialog = new ElementListSelectionDialog(parent.getShell(),
new LabelProvider() {
@Override
public String getText(Object element) {
IProject data = (IProject) element;
if (data != null) {
return data.getName();
}
return ""; //$NON-NLS-1$
}
});
dialog.setTitle(Messages.MainTab_ProjectSelection);
// Set the selectable elements of the dialog.
// A project may be closed
// so we use only open (accessible) projects as possible
// selection.
List<IProject> projects = new ArrayList<>();
for (IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
if (p.isAccessible() && Sketch.isSketch(p)) {
projects.add(p);
}
}
dialog.setElements(projects.toArray());
dialog.open();
// Get result from dialog and set text field value
Object[] results = dialog.getResult();
if (results != null && results.length > 0) {
IProject result = (IProject) results[0];
text.setText(result.getName());
}
}
});
}
/**
* Checks if the current input makes sense and set an error message
* accordingly.
*
* @return true if the input is valid. false otherwise
*/
private boolean checkConsistency() {
setErrorMessage(checkErrors());
return getErrorMessage() == null;
}
/**
* Checks if the current input makes sense and returns an error message
* accordingly.
*
* @return an appropriate error message or null if there is no error.
*/
private String checkErrors() {
// Project is specified
if (StringUtils.isBlank(this.project.getText())) {
return Messages.MainTab_SpecifyProject;
}
// Project exists
IProject proj = LaunchConfiguration.findProject(this.project.getText());
if (proj == null) {
return Messages.MainTab_ProjectDoesNotExist;
}
// Project has correct nature
if (!Sketch.isSketch(proj)) {
return Messages.MainTab_ProjectWrongType;
}
return null;
}
@Override
public String getName() {
return Messages.MainTab_Main;
}
@Override
public void initializeFrom(ILaunchConfiguration launchConfig) {
try {
this.project.setText(launchConfig.getAttribute(LaunchConfiguration.ATTR_PROJECT, "")); //$NON-NLS-1$
} catch (CoreException e) {
e.printStackTrace();
}
}
@Override
public void performApply(ILaunchConfigurationWorkingCopy launchConfig) {
launchConfig.setAttribute(LaunchConfiguration.ATTR_PROJECT, this.project.getText());
// Check the user input for consistency
checkConsistency();
}
@Override
public void setDefaults(ILaunchConfigurationWorkingCopy launchConfig) {
// We set default values via a LaunchShortcut
}
}