blob: f916efd8af17c371fd392a21ab7627347e9db4dc [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2011 IBM Corporation 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.jsdt.debug.internal.ui.launching;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.jface.preference.BooleanFieldEditor;
import org.eclipse.jface.preference.ComboFieldEditor;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.jface.preference.PreferenceStore;
import org.eclipse.jface.preference.StringFieldEditor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.wst.jsdt.debug.core.jsdi.connect.Connector;
import org.eclipse.wst.jsdt.debug.core.jsdi.connect.Connector.Argument;
import org.eclipse.wst.jsdt.debug.core.jsdi.connect.Connector.BooleanArgument;
import org.eclipse.wst.jsdt.debug.core.jsdi.connect.Connector.IntegerArgument;
import org.eclipse.wst.jsdt.debug.core.jsdi.connect.Connector.SelectedArgument;
import org.eclipse.wst.jsdt.debug.core.jsdi.connect.Connector.StringArgument;
import org.eclipse.wst.jsdt.debug.internal.core.JavaScriptDebugPlugin;
import org.eclipse.wst.jsdt.debug.internal.core.launching.ILaunchConstants;
import org.eclipse.wst.jsdt.debug.internal.ui.IHelpContextIds;
import org.eclipse.wst.jsdt.debug.internal.ui.ISharedImages;
import org.eclipse.wst.jsdt.debug.internal.ui.JavaScriptImageRegistry;
import org.eclipse.wst.jsdt.debug.internal.ui.Messages;
import org.eclipse.wst.jsdt.debug.internal.ui.SWTFactory;
/**
* Tab to allow connection information to be specified
*
* @since 1.0
*/
public class JavaScriptConnectTab extends AbstractLaunchConfigurationTab implements IPropertyChangeListener {
class ArgComparator implements Comparator {
/* (non-Javadoc)
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(Object o1, Object o2) {
if(o1 instanceof Entry && o2 instanceof Entry) {
//String > Integer > List > Boolean
//sort by kind and by label
Object val1 = ((Entry)o1).getValue();
Object val2 = ((Entry)o2).getValue();
if(val1 instanceof StringArgument) {
if(val2 instanceof StringArgument) {
return stripAccel(((Argument)val1).label()).compareTo(stripAccel(((Argument)val2).label()));
}
return -1;
}
else if(val1 instanceof IntegerArgument) {
if(val2 instanceof IntegerArgument) {
return stripAccel(((Argument)val1).label()).compareTo(stripAccel(((Argument)val2).label()));
}
else if(val2 instanceof StringArgument) {
return 1;
}
return -1;
}
else if(val1 instanceof SelectedArgument) {
if(val2 instanceof SelectedArgument) {
return stripAccel(((Argument)val1).label()).compareTo(stripAccel(((Argument)val2).label()));
}
else if(val2 instanceof StringArgument || val2 instanceof IntegerArgument) {
return 1;
}
return -1;
}
else if(val1 instanceof BooleanArgument) {
if(val2 instanceof BooleanArgument) {
return stripAccel(((Argument)val1).label()).compareTo(stripAccel(((Argument)val2).label()));
}
else if(val2 instanceof StringArgument || val2 instanceof IntegerArgument || val2 instanceof SelectedArgument) {
return 1;
}
return -1;
}
}
return o1.equals(o2) ? 0 : -1;
}
String stripAccel(String text) {
return text.replaceAll("\\&", ""); //$NON-NLS-1$ //$NON-NLS-2$
}
}
Text description = null;
Combo connectorcombo = null;
Connector selectedconnector = null;
Group argumentsgroup = null;
HashMap editormap = new HashMap();
Comparator comparator = new ArgComparator();
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
*/
public void createControl(Composite parent) {
Composite comp = SWTFactory.createComposite(parent, 1, 1, GridData.FILL_HORIZONTAL);
//connectors combo
Group group = SWTFactory.createGroup(comp, Messages.connector, 1, 1, GridData.FILL_HORIZONTAL);
this.connectorcombo = SWTFactory.createCombo(group, SWT.FLAT | SWT.BORDER | SWT.READ_ONLY, 1, null);
GridData gd = (GridData) this.connectorcombo.getLayoutData();
gd.grabExcessHorizontalSpace = true;
this.connectorcombo.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
handleConnectorSelected();
}
});
this.description = SWTFactory.createText(group, SWT.WRAP | SWT.READ_ONLY, 1);
gd = (GridData) this.description.getLayoutData();
gd.heightHint = 30;
//hack to make sure the disabled colour is propagated on *Nix's
this.description.setBackground(group.getBackground());
List connectors = JavaScriptDebugPlugin.getConnectionsManager().getConnectors();
Connector connector = null;
for (int i = 0; i < connectors.size(); i++) {
connector = (Connector)connectors.get(i);
this.connectorcombo.add(connector.name());
this.connectorcombo.setData(connector.name(), connector);
}
this.argumentsgroup = SWTFactory.createGroup(comp, Messages.connector_properties, 2, 1, GridData.FILL_HORIZONTAL);
this.argumentsgroup.setVisible(false);
PlatformUI.getWorkbench().getHelpSystem().setHelp(comp, IHelpContextIds.CONNECT_TAB);
setControl(comp);
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getHelpContextId()
*/
public String getHelpContextId() {
return IHelpContextIds.CONNECT_TAB;
};
/**
* Returns the {@link Connector} based on the selection of the combo
* @return the selected combo
*/
Connector getSelectedConnector() {
if(this.connectorcombo.getItemCount() > 0) {
int idx = this.connectorcombo.getSelectionIndex();
idx = (idx < 0 ? 0 : idx);
String name = this.connectorcombo.getItem(idx);
return (Connector) this.connectorcombo.getData(name);
}
return null;
}
/**
* Handles creating the UI for the connector selected
*/
void handleConnectorSelected() {
Connector connect = getSelectedConnector();
if(connect == null || connect.equals(this.selectedconnector)) {
//nothing changed
return;
}
this.selectedconnector = connect;
String desc = this.selectedconnector.description();
if(desc != null) {
this.description.setText(desc);
}
else {
this.description.setText(Messages.no_description_provided);
}
this.editormap.clear();
//get rid of the old controls
Control[] children = this.argumentsgroup.getChildren();
for (int i = 0; i < children.length; i++) {
children[i].dispose();
}
PreferenceStore store = new PreferenceStore();
Entry entry = null;
Argument argument = null;
FieldEditor editor = null;
String key = null;
ArrayList entries = new ArrayList(this.selectedconnector.defaultArguments().entrySet());
Collections.sort(entries, comparator);
for (Iterator iter = entries.iterator(); iter.hasNext();) {
entry = (Entry) iter.next();
key = (String) entry.getKey();
argument = (Argument) entry.getValue();
if(argument instanceof IntegerArgument) {
//create an int editor
store.setDefault(argument.name(), ((IntegerArgument)argument).intValue());
editor = new IntegerFieldEditor(argument.name(), argument.label(), this.argumentsgroup);
}
else if(argument instanceof BooleanArgument) {
//create boolean editor
store.setDefault(argument.name(), ((BooleanArgument)argument).booleanValue());
editor = new BooleanFieldEditor(argument.name(), argument.label(), this.argumentsgroup);
editor.fillIntoGrid(argumentsgroup, 2);
}
else if(argument instanceof StringArgument) {
//create String editor
store.setDefault(argument.name(), argument.value());
editor = new StringFieldEditor(argument.name(), argument.label(), this.argumentsgroup);
}
else if(argument instanceof SelectedArgument) {
//create list selection editor
List choices = ((SelectedArgument)argument).choices();
String[][] namesAndValues = new String[choices.size()][2];
int count = 0;
for (Iterator iter2 = choices.iterator(); iter2.hasNext();) {
String choice = (String)iter2.next();
namesAndValues[count][0] = choice;
namesAndValues[count][1] = choice;
count++;
}
store.setDefault(argument.name(), argument.value());
editor = new ComboFieldEditor(argument.name(), argument.label(), namesAndValues, this.argumentsgroup);
}
if(editor != null) {
editor.setPreferenceStore(store);
editor.loadDefault();
editor.setPropertyChangeListener(this);
this.editormap.put(key, editor);
editor = null;
}
}
//reset margins to undo FieldEditor bogosity
GridLayout gd = (GridLayout) this.argumentsgroup.getLayout();
gd.marginHeight = 5;
gd.marginWidth = 5;
gd.numColumns = 2;
this.argumentsgroup.getParent().layout(true);
this.argumentsgroup.setVisible(true);
this.argumentsgroup.layout(true);
updateLaunchConfigurationDialog();
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#isValid(org.eclipse.debug.core.ILaunchConfiguration)
*/
public boolean isValid(ILaunchConfiguration launchConfig) {
setErrorMessage(null);
Iterator keys = this.editormap.keySet().iterator();
Connector connector = getSelectedConnector();
if(connector == null) {
return false;
}
while (keys.hasNext()) {
String key = (String)keys.next();
Argument arg = (Argument)connector.defaultArguments().get(key);
FieldEditor editor = (FieldEditor)this.editormap.get(key);
if (editor instanceof StringFieldEditor) {
String value = ((StringFieldEditor)editor).getStringValue();
if (!arg.isValid(value)) {
setErrorMessage(NLS.bind(Messages.the_argument_0_is_not_valid, new String[] {arg.name()}));
return false;
}
}
else if (editor instanceof BooleanFieldEditor) {
boolean value = ((BooleanFieldEditor)editor).getBooleanValue();
if (!arg.isValid(String.valueOf(value))) {
setErrorMessage(NLS.bind(Messages.the_argument_0_is_not_valid, new String[] {arg.name()}));
return false;
}
}
else if (editor instanceof IntegerFieldEditor) {
int value = ((IntegerFieldEditor)editor).getIntValue();
if (!arg.isValid(String.valueOf(value))) {
setErrorMessage(NLS.bind(Messages.the_argument_0_is_not_valid, new String[] {arg.name()}));
return false;
}
}
else if(editor instanceof ComboFieldEditor) {
editor.store();
if (!arg.isValid(editor.getPreferenceStore().getString(key))) {
setErrorMessage(NLS.bind(Messages.the_argument_0_is_not_valid, new String[] {arg.name()}));
return false;
}
}
}
return true;
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
*/
public String getName() {
return Messages.connect;
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getImage()
*/
public Image getImage() {
return JavaScriptImageRegistry.getSharedImage(ISharedImages.IMG_CONNECT);
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
*/
public void initializeFrom(ILaunchConfiguration configuration) {
try {
String connectorid = configuration.getAttribute(ILaunchConstants.CONNECTOR_ID, (String)null);
if(connectorid != null) {
Connector connector = JavaScriptDebugPlugin.getConnectionsManager().getConnector(connectorid);
if(connector != null) {
int idx = this.connectorcombo.indexOf(connector.name());
if(idx > -1) {
this.connectorcombo.select(idx);
handleConnectorSelected();
Map argmap = configuration.getAttribute(ILaunchConstants.ARGUMENT_MAP, (Map)null);
if(argmap != null) {
Entry entry = null;
Argument argument = null;
String key = null;
FieldEditor editor = null;
for (Iterator iter = argmap.entrySet().iterator(); iter.hasNext();) {
entry = (Entry) iter.next();
key = (String) entry.getKey();
argument = (Argument) connector.defaultArguments().get(key);
editor = (FieldEditor)this.editormap.get(key);
if (argument != null && editor != null) {
String value = (String)argmap.get(key);
if (argument instanceof StringArgument || argument instanceof SelectedArgument) {
editor.getPreferenceStore().setValue(key, value);
}
else if (argument instanceof BooleanArgument) {
editor.getPreferenceStore().setValue(key, Boolean.valueOf(value).booleanValue());
}
else if (argument instanceof IntegerArgument) {
editor.getPreferenceStore().setValue(key, new Integer(value).intValue());
}
editor.load();
}
}
}
}
else {
this.connectorcombo.select(0);
handleConnectorSelected();
}
}
}
}
catch(CoreException ce) {
//ignore
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#performApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
*/
public void performApply(ILaunchConfigurationWorkingCopy configuration) {
Connector connector = getSelectedConnector();
if(connector != null) {
configuration.setAttribute(ILaunchConstants.CONNECTOR_ID, connector.id());
Entry entry = null;
FieldEditor editor = null;
String key = null;
HashMap argmap = new HashMap();
Argument argument = null;
for (Iterator iter = this.editormap.entrySet().iterator(); iter.hasNext();) {
entry = (Entry) iter.next();
editor = (FieldEditor) entry.getValue();
if(!editor.isValid()) {
return;
}
key = (String) entry.getKey();
argument = (Argument) connector.defaultArguments().get(key);
if(argument == null) {
continue;
}
editor.store();
if (argument instanceof StringArgument || argument instanceof SelectedArgument) {
argmap.put(key, editor.getPreferenceStore().getString(key));
}
else if (argument instanceof BooleanArgument) {
argmap.put(key, Boolean.valueOf(editor.getPreferenceStore().getBoolean(key)).toString());
}
else if (argument instanceof IntegerArgument) {
argmap.put(key, new Integer(editor.getPreferenceStore().getInt(key)).toString());
}
}
configuration.setAttribute(ILaunchConstants.ARGUMENT_MAP, argmap);
}
else {
configuration.removeAttribute(ILaunchConstants.ARGUMENT_MAP);
configuration.removeAttribute(ILaunchConstants.CONNECTOR_ID);
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.ILaunchConfigurationTab#setDefaults(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
*/
public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
List connectors = JavaScriptDebugPlugin.getConnectionsManager().getConnectors();
if(!connectors.isEmpty()) {
configuration.setAttribute(ILaunchConstants.CONNECTOR_ID, ((Connector)connectors.get(0)).id());
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent event) {
updateLaunchConfigurationDialog();
}
}