com.schnee.tweetgeister.visualization.TweetgeisterBalloonLayout.java Source code

Java tutorial

Introduction

Here is the source code for com.schnee.tweetgeister.visualization.TweetgeisterBalloonLayout.java

Source

package com.schnee.tweetgeister.visualization;

/*
 * Copyright (c) 2003, the JUNG Project and the Regents of the University of
 * California All rights reserved.
 * 
 * This software is open-source under the BSD license; see either "license.txt"
 * or http://jung.sourceforge.net/license.txt for a description.
 * 
 */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JToggleButton;

import org.apache.commons.collections15.Factory;
import org.apache.commons.collections15.Predicate;
import org.apache.commons.collections15.functors.ConstantTransformer;

import com.schnee.tweetgeister.Clusterer;
import com.schnee.tweetgeister.analysis.TokenizedCharSequence;
import com.schnee.tweetgeister.data.Node;

import twitter4j.Query;
import twitter4j.QueryResult;
import twitter4j.Tweet;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;

import edu.uci.ics.jung.algorithms.layout.BalloonLayout;
import edu.uci.ics.jung.algorithms.layout.RadialTreeLayout;
import edu.uci.ics.jung.algorithms.layout.TreeLayout;
import edu.uci.ics.jung.graph.DirectedGraph;
import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
import edu.uci.ics.jung.graph.Forest;
import edu.uci.ics.jung.graph.DelegateForest;
import edu.uci.ics.jung.graph.DelegateTree;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.graph.Tree;
import edu.uci.ics.jung.graph.util.Context;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.Layer;
import edu.uci.ics.jung.visualization.VisualizationServer;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalLensGraphMouse;
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 edu.uci.ics.jung.visualization.layout.LayoutTransition;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import edu.uci.ics.jung.visualization.transform.LensSupport;
import edu.uci.ics.jung.visualization.transform.MutableTransformer;
import edu.uci.ics.jung.visualization.transform.MutableTransformerDecorator;
import edu.uci.ics.jung.visualization.transform.shape.HyperbolicShapeTransformer;
import edu.uci.ics.jung.visualization.transform.shape.ViewLensSupport;
import edu.uci.ics.jung.visualization.util.Animator;

/**
 * Demonstrates the visualization of a Tree using TreeLayout
 * and BalloonLayout. An examiner lens performing a hyperbolic
 * transformation of the view is also included.
 * 
 * @author Tom Nelson
 * 
 */
@SuppressWarnings("serial")
public class TweetgeisterBalloonLayout extends JApplet {

    /**
     * the graph
     */
    Forest<Node, Integer> graph;

    Factory<DirectedGraph<Node, Integer>> graphFactory = new Factory<DirectedGraph<Node, Integer>>() {

        public DirectedGraph<Node, Integer> create() {
            return new DirectedSparseMultigraph<Node, Integer>();
        }
    };

    Factory<Tree<Node, Integer>> treeFactory = new Factory<Tree<Node, Integer>>() {

        public Tree<Node, Integer> create() {
            return new DelegateTree<Node, Integer>(graphFactory);
        }
    };

    Factory<Integer> edgeFactory = new Factory<Integer>() {
        int i = 0;

        public Integer create() {
            return i++;
        }
    };

    Factory<String> vertexFactory = new Factory<String>() {
        int i = 0;

        public String create() {
            return "V" + i++;
        }
    };

    /**
     * the visual component and renderer for the graph
     */
    VisualizationViewer<Node, Integer> vv;

    VisualizationServer.Paintable rings;

    String root;

    TreeLayout<Node, Integer> layout;

    BalloonLayout<Node, Integer> balloonLayout;

    RadialTreeLayout<Node, Integer> radialTreeLayout;

    /**
     * provides a Hyperbolic lens for the view
     */
    LensSupport hyperbolicViewSupport;

    public TweetgeisterBalloonLayout() {

        // create a simple graph for the demo
        graph = new DelegateForest<Node, Integer>();

        createTree();

        layout = new TreeLayout<Node, Integer>(graph);
        radialTreeLayout = new RadialTreeLayout<Node, Integer>(graph);
        balloonLayout = new BalloonLayout<Node, Integer>(graph);
        balloonLayout.setSize(new Dimension(5900, 5900));

        writeGraph();
        /*       
           vv = new VisualizationViewer<Node, Integer>(layout, new Dimension(6000, 6000));
           vv.setBackground(Color.white);
           vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line());
           vv.getRenderContext().setVertexLabelTransformer(new TopicNodeLabeller());
           // add a listener for ToolTips
           vv.setVertexToolTipTransformer(new ToStringLabeller());
           vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray));
             
            
           Container content = getContentPane();
           final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
           content.add(panel);
            
           final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse();
            
           vv.setGraphMouse(graphMouse);
           vv.addKeyListener(graphMouse.getModeKeyListener());
           vv.addPreRenderPaintable(rings);
            
           hyperbolicViewSupport = new ViewLensSupport<Node, Integer>(vv, new HyperbolicShapeTransformer(vv, vv
                   .getRenderContext().getMultiLayerTransformer().getTransformer(Layer.VIEW)), new ModalLensGraphMouse());
            
           graphMouse.addItemListener(hyperbolicViewSupport.getGraphMouse().getModeListener());
            
           JComboBox modeBox = graphMouse.getModeComboBox();
           modeBox.addItemListener(graphMouse.getModeListener());
           graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);
            
           final ScalingControl scaler = new CrossoverScalingControl();
            
           vv.scaleToLayout(scaler);
            
           JButton plus = new JButton("+");
           plus.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e) {
                   scaler.scale(vv, 1.1f, vv.getCenter());
               }
           });
           JButton minus = new JButton("-");
           minus.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e) {
                   scaler.scale(vv, 1 / 1.1f, vv.getCenter());
               }
           });
            
           JToggleButton radial = new JToggleButton("Balloon");
           radial.addItemListener(new ItemListener() {
            
               public void itemStateChanged(ItemEvent e) {
                   if (e.getStateChange() == ItemEvent.SELECTED) {
            
                       LayoutTransition<Node, Integer> lt = new LayoutTransition<Node, Integer>(vv, layout, radialLayout);
                       Animator animator = new Animator(lt);
                       animator.start();
                       vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity();
                       vv.addPreRenderPaintable(rings);
                   } else {
            
                       LayoutTransition<Node, Integer> lt = new LayoutTransition<Node, Integer>(vv, radialLayout, layout);
                       Animator animator = new Animator(lt);
                       animator.start();
                       vv.getRenderContext().getMultiLayerTransformer().getTransformer(Layer.LAYOUT).setToIdentity();
                       vv.removePreRenderPaintable(rings);
                   }
                   vv.repaint();
               }
           });
           final JRadioButton hyperView = new JRadioButton("Hyperbolic View");
           hyperView.addItemListener(new ItemListener() {
               public void itemStateChanged(ItemEvent e) {
                   hyperbolicViewSupport.activate(e.getStateChange() == ItemEvent.SELECTED);
               }
           });
            
           JPanel scaleGrid = new JPanel(new GridLayout(1, 0));
           scaleGrid.setBorder(BorderFactory.createTitledBorder("Zoom"));
            
           JPanel controls = new JPanel();
           scaleGrid.add(plus);
           scaleGrid.add(minus);
           controls.add(radial);
           controls.add(scaleGrid);
           controls.add(modeBox);
           controls.add(hyperView);
           content.add(controls, BorderLayout.SOUTH);
           */
    }

