ca.phon.app.query.QueryInfoPanel.java Source code

Java tutorial

Introduction

Here is the source code for ca.phon.app.query.QueryInfoPanel.java

Source

/*
 * Phon - An open source tool for research in phonology.
 * Copyright (C) 2005 - 2015, Gregory Hedlund <ghedlund@mun.ca> and Yvan Rose <yrose@mun.ca>
 * Dept of Linguistics, Memorial University <https://phon.ca>
 * 
 * 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 ca.phon.app.query;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.RowFilter;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.SwingUtilities;
import javax.swing.event.MouseInputAdapter;
import javax.swing.table.TableRowSorter;

import org.jdesktop.swingx.JXBusyLabel;
import org.jdesktop.swingx.JXLabel;
import org.jdesktop.swingx.JXTable;
import org.jdesktop.swingx.decorator.HighlighterFactory;

import ca.phon.app.opgraph.report.ReportLibrary;
import ca.phon.plugin.PluginEntryPointRunner;
import ca.phon.plugin.PluginException;
import ca.phon.project.Project;
import ca.phon.query.db.Query;
import ca.phon.query.db.QueryManager;
import ca.phon.query.db.ResultSet;
import ca.phon.query.db.ResultSetManager;
import ca.phon.query.script.QueryName;
import ca.phon.query.script.QueryScript;
import ca.phon.script.PhonScriptException;
import ca.phon.script.params.ScriptParam;
import ca.phon.script.params.ScriptParameters;
import ca.phon.session.DateFormatter;
import ca.phon.ui.CommonModuleFrame;
import ca.phon.ui.StarBox;
import ca.phon.ui.action.PhonUIAction;
import ca.phon.ui.nativedialogs.NativeDialogs;
import ca.phon.util.icons.IconManager;
import ca.phon.util.icons.IconSize;

import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

/**
 * Display information about a given query.
 *
 */
public class QueryInfoPanel extends JPanel {

    private static final long serialVersionUID = 7694431501108852083L;

    private final static Logger LOGGER = Logger.getLogger(QueryInfoPanel.class.getName());

    private StarBox starBox;

    /**
     * Name label
     */
    private JXLabel nameLabel;
    private JTextField nameField;

    /**
     * Comments label
     */
    private JTextArea commentsArea;

    /**
     * Edit/open buttons
     */
    private JButton editButton;
    private JButton openButton;

    /**
     * Results table
     */
    private JXBusyLabel busyLabel;
    private JXTable resultsTable;
    private TableRowSorter<ResultSetTableModel> resultsRowSorter;
    private ResultSetTableModel resultsModel;
    private JCheckBox hideResultsBox;
    private JCheckBox openEditorBox;
    private JButton reportButton;

    /**
     * Section panels
     */
    private JPanel infoSection;
    private JPanel resultsSection;

    /**
     * Date label
     */
    private JLabel dateLabel;

    /**
     * Uuid label
     */
    private JLabel uuidLabel;

    /**
     * Project
     */
    private Project project;

    /**
     * Query
     */
    private Query query;

    /**
     * Construction
     */
    public QueryInfoPanel(Project project) {
        super();

        this.project = project;

        init();
    }

