is.iclt.jcorpald.CorpaldView.java Source code

Java tutorial

Introduction

Here is the source code for is.iclt.jcorpald.CorpaldView.java

Source

/*
Corpald
Copyright 2011 Anton Karl Ingason
Website: http://linguist.is/corpald
Contact: anton.karl.ingason@gmail.com
    
Icelandic Parsed Historical Corpus (IcePaHC)
is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
    
You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
Corpald is a cross-platform graphical user interface to search corpora in labeled bracketing format.
Corpald calls CorpusSearch by Beth Randall on the command line to execute
search queries. (http://corpussearch.sourceforge.net/)
    
The project is funded in part by the following grant:
From the Icelandic Research Fund (RANN?S), grant nr. 090662011, Viable Language Technology beyond English  Icelandic as a test case.
*/

package is.iclt.jcorpald;

import java.awt.*;
import java.awt.datatransfer.*;
import java.awt.event.*;
import java.io.File;
import java.io.IOException;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileFilter;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;

public class CorpaldView extends JFrame
        implements ActionListener, QueryObserver, ResultObserver, KeyListener, ItemListener, ClipboardOwner {

    CorpaldModelInterface model;
    ControllerInterface controller;

    // For gathering input for searches
    JTextField txtRootNode = null;
    JLabel labQuery = new JLabel("Query:");
    JHighlightPane txtQuery = null;
    JCheckBox chkNodesOnly = null;
    JCheckBox chkRemoveNodes = null;

    // Buttons
    JButton butNewQuery = null;
    JButton butSaveQuery = null;
    JButton butSaveQueryAs = null;
    JButton butOpenQuery = null;
    JButton butOpenDef = null;
    JButton butRunQuery = null;

    JButton butCopyResults = null;
    JButton butOpenFolder = null;
    JButton butTextEditor = null;

    // For syntax highlighting
    String[] keywords = new String[] { "CCommands", "cCommands", "ccommands", "column", "Col", "col", "Dominates",
            "dominates", "Doms", "doms", "domsWords", "domswords", "DomsWords<", ",domsWords<", "domswords<",
            "DomsWords>", "domsWords>", "domswords>", "Exists", "exists", "HasLabel", "hasLabel", "haslabel",
            "HasSister", "hasSister", "hassister", "iDominates", "idominates", "iDoms", "idoms", "iDomsFirst",
            "idomsfirst", "iDomsLast", "idomslast", "iDomsMod", "idomsmod", "iDomsNumber", "idomsnumber",
            "iDomsNum", "idomsnum", "iDomsOnly", "idomsonly", "iDomsTotal", "idomstotal", "iDomsTotal<",
            "idomstotal<", "iDomsTotal>", "idomstotal>", "iDomsViaTrace", "idomsviatrace", "InID", "inID",
            "iPrecedes", "iprecedes", "iPres", "ipres", "IsRoot", "isRoot", "isroot", "Precedes", "precedes",
            "Pres", "pres", "SameIndex", "sameIndex", "sameindex" };
    String[] operators = new String[] { "AND", "OR", "NOT" };
    String[] defwords = new String[] {};

    // Dialogs
    final JFileChooser queryChooser = new JFileChooser();
    final JFileChooser defChooser = new JFileChooser();

    // For displaying results from searches
    JTextArea txtResult = null;

    private static final long serialVersionUID = 9022781806157292479L;

    public CorpaldView(ControllerInterface controller, CorpaldModelInterface model) {
        this.controller = controller;
        this.model = model;
        model.registerQueryObserver((QueryObserver) this);
        model.registerResultObserver((ResultObserver) this);
    }

    public void createAndShowGUI() {
        CorpaldSettings settings = CorpaldSettings.getInstance();

        //Create and set up the window.
        JFrame frame = new JFrame(settings.getProperty("corpus.acronym") + " "
                + settings.getProperty("corpus.version") + " - " + settings.getProperty("corpus.longname"));
        frame.setIconImage((new ImageIcon("icons/corpald.png")).getImage());

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // frame.setBounds(50, 50, 700, 450);
        frame.setPreferredSize(new Dimension(750, 720));

        // Create the panel that has the query and the result        
        JPanel panMainArea = new JPanel(new BorderLayout());
        JPanel panQuery = new JPanel(new BorderLayout());

        txtQuery = new JHighlightPane();
        txtQuery.addKeyListener(this);

        txtQuery.setFont(new Font("Monospaced", Font.BOLD, 16));
        this.updateHighlighting();
        txtQuery.setPreferredSize(new Dimension(700, 150));

        panQuery.add(labQuery, BorderLayout.NORTH);
        panQuery.add(new JScrollPane(txtQuery, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS), BorderLayout.CENTER);
        panQuery.setBorder(new EmptyBorder(0, 10, 10, 10));

        String welcomeMessage = "";
        try {
            welcomeMessage = FileUtils.readFileToString(new File(settings.getProperty("corpus.welcome")), "utf-8");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        JPanel panResult = new JPanel(new BorderLayout());
        txtResult = new JTextArea(welcomeMessage);

        txtResult.setEditable(false);
        txtResult.setFont(new Font("Monospaced", Font.BOLD, 14));

        JScrollPane scrResult = new JScrollPane(txtResult, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
        scrResult.setPreferredSize(new Dimension(700, 400));
        panResult.add(new JLabel("Result:"), BorderLayout.NORTH);
        panResult.add(scrResult, BorderLayout.CENTER);
        panResult.setBorder(new EmptyBorder(0, 10, 0, 10));

        panMainArea.add(panQuery, BorderLayout.NORTH);
        panMainArea.add(panResult, BorderLayout.CENTER);

        // Create panel at top with buttons
        JPanel panToolbar = new JPanel(new FlowLayout(FlowLayout.CENTER));

        // New, Open, Save
        // New
        ImageIcon icoNewQuery = new ImageIcon("icons/page_white.png");
        butNewQuery = new JButton(icoNewQuery);
        butNewQuery.addActionListener(this);
        butNewQuery.setPreferredSize(new Dimension(26, 26));
        butNewQuery.setToolTipText("Create a new empty query");
        panToolbar.add(butNewQuery);
        // Open
        ImageIcon icoOpenQuery = new ImageIcon("icons/folder.png");
        butOpenQuery = new JButton(icoOpenQuery);
        butOpenQuery.addActionListener(this);
        butOpenQuery.setPreferredSize(new Dimension(26, 26));
        butOpenQuery.setToolTipText("Open a query file");
        panToolbar.add(butOpenQuery);
        // Save
        ImageIcon icoSaveQuery = new ImageIcon("icons/page_save.png");
        butSaveQuery = new JButton(icoSaveQuery);
        butSaveQuery.addActionListener(this);
        butSaveQuery.setPreferredSize(new Dimension(26, 26));
        butSaveQuery.setToolTipText("Save current query");
        panToolbar.add(butSaveQuery);
        // Save as
        ImageIcon icoSaveQueryAs = new ImageIcon("icons/page_save_as.png");
        butSaveQueryAs = new JButton(icoSaveQueryAs);
        butSaveQueryAs.addActionListener(this);
        butSaveQueryAs.setPreferredSize(new Dimension(26, 26));
        butSaveQueryAs.setToolTipText("Save current query under a new file name");
        panToolbar.add(butSaveQueryAs);

        // Open definitions file
        ImageIcon icoOpenDef = new ImageIcon("icons/folder_table.png");
        butOpenDef = new JButton(icoOpenDef);
        butOpenDef.addActionListener(this);
        butOpenDef.setPreferredSize(new Dimension(26, 26));
        butOpenDef.setToolTipText("Select a new definitions file");
        panToolbar.add(butOpenDef);

        // Run Query button
        ImageIcon icoRunQuery = new ImageIcon("icons/control_play_blue.png");
        butRunQuery = new JButton("Run Query", icoRunQuery);
        butRunQuery.setPreferredSize(new Dimension(130, 26));
        butRunQuery.addActionListener(this);
        butRunQuery.setToolTipText("Run the current query using CorpusSearch");
        panToolbar.add(butRunQuery);

        // TextField for root node label
        JLabel labRootNode = new JLabel("Root:");
        panToolbar.add(labRootNode);
        txtRootNode = new JTextField("", 12);
        txtRootNode.setPreferredSize(new Dimension(50, 26));
        txtRootNode.addKeyListener(this);
        txtRootNode.setMargin(new Insets(3, 3, 3, 3));
        txtRootNode.setToolTipText("<html>Search within instances of a particular type of node,<br/>"
                + "such as IP-*, IP-SUB, NP-*, etc. $ROOT matches<br/>"
                + "the root node of every tree in the corpus.</html>");
        panToolbar.add(txtRootNode);

        chkNodesOnly = new JCheckBox("Nodes only");
        chkNodesOnly.addItemListener(this);
        chkNodesOnly.setToolTipText("<html>If checked, CorpusSearch prints out only the nodes that<br/>"
                + "contain the structure described in \"Query\". If not checked,<br/>"
                + "CorpusSearch prints out the entire sentence that contains the<br/>"
                + "structure described in \"Query\".</html>");
        panToolbar.add(chkNodesOnly);

        chkRemoveNodes = new JCheckBox("Remove nodes");
        chkRemoveNodes.addItemListener(this);
        chkRemoveNodes.setToolTipText("<html>Remove subtrees whose root is of the same syntactic category<br/>"
                + "as the node boundary embedded within a instance of that node<br/>"
                + "boundary. \"Remove nodes\" thus removes recursive structure.</html>");
        panToolbar.add(chkRemoveNodes);

        // Create panel at top with buttons
        JPanel panBottombar = new JPanel(new FlowLayout(FlowLayout.CENTER));
        // panBottombar.setBorder(new EmptyBorder(0, 0, 10, 5));
        ImageIcon icoOpenFolder = new ImageIcon("icons/folder.png");
        butOpenFolder = new JButton("Show result in folder", icoOpenFolder);
        butOpenFolder.setEnabled(false);
        butOpenFolder.addActionListener(this);
        panBottombar.add(butOpenFolder);

        ImageIcon icoTextEditor = new ImageIcon("icons/page_white_go.png");
        butTextEditor = new JButton("Open result in text editor", icoTextEditor);
        butTextEditor.setEnabled(false);
        butTextEditor.addActionListener(this);
        panBottombar.add(butTextEditor);

        ImageIcon icoCopyResults = new ImageIcon("icons/page_copy.png");
        butCopyResults = new JButton("Copy result to clipboard", icoCopyResults);
        butCopyResults.setEnabled(false);
        butCopyResults.addActionListener(this);
        panBottombar.add(butCopyResults);

        // Add stuff to top level content pane                
        frame.getContentPane().setLayout(new BorderLayout());
        frame.getContentPane().add(panToolbar, BorderLayout.NORTH);
        frame.getContentPane().add(panMainArea, BorderLayout.CENTER);
        frame.getContentPane().add(panBottombar, BorderLayout.SOUTH);

        this.configureFileFilters();

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public void updateHighlighting() {
        txtQuery.clearKeyWords();
        txtQuery.addKeyWords(keywords, new Color(0xE56717));
        txtQuery.addKeyWords(operators, new Color(0x0000AA));
        txtQuery.addKeyWords(defwords, new Color(0x00BB00));
    }

    public void configureFileFilters() {
        queryChooser.setFileFilter(new FileFilter() {

            @Override
            public boolean accept(File file) {
                if (file.isDirectory()) {
                    return true;
                }

                return file.getAbsolutePath().endsWith(".q");
            }

            @Override
            public String getDescription() {
                return "CorpusSearch query files (*.q)";
            }

        });

        defChooser.setFileFilter(new FileFilter() {

            @Override
            public boolean accept(File file) {
                if (file.isDirectory()) {
                    return true;
                }

                return file.getAbsolutePath().endsWith(".def");
            }

            @Override
            public String getDescription() {
                return "CorpusSearch definitions files (*.def)";
            }

        });
    }

    /*
     * Event handling section
     */

    public void actionPerformed(ActionEvent event) {
        if (event.getSource() == butRunQuery) {
            controller.runQuery();
        } else if (event.getSource() == butOpenQuery) {

            int returnVal = queryChooser.showOpenDialog(this);

            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = queryChooser.getSelectedFile();
                controller.openQuery(file);
            }
        } else if (event.getSource() == butNewQuery) {
            controller.newQuery();
        } else if (event.getSource() == butSaveQuery) {
            // save if there is a file already
            this.doSave();
        } else if (event.getSource() == butSaveQueryAs) {
            this.doSaveAs();
        } else if (event.getSource() == butOpenDef) {

            int returnVal = defChooser.showOpenDialog(this);

            if (returnVal == JFileChooser.APPROVE_OPTION) {
                File file = defChooser.getSelectedFile();
                controller.openDef(file);
            }
        } else if (event.getSource() == butOpenFolder) {
            this.openFolder();
        } else if (event.getSource() == butTextEditor) {
            this.openTextEditor();
        } else if (event.getSource() == butCopyResults) {
            this.copyToClipboard();
        }
    }

    private void openFolder() {
        try {
            String str = FilenameUtils.separatorsToUnix(model.getFileName());
            str = str.substring(0, str.lastIndexOf("/"));
            Desktop.getDesktop().open(new File(str));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void openTextEditor() {
        try {
            Desktop.getDesktop().open(model.getResultFile());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void copyToClipboard() {
        try {
            File toOpen = model.getResultFile();
            String resultString = FileUtils.readFileToString(toOpen);
            StringSelection stringSelection = new StringSelection(resultString);
            Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
            clipboard.setContents(stringSelection, this);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void doSave() {
        if (model.getFileName() != null) {
            controller.saveQuery();
        } else { // otherwise fire up the save as dialog
            this.doSaveAs();
        }
    }

    private void doSaveAs() {
        int returnVal = queryChooser.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = queryChooser.getSelectedFile();
            controller.saveQueryAs(file);
        }
    }

    public void queryChanged() {
        txtRootNode.setText(model.getRootNode());
        txtQuery.setText(model.getQuery());
        chkNodesOnly.setSelected(model.getNodesOnly());
        chkRemoveNodes.setSelected(model.getRemoveNodes());
        butSaveQuery.setEnabled(model.isModified());
        if (model.isModified()) {
            butSaveQueryAs.setEnabled(true);
        }
        if (model.getQuery().trim().length() == 0) {
            butSaveQuery.setEnabled(false);
            butSaveQueryAs.setEnabled(false);
        }

        // Construct the message above the query field
        String labString = "Query";
        if (model.getFileName() != null) {
            labString += " (" + model.getFileName();
            if (model.isModified()) {
                labString += "*";
            }
            labString += ")";
        } else {
            if (model.isModified()) {
                labString += "(*)";
            }
        }

        // Construct the tooltip for the definitions file
        labString += ":";
        labQuery.setText(labString);

        String defString = "<html>Select definitions file";
        if (model.getDefinitionsFileName() != null) {
            defString += "<br/>Current: " + model.getDefinitionsFileName();
        }
        defString += "</html>";
        butOpenDef.setToolTipText(defString);

        // load definitions into the highlighting system
        if (model.getDefWords() != null) {
            defwords = model.getDefWords().toArray(new String[model.getDefWords().size()]);
            this.updateHighlighting();
        }
    }

    public void resultChanged() {
        boolean hasResult = (model.getResult().length() != 0);
        butCopyResults.setEnabled(hasResult);
        butOpenFolder.setEnabled(hasResult);
        butTextEditor.setEnabled(hasResult);
        txtResult.setText(model.getResult());
    }

    public void keyReleased(KeyEvent event) {
        // it can either be the root node field ...
        if (event.getSource() == txtRootNode) {
            controller.setRootNode(txtRootNode.getText());
        } else { // ... or the query itself
            controller.setQuery(txtQuery.getText());
        }
    }

    public void keyPressed(KeyEvent event) {
        if (event.getKeyCode() == java.awt.event.KeyEvent.VK_S) {
            if (event.isControlDown()) {
                this.doSave();
            }
        }

    }

    public void keyTyped(KeyEvent event) {
    }

    public void itemStateChanged(ItemEvent event) {
        if (event.getSource() == chkNodesOnly) {
            controller.setNodesOnly(chkNodesOnly.isSelected());
        } else if (event.getSource() == chkRemoveNodes) {
            controller.setRemoveNodes(chkRemoveNodes.isSelected());
        }

    }

    public void lostOwnership(Clipboard arg0, Transferable arg1) {
        // do nothing
    }

}