/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Whole Platform is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.product.lw.launching; import static org.whole.product.lw.launching.IWholeOperationLauncherConstants.ENVIRONMENT; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; 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.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.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; import org.whole.lang.bindings.BindingManagerFactory; import org.whole.lang.bindings.IBindingScope; import org.whole.lang.model.IEntity; import org.whole.lang.reflect.DataKinds; import org.whole.lang.ui.util.UIUtils; import org.whole.lang.util.DataTypeUtils; /** * @author Enrico Persiani */ public class EnvironmentBlock extends AbstractBlock { protected IBindingScope scope; protected TableViewer environmentViewer; protected Button addButton; protected Button editButton; protected Button removeButton; public EnvironmentBlock(WholeOperationMainTab tab) { super("Arguments", tab); } protected void createContents(Composite composite) { composite.setLayoutData(new GridData(GridData.FILL_BOTH)); createEnvironmentViewer(composite); createEnvironmentViewerButtons(composite); } protected void createEnvironmentViewer(Composite composite) { environmentViewer = new TableViewer(composite, SWT.SINGLE); GridData gd = new GridData(GridData.FILL_BOTH); gd.widthHint = 300; environmentViewer.getControl().setLayoutData(gd); environmentViewer.setContentProvider(new EnvironmentContentProvider()); environmentViewer.setLabelProvider(new EnvironmentLabelProvider()); environmentViewer.setComparator(new ViewerComparator() { @Override public boolean isSorterProperty(Object element, String property) { return true; } }); Table table = environmentViewer.getTable(); TableLayout tableLayout = new TableLayout(); table.setLayout(tableLayout); table.setHeaderVisible(true); ColumnWeightData columnWeightData = new ColumnWeightData(20); tableLayout.addColumnData(columnWeightData); TableColumn tc = new TableColumn(table, SWT.NONE, 0); tc.setResizable(columnWeightData.resizable); tc.setText("Name"); columnWeightData = new ColumnWeightData(10); tableLayout.addColumnData(columnWeightData); tc = new TableColumn(table, SWT.NONE, 1); tc.setResizable(columnWeightData.resizable); tc.setText("Type"); columnWeightData = new ColumnWeightData(70); tableLayout.addColumnData(columnWeightData); tc = new TableColumn(table, SWT.NONE, 2); tc.setResizable(columnWeightData.resizable); tc.setText("Value"); } protected void createEnvironmentViewerButtons(Composite composite) { Composite buttonComposite = new Composite(composite, SWT.NONE); GridLayout glayout = new GridLayout(); glayout.marginHeight = 0; glayout.marginWidth = 0; glayout.numColumns = 1; GridData gdata = new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.HORIZONTAL_ALIGN_END); buttonComposite.setLayout(glayout); buttonComposite.setLayoutData(gdata); buttonComposite.setFont(composite.getFont()); addButton = createButton(buttonComposite, "Add ..."); editButton = createButton(buttonComposite, "Edit ..."); removeButton = createButton(buttonComposite, "Remove ..."); addButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { VariableDialog dialog = new VariableDialog(getTab().getControl().getShell(), "Add variable", "Add a new variable to the operation environment"); if (dialog.open() == Window.OK) { scope.wDef(dialog.getName(), dialog.getValue()); environmentViewer.refresh(); updateLaunchConfiguration(); } } }); editButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { IStructuredSelection structuredSelection = (IStructuredSelection) environmentViewer.getSelection(); String selectedVariableName = (String) ((Object[]) structuredSelection.getFirstElement())[0]; VariableDialog dialog = new VariableDialog(getTab().getControl().getShell(), "Edit variable", "Edit a variable in the operation environment", selectedVariableName, scope.wGet(selectedVariableName)); if (dialog.open() == Window.OK) { scope.wUnset(selectedVariableName); scope.wDef(dialog.getName(), dialog.getValue()); environmentViewer.refresh(); updateLaunchConfiguration(); } } }); removeButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent event) { IStructuredSelection structuredSelection = (IStructuredSelection) environmentViewer.getSelection(); String selectedVariableName = (String) ((Object[]) structuredSelection.getFirstElement())[0]; if (MessageDialog.openQuestion(getTab().getControl().getShell(), "Remove variable", "Are you sure you want to remove the variable '"+selectedVariableName+"'?")) { scope.wUnset(selectedVariableName); environmentViewer.refresh(); updateLaunchConfiguration(); } } }); // setup buttons enablement on selection uptade editButton.setEnabled(false); removeButton.setEnabled(false); environmentViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { boolean hasSelection = !event.getSelection().isEmpty(); editButton.setEnabled(hasSelection); removeButton.setEnabled(hasSelection); } }); } private Button createButton(Composite composite, String text) { Button button = new Button(composite, SWT.PUSH); button.setText(text); button.setFont(JFaceResources.getDialogFont()); int widthHint = UIUtils.getButtonWidthHint(composite); GridData gd = new GridData(); gd.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x); gd.horizontalAlignment = GridData.FILL; button.setLayoutData(gd); return button; } @Override public void initializeFrom(ILaunchConfiguration configuration) throws CoreException { scope = LaunchConfigurationUtils.loadBindingScope(configuration); environmentViewer.setInput(scope); } @Override public void performApply(ILaunchConfigurationWorkingCopy configuration) { LaunchConfigurationUtils.saveBindingScope(configuration, scope); } @Override public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { configuration.setAttribute(ENVIRONMENT, new HashMap<String, String>()); } protected class EnvironmentContentProvider implements IStructuredContentProvider { public Object[] getElements(Object inputElement) { IBindingScope scope = (IBindingScope) inputElement; Set<String> localNames = scope.wLocalNames(); int size = localNames.size(); Object[][] elements = new Object[size][2]; int index = 0; Iterator<String> iterator = localNames.iterator();; while (iterator.hasNext()) { String name = iterator.next(); elements[index][0] = name; elements[index++][1] = scope.wGet(name); } return elements; } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } } protected class EnvironmentLabelProvider extends LabelProvider implements ITableLabelProvider { public String getColumnText(Object element, int columnIndex) { String result = null; if (element != null) { Object[] pair = (Object[]) element; switch (columnIndex) { case 0: result = (String) pair[0]; break; case 1: result = DataTypeUtils.getDataKind((IEntity) pair[1]).toString(); break; case 2: result = ((IEntity) pair[1]).wStringValue(); break; } } return result; } @Override public String getText(Object element) { return getColumnText(element, 0); } public Image getColumnImage(Object element, int columnIndex) { return null; } } private static class VariableDialog extends Dialog { protected String name; protected IEntity value; protected Text nameText; protected Combo typeCombo; protected Text valueText; protected String title; protected String message; protected Label errorMessageLabel; public VariableDialog(Shell parentShell, String title, String message) { this(parentShell, title, message, null, null); } public VariableDialog(Shell parentShell, String title, String message, String initName, IEntity initValue) { super(parentShell); setShellStyle(getShellStyle() | SWT.SHELL_TRIM); initDefaults(initName, initValue); this.title = title; this.message = message; } public String getName() { return name; } public IEntity getValue() { return value; } protected void initDefaults(String initName, IEntity initValue) { name = initName != null ? initName : ""; value = initValue != null ? initValue : BindingManagerFactory.instance.createValue(""); } @Override protected void configureShell(Shell newShell) { super.configureShell(newShell); if (title != null) newShell.setText(title); } @Override protected Control createDialogArea(Composite parent) { Composite outerComposite = (Composite) super.createDialogArea(parent); GridData gridData = new GridData(GridData.FILL_HORIZONTAL); Label messageLabel = new Label(outerComposite, SWT.NONE); messageLabel.setText(message); messageLabel.setLayoutData(gridData); Composite innerComposite = new Composite(outerComposite, SWT.NONE); GridLayout layout = new GridLayout(2, false); innerComposite.setLayout(layout); gridData = new GridData(GridData.FILL_BOTH); innerComposite.setLayoutData(gridData); gridData = new GridData(GridData.FILL_HORIZONTAL); gridData.widthHint = 300; Label labelControl = new Label(innerComposite, SWT.NONE); labelControl.setText("Name:"); nameText = new Text(innerComposite, SWT.SINGLE | SWT.BORDER); nameText.setLayoutData(gridData); labelControl = new Label(innerComposite, SWT.NONE); labelControl.setText("Type:"); typeCombo = new Combo(innerComposite, SWT.NONE); typeCombo.setLayoutData(gridData); labelControl = new Label(innerComposite, SWT.NONE); labelControl.setText("Value:"); valueText = new Text(innerComposite, SWT.SINGLE | SWT.BORDER); valueText.setLayoutData(gridData); gridData = new GridData(GridData.FILL_HORIZONTAL); errorMessageLabel = new Label(outerComposite, SWT.NONE); errorMessageLabel.setLayoutData(gridData); configureControls(); applyDialogFont(outerComposite); return outerComposite; } @Override protected Control createContents(Composite parent) { Control control = super.createContents(parent); registerValidation(); return control; } private void configureControls() { nameText.setText(name); DataKinds[] values = DataKinds.values(); String[] items = new String[values.length - 3]; for (int i=0, j=0; i<values.length; i++) if (!values[i].isEnumValue() && !values[i].isObject() && !values[i].isNotAData()) items[j++] = values[i].toString(); typeCombo.setItems(items); typeCombo.setText(DataTypeUtils.getDataKind(value).toString()); valueText.setText(value.wStringValue()); } private void registerValidation() { nameText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { validate(); } }); typeCombo.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { validate(); } }); valueText.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { validate(); } }); validate(); } private void validate() { name = nameText.getText(); if (name.length() == 0) setErrorMessage("Invalid variable name"); else try { parseVariable(); setErrorMessage(null); } catch (Exception e) { setErrorMessage("Invalid value for type "+typeCombo.getText()); } } private void parseVariable() { IEntity newEntity = null; switch (DataKinds.valueOf(typeCombo.getText())) { case BOOLEAN: newEntity = BindingManagerFactory.instance.createValue(true); break; case BYTE: newEntity = BindingManagerFactory.instance.createValue((byte) 0); break; case SHORT: newEntity = BindingManagerFactory.instance.createValue((short) 0); break; case INT: newEntity = BindingManagerFactory.instance.createValue((int) 0); break; case LONG: newEntity = BindingManagerFactory.instance.createValue((long) 0); break; case DOUBLE: newEntity = BindingManagerFactory.instance.createValue(0.0); break; case FLOAT: newEntity = BindingManagerFactory.instance.createValue(0.0f); break; case DATE: newEntity = BindingManagerFactory.instance.createValue(new Date()); break; case CHAR: newEntity = BindingManagerFactory.instance.createValue(' '); break; case STRING: newEntity = BindingManagerFactory.instance.createValue(""); break; // case OBJECT: // case ENUM_VALUE: } newEntity.wSetValue(valueText.getText()); value = newEntity; } private void setErrorMessage(String errorMessage) { if (errorMessage == null) { errorMessageLabel.setText(""); getButton(IDialogConstants.OK_ID).setEnabled(true); } else { errorMessageLabel.setText(errorMessage); getButton(IDialogConstants.OK_ID).setEnabled(false); } } }; }