/*******************************************************************************
* This file is protected by Copyright.
* Please refer to the COPYRIGHT file distributed with this source distribution.
*
* This file is part of REDHAWK IDE.
*
* 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
*******************************************************************************/
package gov.redhawk.ide.graphiti.sad.ui.diagram.wizards;
import gov.redhawk.eclipsecorba.idl.IdlInterfaceDcl;
import gov.redhawk.ide.graphiti.sad.ui.images.SadWizardImages;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.databinding.wizard.WizardPageSupport;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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;
public class PortsWizardPage extends WizardPage {
// inner class model used to store user selections
public static class Model {
public static final String USES_PORT_NAMES = "usesPortNames";
public static final String PROVIDES_PORT_NAMES = "providesPortNames";
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private List<String> usesPortNames = new ArrayList<String>();
private List<String> providesPortNames = new ArrayList<String>();
public Model() {
}
public List<String> getUsesPortNames() {
return usesPortNames;
}
public void setUsesPortNames(List<String> usesPortNames) {
final List<String> oldValue = this.usesPortNames;
this.usesPortNames = usesPortNames;
this.pcs.firePropertyChange(new PropertyChangeEvent(this, Model.USES_PORT_NAMES, oldValue, usesPortNames));
}
public List<String> getProvidesPortNames() {
return providesPortNames;
}
public void setProvidesPortNames(List<String> providesPortNames) {
final List<String> oldValue = this.providesPortNames;
this.providesPortNames = providesPortNames;
this.pcs.firePropertyChange(new PropertyChangeEvent(this, Model.PROVIDES_PORT_NAMES, oldValue, providesPortNames));
}
public void addPropertyChangeListener(final PropertyChangeListener listener) {
this.pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(final PropertyChangeListener listener) {
this.pcs.removePropertyChangeListener(listener);
}
public boolean isComplete() {
return true;
}
};
private static final ImageDescriptor TITLE_IMAGE = null;
private Model model;
private DataBindingContext dbc;
private Button usesPortAddBtn, usesPortDeleteBtn, providesPortAddBtn, providesPortDeleteBtn;
private Text usesPortNameText, providesPortNameText;
private Image addImage;
private Image removeImage;
private org.eclipse.swt.widgets.List providesPortList;
private org.eclipse.swt.widgets.List usesPortList;
public PortsWizardPage() {
super("portWizardPage", "Identify Ports", TITLE_IMAGE);
this.setDescription("Enter the names of any uses and provides ports from the device you want to use");
model = new Model();
dbc = new DataBindingContext();
addImage = SadWizardImages.ADD.createImage();
removeImage = SadWizardImages.REMOVE.createImage();
}
public PortsWizardPage(List<String> providesPortNames, List<String> usesPortNames) {
this();
getModel().setUsesPortNames(usesPortNames);
getModel().setProvidesPortNames(providesPortNames);
}
@Override
public void createControl(Composite parent) {
WizardPageSupport.create(this, dbc);
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
composite.setLayout(new GridLayout(1, false));
// port group
final Group portOptions = new Group(composite, SWT.NONE);
portOptions.setLayout(new GridLayout(2, true));
portOptions.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
portOptions.setText("Port(s) to use for connections");
// provides port composite
final Composite providesPortComposite = createPortComposite(portOptions);
Label providesPortsLabel = new Label(providesPortComposite, SWT.NONE);
providesPortsLabel.setText("Provides Ports");
GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(providesPortsLabel);
// add provides port name text
providesPortNameText = addPortNameText(providesPortComposite, providesPortList);
providesPortNameText.setToolTipText("The specified provides port on the component will be located to make connections");
// add provides port "Add" button
providesPortAddBtn = new Button(providesPortComposite, SWT.PUSH);
providesPortAddBtn.setImage(addImage);
providesPortAddBtn.setToolTipText("Add new port to list");
//providesPortAddBtn.setText("Add Provides Port");
// add provides port list
providesPortList = addPortList(providesPortComposite, Model.PROVIDES_PORT_NAMES);
// add provides port "Delete" button
providesPortDeleteBtn = new Button(providesPortComposite, SWT.PUSH);
providesPortDeleteBtn.setImage(removeImage);
providesPortDeleteBtn.setToolTipText("Remove port from list");
//providesPortDeleteBtn.setText("Delete");
if (providesPortList.getItemCount() <= 0) {
providesPortDeleteBtn.setEnabled(false);
}
// add provides port listeners
providesPortAddBtn.addSelectionListener(getPortAddListener(providesPortList, providesPortNameText, providesPortDeleteBtn));
providesPortDeleteBtn.addSelectionListener(getPortDeleteListener(providesPortList, providesPortDeleteBtn));
// uses port composite
final Composite usesPortComposite = createPortComposite(portOptions);
Label usesPortsLabel = new Label(usesPortComposite, SWT.NONE);
usesPortsLabel.setText("Uses Ports");
GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(usesPortsLabel);
// add uses port name text
usesPortNameText = addPortNameText(usesPortComposite, usesPortList);
usesPortNameText.setToolTipText("The specified uses port on the component will be located to make connections");
// add uses port "Add" button
usesPortAddBtn = new Button(usesPortComposite, SWT.PUSH);
usesPortAddBtn.setImage(addImage);
usesPortAddBtn.setToolTipText("Add new port to list");
//usesPortAddBtn.setText("Add Uses Port");
// add uses port list
usesPortList = addPortList(usesPortComposite, Model.USES_PORT_NAMES);
// add uses port "Delete" button
usesPortDeleteBtn = new Button(usesPortComposite, SWT.PUSH);
usesPortDeleteBtn.setImage(removeImage);
usesPortDeleteBtn.setToolTipText("Remove port from list");
//usesPortDeleteBtn.setText("Delete");
if (usesPortList.getItemCount() <= 0) {
usesPortDeleteBtn.setEnabled(false);
}
// add uses port listeners
usesPortAddBtn.addSelectionListener(getPortAddListener(usesPortList, usesPortNameText, usesPortDeleteBtn));
usesPortDeleteBtn.addSelectionListener(getPortDeleteListener(usesPortList, usesPortDeleteBtn));
setControl(composite);
dbc.updateModels();
}
private Composite createPortComposite(Composite portOptions) {
final Composite composite = new Composite(portOptions, SWT.None);
composite.setLayout(new GridLayout(2, false));
composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
return composite;
}
private Text addPortNameText(Composite portComposite, final org.eclipse.swt.widgets.List portList) {
final Text portNameText = new Text(portComposite, SWT.BORDER);
GridData layoutData = new GridData(SWT.FILL, SWT.DEFAULT, true, true, 1, 1);
layoutData.minimumWidth = 200;
portNameText.setLayoutData(layoutData);
portNameText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
setErrorMessage(validateAll());
}
});
return portNameText;
}
private String validateAll() {
String err = null;
if (usesPortNameText != null) {
err = validPortNameText("Uses port", usesPortList, usesPortNameText);
if (err != null) {
return err;
}
}
if (providesPortNameText != null) {
err = validPortNameText("Provides port", providesPortList, providesPortNameText);
if (err != null) {
return err;
}
}
return null;
}
/**
* If returns null, that means the value is valid/has no spaces.
* Verifies string is unique
* @param valueType
* @param value
* @return
*/
public static String validPortNameText(String valueType, final org.eclipse.swt.widgets.List portList, Text valueText) {
if (valueText != null && valueText.getText().contains(" ")) {
return valueType + " must not include spaces";
}
//verify unique
if (portList != null) {
for (String portName: portList.getItems()) {
if (portName.equals(valueText.getText())) {
return valueType + " must be unique within the port list";
}
}
}
return null;
}
public static String validPortName(String valueType, String value) {
if (value.contains(" ")) {
return valueType + " must not include spaces";
}
return null;
}
private org.eclipse.swt.widgets.List addPortList(Composite portComposite, String propertyName) {
org.eclipse.swt.widgets.List portList = new org.eclipse.swt.widgets.List(portComposite, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL);
GridData listLayout = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
listLayout.heightHint = 80;
portList.setLayoutData(listLayout);
@SuppressWarnings("unchecked")
IObservableList< ? > modelObservableList = BeanProperties.list(model.getClass(), propertyName).observe(model);
dbc.bindList(WidgetProperties.items().observe(portList), modelObservableList);
return portList;
}
private SelectionListener getPortAddListener(final org.eclipse.swt.widgets.List portList, final Text portNameText, final Button deleteBtn) {
SelectionListener listener = new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
String err = validPortNameText("Port", portList, providesPortNameText);
if (err != null) {
return;
}
String portName = portNameText.getText();
if (portName != null && !portName.isEmpty() && !("").equals(portName)) {
portList.add(portName);
portNameText.setText("");
deleteBtn.setEnabled(true);
dbc.updateModels();
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
};
return listener;
}
private SelectionListener getPortDeleteListener(final org.eclipse.swt.widgets.List portList, final Button deleteBtn) {
SelectionListener listener = new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
String[] selections = portList.getSelection();
if (selections != null) {
for (String selection : selections) {
portList.remove(selection);
}
dbc.updateModels();
}
if (portList.getItemCount() <= 0) {
deleteBtn.setEnabled(false);
}
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
};
return listener;
}
/**
* Return true if interface extends PortSupplier interface
* @param idlInterfaceDcl
* @return
*/
public boolean extendsPortSupplier(IdlInterfaceDcl idlInterfaceDcl) {
if (idlInterfaceDcl.getInheritedInterfaces() != null) {
for (IdlInterfaceDcl inheritedInterface : idlInterfaceDcl.getInheritedInterfaces()) {
if (inheritedInterface.getRepId().startsWith("IDL:CF/PortSupplier") || extendsPortSupplier(inheritedInterface)) {
return true;
}
}
}
return false;
}
public Model getModel() {
return model;
}
@Override
public void dispose() {
removeImage.dispose();
addImage.dispose();
super.dispose();
}
}