| /******************************************************************************* |
| * 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"; |
| } |
| } |