3

I'm creating a user interface for a java swing program that should be able to allow the user to create a network of nodes, connected by edges. The user is allowed to label those nodes and edges.

The UI currently has a custom graphical component that extends JPanel and it is meaningful on it's own, having working operations such as zoom and drag. I'm trying to use the GraphStream library (http://graphstream-project.org/) to turn this custom panel into a View that supports GraphStream Graphs. Since GraphStream comes with a DefaultView class that is able to show basic graphs out of the box and extends JPanel, I decided to modify my map component so that it extends DefaultView. So my class definition for the background component is now

public class CustomPanel extends DefaultView implements ICustomListener
{
    public CustomPanel(Viewer viewer, String identifier, GraphRenderer renderer)
    {
        super(viewer, identifier, renderer);
        ...
    }
}

However, the component fails to display any graphs or drawing capabilities. This is how I proceeded to form a test graph

Graph graph = new GraphicGraph("embedded");
Viewer viewer = new Viewer(graph, Viewer.ThreadingModel.GRAPH_IN_GUI_THREAD);

Node a = graph.addNode("A");
a.addAttribute("xy", 0, 0);
Node b = graph.addNode("B");
b.addAttribute("xy", 10, 0);
Node c = graph.addNode("C");
c.addAttribute("xy", 10, 10);
graph.addEdge("AB","A","B");

//This is where I assume the GraphStream magic should happen.
CustomPanel myPanel = new CustomPanel(viewer, "defaultView", Viewer.newGraphRenderer());
viewer.addView(myPanel);
myPanel.display((GraphicGraph)(graph), true);

I am able to display the same graph with

viewer.addDefaultView(true);

but it opens in a new window.

So what am I doing wrong or is it even possible to display graphs with GraphStream on custom components? If there is another library that could do this I would be thankful to know. I am aware of JUNG2 and Java2D but have not tried them yet. I could also live with a solution that opens an editor in another window, but I would still need my CustomPanel as the background.

milez
  • 2,201
  • 12
  • 31
  • See also [*Visualisation*](http://graphstream-project.org/doc/Tutorials/Graph-Visualisation_1.0/). – trashgod Jul 13 '15 at 11:11
  • Thanks for the link, but I read through it before posting the question. The Advanced section seems to give some hints, but it still remains unclear what to do. Additionally, sentences such as "In order to integrate the viewer in a Swing GUI, you will need to create the viewer by yourself" and "Even if you did not created the view yourself, you can always access the default view created for you" conflict each other, especially since the library uses and needs both the View and the Viewer to function. – milez Jul 13 '15 at 11:22

2 Answers2

1

If someone faces the same problem, here is what I did to overcome it. Keep in mind it was crucial the background component maintained all its original capabilities. Overall, the implementation of GraphStream's DefaultView was a good example.

I made a class that extended from the background and implemented org.graphstream.ui.view.View

public class HybridView extends CustomView implements View

Then I found out I had to modify the default GraphStream renderers where it was crucial to write my own renderGraph method. I simply copied the implementation from the superclass and commented out some lines:

protected void renderGraph(Graphics2D g) {
    StyleGroup style = graph.getStyle();

    setupGraphics(g);
    //Dont paint on the background
    //renderGraphBackground(g);
    //Commenting out the next line had no visible effects so I left it unmodified, tho it's name begs for being commented out
    renderBackLayer(g);
    camera.pushView(graph, g);
    renderGraphElements(g);

    if (style.getStrokeMode() != StyleConstants.StrokeMode.NONE
            && style.getStrokeWidth().value != 0) {
        GraphMetrics metrics = camera.getMetrics();
        Rectangle2D rect = new Rectangle2D.Double();
        double px1 = metrics.px1;
        Value stroke = style.getShadowWidth();

        rect.setFrame(metrics.lo.x, metrics.lo.y + px1,
                metrics.size.data[0] - px1, metrics.size.data[1] - px1);
        g.setStroke(new BasicStroke((float) metrics.lengthToGu(stroke)));
        g.setColor(graph.getStyle().getStrokeColor(0));
        g.draw(rect);
    }

    camera.popView(g);
    renderForeLayer(g);
}

public class MyGraphRenderer extends GraphRendererBase 

Then to use the component with the drawing capabilities of GraphStream and my previously existing meaningful background component:

Graph graph = new GraphicGraph("embedded");
Viewer viewer = new Viewer(graph, Viewer.ThreadingModel.GRAPH_IN_GUI_THREAD);
CustomPanel myPanel = new CustomPanel(viewer, "defaultView", new MyGraphRenderer());
milez
  • 2,201
  • 12
  • 31
0

Not sure I get what you want to do. But if you simply want to add a GraphStream view into your own GUI then you don't need to extend the DefaultView. The viewer you created is OK so you only need to insert a new view in your GUI like so :

    // create a view *without* a JFrame
    View view = viewer.addDefaultView(false);
    view.setPreferredSize(new Dimension(600, 400));

    JFrame f = new JFrame("Your GUI");
    // add the view to your components (JFrame, JPanel...)
    f.add(view, BorderLayout.CENTER);
    // add your other GUI stuff here...
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.pack();
    f.setVisible(true);
Yoann
  • 556
  • 3
  • 11
  • Thanks for your answer. The thing is that I want a previously existing GUI element (that extends JPanel) to act as the View of my Graph. So I extended that custom component from DefaultView in attempt to achieve that. Simply fetching the view from viewer does not achieve that, as then the view and my custom component would not be united, if that makes sense? – milez Jul 13 '15 at 15:18
  • Now I get it. Then your example works. You only need to make sure that the `myPanel` object gets attached to the existing GUI `someGUIFrame.add(myPanel, BorderLayout.CENTER);` – Yoann Jul 13 '15 at 22:49
  • Alright, I can see the graph, but the bad thing is that it totally hides my costom component (myPanel) under it. Are you aware of a method to simply draw nodes and edges on top of my component while also being able to see the background component? Will I have to edit the renderer? – milez Jul 14 '15 at 06:11