com.griddynamics.jagger.diagnostics.visualization.GraphVisualizationHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.griddynamics.jagger.diagnostics.visualization.GraphVisualizationHelper.java

Source

/*
 * Copyright (c) 2010-2012 Grid Dynamics Consulting Services, Inc, All Rights Reserved
 * http://www.griddynamics.com
 *
 * This library is free software; you can redistribute it and/or modify it under the terms of
 * the GNU Lesser General Public License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.griddynamics.jagger.diagnostics.visualization;

import edu.uci.ics.jung.algorithms.layout.*;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.VisualizationImageServer;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import edu.uci.ics.jung.visualization.renderers.VertexLabelAsShapeRenderer;
import org.apache.commons.collections15.Transformer;
import org.apache.commons.collections15.functors.ChainedTransformer;

import java.awt.*;
import java.awt.geom.Point2D;
import java.util.Map;

public class GraphVisualizationHelper {
    public enum GraphLayout {
        CIRCLE, ISOM, FR, KK
    }

    public enum ColorTheme {
        LIGHT, DARK
    }

    private static final double IMAGE_HORIZONTAL_MARGIN = 0.2;
    private static final double IMAGE_VERTICAL_MARGIN = 0.2;
    private static final int MAX_LABEL_LENGTH = 30;

    public static <V, E> Image renderGraph(Graph<V, E> graph, int width, int height, GraphLayout graphLayout,
            final ColorTheme colorTheme, final Map<V, Paint> customNodeColors) {

        Layout<V, E> layout;
        switch (graphLayout) {
        case CIRCLE:
            layout = new CircleLayout<V, E>(graph);
            break;
        case ISOM:
            layout = new ISOMLayout<V, E>(graph);
            break;
        case FR:
            layout = new FRLayout<V, E>(graph);
            break;
        case KK:
            layout = new KKLayout<V, E>(graph);
            break;
        default:
            throw new RuntimeException("Unknown Graph Layout : [" + graphLayout + "]");
        }

        layout.setSize(new Dimension((int) (width * (1 - IMAGE_HORIZONTAL_MARGIN)),
                (int) (height * (1 - IMAGE_VERTICAL_MARGIN))));

        VisualizationImageServer<V, E> server = new VisualizationImageServer<V, E>(displacementLayout(layout,
                (int) (width * IMAGE_HORIZONTAL_MARGIN / 2), (int) (height * IMAGE_VERTICAL_MARGIN / 2)),
                new Dimension(width, height));

        final Color edgeColor;
        switch (colorTheme) {
        case LIGHT:
            server.setBackground(Color.WHITE);
            edgeColor = Color.BLACK;
            break;
        case DARK:
            server.setBackground(Color.BLACK);
            edgeColor = Color.LIGHT_GRAY;
            break;
        default:
            throw new RuntimeException("Unknown Color Theme : [" + colorTheme + "]");
        }

        Transformer<V, Paint> vertexPaint = new Transformer<V, Paint>() {
            public Paint transform(V v) {
                Paint paint = customNodeColors.get(v);
                if (paint == null) {
                    paint = Color.LIGHT_GRAY;
                }
                return paint;
            }
        };

        Transformer<V, Paint> vertexBorderPaint = new Transformer<V, Paint>() {
            public Paint transform(V v) {
                return Color.DARK_GRAY;
            }
        };

        Transformer<E, Paint> edgePaint = new Transformer<E, Paint>() {
            public Paint transform(E e) {
                return edgeColor;
            }
        };

        server.getRenderContext().setVertexFillPaintTransformer(vertexPaint);
        server.getRenderContext().setEdgeDrawPaintTransformer(edgePaint);
        server.getRenderContext().setArrowDrawPaintTransformer(edgePaint);
        server.getRenderContext().setArrowFillPaintTransformer(edgePaint);

        server.getRenderContext().setVertexLabelTransformer(new ToStringLabeller<V>());
        server.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller<E>());
        server.getRenderContext().setVertexDrawPaintTransformer(vertexBorderPaint);

        server.getRenderContext().setVertexLabelTransformer(new ChainedTransformer<V, String>(
                new Transformer[] { new ToStringLabeller<V>(), new Transformer<String, String>() {
                    public String transform(String input) {
                        return "<html><center><p>" + formatLabel(input, MAX_LABEL_LENGTH);
                    }
                } }));
        VertexLabelAsShapeRenderer<V, E> vlasr = new VertexLabelAsShapeRenderer<V, E>(server.getRenderContext());
        server.getRenderContext().setVertexShapeTransformer(vlasr);
        server.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR);

        return server.getImage(new Point(0, 0), new Dimension(width, height));
    }

    private static String formatLabel(String string, int maxLength) {
        StringBuffer buffer = new StringBuffer(string);
        int runLength = 0;
        for (int i = 0; i < buffer.length(); i++) {
            if (buffer.charAt(i) != '\n') {
                runLength++;
            } else {
                runLength = 0;
            }

            if (runLength >= maxLength) {
                buffer.insert(i, '\n');
                runLength = 0;
            }
        }

        return buffer.toString().replaceAll("\\n", "<br/>");
    }

    private static <V, E> Layout<V, E> displacementLayout(Layout<V, E> layout, final int xOffset,
            final int yOffset) {
        return new LayoutDecorator<V, E>(layout) {
            @Override
            public Point2D transform(V v) {
                Point2D point = delegate.transform(v);
                return new Point.Double(point.getX() + xOffset, point.getY() + yOffset);
            }
        };
    }
}