package org.eclipse.etrice.ui.behavior.dialogs;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.validation.IValidator;
import org.eclipse.core.databinding.validation.ValidationStatus;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.etrice.core.naming.RoomNameProvider;
import org.eclipse.etrice.core.room.ActorClass;
import org.eclipse.etrice.core.room.CPBranchTransition;
import org.eclipse.etrice.core.room.DetailCode;
import org.eclipse.etrice.core.room.ExternalPort;
import org.eclipse.etrice.core.room.Guard;
import org.eclipse.etrice.core.room.InitialTransition;
import org.eclipse.etrice.core.room.InterfaceItem;
import org.eclipse.etrice.core.room.Message;
import org.eclipse.etrice.core.room.MessageFromIf;
import org.eclipse.etrice.core.room.Port;
import org.eclipse.etrice.core.room.RoomFactory;
import org.eclipse.etrice.core.room.RoomPackage;
import org.eclipse.etrice.core.room.SPPRef;
import org.eclipse.etrice.core.room.ServiceImplementation;
import org.eclipse.etrice.core.room.StateGraph;
import org.eclipse.etrice.core.room.Transition;
import org.eclipse.etrice.core.room.Trigger;
import org.eclipse.etrice.core.room.TriggeredTransition;
import org.eclipse.etrice.ui.behavior.Activator;
import org.eclipse.etrice.ui.common.dialogs.AbstractPropertyDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
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.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.FormToolkit;
public class TransitionPropertyDialog extends AbstractPropertyDialog {
private class TriggerContentProvider implements IStructuredContentProvider {
@Override
public void dispose() {}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
@Override
public Object[] getElements(Object inputElement) {
if (trans instanceof TriggeredTransition) {
return ((TriggeredTransition) trans).getTriggers().toArray();
}
return new Object[] {};
}
}
private class TriggerLabelProvider extends LabelProvider implements
IBaseLabelProvider {
@Override
public String getText(Object element) {
if (element instanceof Trigger) {
Trigger trig = (Trigger) element;
return RoomNameProvider.getTriggerLabel(trig);
}
return super.getText(element);
}
}
private class MessageFromInterfaceContentProvider implements IStructuredContentProvider {
private Trigger currentTrigger = null;
@Override
public void dispose() {}
@Override
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
if (newInput instanceof Trigger)
currentTrigger = (Trigger) newInput;
}
@Override
public Object[] getElements(Object inputElement) {
if (inputElement instanceof Trigger) {
return ((Trigger) inputElement).getMsgFromIfPairs().toArray();
}
return new Object[] {};
}
public Trigger getCurrentTrigger() {
return currentTrigger;
}
}
private class MessageFromInterfaceLabelProvider extends LabelProvider implements
IBaseLabelProvider {
@Override
public String getText(Object element) {
if (element instanceof MessageFromIf) {
MessageFromIf mif = (MessageFromIf) element;
return RoomNameProvider.getMsgFromIfLabel(mif);
}
return super.getText(element);
}
}
class NameValidator implements IValidator {
@Override
public IStatus validate(Object value) {
if (value instanceof String) {
String name = (String) value;
if (name.isEmpty())
return ValidationStatus.error("name must not be empty");
for (Transition t : sg.getTransitions()) {
if (t!=trans && t.getName()!=null && t.getName().equals(name))
return ValidationStatus.error("name already used");
}
}
return Status.OK_STATUS;
}
}
private Transition trans;
private StateGraph sg;
private Combo messageCombo;
private Combo interfaceCombo;
private TableViewer mifViewer;
private ActorClass ac;
private List<InterfaceItem> interfaceItems = new ArrayList<InterfaceItem>();
private TableViewer triggerViewer;
private EList<Message> currentMsgs;
private DetailCodeToString m2s;
private StringToDetailCode s2m;
private Text guardText;
private Button removeMifButton;
public TransitionPropertyDialog(Shell shell, StateGraph sg, Transition trans) {
super(shell, "Edit Transition");
this.sg = sg;
this.trans = trans;
this.ac = getActorClass(sg);
m2s = new DetailCodeToString();
s2m = new StringToDetailCode();
collectInterfaceItems();
}
private void collectInterfaceItems() {
interfaceItems.addAll(ac.getIntPorts());
for (ExternalPort p : ac.getExtPorts()) {
interfaceItems.add(p.getIfport());
}
interfaceItems.addAll(ac.getStrSAPs());
for (ServiceImplementation svc : ac.getServiceImplementations()) {
interfaceItems.add(svc.getSpp());
}
}
private ActorClass getActorClass(StateGraph sg2) {
EObject obj = sg;
while (obj!=null) {
if (obj instanceof ActorClass) {
return (ActorClass) obj;
}
obj = obj.eContainer();
}
return null;
}
@Override
protected Image getImage() {
return Activator.getImage("icons/Behavior.gif");
}
@Override
protected void createContent(IManagedForm mform, Composite body,
DataBindingContext bindingContext) {
if (!(trans instanceof InitialTransition)) {
NameValidator nv = new NameValidator();
Text name = createText(body, "Name:", trans, RoomPackage.eINSTANCE.getTransition_Name(), nv);
createDecorator(name, "invalid name");
name.setFocus();
}
if (trans instanceof TriggeredTransition) {
FormToolkit toolkit = mform.getToolkit();
Label l = toolkit.createLabel(body, "Triggers:", SWT.NONE);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
l.setLayoutData(gd);
if (triggersAvailable()) {
createTriggerCompartment(body, toolkit);
addListeners();
triggerViewer.setSelection(new StructuredSelection(((TriggeredTransition) trans).getTriggers().get(0)), true);
}
else {
Label error = toolkit.createLabel(body, "No triggers available (interface item with incoming message missing).", SWT.NONE);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
error.setLayoutData(gd);
}
}
if (trans instanceof CPBranchTransition) {
Text cond = createText(body, "Condition:", trans, RoomPackage.eINSTANCE.getCPBranchTransition_Condition(), null, s2m, m2s, true);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.heightHint = 100;
cond.setLayoutData(gd);
}
{
Text action = createText(body, "Action Code:", trans, RoomPackage.eINSTANCE.getTransition_Action(), null, s2m, m2s, true);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.heightHint = 100;
action.setLayoutData(gd);
}
}
private boolean triggersAvailable() {
if (interfaceItems.isEmpty())
return false;
for (InterfaceItem item : interfaceItems) {
if (!getMessages(item).isEmpty())
return true;
}
return false;
}
private void createTriggerCompartment(Composite body, FormToolkit toolkit) {
Composite triggerCompartment = toolkit.createComposite(body);
triggerCompartment.setLayout(new GridLayout(3, false));
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
triggerCompartment.setLayoutData(gd);
createTriggerTable(triggerCompartment, toolkit);
createMifTable(triggerCompartment, toolkit);
createMifCompartment(triggerCompartment, toolkit);
}
private void createTriggerTable(Composite triggerCompartment, FormToolkit toolkit) {
Composite tableCompartment = toolkit.createComposite(triggerCompartment);
tableCompartment.setLayout(new GridLayout(2, false));
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
tableCompartment.setLayoutData(gd);
Table triggerTable = toolkit.createTable(tableCompartment, SWT.NONE | SWT.SINGLE);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.heightHint = 50;
gd.widthHint = 100;
gd.horizontalSpan = 2;
triggerTable.setLayoutData(gd);
triggerViewer = new TableViewer(triggerTable);
triggerViewer.setContentProvider(new TriggerContentProvider());
triggerViewer.setLabelProvider(new TriggerLabelProvider());
triggerViewer.setInput(trans);
if (((TriggeredTransition) trans).getTriggers().isEmpty())
addNewTrigger();
Button add = toolkit.createButton(tableCompartment, "Add", SWT.NONE);
gd = new GridData(GridData.FILL_HORIZONTAL);
add.setLayoutData(gd);
final Button remove = toolkit.createButton(tableCompartment, "Remove", SWT.NONE);
gd = new GridData(GridData.FILL_HORIZONTAL);
remove.setLayoutData(gd);
if (((TriggeredTransition) trans).getTriggers().size()==1)
remove.setEnabled(false);
add.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
addNewTrigger();
remove.setEnabled(true);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
remove.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
removeCurrentTrigger();
if (((TriggeredTransition) trans).getTriggers().size()==1)
remove.setEnabled(false);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
}
private void createMifTable(Composite triggerCompartment, FormToolkit toolkit) {
Composite tableCompartment = toolkit.createComposite(triggerCompartment);
tableCompartment.setLayout(new GridLayout(2, false));
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
tableCompartment.setLayoutData(gd);
Table mifTable = toolkit.createTable(tableCompartment, SWT.NONE | SWT.SINGLE);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.heightHint = 50;
gd.widthHint = 100;
gd.horizontalSpan = 2;
mifTable.setLayoutData(gd);
mifViewer = new TableViewer(mifTable);
mifViewer.setContentProvider(new MessageFromInterfaceContentProvider());
mifViewer.setLabelProvider(new MessageFromInterfaceLabelProvider());
Button add = toolkit.createButton(tableCompartment, "Add", SWT.NONE);
gd = new GridData(GridData.FILL_HORIZONTAL);
add.setLayoutData(gd);
removeMifButton = toolkit.createButton(tableCompartment, "Remove", SWT.NONE);
gd = new GridData(GridData.FILL_HORIZONTAL);
removeMifButton.setLayoutData(gd);
add.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
addNewMif();
removeMifButton.setEnabled(true);
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
removeMifButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
removeCurrentMif();
updateMifButton();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
}
private void updateMifButton() {
removeMifButton.setEnabled(mifViewer.getTable().getItemCount()>1);
}
private void createMifCompartment(Composite triggerCompartment, FormToolkit toolkit) {
Composite mifCompartment = toolkit.createComposite(triggerCompartment);
mifCompartment.setLayout(new GridLayout(2, false));
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
gd.verticalAlignment = SWT.BEGINNING;
mifCompartment.setLayoutData(gd);
createInterfaceCombo(mifCompartment, toolkit);
createMessageCombo(mifCompartment, toolkit);
Label l = toolkit.createLabel(mifCompartment, "Guard:", SWT.NONE);
l.setLayoutData(new GridData());
guardText = toolkit.createText(mifCompartment, "", SWT.BORDER | SWT.MULTI);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.heightHint = 50;
guardText.setLayoutData(gd);
}
private void createInterfaceCombo(Composite triggerCompartment,
FormToolkit toolkit) {
Label l = toolkit.createLabel(triggerCompartment, "Interface Item:", SWT.NONE);
l.setLayoutData(new GridData());
interfaceCombo = new Combo(triggerCompartment, SWT.READ_ONLY);
GridData gd = new GridData(GridData.FILL_HORIZONTAL);
interfaceCombo.setLayoutData(gd);
interfaceCombo.setVisibleItemCount(10);
toolkit.adapt(interfaceCombo, true, true);
for (InterfaceItem item : interfaceItems) {
interfaceCombo.add(item.getName());
}
}
private void createMessageCombo(Composite triggerCompartment, FormToolkit toolkit) {
Label l = toolkit.createLabel(triggerCompartment, "Message:", SWT.NONE);
l.setLayoutData(new GridData());
messageCombo = new Combo(triggerCompartment, SWT.READ_ONLY);
messageCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
messageCombo.setVisibleItemCount(10);
toolkit.adapt(messageCombo, true, true);
}
private void addListeners() {
triggerViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
updateMifAndGuard();
}
});
mifViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
updateCombos();
}
});
interfaceCombo.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
updateInterfaceItem();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
messageCombo.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
updateMessage();
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
widgetSelected(e);
}
});
guardText.addFocusListener(new FocusListener() {
@Override
public void focusLost(FocusEvent e) {
Object element = ((IStructuredSelection)triggerViewer.getSelection()).getFirstElement();
if (element instanceof Trigger) {
DetailCode dc = (DetailCode) s2m.convert(guardText.getText());
Guard guard = null;
if (dc!=null) {
guard = RoomFactory.eINSTANCE.createGuard();
guard.setGuard(dc);
}
((Trigger) element).setGuard(guard);
}
}
@Override
public void focusGained(FocusEvent e) {
}
});
}
private void updateMessage() {
String msgName = messageCombo.getItem(messageCombo.getSelectionIndex());
for (Message message : currentMsgs) {
if (msgName.equals(message.getName())) {
MessageFromIf mif = (MessageFromIf) ((IStructuredSelection)mifViewer.getSelection()).getFirstElement();
mif.setMessage(message);
break;
}
}
triggerViewer.refresh();
mifViewer.refresh();
}
private void updateInterfaceItem() {
String ifName = interfaceCombo.getItem(interfaceCombo.getSelectionIndex());
for (InterfaceItem item : interfaceItems) {
if (item.getName().equals(ifName)) {
MessageFromIf mif = (MessageFromIf) ((IStructuredSelection)mifViewer.getSelection()).getFirstElement();
mif.setFrom(item);
updateCombos();
break;
}
}
triggerViewer.refresh();
mifViewer.refresh();
}
private void updateCombos() {
messageCombo.removeAll();
if (mifViewer.getSelection() instanceof IStructuredSelection) {
Object sel = ((IStructuredSelection)mifViewer.getSelection()).getFirstElement();
if (sel instanceof MessageFromIf) {
MessageFromIf mif = (MessageFromIf) sel;
String[] items = interfaceCombo.getItems();
for (int i = 0; i < items.length; i++) {
if (items[i].equals(mif.getFrom().getName())) {
interfaceCombo.select(i);
currentMsgs = getMessages(mif.getFrom());
int pos = 0;
int idx = -1;
for (Message message : currentMsgs) {
messageCombo.add(message.getName());
if (message==mif.getMessage())
idx = pos;
++pos;
}
if (idx==-1) {
idx = 0;
mif.setMessage(currentMsgs.get(idx));
triggerViewer.refresh();
mifViewer.refresh();
}
messageCombo.select(idx);
break;
}
}
}
}
}
private EList<Message> getMessages(InterfaceItem item) {
boolean regular = true;
if (item instanceof Port) {
if (((Port)item).isConjugated())
regular = false;
}
else if (item instanceof SPPRef)
regular = false;
return regular? item.getProtocol().getIncomingMessages()
: item.getProtocol().getOutgoingMessages();
}
private void addNewTrigger() {
Trigger tri = RoomFactory.eINSTANCE.createTrigger();
EList<Trigger> triggers = ((TriggeredTransition) trans).getTriggers();
triggers.add(tri);
if (!interfaceItems.isEmpty()) {
MessageFromIf mif = createDefaultMif();
tri.getMsgFromIfPairs().add(mif);
}
triggerViewer.refresh();
triggerViewer.setSelection(new StructuredSelection(triggers.get(triggers.size()-1)), true);
}
private MessageFromIf createDefaultMif() {
MessageFromIf mif = RoomFactory.eINSTANCE.createMessageFromIf();
for (InterfaceItem item : interfaceItems) {
if (!getMessages(item).isEmpty()) {
mif.setFrom(item);
mif.setMessage(getMessages(item).get(0));
return mif;
}
}
return null;
}
private void removeCurrentTrigger() {
Object element = ((IStructuredSelection)triggerViewer.getSelection()).getFirstElement();
((TriggeredTransition) trans).getTriggers().remove(element);
triggerViewer.refresh();
triggerViewer.setSelection(new StructuredSelection(((TriggeredTransition) trans).getTriggers().get(0)), true);
}
private void addNewMif() {
Trigger trigger = ((MessageFromInterfaceContentProvider)mifViewer.getContentProvider()).getCurrentTrigger();
if (trigger!=null) {
MessageFromIf mif = createDefaultMif();
trigger.getMsgFromIfPairs().add(mif);
mifViewer.refresh();
triggerViewer.refresh();
mifViewer.setSelection(new StructuredSelection(mif), true);
}
}
private void removeCurrentMif() {
Object element = ((IStructuredSelection)mifViewer.getSelection()).getFirstElement();
Trigger trigger = ((MessageFromInterfaceContentProvider)mifViewer.getContentProvider()).getCurrentTrigger();
if (trigger!=null) {
trigger.getMsgFromIfPairs().remove(element);
mifViewer.refresh();
triggerViewer.refresh();
mifViewer.setSelection(new StructuredSelection(trigger.getMsgFromIfPairs().get(0)), true);
}
}
private void updateMifAndGuard() {
Object selected = ((IStructuredSelection) triggerViewer.getSelection()).getFirstElement();
mifViewer.setInput(selected);
updateMifButton();
if (selected instanceof Trigger) {
mifViewer.setSelection(new StructuredSelection(((Trigger)selected).getMsgFromIfPairs().get(0)), true);
Guard guard2 = ((Trigger) selected).getGuard();
String text = null;
if (guard2!=null)
text = (String) m2s.convert(guard2.getGuard());
if (text==null)
text = "";
guardText.setText(text);
}
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
if (!triggersAvailable())
getButton(IDialogConstants.OK_ID).setEnabled(false);
}
}