Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Map Scene Sample in Visual Library

DZone's Guide to

Map Scene Sample in Visual Library

· Java Zone
Free Resource

Get the Edge with a Professional Java IDE. 30-day free trial.

An old sample by Visual Library creator David Kaspar, which I never got around to documenting before:

David writes: "Note that the sample is a view-only - it does not allow to edit the map, does not have object selection... only Labels of the Markers can be moved."

Create the Widgets

There are two special widgets in the screenshot above, a CircleWidget and a MarkerWidget:

import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import org.netbeans.api.visual.widget.Scene;
import org.netbeans.api.visual.widget.Widget;

class CircleWidget extends Widget {

    private final int radius;

    public CircleWidget(Scene scene, int radius) {
        super(scene);
        this.radius = radius;
    }

    @Override
    protected Rectangle calculateClientArea() {
        Rectangle rect = new Rectangle (-radius, -radius, 2 * radius, 2 * radius);
        rect.grow (1, 1); // counting with line-width
        return rect;
    }

    @Override
    protected void paintWidget() {
        super.paintWidget();
        Graphics2D gr = getGraphics();
        gr.setColor (getForeground());
        gr.fill(new Ellipse2D.Float (-radius, -radius, 2 * radius, 2 * radius));
    }

}
import java.awt.Color;
import java.awt.Point;
import org.netbeans.api.visual.action.ActionFactory;
import org.netbeans.api.visual.widget.LabelWidget;
import org.netbeans.api.visual.widget.Scene;
import org.netbeans.api.visual.widget.Widget;

class MarkerWidget extends Widget {

    private final CircleWidget circle;
    private final LabelWidget label;

    MarkerWidget(Scene scene, String name) {
        super(scene);
        circle = new CircleWidget (scene, 10);
        addChild (circle);
        label = new LabelWidget (scene, name);
        label.setBackground (Color.WHITE);
        label.setOpaque (true);
        label.setPreferredLocation (new Point (20, 0));
        addChild (label);
        label.getActions().addAction (ActionFactory.createMoveAction()); // moveable label
    }

    Widget getCircleWidget() {
        return circle;
    }

}

Create the Scene 

Use the widgets above in a scene, as follows:

import java.awt.Color;
import java.awt.Point;
import java.util.Arrays;
import org.netbeans.api.visual.anchor.AnchorFactory;
import org.netbeans.api.visual.graph.GraphScene;
import org.netbeans.api.visual.layout.LayoutFactory.ConnectionWidgetLayoutAlignment;
import org.netbeans.api.visual.widget.ConnectionWidget;
import org.netbeans.api.visual.widget.LabelWidget;
import org.netbeans.api.visual.widget.LayerWidget;
import org.netbeans.api.visual.widget.Widget;

public class MapScene extends GraphScene<String,String> {

    private final LayerWidget backgroundLayer;
    private final LayerWidget mainLayer;
    private final LayerWidget connectionLayer;

    public MapScene() {
        addChild (backgroundLayer = new LayerWidget (this));
        backgroundLayer.addChild(createCountryBoundary ());
        addChild (mainLayer = new LayerWidget (this));
        addChild (connectionLayer = new LayerWidget (this));
    }

    private Widget createCountryBoundary() {
        ConnectionWidget country = new ConnectionWidget (this);
        country.setRoutingPolicy(ConnectionWidget.RoutingPolicy.DISABLE_ROUTING);
        country.setControlPoints(Arrays.asList (
                new Point (200, 0),
                new Point (150, 0),
                new Point (0, 150),
                new Point (150, 300),
                new Point (350, 280),
                new Point (500, 140),
                new Point (200, 0)
        ), true);
        return country;
    }

    void createSampleData() {
        addNode ("Praha").setPreferredLocation(new Point (150, 120));
        addNode ("Brno").setPreferredLocation(new Point (300, 240));
        addEdge ("D1");
        setEdgeSource ("D1", "Praha");
        setEdgeTarget ("D1", "Brno");
    }

    @Override
    protected Widget attachNodeWidget(String node) {
        Widget marker = new MarkerWidget (this, node);
        mainLayer.addChild(marker);
        return marker;
    }

    @Override
    protected Widget attachEdgeWidget(String edge) {
        ConnectionWidget conn = new ConnectionWidget (this);
        LabelWidget label = new LabelWidget (this, edge);
        label.setBackground(Color.WHITE);
        label.setOpaque(true);
        conn.addChild(label);
        conn.setConstraint(label, ConnectionWidgetLayoutAlignment.CENTER, 0.5f);
        connectionLayer.addChild(conn);
        return conn;
    }

    @Override
    protected void attachEdgeSourceAnchor(String edge, String oldNode, String newNode) {
        ConnectionWidget conn = (ConnectionWidget) findWidget (edge);
        MarkerWidget marker = (MarkerWidget) findWidget (newNode);
        conn.setSourceAnchor(AnchorFactory.createCenterAnchor(marker.getCircleWidget ()));
    }

    @Override
    protected void attachEdgeTargetAnchor(String edge, String oldNode, String newNode) {
        ConnectionWidget conn = (ConnectionWidget) findWidget (edge);
        MarkerWidget marker = (MarkerWidget) findWidget (newNode);
        conn.setTargetAnchor(AnchorFactory.createCenterAnchor(marker.getCircleWidget ()));
    }

}

Hook the Scene into the TopComponent

In the constructor of the TopComponent:

        scene = new MapScene ();
        scene.createSampleData ();
        add (scene.createView (), BorderLayout.CENTER);

Now run the application and you'll see a window with the map shown at the start of this article.

Get the Java IDE that understands code & makes developing enjoyable. Level up your code with IntelliJ IDEA. Download the free trial.

Topics:

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}