    private void writeGraph() {
        Container c = new Container();

        VisualizationViewer<Node, Integer> vv = new VisualizationViewer<Node, Integer>(balloonLayout,
                new Dimension(3000, 3000));
        vv.setBackground(Color.white);
        vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line());
        vv.getRenderContext().setVertexLabelTransformer(new TopicNodeLabeller(graph));
        vv.getRenderContext().setVertexIncludePredicate(new VertexDisplayPredicate(false));
        // add a listener for ToolTips
        vv.getRenderContext().setArrowFillPaintTransformer(new ConstantTransformer(Color.lightGray));
        //vv.addPreRenderPaintable(rings);
        vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.AUTO);
        rings = new Rings(balloonLayout, vv);
        vv.addPreRenderPaintable(rings);
        java.awt.image.BufferedImage bi = new java.awt.image.BufferedImage(3000, 3000,
                java.awt.image.BufferedImage.TYPE_INT_RGB);

        Graphics2D gr = bi.createGraphics();

        // MOST-IMPORTANT

        vv.setSize(3000, 3000);

        final ScalingControl scaler = new CrossoverScalingControl();

        vv.scaleToLayout(scaler);

        // MOST-IMPORTANT

        c.addNotify();

        c.add(vv);

        c.setVisible(true);

        c.paintComponents(gr);

        try {
            ImageIO.write(bi, "png", new File("vis.png"));
            System.out.println("done");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * 
     */
    private void createTree() {

        try {
            Twitter twitter = new TwitterFactory().getInstance();

            List<Tweet> allTweets = new ArrayList<Tweet>();
            String qString = "bp";
            Query query = new Query(qString);
            query.setRpp(100);
            query.setLang("en");

            int hits = 100;
            int page = 1;
            while (allTweets.size() < 1400 && page < 16 && hits == 100) {

                query.setPage(page);

                // System.out.println(query.toString());
                QueryResult result = twitter.search(query);
                List<Tweet> tweets = result.getTweets();
                allTweets.addAll(tweets);
                hits = tweets.size();
                System.out.println("page: " + page + " hits: " + hits + " all tweets:" + allTweets.size());
                page++;
            }
            System.out.println("hits: " + allTweets.size());

            Set<CharSequence> inputSet = new HashSet<CharSequence>();

            for (Tweet tweet : allTweets) {
                inputSet.add(tweet.getText());
            }

            Clusterer cl = new Clusterer(inputSet, TokenizedCharSequence.TOKENIZER_FACTORY);

            com.schnee.tweetgeister.data.Tree<CharSequence> mindmap = cl.buildTree();

            fillTree(mindmap);

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    private void fillTree(com.schnee.tweetgeister.data.Tree<CharSequence> mindmap) {

        Node<CharSequence> theRoot = mindmap.getRootElement();

        int tabLevel = 0;

        graph.addVertex(theRoot);

        walk(theRoot, tabLevel);

    }

    private void walk(Node<CharSequence> element, int tabLevel) {

        CharSequence text = element.getData();
        String theData = text.toString();

        theData = cleanNewLines(theData);

        tabLevel++;
        for (Node<CharSequence> data : element.getChildren()) {

            graph.addEdge(edgeFactory.create(), element, data);
            walk(data, tabLevel);

        }

    }

    private String cleanNewLines(String theData) {

        //theData = theData.replaceAll("[\\n\\r]+", " ");
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < theData.length(); i++) {
            char toAppend = 'a';
            switch (theData.charAt(i)) {
            case '\r':
                toAppend = ' ';
                break;
            case '\n':
                toAppend = ' ';
                break;
            default:
                toAppend = theData.charAt(i);
            }
            sb.append(toAppend);
        }
        theData = sb.toString();

        return theData;

    }

    /**
     * a driver for this demo
     */
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        Container content = frame.getContentPane();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        content.add(new TweetgeisterBalloonLayout());
        frame.pack();
        frame.setVisible(true);
    }

    private final static class VertexDisplayPredicate<V, E> implements Predicate<Context<Graph<V, E>, V>>
    //  extends  AbstractGraphPredicate<V,E>
    {
        protected boolean filter_small;

        protected final static int MIN_DEGREE = 4;

        public VertexDisplayPredicate(boolean filter) {
            this.filter_small = filter;
        }

        public void filterSmall(boolean b) {
            filter_small = b;
        }

        public boolean evaluate(Context<Graph<V, E>, V> context) {
            Graph<V, E> graph = context.graph;
            V v = context.element;
            //        Vertex v = (Vertex)arg0;
            if (filter_small)
                return (graph.degree(v) >= MIN_DEGREE);
            else
                return true;
        }
    }
}