    private void init() {
        setLayout(new BorderLayout());

        starBox = new StarBox(IconSize.SMALL);
        starBox.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                toggleStarred();
            }
        });

        // query name
        nameLabel = new JXLabel();
        Font nameFont = nameLabel.getFont().deriveFont(Font.BOLD, 14.0f);
        nameLabel.setFont(nameFont);

        final ImageIcon searchIcon = IconManager.getInstance().getIcon("actions/system-search", IconSize.SMALL);
        final PhonUIAction openAction = new PhonUIAction(this, "onOpenQuery");
        openAction.putValue(PhonUIAction.NAME, "Open Query");
        openAction.putValue(PhonUIAction.SMALL_ICON, searchIcon);
        openAction.putValue(PhonUIAction.SHORT_DESCRIPTION, "Open query in editor");
        openButton = new JButton(openAction);

        nameField = new JTextField();
        nameField.setFont(nameFont);

        uuidLabel = new JLabel();

        dateLabel = new JLabel();

        commentsArea = new JTextArea();
        commentsArea.setRows(5);
        commentsArea.setLineWrap(true);
        commentsArea.setEditable(false);
        commentsArea.setFont(Font.getFont("dialog"));
        final JScrollPane commentsLabelScroller = new JScrollPane(commentsArea);

        // layout form components
        final FormLayout layout = new FormLayout("right:pref, 3dlu, fill:pref:grow, right:pref",
                "pref, 3dlu, pref, 3dlu, pref, 3dlu, top:pref, fill:pref:grow");
        final CellConstraints cc = new CellConstraints();

        infoSection = new JPanel(layout);
        infoSection.setBorder(BorderFactory.createTitledBorder("Information"));
        infoSection.add(starBox, cc.xy(1, 1));
        infoSection.add(nameLabel, cc.xy(3, 1));
        infoSection.add(openButton, cc.xy(4, 1));

        infoSection.add(new JLabel("UUID:"), cc.xy(1, 3));
        infoSection.add(uuidLabel, cc.xyw(3, 3, 2));

        infoSection.add(new JLabel("Date:"), cc.xy(1, 5));
        infoSection.add(dateLabel, cc.xyw(3, 5, 2));

        infoSection.add(new JLabel("Comments:"), cc.xy(1, 7));
        infoSection.add(commentsLabelScroller, cc.xywh(3, 7, 2, 2));

        resultsModel = new ResultSetTableModel(project, null);
        resultsModel.addPropertyChangeListener(bgTaskPropertyListener);
        resultsTable = new JXTable(resultsModel);
        resultsTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        resultsTable.addMouseListener(resultsMouseListener);
        resultsRowSorter = new TableRowSorter<ResultSetTableModel>(resultsModel);
        resultsRowSorter.setSortsOnUpdates(true);
        final RowSorter.SortKey sortKey = new RowSorter.SortKey(ResultSetTableModel.Columns.ID.ordinal(),
                SortOrder.ASCENDING);
        resultsRowSorter.setSortKeys(Collections.singletonList(sortKey));
        resultsTable.setRowSorter(resultsRowSorter);
        resultsTable.setColumnControlVisible(true);
        resultsTable.addHighlighter(HighlighterFactory.createSimpleStriping());
        resultsTable.setVisibleRowCount(10);

        // remove selection column
        resultsTable.getColumnModel().removeColumn(resultsTable.getColumn(0));
        JScrollPane resultsScroller = new JScrollPane(resultsTable);

        final ImageIcon reportIcon = IconManager.getInstance().getIcon("mimetypes/x-office-spreadsheet",
                IconSize.SMALL);
        final PhonUIAction reportAction = new PhonUIAction(this, "onReport");
        reportAction.putValue(PhonUIAction.NAME, "Report");
        reportAction.putValue(PhonUIAction.SHORT_DESCRIPTION, "Create report");
        reportAction.putValue(PhonUIAction.SMALL_ICON, reportIcon);
        reportButton = new JButton(reportAction);

        busyLabel = new JXBusyLabel(new Dimension(16, 16));
        busyLabel.setBusy(false);

        hideResultsBox = new JCheckBox("Hide empty result sets");
        hideResultsBox.setSelected(false);
        hideResultsBox.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                toggleRowFilter();
            }
        });

        // system preference
        openEditorBox = new JCheckBox("Open session with result set");
        openEditorBox.setSelected(true);

        resultsSection = new JPanel(new BorderLayout());
        resultsSection.setBorder(BorderFactory.createTitledBorder("Results"));
        final FormLayout topLayout = new FormLayout("pref, left:pref, left:pref, fill:pref:grow, right:pref",
                "pref");
        final JPanel topResultsPanel = new JPanel();
        topResultsPanel.setLayout(topLayout);
        topResultsPanel.add(busyLabel, cc.xy(1, 1));
        topResultsPanel.add(hideResultsBox, cc.xy(2, 1));
        topResultsPanel.add(openEditorBox, cc.xy(3, 1));
        topResultsPanel.add(reportButton, cc.xy(5, 1));

        resultsSection.add(topResultsPanel, BorderLayout.NORTH);
        resultsSection.add(resultsScroller, BorderLayout.CENTER);

        openButton.setEnabled(false);
        reportButton.setEnabled(false);

        add(infoSection, BorderLayout.NORTH);
        add(resultsSection, BorderLayout.CENTER);
    }

    private void toggleRowFilter() {
        if (hideResultsBox.isSelected()) {
            final RowFilter<ResultSetTableModel, Integer> filter = RowFilter.regexFilter("[1-9][0-9]*",
                    ResultSetTableModel.Columns.ResultCount.ordinal());
            resultsRowSorter.setRowFilter(filter);
        } else {
            resultsRowSorter.setRowFilter(null);
        }
    }

    public void setQuery(Query query) {
        this.query = query;
        updateForm();
    }

    public void toggleStarred() {
        boolean starred = starBox.isSelected();
        if (query != null && query.isStarred() != starred) {
            query.setStarred(starred);
            final QueryManager qManager = QueryManager.getSharedInstance();
            final ResultSetManager rsManager = qManager.createResultSetManager();
            try {
                rsManager.saveQuery(project, query);
            } catch (IOException e) {
                LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
            }
        }
    }

    public void onReport() {
        if (project == null || query == null)
            return;
        final JMenu menu = new JMenu();
        final ReportLibrary library = new ReportLibrary();
        library.setupMenu(project, query.getUUID().toString(), menu);
        menu.getPopupMenu().show(reportButton, 0, reportButton.getHeight());
    }

    public void onOpenQuery() {
        final QueryScript script = new QueryScript(query.getScript().getSource());
        ScriptParameters params = new ScriptParameters();
        try {
            params = script.getContext().getScriptParameters(script.getContext().getEvaluatedScope());
        } catch (PhonScriptException e) {
            LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
        }
        for (ScriptParam sp : params) {
            for (String id : sp.getParamIds()) {
                Object v = query.getScript().getParameters().get(id);
                if (v != null) {
                    sp.setValue(id, v);
                }
            }
        }

        final QueryName qn = new QueryName(query.getName());
        script.putExtension(QueryName.class, qn);

        QueryEditorWindow sd = new QueryEditorWindow("Script Editor", project, script);
        sd.pack();
        sd.setLocationByPlatform(true);
        sd.setVisible(true);
    }

    public void updateForm() {
        if (query != null) {
            nameLabel.setText(query.getName());
            uuidLabel.setText(query.getUUID().toString());
            dateLabel.setText(DateFormatter.dateTimeToString(query.getDate()));
            commentsArea.setText(query.getComments());
            commentsArea.setCaretPosition(0);
            starBox.setSelected(query.isStarred());

            openButton.setEnabled(true);
            reportButton.setEnabled(true);
        } else {
            nameLabel.setText("");
            uuidLabel.setText("");
            dateLabel.setText("");
            commentsArea.setText("");
            starBox.setSelected(false);

            openButton.setEnabled(false);
            reportButton.setEnabled(false);
        }
        resultsModel.setQuery(query);
    }

    /**
     * Open the given result set in a new window.
     * 
     * @param rs
     */
    public void openResultSet(ResultSet rs) {
        HashMap<String, Object> initInfo = new HashMap<String, Object>();
        initInfo.put("project", project);
        initInfo.put("query", query);
        initInfo.put("resultset", rs);
        initInfo.put("opensession", openEditorBox.isSelected());

        // open editor first....
        try {
            PluginEntryPointRunner.executePlugin("ResultSetViewer", initInfo);
        } catch (PluginException e) {
            LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
        }
    }

    public void deleteResultSet(ResultSet rs) {
        String msg = "Delete result set '" + rs.getSessionPath() + "' for query '" + query.getName()
                + "'?  Action cannot be undone.";
        int result = NativeDialogs.showOkCancelDialogBlocking(CommonModuleFrame.getCurrentFrame(), null,
                "Delete result set", msg);
        if (result == 0) {
            final QueryManager qManager = QueryManager.getSharedInstance();
            final ResultSetManager rsManager = qManager.createResultSetManager();

            try {
                rsManager.deleteResultSet(project, query, rs);
                resultsModel.removeResultSet(rs);
            } catch (IOException e) {
                LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
            }
        }
    }

    /**
     * Listener for background tasks on the table model
     */
    private final PropertyChangeListener bgTaskPropertyListener = new PropertyChangeListener() {

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (!evt.getPropertyName().equals(ResultSetTableModel.RUNNING_IN_BACKGROUND))
                return;
            final Boolean busy = (Boolean) evt.getNewValue();
            final Runnable setBusy = new Runnable() {

                @Override
                public void run() {
                    busyLabel.setBusy(busy);
                }
            };
            SwingUtilities.invokeLater(setBusy);
        }
    };

    /**
     * Mouse listener for the result table
     */
    private final MouseListener resultsMouseListener = new MouseInputAdapter() {
        @Override
        public void mouseClicked(MouseEvent me) {
            // handle double clicks
            if (me.getClickCount() == 2 && me.getButton() == MouseEvent.BUTTON1) {
                int selectedRow = resultsTable.getSelectedRow();
                if (selectedRow < 0)
                    return;
                selectedRow = resultsTable.convertRowIndexToModel(selectedRow);
                final ResultSet rs = resultsModel.resultSetForRow(selectedRow);
                if (rs != null) {
                    openResultSet(rs);
                }
            }
        }

        @Override
        public void mousePressed(MouseEvent me) {
            if (me.isPopupTrigger()) {
                int row = resultsTable.rowAtPoint(me.getPoint());
                if (row >= 0)
                    resultsTable.getSelectionModel().setSelectionInterval(row, row);

                showResultSetContextMenu(me);
            }
        }

        @Override
        public void mouseReleased(MouseEvent me) {
            if (me.isPopupTrigger()) {
                int row = resultsTable.rowAtPoint(me.getPoint());
                if (row >= 0)
                    resultsTable.getSelectionModel().setSelectionInterval(row, row);

                showResultSetContextMenu(me);
            }
        }

        private void showResultSetContextMenu(MouseEvent me) {
            int selectedRow = resultsTable.getSelectedRow();
            if (selectedRow < 0)
                return;
            selectedRow = resultsTable.convertRowIndexToModel(selectedRow);
            final ResultSet rs = resultsModel.resultSetForRow(selectedRow);

            final PhonUIAction openAct = new PhonUIAction(QueryInfoPanel.this, "openResultSet", rs);
            openAct.putValue(PhonUIAction.NAME, "Open");
            openAct.putValue(PhonUIAction.SHORT_DESCRIPTION, "Open result set");
            final JMenuItem openItem = new JMenuItem(openAct);

            final PhonUIAction deleteAct = new PhonUIAction(QueryInfoPanel.this, "deleteResultSet", rs);
            deleteAct.putValue(PhonUIAction.NAME, "Delete");
            deleteAct.putValue(PhonUIAction.SHORT_DESCRIPTION, "Delete result set");
            final JMenuItem deleteItem = new JMenuItem(deleteAct);

            final JPopupMenu popupMenu = new JPopupMenu();
            popupMenu.add(openItem);
            popupMenu.addSeparator();
            popupMenu.add(deleteItem);

            popupMenu.show(resultsTable, me.getX(), me.getY());
        }
    };
}