jcomponentjgraphx

Vertex renderered as JComponent


I am currently trying to migrate a JGraph 5 application to JGraphX. I have vertex renderers implemented as nested JComponent with complex layout.

Using the mxStylesheet is the only I found so far to customize the vertext rendering. Is there any renderer concept in JGraphX ? Is it possible to implement the renderers as JComponents?


Solution

  • I found the answer in the CustomCanvas.java JGraphX sample.

    This sample works fine for non-composite components (JLabel...) but fails for composite components. The paintComponent() method is called for the parent but not for the children. It seems to be related to the fact that the CellRendererPane as no parent in this sample. Adding to the CellRendererPaneto the graphComponent solved the problem (For me the canvas was the natural parent but it doesn't seem to be a container).

    So, the answer to my original question is: no, JGraphX doesn't provide support for renderers but it seems that you can add such support yourself by subclassing both mxGraph, mxGraphComponent and mxInteractiveCanvas.

    Finally, this sample can easily be extended to implement the "renderer" pattern in a more usual way. I did not introduce a renderer factory to keep the snippet short but that would probably make sense.

    public class SwingCanvas<USER_OBJECT> extends mxInteractiveCanvas {
        private final CellRendererPane rendererPane = new CellRendererPane();
        protected mxGraphComponent graphComponent;
    
        public SwingCanvas(SwingMxGraphComponent<USER_OBJECT> graphComponent) {
            this.graphComponent = graphComponent;
            graphComponent.add(rendererPane);    
        }
    
        public void drawVertex(mxCellState state, String label) {
            SwingMxGraph<USER_OBJECT> graph = graphComponent.getGraph();
            VertexRenderer<USER_OBJECT>  vertexRenderer = graph.getVertexRenderer();
            USER_OBJECT userValue = (USER_OBJECT)((mxCell)state.getCell()).getValue();
            JComponent rendererComponent = vertexRenderer.getRendererComponent(graphComponent.getGraph(), userValue);
            rendererPane.paintComponent(g, rendererComponent, graphComponent,
                (int) state.getX() + translate.x,
                (int) state.getY() + translate.y,
                (int) state.getWidth(), (int) state.getHeight(), true);
        }
    }
    
    public interface VertexRenderer<USER_OBJECT> {
        /* Provide graph instance just in case...*/
        JComponent getRendererComponent(mxGraph graph, USER_OBJECT userObject);
    }
    
    public class SwingMxGraph<USER_OBJECT> extends mxGraph {
        private VertexRenderer<USER_OBJECT> vertexRenderer;
    
        /* Add the same method override as in sample
        ...
        ... */
    
        public VertexRenderer<USER_OBJECT> getVertextRenderer() {
            return vertexRenderer;
        }
    }