/*
* Copyright (c) 2011 Patrick Meyer
*
* 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 com.itemanalysis.jmetrik.gui;
import com.itemanalysis.jmetrik.dao.DatabaseAccessObject;
import com.itemanalysis.jmetrik.graph.barchart.BarChartProcess;
import com.itemanalysis.jmetrik.graph.histogram.HistogramProcess;
import com.itemanalysis.jmetrik.graph.irt.IrtPlotDialog;
import com.itemanalysis.jmetrik.graph.itemmap.ItemMapProcess;
import com.itemanalysis.jmetrik.graph.linechart.LineChartProcess;
import com.itemanalysis.jmetrik.graph.nicc.NonparametricCurveProcess;
import com.itemanalysis.jmetrik.graph.piechart.PieChartProcess;
import com.itemanalysis.jmetrik.graph.scatterplot.ScatterplotProcess;
import com.itemanalysis.jmetrik.model.SortedListModel;
import com.itemanalysis.jmetrik.model.VariableModel;
import com.itemanalysis.jmetrik.scoring.BasicScoringProcess;
import com.itemanalysis.jmetrik.scoring.ScoringProcess;
import com.itemanalysis.jmetrik.sql.DatabaseName;
import com.itemanalysis.jmetrik.stats.cmh.CmhProcess;
import com.itemanalysis.jmetrik.stats.correlation.CorrelationProcess;
import com.itemanalysis.jmetrik.graph.density.DensityProcess;
import com.itemanalysis.jmetrik.stats.descriptives.DescriptiveProcess;
import com.itemanalysis.jmetrik.stats.frequency.FrequencyProcess;
import com.itemanalysis.jmetrik.stats.irt.equating.IrtEquatingProcess;
import com.itemanalysis.jmetrik.stats.irt.estimation.IrtItemCalibrationProcess;
import com.itemanalysis.jmetrik.stats.irt.estimation.IrtPersonScoringProcess;
import com.itemanalysis.jmetrik.stats.irt.linking.IrtLinkingProcess;
import com.itemanalysis.jmetrik.stats.irt.rasch.RaschAnalysisProcess;
import com.itemanalysis.jmetrik.stats.itemanalysis.ItemAnalysisProcess;
import com.itemanalysis.jmetrik.stats.ranking.RankingProcess;
import com.itemanalysis.jmetrik.stats.scaling.TestScalingProcess;
import com.itemanalysis.jmetrik.stats.transformation.LinearTransformationProcess;
import com.itemanalysis.jmetrik.swing.*;
import com.itemanalysis.jmetrik.sql.DataTableName;
import com.itemanalysis.jmetrik.statusbar.StatusBar;
import com.itemanalysis.jmetrik.utils.JmetrikFileUtils;
import com.itemanalysis.jmetrik.utils.PrintUtilities;
import com.itemanalysis.jmetrik.workspace.*;
import com.itemanalysis.psychometrics.data.VariableAttributes;
import com.itemanalysis.psychometrics.data.VariableName;
import org.apache.commons.math3.util.Precision;
import org.apache.log4j.Logger;
import sun.print.DialogOwner;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.filechooser.FileSystemView;
import javax.swing.table.JTableHeader;
import javax.swing.text.DefaultEditorKit;
import java.awt.*;
import java.awt.event.*;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.TreeMap;
public class Jmetrik extends JFrame{
final static String APP_NAME = "jMetrik";
final static String VERSION = "4.0.3";
final static boolean BETA_VERSION = false;
final static String RELEASE_DATE = "March 30, 2016";
final static String COPYRIGHT_YEAR = "2009 - 2016";
final static String AUTHOR = "J. Patrick Meyer";
private DataTable dataTable = null;
private DataTable variableTable = null;
private StatusBar statusBar = null;
private Workspace workspace = null;
private JList workspaceList = null;
private JTabbedPane tabbedPane = null;
private JmetrikFileUtils fileUtils = null;
private String importExportPath = ".";
private PrintRequestAttributeSet attributes = null;
public final static String JMETRIK_TEXT_FILE = "com.itemanalysis.jmetrik.swing.JmetrikTextFile";
static Logger logger = Logger.getLogger("jmetrik-logger");
private JButton refreshButton = null;
//Dialog components
private IrtPlotDialog irtPlotDialog = null;
private TreeMap<String, JDialog> dialogs = new TreeMap<String, JDialog>();
public Jmetrik(){
super("jMetrik");
setPreferredSize(new Dimension(1024,650));
setDefaultCloseOperation(EXIT_ON_CLOSE);
//properly close database if user closes window
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent we) {
if(workspace!=null){
workspace.closeDatabase();
}
System.exit(0);
}
});
//add statusbar
statusBar = new StatusBar(1024,30);
statusBar.setBorder(new EmptyBorder(2,2,2,2));
getContentPane().add(statusBar, BorderLayout.SOUTH);
//start logging
startLog();
//left-right splitpane
JSplitPane splitPane1 = new JSplitPane();
splitPane1.setDividerLocation(200);
//setup workspace list
workspaceList = new JList();
workspaceList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
workspaceList.setModel(new SortedListModel<DataTableName>());
workspaceList.addKeyListener(new DeleteKeyListener());
// workspaceList.getInsets().set(5, 5, 5, 5);
//add icon to list cell renderer
String urlString = "/images/spreadsheet.png";
URL url = this.getClass().getResource(urlString);
final ImageIcon tableIcon = new ImageIcon(url, "Table");
workspaceList.setCellRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
label.setIcon(tableIcon);
return label;
}
});
JScrollPane scrollPane1 = new JScrollPane(workspaceList);
scrollPane1.setPreferredSize(new Dimension(200, 698));
splitPane1.setLeftComponent(scrollPane1);
//tabbed pane for top pane
tabbedPane = new JTabbedPane();
tabbedPane.setTabPlacement(JTabbedPane.BOTTOM);
//setup data table
dataTable = new DataTable();
dataTable.setRowHeight(18);
//change size of table header and center text
JTableHeader header = dataTable.getTableHeader();
header.setDefaultRenderer(new TableHeaderCellRenderer());
JScrollPane dataScrollPane = new JScrollPane(dataTable);
tabbedPane.addTab("Data", dataScrollPane);
//setup variable table
variableTable = new DataTable();
variableTable.setRowHeight(18);
variableTable.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
if(e.getClickCount()==2){
JTable target = (JTable)e.getSource();
int row = target.getSelectedRow();
int col = target.getSelectedColumn();
if(col==0){
if(target.getModel() instanceof VariableModel){
VariableModel vModel = (VariableModel)target.getModel();
String s = (String)vModel.getValueAt(row, col);
DatabaseName db = workspace.getDatabaseName();
DataTableName table = workspace.getCurrentDataTable();
RenameVariableDialog renameVariableDialog = new RenameVariableDialog(Jmetrik.this, db, table, s);
renameVariableDialog.setVisible(true);
if(renameVariableDialog.canRun()){
RenameVariableCommand command = renameVariableDialog.getCommand();
workspace.runProcess(command);
}
}//end instanceof
}//end if col==0
}//end if click count==2
}//end mouse clicked
});
//change size of table header and center text
JTableHeader variableHeader = variableTable.getTableHeader();
variableHeader.setDefaultRenderer(new TableHeaderCellRenderer());
variableHeader.setPreferredSize(new Dimension(30, 21));
JScrollPane variableScrollPane = new JScrollPane(variableTable);
tabbedPane.addTab("Variables", variableScrollPane);
splitPane1.setRightComponent(tabbedPane);
getContentPane().add(splitPane1, BorderLayout.CENTER);
//add status bar listener - needed to display status message that are generated within this class
this.addPropertyChangeListener(statusBar.getStatusListener());
//add listener for displaying error messages - needed to display errors and exceptions
this.addPropertyChangeListener(new ErrorOccurredPropertyChangeListener());
//instantiate file utilities
fileUtils = new JmetrikFileUtils();
fileUtils.addPropertyChangeListener(statusBar.getStatusListener());
//set import and export path to user's documents folder
JFileChooser chooser = new JFileChooser();
FileSystemView fw = chooser.getFileSystemView();
importExportPath = fw.getDefaultDirectory().toString().replaceAll("\\\\", "/");
//create and start a workspace
startWorkspace();
//create menu bar and tool bar
this.setJMenuBar(createMenuBar());
JToolBar toolBar = createToolBar();
toolBar.setFloatable(false);
toolBar.setRollover(true);
getContentPane().add(toolBar,BorderLayout.PAGE_START);
pack();
}
/**
* Start logging. The log properties file must exist in a fixed location.
* This location is teh same as that used for storing the application properties.
* See also JmetrikPropertiesManager.java
*/
private void startLog(){
JmetrikPreferencesManager prefs = new JmetrikPreferencesManager();
prefs.addPropertyChangeListener(statusBar.getStatusListener());
prefs.loadLog();
}
private void closeWorkspace(){
if(workspace!=null) workspace.closeDatabase();
workspace = null;
}
private void startWorkspace(){
if(workspace!=null) workspace.closeDatabase();
workspace = new Workspace(workspaceList, tabbedPane, dataTable, variableTable);
workspace.addPropertyChangeListener(new TableNameListener());
workspace.addPropertyChangeListener(statusBar.getStatusListener());
workspace.addPropertyChangeListener(new ErrorOccurredPropertyChangeListener());
// workspace.setRefreshButton(refreshButton);
}
private void openWorkspace(String dbName){
if(workspace!=null){
workspace.closeDatabase();
}
try{
workspace.openDatabase(dbName);
resetDialogs();
}catch(SQLException ex){
logger.fatal(ex.getMessage(), ex);
this.firePropertyChange("error", "", "Error - Check log for details.");
}
}
private JMenuBar createMenuBar(){
final JMenuBar menuBar = new JMenuBar();
JMenuItem mItem = null;
String urlString;
URL url;
//============================================================================================
// File Menu
//============================================================================================
JMenu fileMenu = new JMenu("File");
fileMenu.setMnemonic('f');
menuBar.add(fileMenu);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/document-new.png";
url = this.getClass().getResource( urlString );
ImageIcon iconNew = new ImageIcon(url, "New");
mItem = new JMenuItem(new NewTextFileAction("New", iconNew));
fileMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/document-open.png";
url = this.getClass().getResource( urlString );
ImageIcon iconOpen = new ImageIcon(url, "Open");
mItem = new JMenuItem(new OpenFileAction("Open...", iconOpen, new Integer(KeyEvent.VK_A)));
fileMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/document-save.png";
url = this.getClass().getResource( urlString );
ImageIcon iconSave = new ImageIcon(url, "Save");
mItem = new JMenuItem(new SaveAction("Save",iconSave,new Integer(KeyEvent.VK_S)));
fileMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/document-save-as.png";
url = this.getClass().getResource( urlString );
ImageIcon iconSaveAs = new ImageIcon(url, "Save As");
mItem = new JMenuItem(new SaveAsAction("Save As...",iconSaveAs));
fileMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/status/folder-visiting.png";
url = this.getClass().getResource( urlString );
ImageIcon iconClose = new ImageIcon(url, "Close All Tabs");
mItem = new JMenuItem(new CloseAllTabsAction("Close All Tabs...", iconClose, new Integer(KeyEvent.VK_C)));
fileMenu.add(mItem);
fileMenu.addSeparator();
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/document-print.png";
url = this.getClass().getResource( urlString );
ImageIcon iconPrint = new ImageIcon(url, "Print");
mItem = new JMenuItem(new PrintAction("Print...",iconPrint));
fileMenu.add(mItem);
fileMenu.addSeparator();
// exit menu item
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/system-log-out.png";
url = this.getClass().getResource( urlString );
ImageIcon iconExit = new ImageIcon(url, "Exit");
mItem = new JMenuItem(new ExitAction("Exit",iconExit));
fileMenu.add(mItem);
//============================================================================================
// Edit Menu
//============================================================================================
JMenu editMenu = new JMenu("Edit");
editMenu.setMnemonic(KeyEvent.VK_E);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-cut.png";
url = this.getClass().getResource( urlString );
ImageIcon iconCut = new ImageIcon(url, "Cut");
mItem = new JMenuItem(new DefaultEditorKit.CutAction());
mItem.setText("Cut");
mItem.setIcon(iconCut);
mItem.setMnemonic(KeyEvent.VK_X);
editMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-copy.png";
url = this.getClass().getResource( urlString );
ImageIcon iconCopy = new ImageIcon(url, "Copy");
mItem = new JMenuItem(new DefaultEditorKit.CopyAction());
mItem.setText("Copy");
mItem.setIcon(iconCopy);
mItem.setMnemonic(KeyEvent.VK_C);
editMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-paste.png";
url = this.getClass().getResource( urlString );
ImageIcon iconPaste = new ImageIcon(url, "Paste");
mItem = new JMenuItem(new DefaultEditorKit.PasteAction());
mItem.setText("Paste");
mItem.setIcon(iconPaste);
mItem.setMnemonic(KeyEvent.VK_V);
editMenu.add(mItem);
editMenu.addSeparator();
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-undo.png";
url = this.getClass().getResource( urlString );
ImageIcon iconUndo = new ImageIcon(url, "Undo");
mItem = new JMenuItem(new UndoAction("Undo",iconUndo,new Integer(KeyEvent.VK_Z)));
editMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-redo.png";
url = this.getClass().getResource( urlString );
ImageIcon iconRedo = new ImageIcon(url, "Redo");
mItem = new JMenuItem(new RedoAction("Redo",iconRedo,new Integer(KeyEvent.VK_Y)));
editMenu.add(mItem);
editMenu.addSeparator();
urlString = "/org/tango-project/tango-icon-theme/16x16/categories/preferences-system.png";
url = this.getClass().getResource( urlString );
ImageIcon iconView = new ImageIcon(url, "Preferences");
mItem = new JMenuItem("Preferences");
mItem.setIcon(iconView);
mItem.setToolTipText("Edit jMetrik preferences");
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JmetrikPreferencesManager prefs = new JmetrikPreferencesManager();
prefs.addPropertyChangeListener(new ErrorOccurredPropertyChangeListener());
prefs.addPropertyChangeListener(statusBar.getStatusListener());
JmetrikPreferencesDialog propDialog = new JmetrikPreferencesDialog(Jmetrik.this, prefs);
// propDialog.loadPreferences();
propDialog.setVisible(true);
}
});
editMenu.setMnemonic('e');
editMenu.add(mItem);
menuBar.add(editMenu);
//============================================================================================
// Log Menu
//============================================================================================
JMenu logMenu = new JMenu("Log");
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/document-properties.png";
url = this.getClass().getResource( urlString );
ImageIcon iconLog = new ImageIcon(url, "View Log");
mItem = new JMenuItem(new ViewLogAction("View Log",iconLog));
logMenu.setMnemonic('l');
logMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/mimetypes/text-x-generic.png";
url = this.getClass().getResource( urlString );
ImageIcon iconCommand = new ImageIcon(url, "Script Log");
mItem = new JMenuItem(new ViewScriptLogAction("Script Log",iconCommand));
logMenu.setMnemonic('c');
logMenu.add(mItem);
menuBar.add(logMenu);
//============================================================================================
// Manage Menu
//============================================================================================
JMenu manageMenu = new JMenu("Manage");
manageMenu.setMnemonic('m');
mItem = new JMenuItem("New Database...");//create db
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
NewDatabaseDialog newDatabaseDialog = new NewDatabaseDialog(Jmetrik.this);
newDatabaseDialog.setVisible(true);
if(newDatabaseDialog.canRun()){
if(workspace==null) {
// workspace = new Workspace(workspaceTree, tabbedPane, dataTable, variableTable);
workspace = new Workspace(workspaceList, tabbedPane, dataTable, variableTable);
workspace.addPropertyChangeListener(statusBar.getStatusListener());
workspace.addPropertyChangeListener(new ErrorOccurredPropertyChangeListener());
}
workspace.runProcess(newDatabaseDialog.getCommand());
// workspace.createDatabase(newDatabaseDialog.getCommand());
}
}
});
manageMenu.add(mItem);
mItem = new JMenuItem("Open Database...");
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
OpenDatabaseDialog openDbDialog = new OpenDatabaseDialog(Jmetrik.this, "Open");
JList l = openDbDialog.getDatabaseList();
workspace.setDatabaseListModel(l);
openDbDialog.setVisible(true);
if(openDbDialog.canRun()){
openWorkspace(openDbDialog.getDatabaseName());
}
}
});
manageMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-delete.png";
url = this.getClass().getResource( urlString );
ImageIcon iconDelete = new ImageIcon(url, "Delete");
mItem = new JMenuItem("Delete Database...");
mItem.setIcon(iconDelete);
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
OpenDatabaseDialog selectDialog = new OpenDatabaseDialog(Jmetrik.this, "Delete");
JList l = selectDialog.getDatabaseList();
workspace.setDatabaseListModel(l);
selectDialog.setVisible(true);
if(selectDialog.canRun()){
int answer = JOptionPane.showConfirmDialog(Jmetrik.this,
"Do you want to delete " + selectDialog.getDatabaseName() + " and all of its contents? \n" +
"All data will be permanently deleted. You cannot undo this action.",
"Delete Database",
JOptionPane.WARNING_MESSAGE,
JOptionPane.YES_NO_OPTION);
if(answer==JOptionPane.YES_OPTION){
DatabaseCommand command = new DatabaseCommand();
DatabaseName dbName = new DatabaseName(selectDialog.getDatabaseName());
command.getFreeOption("name").add(dbName.getName());
command.getSelectOneOption("action").setSelected("delete-db");
DatabaseName currentDb = workspace.getDatabaseName();
if(currentDb.getName().equals(dbName.getName())){
JOptionPane.showMessageDialog(Jmetrik.this, "You cannot delete the current database.\n" +
"Close the database before attempting to delete it.",
"Database Delete Error",
JOptionPane.WARNING_MESSAGE);
}else{
workspace.runProcess(command);
}
}
}
}
});
manageMenu.add(mItem);
manageMenu.addSeparator();
urlString = "/org/tango-project/tango-icon-theme/16x16/apps/accessories-text-editor.png";
url = this.getClass().getResource( urlString );
ImageIcon iconDesc = new ImageIcon(url, "Descriptions");
mItem = new JMenuItem("Table Descriptions...");
mItem.setIcon(iconDesc);
mItem.addActionListener(new TableDescriptionActionListener());
manageMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/list-add.png";
url = this.getClass().getResource( urlString );
ImageIcon iconImport = new ImageIcon(url, "Import");
mItem = new JMenuItem("Import Data...");
mItem.setIcon(iconImport);
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(workspace.databaseOpened()){
ImportDialog importDialog = new ImportDialog(Jmetrik.this, workspace.getDatabaseName(), importExportPath);
importDialog.setVisible(true);
if(importDialog.canRun()){
importExportPath = importDialog.getCurrentDirectory();
workspace.runProcess(importDialog.getCommand());
}
}else{
JOptionPane.showMessageDialog(Jmetrik.this, "You must open a database before importing data.",
"No Open Database", JOptionPane.ERROR_MESSAGE);
}
}
});
manageMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/format-indent-less.png";
url = this.getClass().getResource( urlString );
ImageIcon iconExport = new ImageIcon(url, "Export");
mItem = new JMenuItem("Export Data...");
mItem.setIcon(iconExport);
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DataTableName tableName = (DataTableName)workspaceList.getSelectedValue();
if(!workspace.databaseOpened()){
JOptionPane.showMessageDialog(Jmetrik.this, "You must open a database before exporting data.",
"No Open Database", JOptionPane.ERROR_MESSAGE);
}else if(tableName==null){
JOptionPane.showMessageDialog(Jmetrik.this, "You must select a table in the workspace list. \n " +
"Select a table to continue the export.", "No Table Selected", JOptionPane.ERROR_MESSAGE);
}else{
ExportDataDialog exportDialog = new ExportDataDialog(Jmetrik.this, workspace.getDatabaseName(), tableName, importExportPath);
if(exportDialog.canRun()){
importExportPath = exportDialog.getCurrentDirectory();
workspace.runProcess(exportDialog.getCommand());
}
}
}
});
manageMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-delete.png";
url = this.getClass().getResource( urlString );
ImageIcon iconDeleteTable = new ImageIcon(url, "Delete");
mItem = new JMenuItem("Delete Table...");
mItem.setIcon(iconDeleteTable);
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(workspace.databaseOpened()){
DeleteTableDialog deleteDialog = new DeleteTableDialog(Jmetrik.this, workspace.getDatabaseName(), (SortedListModel<DataTableName>)workspaceList.getModel());
deleteDialog.setVisible(true);
if(deleteDialog.canRun()){
int nSelected = deleteDialog.getNumberOfSelectedTables();
int answer = JOptionPane.NO_OPTION;
if(nSelected>1){
answer = JOptionPane.showConfirmDialog(Jmetrik.this,
"Do you want to delete these " + nSelected + " tables? \n" +
"All data will be permanently deleted. You cannot undo this action.",
"Delete Database",
JOptionPane.WARNING_MESSAGE,
JOptionPane.YES_NO_OPTION);
}else{
ArrayList<DataTableName> dList = deleteDialog.getSelectedTables();
answer = JOptionPane.showConfirmDialog(Jmetrik.this,
"Do you want to delete the table " + dList.get(0).getTableName() + "? \n" +
"All data will be permanently deleted. You cannot undo this action.",
"Delete Database",
JOptionPane.WARNING_MESSAGE,
JOptionPane.YES_NO_OPTION);
}
if(answer==JOptionPane.YES_OPTION){
workspace.runProcess(deleteDialog.getCommand());
}
}
}else{
JOptionPane.showMessageDialog(Jmetrik.this, "You must open a database before deleting a table.",
"No Open Database", JOptionPane.ERROR_MESSAGE);
}
}
});
manageMenu.add(mItem);
manageMenu.addSeparator();
SubsetCasesProcess subsetCasesProcess = new SubsetCasesProcess();
subsetCasesProcess.addMenuItem(Jmetrik.this, manageMenu, dialogs, workspace, workspaceList);
SubsetVariablesProcess subsetVariablesProcess = new SubsetVariablesProcess();
subsetVariablesProcess.addMenuItem(Jmetrik.this, manageMenu, dialogs, workspace, workspaceList);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-delete.png";
url = this.getClass().getResource( urlString );
ImageIcon iconDeleteVariables = new ImageIcon(url, "Delete Variables");
mItem = new JMenuItem("Delete Variables...");
mItem.setIcon(iconDeleteVariables);
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DataTableName tableName = (DataTableName)workspaceList.getSelectedValue();
if(!workspace.databaseOpened()){
JOptionPane.showMessageDialog(Jmetrik.this, "You must open a database before subsetting data.",
"No Open Database", JOptionPane.ERROR_MESSAGE);
}else if(tableName==null){
JOptionPane.showMessageDialog(Jmetrik.this, "You must select a table in the workspace list. \n " +
"Select a table to continue.", "No Table Selected", JOptionPane.ERROR_MESSAGE);
}else if(workspace.tableOpen()){
DeleteVariableDialog deleteVariableDialog = new DeleteVariableDialog(
Jmetrik.this,
workspace.getDatabaseName(),
workspace.getCurrentDataTable(),
workspace.getVariables());
deleteVariableDialog.setVisible(true);
if(deleteVariableDialog.canRun()){
int nSelected = deleteVariableDialog.getNumberOfSelectedVariables();
int answer = JOptionPane.NO_OPTION;
if(nSelected>1){
answer = JOptionPane.showConfirmDialog(Jmetrik.this,
"Do you want to delete these " + nSelected + " variables? \n" +
"All data will be permanently deleted. You cannot undo this action.",
"Delete Variables",
JOptionPane.WARNING_MESSAGE,
JOptionPane.YES_NO_OPTION);
}else{
VariableAttributes v = deleteVariableDialog.getSelectedVariable();
answer = JOptionPane.showConfirmDialog(Jmetrik.this,
"Do you want to delete the variable " + v.getName().toString() + "? \n" +
"All data will be permanently deleted. You cannot undo this action.",
"Delete Database",
JOptionPane.WARNING_MESSAGE,
JOptionPane.YES_NO_OPTION);
}
if(answer==JOptionPane.YES_OPTION){
workspace.runProcess(deleteVariableDialog.getCommand());
}
}
}
}
});
manageMenu.add(mItem);
menuBar.add(manageMenu);
//============================================================================================
// Transform Menu
//============================================================================================
JMenu transformMenu = new JMenu("Transform");
transformMenu.setMnemonic('t');
BasicScoringProcess basicScoringProcess = new BasicScoringProcess();
basicScoringProcess.addMenuItem(Jmetrik.this, transformMenu, dialogs, workspace, workspaceList);
ScoringProcess scoringProcess = new ScoringProcess();
scoringProcess.addMenuItem(Jmetrik.this, transformMenu, dialogs, workspace, workspaceList);
transformMenu.addSeparator();
RankingProcess rankingProcess = new RankingProcess();
rankingProcess.addMenuItem(Jmetrik.this, transformMenu, dialogs, workspace, workspaceList);
TestScalingProcess testScalingProcess = new TestScalingProcess();
testScalingProcess.addMenuItem(Jmetrik.this, transformMenu, dialogs, workspace, workspaceList);
LinearTransformationProcess linearTransformationProcess = new LinearTransformationProcess();
linearTransformationProcess.addMenuItem(Jmetrik.this, transformMenu, dialogs, workspace, workspaceList);
transformMenu.addSeparator();
IrtLinkingProcess irtLinkingProcess = new IrtLinkingProcess();
irtLinkingProcess.addMenuItem(Jmetrik.this, transformMenu, dialogs, workspace, workspaceList);
IrtEquatingProcess irtEquatingProcess = new IrtEquatingProcess();
irtEquatingProcess.addMenuItem(Jmetrik.this, transformMenu, dialogs, workspace, workspaceList);
menuBar.add(transformMenu);
//============================================================================================
// Analyze Menu
//============================================================================================
JMenu analyzeMenu = new JMenu("Analyze");
analyzeMenu.setMnemonic('a');
FrequencyProcess frequencyProcess = new FrequencyProcess();
frequencyProcess.addMenuItem(Jmetrik.this, analyzeMenu, dialogs, workspace, workspaceList);
DescriptiveProcess descriptiveProcess = new DescriptiveProcess();
descriptiveProcess.addMenuItem(Jmetrik.this, analyzeMenu, dialogs, workspace, workspaceList);
CorrelationProcess correlationProcess = new CorrelationProcess();
correlationProcess.addMenuItem(Jmetrik.this, analyzeMenu, dialogs, workspace, workspaceList);
analyzeMenu.addSeparator();
ItemAnalysisProcess itemAnalysisProcess = new ItemAnalysisProcess();
itemAnalysisProcess.addMenuItem(Jmetrik.this, analyzeMenu, dialogs, workspace, workspaceList);
CmhProcess cmhProcess = new CmhProcess();
cmhProcess.addMenuItem(Jmetrik.this, analyzeMenu, dialogs, workspace, workspaceList);
analyzeMenu.addSeparator();
RaschAnalysisProcess raschAnalysisProcess = new RaschAnalysisProcess();
raschAnalysisProcess.addMenuItem(Jmetrik.this, analyzeMenu, dialogs, workspace, workspaceList);
IrtItemCalibrationProcess irtItemCalibrationProcess = new IrtItemCalibrationProcess();
irtItemCalibrationProcess.addMenuItem(Jmetrik.this, analyzeMenu, dialogs, workspace, workspaceList);
IrtPersonScoringProcess irtPersonScoringProcess = new IrtPersonScoringProcess();
irtPersonScoringProcess.addMenuItem(Jmetrik.this, analyzeMenu, dialogs, workspace, workspaceList);
menuBar.add(analyzeMenu);
//============================================================================================
// Graph Menu
//============================================================================================
JMenu graphMenu = new JMenu("Graph");
graphMenu.setMnemonic('g');
BarChartProcess barchartProcess = new BarChartProcess();
barchartProcess.addMenuItem(Jmetrik.this, graphMenu, dialogs, workspace, workspaceList);
PieChartProcess piechartProcess = new PieChartProcess();
piechartProcess.addMenuItem(Jmetrik.this, graphMenu, dialogs, workspace, workspaceList);
graphMenu.addSeparator();
HistogramProcess histogramProcess = new HistogramProcess();
histogramProcess.addMenuItem(Jmetrik.this, graphMenu, dialogs, workspace, workspaceList);
DensityProcess densityProcess= new DensityProcess();
densityProcess.addMenuItem(Jmetrik.this, graphMenu, dialogs, workspace, workspaceList);
LineChartProcess lineChartProcess = new LineChartProcess();
lineChartProcess.addMenuItem(Jmetrik.this, graphMenu, dialogs, workspace, workspaceList);
ScatterplotProcess scatterplotProcess = new ScatterplotProcess();
scatterplotProcess.addMenuItem(Jmetrik.this, graphMenu, dialogs, workspace, workspaceList);
graphMenu.addSeparator();
NonparametricCurveProcess nonparametricCurveProcess = new NonparametricCurveProcess();
nonparametricCurveProcess.addMenuItem(Jmetrik.this, graphMenu, dialogs, workspace, workspaceList);
mItem = new JMenuItem("Irt Plot...");
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DataTableName tableName = (DataTableName) workspaceList.getSelectedValue();
if(tableName==null){
JOptionPane.showMessageDialog(Jmetrik.this, "You must open a database and select a table. \n " +
"Select a table to continue scoring.", "No Table Selected", JOptionPane.ERROR_MESSAGE);
}else {
if(irtPlotDialog==null && workspace.tableOpen()){
//Note that starting this dialog is different because variables
//names must be obtained from the rows of a table.
DatabaseAccessObject dao = workspace.getDatabaseFactory().getDatabaseAccessObject();
try{
ArrayList<VariableAttributes> tempVar = dao.getVariableAttributesFromColumn(workspace.getConnection(), workspace.getCurrentDataTable(), new VariableName("name"));
irtPlotDialog = new IrtPlotDialog(Jmetrik.this, workspace.getDatabaseName(), tableName, tempVar, (SortedListModel<DataTableName>)workspaceList.getModel());
}catch(SQLException ex){
logger.fatal(ex.getMessage(), ex);
firePropertyChange("error", "", "Error - Check log for details.");
}
}
if(irtPlotDialog!=null) irtPlotDialog.setVisible(true);
}
if(irtPlotDialog!=null && irtPlotDialog.canRun()){
workspace.runProcess(irtPlotDialog.getCommand());
}
}
});
graphMenu.add(mItem);
ItemMapProcess itemMapProcess = new ItemMapProcess();
itemMapProcess.addMenuItem(Jmetrik.this, graphMenu, dialogs, workspace, workspaceList);
menuBar.add(graphMenu);
//============================================================================================
// Command Menu
//============================================================================================
JMenu commandMenu = new JMenu("Commands");
commandMenu.setMnemonic('c');
mItem = new JMenuItem("Run command");
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JScrollPane pain = (JScrollPane)tabbedPane.getSelectedComponent();
JViewport vp = pain.getViewport();
Component c = vp.getComponent(0);
if(c instanceof JmetrikTextFile){
JmetrikTab tempTab = (JmetrikTab)tabbedPane.getTabComponentAt(tabbedPane.getSelectedIndex());
JmetrikTextFile textFile = (JmetrikTextFile)c;
workspace.runFromSyntax(textFile.getText());
}
}
});
commandMenu.add(mItem);
mItem = new JMenuItem("Stop command");
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//add something
}
});
mItem.setEnabled(false);
commandMenu.add(mItem);
mItem = new JMenuItem("Command Reference...");
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
//add something
}
});
mItem.setEnabled(false);
commandMenu.add(mItem);
menuBar.add(commandMenu);
//============================================================================================
// Help Menu
//============================================================================================
JMenu helpMenu = new JMenu("Help");
helpMenu.setMnemonic('h');
mItem = new JMenuItem("Quick Start Guide");
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Desktop deskTop = Desktop.getDesktop();
try{
URI uri = new URI("http://www.itemanalysis.com/quick-start-guide.php");
deskTop.browse(uri);
}catch(URISyntaxException ex){
logger.fatal(ex.getMessage(), ex);
firePropertyChange("error", "", "Error - Check log for details.");
}catch(IOException ex){
logger.fatal(ex.getMessage(), ex);
firePropertyChange("error", "", "Error - Check log for details.");
}
}
});
helpMenu.add(mItem);
urlString = "/org/tango-project/tango-icon-theme/16x16/apps/help-browser.png";
url = this.getClass().getResource( urlString );
ImageIcon iconAbout = new ImageIcon(url, "About");
mItem = new JMenuItem("About");
mItem.setIcon(iconAbout);
mItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JmetrikAboutDialog aboutDialog = new JmetrikAboutDialog(Jmetrik.this,
APP_NAME, VERSION, AUTHOR, RELEASE_DATE, COPYRIGHT_YEAR, BETA_VERSION);
aboutDialog.setVisible(true);
}
});
helpMenu.add(mItem);
menuBar.add(helpMenu);
return menuBar;
}
private JToolBar createToolBar(){
String urlString;
URL url;
final JToolBar tools = new JToolBar("jMetrik Tool Bar");
JButton button;
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/document-new.png";
url = this.getClass().getResource( urlString );
ImageIcon iconNew = new ImageIcon(url, "New");
button = new JButton(new NewTextFileAction("", iconNew));
tools.add(button);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/document-open.png";
url = this.getClass().getResource( urlString );
ImageIcon iconOpen = new ImageIcon(url, "Open");
button = new JButton(new OpenFileAction("",iconOpen));
tools.add(button);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/document-save.png";
url = this.getClass().getResource( urlString );
ImageIcon iconSave = new ImageIcon(url, "Save As");
button = new JButton(new SaveAction("",iconSave));
tools.add(button);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/document-save-as.png";
url = this.getClass().getResource( urlString );
ImageIcon iconSaveAs = new ImageIcon(url, "Save As");
button = new JButton(new SaveAsAction("",iconSaveAs));
tools.add(button);
tools.addSeparator();
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/document-print.png";
url = this.getClass().getResource( urlString );
ImageIcon iconPrint = new ImageIcon(url, "Print");
button = new JButton(new PrintAction("",iconPrint));
tools.add(button);
tools.addSeparator();
// urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-cut.png";
// url = this.getClass().getResource( urlString );
// ImageIcon iconCut = new ImageIcon(url, "Cut");
// button = new JButton(new DefaultEditorKit.CutAction());
// button.setText("");
// button.setIcon(iconCut);
// tools.addArgument(button);
//
// urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-copy.png";
// url = this.getClass().getResource( urlString );
// ImageIcon iconCopy = new ImageIcon(url, "Copy");
// button = new JButton(new DefaultEditorKit.CopyAction());
// button.setText("");
// button.setIcon(iconCopy);
// tools.addArgument(button);
//
// urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-paste.png";
// url = this.getClass().getResource( urlString );
// ImageIcon iconPaste = new ImageIcon(url, "Paste");
// button = new JButton(new DefaultEditorKit.PasteAction());
// button.setIcon(iconPaste);
// button.setText("");
// tools.addArgument(button);
//
// tools.addSeparator();
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-undo.png";
url = this.getClass().getResource( urlString );
ImageIcon iconUndo = new ImageIcon(url, "Undo");
button = new JButton(new UndoAction("",iconUndo));
tools.add(button);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/edit-redo.png";
url = this.getClass().getResource( urlString );
ImageIcon iconRedo = new ImageIcon(url, "Redo");
button = new JButton(new RedoAction("",iconRedo));
tools.add(button);
tools.addSeparator();
urlString = "/org/tango-project/tango-icon-theme/16x16/apps/accessories-text-editor.png";
url = this.getClass().getResource( urlString );
ImageIcon iconDesc = new ImageIcon(url, "Descriptions");
button = new JButton("", iconDesc);
button.setToolTipText("View table descriptions");
button.addActionListener(new TableDescriptionActionListener());
tools.add(button);
tools.addSeparator();
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/media-playback-start.png";
url = this.getClass().getResource( urlString );
ImageIcon iconStart = new ImageIcon(url, "Run Analysis from Syntax");
button = new JButton(iconStart);
button.setToolTipText("Run commands");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JScrollPane pain = (JScrollPane)tabbedPane.getSelectedComponent();
JViewport vp = pain.getViewport();
Component c = vp.getComponent(0);
if(c instanceof JmetrikTextFile){
JmetrikTab tempTab = (JmetrikTab)tabbedPane.getTabComponentAt(tabbedPane.getSelectedIndex());
JmetrikTextFile textFile = (JmetrikTextFile)c;
workspace.runFromSyntax(textFile.getText());
}
}
});
tools.add(button);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/media-playback-stop.png";
url = this.getClass().getResource( urlString );
ImageIcon iconStopThreads = new ImageIcon(url, "Stop Analysis");
// button = new JButton(new StopAllThreadsAction("",iconStopThreads));
button = new JButton(iconStopThreads);
tools.add(button);
tools.addSeparator();
urlString = "/org/tango-project/tango-icon-theme/16x16/apps/utilities-system-monitor.png";
url = this.getClass().getResource(urlString);
ImageIcon iconStartMemoryMonitor = new ImageIcon(url, "Start Memory Monitor");
button = new JButton(iconStartMemoryMonitor);
button.setToolTipText("View memory allocation");
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
double m = (double)Runtime.getRuntime().maxMemory();
double f = (double)Runtime.getRuntime().freeMemory();
double t = (double)Runtime.getRuntime().totalMemory();
f = f/1048576.0;
t = t/1048576.0;
m = m/1048576.0;
double amem = Precision.round(f/t*100.0, 2);
JOptionPane.showMessageDialog(Jmetrik.this,
"Total memory available: " + Precision.round(m,2) + " MB\n" +
"Current allocation: " + Precision.round(t,2) + " MB\n" +
"Current amount free: " + Precision.round(f,2) + " MB (" + amem + "%)",
"JVM Memory Available",
JOptionPane.INFORMATION_MESSAGE);
}
});
tools.add(button);
urlString = "/org/tango-project/tango-icon-theme/16x16/status/folder-visiting.png";
url = this.getClass().getResource( urlString );
ImageIcon iconCloseAllTabs = new ImageIcon(url, "Close All");
button = new JButton(new CloseAllTabsAction("",iconCloseAllTabs));
tools.add(button);
urlString = "/org/tango-project/tango-icon-theme/16x16/actions/view-refresh.png";
url = this.getClass().getResource( urlString );
ImageIcon iconRefreshData = new ImageIcon(url, "Refresh Data View");
refreshButton = new JButton("",iconRefreshData);
refreshButton.setEnabled(false);
tools.add(refreshButton);
refreshButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
workspace.reloadTable(workspace.getCurrentDataTable());
refreshButton.setEnabled(false);
refreshButton.setText("");
}
});
workspace.setRefreshButton(refreshButton);
return tools;
}
public void addTab(String title, Component p){
final Component P = p;
tabbedPane.addTab(null, p);
JmetrikTab jTab = new JmetrikTab(title);
jTab.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int closeTabNumber = tabbedPane.indexOfComponent(P);
JScrollPane sp = (JScrollPane)tabbedPane.getComponentAt(closeTabNumber);
JViewport vp = sp.getViewport();
if(vp.getComponent(0).getClass().getName().equals(JMETRIK_TEXT_FILE)){
int result = ((JmetrikTextFile)vp.getComponent(0)).promptToSave(Jmetrik.this);
if(result==JOptionPane.YES_OPTION || result==JOptionPane.NO_OPTION){
tabbedPane.removeTabAt(closeTabNumber);
}
}
}
});
tabbedPane.setTabComponentAt(tabbedPane.getTabCount()-1, jTab);
tabbedPane.setSelectedIndex(tabbedPane.getTabCount()-1);
}
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
try {
Color SELECTED_COLOR = new Color(184, 204, 217);
Color BASE_COLOR = new Color(220,231,243, 50);
Color ALT_COLOR = new Color(220,231,243,115);
// Insets MENU_INSETS = new Insets(1,12,2,5);//default values
// Font MENU_FONT = new Font("SansSerif ", Font.PLAIN, 12);//default values
// UIManager.put("nimbusBase", BASE_COLOR);
UIManager.put("nimbusSelection", SELECTED_COLOR);
UIManager.put("nimbusSelectionBackground", SELECTED_COLOR);
UIManager.put("Menu[Enabled+Selected].backgroundPainter", SELECTED_COLOR);
//override defaults
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if (info.getName().equals("Nimbus")) {
UIManager.setLookAndFeel(info.getClassName());
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
defaults.put("Table.gridColor", Color.lightGray);
defaults.put("Table.disabled", false);
defaults.put("Table.showGrid", true);
defaults.put("Table.intercellSpacing", new Dimension(1, 1));
break;
}
}
// UIManager.put("TitledBorder.position", TitledBorder.TOP);
// UIManager.put("Table.showGrid", true);
// UIManager.put("Table.gridColor", Color.RED);
// UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
}catch(UnsupportedLookAndFeelException ulafe){
// logger.fatal("Substance failed to set", ulafe);
}catch(Exception ex){
// logger.fatal(ex.getMessage(), ex);
}
JFrame frame = new Jmetrik();
// set window to maximum size but account for taskbar
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
Rectangle rect = env.getMaximumWindowBounds();
int width = Double.valueOf(rect.getWidth()-1.0).intValue();
int height = Double.valueOf(rect.getHeight()-1.0).intValue();
frame.setMaximizedBounds(new Rectangle(0,0,width, height));
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
frame.pack();
// frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible(true);
//check for updates to jmetrik
((Jmetrik)frame).checkForUpdates();
}
});
}
/**
* Saving file happen in its own thread
*/
private void save(JmetrikTextFile textFile, JmetrikTab tab){
File f = null;
if(!textFile.hasFile()){
f = fileUtils.chooseFileToSave(Jmetrik.this, textFile.getFile());
if(f!=null){
Toolkit.getDefaultToolkit().beep();
int question = JOptionPane.showConfirmDialog(Jmetrik.this,
f.getName() + " already fileExists. Do you want to overwrite it?",
"File Exists",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if(question==JOptionPane.YES_OPTION) {
textFile.fileSave(f, tab);
}
}
}else{
textFile.fileSave(tab);
}
}
private void saveAs(JmetrikTextFile textFile, JmetrikTab tab){
File f = fileUtils.chooseFileToSave(Jmetrik.this, textFile.getFile());
if(f!=null){
if(f.exists()){
Toolkit.getDefaultToolkit().beep();
int question = JOptionPane.showConfirmDialog(Jmetrik.this,
f.getName() + " already fileExists. Do you want to overwrite it?",
"File Exists",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE);
if(question==JOptionPane.YES_OPTION) {
textFile.fileSave(f, tab);
}
}else{
textFile.fileSave(f, tab);
}
}
}
private void resetDialogs(){
irtPlotDialog = null;
for(String s : dialogs.keySet()){
JDialog d = dialogs.get(s);
d.dispose();
d = null;
}
dialogs.clear();
}
private void checkForUpdates(){
URL url = null;
URLConnection urlConn = null;
BufferedReader br = null;
logger.info("Checking for updates...");
try{
url = new URL("http://www.itemanalysis.com/version/jmetrik-version.txt");
urlConn = url.openConnection();
urlConn.setDoInput(true);
urlConn.setUseCaches(false);
br = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));
String s = "";
String[] availableVersion = null;
String[] currentVersion = VERSION.split("\\.");
int needUpdate = 0;
while((s=br.readLine())!=null){
availableVersion = s.trim().split("\\.");
}
br.close();
if(currentVersion.length < availableVersion.length){
needUpdate++;
}
for(int i=0;i<currentVersion.length;i++){
if(Integer.parseInt(currentVersion[i].trim())<Integer.parseInt(availableVersion[i].trim())){
needUpdate++;
}
}
if(needUpdate>0 && !BETA_VERSION){
showUpdateResults(needUpdate>0);
logger.info("jMetrik updates available. Please go to www.ItemAnalysis.com and download the new version.");
}else{
logger.info("No updates available. You have the most current version of jMetrik.");
}
}catch(MalformedURLException ex){
logger.fatal("Could not access update information: MalformedURLException");
}catch(IOException ex){
logger.fatal("Could not access update information: IOException");
}
}
private void showUpdateResults(boolean updateAvailable){
String text = "";
if(updateAvailable){
text = "<html><body>jMetrik Update Available. <br>" +
"Go to <a href=http://www.itemanalysis.com/jmetrik_download.php>http://www.itemanalysis.com/jmetrik-download.php</a><br>" +
"and download the new version.<br>" +
"</body></html>";
}else{
text = "<html><body>No Update Available. <br>" +
"You have the most current version of jMetrik. <br></body></html>";
}
final JEditorPane p = new JEditorPane("text/html", text);
p.setEditable(false);
p.addHyperlinkListener( new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
Desktop deskTop = Desktop.getDesktop();
try{
URI uri = new URI("http://www.itemanalysis.com/jmetrik-download.php");
deskTop.browse(uri);
}catch(URISyntaxException ex){
logger.fatal(ex.getMessage(), ex);
}catch(IOException ex){
logger.fatal(ex.getMessage(), ex);
}
}
}
});
JOptionPane.showMessageDialog(Jmetrik.this, p, "jMetrik Update Status", JOptionPane.INFORMATION_MESSAGE);
}
//=================================================================================================================
// Menu Actions
//=================================================================================================================
public class NewTextFileAction extends AbstractAction{
private static final long serialVersionUID = 1L;
final static String TOOL_TIP = "New text file";
public NewTextFileAction(String text, ImageIcon icon, Integer mnemonic){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
putValue(MNEMONIC_KEY, mnemonic);
}
public NewTextFileAction(String text, ImageIcon icon){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public NewTextFileAction(String text){
super(text);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public void actionPerformed(ActionEvent e){
newDocument();
}
public void newDocument(){
String userHome = null;
String name = "New File.txt";
JmetrikTextFile textFile = new JmetrikTextFile();
textFile.addPropertyChangeListener(statusBar.getStatusListener());
JScrollPane p = new JScrollPane(textFile);
p.setPreferredSize(new Dimension(730,550));
addTab(name, p);
}
} // end NewAction
public class OpenFileAction extends AbstractAction{
private static final long serialVersionUID = 1L;
final static String TOOL_TIP = "Open text file";
public OpenFileAction(String text, ImageIcon icon, Integer mnemonic){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
putValue(MNEMONIC_KEY, mnemonic);
}
public OpenFileAction(String text, ImageIcon icon){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public OpenFileAction(String text){
super(text);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public void actionPerformed(ActionEvent e){
openDocument();
}
public void openDocument(){
File f = fileUtils.chooseFileToOpen(Jmetrik.this);
if(f!=null){
JmetrikTextFile textFile = new JmetrikTextFile();
textFile.addPropertyChangeListener(statusBar.getStatusListener());
JScrollPane p = new JScrollPane(textFile);
p.setPreferredSize(new Dimension(730,550));
textFile.openFile(f);
addTab(f.getName(), p);
}
}
} // end OpenAction
public class CloseAllTabsAction extends AbstractAction{
private static final long serialVersionUID = 1L;
final static String TOOL_TIP = "Close all tabs without saving";
public CloseAllTabsAction(String text, ImageIcon icon, Integer mnemonic){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
putValue(MNEMONIC_KEY, mnemonic);
}
public CloseAllTabsAction(String text, ImageIcon icon){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public CloseAllTabsAction(String text){
super(text);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public void actionPerformed(ActionEvent e){
int count = tabbedPane.getTabCount();
if(count>2){
int result = JOptionPane.showConfirmDialog(Jmetrik.this,
"Close all tabs without saving?",
"Close All Tabs",
JOptionPane.YES_NO_OPTION);
if(result==JOptionPane.YES_OPTION){
while(count>2){
tabbedPane.removeTabAt(count-1);
count = tabbedPane.getTabCount();
}
}
}
}
} // end Action
public class SaveAction extends AbstractAction{
private static final long serialVersionUID = 1L;
final static String TOOL_TIP = "Save text file";
public SaveAction(String text, ImageIcon icon, Integer mnemonic){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
putValue(MNEMONIC_KEY, mnemonic);
}
public SaveAction(String text, ImageIcon icon){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public SaveAction(String text){
super(text);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public void actionPerformed(ActionEvent e){
JScrollPane pain = (JScrollPane)tabbedPane.getSelectedComponent();
JViewport vp = pain.getViewport();
Component c = vp.getComponent(0);
if(c instanceof JmetrikTextFile){
JmetrikTab tempTab = (JmetrikTab)tabbedPane.getTabComponentAt(tabbedPane.getSelectedIndex());
JmetrikTextFile textFile = (JmetrikTextFile)c;
save(textFile, tempTab);
}
}
}//end save action
public class SaveAsAction extends AbstractAction{
private static final long serialVersionUID = 1L;
final static String TOOL_TIP = "Save As text file";
public SaveAsAction(String text, ImageIcon icon, Integer mnemonic){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
putValue(MNEMONIC_KEY, mnemonic);
}
public SaveAsAction(String text, ImageIcon icon){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public SaveAsAction(String text){
super(text);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public void actionPerformed(ActionEvent e){
JScrollPane pain = (JScrollPane)tabbedPane.getSelectedComponent();
JViewport vp = pain.getViewport();
Component c = vp.getComponent(0);
if(c instanceof JmetrikTextFile){
JmetrikTab tempTab = (JmetrikTab)tabbedPane.getTabComponentAt(tabbedPane.getSelectedIndex());
JmetrikTextFile textFile = (JmetrikTextFile)c;
saveAs(textFile, tempTab);
}
}
}//end SaveAsAction
public class PrintAction extends AbstractAction{
private static final long serialVersionUID = 1L;
final static String TOOL_TIP = "Print text file";
public PrintAction(String text, ImageIcon icon, Integer mnemonic){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
putValue(MNEMONIC_KEY, mnemonic);
}
public PrintAction(String text, ImageIcon icon){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public PrintAction(String text){
super(text);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public void actionPerformed(ActionEvent e){
if(!tabbedPane.getSelectedComponent().getClass().getName().equals("javax.swing.JPanel")){
JScrollPane pain = (JScrollPane)tabbedPane.getSelectedComponent();
JViewport vp = pain.getViewport();
Component c = vp.getComponent(0);
if(c instanceof JmetrikTextFile){
JmetrikTextFile textFile = (JmetrikTextFile)c;
PrintUtilities printer=new PrintUtilities(textFile);
try{
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(printer);
if(attributes==null){
attributes = new HashPrintRequestAttributeSet();
// attributes.addArgument(DialogTypeSelection.NATIVE);
attributes.add(new DialogOwner(Jmetrik.this));
}
boolean ok = job.printDialog(attributes);
if(ok) job.print(attributes);
}catch(PrinterException ex){
logger.fatal(ex.getMessage(), ex);
this.firePropertyChange("error", "", "Error - Check log for details.");
}
}
}
}
}//end PrintAction
public class ExitAction extends AbstractAction{
private static final long serialVersionUID = 1L;
final static String TOOL_TIP = "Exit";
public ExitAction(String text, ImageIcon icon, Integer mnemonic){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
putValue(MNEMONIC_KEY, mnemonic);
}
public ExitAction(String text, ImageIcon icon){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public ExitAction(String text){
super(text);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public void actionPerformed(ActionEvent e){
if(workspace!=null) workspace.closeDatabase();
System.exit(0);
}
}//end ExitAction
public class ViewLogAction extends AbstractAction{
private static final long serialVersionUID = 1L;
final static String TOOL_TIP = "View Log";
public ViewLogAction(String text, ImageIcon icon, Integer mnemonic){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
putValue(MNEMONIC_KEY, mnemonic);
}
public ViewLogAction(String text, ImageIcon icon){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public ViewLogAction(String text){
super(text);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public void actionPerformed(ActionEvent e){
this.firePropertyChange("status", null, "Opening file...");
JmetrikPreferencesManager prefs = new JmetrikPreferencesManager();
String logHome = prefs.getLogHome();
File f = new File(logHome + "/"+JmetrikPreferencesManager.DEFAULT_LOG_NAME);
JmetrikTextFile textFile = new JmetrikTextFile();
JScrollPane p = new JScrollPane(textFile);
p.setPreferredSize(new Dimension(730,550));
addTab(f.getName(), p);
FileOpener fileOpener = new FileOpener(f, textFile);
fileOpener.addPropertyChangeListener(statusBar.getStatusListener());
fileOpener.addPropertyChangeListener(new ErrorOccurredPropertyChangeListener());
fileOpener.execute();//open in independent thread
}
}//end View LogAction
public class ViewScriptLogAction extends AbstractAction{
private static final long serialVersionUID = 1L;
final static String TOOL_TIP = "View Script Log";
public ViewScriptLogAction(String text, ImageIcon icon, Integer mnemonic){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
putValue(MNEMONIC_KEY, mnemonic);
}
public ViewScriptLogAction(String text, ImageIcon icon){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public ViewScriptLogAction(String text){
super(text);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public void actionPerformed(ActionEvent e){
this.firePropertyChange("status", null, "Opening Script log...");
JmetrikPreferencesManager prefs = new JmetrikPreferencesManager();
String logHome = prefs.getLogHome();
File f = new File(logHome + "/" + JmetrikPreferencesManager.DEFAULT_SCRIPT_LOG_NAME);
JmetrikTextFile textFile = new JmetrikTextFile();
JScrollPane p = new JScrollPane(textFile);
p.setPreferredSize(new Dimension(730,550));
addTab(f.getName(), p);
FileOpener fileOpener = new FileOpener(f, textFile);
fileOpener.addPropertyChangeListener(statusBar.getStatusListener());
fileOpener.addPropertyChangeListener(new ErrorOccurredPropertyChangeListener());
fileOpener.execute();//open in independent thread
}
}//end View Script LogAction
public class UndoAction extends AbstractAction{
private static final long serialVersionUID = 1L;
final static String TOOL_TIP = "Undo";
public UndoAction(String text, ImageIcon icon, Integer mnemonic){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
putValue(MNEMONIC_KEY, mnemonic);
}
public UndoAction(String text, ImageIcon icon){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public UndoAction(String text){
super(text);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public void actionPerformed(ActionEvent e){
Component c = tabbedPane.getSelectedComponent();
if(c.getClass().getName().equals("javax.swing.JScrollPane")){
JScrollPane pain = (JScrollPane)c;
JViewport vp = pain.getViewport();
Component c2 = vp.getComponent(0);
if(c2 instanceof JmetrikTextFile){
JmetrikTextFile tp = (JmetrikTextFile)vp.getComponent(0);
tp.undoText();
}
}
}
}//end UndoAction
public class RedoAction extends AbstractAction{
private static final long serialVersionUID = 1L;
final static String TOOL_TIP = "Redo";
public RedoAction(String text, ImageIcon icon, Integer mnemonic){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
putValue(MNEMONIC_KEY, mnemonic);
}
public RedoAction(String text, ImageIcon icon){
super(text, icon);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public RedoAction(String text){
super(text);
putValue(SHORT_DESCRIPTION, TOOL_TIP);
}
public void actionPerformed(ActionEvent e){
// check to see if component is a TextfileArea which is in a JScrollPane
Component c = tabbedPane.getSelectedComponent();
if(c.getClass().getName().equals("javax.swing.JScrollPane")){
JScrollPane pain = (JScrollPane)tabbedPane.getSelectedComponent();
JViewport vp = pain.getViewport();
Component c2 = vp.getComponent(0);
if(c2 instanceof JmetrikTextFile){
JmetrikTextFile tp = (JmetrikTextFile)vp.getComponent(0);
tp.redoText();
}
}
}
}//end RedoAction
class TableDescriptionActionListener implements ActionListener{
public void actionPerformed(ActionEvent evt){
if(workspace.databaseOpened()){
DatabaseAccessObject dao = workspace.getDatabaseFactory().getDatabaseAccessObject();
TableDescriptionDialog descriptionDialog = new TableDescriptionDialog(
Jmetrik.this,
workspace.getConnection(),
dao,
workspace.getDatabaseName(),
(SortedListModel<DataTableName>)workspaceList.getModel());
descriptionDialog.setVisible(true);
}else{
JOptionPane.showMessageDialog(Jmetrik.this, "You must open a database before viewing table descriptions.",
"No Open Database", JOptionPane.ERROR_MESSAGE);
}
}
}
/**
* Listener will reset all dialogs if table data has changed (i.e. table-updated)
* or if a new table is selected in teh tree (i.e. table-selection). It
* will also display the data table if teh selected table has changed.
*
* Dialogs are reset when table-updated is fired because variables need to
* have the most up to date information such as any recently changed scoring.
*/
class TableNameListener implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName();
if("table-selection".equals(propertyName)){
DataTableName newName = (DataTableName)e.getNewValue();
DataTableName oldName = (DataTableName)e.getOldValue();
if(!newName.equals(oldName)){
resetDialogs();
tabbedPane.setSelectedIndex(0);//show selected table in tabbed pane
}
}
else if("table-updated".equals(propertyName)){
DataTableName newName = (DataTableName)e.getNewValue();
DataTableName oldName = (DataTableName)e.getOldValue();
if(!newName.equals(oldName)){
resetDialogs();
}
}
}
}
class ErrorOccurredPropertyChangeListener implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent e) {
String propertyName = e.getPropertyName();
if("error".equals(propertyName)){
JOptionPane.showMessageDialog(Jmetrik.this,
"An error occurred. \n" +
"View the information in the Log file for details.\n" +
"Contact support@itemanalysis.com for help",
e.getNewValue().toString(),
JOptionPane.ERROR_MESSAGE);
firePropertyChange("progress-off", null, null); //make statusbar progress not visible
}
}
}
public class DeleteKeyListener implements KeyListener{
public void keyPressed(KeyEvent ke){
if (ke.getKeyCode() == KeyEvent.VK_DELETE) {
DataTableName tableName = (DataTableName)workspaceList.getSelectedValue();
if(tableName!=null && workspace.databaseOpened()){
int answer = JOptionPane.showConfirmDialog(Jmetrik.this,
"Do you want to delete the table " + tableName.getTableName() + "? \n" +
"All data will be permanently deleted. You cannot undo this action.",
"Delete Table",
JOptionPane.WARNING_MESSAGE,
JOptionPane.YES_NO_OPTION);
if(answer==JOptionPane.YES_OPTION){
DatabaseCommand dbCommand = new DatabaseCommand();
dbCommand.getFreeOption("name").add(workspace.getDatabaseName().toString());
dbCommand.getFreeOptionList("tables").addValue(tableName.toString());
dbCommand.getSelectOneOption("action").setSelected("delete-table");
workspace.runProcess(dbCommand);
}
}
}
}
public void keyReleased(KeyEvent ke){
}
public void keyTyped(KeyEvent ke){
}
}
}