mavn.network.view.JUNGPanelAdapter.java Source code

Java tutorial

Introduction

Here is the source code for mavn.network.view.JUNGPanelAdapter.java

Source

/*
JUNGPanelAdapter -- a class within the Machine Artificial Vision Network
(Machine Artificial Vision Network).
Copyright (C) 2012, Kaleb Kircher.
    
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package mavn.network.view;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.print.Printable;
import java.io.File;
import java.util.HashMap;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JPanel;
import org.apache.commons.collections15.functors.MapTransformer;
import org.apache.commons.collections15.map.LazyMap;
import edu.uci.ics.jung.algorithms.layout.AbstractLayout;
import edu.uci.ics.jung.algorithms.layout.StaticLayout;
import edu.uci.ics.jung.graph.DirectedGraph;
import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
import edu.uci.ics.jung.graph.util.EdgeType;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.annotations.AnnotationControls;
import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
import edu.uci.ics.jung.visualization.control.EditingModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ScalingControl;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import java.awt.Paint;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import org.apache.commons.collections15.Factory;
import org.apache.commons.collections15.Transformer;

/**
 * JUNG Panel Adaptor class uses an Adaptor Pattern to take
 * the MANV Network's and render the them with the JUNG Framework's Graphical Network.
 */
public class JUNGPanelAdapter extends JPanel implements Printable {

    ArrayList verticies = new ArrayList();
    double[][] w2;
    double[][] w1;
    double[][] w0;
    // indicies to keep track of the verticies in the collection
    private int inputX;
    private int inputY;
    private int andMin;
    private int andMax;
    private int orMin;
    private int orMax;
    private int output;
    private DirectedGraph<Number, Number> graph;
    private AbstractLayout<Number, Number> layout;
    //the visual component and renderer for the graph
    private VisualizationViewer<Number, Number> vv;

    Factory<Number> vertexFactory = new VertexFactory();
    Factory<Number> edgeFactory = new EdgeFactory();
    // count the number of verticies
    int nodeCount = 0;
    // count the number of edges
    int edgeCount = 0;

    /**
     * Create an instance of a simple graph with popup controls to
     * create a graph.
     *
     */
    public JUNGPanelAdapter(double[][] w2, double[][] w1, double[][] w0) {
        this.w2 = w2;
        this.w1 = w1;
        this.w0 = w0;
        this.setPreferredSize(new Dimension(600, 400));
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        // create a simple graph for the demo
        graph = new DirectedSparseMultigraph<Number, Number>();

        this.layout = new StaticLayout<Number, Number>(graph, new Dimension(600, 600));

        if (w2.length > 0) {
            findIndicies();
            createVerticies();
            drawEdges();
            drawVerticies();
        }

        vv = new VisualizationViewer<Number, Number>(layout);

        vv.setBackground(Color.getColor("#333333"));

        vv.getRenderContext().setVertexLabelTransformer(MapTransformer.<Number, String>getInstance(
                LazyMap.<Number, String>decorate(new HashMap<Number, String>(), new ToStringLabeller<Number>())));

        vv.setVertexToolTipTransformer(vv.getRenderContext().getVertexLabelTransformer());

        vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line());

        final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
        this.add(panel);

        final EditingModalGraphMouse<Number, Number> graphMouse = new EditingModalGraphMouse<Number, Number>(
                vv.getRenderContext(), vertexFactory, edgeFactory);

        Transformer<Number, Paint> vertexPaint = new Transformer<Number, Paint>() {
            @Override
            public Paint transform(Number i) {
                return Color.getHSBColor(0, 0.73f, 1);
            }
        };

        vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint);

        // the EditingGraphMouse will pass mouse event coordinates to the
        // vertexLocations function to set the locations of the vertices as
        // they are created
        // graphMouse.setVertexLocations(vertexLocations);
        vv.setGraphMouse(graphMouse);
        vv.addKeyListener(graphMouse.getModeKeyListener());

        graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);

        final ScalingControl scaler = new CrossoverScalingControl();
        JButton plus = new JButton("+");
        plus.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                scaler.scale(vv, 1.1f, vv.getCenter());
            }
        });
        JButton minus = new JButton("-");
        minus.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                scaler.scale(vv, 1 / 1.1f, vv.getCenter());
            }
        });

        JPanel controls = new JPanel();
        controls.add(plus);
        controls.add(minus);
        this.add(controls);
        this.setVisible(true);
    }

    public void createVerticies() {
        for (int i = 0; i <= output; i++) {
            graph.addVertex(vertexFactory.create());
        }

        Iterator iterate = graph.getVertices().iterator();
        while (iterate.hasNext()) {
            verticies.add((Number) iterate.next());
        }

        Collections.sort(verticies);
    }

    public void drawEdges() {
        Iterator iterator = verticies.iterator();

        Number xNode = null;
        Number yNode = null;
        int count = 0;
        // draw the input layer edges
        while (iterator.hasNext()) {

            Number v = (Number) iterator.next();

            if (count == 0) {
                xNode = v;
            }
            if (count == 1) {
                yNode = v;
            }
            if (count > 1 && count < w2[0].length + 2) {
                graph.addEdge(edgeCount, xNode, v, EdgeType.DIRECTED);
                edgeCount++;
                graph.addEdge(edgeCount, yNode, v, EdgeType.DIRECTED);
                edgeCount++;
            }
            count++;
        }
        // draw the ANDing to ORing edges
        for (int i = 0; i < w1.length; i++) {
            for (int j = 0; j < w1[i].length; j++) {
                if (w1[i][j] == 1) {
                    graph.addEdge(edgeCount, andMin + j, orMin + i, EdgeType.DIRECTED);
                    edgeCount++;
                }
            }
        }
        for (int i = 0; i < w0.length; i++) {
            for (int j = 0; j < w0[i].length; j++) {
                if (w0[i][j] == 1) {
                    graph.addEdge(edgeCount, orMin + i, output, EdgeType.DIRECTED);
                    edgeCount++;
                }
            }
        }
    }

    public void drawVerticies() {
        Iterator iterateVerticies = verticies.iterator();

        int count = 0;
        int x = 50;
        int y = 50;
        while (iterateVerticies.hasNext()) {
            Number v = (Number) iterateVerticies.next();
            y += 50;
            if (count == inputX) {
                y = (int) (Math.floor((50 * w2[0].length / 2)) - 50);
            }
            if (count == inputY) {
                y = (int) (50 + Math.floor((50 * w2[0].length / 2)));
            }
            if (count == andMin) {
                x += 150;
                y = 50;
            }
            if (count == orMin) {
                x += 150;
                y = (int) (Math.floor((50 * w2[0].length / 2)) - 75);
            }
            if (count == output) {

                x += 150;
                y = (int) (Math.floor((50 * w2[0].length / 2)));
            }

            layout.setLocation(v, x, y);
            layout.lock(v, true);
            count++;
        }
    }

    public void findIndicies() {
        //Indicies to keep track of what nodes belong to what layer
        // in the verticies collection.
        // The first two indicies are for the X and Y coordinate
        // inputs.
        inputX = 0;
        inputY = 1;

        // The third index through the number of nodes in the
        // ANDing layer
        andMin = inputY + 1;
        andMax = andMin + w2[0].length - 1;

        // The third index through the number of nodes in the
        // ANDing layer + 1
        orMin = andMax + 1;
        orMax = orMin + w1.length - 1;
        output = orMax + 1;
    }

    public void fireNodes(final double[] result) {
        Transformer<Number, Paint> vertexPaint = new Transformer<Number, Paint>() {

            private final Color[] palette = { new Color(51, 181, 229), Color.BLACK, new Color(255, 68, 68) };

            @Override
            public Paint transform(Number i) {
                if (i.doubleValue() == inputX || i.doubleValue() == inputY) {
                    if (result[inputX] == 1) {
                        return palette[0];
                    }
                    if (result[inputY] == -1) {
                        return palette[0];
                    }
                }
                if (i.doubleValue() >= andMin && i.doubleValue() <= andMax) {
                    if (result[i.intValue()] == 1) {
                        return palette[0];
                    }
                    if (result[i.intValue()] == -1) {
                        return palette[1];
                    }
                }
                if (i.doubleValue() >= orMin && i.doubleValue() <= orMax) {
                    if (result[i.intValue()] == 1) {
                        return palette[0];
                    }
                    if (result[i.intValue()] == -1) {
                        return palette[1];
                    }
                }
                if (i.doubleValue() == output) {
                    if (result[output] == 1) {
                        return palette[0];
                    }
                    if (result[output] == -1) {
                        return palette[1];
                    }
                }
                return palette[2];
            }
        };

        vv.getRenderContext().setVertexFillPaintTransformer(vertexPaint);
    }

    @Override
    public int print(java.awt.Graphics graphics, java.awt.print.PageFormat pageFormat, int pageIndex)
            throws java.awt.print.PrinterException {
        if (pageIndex > 0) {
            return (Printable.NO_SUCH_PAGE);
        } else {
            java.awt.Graphics2D g2d = (java.awt.Graphics2D) graphics;
            vv.setDoubleBuffered(false);
            g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());

            vv.paint(g2d);
            vv.setDoubleBuffered(true);

            return (Printable.PAGE_EXISTS);
        }
    }

    /**
     * copy the visible part of the graph to a file as a jpeg image
     * @param file
     */
    public void writeJPEGImage(File file) {
        int width = vv.getWidth();
        int height = vv.getHeight();

        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = bi.createGraphics();
        vv.paint(graphics);
        graphics.dispose();

        try {
            ImageIO.write(bi, "jpeg", file);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    class VertexFactory implements Factory<Number> {

        @Override
        public Number create() {
            return nodeCount++;
        }
    }

    class EdgeFactory implements Factory<Number> {

        @Override
        public Number create() {
            return edgeCount++;
        }
    }
}