com.rapidminer.gui.graphs.GraphViewer.java Source code

Java tutorial

Introduction

Here is the source code for com.rapidminer.gui.graphs.GraphViewer.java

Source

/**
 * Copyright (C) 2001-2015 by RapidMiner and the contributors
 *
 * Complete list of developers available at our web site:
 *
 *      http://rapidminer.com
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/.
 */
package com.rapidminer.gui.graphs;

import com.rapidminer.RapidMiner;
import com.rapidminer.gui.actions.export.ExportImageAction;
import com.rapidminer.gui.actions.export.PrintableComponent;
import com.rapidminer.gui.actions.export.SimplePrintableComponent;
import com.rapidminer.gui.graphs.actions.PickingModeAction;
import com.rapidminer.gui.graphs.actions.TransformingModeAction;
import com.rapidminer.gui.graphs.actions.ZoomInAction;
import com.rapidminer.gui.graphs.actions.ZoomOutAction;
import com.rapidminer.gui.tools.ExtendedJScrollPane;
import com.rapidminer.gui.tools.ExtendedJToolBar;
import com.rapidminer.gui.tools.IconSize;
import com.rapidminer.gui.tools.SwingTools;
import com.rapidminer.parameter.ParameterType;
import com.rapidminer.report.Renderable;
import com.rapidminer.tools.I18N;
import edu.uci.ics.jung.algorithms.layout.ISOMLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.algorithms.layout.StaticLayout;
import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.Layer;
import edu.uci.ics.jung.visualization.MultiLayerTransformer;
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.GraphMouseListener;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ScalingControl;
import edu.uci.ics.jung.visualization.decorators.ConstantDirectionalEdgeValueTransformer;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.layout.LayoutTransition;
import edu.uci.ics.jung.visualization.renderers.BasicVertexRenderer;
import edu.uci.ics.jung.visualization.renderers.EdgeLabelRenderer;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import edu.uci.ics.jung.visualization.renderers.VertexLabelRenderer;
import edu.uci.ics.jung.visualization.util.Animator;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.HeadlessException;
import java.awt.Insets;
import java.awt.Paint;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
import java.util.List;

import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import javax.swing.JToolBar;

import org.apache.commons.collections15.Transformer;

/**
 * The basic graph viewer component for graphs.
 * 
 * @author Ingo Mierswa
 */
public class GraphViewer<V, E> extends JPanel implements Renderable, PrintableComponent {

    private static final long serialVersionUID = -7501422172633548861L;

    public static final int MARGIN = 10;

    public static final Font EDGE_FONT = new Font("SansSerif", Font.PLAIN, 10);

    public static final Font VERTEX_BOLD_FONT = new Font("SansSerif", Font.BOLD, 11);

    public static final Font VERTEX_PLAIN_FONT = new Font("SansSerif", Font.PLAIN, 11);

    private static final String INSTRUCTIONS = "<html>" + "<h3>General Info:</h3>" + "<ul>"
            + "<li>Mousewheel scales the view</li>" + "</ul>" + "<h3>Transforming Mode:</h3>" + "<ul>"
            + "<li>Mouse1+drag pans the graph" + "<li>Mouse1+Shift+drag rotates the graph"
            + "<li>Mouse1+CTRL(or Command)+drag shears the graph" + "</ul>" + "<h3>Picking Mode:</h3>" + "<ul>"
            + "<li>Mouse1 on a node selects the node" + "<li>Mouse1 elsewhere unselects all nodes"
            + "<li>Mouse1+Shift on a node adds/removes node selection"
            + "<li>Mouse1+drag on a node moves all selected nodes"
            + "<li>Mouse1+drag elsewhere selects modes in a region"
            + "<li>Mouse1+Shift+drag adds selection of modes in a new region"
            + "<li>Mouse1+CTRL on a mode selects the mode and centers the display on it" + "</ul>" + "</html>";

    private final transient Action transformAction = new TransformingModeAction<>(this, IconSize.SMALL);
    private final transient Action pickingAction = new PickingModeAction<>(this, IconSize.SMALL);

    private VisualizationViewer<V, E> vv;

    private transient Layout<V, E> layout;

    private transient GraphCreator<V, E> graphCreator;

    private LayoutSelection<V, E> layoutSelection;

    private transient ScalingControl scaler = new CrossoverScalingControl();

