adams.gui.tools.FileMonitorPanel.java Source code

Java tutorial

Introduction

Here is the source code for adams.gui.tools.FileMonitorPanel.java

Source

/*
 *   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/>.
 */

/*
 * FileMonitorPanel.java
 * Copyright (C) 2018 University of Waikato, Hamilton, NZ
 */

package adams.gui.tools;

import adams.core.CleanUpHandler;
import adams.gui.chooser.BaseFileChooser;
import adams.gui.core.BasePanel;
import adams.gui.core.BaseScrollPane;
import adams.gui.core.BaseTextArea;
import adams.gui.core.ConsolePanel;
import adams.gui.core.ExtensionFileFilter;
import adams.gui.core.Fonts;
import adams.gui.core.GUIHelper;
import adams.gui.core.MenuBarProvider;
import adams.gui.core.RecentFilesHandler;
import adams.gui.core.TitleGenerator;
import adams.gui.event.RecentItemEvent;
import adams.gui.event.RecentItemListener;
import org.apache.commons.io.input.Tailer;
import org.apache.commons.io.input.TailerListenerAdapter;

import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.event.ChangeEvent;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.logging.Level;

/**
 * Allows the user to monitor a file for new data being appended, like log files.
 *
 * @author FracPete (fracpete at waikato dot ac dot nz)
 */
public class FileMonitorPanel extends BasePanel implements MenuBarProvider, CleanUpHandler {

    private static final long serialVersionUID = -3090959157666111892L;

    /** the file to store the recent files in. */
    public final static String SESSION_FILE = "FileMonitorSession.props";

    public static class Listener extends TailerListenerAdapter {

        /** the owner. */
        protected FileMonitorPanel m_Owner;

        /** the monitored file. */
        protected String m_File;

        /**
         * Initializes the owner.
         *
         * @param owner   the owning actor
         */
        public Listener(FileMonitorPanel owner, String file) {
            m_Owner = owner;
            m_File = file;
        }

        /**
         * Handles a line from a Tailer.
         * @param line the line.
         */
        @Override
        public void handle(String line) {
            m_Owner.addLine(line);
        }

        /**
         * Handles an Exception .
         * @param ex the exception.
         */
        @Override
        public void handle(Exception ex) {
            ConsolePanel.getSingleton().append(Level.SEVERE, "Error tailing file: " + m_File, ex);
        }
    }

    /** for generating the title. */
    protected TitleGenerator m_TitleGenerator;

    /** the filename of the current file. */
    protected File m_CurrentFile;

    /** the filedialog for loading files. */
    protected BaseFileChooser m_FileChooser;

    /** the menu bar, if used. */
    protected JMenuBar m_MenuBar;

    /** the "open" submenu. */
    protected JMenuItem m_MenuItemOpen;

    /** the "open recent" submenu. */
    protected JMenu m_MenuItemOpenRecent;

    /** the "close" submenu. */
    protected JMenuItem m_MenuItemClose;

    /** the recent files handler. */
    protected RecentFilesHandler<JMenu> m_RecentFilesHandler;

    /** for displaying the content. */
    protected BaseTextArea m_TextMonitor;

    /** the tailer instance. */
    protected transient Tailer m_Tailer;

    /**
     * Initializes the members.
     */
    @Override
    protected void initialize() {
        super.initialize();

        m_CurrentFile = null;
        m_RecentFilesHandler = null;
        m_TitleGenerator = new TitleGenerator("Flow runner", true);
        m_FileChooser = new BaseFileChooser();
        m_FileChooser.addChoosableFileFilter(ExtensionFileFilter.getLogFileFilter());
        m_FileChooser.addChoosableFileFilter(ExtensionFileFilter.getTextFileFilter());
        m_FileChooser.setAcceptAllFileFilterUsed(true);
    }

    /**
     * Initializes the widgets.
     */
    @Override
    protected void initGUI() {
        super.initGUI();

        setLayout(new BorderLayout());

        m_TextMonitor = new BaseTextArea(20, 40);
        m_TextMonitor.setTextFont(Fonts.getMonospacedFont());
        add(new BaseScrollPane(m_TextMonitor), BorderLayout.CENTER);
    }

