org.addition.epanet.ui.EpanetUI.java Source code

Java tutorial

Introduction

Here is the source code for org.addition.epanet.ui.EpanetUI.java

Source

/*
 * Copyright (C) 2012  Addition, Lda. (addition at addition dot pt)
 *
 * 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 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/.
 */

package org.addition.epanet.ui;

import com.jgoodies.looks.plastic.Plastic3DLookAndFeel;
import org.addition.epanet.util.ENException;
import org.addition.epanet.network.Network;
import org.addition.epanet.network.io.input.InputParser;
import org.addition.epanet.network.io.output.OutputComposer;
import org.addition.epanet.network.structures.Node;
import org.addition.epanet.network.structures.Tank;
import org.addition.epanet.util.ENLevels;
import org.addition.epanet.util.Utilities;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.logging.*;

/**
 * The frontend UI class for the Aware-P Epanet application.
 */
public class EpanetUI implements ActionListener {

    private static final String WEBLINK = "http://www.baseform.org/?epaToolLink";
    private JPanel root;
    private JButton openINPButton;
    private JButton runSimulationButton;
    private JPanel top;
    private JPanel right;
    private JLabel textDemand;
    private JLabel textQuality;
    private JPanel properties;
    private JPanel network;
    private JLabel textReservoirs;
    private JLabel textTanks;
    private JLabel textPipes;
    private JLabel textNodes;
    private JLabel textDuration;
    private JLabel textUnits;
    private JLabel textHeadloss;
    private JCheckBox checkNodes;
    private JCheckBox checkTanks;
    private JCheckBox checkPipes;
    private JPanel propertiesRoot;
    private JPanel left;
    private JPanel checks;
    private JButton logoB;
    private JLabel hr1;
    private JLabel inpName;
    private JLabel textHydraulic;
    private JLabel msxName;
    private JPanel middle;
    private JPanel bottom;
    private JLabel textPattern;
    private JButton saveButton;

    /**
     * Reference to the selected node in network map.
     */
    private Node selectedNode = null;
    /**
     * Window main frame.
     */
    private JFrame frame;
    /**
     * Abstract representation of the network file(INP/XLSX/XML).
     */
    private File inpFile;
    /**
     * Abstract representation of the msx config file.
     */
    private File msxFile;
    /**
     * Loaded hydraulic network.
     */
    private Network epanetNetwork;

    /**
     * Reference to the file chooser.
     */
    private JFileChooser fileChooser = null;

    /**
     * Reference to the report options window.
     */
    ReportOptions reportOptions;

    /**
     * Application title string.
     */
    private static final String APP_TITTLE = "Baseform Epanet Java";

    /**
     * Reference for the file>open entry.
     */
    private static JMenuItem openAction;
    /**
     * Reference for the file>save entry.
     */
    private static JMenuItem saveAction;
    /**
     * Reference for the file>run entry.
     */
    private static JMenuItem runAction;
    private Logger log;
    private static final String LOG_FILENAME = "log/epanet.log";

    /**
     * Hydraulic rendering Panel.
     */
    class NetworkPanel extends JPanel {

        public NetworkPanel() {
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);

            if (epanetNetwork == null)
                return;

            int w = this.getWidth();
            int h = this.getHeight();

            if (epanetNetwork == null)
                return;

