Newer
Older
jrex / src / jrex / JRexFrame.java
package jrex;

import com.google.common.collect.ListMultimap;
import java.awt.Color;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.Action;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.KeyStroke;
import javax.swing.SpinnerNumberModel;
import javax.swing.UIManager;
import javax.swing.table.TableModel;
import javax.swing.text.DefaultEditorKit;

/**
 *
 * @author Mark George <mark.george@otago.ac.nz>
 */
public class JRexFrame extends javax.swing.JFrame {

	private String exprChar = "?";
	private Color defaultTextColor;

	/**
	 * Creates new form JRexFrame
	 */
	public JRexFrame() {
		initComponents();
		splitPane.setResizeWeight(0.66);
		spnColumns.setModel(new SpinnerNumberModel(0, 0, Integer.MAX_VALUE, 1));

		JPopupMenu rightClickMenu = new JPopupMenu();

		Action cut = new DefaultEditorKit.CutAction();
		cut.putValue(Action.NAME, "Cut");
		cut.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control X"));
		rightClickMenu.add(cut);

		Action copy = new DefaultEditorKit.CopyAction();
		copy.putValue(Action.NAME, "Copy");
		copy.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control C"));
		rightClickMenu.add(copy);

		Action paste = new DefaultEditorKit.PasteAction();
		paste.putValue(Action.NAME, "Paste");
		paste.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke("control V"));
		rightClickMenu.add(paste);

		Action tab = new DefaultEditorKit.InsertTabAction();
		tab.putValue(Action.NAME, "Insert Tab");
		rightClickMenu.add(tab);

		txtInput.setComponentPopupMenu(rightClickMenu);
		txtOutput.setComponentPopupMenu(rightClickMenu);
		txtRegex.setComponentPopupMenu(rightClickMenu);
		txtFormat.setComponentPopupMenu(rightClickMenu);
		txtReplace.setComponentPopupMenu(rightClickMenu);

		defaultTextColor = txtRegex.getBackground();
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
   // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
   private void initComponents() {

      expGrp = new javax.swing.ButtonGroup();
      splitPane = new javax.swing.JSplitPane();
      pnlInput = new javax.swing.JPanel();
      btnClear = new javax.swing.JButton();
      btnLoad = new javax.swing.JButton();
      scrollInput = new javax.swing.JScrollPane();
      txtInput = new javax.swing.JTextArea();
      lblExpression = new javax.swing.JLabel();
      txtRegex = new javax.swing.JTextField();
      spnColumns = new javax.swing.JSpinner();
      btnTSV = new javax.swing.JButton();
      btnCSV = new javax.swing.JButton();
      btnMatch = new javax.swing.JButton();
      scrollTable = new javax.swing.JScrollPane();
      jTable = new javax.swing.JTable();
      btnTranspose = new javax.swing.JButton();
      btnLiteralise = new javax.swing.JButton();
      btnPivot = new javax.swing.JButton();
      btnReplace = new javax.swing.JButton();
      pnlOutput = new javax.swing.JPanel();
      lblFormat = new javax.swing.JLabel();
      txtFormat = new javax.swing.JTextField();
      btnFormat = new javax.swing.JButton();
      scrollOutput = new javax.swing.JScrollPane();
      txtOutput = new javax.swing.JTextArea();
      rdoQuestion = new javax.swing.JRadioButton();
      rdoDollar = new javax.swing.JRadioButton();
      rdoSlash = new javax.swing.JRadioButton();
      lblArgumentMarker = new javax.swing.JLabel();
      cbBlanks = new javax.swing.JCheckBox();
      txtReplace = new javax.swing.JTextField();

      setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

      splitPane.setBorder(null);
      splitPane.setDividerLocation(366);
      splitPane.setDividerSize(15);
      splitPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
      splitPane.setName("splitPane"); // NOI18N
      splitPane.setOneTouchExpandable(true);

      pnlInput.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Input", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Dialog", 0, 12))); // NOI18N
      pnlInput.setName("pnlInput"); // NOI18N

      btnClear.setText("Clear");
      btnClear.setName("btnClear"); // NOI18N
      btnClear.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnClearActionPerformed(evt);
         }
      });

      btnLoad.setText("Load");
      btnLoad.setName("btnLoad"); // NOI18N
      btnLoad.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnLoadActionPerformed(evt);
         }
      });

      scrollInput.setName("scrollInput"); // NOI18N

      txtInput.setColumns(20);
      txtInput.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N
      txtInput.setRows(5);
      txtInput.setName("txtInput"); // NOI18N
      scrollInput.setViewportView(txtInput);

      lblExpression.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
      lblExpression.setText("Expression:");
      lblExpression.setName("lblExpression"); // NOI18N

      txtRegex.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N
      txtRegex.setName("txtRegex"); // NOI18N
      txtRegex.addKeyListener(new java.awt.event.KeyAdapter() {
         public void keyPressed(java.awt.event.KeyEvent evt) {
            txtRegexKeyPressed(evt);
         }
      });

      spnColumns.setName("spnColumns"); // NOI18N
      spnColumns.addMouseWheelListener(new java.awt.event.MouseWheelListener() {
         public void mouseWheelMoved(java.awt.event.MouseWheelEvent evt) {
            spnColumnsMouseWheelMoved(evt);
         }
      });

      btnTSV.setText("TSV");
      btnTSV.setName("btnTSV"); // NOI18N
      btnTSV.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnTSVActionPerformed(evt);
         }
      });

      btnCSV.setText("CSV");
      btnCSV.setName("btnCSV"); // NOI18N
      btnCSV.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnCSVActionPerformed(evt);
         }
      });

      btnMatch.setText("Apply");
      btnMatch.setName("btnMatch"); // NOI18N
      btnMatch.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnMatchActionPerformed(evt);
         }
      });

      scrollTable.setName("scrollTable"); // NOI18N

      jTable.setName("jTable"); // NOI18N
      scrollTable.setViewportView(jTable);

      btnTranspose.setText("Transpose");
      btnTranspose.setName("btnTranspose"); // NOI18N
      btnTranspose.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnTransposeActionPerformed(evt);
         }
      });

      btnLiteralise.setText("Literalise");
      btnLiteralise.setName("btnLiteralise"); // NOI18N
      btnLiteralise.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnLiteraliseActionPerformed(evt);
         }
      });

      btnPivot.setText("Pivot (Wide to Long)");
      btnPivot.setName("btnPivot"); // NOI18N
      btnPivot.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnPivotActionPerformed(evt);
         }
      });

      btnReplace.setText("Replace");
      btnReplace.setName("btnReplace"); // NOI18N
      btnReplace.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnReplaceActionPerformed(evt);
         }
      });

      javax.swing.GroupLayout pnlInputLayout = new javax.swing.GroupLayout(pnlInput);
      pnlInput.setLayout(pnlInputLayout);
      pnlInputLayout.setHorizontalGroup(
         pnlInputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
         .addGroup(pnlInputLayout.createSequentialGroup()
            .addContainerGap()
            .addGroup(pnlInputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
               .addComponent(scrollTable, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 566, Short.MAX_VALUE)
               .addComponent(scrollInput, javax.swing.GroupLayout.Alignment.LEADING)
               .addGroup(javax.swing.GroupLayout.Alignment.LEADING, pnlInputLayout.createSequentialGroup()
                  .addComponent(spnColumns, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addComponent(btnCSV)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addComponent(btnTSV)
                  .addGap(18, 18, 18)
                  .addComponent(lblExpression)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addComponent(txtRegex)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addComponent(btnLiteralise)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addComponent(btnMatch))
               .addGroup(pnlInputLayout.createSequentialGroup()
                  .addGap(0, 318, Short.MAX_VALUE)
                  .addComponent(btnPivot)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addComponent(btnTranspose))
               .addGroup(pnlInputLayout.createSequentialGroup()
                  .addComponent(btnReplace)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                  .addComponent(btnLoad)
                  .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                  .addComponent(btnClear)))
            .addContainerGap())
      );
      pnlInputLayout.setVerticalGroup(
         pnlInputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
         .addGroup(pnlInputLayout.createSequentialGroup()
            .addGroup(pnlInputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
               .addComponent(btnLoad, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
               .addComponent(btnClear, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
               .addComponent(btnReplace))
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(scrollInput, javax.swing.GroupLayout.DEFAULT_SIZE, 100, Short.MAX_VALUE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
            .addGroup(pnlInputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
               .addComponent(txtRegex, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
               .addComponent(lblExpression)
               .addComponent(btnTSV)
               .addComponent(btnCSV)
               .addComponent(spnColumns, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
               .addComponent(btnMatch)
               .addComponent(btnLiteralise))
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
            .addComponent(scrollTable, javax.swing.GroupLayout.DEFAULT_SIZE, 101, Short.MAX_VALUE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addGroup(pnlInputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
               .addComponent(btnTranspose)
               .addComponent(btnPivot))
            .addContainerGap())
      );

      splitPane.setTopComponent(pnlInput);

      pnlOutput.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Output", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Dialog", 0, 12))); // NOI18N
      pnlOutput.setName("pnlOutput"); // NOI18N

      lblFormat.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
      lblFormat.setText("Format:");
      lblFormat.setName("lblFormat"); // NOI18N

      txtFormat.setName("txtFormat"); // NOI18N

      btnFormat.setText("Apply");
      btnFormat.setName("btnFormat"); // NOI18N
      btnFormat.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnFormatActionPerformed(evt);
         }
      });

      scrollOutput.setName("scrollOutput"); // NOI18N

      txtOutput.setColumns(20);
      txtOutput.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N
      txtOutput.setRows(5);
      txtOutput.setName("txtOutput"); // NOI18N
      scrollOutput.setViewportView(txtOutput);

      expGrp.add(rdoQuestion);
      rdoQuestion.setSelected(true);
      rdoQuestion.setText("?");
      rdoQuestion.setName("rdoQuestion"); // NOI18N
      rdoQuestion.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            rdoQuestionActionPerformed(evt);
         }
      });

      expGrp.add(rdoDollar);
      rdoDollar.setText("$");
      rdoDollar.setName("rdoDollar"); // NOI18N
      rdoDollar.addActionListener(new java.awt.event.ActionListener() {
         public void actionPerformed(java.awt.event.ActionEvent evt) {
            rdoDollarActionPerformed(evt);
         }
      });

      expGrp.add(rdoSlash);
      rdoSlash.setText("\\");
         rdoSlash.setName("rdoSlash"); // NOI18N
         rdoSlash.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
               rdoSlashActionPerformed(evt);
            }
         });

         lblArgumentMarker.setText("Argument Marker:");
         lblArgumentMarker.setName("lblArgumentMarker"); // NOI18N

         cbBlanks.setText("Replace blanks?");
         cbBlanks.setName("cbBlanks"); // NOI18N

         txtReplace.setText("null");
         txtReplace.setName("txtReplace"); // NOI18N

         javax.swing.GroupLayout pnlOutputLayout = new javax.swing.GroupLayout(pnlOutput);
         pnlOutput.setLayout(pnlOutputLayout);
         pnlOutputLayout.setHorizontalGroup(
            pnlOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlOutputLayout.createSequentialGroup()
               .addContainerGap()
               .addGroup(pnlOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                  .addComponent(scrollOutput)
                  .addGroup(pnlOutputLayout.createSequentialGroup()
                     .addComponent(lblArgumentMarker)
                     .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                     .addComponent(rdoQuestion)
                     .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                     .addComponent(rdoDollar)
                     .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                     .addComponent(rdoSlash)
                     .addGap(18, 18, 18)
                     .addComponent(cbBlanks)
                     .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                     .addComponent(txtReplace, javax.swing.GroupLayout.DEFAULT_SIZE, 177, Short.MAX_VALUE))
                  .addGroup(pnlOutputLayout.createSequentialGroup()
                     .addComponent(lblFormat)
                     .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                     .addComponent(txtFormat)
                     .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                     .addComponent(btnFormat)))
               .addContainerGap())
         );
         pnlOutputLayout.setVerticalGroup(
            pnlOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlOutputLayout.createSequentialGroup()
               .addGroup(pnlOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                  .addComponent(rdoQuestion)
                  .addComponent(rdoDollar)
                  .addComponent(rdoSlash)
                  .addComponent(lblArgumentMarker)
                  .addComponent(cbBlanks)
                  .addComponent(txtReplace, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
               .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
               .addGroup(pnlOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                  .addComponent(lblFormat)
                  .addComponent(txtFormat, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                  .addComponent(btnFormat))
               .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
               .addComponent(scrollOutput, javax.swing.GroupLayout.DEFAULT_SIZE, 102, Short.MAX_VALUE)
               .addContainerGap())
         );

         splitPane.setRightComponent(pnlOutput);

         javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
         getContentPane().setLayout(layout);
         layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
               .addContainerGap()
               .addComponent(splitPane)
               .addContainerGap())
         );
         layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
               .addContainerGap()
               .addComponent(splitPane)
               .addContainerGap())
         );

         pack();
      }// </editor-fold>//GEN-END:initComponents

	private void match() {
		txtOutput.setText("");
		String regex = txtRegex.getText();
		String text = txtInput.getText();

		String[] input = null;

		try {

			Pattern pattern = Pattern.compile(regex);

			int flagsMask = pattern.flags();

			StringBuilder flags = new StringBuilder();

			boolean dotall = false;

			// work out which flags are being used
			if ((flagsMask & Pattern.DOTALL) == Pattern.DOTALL) {
				flags.append("DOTALL ");
				dotall = true;
			}

			if ((flagsMask & Pattern.MULTILINE) == Pattern.MULTILINE) {
				flags.append("MULTILINE ");
			}

			if ((flagsMask & Pattern.CASE_INSENSITIVE) == Pattern.CASE_INSENSITIVE) {
				flags.append("CASE_INSENSITIVE ");
			}

			PivotTableModel model = new PivotTableModel();
			jTable.setModel(model);

			int numMatches = 0;

			// it DOTALL mode is on then grab the entire text rather then seperating by line
			if (dotall) {
				input = new String[1];
				input[0] = text;
			} else {
				input = text.split("\n");
			}

			for (String line : input) {
				Matcher matcher = pattern.matcher(line);
				while (matcher.find()) {

					// group() matches the entire line if there was a match.
					// This if-statment is to suppress extra empty groups from being
					// produced if the regex matches the entire line
					if (matcher.group().length() != line.length()) {
						continue;
					}

					numMatches++;

					txtOutput.append(matcher.group(0) + "\n");

					String[] groups = new String[matcher.groupCount()];
					for (int j = 1; j <= matcher.groupCount(); j++) {
						String s = matcher.group(j);
						groups[j - 1] = s;
					}

					model.addRow(groups);
				}
			}

			model.fireTableStructureChanged();

			txtOutput.append("\nMatched " + numMatches + " line(s) out of "
					+ input.length + " line(s) of input.");

			if (!flags.toString().isEmpty()) {
				txtOutput.append("\n\nFlags: " + flags.toString().trim());
			}

		} catch (PatternSyntaxException ex) {
			txtOutput.setText("");
			txtOutput.append(ex.getMessage());
			txtRegex.setBackground(new Color(1f, 0.3f, 0.3f));
		}

	}

	private void format() {

		txtOutput.setText("");

		TableModel model = jTable.getModel();

		String formatter = this.txtFormat.getText().replaceAll("\\" + exprChar + "(\\d*)", "%$1\\$s");

		for (int row = 0; row < model.getRowCount(); row++) {

			Object[] values = new Object[model.getColumnCount()];

			for (int col = 0; col < model.getColumnCount(); col++) {
				String val = (String) model.getValueAt(row, col);

				if (cbBlanks.isSelected() && val.isEmpty()) {
					val = txtReplace.getText();
				}

				values[col] = val;
			}

			String formatted = String.format(formatter, values);
			txtOutput.append(formatted + "\n");
		}

	}

	private void transpose() {
		PivotTableModel model = (PivotTableModel) jTable.getModel();
		model.transpose();
	}

	private void pivot() {
		PivotTableModel model = (PivotTableModel) jTable.getModel();
		ListMultimap<String, String> columns = new PivotDialog(this).mapColumns(model);
		model.pivotWideToLong(columns.get("preserved"), columns.get("values"));
	}

	private void csv() {
		Integer cols = (Integer) spnColumns.getValue();

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < cols - 1; i++) {
			sb.append("(.*?),");
		}

		sb.append("(.*)");

		txtRegex.setText(sb.toString());
	}

	private void tsv() {
		Integer cols = (Integer) spnColumns.getValue();

		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < cols - 1; i++) {
			sb.append("(.*?)\\t");
		}

		sb.append("(.*)");

		txtRegex.setText(sb.toString());
	}

	private void load() {
		JFileChooser jfc = new JFileChooser();
		if (jfc.showOpenDialog(JRexFrame.this) == JFileChooser.APPROVE_OPTION) {
			try {
				String data = readFile(jfc.getSelectedFile());

				txtInput.setText(data);

			} catch (Exception ex) {
				JOptionPane.showMessageDialog(this, "Error", ex.getMessage(), JOptionPane.ERROR_MESSAGE);
			}
		}
	}

	public String readFile(File file) throws Exception {
		StringBuilder fileContents;
		try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
			@SuppressWarnings("UnusedAssignment")
			String line = null;
			fileContents = new StringBuilder();
			while ((line = reader.readLine()) != null) {
				fileContents.append(line);
				fileContents.append(System.getProperty("line.separator"));
			}
		}
		return fileContents.toString();
	}

   private void btnFormatActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnFormatActionPerformed
		format();
   }//GEN-LAST:event_btnFormatActionPerformed

   private void btnTransposeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTransposeActionPerformed
		transpose();
   }//GEN-LAST:event_btnTransposeActionPerformed

   private void btnMatchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMatchActionPerformed
		match();
   }//GEN-LAST:event_btnMatchActionPerformed

   private void btnCSVActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCSVActionPerformed
		csv();
   }//GEN-LAST:event_btnCSVActionPerformed

   private void btnTSVActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTSVActionPerformed
		tsv();
   }//GEN-LAST:event_btnTSVActionPerformed

   private void btnLoadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLoadActionPerformed
		load();
   }//GEN-LAST:event_btnLoadActionPerformed

   private void btnClearActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnClearActionPerformed
		txtInput.setText("");
   }//GEN-LAST:event_btnClearActionPerformed

   private void rdoQuestionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdoQuestionActionPerformed
		exprChar = "?";
   }//GEN-LAST:event_rdoQuestionActionPerformed

   private void rdoDollarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdoDollarActionPerformed
		exprChar = "$";
   }//GEN-LAST:event_rdoDollarActionPerformed

   private void rdoSlashActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_rdoSlashActionPerformed
		exprChar = "\\";
   }//GEN-LAST:event_rdoSlashActionPerformed

   private void btnLiteraliseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLiteraliseActionPerformed
		txtOutput.setText(this.txtRegex.getText().replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\""));
   }//GEN-LAST:event_btnLiteraliseActionPerformed

   private void spnColumnsMouseWheelMoved(java.awt.event.MouseWheelEvent evt) {//GEN-FIRST:event_spnColumnsMouseWheelMoved
		Integer value = (Integer) spnColumns.getValue();
		value -= evt.getUnitsToScroll();
		spnColumns.setValue(value > 0 ? value : 0);
   }//GEN-LAST:event_spnColumnsMouseWheelMoved

   private void btnPivotActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnPivotActionPerformed
		pivot();
   }//GEN-LAST:event_btnPivotActionPerformed

   private void txtRegexKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtRegexKeyPressed
		// restore default color
		txtRegex.setBackground(defaultTextColor);
   }//GEN-LAST:event_txtRegexKeyPressed

   private void btnReplaceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnReplaceActionPerformed
		new ReplaceDialog(this, txtInput).setVisible(true);
   }//GEN-LAST:event_btnReplaceActionPerformed

	/**
	 * @param args the command line arguments
	 */
	public static void main(String args[]) throws Exception {
		UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
		if (args.length > 0 && "dark".equalsIgnoreCase(args[0])) {
			UIManager.put("control", new Color(50, 50, 50));
			UIManager.put("nimbusBase", new Color(60, 60, 60));
			UIManager.put("nimbusBlueGrey", new Color(60, 60, 60));
			UIManager.put("nimbusFocus", new Color(90, 90, 90));
			UIManager.put("nimbusLightBackground", new Color(70, 70, 70));
			UIManager.put("text", new Color(230, 230, 230));
		}
		java.awt.EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				new JRexFrame().setVisible(true);
			}
		});
	}

   // Variables declaration - do not modify//GEN-BEGIN:variables
   private javax.swing.JButton btnCSV;
   private javax.swing.JButton btnClear;
   private javax.swing.JButton btnFormat;
   private javax.swing.JButton btnLiteralise;
   private javax.swing.JButton btnLoad;
   private javax.swing.JButton btnMatch;
   private javax.swing.JButton btnPivot;
   private javax.swing.JButton btnReplace;
   private javax.swing.JButton btnTSV;
   private javax.swing.JButton btnTranspose;
   private javax.swing.JCheckBox cbBlanks;
   private javax.swing.ButtonGroup expGrp;
   private javax.swing.JTable jTable;
   private javax.swing.JLabel lblArgumentMarker;
   private javax.swing.JLabel lblExpression;
   private javax.swing.JLabel lblFormat;
   private javax.swing.JPanel pnlInput;
   private javax.swing.JPanel pnlOutput;
   private javax.swing.JRadioButton rdoDollar;
   private javax.swing.JRadioButton rdoQuestion;
   private javax.swing.JRadioButton rdoSlash;
   private javax.swing.JScrollPane scrollInput;
   private javax.swing.JScrollPane scrollOutput;
   private javax.swing.JScrollPane scrollTable;
   private javax.swing.JSplitPane splitPane;
   private javax.swing.JSpinner spnColumns;
   private javax.swing.JTextField txtFormat;
   private javax.swing.JTextArea txtInput;
   private javax.swing.JTextArea txtOutput;
   private javax.swing.JTextField txtRegex;
   private javax.swing.JTextField txtReplace;
   // End of variables declaration//GEN-END:variables

}