blob: 476d4430e40bcc966666a5e278974c5b390e6fe8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 protos software gmbh (http://www.protos.de).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* CONTRIBUTORS:
* Thomas Schuetz and Henrik Rentz-Reichert (initial contribution)
*
*******************************************************************************/
package org.eclipse.etrice.ui.structure.dialogs;
import java.util.ArrayList;
import java.util.Iterator;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.PojoObservables;
import org.eclipse.core.databinding.conversion.Converter;
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.ecore.EObject;
import org.eclipse.etrice.core.fsm.fSM.FSMPackage;
import org.eclipse.etrice.core.fsm.validation.FSMValidationUtilXtend.Result;
import org.eclipse.etrice.core.room.ActorClass;
import org.eclipse.etrice.core.room.ActorContainerClass;
import org.eclipse.etrice.core.room.CommunicationType;
import org.eclipse.etrice.core.room.CompoundProtocolClass;
import org.eclipse.etrice.core.room.ExternalPort;
import org.eclipse.etrice.core.room.GeneralProtocolClass;
import org.eclipse.etrice.core.room.Port;
import org.eclipse.etrice.core.room.ProtocolClass;
import org.eclipse.etrice.core.room.RoomFactory;
import org.eclipse.etrice.core.room.RoomPackage;
import org.eclipse.etrice.core.room.SubSystemClass;
import org.eclipse.etrice.ui.common.base.dialogs.AbstractPropertyDialog;
import org.eclipse.etrice.ui.structure.Activator;
import org.eclipse.etrice.ui.structure.support.SupportUtil;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
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.Text;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
@SuppressWarnings({"rawtypes", "unchecked", "deprecation"})
public class PortPropertyDialog extends AbstractPropertyDialog {
class NameValidator implements IValidator {
@Override
public IStatus validate(Object value) {
if (value instanceof String) {
String name = (String) value;
Result result = SupportUtil.getInstance().getValidationUtil().isUniqueName(port, name);
if (!result.isOk())
return ValidationStatus.error(result.getMsg());
}
return Status.OK_STATUS;
}
}
class ProtocolValidator implements IValidator {
@Override
public IStatus validate(Object value) {
if (value==null)
return ValidationStatus.error("select a protocol");
if (value instanceof CompoundProtocolClass)
if (!relay)
return ValidationStatus.error("compound protocol only possible for relay port");
return Status.OK_STATUS;
}
}
class MultiplicityValidator implements IValidator {
private boolean mayChange;
private int old;
private boolean multAnyAllowed;
public MultiplicityValidator(boolean mayChange, int old, boolean multAnyAllowed) {
this.mayChange = mayChange;
this.old = old;
this.multAnyAllowed = multAnyAllowed;
}
@Override
public IStatus validate(Object value) {
if (value instanceof Integer) {
int m = (Integer) value;
if (m==0)
return ValidationStatus.error("multiplicity must not be 0");
if (m<-1)
return ValidationStatus.error("multiplicity must be -1 or positive");
if (!mayChange) {
if (old==1 && (m>1 || m==-1))
return ValidationStatus.error("cannot change connected port to replicated");
if ((old>1 || old==-1) && m==1)
return ValidationStatus.error("cannot change connected port to not replicated");
}
if (m==-1 && !multAnyAllowed)
return ValidationStatus.error("multiplicity * not allowed (actor used replicated)");
if (port.getProtocol()!=null)
if (port.getProtocol() instanceof ProtocolClass && ((ProtocolClass)port.getProtocol()).getCommType()==CommunicationType.DATA_DRIVEN) {
if (m!=1)
return ValidationStatus.error("data driven ports can not be replicated");
}
}
else if (value instanceof String) {
if (!value.equals("*")) {
try {
Integer.parseInt((String) value);
}
catch (NumberFormatException e) {
return ValidationStatus.error("Multiplicity must be * or integer > 0");
}
}
}
else {
return ValidationStatus.error("Multiplicity must be * or integer > 0");
}
return Status.OK_STATUS;
}
}
class RelayValidator implements IValidator {
/* (non-Javadoc)
* @see org.eclipse.core.databinding.validation.IValidator#validate(java.lang.Object)
*/
@Override
public IStatus validate(Object value) {
if (!((Boolean)value).booleanValue())
if (port.getProtocol() instanceof CompoundProtocolClass)
return ValidationStatus.error("external end port must not have compound protocol");
return Status.OK_STATUS;
}
}
static class Multiplicity2StringConverter extends Converter {
public Multiplicity2StringConverter() {
super(Integer.class, String.class);
}
@Override
public Object convert(Object fromObject) {
if (fromObject instanceof Integer) {
int val = (Integer) fromObject;
if (val==-1)
return "*";
else
return fromObject.toString();
}
return fromObject;
}
}
static class String2MultiplicityConverter extends Converter {
String2MultiplicityConverter() {
super(String.class, Integer.class);
}
@Override
public Object convert(Object fromObject) {
if (fromObject.equals("*"))
return -1;
else {
try {
return Integer.parseInt((String) fromObject);
}
catch (NumberFormatException e) {
return "";
}
}
}
}
private Port port;
private IScope scope;
private ActorContainerClass acc;
private boolean newPort;
private boolean refitem;
private boolean internal;
private Button relayCheck = null;
private boolean relay;
private boolean oldRelay;
public PortPropertyDialog(Shell shell, Port port, IScope scope, ActorContainerClass acc, boolean newPort, boolean refitem, boolean internal) {
super(shell, "Edit Port");
this.port = port;
this.scope = scope;
this.acc = acc;
this.newPort = newPort;
this.refitem = refitem;
this.internal = internal;
relay = isPortRelay();
oldRelay = relay;
}
private boolean isPortRelay() {
if (internal)
return false;
if (acc instanceof SubSystemClass)
return true;
else if (acc instanceof ActorClass) {
for (ExternalPort xp : ((ActorClass) acc).getExternalPorts()) {
if (xp.getInterfacePort()==port)
return false;
}
return true;
}
return false;
}
@Override
protected void initializeBounds() {
super.initializeBounds();
Point size = getShell().getSize();
getShell().setSize((int)(size.x*1.2), size.y);
}
@Override
protected void createContent(IManagedForm mform, Composite body, DataBindingContext bindingContext) {
Result notReferenced = SupportUtil.getInstance().getValidationUtil().isFreeOfReferences(port);
boolean multiplicityAnyAllowed = true;
ActorContainerClass parent = (ActorContainerClass) port.eContainer();
if (parent instanceof ActorClass) {
if (SupportUtil.getInstance().getValidationUtil().isReferencedAsReplicatedInModel((ActorClass) parent))
multiplicityAnyAllowed = false;
}
NameValidator nv = new NameValidator();
ProtocolValidator pv = new ProtocolValidator();
MultiplicityValidator mv = new MultiplicityValidator(newPort || notReferenced.isOk(), port.getMultiplicity(), multiplicityAnyAllowed);
ArrayList<IEObjectDescription> protocols = new ArrayList<IEObjectDescription>();
Iterator<IEObjectDescription> it = scope.getAllElements().iterator();
while (it.hasNext()) {
IEObjectDescription desc = it.next();
EObject obj = desc.getEObjectOrProxy();
if (obj instanceof GeneralProtocolClass)
protocols.add(desc);
}
Text name = createText(body, "&Name:", port, FSMPackage.eINSTANCE.getAbstractInterfaceItem_Name(), nv);
Combo protocol = createComboUsingDesc(body, "&Protocol:", port, GeneralProtocolClass.class, RoomPackage.eINSTANCE.getPort_Protocol(), protocols, RoomPackage.eINSTANCE.getRoomClass_Name(), pv);
Button conj = createCheck(body, "&Conjugated:", port, RoomPackage.eINSTANCE.getPort_Conjugated());
if (!internal && !refitem && (acc instanceof ActorClass))
createRelayCheck(body, notReferenced, mform.getToolkit());
Multiplicity2StringConverter m2s = new Multiplicity2StringConverter();
String2MultiplicityConverter s2m = new String2MultiplicityConverter();
Text multi = createText(body, "&Multiplicity:", port, RoomPackage.eINSTANCE.getPort_Multiplicity(), mv, s2m, m2s, false);
if (!newPort) {
if (!notReferenced.isOk()) {
protocol.setEnabled(false);
createInfoDecorator(protocol, notReferenced.getMsg());
conj.setEnabled(false);
createInfoDecorator(conj, notReferenced.getMsg());
if (port.getMultiplicity()==1) {
multi.setEnabled(false);
createInfoDecorator(multi, notReferenced.getMsg());
}
}
if (refitem) {
name.setEnabled(false);
createInfoDecorator(name, "inherited");
protocol.setEnabled(false);
createInfoDecorator(protocol, "inherited");
conj.setEnabled(false);
createInfoDecorator(conj, "inherited");
multi.setEnabled(false);
createInfoDecorator(multi, "inherited");
}
}
createDecorator(name, "invalid name");
createDecorator(protocol, "no protocol selected");
createDecorator(multi, "multiplicity must be greater 1");
name.selectAll();
name.setFocus();
}
private void createRelayCheck(Composite parent, Result notReferenced, FormToolkit toolkit) {
Label l = toolkit.createLabel(parent, "Is Relay Port:", SWT.NONE);
l.setLayoutData(new GridData(SWT.NONE));
relayCheck = toolkit.createButton(parent, "", SWT.CHECK);
relayCheck.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
relayCheck.setSelection(relay);
relayCheck.setEnabled(notReferenced.isOk());
RelayValidator validator = new RelayValidator();
UpdateValueStrategy t2m = new UpdateValueStrategy();
t2m.setAfterConvertValidator(validator);
t2m.setBeforeSetValidator(validator);
UpdateValueStrategy m2t = new UpdateValueStrategy();
m2t.setAfterConvertValidator(validator);
m2t.setBeforeSetValidator(validator);
getBindingContext().bindValue(SWTObservables.observeSelection(relayCheck), PojoObservables.observeValue(
this, "relay"), t2m, m2t);
if (notReferenced.isOk())
createDecorator(relayCheck, "");
else
createInfoDecorator(relayCheck, notReferenced.getMsg());
}
@Override
protected void okPressed() {
if (relay!=oldRelay) {
// we know it's an ActorClass (else the flag couldn't have changed)
ActorClass ac = (ActorClass) acc;
if (relay) {
for (ExternalPort xp : ac.getExternalPorts()) {
if (xp.getInterfacePort()==port) {
ac.getExternalPorts().remove(xp);
break;
}
}
}
else {
ExternalPort xp = RoomFactory.eINSTANCE.createExternalPort();
xp.setInterfacePort(port);
ac.getExternalPorts().add(xp);
}
}
super.okPressed();
}
@Override
protected Image getImage() {
return Activator.getImage("icons/Structure.gif");
}
public boolean isRelay() {
return relay;
}
public void setRelay(boolean relay) {
this.relay = relay;
}
@Override
protected String getFeatureContextHelpId() {
return "PortPropertyDialog";
}
}