            NetworkImage.drawNetwork(g, w, h, epanetNetwork, checkPipes.isSelected(), checkTanks.isSelected(),
                    checkNodes.isSelected(), selectedNode);
        }
    }

    /**
     * Create the custom ui components.
     */
    private void createUIComponents() {
        root = new JPanel();
        top = new JPanel();
        right = new JPanel();
        properties = new JPanel();
        propertiesRoot = new JPanel();
        network = new NetworkPanel();
        network.addMouseListener(new MouseListener() {
            public void mouseClicked(MouseEvent mouseEvent) {
            }

            public void mousePressed(MouseEvent mouseEvent) {

                selectedNode = NetworkImage.peekNearest((int) network.getSize().getWidth(),
                        (int) network.getSize().getHeight(), mouseEvent.getX(), mouseEvent.getY(), epanetNetwork);
                network.repaint();
            }

            public void mouseReleased(MouseEvent mouseEvent) {
            }

            public void mouseEntered(MouseEvent mouseEvent) {
            }

            public void mouseExited(MouseEvent mouseEvent) {
            }
        });
    }

    /**
     * Aware-P Epanet frontend constructor.
     */
    public EpanetUI() {
        initLogger();

        frame = new JFrame();
        frame.setTitle(APP_TITTLE);
        frame.add(root);

        if (!Utilities.isMac()) {
            JMenuBar menuBar = new JMenuBar();

            JMenu fileMenu = new JMenu("File");
            menuBar.add(fileMenu);

            openAction = new JMenuItem("Open");
            saveAction = new JMenuItem("Save");
            runAction = new JMenuItem("Run");

            fileMenu.add(openAction);
            fileMenu.add(openAction);
            fileMenu.add(runAction);

            frame.setJMenuBar(menuBar);
        }

        openAction.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                openEvent();
                network.repaint();
            }
        });

        saveAction.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                saveEvent();
            }
        });

        runAction.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                runSimulation();
            }
        });

        frame.pack();
        frame.setMinimumSize(new Dimension(848, 500));
        frame.setLocationRelativeTo(null);

        clearInterface();

        frame.setVisible(true);

        openINPButton.addActionListener(this);
        runSimulationButton.addActionListener(this);
        logoB.addActionListener(this);
        checkTanks.addActionListener(this);
        checkNodes.addActionListener(this);
        checkPipes.addActionListener(this);
        saveButton.addActionListener(this);
        //runMSXButton.addActionListener(this);
        //saveReport.addActionListener(this);

        frame.addWindowListener(new WindowListener() {
            public void windowOpened(WindowEvent e) {
            }

            public void windowClosing(WindowEvent e) {
                for (Handler handler : log.getHandlers()) {
                    handler.flush();
                }
                System.exit(0);
            }

            public void windowClosed(WindowEvent e) {
            }

            public void windowIconified(WindowEvent e) {
            }

            public void windowDeiconified(WindowEvent e) {
            }

            public void windowActivated(WindowEvent e) {
            }

            public void windowDeactivated(WindowEvent e) {
            }
        });
    }

    private void initLogger() {
        log = Logger.getLogger(this.getClass().getName());
        log.setUseParentHandlers(false);
        log.setLevel(Level.ALL);

        try {
            new File(LOG_FILENAME).getParentFile().mkdirs();
            StreamHandler handle = new StreamHandler(new FileOutputStream(LOG_FILENAME), new SimpleFormatter()) {
                @Override
                public boolean isLoggable(LogRecord record) {
                    return true;//record.getLevel() == ENLevels.ERROR;
                }

                @Override
                public void publish(LogRecord record) {
                    super.publish(record);
                }
            };

            log.addHandler(handle);

        } catch (IOException e) {

        }
    }

    /**
     * Handle ui components events.
     */
    public void actionPerformed(ActionEvent e) {
        if (e.getSource().equals(saveButton)) {

            //fileChooser.setTitle("Save File");
            //fileChooser.setFilenameFilter(new InputFilterAWT());
            //fileChooser.setVisible(true);
            //fileChooser.setMode(FileDialog.SAVE);
            //OutputComposer excelComp = OutputComposer.create(Network.FileType.EXCEL_FILE);

            saveEvent();
        } else if (e.getSource().equals(openINPButton)) {
            openEvent();
        } else if (e.getSource().equals(runSimulationButton)) {
            runSimulation();
        } else if (e.getSource() == logoB) {
            browse(WEBLINK);
        }
        network.repaint();
    }

    /**
     * Show report options window to configure and run the simulation.
     */
    private void runSimulation() {
        if (reportOptions == null) {
            reportOptions = new ReportOptions(inpFile, msxFile, log);
            reportOptions.showWindow(frame, true);
        } else
            reportOptions.showWindow(frame, false);
    }

    /**
     * Show the save dialog to save the network file.
     */
    private void saveEvent() {
        JFileChooser fileSaver = new JFileChooser(inpFile.getParent());
        fileSaver.setFileSelectionMode(JFileChooser.FILES_ONLY);
        fileSaver.setAcceptAllFileFilterUsed(false);
        fileSaver.addChoosableFileFilter(new XLSXFilter());
        fileSaver.addChoosableFileFilter(new XMLFilter());
        fileSaver.addChoosableFileFilter(new INPFilter());

        fileSaver.showSaveDialog(frame);

        if (fileSaver.getSelectedFile() == null)
            return;

        Network.FileType netType = Network.FileType.INP_FILE;

        if (fileSaver.getFileFilter() instanceof XLSXFilter) {
            netType = Network.FileType.EXCEL_FILE;
        } else if (fileSaver.getFileFilter() instanceof XMLFilter) {
            netType = Network.FileType.XML_FILE;
            JOptionPane.showMessageDialog(frame, "Not supported yet !", "Error", JOptionPane.OK_OPTION);
            return;
        }

        OutputComposer compose = OutputComposer.create(netType);

        String extension = "";

        if (Utilities.getFileExtension(fileSaver.getSelectedFile().getName()).equals(""))
            switch (netType) {

            case INP_FILE:
                extension = ".inp";
                break;
            case EXCEL_FILE:
                extension = ".xlsx";
                break;
            case XML_FILE:
                extension = ".xml";
                break;
            }

        try {
            compose.composer(epanetNetwork, new File(fileSaver.getSelectedFile().getAbsolutePath() + extension));
        } catch (ENException e1) {
            e1.printStackTrace();
        }
    }

    /**
     * Show the open dialog and open the INP/XLSX and XML files.
     */
    private void openEvent() {
        if (fileChooser == null) {
            //fileChooser = new FileDialog(frame);
            fileChooser = new JFileChooser(System.getProperty("user.dir"));
            fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
            fileChooser.setAcceptAllFileFilterUsed(false);
            fileChooser.addChoosableFileFilter(new XLSXFilter());
            fileChooser.addChoosableFileFilter(new XMLFilter());
            fileChooser.addChoosableFileFilter(new MSXFilter());
            fileChooser.addChoosableFileFilter(new INPFilter());
            fileChooser.addChoosableFileFilter(new AllSuportedFilesFilter());
        }

        if (fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
            File netFile = fileChooser.getSelectedFile();
            String fileExtension = Utilities.getFileExtension(netFile.getName());

            if (fileExtension.equals("xlsx") || fileExtension.equals("inp") || fileExtension.equals("xml")) {
                inpFile = netFile;
                msxFile = null;
                msxName.setText("");

                Network.FileType netType = Network.FileType.INP_FILE;
                if (fileExtension.equals("xlsx"))
                    netType = Network.FileType.EXCEL_FILE;
                else if (fileExtension.equals("xml")) {
                    netType = Network.FileType.XML_FILE;
                    JOptionPane.showMessageDialog(frame, "Not supported yet !", "Error", JOptionPane.OK_OPTION);
                    return;
                }

                epanetNetwork = new Network();
                InputParser inpParser = InputParser.create(netType, log);
                try {
                    inpParser.parse(epanetNetwork, inpFile);
                } catch (ENException en_ex) {
                    JOptionPane.showMessageDialog(frame,
                            en_ex.toString() + "\nCheck epanet.log for detailed error description", "Error",
                            JOptionPane.OK_OPTION);
                    clearInterface();
                    inpFile = null;
                    return;
                } catch (Exception egen) {
                    JOptionPane.showMessageDialog(frame, "Unable to parse network configuration file", "Error",
                            JOptionPane.OK_OPTION);
                    log.log(ENLevels.ERROR, "openEvent", egen);
                    clearInterface();
                    inpFile = null;

                    return;
                }

                int resrvCount = 0;
                int tanksCount = 0;

                for (Tank tank : epanetNetwork.getTanks())
                    if (tank.getArea() == 0.0)
                        resrvCount++;
                    else
                        tanksCount++;

                textReservoirs.setText(Integer.toString(resrvCount));
                textTanks.setText(Integer.toString(tanksCount));
                textPipes.setText(Integer.toString(epanetNetwork.getLinks().size()));
                textNodes.setText(Integer.toString(epanetNetwork.getNodes().size()));
                try {
                    textDuration.setText(Utilities.getClockTime(epanetNetwork.getPropertiesMap().getDuration()));
                    textUnits.setText(epanetNetwork.getPropertiesMap().getUnitsflag().name());
                    textHeadloss.setText(epanetNetwork.getPropertiesMap().getFormflag().name());
                    textQuality.setText(epanetNetwork.getPropertiesMap().getQualflag().name());
                    textDemand.setText(epanetNetwork.getPropertiesMap().getDmult().toString());
                    textHydraulic.setText(Utilities.getClockTime(epanetNetwork.getPropertiesMap().getHstep()));
                    textPattern.setText(Utilities.getClockTime(epanetNetwork.getPropertiesMap().getPstep()));
                } catch (ENException ex) {
                }
                frame.setTitle(APP_TITTLE + inpFile.getName());
                inpName.setText(inpFile.getName());
                runSimulationButton.setEnabled(true);

                saveButton.setEnabled(true);
                reportOptions = null;
            } else if (fileExtension.equals("msx")) {
                if (inpFile == null) {
                    JOptionPane.showMessageDialog(frame,
                            "Load an INP or XLSX file with network configuration before opening the MSX file.",
                            "Error", JOptionPane.OK_OPTION);
                    return;
                }

                msxFile = netFile;
                msxName.setText(fileChooser.getSelectedFile().getName());//fileChooser.getFile());
                reportOptions = null;
            }

            saveAction.setEnabled(true);
            runAction.setEnabled(true);

        }
    }

    /**
     * Reset the interface layout
     */
    private void clearInterface() {
        epanetNetwork = null;
        inpFile = null;
        frame.setTitle(APP_TITTLE);
        textReservoirs.setText("0");
        textTanks.setText("0");
        textPipes.setText("0");
        textNodes.setText("0");
        textDuration.setText("00:00:00");
        textHydraulic.setText("00:00:00");
        textPattern.setText("00:00:00");
        textUnits.setText("NONE");
        textHeadloss.setText("NONE");
        textQuality.setText("NONE");
        textDemand.setText("0.0");
        saveAction.setEnabled(false);
        runAction.setEnabled(false);
        runSimulationButton.setEnabled(false);
    }

    /**
     * Aware-P Epanet application entry point
     *
     * @param args
     * @throws UnsupportedLookAndFeelException
     *
     */
    public static void main(String[] args) throws UnsupportedLookAndFeelException {
        //        if (Utilities.isMac()) {
        //            System.setProperty("apple.laf.useScreenMenuBar", "true");
        //            System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Aware-P Epanet");
        //
        //            try {
        //
        //                Class<?> appCl = Class.forName("com.apple.eawt.Application");
        //                Object app = appCl.getMethod("getApplication", new Class[]{}).invoke(null);
        //                Image dockImage = Toolkit.getDefaultToolkit().getImage(EpanetUI.class.getResource("/uiresources/ae.png"));
        //                appCl.getMethod("setDockIconImage",java.awt.Image.class).invoke(app, dockImage);
        //                JMenuBar menuBar = new JMenuBar();
        //                JMenu fileMenu = new JMenu("File");
        //                menuBar.add(fileMenu);
        //
        //                openAction = new JMenuItem("Open");
        //                saveAction = new JMenuItem("Save");
        //                runAction = new JMenuItem("Run");
        //
        //                fileMenu.add(openAction);
        //                fileMenu.add(saveAction);
        //                fileMenu.add(runAction);
        //                appCl.getMethod("setDefaultMenuBar",javax.swing.JMenuBar.class).invoke(app,menuBar);
        //            } catch (Exception e) {
        //                throw new RuntimeException(e);
        //            }
        //        }
        if (Utilities.isMac()) {
            System.setProperty("apple.laf.useScreenMenuBar", "true");
            System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Aware-P Epanet");

            try {

                Class<?> appCl = Class.forName("com.apple.eawt.Application");
                Object app = appCl.getMethod("getApplication", new Class[] {}).invoke(null);
                Image dockImage = Toolkit.getDefaultToolkit()
                        .getImage(EpanetUI.class.getResource("/uiresources/ae.png"));
                appCl.getMethod("setDockIconImage", java.awt.Image.class).invoke(app, dockImage);
                JMenuBar menuBar = new JMenuBar();
                JMenu fileMenu = new JMenu("File");
                menuBar.add(fileMenu);

                openAction = new JMenuItem("Open");
                saveAction = new JMenuItem("Save");
                runAction = new JMenuItem("Run");

                fileMenu.add(openAction);
                fileMenu.add(saveAction);
                fileMenu.add(runAction);
                //                appCl.getMethod("setDefaultMenuBar",javax.swing.JMenuBar.class).invoke(app,menuBar);

            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        try {
            UIManager.setLookAndFeel(new Plastic3DLookAndFeel());
        } catch (UnsupportedLookAndFeelException e) {
            e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
        }

        new EpanetUI();

    }

    /**
     * Open the aware-p webpage in the browser.
     *
     * @param url
     */
    private void browse(String url) {
        if (!java.awt.Desktop.isDesktopSupported()) {
            System.err.println("Desktop is not supported");
            return;
        }

        java.awt.Desktop desktop = java.awt.Desktop.getDesktop();

        if (!desktop.isSupported(java.awt.Desktop.Action.BROWSE)) {
            System.err.println("Desktop doesn't support the browse action");
            System.exit(1);
        }

        try {
            java.net.URI uri = new java.net.URI(url);
            desktop.browse(uri);
        } catch (Exception e) {

            System.err.println(e.getMessage());
        }
    }

    /**
     * INP file filter.
     */
    private class INPFilter extends FileFilter {

        public boolean accept(File f) {
            if (f.isDirectory()) {
                return true;
            }

            if (Utilities.getFileExtension(f.getName()).equals("inp"))
                return true;
            return false;
        }

        public String getDescription() {
            return "Epanet INP network file (*.inp)";
        }
    }

    /**
     * XLSX file filter.
     */
    private class XLSXFilter extends FileFilter {

        public boolean accept(File f) {
            if (f.isDirectory()) {
                return true;
            }

            if (Utilities.getFileExtension(f.getName()).equals("xlsx"))
                return true;
            return false;
        }

        public String getDescription() {
            return "Epanet XLSX network file (*.xlsx)";
        }
    }

    /**
     * XML file filter.
     */
    private class XMLFilter extends FileFilter {

        public boolean accept(File f) {
            if (f.isDirectory()) {
                return true;
            }

            if (Utilities.getFileExtension(f.getName()).equals("xml"))
                return true;
            return false;
        }

        public String getDescription() {
            return "Epanet XML network file (*.xml)";
        }
    }

    /**
     * MSX file filter.
     */
    private class MSXFilter extends FileFilter {

        public boolean accept(File f) {
            if (f.isDirectory()) {
                return true;
            }

            if (Utilities.getFileExtension(f.getName()).equals("msx"))
                return true;
            return false;
        }

        public String getDescription() {
            return "Epanet MSX quality file (*.msx)";
        }
    }

    private class AllSuportedFilesFilter extends FileFilter {

        public boolean accept(File f) {
            if (f.isDirectory()) {
                return true;
            }

            String extension = Utilities.getFileExtension(f.getName());

            if (extension.equals("msx") || extension.equals("inp") || extension.equals("xlsx"))
                return true;
            return false;
        }

        public String getDescription() {
            return "Supported files (*.msx, *.inp, *.xlsx, *.xml)";
        }
    }
}