Tuesday, March 22, 2011

Implementing graph editor in JavaFX using MVC like approach

JavaFX has very good SVG support, embedded into language runtime. This makes it interesting choice for implementing custom UI components, which includes graph editors.
In this article, I show how to create a simple graph editor, using MVC like approach and XML serialization via XStream.

Example can be found here: Launch JNLP, Browse on GitHub.
Application brings graph editing functionality and maximum network flow computation using Ford Fulkerson algorithm

Architecture is divided into Model, View and Controller. I made a slight upgrade to classic understanding of MVC. Classic View was responsible for displaying data only. Here, View consists also of UI parts, which include editable labels or combo boxes. Also, in Classic MVC, Model was responsible for refreshing View after Model changes by sending events to registered views. Here, Controller is responsible for refreshing View after Model changes and Model is just a plain POJO structure. I found such approach easier to implement.

Model consists of Three Java classes (non JavaFX), which represent structure of a graph: MNode, MShape, MConnection. Separating those classes from UI gives benefit of easier serialization. In this case using XStream::toXML(model) does the job. Sample output is like this:

View consists of corresponding UI implementations for Model elements, which are UINode, UILine, UIShape. Here, UINode is connected to MNode through model property. This is Bridge Pattern like approach for splitting class hierarchy of nodes into two.
UINode classes refer to controller to perform user input actions, like delete node.

Controller implements user action logic. This includes add, delete, and drag node. It is also responsible for refreshing UI after model changes. In order to do that easily, it uses Weak Hash Map, which keys are Model nodes and values are UI Nodes. Update function is like this:

Because of Weak Hash Map, removing nodes from Model leads to removing corresponding UI elements from map automaticly.

JavaFX SVG support and Layouts make it easy to render quite good looking nodes and connections.

Monday, March 7, 2011

Drawing arrows in JavaFX

Some time in the past, I was wondering what's the easiest solution for drawing arrow connections between shapes. The problem boils down to computing boundary point for given shape, which intersects with connecting line.
The solution is not so difficult when we consider polygon shapes. But it becomes more difficult considering curves and far more difficult for generic SVG shapes.
In this article, I show a simple way to find such boundary points for generic SVG shapes, utilizing JavaFX "contains" method and simple bisection algorithm.
Following application does the job: Launch JNLP, Browse on GitHub.
Application allows to drag shapes to track shape boundaries.

So, "contains" method in JavaFX allows us to poll any 2D point for intersection with SVG shape. Next, we need to assume, that we know a point inside a shape, from which every ray has exactly one intersection. This includes star-like shapes and ellipses. Next, we can use simple bisection algorithm to find such boundary point. We cut off once length between two points is too small. Following snippet does the job: Next, we need to draw arrows on the ends. In order to do that, we can use JavaFX Affine Transform, which is matrix transformation for SVG path. We need to compute transformation vectors for the matrix. This sounds scarry, but in fact is relatively easy. First vector in matrix is (targetPoint - sourcePoint) / length. Second one is perpendicular to it. Following code applies transformation: