Commit a405d7dd authored by Liana Soima's avatar Liana Soima
Browse files

Merge branch 'master' of https://git.fortiss.org/af3/af3.git into 3976

parents d64b0d1f 38a6f48a
......@@ -75,12 +75,15 @@ public class HierarchicalCompositionRules extends PlatformHierarchicalCompositio
rval.add(ITileDomain.class);
rval.add(IOffChipNetworkDomain.class);
rval.add(IMemoryDomain.class);
rval.add(IElectronicsDomain.class);
rval.add(IPeripheralsDomain.class);
} else if(hasEqualLevel(domain, ITileDomain.class)) {
// Required for availability of these elements at the tile level (i.e., to drop elements
// from the processor / NoC domain into tile domain elements.)
rval.add(IProcessorDomain.class);
rval.add(IMemoryDomain.class);
rval.add(INocDomain.class);
rval.add(IElectronicsDomain.class);
} else if(hasEqualLevel(domain, IMemoryDomain.class)) {
rval.add(IProcessorDomain.class);
rval.add(ITileDomain.class);
......
BusCompositor.java 26b60c609de15d545abc945cc7c35d487531800c GREEN
ClockCompositor.java 360aea01ec2ae832ab5c69e95b38b38ade3f5f2f GREEN
ClusterCompositor.java 6a2861b896f790c404753844eaa15222518fd59d GREEN
ClusterCompositor.java de1ea49354a09bc3c098c64674bfc4a15dcae81e GREEN
CoreCompositor.java 050798a2f694a04c23595ab7b9dee9756e9a3404 GREEN
MemoryCompositor.java 3064bb9b47a0df16eb85304481716d56273a21b9 GREEN
NetworkInterfaceCompositor.java da20db4c57e17921143fd8ea87635d9f341904b5 GREEN
NocRouterCompositor.java 3180a7cc98c6335f3fdc70befbdd5367e924e3d2 GREEN
NodeCompositor.java 02f6556b04c58a481c698a161e7a2607be30c2f8 GREEN
NodeCompositor.java 096dee7cba39dec1c767ebfc68cc13dbded7fa56 GREEN
OffChipNetworkCompositor.java 7eae93d5e917837891bfdd624fede77fd762858d GREEN
OffChipNetworkGatewayCompositor.java 9aed7241e987c5bb525886840fed9604dd78ede0 GREEN
OffChipNetworkRouterCompositor.java b7893fbbc0865f98d63c4ac7c647f5efba3b7b28 GREEN
OnChipNetworkCompositor.java b90a297b0efdeb97b4b06c2bd0e22ad7737df588 GREEN
OnChipOffChipGatewayCompositor.java e9f51bc859ec7901c8f9fa1b1751c2a5804d6b3c GREEN
PowerSupplyCompositor.java 1a3f76d53557533d80c7ffdb8c28500bd453ff47 GREEN
TileCompositor.java 2b59f673831d5d6a2065db8903b2bf8c06f0c1e8 GREEN
TileCompositor.java ebeed4a6bfcddf498379e5a05d1bc33d3a633afa GREEN
WatchDogCompositor.java 9d121bde08bc3e68c91ab53c673bd8865ae6fc44 GREEN
......@@ -24,6 +24,7 @@ import org.fortiss.af3.platform.hierarchic.compose.HierarchicalCompositionRules;
import org.fortiss.af3.platform.hierarchic.compose.base.IPlatformHierarchicalCompositionRules;
import org.fortiss.af3.platform.hierarchic.compose.base.elements.PlatformElementCompositorBase;
import org.fortiss.af3.platform.hierarchic.model.cluster.Cluster;
import org.fortiss.af3.platform.hierarchic.model.electronics.Clock;
import org.fortiss.af3.platform.hierarchic.model.electronics.ClockOut;
import org.fortiss.af3.platform.hierarchic.model.electronics.PowerOut;
import org.fortiss.af3.platform.hierarchic.model.node.Node;
......@@ -63,8 +64,8 @@ public final class ClusterCompositor extends PlatformElementCompositorBase<Clust
public boolean canCompose(Cluster container, EObject contained,
IElementCompositionContext context) {
// Exception to enable addition of OffChipNetworkPort to Cluster
return contained instanceof OffChipNetworkPort ||
super.canCompose(container, contained, context);
return !(contained instanceof Clock) && (contained instanceof OffChipNetworkPort ||
super.canCompose(container, contained, context));
}
/** {@inheritDoc} */
......
......@@ -24,6 +24,7 @@ import org.fortiss.af3.platform.hierarchic.model.electronics.PowerIn;
import org.fortiss.af3.platform.hierarchic.model.node.Node;
import org.fortiss.af3.platform.hierarchic.model.peripherals.GeneralPurposeInput;
import org.fortiss.af3.platform.hierarchic.model.peripherals.GeneralPurposeOutput;
import org.fortiss.af3.platform.hierarchic.model.peripherals.WatchDog;
import org.fortiss.af3.platform.hierarchic.model.tile.OnChipNetwork;
import org.fortiss.af3.platform.hierarchic.model.tile.Tile;
import org.fortiss.af3.platform.model.IArchitectureDomain;
......@@ -51,7 +52,7 @@ public final class NodeCompositor extends ExecutionUnitComponentCompositorBase<N
@Override
protected boolean canBeAddedAtCurrentLevel(IArchitectureDomain element) {
return super.canBeAddedAtCurrentLevel(element) ||
isInstanceOfAny(element, Tile.class, OnChipNetwork.class, PowerIn.class,
GeneralPurposeInput.class, GeneralPurposeOutput.class);
isInstanceOfAny(element, WatchDog.class, Tile.class, OnChipNetwork.class,
PowerIn.class, GeneralPurposeInput.class, GeneralPurposeOutput.class);
}
}
......@@ -23,7 +23,6 @@ import org.fortiss.af3.platform.hierarchic.compose.base.elements.ExecutionUnitCo
import org.fortiss.af3.platform.hierarchic.model.peripherals.GeneralPurposeInput;
import org.fortiss.af3.platform.hierarchic.model.peripherals.GeneralPurposeOutput;
import org.fortiss.af3.platform.hierarchic.model.peripherals.WatchDogIn;
import org.fortiss.af3.platform.hierarchic.model.tile.OnChipOffChipExport;
import org.fortiss.af3.platform.hierarchic.model.tile.Tile;
import org.fortiss.af3.platform.model.IArchitectureDomain;
......@@ -49,8 +48,7 @@ public final class TileCompositor extends ExecutionUnitComponentCompositorBase<T
/** {@inheritDoc} */
@Override
protected boolean canBeAddedAtCurrentLevel(IArchitectureDomain element) {
return isInstanceOfAny(element, OnChipOffChipExport.class, WatchDogIn.class,
GeneralPurposeInput.class, GeneralPurposeOutput.class) ||
super.canBeAddedAtCurrentLevel(element);
return isInstanceOfAny(element, WatchDogIn.class, GeneralPurposeInput.class,
GeneralPurposeOutput.class) || super.canBeAddedAtCurrentLevel(element);
}
}
......@@ -6,7 +6,7 @@ DeleteOutputPortReference.java f4e0b20d1671d6675780b3a37647bb6868d03775 GREEN
DeleteReference.java 348af1127eb54397a68642c71cf5515879333a4f GREEN
DeleteRequirementReference.java d8918d7b8a059b5bf9ff093ec8a55f16c9e6fdf6 GREEN
GenerateModuleConnections.java f07409c4f9276d9359991ec4cd0ddaaed76839dd GREEN
GoToReferencedAF3Element.java a045feb80e8caa131fb5520dfb8d3dbbabe7a89f GREEN
GoToReferencedAF3Element.java 640c31613dfa07f0017db1d7fe35dd01bef99676 GREEN
GoToReferencedComponentInputPorts.java 82d4ac5b6b589a45dcabf1496ebe89d2031593de GREEN
GoToReferencedComponentOutputPorts.java d4c80efe328159b47aafafa525d6c7391d384bee GREEN
GoToReferencedContext.java 158f24ccf9e520c2e33e91d1ceacab1beaacb006 GREEN
......
......@@ -28,7 +28,6 @@ import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IContributionItem;
import org.fortiss.af3.safetycases.model.ArgumentElement;
import org.fortiss.af3.safetycases.ui.AF3SafetyCasesUIActivator;
import org.fortiss.tooling.kernel.model.constraints.ConstraintInstance;
import org.fortiss.tooling.kernel.ui.extension.IContextMenuContributor;
import org.fortiss.tooling.kernel.ui.extension.data.ContextMenuContextProvider;
......@@ -76,8 +75,7 @@ public class GoToReferencedAF3Element implements IContextMenuContributor {
/** {@inheritDoc} */
@Override
public void run() {
if(selected.getAf3Element() != null &&
!(selected.getAf3Element() instanceof ConstraintInstance)) {
if(selected.getAf3Element() != null) {
getInstance().openInEditor(selected.getAf3Element());
}
}
......
requirementspatterns.ecore b2f09bfc949bafb0392929115b3c0321bf2b192c RED
safetyargumentationpackage.ecore e95d1c0c64d12fa1660899df86cc9009dbae1754 RED
safetycases.ecore b3b1dcf0f18facde3ebb68f29c4300b4e7bcf349 RED
safetycases.ecore f00dffa5abfeb387c709853c5bdea4e78ca05165 GREEN
......@@ -51,7 +51,7 @@
</eClassifiers>
<eClassifiers xsi:type="ecore:EClass" name="EntryConnector" eSuperTypes="#//SafetyCasesConnector platform:/resource/org.fortiss.tooling.base/model/base.ecore#//base/EntryConnectorBase"/>
<eClassifiers xsi:type="ecore:EClass" name="ExitConnector" eSuperTypes="#//SafetyCasesConnector platform:/resource/org.fortiss.tooling.base/model/base.ecore#//base/ExitConnectorBase"/>
<eClassifiers xsi:type="ecore:EClass" name="ArgumentElementBase" eSuperTypes="platform:/resource/org.fortiss.tooling.base/model/base.ecore#//base/HierarchicElementBase platform:/resource/org.fortiss.tooling.kernel/model/kernel.ecore#//constraints/IConstrained">
<eClassifiers xsi:type="ecore:EClass" name="ArgumentElementBase" eSuperTypes="platform:/resource/org.fortiss.tooling.base/model/base.ecore#//base/HierarchicElementBase">
<eOperations name="getEntryConnectors" upperBound="-1" eType="#//EntryConnector">
<eAnnotations source="http://www.eclipse.org/emf/2002/GenModel">
<details key="body" value="return org.fortiss.tooling.kernel.utils.EcoreUtils.pickInstanceOf(&#xD;&#xA;&#x9;&#x9;&#x9;&#x9;EntryConnector.class, getConnectors());"/>
......
DataStateFXEditor.java e64fcec84ea83e5ba99e48a6825063471e9ea70d GREEN
DataStateFXEditorBase.java 0bec3533962ebcd7326f6597d598a5ff7c8ba8e6 GREEN
DataStateFXEditorBase.java 83655742fdcfdade31eabd7deafa88862f28ba22 GREEN
DataStateFXEditorBinding.java 46ab36b197a6fca102a5e2d75aa24b1fbba26b89 GREEN
DataStateFXEditorContentProvider.java 324cd24e2219ba2cf360b0f82e3628ca1b5dabba GREEN
DataStateFXEditorUIProvider.java 4993d4a6685b7738dd28a7a55177ab43fe81fc53 GREEN
StateAutomatonControllerFactory.java 03d624ad560508280c01898da29eac0450bbb237 GREEN
StateAutomatonControllerFactory.java 67f7f7bbc318018080a4569d84e0f1830ce33bda GREEN
StateAutomatonFXEditor.java eea88e496c873ec92f6b2a0735cbd3d542a3063f GREEN
StateAutomatonFXEditorBase.java 788601b7fa8ba9bb9ca0b5d946d78ec4db220fbe GREEN
StateAutomatonFXEditorBase.java 901e1ce52a2a53fb73c160b0af7fd7fbfc1e3044 GREEN
StateAutomatonFXEditorBinding.java 5fae7a8e04236c07d176a2b1ed22f7043e3a09fe GREEN
StateAutomatonFXEditorBindingBase.java c2bf20b1e1d709a9c7662a62795662f8fc33b855 GREEN
StateAutomatonModelFactory.java 07989fa95608fc8ce25e977cba898cf94932e0ae GREEN
......
......@@ -19,17 +19,21 @@ import static org.eclipse.emf.ecore.util.EcoreUtil.delete;
import static org.fortiss.af3.component.utils.BehaviorModelElementFactory.createDataStateVariable;
import static org.fortiss.af3.expression.utils.ExpressionModelElementFactory.intConst;
import static org.fortiss.af3.expression.utils.ExpressionModelElementFactory.intType;
import static org.fortiss.tooling.common.ui.javafx.util.GraphicUtils.getFXImage;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EObject;
import org.fortiss.af3.component.model.behavior.common.DataStateVariable;
import org.fortiss.af3.component.model.behavior.common.IDataStateVariableProvider;
import org.fortiss.af3.expression.ui.databinding.validate.StringToTypeValidator;
import org.fortiss.tooling.common.ui.javafx.control.treetableview.DynamicTreeContentProviderBase;
import org.fortiss.tooling.common.ui.javafx.control.treetableview.DynamicTreeTableViewer;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.service.IPersistencyService;
import org.fortiss.tooling.kernel.ui.ToolingKernelUIActivator;
import org.fortiss.tooling.kernel.ui.extension.base.FXEditorBase;
import org.fortiss.tooling.kernel.utils.KernelServiceBasedModelListenerBase;
......@@ -37,6 +41,10 @@ import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
......@@ -47,18 +55,18 @@ import javafx.scene.layout.VBox;
*/
public abstract class DataStateFXEditorBase<T extends IDataStateVariableProvider>
extends FXEditorBase<T> {
/** The description. */
private static final String DESCRIPTION = "Define data state variables with the table below:";
/** The tree-table viewer. */
private DynamicTreeTableViewer<EObject> viewer;
/** The remove button. */
private Button removeButton;
/** The add button. */
private Button addButton;
/** The model listener. */
private KernelServiceBasedModelListenerBase<IDataStateVariableProvider> modelListener;
/** The description / error label. */
private Label descriptionError;
/** {@inheritDoc} */
@Override
......@@ -76,10 +84,39 @@ public abstract class DataStateFXEditorBase<T extends IDataStateVariableProvider
DynamicTreeContentProviderBase<EObject> contentProvider =
new DataStateFXEditorContentProvider();
DataStateFXEditorUIProvider uiProvider = new DataStateFXEditorUIProvider();
DataStateFXEditorUIProvider uiProvider = new DataStateFXEditorUIProvider() {
@Override
public void validateOnKeyReleased(KeyEvent event, int colIndex, EObject item,
String text) {
String message = DataStateFXEditorBase.DESCRIPTION;
ImageView icon = null;
if(event.getCode() != KeyCode.ESCAPE && colIndex == 1) {
StringToTypeValidator validator = new StringToTypeValidator(item);
IStatus status = validator.validate(text);
if(!status.isOK()) {
message = status.getMessage();
icon = new ImageView(
getFXImage(ToolingKernelUIActivator.PLUGIN_ID, "/icons/error.png"));
}
}
descriptionError.setText(message);
descriptionError.setGraphic(icon);
event.consume();
}
/** {@inheritDoc} */
@Override
public void validateOnCancelEdit(int colIndex, EObject item) {
descriptionError.setText(DataStateFXEditorBase.DESCRIPTION);
descriptionError.setGraphic(null);
}
};
// Add main pane with the table.
BorderPane mainPane = new BorderPane();
descriptionError = new Label(DESCRIPTION);
mainPane.setTop(descriptionError);
viewer = new DynamicTreeTableViewer<>(provider, false, 2, contentProvider, uiProvider);
viewer.addColumn("Variable", 160);
viewer.addColumn("Type", 160);
......
......@@ -15,22 +15,22 @@
+--------------------------------------------------------------------------*/
package org.fortiss.af3.state.ui.editor.fx;
import org.fortiss.tooling.common.ui.javafx.lwfxef.controller.IController;
import org.fortiss.tooling.common.ui.javafx.lwfxef.controller.IControllerFactory;
import org.fortiss.tooling.common.ui.javafx.lwfxef.mvc.IContentAnchorageMVCBundle;
import org.fortiss.tooling.common.ui.javafx.lwfxef.mvc.IContentMVCBundle;
import org.fortiss.tooling.common.ui.javafx.lwfxef.mvc.IDiagramAnchorageMVCBundle;
import org.fortiss.tooling.common.ui.javafx.lwfxef.mvc.IDiagramMVCBundle;
import org.fortiss.tooling.common.ui.javafx.lwfxef.mvc.ILinkMVCBundle;
import org.fortiss.af3.state.model.State;
import org.fortiss.af3.state.model.StateAutomaton;
import org.fortiss.af3.state.model.TransitionSegment;
import org.fortiss.af3.state.model.TransitionSegmentConnector;
import org.fortiss.tooling.base.ui.editor.fx.controller.CurvedLinkLayoutedContentAnchorangeController;
import org.fortiss.tooling.base.ui.editor.fx.controller.CurvedLinkLayoutedDiagramAnchorangeController;
import org.fortiss.tooling.base.ui.editor.fx.controller.EObjectDiagramController;
import org.fortiss.tooling.base.ui.editor.fx.controller.LayoutedCurveLinkBendPointController;
import org.fortiss.tooling.base.ui.editor.fx.controller.LayoutedDiagramAnchorageController;
import org.fortiss.tooling.base.ui.editor.fx.controller.LayoutedEllipticResizableContentController;
import org.fortiss.tooling.common.ui.javafx.lwfxef.controller.IController;
import org.fortiss.tooling.common.ui.javafx.lwfxef.controller.IControllerFactory;
import org.fortiss.tooling.common.ui.javafx.lwfxef.mvc.IContentAnchorageMVCBundle;
import org.fortiss.tooling.common.ui.javafx.lwfxef.mvc.IContentMVCBundle;
import org.fortiss.tooling.common.ui.javafx.lwfxef.mvc.IDiagramAnchorageMVCBundle;
import org.fortiss.tooling.common.ui.javafx.lwfxef.mvc.IDiagramMVCBundle;
import org.fortiss.tooling.common.ui.javafx.lwfxef.mvc.ILinkMVCBundle;
/**
* The implementation of the {@link IControllerFactory} for a {@link StateAutomaton}.
......@@ -41,21 +41,21 @@ public class StateAutomatonControllerFactory implements IControllerFactory {
/** {@inheritDoc} */
@Override
public IController createContentController(IContentMVCBundle model) {
return new LayoutedEllipticResizableContentController<State>(model, State.class);
return new LayoutedEllipticResizableContentController<>(model, State.class);
}
/** {@inheritDoc} */
@Override
public IController createDiagramAnchorageController(IDiagramAnchorageMVCBundle modelBundle) {
return new LayoutedDiagramAnchorageController<TransitionSegmentConnector>(modelBundle,
return new CurvedLinkLayoutedDiagramAnchorangeController<>(modelBundle,
TransitionSegmentConnector.class);
}
/** {@inheritDoc} */
@Override
public IController createContentAnchorageController(IContentAnchorageMVCBundle modelBundle) {
return new CurvedLinkLayoutedContentAnchorangeController<TransitionSegmentConnector>(
modelBundle, TransitionSegmentConnector.class);
return new CurvedLinkLayoutedContentAnchorangeController<>(modelBundle,
TransitionSegmentConnector.class);
}
/** {@inheritDoc} */
......
......@@ -18,11 +18,11 @@ package org.fortiss.af3.state.ui.editor.fx;
import static javafx.scene.paint.Color.LIGHTGRAY;
import org.eclipse.emf.ecore.EObject;
import org.fortiss.tooling.common.ui.javafx.lwfxef.DiagramViewerFeatures;
import org.fortiss.tooling.common.ui.javafx.lwfxef.DiagramViewerFeatures.IndicatorType;
import org.fortiss.af3.state.model.State;
import org.fortiss.af3.state.model.TransitionSegmentEntryConnector;
import org.fortiss.af3.state.model.TransitionSegmentExitConnector;
import org.fortiss.tooling.common.ui.javafx.lwfxef.DiagramViewerFeatures;
import org.fortiss.tooling.common.ui.javafx.lwfxef.DiagramViewerFeatures.IndicatorType;
import org.fortiss.tooling.kernel.ui.extension.base.LWFXEFEditorBase;
/**
......
state.ecore 9703d36fa2573a508865128d27faa21b248ae6ae GREEN
state.ecore 1cb9e1de6d65d0a370752c64ad06316743344bb4 GREEN
This diff is collapsed.
BehaviorComponentCompositor.java a1dbd75cfce361b709249b0d851f080cf63d243c GREEN
ConnectorConnectionCompositor.java aa5842f6de9a764cbd5e1b90fc56427560e062a0 GREEN
ConnectorConnectionCompositor.java cfa132219000b2f3048c56452e22eeac832314b3 GREEN
ConnectorStateConnectionCompositor.java a0fb18af7ded52cbcb18be83cf1d9960028ceac2 GREEN
StateAutomatonCompositor.java 42625f27b7e2d5de0df39c56618173ff057ea7a5 GREEN
StateCompositor.java 299d369552fb940a1297d64606c3c0c1698e57a8 GREEN
......
......@@ -22,6 +22,7 @@ import org.fortiss.af3.state.model.State;
import org.fortiss.tooling.base.compose.ConnectorConnectionCompositorBase;
import org.fortiss.tooling.base.model.base.ConnectionSegmentBase;
import org.fortiss.tooling.base.model.base.ConnectorBase;
import org.fortiss.tooling.base.model.base.EntryConnectorBase;
import org.fortiss.tooling.base.model.element.IConnection;
import org.fortiss.tooling.kernel.extension.data.IConnectionCompositionContext;
......@@ -37,17 +38,55 @@ public class ConnectorConnectionCompositor
@Override
public boolean canConnect(ConnectorBase source, ConnectorBase target, State parent,
IConnectionCompositionContext context) {
// Do not allow connections from and to already occupied ports. Since a link can be drawn
// from an entry not to an exit node as well, both end points have to be checked for both
// incoming and outgoing links.
boolean freeSource = source.getOutgoing().isEmpty() && source.getIncoming().isEmpty();
boolean freeTarget = target.getIncoming().isEmpty() && target.getOutgoing().isEmpty();
// Do not allow connections from and to already occupied ports.
// Since a link can be drawn from an entry not to an exit node as well, both end
// points have to be checked for both incoming and outgoing links.
boolean freeSource = false;
boolean freeTarget = false;
// If both connectors are on the same level, they can be connected only once:
if(source.eContainer() == target.eContainer()) {
freeSource = isSameLevelPortFree(source);
freeTarget = isSameLevelPortFree(target);
// In case on of the connections is attached to the parent, it is possible that a port
// has an incoming and an outcoming connection (one on each level):
} else if(source.eContainer() == target.eContainer().eContainer()) {
// Case where the source is the cross-level port:
freeSource = isCrossLevelPortFree(source);
freeTarget = isSameLevelPortFree(target);
} else if(source.eContainer() != target.eContainer().eContainer()) {
// Case where the target is the cross-level port:
freeSource = isSameLevelPortFree(source);
freeTarget = isCrossLevelPortFree(target);
}
if(freeSource && freeTarget) {
return super.canConnect(source, target, parent, context);
}
return false;
}
/**
* Checks whether a port is available for a connection on the same level. In this case the port
* cannot have any other connections.
*/
private boolean isSameLevelPortFree(ConnectorBase connector) {
return connector.getOutgoing().isEmpty() && connector.getIncoming().isEmpty();
}
/**
* Checks whether a port is available for a connection to or from another level. In this case
* the port may already have another connection on the other level. However, the port cannot
* have an existing connection on the level of the connection to be established.
*/
private boolean isCrossLevelPortFree(ConnectorBase connector) {
boolean isFree;
if(connector instanceof EntryConnectorBase) {
isFree = connector.getOutgoing().isEmpty();
} else {
isFree = connector.getIncoming().isEmpty();
}
return isFree;
}
/** {@inheritDoc} */
@Override
protected ConnectionSegmentBase createConnection() {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment