All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.davidmoten.xuml.StateDiagramViewer Maven / Gradle / Ivy

package com.github.davidmoten.xuml;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.print.PrinterException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;

import org.apache.commons.collections15.Transformer;

import edu.uci.ics.jung.algorithms.layout.FRLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.graph.DirectedSparseGraph;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import xuml.tools.miuml.metamodel.jaxb.Class;
import xuml.tools.miuml.metamodel.jaxb.ModeledDomain;
import xuml.tools.model.compiler.Util;

public class StateDiagramViewer {

    private final JFrame frame = new JFrame();
    private final JPanel vvContainer = createVvContainer();
    private volatile JMenu classMenu;

    private final static ThreadLocal state = new ThreadLocal<>();

    private void open(ModeledDomain domain) {
        if (classMenu == null)
            throw new RuntimeException("must call start() before calling open(domain)");
        classMenu.removeAll();
        List classes = Util.getClasses(domain);
        classes.stream().forEach(cls -> {
            JMenuItem m = new JMenuItem(cls.getName());
            m.setEnabled(cls.getLifecycle() != null);
            m.addActionListener(evt -> show(cls));
            classMenu.add(m);
        });
        // show the first class with a lifecyle
        classes.stream().filter(cls -> cls.getLifecycle() != null).limit(1)
                .forEach(cls -> show(cls));
    }

    public void show(Class c) {
        System.out.println("showing " + c.getName());
        Graph g = new DirectedSparseGraph();
        if (c.getLifecycle() != null) {
            c.getLifecycle().getState().stream().forEach(state -> g.addVertex(state.getName()));
            c.getLifecycle().getTransition().stream().forEach(transition -> {
                String fromState = transition.getState();
                String toState = transition.getDestination();
                String eventName = c.getLifecycle().getEvent().stream().map(ev -> ev.getValue())
                        .filter(event -> event.getID().equals(transition.getEventID()))
                        .map(event -> event.getName()).findAny().get();
                g.addEdge(new Edge(eventName), fromState, toState);
            });
        }
        if (!g.getVertices().isEmpty()) {
            VisualizationViewer vv = createVisualizationViewer(g);
            EventQueue.invokeLater(() -> {
                vvContainer.removeAll();
                vvContainer.add(vv);
                vvContainer.setFocusable(true);
                vvContainer.repaint();
                vvContainer.revalidate();
                System.out.println("added vv");
                frame.setTitle(c.getName());
            });
        }
    }

    private void start() {
        EventQueue.invokeLater(() -> {
            // Creates a menubar for a JFrame
            JMenuBar menuBar = new JMenuBar();
            // Add the menubar to the frame
            frame.setJMenuBar(menuBar);
            // Define and add two drop down menu to the menubar
            JMenu fileMenu = new JMenu("File");
            classMenu = new JMenu("Class");
            JMenu editMenu = new JMenu("Edit");
            menuBar.add(fileMenu);
            menuBar.add(editMenu);
            menuBar.add(classMenu);
            JMenuItem openMenuItem = new JMenuItem("Open");
            JMenuItem printMenuItem = new JMenuItem("Print...");
            JMenuItem saveAsImageMenuItem = new JMenuItem("Save as PNG...");
            JMenuItem exitMenuItem = new JMenuItem("Exit");
            fileMenu.add(openMenuItem);
            fileMenu.add(printMenuItem);
            fileMenu.add(saveAsImageMenuItem);
            fileMenu.add(exitMenuItem);
            openMenuItem.addActionListener(System.out::println);
            exitMenuItem.addActionListener(e -> System.exit(0));
            printMenuItem.addActionListener(e -> print());
            saveAsImageMenuItem.addActionListener(e -> saveAsImage());

            frame.getContentPane().add(vvContainer);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(new Dimension(1000, 800));
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        });

    }

    private void saveAsImage() {
        JFileChooser fc = new JFileChooser();
        fc.addChoosableFileFilter(new ImageFilter());
        int returnVal = fc.showSaveDialog(vvContainer);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            if (!file.getName().toUpperCase().endsWith(".PNG"))
                file = new File(file.getAbsolutePath() + ".png");
            Color bg = vvContainer.getBackground();
            try {
                vvContainer.setPreferredSize(vvContainer.getSize());
                vvContainer.setBackground(Color.white);
                Panels.saveImage(vvContainer, file);
            } catch (RuntimeException e1) {
                e1.printStackTrace();
            } finally {
                vvContainer.setBackground(bg);
            }
        }
    }

    private void print() {
        Color bg = vvContainer.getBackground();
        try {
            vvContainer.setPreferredSize(vvContainer.getSize());
            vvContainer.setBackground(Color.white);
            Panels.print(vvContainer);
        } catch (PrinterException e1) {
            e1.printStackTrace();
        } finally {
            vvContainer.setBackground(bg);
        }
    }

    private static JPanel createVvContainer() {
        JPanel panel = new JPanel();
        panel.setPreferredSize(new Dimension(800, 600));
        // panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        panel.setLayout(new GridLayout(0, 1));
        return panel;
    }

    public static final class Edge {
        final String name;

        Edge(String name) {
            this.name = name;
        }

        public static Edge of(String name) {
            return new Edge(name);
        }
    }

    private static class DrawingState {

    }

    private static VisualizationViewer createVisualizationViewer(
            Graph graph) {
        FRLayout layout = new FRLayout(graph, new Dimension(800, 600));
        while (!layout.done())
            layout.step();

        VisualizationViewer vv = new VisualizationViewer(layout,
                new Dimension(800, 600)) {

            private static final long serialVersionUID = -3546358007558213875L;

            @Override
            public void paintComponents(Graphics g) {
                try {
                    state.set(new DrawingState());
                    super.paintComponents(g);
                } finally {
                    state.remove();
                }
            }

        };
        vv.setBackground(Color.white);
        vv.getRenderContext().setVertexLabelTransformer(s -> s);
        vv.getRenderContext().setVertexFillPaintTransformer(vertex -> vertex.equals("Created")
                ? Color.decode("#B5D9E6") : Color.decode("#FFF1BC"));
        vv.getRenderContext().setVertexDrawPaintTransformer(vertex -> Color.black);
        vv.getRenderContext().setVertexShapeTransformer(createVertexShapeTransformer(layout));
        vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR);
        vv.getRenderContext().setEdgeLabelTransformer(edge -> " " + edge.name + " ");
        vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.QuadCurve());
        vv.getRenderer().setEdgeLabelRenderer(new MyEdgeLabelRenderer<>(-10, Color.white));

        // The following code adds capability for mouse picking of
        // vertices/edges. Vertices can even be moved!
        final DefaultModalGraphMouse graphMouse = new DefaultModalGraphMouse();
        vv.setGraphMouse(graphMouse);
        graphMouse.setMode(ModalGraphMouse.Mode.PICKING);
        return vv;
    }

    private static Transformer createVertexShapeTransformer(
            Layout layout) {
        return vertex -> {
            int w = 150;
            int margin = 5;
            int ascent = 12;
            int descent = 5;
            Shape shape = new Rectangle(-w / 2 - margin, -ascent - margin, w + 2 * margin,
                    (ascent + descent) + 2 * margin);
            return shape;
        };
    }

    private static class ImageFilter extends FileFilter {

        // Accept all directories and all gif, jpg, tiff, or png files.
        @Override
        public boolean accept(File f) {
            if (f.isDirectory()) {
                return true;
            }
            return f.getName().toUpperCase().endsWith(".PNG");
        }

        // The description of this filter
        @Override
        public String getDescription() {
            return "PNG files";
        }
    }

    public void start(String resource, String domainName) {
        start(StateDiagramViewer.class.getResourceAsStream(resource), domainName);
    }

    public void start(InputStream input, String domainName) {
        try (InputStream is = input) {
            start();
            ModeledDomain domain = Util.getModeledDomain(is, domainName);
            open(domain);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy