Displaying Runtime Values

When any native model execution is not running in the Cameo Simulation Toolkit, an external tool executes the model. There is a capability to dynamically display any custom value string on parts and/or ports in structure diagrams, without modifying the model in Cameo Simulation Toolkit. Currently, only parts and ports that are typed with a primitive data type are supported.

Start by extending com.nomagic.magicdraw.simulation.dashboard.api.ExternalValueProvider class to create a custom implementation. The returned custom values will be displayed on the diagrams representing the context for which the ExternalValueProvider instance was constructed. The model is not modified in any way when these values are displayed. The color in which the values are displayed is configurable via the  Runtime Value Text Color on Shapes project option. In the image below, two such values are provided and displayed in a diagram of the Transmission.mdzip sample project: 30.0 mi/h for carSpeed and 19.0 for wheelDiameter.

Image displaying the runtime values

Below is the implementation that was designed specifically for the Transmission.mdzip sample and provides just the two values seen in the above image:

//Engine Control Unit refers to ECU block in the Transmission sample project
public class EngineControlUnitValueProvider extends ExternalValueProvider
{
	private final Element carSpeedElement;
	private final Element wheelDiameterElement;
	
	//Mimics some model execution process that happens outside this tool and produces values to display
	private final MockExternalExecution externalExecution;

	public EngineControlUnitValueProvider(Element context)
	{
		super(context);
		Project project = Project.getProject(context);
		carSpeedElement = FinderByQualifiedName.getInstance().find(project, "Transmission::Structure::ECU::carSpeed", Property.class);
		wheelDiameterElement = FinderByQualifiedName.getInstance().find(project, "Transmission::Structure::ECU::wheelDiameter", Property.class);
		externalExecution = new MockExternalExecution(this);
	}

	@CheckForNull
	@Override
	public String getValueText(Element element, List<? extends Element> pathInContext)
	{
		// values should be pre-collected for diagram related performance reasons. Avoid time demanding implementations (e.g. remote calls) of this method
		if (element == carSpeedElement)
		{
			return externalExecution.getCarSpeed() + " mi/h";
		}
		else if (element == wheelDiameterElement)
		{
			return externalExecution.getWheelDiameter() + "\""; // double quote to represent inches
		}
		return null; // do not provide custom value for other elements in this context
	}

	/**
	 * To be called every time speed changes to call {@link #getValueText(Element, List)} for that element again
	 * @see #invalidate(Element)
	 * @see #invalidateAll() 
	 */
	public void invalidateCarSpeed()
	{
		invalidate(carSpeedElement);
	}
}

To have the effect, an instance of the implemented provider must be registered to the ExternalValueProviders service, as illustrated here:

	Project project = <...>
	// The root context of the external execution. Values will only be visible in the Diagrams that have this element set as context
	Classifier context = Finder.byQualifiedName().find(project, "Transmission::Structure::PowerTrain", Class.class);
	if (context != null)
	{
		EngineControlUnitValueProvider valueProvider = new EngineControlUnitValueProvider(context);
		ExternalValueProviders.getInstance(project).register(valueProvider);

		// if later the provider needs to be unregistered, it should be done by calling:
		// ExternalValueProviders.getInstance(project).unregister(valueProvider);
		// Since providers are registered for specific open project, there is no obligation to unregister manually on project close.
	}

 The full code example is available in <installation_directory>\openapi\examples\externalvalueindiagrams.

Animating flowing information

Additionally, it is possible to display animation for the information that flows via connector from one end to another. For a fixed amount of time, a banner with the custom value will move from the source towards the target. During the full duration of the animation, the connector presentation element will be highlighted in color which is controlled by a project option Active Color.

Image displaying the animation in between the connectors
			Connector connector = <..> // select connector via which to animate
            ConnectorEnd sourceEnd = selectSourceEnd(connector); // pick end from which to start the animation
			String flowingInformation = "myFlowingInformation"; // hardcoded for example, should be some actual data compatible with end/connector/flow types
			FlowingInformationDescriptor descriptor = new FlowingInformationDescriptor(flowingInformation, connector, sourceEnd);

			long duration = 4000; // 4 seconds to reach the other end
			FlowAnimation.getInstance(Project.getProject(connector)).animate(descriptor, duration, finished -> {/* do something when animation completes*/});

The full code example for this feature is available in <installation_directory>\openapi\examples\flowanimation.