org.tros.logo.swing.LogoMenuBar.java Source code

Java tutorial

Introduction

Here is the source code for org.tros.logo.swing.LogoMenuBar.java

Source

/*
 * Copyright 2015-2016 Matthew Aguirre
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.tros.logo.swing;

import org.tros.torgo.swing.BufferedImageProvider;
import org.tros.logo.LogoCanvas;
import org.tros.torgo.swing.Localization;
import org.tros.torgo.Controller;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import javax.swing.JColorChooser;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URL;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageOutputStream;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import org.apache.batik.dom.GenericDOMImplementation;
import org.apache.commons.io.IOUtils;
import org.tros.torgo.TorgoToolkit;
import org.tros.torgo.swing.TorgoMenuBar;
import org.w3c.dom.DOMImplementation;
import org.apache.batik.svggen.*;
import org.apache.batik.anim.dom.SVGDOMImplementation;
import org.w3c.dom.Document;
import org.tros.utils.GifSequenceWriter;

/**
 * Sets up a menu bar for the Logo application.
 *
 * @author matta
 */
public final class LogoMenuBar extends TorgoMenuBar {

    private JMenuItem toolsPenColorChooser;
    private JMenuItem toolsCanvasColorChooser;

    private final LogoCanvas canvas;
    protected static final String WAIT_FOR_REPAINT = "wait-for-repaint";