    /**
     * Creates a menu bar (singleton per panel object). Can be used in frames.
     *
     * @return      the menu bar
     */
    @Override
    public JMenuBar getMenuBar() {
        JMenuBar result;
        JMenu menu;
        JMenu submenu;
        JMenuItem menuitem;

        if (m_MenuBar == null) {
            result = new JMenuBar();

            // File
            menu = new JMenu("File");
            result.add(menu);
            menu.setMnemonic('F');
            menu.addChangeListener((ChangeEvent e) -> updateMenu());

            menuitem = new JMenuItem("Open...", GUIHelper.getIcon("open.gif"));
            menuitem.setMnemonic('O');
            menuitem.setAccelerator(GUIHelper.getKeyStroke("ctrl pressed O"));
            menuitem.addActionListener((ActionEvent e) -> open());
            menu.add(menuitem);
            m_MenuItemOpen = menuitem;

            // File/Recent files
            submenu = new JMenu("Open recent");
            menu.add(submenu);
            m_RecentFilesHandler = new RecentFilesHandler<>(SESSION_FILE, 5, submenu);
            m_RecentFilesHandler.addRecentItemListener(new RecentItemListener<JMenu, File>() {
                public void recentItemAdded(RecentItemEvent<JMenu, File> e) {
                    // ignored
                }

                public void recentItemSelected(RecentItemEvent<JMenu, File> e) {
                    open(e.getItem());
                }
            });
            m_MenuItemOpenRecent = submenu;

            menu.addSeparator();

            menuitem = new JMenuItem("Close", GUIHelper.getIcon("exit.png"));
            menuitem.setMnemonic('C');
            menuitem.setAccelerator(GUIHelper.getKeyStroke("ctrl pressed Q"));
            menuitem.addActionListener((ActionEvent e) -> close());
            menu.add(menuitem);
            m_MenuItemClose = menuitem;

            // update menu
            m_MenuBar = result;
            updateMenu();
        } else {
            result = m_MenuBar;
        }

        return result;
    }

    /**
     * Prompts the user to select a file to monitor.
     */
    protected void open() {
        int retVal;

        retVal = m_FileChooser.showOpenDialog(this);
        if (retVal != BaseFileChooser.APPROVE_OPTION)
            return;

        open(m_FileChooser.getSelectedFile());
    }

    /**
     * Monitors the specified file.
     *
     * @param file    the file to monitor
     */
    protected void open(File file) {
        Listener listener;

        stopListening();
        listener = new Listener(this, file.getAbsolutePath());
        m_Tailer = Tailer.create(file.getAbsoluteFile(), listener, 100, true);
        m_RecentFilesHandler.addRecentItem(file);
        setCurrentFile(file);
    }

    /**
     * Closes the dialog or frame.
     */
    protected void close() {
        cleanUp();
        closeParent();
    }

    /**
     * Updates the state of the menu items.
     */
    protected void updateMenu() {
        updateTitle();

        if (m_MenuBar == null)
            return;

        // File
        m_MenuItemOpen.setEnabled(true);
        m_MenuItemOpenRecent.setEnabled(m_RecentFilesHandler.size() > 0);
        m_MenuItemClose.setEnabled(true);
    }

    /**
     * Appends the line from the file.
     *
     * @param line   the line to append
     */
    public void addLine(String line) {
        boolean end;

        end = (m_TextMonitor.getCaretPosition() == m_TextMonitor.getText().length());
        m_TextMonitor.append(line + "\n");
        if (end)
            m_TextMonitor.setCaretPositionLast();
    }

    /**
     * Returns the title generator in use.
     *
     * @return      the generator
     */
    public TitleGenerator getTitleGenerator() {
        return m_TitleGenerator;
    }

    /**
     * Updates the title of the dialog.
     */
    protected void updateTitle() {
        if (!m_TitleGenerator.isEnabled())
            return;
        setParentTitle(m_TitleGenerator.generate(m_CurrentFile));
    }

    /**
     * Sets the current file.
     *
     * @param value   the file
     */
    protected void setCurrentFile(File value) {
        m_CurrentFile = value;
    }

    /**
     * Returns the current file in use.
     *
     * @return      the current file, can be null
     */
    public File getCurrentFile() {
        return m_CurrentFile;
    }

    /**
     * Stops the file tailer.
     */
    protected void stopListening() {
        if (m_Tailer != null) {
            m_Tailer.stop();
            m_Tailer = null;
        }
    }

    /**
     * Cleans up data structures, frees up memory.
     */
    public void cleanUp() {
        stopListening();
    }
}