-
Notifications
You must be signed in to change notification settings - Fork 67
VWorkflows-Core provides a flow/graph model with multiple edge types and an abstract skin model that does not depend on a specific ui technology. Skins are created by factories that can be nested. They define hierarchical relations which allows for easy subflow visualization.
VWorkflows-FX is a JavaFX based UI for the core model. It utilizes components from the JFXtras project (Window control, ScalableContentPane). It supports
- subflow visualization
- arbitrary zoom levels
- multiple visualizations of the same flow (visualizations are synced and fully editable)
- zoom dependent visualization (level of detail)
- ...
// create a flow object
VFlow flow = FlowFactory.newFlow();
// add two nodes to the flow
VNode n1 = flow.newNode();
VNode n2 = flow.newNode();
// create input and output connectors of type "default-type"
Connector inN1 = n1.addInput("default-type");
Connector outN1 = n1.addOutput("default-type");
Connector inN2 = n2.addInput("default-type");
Connector outN2 = n2.addOutput("default-type");
// create a connections
flow.connect(outN1, inN2);
// we assume a flow already exists
VFlow flow = ...
// make the flow visible
flow.setVisible(true);
// create a zoomable canvas
VCanvas canvas = new VCanvas();
Pane root = canvas.getContent();
// creating a skin factory and attach it to the flow
FXSkinFactory skinFactory = new FXSkinFactory(root);
flow.setSkinFactories(skinFactory);
// create a flow object
VFlow flow = FlowFactory.newFlow();
// create a subflow
VFlow subFlow = flow.newSubFlow();
NOTE: Serialization contains bugs that need fixing! Looking for volunteers!
WorkflowIO.saveToXML(Paths.get("flow-01.xml"), flow1.getModel());
NOTE: Serialization contains bugs that need fixing! Looking for volunteers!
VFlow flow = WorkflowIO.loadFromXML(Paths.get("flow-01.xml"));
// we assume a flow already exists
VFlow flow = ...
// we assume that connector c1 and c2 exit
Connector c1 = ...
Connector c2 = ...
// check compatibility
ConnectionResult result = flow.tryConnect(c1,c2);
if (!result.getStatus().isCompatible()) {
// connection failed!
// use message string to create report status
String msg = result.getStatus().getMessage();
}
To get a collection of all receivers of a node (nodes that are connected with an output of the node) it is necessary to request this information from the connections object of the parent flow.
List<VNode> receivers
= sender.getOutputs().stream().
flatMap(o -> flow.getConnections(o.getType()).
getAllWith(o).stream()).
map(conn -> conn.getReceiver().getNode()).
collect(Collectors.toList());
It is not advised to access the UI directly. Sometimes, however, it is necessary to add UI framework specific functionality that is not part of the model.
NOTE: each VNode can be visualized by multiple views.
VNode n = ...
List<Window> windows = flow.getNodeSkinsById(n.getId()).stream().
filter(s -> s instanceof FXFlowNodeSkin).
map(s -> ((FXFlowNodeSkin) s).getNode()).
collect(Collectors.toList());
It is not advised to access the UI directly. Sometimes, however, it is necessary to add UI framework specific functionality that is not part of the model.
NOTE: each Connector can be visualized by multiple views.
Connector c = ...
VNode n = c.getNode()
List<Node> connectorNodes =
flow.getNodeSkinsById(n.getId()).stream().
filter(s -> s instanceof FXFlowNodeSkin).
map(s -> ((FXFlowNodeSkin) s).
getConnectorNodeByReference(c)).
collect(Collectors.toList());
VNode n = ...
flow.getNodeSkinsById(n.getId()).stream().
filter(s -> s instanceof FXFlowNodeSkin).
map(s -> ((FXFlowNodeSkin) s).getNode()).
forEach(w->w.getLeftIcons().clear());
This can be accomplished by creating a custom SkinFactory:
VFlow flow = ...
flow.setSkinFactories(new FXSkinFactory(root) {
@Override
public VNodeSkin createSkin(VNode n, VFlow flow) {
FXFlowNodeSkin skin = new FXFlowNodeSkin(
this, getFxParent(), n, flow);
skin.getNode().getLeftIcons().add(
new RotateIcon(skin.getNode()));
return skin;
}
});
VWorkflows uses a left-to-right layout for connectors/connections. Sometimes this is not flexible enougth. Therefore, it is possible to change the default behavior. The auto-layout
positions input connectors either at the top or the left VNode/window border depending on incoming/outgoing connections.
Connector c = ...
c.getVisualizationRequest().set(
VisualizationRequest.KEY_CONNECTOR_AUTO_LAYOUT, true);
VWorkflows automatically computes the connector size depending on the VNode/window size and the number of connectors. Sometimes, the connector sizes are not optimal. VisualizationRequests
support maximum and minimum connector sizes.
VNode n = ...
n.getVisualizationRequest().set(
VisualizationRequest.KEY_MAX_CONNECTOR_SIZE, 10.0);
To prevent VNodes/windows from being dragged around VisualizationRequest.KEY_DISABLE_EDITING
can be used to disable editing capabilities.
NOTE: VNodes/windows still receive mouse events. They just don't move and cannot be resized.
VNode n = ...
n.getVisualizationRequest().set(
VisualizationRequest.KEY_DISABLE_EDITING, true);