    /**
     * Constructor.
     *
     * @param parent
     * @param controller
     * @param canvas
     */
    @SuppressWarnings("OverridableMethodCallInConstructor")
    public LogoMenuBar(Component parent, Controller controller, LogoCanvas canvas) {
        super(parent, controller);
        this.canvas = canvas;

        add(setupExportMenu());
        add(setupToolsMenu());
        JMenu menu = new JMenu("Logo Options");
        menu.add(setupMenu("Examples From Tortue", "logo/examples/tortue"));
        menu.add(setupMenu("Examples From ANTLR", "logo/examples/antlr"));

        final java.util.prefs.Preferences prefs = java.util.prefs.Preferences.userNodeForPackage(LogoMenuBar.class);
        final JCheckBoxMenuItem speedMenu = new JCheckBoxMenuItem("Wait for Repaint");
        boolean checked = prefs.getBoolean(WAIT_FOR_REPAINT, true);
        speedMenu.setSelected(checked);
        speedMenu.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                prefs.putBoolean(WAIT_FOR_REPAINT, speedMenu.isSelected());
            }
        });
        menu.add(speedMenu);
        add(menu);
    }

    /**
     * Create a SVG image. The image handler will write all images files to
     * "res/images".
     *
     * @param p
     * @param outStream
     * @throws UnsupportedEncodingException
     * @throws SVGGraphics2DIOException
     */
    private void generateSVG(Drawable p, OutputStream outStream)
            throws UnsupportedEncodingException, SVGGraphics2DIOException {
        DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
        String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI;
        Document myFactory = domImpl.createDocument(svgNS, "svg", null);
        SVGGeneratorContext ctx = SVGGeneratorContext.createDefault(myFactory);
        GenericImageHandler ihandler = new CachedImageHandlerPNGEncoder("res/images", null);
        ctx.setGenericImageHandler(ihandler);

        SVGGraphics2D svgGenerator = new SVGGraphics2D(ctx, false);

        TurtleState ts = new TurtleState();

        p.draw(svgGenerator, ts);
        // Create the SVG DOM tree.
        Writer out = new OutputStreamWriter(outStream, "UTF-8");
        svgGenerator.stream(out, true);
    }

    /**
     * Create an animated GIF.
     *
     * @param p
     * @param canvas
     * @param filename
     * @throws UnsupportedEncodingException
     * @throws SVGGraphics2DIOException
     * @throws IOException
     */
    private void generateGIF(final Drawable p, final BufferedImageProvider canvas, String filename)
            throws UnsupportedEncodingException, SVGGraphics2DIOException, IOException {
        final ImageOutputStream output = new FileImageOutputStream(new File(filename));
        final GifSequenceWriter writer = new GifSequenceWriter(output, canvas.getBufferedImage().getType(), 1,
                true);

        final BufferedImage image = canvas.getBufferedImage();

        final Graphics2D g2d = image.createGraphics();
        DrawListener dl = new DrawListener() {
            @Override
            public void drawn(Drawable sender) {
                try {
                    writer.writeToSequence(image);
                } catch (IOException ex) {
                }
            }
        };
        p.addListener(dl);

        TurtleState ts = new TurtleState();
        ts.width = image.getWidth();
        ts.height = image.getHeight();

        p.draw(g2d, ts);
        writer.close();

        p.removeListener(dl);
        org.tros.utils.logging.Logging.getLogFactory().getLogger(LogoMenuBar.class)
                .info("{0} animation is complete!", filename);
        JOptionPane.showMessageDialog(parent, MessageFormat.format("{0} animation is complete!", filename),
                "Animated GIF Sequence Complete", JOptionPane.INFORMATION_MESSAGE);
    }

    /**
     * Set up the menus for examples.
     *
     * @param name
     * @param base
     * @return
     */
    private JMenu setupMenu(String name, String base) {
        JMenu samplesMenu = new JMenu(name);
        try {
            InputStream resourceAsStream = TorgoToolkit.getDefaultResourceAccessor()
                    .open(base + "/resource.manifest");
            List<String> readLines = IOUtils.readLines(resourceAsStream, "utf-8");
            Collections.sort(readLines);
            for (String line : readLines) {
                JMenuItem jmi = new JMenuItem(base + "/" + line);
                if (!jmi.getText().endsWith("manifest")) {
                    samplesMenu.add(jmi);
                    jmi.addActionListener(new ActionListener() {

                        @Override
                        public void actionPerformed(ActionEvent e) {
                            String val = e.getActionCommand();
                            URL resource = ClassLoader.getSystemClassLoader().getResource(val);
                            LogoMenuBar.this.controller.openFile(resource);
                        }
                    });
                }
            }
        } catch (IOException ex) {
            org.tros.utils.logging.Logging.getLogFactory().getLogger(LogoMenuBar.class).fatal(null, ex);
        }
        return samplesMenu;
    }

    private void generatePNG(BufferedImageProvider bip, String filename) {
        BufferedImage bi = bip.getBufferedImage();
        File outputfile = new File(filename);
        try {
            ImageIO.write(bi, "png", outputfile);
        } catch (IOException ex) {
            Logger.getLogger(LogoMenuBar.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Set up the export menu.
     *
     * @return
     */
    private JMenu setupExportMenu() {
        JMenu exportMenu = new JMenu(Localization.getLocalizedString("ExportMenu"));

        JMenuItem exportGif = new JMenuItem(Localization.getLocalizedString("ExportGIF"));
        JMenuItem exportPng = new JMenuItem(Localization.getLocalizedString("ExportPNG"));
        JMenuItem exportSvg = new JMenuItem(Localization.getLocalizedString("ExportSVG"));

        exportSvg.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                JFileChooser chooser = new JFileChooser();
                chooser.setMultiSelectionEnabled(false);
                java.util.prefs.Preferences prefs = java.util.prefs.Preferences
                        .userNodeForPackage(LogoMenuBar.class);
                chooser.setCurrentDirectory(new File(prefs.get("export-directory", ".")));

                chooser.setVisible(true);
                int result = chooser.showSaveDialog(parent);

                if (result == JFileChooser.APPROVE_OPTION) {
                    String filename = chooser.getSelectedFile().getPath();
                    prefs.put("export-directory", chooser.getSelectedFile().getParent());
                    if (Drawable.class.isAssignableFrom(canvas.getClass())) {
                        try (FileOutputStream fos = new FileOutputStream(new File(filename))) {
                            generateSVG((Drawable) canvas, fos);
                            fos.flush();
                        } catch (IOException ex) {
                            org.tros.utils.logging.Logging.getLogFactory().getLogger(LogoMenuBar.class).warn(null,
                                    ex);
                        }
                    }
                }
            }
        });

        exportGif.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                JFileChooser chooser = new JFileChooser();
                chooser.setMultiSelectionEnabled(false);
                java.util.prefs.Preferences prefs = java.util.prefs.Preferences
                        .userNodeForPackage(LogoMenuBar.class);
                chooser.setCurrentDirectory(new File(prefs.get("export-directory", ".")));

                chooser.setVisible(true);
                int result = chooser.showSaveDialog(parent);

                if (result == JFileChooser.APPROVE_OPTION) {
                    final String filename = chooser.getSelectedFile().getPath();
                    prefs.put("export-directory", chooser.getSelectedFile().getParent());
                    Thread t = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            if (Drawable.class.isAssignableFrom(canvas.getClass())
                                    && BufferedImageProvider.class.isAssignableFrom((canvas.getClass()))) {
                                try {
                                    generateGIF(((Drawable) canvas).cloneDrawable(), (BufferedImageProvider) canvas,
                                            filename);
                                } catch (SVGGraphics2DIOException ex) {
                                    Logger.getLogger(LogoMenuBar.class.getName()).log(Level.SEVERE, null, ex);
                                } catch (IOException ex) {
                                    Logger.getLogger(LogoMenuBar.class.getName()).log(Level.SEVERE, null, ex);
                                }
                            }
                        }
                    });
                    t.setDaemon(true);
                    t.start();
                }
            }
        });
        exportPng.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                JFileChooser chooser = new JFileChooser();
                chooser.setMultiSelectionEnabled(false);
                java.util.prefs.Preferences prefs = java.util.prefs.Preferences
                        .userNodeForPackage(LogoMenuBar.class);
                chooser.setCurrentDirectory(new File(prefs.get("export-directory", ".")));

                chooser.setVisible(true);
                int result = chooser.showSaveDialog(parent);

                if (result == JFileChooser.APPROVE_OPTION) {
                    String filename = chooser.getSelectedFile().getPath();
                    prefs.put("export-directory", chooser.getSelectedFile().getParent());
                    // retrieve image
                    if (BufferedImageProvider.class.isAssignableFrom(canvas.getClass())) {
                        generatePNG((BufferedImageProvider) canvas, filename);
                    }
                }
            }
        });

        exportMenu.add(exportSvg);
        exportMenu.add(exportGif);
        exportMenu.add(exportPng);
        exportMenu.setMnemonic('X');
        exportSvg.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.ALT_MASK));
        exportGif.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_G, InputEvent.ALT_MASK));
        exportPng.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.ALT_MASK));
        return (exportMenu);
    }

    /**
     * Set up the tools menu.
     *
     * @return
     */
    private JMenu setupToolsMenu() {
        JMenu toolsMenu = new JMenu(Localization.getLocalizedString("ToolsMenu"));

        toolsPenColorChooser = new JMenuItem(Localization.getLocalizedString("ToolsPenColorChooser"));
        toolsCanvasColorChooser = new JMenuItem(Localization.getLocalizedString("ToolsCanvasColorChooser"));

        toolsPenColorChooser.setMnemonic('P');
        toolsCanvasColorChooser.setMnemonic('C');

        toolsPenColorChooser.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                Color selected = JColorChooser.showDialog(parent, Localization.getLocalizedString("ColorChooser"),
                        null);
                if (selected != null) {
                    int red = selected.getRed();
                    int green = selected.getGreen();
                    int blue = selected.getBlue();
                    String hex = String.format("#%02x%02x%02x", red, green, blue);
                    controller.insertCommand("pencolor" + " " + hex);
                }
            }
        });
        toolsCanvasColorChooser.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                Color selected = JColorChooser.showDialog(parent, Localization.getLocalizedString("ColorChooser"),
                        null);
                if (selected != null) {
                    int red = selected.getRed();
                    int green = selected.getGreen();
                    int blue = selected.getBlue();
                    String hex = String.format("#%02x%02x%02x", red, green, blue);
                    controller.insertCommand("canvascolor" + " " + hex);
                }
            }
        });

        toolsMenu.add(toolsPenColorChooser);
        toolsMenu.add(toolsCanvasColorChooser);

        toolsMenu.setMnemonic('T');

        return (toolsMenu);
    }
}