    private transient DefaultModalGraphMouse graphMouse;

    private boolean showEdgeLabels = true;

    private boolean showVertexLabels = true;

    private transient JSplitPane objectViewerSplitPane;

    private transient ModalGraphMouse.Mode currentMode = ModalGraphMouse.Mode.TRANSFORMING;

    public GraphViewer(final GraphCreator<V, E> graphCreator) {
        try {
            if (!RapidMiner.getExecutionMode().isHeadless()) {
                graphMouse = new DefaultModalGraphMouse(1 / 1.1f, 1.1f);
            }
        } catch (HeadlessException e) {
        }

        this.graphCreator = graphCreator;

        setLayout(new BorderLayout());

        Graph<V, E> graph = graphCreator.createGraph();
        this.layoutSelection = new LayoutSelection<>(this, graph);
        this.layout = new ISOMLayout<>(graph);
        vv = new VisualizationViewer<V, E>(layout) {

            private static final long serialVersionUID = 8247229781249216143L;

            private boolean initialized = false;

            /**
             * Necessary in order to re-change layout after first painting (starting position and
             * size).
             */
            @Override
            public void paint(Graphics g) {
                super.paint(g);
                if (!initialized) {
                    initialized = true;
                    updateLayout();
                    if (objectViewerSplitPane != null) {
                        objectViewerSplitPane.setDividerLocation(0.9);
                    }
                }
            }
        };
        vv.setBorder(BorderFactory.createEmptyBorder());
        vv.setBackground(Color.white);

        // === design ===

        // ## edge layout ##
        // EDGE SHAPE
        int edgeShapeType = graphCreator.getEdgeShape();
        switch (edgeShapeType) {
        case GraphCreator.EDGE_SHAPE_LINE:
            vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line<V, E>());
            break;
        case GraphCreator.EDGE_SHAPE_QUAD_CURVE:
            vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.QuadCurve<V, E>());
            break;
        case GraphCreator.EDGE_SHAPE_CUBIC_CURVE:
            vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.CubicCurve<V, E>());
            break;
        case GraphCreator.EDGE_SHAPE_BENT_LINE:
            vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.BentLine<V, E>());
            break;
        case GraphCreator.EDGE_SHAPE_WEDGE:
            vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Wedge<V, E>(5));
            break;
        default:
            vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.Line<V, E>());
            break;
        }

        // EDGE FONT
        vv.getRenderContext().setEdgeFontTransformer(new Transformer<E, Font>() {

            @Override
            public Font transform(E arg0) {
                return EDGE_FONT;
            }
        });

        // EDGE COLORS
        vv.getRenderContext().setEdgeDrawPaintTransformer(new Transformer<E, Paint>() {

            @Override
            public Paint transform(E edge) {
                double edgeStrength = graphCreator.getEdgeStrength(edge);
                int value = (int) Math.max(140, Math.min(230, 230 - edgeStrength * 90));
                return new Color(value, value, value);
            }
        });
        vv.getRenderContext().setArrowDrawPaintTransformer(new Transformer<E, Paint>() {

            @Override
            public Paint transform(E edge) {
                double edgeStrength = graphCreator.getEdgeStrength(edge);
                int value = (int) Math.max(140, Math.min(230, 230 - edgeStrength * 90));
                return new Color(value, value, value).darker();
            }
        });
        vv.getRenderContext().setArrowFillPaintTransformer(new Transformer<E, Paint>() {

            @Override
            public Paint transform(E edge) {
                double edgeStrength = graphCreator.getEdgeStrength(edge);
                int value = (int) Math.max(140, Math.min(230, 230 - edgeStrength * 90));
                return new Color(value, value, value);
            }
        });

        // EDGE LABEL POSITION
        vv.getRenderContext()
                .setEdgeLabelClosenessTransformer(new ConstantDirectionalEdgeValueTransformer<V, E>(0.5d, 0.5d));
        int labelOffset = graphCreator.getLabelOffset();
        if (labelOffset >= 0) {
            vv.getRenderContext().setLabelOffset(labelOffset);
        }

        // EDGE LABELS
        vv.getRenderContext().setEdgeLabelTransformer(new Transformer<E, String>() {

            @Override
            public String transform(E object) {
                return graphCreator.getEdgeName(object);
            }
        });
        // EDGE LABEL RENDERER
        Renderer.EdgeLabel<V, E> edgeLabelRenderer = graphCreator.getEdgeLabelRenderer();
        if (edgeLabelRenderer != null) {
            vv.getRenderer().setEdgeLabelRenderer(edgeLabelRenderer); // renderer...
        }
        vv.getRenderContext().setEdgeLabelRenderer(new EdgeLabelRenderer() { // ...context!

            private JLabel renderer = new JLabel();

            @Override
            public <T> Component getEdgeLabelRendererComponent(JComponent parent, Object value, Font font,
                    boolean isSelected, T edge) {
                this.renderer.setFont(font);
                if (graphCreator.isEdgeLabelDecorating()) {
                    this.renderer.setOpaque(true);
                    renderer.setBackground(Color.WHITE);
                    // use this for a more fancy look and feel
                    // renderer.setBackground(SwingTools.TRANSPARENT_YELLOW);
                    // this.renderer.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(SwingTools.DARK_BLUE),
                    // BorderFactory.createEmptyBorder(1,1,1,1)));
                }
                this.renderer.setText(value.toString());
                return this.renderer;
            }

            /** Let the graph model decide. */
            @Override
            public boolean isRotateEdgeLabels() {
                return graphCreator.isRotatingEdgeLabels();
            }

            /** Does nothing. */
            @Override
            public void setRotateEdgeLabels(boolean rotate) {
            }
        });

        // ## vertex layout ##

        // VERTEX FONT
        vv.getRenderContext().setVertexFontTransformer(new Transformer<V, Font>() {

            @Override
            public Font transform(V vertex) {
                if (graphCreator.isBold(vertex)) {
                    return VERTEX_BOLD_FONT;
                } else {
                    return VERTEX_PLAIN_FONT;
                }
            }
        });
        // VERTEX NAME
        vv.getRenderContext().setVertexLabelTransformer(new Transformer<V, String>() {

            @Override
            public String transform(V object) {
                return graphCreator.getVertexName(object);
            }
        });
        // VERTEX FILL PAINT
        Transformer<V, Paint> paintTransformer = graphCreator.getVertexPaintTransformer(vv);
        if (paintTransformer == null) {
            paintTransformer = new Transformer<V, Paint>() {

                @Override
                public Paint transform(V vertex) {
                    if (vv.getPickedVertexState().isPicked(vertex)) {
                        return SwingTools.LIGHT_YELLOW;
                    } else {
                        return SwingTools.LIGHT_BLUE;
                    }
                }
            };
        }
        vv.getRenderContext().setVertexFillPaintTransformer(paintTransformer);

        // VERTEX DRAW PAINT
        vv.getRenderContext().setVertexDrawPaintTransformer(new Transformer<V, Paint>() {

            @Override
            public Paint transform(V vertex) {
                if (vv.getPickedVertexState().isPicked(vertex)) {
                    return SwingTools.DARKEST_YELLOW.darker();
                } else {
                    return SwingTools.DARKEST_BLUE.darker();
                }
            }
        });
        // VERTEX TOOL TIP
        this.vv.setVertexToolTipTransformer(new Transformer<V, String>() {

            @Override
            public String transform(V vertex) {
                return graphCreator.getVertexToolTip(vertex);
            }
        });
        // VERTEX SHAPE
        vv.getRenderContext().setVertexShapeTransformer(new ExtendedVertexShapeTransformer<>(graphCreator));

        // VERTEX RENDERER
        Renderer.Vertex<V, E> vertexRenderer = graphCreator.getVertexRenderer();
        if (vertexRenderer != null) {
            vv.getRenderer().setVertexRenderer(vertexRenderer);
        }

        // VERTEX LABEL RENDERER
        setDefaultLabelPosition();
        // custom renderer?
        Renderer.VertexLabel<V, E> customVertexLabelRenderer = graphCreator.getVertexLabelRenderer();
        if (customVertexLabelRenderer != null) {
            vv.getRenderer().setVertexLabelRenderer(customVertexLabelRenderer);
        }

        // context
        vv.getRenderContext().setVertexLabelRenderer(new VertexLabelRenderer() {

            private JLabel label = new JLabel();

            @Override
            public <T> Component getVertexLabelRendererComponent(JComponent parent, Object object, Font font,
                    boolean isSelection, T vertex) {
                label.setFont(font);
                if (object != null) {
                    label.setText(object.toString());
                } else {
                    label.setText("");
                }
                return label;
            }

        });

        // === end of design ===

        // === main panel ===

        if (graphCreator.getObjectViewer() == null) {
            add(vv, BorderLayout.CENTER);
        } else {
            JComponent viewer = graphCreator.getObjectViewer().getViewerComponent();
            if (viewer != null) {
                viewer.setBorder(null);
                objectViewerSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
                objectViewerSplitPane.setResizeWeight(1);
                objectViewerSplitPane.add(vv, 0);
                objectViewerSplitPane.add(viewer, 1);
                add(objectViewerSplitPane, BorderLayout.CENTER);
            } else {
                add(vv, BorderLayout.CENTER);
            }
        }

        // === control panel ===

        Component controlPanel = createControlPanel();
        add(new ExtendedJScrollPane(controlPanel), BorderLayout.WEST);

        this.showEdgeLabels = !graphCreator.showEdgeLabelsDefault();
        togglePaintEdgeLabels();
        this.showVertexLabels = !graphCreator.showVertexLabelsDefault();
        togglePaintVertexLabels();

        this.layoutSelection.setLayout();
    }

    public LayoutSelection<V, E> getLayoutSelection() {
        return this.layoutSelection;
    }

    private JComponent createControlPanel() {
        // === mouse behaviour ===
        if (graphMouse != null) {
            vv.setGraphMouse(graphMouse);
            vv.addKeyListener(graphMouse.getModeKeyListener());
            graphMouse.setMode(ModalGraphMouse.Mode.TRANSFORMING);
        }
        transformAction.setEnabled(false);
        pickingAction.setEnabled(true);

        vv.addGraphMouseListener(new GraphMouseListener<V>() {

            @Override
            public void graphClicked(V vertex, MouseEvent arg1) {
            }

            @Override
            public void graphPressed(V arg0, MouseEvent arg1) {
            }

            @Override
            public void graphReleased(V vertex, MouseEvent arg1) {
                if (currentMode.equals(ModalGraphMouse.Mode.TRANSFORMING)) {
                    if (graphCreator.getObjectViewer() != null) {
                        vv.getPickedVertexState().clear();
                        vv.getPickedVertexState().pick(vertex, true);
                        graphCreator.getObjectViewer().showObject(graphCreator.getObject(vertex));
                    }
                }
            }
        });

        JPanel controls = new JPanel();
        GridBagLayout gbLayout = new GridBagLayout();
        controls.setLayout(gbLayout);
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.BOTH;
        c.insets = new Insets(4, 4, 4, 4);
        c.weightx = 1;
        c.weighty = 0;

        // zooming
        JToolBar zoomBar = new ExtendedJToolBar();
        zoomBar.setLayout(new FlowLayout(FlowLayout.CENTER));
        zoomBar.add(new ZoomInAction(this, IconSize.SMALL));
        zoomBar.add(new ZoomOutAction(this, IconSize.SMALL));
        zoomBar.setBorder(BorderFactory.createTitledBorder("Zoom"));
        c.gridwidth = GridBagConstraints.REMAINDER;
        gbLayout.setConstraints(zoomBar, c);
        controls.add(zoomBar);

        // mode
        JToolBar modeBar = new ExtendedJToolBar();
        modeBar.setLayout(new FlowLayout(FlowLayout.CENTER));
        modeBar.add(transformAction);
        modeBar.add(pickingAction);
        modeBar.setBorder(BorderFactory.createTitledBorder("Mode"));
        c.gridwidth = GridBagConstraints.REMAINDER;
        gbLayout.setConstraints(modeBar, c);
        controls.add(modeBar);

        // layout selection
        c.gridwidth = GridBagConstraints.REMAINDER;
        gbLayout.setConstraints(layoutSelection, c);
        controls.add(layoutSelection);

        // show node labels
        JCheckBox nodeLabels = new JCheckBox("Node Labels", graphCreator.showVertexLabelsDefault());
        nodeLabels.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                togglePaintVertexLabels();
            }
        });
        c.gridwidth = GridBagConstraints.REMAINDER;
        gbLayout.setConstraints(nodeLabels, c);
        controls.add(nodeLabels);

        // show edge labels
        JCheckBox edgeLabels = new JCheckBox("Edge Labels", graphCreator.showEdgeLabelsDefault());
        edgeLabels.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                togglePaintEdgeLabels();
            }
        });
        c.gridwidth = GridBagConstraints.REMAINDER;
        gbLayout.setConstraints(edgeLabels, c);
        controls.add(edgeLabels);

        // option components
        for (int i = 0; i < graphCreator.getNumberOfOptionComponents(); i++) {
            JComponent optionComponent = graphCreator.getOptionComponent(this, i);
            if (optionComponent != null) {
                c.gridwidth = GridBagConstraints.REMAINDER;
                gbLayout.setConstraints(optionComponent, c);
                controls.add(optionComponent);
            }
        }

        // save image
        JButton imageButton = new JButton("Save Image...");
        imageButton.setToolTipText("Saves an image of the current graph.");
        imageButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                final Component tosave = vv;
                new ExportImageAction(false) {

                    private static final long serialVersionUID = 1L;

                    @Override
                    protected PrintableComponent getPrintableComponent() {
                        return new SimplePrintableComponent(tosave, "Graph");
                    }

                }.actionPerformed(e);
            }
        });
        c.gridwidth = GridBagConstraints.REMAINDER;
        gbLayout.setConstraints(imageButton, c);
        controls.add(imageButton);

        // help
        JButton help = new JButton("Help");
        help.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(vv, INSTRUCTIONS);
            }
        });
        c.gridwidth = GridBagConstraints.REMAINDER;
        gbLayout.setConstraints(help, c);
        controls.add(help);

        JPanel fillPanel = new JPanel();
        c.weighty = 1.0d;
        c.gridwidth = GridBagConstraints.REMAINDER;
        gbLayout.setConstraints(fillPanel, c);
        controls.add(fillPanel);

        return controls;
    }

    public void updateLayout() {
        changeLayout(this.layout, this.layoutSelection.getAnimate(), 0, 0);
    }

    public void changeLayout(final Layout<V, E> newLayout, boolean animate, int desiredWidth, int desiredHeight) {
        if (newLayout != null) {
            MultiLayerTransformer transformer = vv.getRenderContext().getMultiLayerTransformer();
            double scale = transformer.getTransformer(Layer.VIEW).getScale();

            // set desired size
            if ((desiredWidth > 0) && (desiredHeight > 0)) {
                vv.setSize(desiredWidth, desiredHeight);
                try {
                    newLayout.setSize(new Dimension(desiredWidth, desiredHeight));
                } catch (Exception e) {
                    // do nothing - some layouts do not support setting of size
                }
            } else {
                // vv.setSize(600, 600);
                int layoutWidth = (int) (vv.getWidth() / scale);
                int layoutHeight = (int) (vv.getHeight() / scale);
                try {
                    newLayout.setSize(new Dimension(layoutWidth, layoutHeight));
                } catch (Exception e) {
                    // do nothing - some layouts do not support setting of size
                }
            }

            if (layout == null) {
                // initial layout --> no transition possible!
                vv.setGraphLayout(newLayout);
            } else {
                // No transition possible if no edges in graph!
                if (animate) {
                    if (newLayout.getGraph().getEdgeCount() > 0 || newLayout.getGraph().getVertexCount() > 0) {
                        try {
                            LayoutTransition<V, E> lt = new LayoutTransition<>(vv, layout, newLayout);
                            Animator animator = new Animator(lt);
                            animator.start();
                        } catch (Throwable e) {
                            // any error --> no transition possible!
                            vv.setGraphLayout(newLayout);
                        }
                    }
                } else {
                    vv.setGraphLayout(newLayout);
                }
            }
            this.layout = newLayout;

            vv.scaleToLayout(this.scaler);

            double viewX = transformer.getTransformer(Layer.VIEW).getTranslateX();
            double viewY = transformer.getTransformer(Layer.VIEW).getTranslateX();
            double scaleViewX = viewX * scale;
            double scaleViewY = viewY * scale;
            transformer.getTransformer(Layer.VIEW).translate(-scaleViewX, -scaleViewY);

            Thread changeToStaticThread = new Thread() {

                @Override
                public void run() {
                    try {
                        sleep(10000);
                    } catch (InterruptedException e) {
                        // do nothing
                    }
                    // change to static
                    // change to static
                    if (GraphViewer.this.layout.equals(newLayout)) { // still the same layout?
                        vv.setGraphLayout(new StaticLayout<>(layout.getGraph(), layout));
                    }
                }
            };
            changeToStaticThread.start();
        }
    }

    /**
     * VertexLabel is not parameterized in Jung. In order to avoid to make all things unchecked, the
     * default label position setting is done in this method.
     */
    private void setDefaultLabelPosition() {
        vv.getRenderer().getVertexLabelRenderer().setPosition(Renderer.VertexLabel.Position.CNTR);
    }

    public void zoomIn() {
        scaler.scale(vv, 1.1f, vv.getCenter());
    }

    public void zoomOut() {
        scaler.scale(vv, 1 / 1.1f, vv.getCenter());
    }

    public void changeMode(ModalGraphMouse.Mode mode) {
        if (graphMouse != null) {
            graphMouse.setMode(mode);
        }
        this.currentMode = mode;
        if (mode.equals(ModalGraphMouse.Mode.PICKING)) {
            pickingAction.setEnabled(false);
            transformAction.setEnabled(true);
        } else {
            pickingAction.setEnabled(true);
            transformAction.setEnabled(false);
        }
    }

    private void togglePaintEdgeLabels() {
        setPaintEdgeLabels(!showEdgeLabels);
    }

    public void setPaintEdgeLabels(boolean showEdgeLabels) {
        this.showEdgeLabels = showEdgeLabels;
        if (this.showEdgeLabels) {
            vv.getRenderContext().setEdgeLabelTransformer(new Transformer<E, String>() {

                @Override
                public String transform(E object) {
                    return graphCreator.getEdgeName(object);
                }
            });
        } else {
            vv.getRenderContext().setEdgeLabelTransformer(new Transformer<E, String>() {

                @Override
                public String transform(E object) {
                    return null;
                }
            });
        }
        vv.repaint();
    }

    private void togglePaintVertexLabels() {
        setPaintVertexLabels(!showVertexLabels);
    }

    public void setPaintVertexLabels(boolean showVertexLabels) {
        this.showVertexLabels = showVertexLabels;
        if (this.showVertexLabels) {
            Renderer.Vertex<V, E> vertexRenderer = graphCreator.getVertexRenderer();
            if (vertexRenderer != null) {
                vv.getRenderer().setVertexRenderer(vertexRenderer);
            }
            vv.getRenderContext().setVertexShapeTransformer(new ExtendedVertexShapeTransformer<>(graphCreator));
            vv.getRenderContext().setVertexLabelTransformer(new Transformer<V, String>() {

                @Override
                public String transform(V object) {
                    return graphCreator.getVertexName(object);
                }
            });
        } else {
            vv.getRenderer().setVertexRenderer(new BasicVertexRenderer<V, E>());
            vv.getRenderContext().setVertexShapeTransformer(new BasicVertexShapeTransformer<V>());
            vv.getRenderContext().setVertexLabelTransformer(new Transformer<V, String>() {

                @Override
                public String transform(V object) {
                    return null;
                }
            });
        }
        vv.repaint();
    }

    public GraphCreator<V, E> getGraphCreator() {
        return this.graphCreator;
    }

    public Component getVisualizationComponent() {
        return vv;
    }

    @Override
    public void prepareRendering() {
    }

    @Override
    public void finishRendering() {
    }

    @Override
    public int getRenderHeight(int preferredHeight) {
        int height = vv.getHeight();
        if (height < 1) {
            height = preferredHeight;
        }
        return height;
    }

    @Override
    public int getRenderWidth(int preferredWidth) {
        int width = vv.getWidth();
        if (width < 1) {
            width = preferredWidth;
        }
        return width;
    }

    @Override
    public void render(Graphics graphics, int width, int height) {
        vv.setSize(width, height);
        vv.setBorder(BorderFactory.createEmptyBorder());
        changeLayout(this.layout, false, width, height);
        vv.paint(graphics);
    }

    public List<ParameterType> getParameterTypes() {
        return new LinkedList<>();
    }

    @Override
    public Component getExportComponent() {
        return vv;
    }

    @Override
    public String getExportName() {
        return I18N.getMessage(I18N.getGUIBundle(), "gui.cards.result_view.graph_view.title");
    }

    @Override
    public String getIdentifier() {
        return null;
    }

    @Override
    public String getExportIconName() {
        return I18N.getGUIMessage("gui.cards.result_view.graph_view.icon");
    }
}