
ncsa.hdf.view.DefaultTableView Maven / Gradle / Ivy
/*****************************************************************************
* Copyright by The HDF Group. *
* Copyright by the Board of Trustees of the University of Illinois. *
* All rights reserved. *
* *
* This file is part of the HDF Java Products distribution. *
* The full copyright notice, including terms governing use, modification, *
* and redistribution, is contained in the files COPYING and Copyright.html. *
* COPYING can be found at the root of the source code distribution tree. *
* Or, see http://hdfgroup.org/products/hdf-java/doc/Copyright.html. *
* If you do not have access to either file, you may request a copy from *
* [email protected]. *
****************************************************************************/
package ncsa.hdf.view;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.BitSet;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.CellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.MatteBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import ncsa.hdf.object.CompoundDS;
import ncsa.hdf.object.Dataset;
import ncsa.hdf.object.Datatype;
import ncsa.hdf.object.FileFormat;
import ncsa.hdf.object.Group;
import ncsa.hdf.object.HObject;
import ncsa.hdf.object.ScalarDS;
import ncsa.hdf.view.ViewProperties.BITMASK_OP;
/**
* TableView displays an HDF dataset as a two-dimensional table.
*
* @author Peter X. Cao
* @version 2.4 9/6/2007
*/
public class DefaultTableView extends JInternalFrame implements TableView, ActionListener, MouseListener {
private static final long serialVersionUID = -7452459299532863847L;
/**
* The main HDFView.
*/
private final ViewManager viewer;
/**
* Numerical data type.
* B = byte array,
* S = short array,
* I = int array,
* J = long array,
* F = float array, and
* D = double array.
*/
private char NT = ' ';
/**
* The Scalar Dataset.
*/
private Dataset dataset;
/**
* The value of the dataset.
*/
private Object dataValue;
/**
* The table used to hold the table data.
*/
private JTable table;
/** Label to indicate the current cell location. */
private JLabel cellLabel;
/** Text field to display the value of of the current cell. */
private JTextArea cellValueField;
private boolean isValueChanged;
private final Toolkit toolkit;
private boolean isReadOnly;
private boolean isDisplayTypeChar;
private boolean isDataTransposed;
private boolean isRegRef;
private boolean isObjRef;
private final JCheckBoxMenuItem checkFixedDataLength;
private int fixedDataLength;
private final JCheckBoxMenuItem checkScientificNotation;
private final JCheckBoxMenuItem checkHex;
private final JCheckBoxMenuItem checkBin;
private final DecimalFormat scientificFormat = new DecimalFormat("###.#####E0#");
private final NumberFormat normalFormat = null; // NumberFormat.getInstance();
private NumberFormat numberFormat = normalFormat;
private boolean showAsHex = false, showAsBin = false;
private final boolean startEditing[] = { false };
private JPopupMenu popupMenu;
private enum ViewType {
TABLE, IMAGE, TEXT
}
private ViewType viewType;
private JTextField frameField;
private long curFrame = 0;
private long maxFrame = 1;
private Object fillValue = null;
private BitSet bitmask;
private BITMASK_OP bitmaskOP = BITMASK_OP.EXTRACT;
private int binaryOrder;
private int indexBase = 0;
private static final int FLOAT_BUFFER_SIZE = 524288;
private static final int INT_BUFFER_SIZE = 524288;
private static final int SHORT_BUFFER_SIZE = 1048576;
private static final int LONG_BUFFER_SIZE = 262144;
private static final int DOUBLE_BUFFER_SIZE = 262144;
private static final int BYTE_BUFFER_SIZE = 2097152;
/* the value of the current cell value in editing. */
private Object currentEditingCellValue = null;
/**
* Constructs an TableView.
*
*
* @param theView
* the main HDFView.
*/
public DefaultTableView(ViewManager theView) {
this(theView, null);
}
/**
* Constructs an TableView.
*
*
* @param theView
* the main HDFView.
* @param map
* the properties on how to show the data. The map is used to
* allow applications to pass properties on how to display the
* data, such as, transposing data, showing data as character,
* applying bitmask, and etc. Predefined keys are listed at
* ViewProperties.DATA_VIEW_KEY.
*/
public DefaultTableView(ViewManager theView, HashMap map) {
super();
setDefaultCloseOperation(JInternalFrame.DISPOSE_ON_CLOSE);
viewer = theView;
toolkit = Toolkit.getDefaultToolkit();
isValueChanged = false;
isReadOnly = false;
isRegRef = false;
isObjRef = false;
viewType = ViewType.TABLE;
fixedDataLength = -1;
HObject hobject = null;
popupMenu = null;
bitmask = null;
if (ViewProperties.isIndexBase1()) indexBase = 1;
checkFixedDataLength = new JCheckBoxMenuItem("Fixed Data Length", false);
checkScientificNotation = new JCheckBoxMenuItem("Show Scientific Notation", false);
checkHex = new JCheckBoxMenuItem("Show Hexadecimal", false);
checkBin = new JCheckBoxMenuItem("Show Binary", false);
if (map != null) {
hobject = (HObject) map.get(ViewProperties.DATA_VIEW_KEY.OBJECT);
bitmask = (BitSet) map.get(ViewProperties.DATA_VIEW_KEY.BITMASK);
bitmaskOP = (BITMASK_OP) map.get(ViewProperties.DATA_VIEW_KEY.BITMASKOP);
Boolean b = (Boolean) map.get(ViewProperties.DATA_VIEW_KEY.CHAR);
if (b != null) isDisplayTypeChar = b.booleanValue();
b = (Boolean) map.get(ViewProperties.DATA_VIEW_KEY.TRANSPOSED);
if (b != null) isDataTransposed = b.booleanValue();
b = (Boolean) map.get(ViewProperties.DATA_VIEW_KEY.INDEXBASE1);
if (b != null) {
if (b.booleanValue())
indexBase = 1;
else
indexBase = 0;
}
}
if (hobject == null) hobject = (HObject) viewer.getTreeView().getCurrentObject();
if ((hobject == null) || !(hobject instanceof Dataset)) {
return;
}
dataset = (Dataset) hobject;
isReadOnly = dataset.getFileFormat().isReadOnly();
long[] dims = dataset.getDims();
long tsize = 1;
for (int i = 0; i < dims.length; i++)
tsize *= dims[i];
if (dataset.getHeight() <= 0 || dataset.getWidth() <= 0 || tsize <= 0) return;
// cannot edit hdf4 vdata
if (dataset.getFileFormat().isThisType(FileFormat.getFileFormat(FileFormat.FILE_TYPE_HDF4))
&& (dataset instanceof CompoundDS)) {
isReadOnly = true;
}
// disable edit feature for szip compression when encode is not enabled
if (!isReadOnly) {
String compression = dataset.getCompression();
if ((compression != null) && compression.startsWith("SZIP")) {
if (!compression.endsWith("ENCODE_ENABLED")) {
isReadOnly = true;
}
}
}
Datatype dtype = dataset.getDatatype();
isDisplayTypeChar = (isDisplayTypeChar &&
(dtype.getDatatypeSize() == 1 ||
(dtype.getDatatypeClass() == Datatype.CLASS_ARRAY &&
dtype.getBasetype().getDatatypeClass() == Datatype.CLASS_CHAR)));
dataset.setEnumConverted(ViewProperties.isConvertEnum());
// create the table and its columnHeader
if (dataset instanceof CompoundDS) {
isDataTransposed = false; // disable transpose for compound dataset
this.setFrameIcon(ViewProperties.getTableIcon());
table = createTable((CompoundDS) dataset);
}
else { /* if (dataset instanceof ScalarDS) */
this.setFrameIcon(ViewProperties.getDatasetIcon());
table = createTable((ScalarDS) dataset);
if (dtype.getDatatypeClass() == Datatype.CLASS_REFERENCE) {
table.addMouseListener(this);
if (dtype.getDatatypeSize() > 8) {
isReadOnly = true;
isRegRef = true;
}
else
isObjRef = true;
}
}
if (table == null) {
viewer.showStatus("Creating table failed - " + dataset.getName());
dataset = null;
super.dispose();
return;
}
table.setName("data");
ColumnHeader columnHeaders = new ColumnHeader(table);
columnHeaders.setName("columnHeaders");
table.setTableHeader(columnHeaders);
table.setCellSelectionEnabled(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setGridColor(Color.gray);
// add the table to a scroller
JScrollPane scrollingTable = new JScrollPane(table);
scrollingTable.getVerticalScrollBar().setUnitIncrement(100);
scrollingTable.getHorizontalScrollBar().setUnitIncrement(100);
// create row headers and add it to the scroller
RowHeader rowHeaders = new RowHeader(table, dataset);
rowHeaders.setName("rowHeaders");
JViewport viewp = new JViewport();
viewp.add(rowHeaders);
viewp.setPreferredSize(rowHeaders.getPreferredSize());
scrollingTable.setRowHeader(viewp);
cellLabel = new JLabel("");
cellLabel.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
Dimension dim = cellLabel.getPreferredSize();
dim.width = 75;
cellLabel.setPreferredSize(dim);
cellLabel.setHorizontalAlignment(JLabel.RIGHT);
cellValueField = new JTextArea();
cellValueField.setLineWrap(true);
cellValueField.setWrapStyleWord(true);
cellValueField.setEditable(false);
cellValueField.setBackground(new Color(255, 255, 240));
JScrollPane scrollingcellValue = new JScrollPane(cellValueField);
scrollingcellValue.getVerticalScrollBar().setUnitIncrement(50);
scrollingcellValue.getHorizontalScrollBar().setUnitIncrement(50);
JPanel valuePane = new JPanel();
valuePane.setLayout(new BorderLayout());
valuePane.add(cellLabel, BorderLayout.WEST);
valuePane.add(scrollingcellValue, BorderLayout.CENTER);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, valuePane, scrollingTable);
splitPane.setDividerLocation(25);
JPanel contentPane = (JPanel) getContentPane();
contentPane.add(splitPane);
// set title
StringBuffer sb = new StringBuffer("TableView - ");
sb.append(hobject.getName());
sb.append(" - ");
sb.append(hobject.getPath());
sb.append(" - ");
sb.append(dataset.getFile());
setTitle(sb.toString());
// setup subset information
int rank = dataset.getRank();
int[] selectedIndex = dataset.getSelectedIndex();
long[] count = dataset.getSelectedDims();
long[] stride = dataset.getStride();
// long[] dims = dataset.getDims();
long[] start = dataset.getStartDims();
int n = Math.min(3, rank);
if (rank > 2) {
curFrame = start[selectedIndex[2]] + indexBase;
maxFrame = dims[selectedIndex[2]];
}
sb.append(" [ dims");
sb.append(selectedIndex[0]);
for (int i = 1; i < n; i++) {
sb.append("x");
sb.append(selectedIndex[i]);
}
sb.append(", start");
sb.append(start[selectedIndex[0]]);
for (int i = 1; i < n; i++) {
sb.append("x");
sb.append(start[selectedIndex[i]]);
}
sb.append(", count");
sb.append(count[selectedIndex[0]]);
for (int i = 1; i < n; i++) {
sb.append("x");
sb.append(count[selectedIndex[i]]);
}
sb.append(", stride");
sb.append(stride[selectedIndex[0]]);
for (int i = 1; i < n; i++) {
sb.append("x");
sb.append(stride[selectedIndex[i]]);
}
sb.append(" ] ");
setJMenuBar(createMenuBar());
viewer.showStatus(sb.toString());
// set cell height for large fonts
int cellRowHeight = table.getFontMetrics(table.getFont()).getHeight();
rowHeaders.setRowHeight(cellRowHeight);
table.setRowHeight(cellRowHeight);
// create popup menu for reg. ref.
if (isRegRef || isObjRef) popupMenu = createPopupMenu();
}
private JMenuBar createMenuBar() {
JMenuBar bar = new JMenuBar();
JButton button;
boolean isEditable = !isReadOnly;
boolean is3D = (dataset.getRank() > 2);
JMenu menu = new JMenu("Table", false);
menu.setMnemonic('T');
bar.add(menu);
JMenuItem item = new JMenuItem("Export Data to Text File");
item.addActionListener(this);
item.setActionCommand("Save table as text");
menu.add(item);
JMenu exportAsBinaryMenu = new JMenu("Export Data to Binary File");
if ((dataset instanceof ScalarDS)) {
menu.add(exportAsBinaryMenu);
}
item = new JMenuItem("Native Order");
item.addActionListener(this);
item.setActionCommand("Save table as binary Native Order");
exportAsBinaryMenu.add(item);
item = new JMenuItem("Little Endian");
item.addActionListener(this);
item.setActionCommand("Save table as binary Little Endian");
exportAsBinaryMenu.add(item);
item = new JMenuItem("Big Endian");
item.addActionListener(this);
item.setActionCommand("Save table as binary Big Endian");
exportAsBinaryMenu.add(item);
menu.addSeparator();
item = new JMenuItem("Import Data from Text File");
item.addActionListener(this);
item.setActionCommand("Import data from file");
item.setEnabled(isEditable);
menu.add(item);
item = checkFixedDataLength;
item.addActionListener(this);
item.setActionCommand("Fixed data length");
if (dataset instanceof ScalarDS) {
menu.add(item);
}
JMenu importFromBinaryMenu = new JMenu("Import Data from Binary File");
if ((dataset instanceof ScalarDS)) {
menu.add(importFromBinaryMenu);
}
item = new JMenuItem("Native Order");
item.addActionListener(this);
item.setActionCommand("Order as Native Order");
importFromBinaryMenu.add(item);
item = new JMenuItem("Little Endian");
item.addActionListener(this);
item.setActionCommand("Order as Little Endian");
importFromBinaryMenu.add(item);
item = new JMenuItem("Big Endian");
item.addActionListener(this);
item.setActionCommand("Order as Big Endian");
importFromBinaryMenu.add(item);
menu.addSeparator();
item = new JMenuItem("Copy");
item.addActionListener(this);
item.setActionCommand("Copy data");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, KeyEvent.CTRL_MASK, true));
menu.add(item);
item = new JMenuItem("Paste");
item.addActionListener(this);
item.setActionCommand("Paste data");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, KeyEvent.CTRL_MASK, true));
item.setEnabled(isEditable);
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Copy to New Dataset");
item.addActionListener(this);
item.setActionCommand("Write selection to dataset");
item.setEnabled(isEditable && (dataset instanceof ScalarDS));
menu.add(item);
item = new JMenuItem("Save Changes to File");
item.addActionListener(this);
item.setActionCommand("Save dataset");
item.setEnabled(isEditable);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_U, KeyEvent.CTRL_MASK, true));
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Select All");
item.addActionListener(this);
item.setActionCommand("Select all data");
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK, true));
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Show Lineplot");
item.addActionListener(this);
item.setActionCommand("Show chart");
menu.add(item);
item = new JMenuItem("Show Statistics");
item.addActionListener(this);
item.setActionCommand("Show statistics");
menu.add(item);
menu.addSeparator();
item = new JMenuItem("Math Conversion");
item.addActionListener(this);
item.setActionCommand("Math conversion");
item.setEnabled(isEditable);
menu.add(item);
menu.addSeparator();
item = checkScientificNotation;
item.addActionListener(this);
item.setActionCommand("Show scientific notation");
if (dataset instanceof ScalarDS) {
menu.add(item);
}
boolean isInt = (NT == 'B' || NT == 'S' || NT == 'I' || NT == 'J');
item = checkHex;
item.addActionListener(this);
item.setActionCommand("Show hexadecimal");
if ((dataset instanceof ScalarDS) && isInt) {
menu.add(item);
}
item = checkBin;
item.addActionListener(this);
item.setActionCommand("Show binary");
if ((dataset instanceof ScalarDS) && isInt) {
menu.add(item);
}
menu.addSeparator();
item = new JMenuItem("Close");
item.addActionListener(this);
item.setActionCommand("Close");
menu.add(item);
bar.add(new JLabel(" "));
// add icons to the menubar
Insets margin = new Insets(0, 2, 0, 2);
// chart button
button = new JButton(ViewProperties.getChartIcon());
bar.add(button);
button.setToolTipText("Line Plot");
button.setMargin(margin);
button.addActionListener(this);
button.setActionCommand("Show chart");
if (is3D) {
bar.add(new JLabel(" "));
// first button
button = new JButton(ViewProperties.getFirstIcon());
bar.add(button);
button.setToolTipText("First");
button.setMargin(margin);
button.addActionListener(this);
button.setActionCommand("First page");
// previous button
button = new JButton(ViewProperties.getPreviousIcon());
bar.add(button);
button.setToolTipText("Previous");
button.setMargin(margin);
button.addActionListener(this);
button.setActionCommand("Previous page");
frameField = new JTextField(String.valueOf(curFrame));
frameField.setMaximumSize(new Dimension(50, 30));
bar.add(frameField);
frameField.setMargin(margin);
frameField.addActionListener(this);
frameField.setActionCommand("Go to frame");
JLabel tmpField = new JLabel(String.valueOf(maxFrame), SwingConstants.CENTER);
tmpField.setMaximumSize(new Dimension(50, 30));
bar.add(tmpField);
// next button
button = new JButton(ViewProperties.getNextIcon());
bar.add(button);
button.setToolTipText("Next");
button.setMargin(margin);
button.addActionListener(this);
button.setActionCommand("Next page");
// last button
button = new JButton(ViewProperties.getLastIcon());
bar.add(button);
button.setToolTipText("Last");
button.setMargin(margin);
button.addActionListener(this);
button.setActionCommand("Last page");
}
return bar;
}
public void actionPerformed(ActionEvent e) {
try {
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
Object source = e.getSource();
String cmd = e.getActionCommand();
if (cmd.equals("Close")) {
dispose(); // terminate the application
}
else if (cmd.equals("Save table as text")) {
try {
saveAsText();
}
catch (Exception ex) {
toolkit.beep();
JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
}
}
else if (cmd.startsWith("Save table as binary")) {
if (cmd.equals("Save table as binary Native Order")) binaryOrder = 1;
if (cmd.equals("Save table as binary Little Endian")) binaryOrder = 2;
if (cmd.equals("Save table as binary Big Endian")) binaryOrder = 3;
try {
saveAsBinary();
}
catch (Exception ex) {
toolkit.beep();
JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
}
}
else if (cmd.equals("Copy data")) {
copyData();
}
else if (cmd.equals("Paste data")) {
pasteData();
}
else if (cmd.equals("Import data from file")) {
String currentDir = dataset.getFileFormat().getParent();
JFileChooser fchooser = new JFileChooser(currentDir);
fchooser.setFileFilter(DefaultFileFilter.getFileFilterText());
int returnVal = fchooser.showOpenDialog(this);
if (returnVal != JFileChooser.APPROVE_OPTION) {
return;
}
File choosedFile = fchooser.getSelectedFile();
if (choosedFile == null) {
return;
}
String txtFile = choosedFile.getAbsolutePath();
importTextData(txtFile);
}
else if (cmd.startsWith("Order as")) {
if (cmd.equals("Order as Native Order")) binaryOrder = 1;
if (cmd.equals("Order as Little Endian")) binaryOrder = 2;
if (cmd.equals("Order as Big Endian")) binaryOrder = 3;
importBinaryData();
}
else if (cmd.equals("Write selection to dataset")) {
JTable jtable = getTable();
if ((jtable.getSelectedColumnCount() <= 0) || (jtable.getSelectedRowCount() <= 0)) {
JOptionPane.showMessageDialog(this, "Select table cells to write.", "HDFView",
JOptionPane.INFORMATION_MESSAGE);
return;
}
TreeView treeView = viewer.getTreeView();
TreeNode node = viewer.getTreeView().findTreeNode(dataset);
Group pGroup = (Group) ((DefaultMutableTreeNode) node.getParent()).getUserObject();
TreeNode root = dataset.getFileFormat().getRootNode();
if (root == null) {
return;
}
Vector list = new Vector(dataset.getFileFormat().getNumberOfMembers() + 5);
DefaultMutableTreeNode theNode = null;
Enumeration local_enum = ((DefaultMutableTreeNode) root).depthFirstEnumeration();
while (local_enum.hasMoreElements()) {
theNode = (DefaultMutableTreeNode) local_enum.nextElement();
list.add(theNode.getUserObject());
}
NewDatasetDialog dialog = new NewDatasetDialog((JFrame) viewer, pGroup, list, this);
dialog.setVisible(true);
HObject obj = (HObject) dialog.getObject();
if (obj != null) {
Group pgroup = dialog.getParentGroup();
try {
treeView.addObject(obj, pgroup);
}
catch (Exception ex) {}
}
list.setSize(0);
}
else if (cmd.equals("Save dataset")) {
try {
updateValueInFile();
}
catch (Exception ex) {
toolkit.beep();
JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
}
}
else if (cmd.equals("Select all data")) {
try {
selectAll();
}
catch (Exception ex) {
toolkit.beep();
JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
}
}
else if (cmd.equals("Show chart")) {
showLineplot();
}
else if (cmd.equals("First page")) {
firstPage();
}
else if (cmd.equals("Previous page")) {
previousPage();
}
else if (cmd.equals("Next page")) {
nextPage();
}
else if (cmd.equals("Last page")) {
lastPage();
}
else if (cmd.equals("Show statistics")) {
try {
Object theData = null;
theData = getSelectedData();
if (dataset instanceof CompoundDS) {
int cols = table.getSelectedColumnCount();
if (cols != 1) {
JOptionPane.showMessageDialog(this,
"Please select one colunm a time for compound dataset.", getTitle(),
JOptionPane.ERROR_MESSAGE);
return;
}
}
else if (theData == null) {
theData = dataValue;
}
double[] minmax = new double[2];
double[] stat = new double[2];
Tools.findMinMax(theData, minmax, fillValue);
if (Tools.computeStatistics(theData, stat, fillValue) > 0) {
String statistics = "Min = " + minmax[0]
+ "\nMax = " + minmax[1]
+ "\nMean = " + stat[0]
+ "\nStandard deviation = " + stat[1];
JOptionPane.showMessageDialog(this, statistics, "Statistics", JOptionPane.INFORMATION_MESSAGE);
}
theData = null;
System.gc();
}
catch (Exception ex) {
toolkit.beep();
JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
}
}
else if (cmd.equals("Math conversion")) {
try {
mathConversion();
}
catch (Exception ex) {
toolkit.beep();
JOptionPane.showMessageDialog((JFrame) viewer, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
}
}
else if (cmd.startsWith("Go to frame")) {
int page = 0;
try {
page = Integer.parseInt(frameField.getText().trim()) - indexBase;
}
catch (Exception ex) {
page = -1;
}
gotoPage(page);
}
else if (cmd.equals("Show scientific notation")) {
if (checkScientificNotation.isSelected()) {
numberFormat = scientificFormat;
checkHex.setSelected(false);
checkBin.setSelected(false);
showAsHex = false;
showAsBin = false;
}
else
numberFormat = normalFormat;
this.updateUI();
}
else if (cmd.equals("Show hexadecimal")) {
showAsHex = checkHex.isSelected();
if (showAsHex) {
checkScientificNotation.setSelected(false);
checkBin.setSelected(false);
showAsBin = false;
numberFormat = normalFormat;
}
this.updateUI();
}
else if (cmd.equals("Show binary")) {
showAsBin = checkBin.isSelected();
if (showAsBin) {
checkScientificNotation.setSelected(false);
checkHex.setSelected(false);
showAsHex = false;
numberFormat = normalFormat;
}
this.updateUI();
}
else if (cmd.equals("Fixed data length")) {
if (!checkFixedDataLength.isSelected()) {
fixedDataLength = -1;
this.updateUI();
return;
}
String str = JOptionPane.showInputDialog(
this,
"Enter fixed data length when importing text data\n\n"
+ "For example, for a text string of \"12345678\"\n\t\tenter 2, the data will be 12, 34, 56, 78\n\t\tenter 4, the data will be 1234, 5678\n",
"");
if ((str == null) || (str.length() < 1)) {
checkFixedDataLength.setSelected(false);
return;
}
try {
fixedDataLength = Integer.parseInt(str);
}
catch (Exception ex) {
fixedDataLength = -1;
}
if (fixedDataLength < 1) {
checkFixedDataLength.setSelected(false);
return;
}
}
else if (cmd.startsWith("Show data as")) {
// show data pointed by reg. ref.
if (cmd.endsWith("table"))
viewType = ViewType.TABLE;
else if (cmd.endsWith("image"))
viewType = ViewType.IMAGE;
else
viewType = ViewType.TABLE;
Object theData = getSelectedData();
if (theData == null) {
toolkit.beep();
JOptionPane.showMessageDialog(this, "No data selected.", getTitle(), JOptionPane.ERROR_MESSAGE);
return;
}
int len = Array.getLength(theData);
for (int i = 0; i < len; i++) {
if (isRegRef)
showRegRefData((String) Array.get(theData, i));
else if (isObjRef) showObjRefData(Array.getLong(theData, i));
}
}
}
finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
}
// Implementing DataView.
public HObject getDataObject() {
return dataset;
}
public void dispose() {
if (isValueChanged && !isReadOnly) {
int op = JOptionPane.showConfirmDialog(this,
"\"" + dataset.getName() + "\" has changed.\n" + "Do you want to save the changes?",
getTitle(), JOptionPane.YES_NO_OPTION);
if (op == JOptionPane.YES_OPTION) {
updateValueInFile();
}
else
dataset.clearData(); // reload data
}
if (dataset instanceof ScalarDS) {
ScalarDS sds = (ScalarDS) dataset;
// reload the data when it is displayed next time
// because the display type (table or image) may be
// different.
if (sds.isImage()) {
sds.clearData();
}
dataValue = null;
table = null;
}
viewer.removeDataView(this);
super.dispose();
}
// Implementing DataObserver.
private void previousPage() {
int rank = dataset.getRank();
if (rank < 3) {
return;
}
long[] start = dataset.getStartDims();
long[] dims = dataset.getDims();
int[] selectedIndex = dataset.getSelectedIndex();
long idx = start[selectedIndex[2]];
if (idx == 0) {
return; // current page is the first page
}
gotoPage(start[selectedIndex[2]] - 1);
}
// Implementing DataObserver.
private void nextPage() {
int rank = dataset.getRank();
if (rank < 3) {
return;
}
long[] start = dataset.getStartDims();
int[] selectedIndex = dataset.getSelectedIndex();
long[] dims = dataset.getDims();
long idx = start[selectedIndex[2]];
if (idx == dims[selectedIndex[2]] - 1) {
return; // current page is the last page
}
gotoPage(start[selectedIndex[2]] + 1);
}
// Implementing DataObserver.
private void firstPage() {
int rank = dataset.getRank();
if (rank < 3) {
return;
}
long[] start = dataset.getStartDims();
int[] selectedIndex = dataset.getSelectedIndex();
long[] dims = dataset.getDims();
long idx = start[selectedIndex[2]];
if (idx == 0) {
return; // current page is the first page
}
gotoPage(0);
}
// Implementing DataObserver.
private void lastPage() {
int rank = dataset.getRank();
if (rank < 3) {
return;
}
long[] start = dataset.getStartDims();
int[] selectedIndex = dataset.getSelectedIndex();
long[] dims = dataset.getDims();
long idx = start[selectedIndex[2]];
if (idx == dims[selectedIndex[2]] - 1) {
return; // current page is the last page
}
gotoPage(dims[selectedIndex[2]] - 1);
}
// Implementing TableObserver.
public JTable getTable() {
return table;
}
// Implementing TableObserver.
private void showLineplot() {
int[] rows = table.getSelectedRows();
int[] cols = table.getSelectedColumns();
if ((rows == null) || (cols == null) || (rows.length <= 0) || (cols.length <= 0)) {
toolkit.beep();
JOptionPane.showMessageDialog(this, "Select rows/columns to draw line plot.", getTitle(),
JOptionPane.ERROR_MESSAGE);
return;
}
int nrow = table.getRowCount();
int ncol = table.getColumnCount();
LineplotOption lpo = new LineplotOption((JFrame) viewer,
"Line Plot Options -- " + dataset.getName(),
nrow, ncol);
lpo.setVisible(true);
int plotType = lpo.getPlotBy();
if (plotType == LineplotOption.NO_PLOT) {
return;
}
boolean isRowPlot = (plotType == LineplotOption.ROW_PLOT);
int xIndex = lpo.getXindex();
// figure out to plot data by row or by column
// Plot data by rows if all columns are selected and part of
// rows are selected, otherwise plot data by column
double[][] data = null;
int nLines = 0;
String title = "Lineplot - " + dataset.getPath() + dataset.getName();
String[] lineLabels = null;
double[] yRange = { Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY };
double xData[] = null;
if (isRowPlot) {
title += " - by row";
nLines = rows.length;
if (nLines > 10) {
toolkit.beep();
nLines = 10;
JOptionPane.showMessageDialog(this,
"More than 10 rows are selected.\n" + "The first 10 rows will be displayed.",
getTitle(), JOptionPane.WARNING_MESSAGE);
}
lineLabels = new String[nLines];
data = new double[nLines][cols.length];
double value = 0.0;
for (int i = 0; i < nLines; i++) {
lineLabels[i] = String.valueOf(rows[i]);
for (int j = 0; j < cols.length; j++) {
data[i][j] = 0;
try {
value = Double.parseDouble(table.getValueAt(rows[i], cols[j]).toString());
data[i][j] = value;
yRange[0] = Math.min(yRange[0], value);
yRange[1] = Math.max(yRange[1], value);
}
catch (NumberFormatException ex) {}
} // for (int j = 0; j < ncols; j++)
} // for (int i = 0; i < rows.length; i++)
if (xIndex >= 0) {
xData = new double[cols.length];
for (int j = 0; j < cols.length; j++) {
xData[j] = 0;
try {
value = Double.parseDouble(table.getValueAt(xIndex, cols[j]).toString());
xData[j] = value;
}
catch (NumberFormatException ex) {}
}
}
} // if (isRowPlot)
else {
title += " - by column";
nLines = cols.length;
if (nLines > 10) {
toolkit.beep();
nLines = 10;
JOptionPane.showMessageDialog(this, "More than 10 columns are selected.\n"
+ "The first 10 columns will be displayed.", getTitle(), JOptionPane.WARNING_MESSAGE);
}
lineLabels = new String[nLines];
data = new double[nLines][rows.length];
double value = 0.0;
for (int j = 0; j < nLines; j++) {
lineLabels[j] = table.getColumnName(cols[j]);
for (int i = 0; i < rows.length; i++) {
data[j][i] = 0;
try {
value = Double.parseDouble(table.getValueAt(rows[i], cols[j]).toString());
data[j][i] = value;
yRange[0] = Math.min(yRange[0], value);
yRange[1] = Math.max(yRange[1], value);
}
catch (NumberFormatException ex) {}
} // for (int j=0; j= 0) {
xData = new double[rows.length];
for (int j = 0; j < rows.length; j++) {
xData[j] = 0;
try {
value = Double.parseDouble(table.getValueAt(rows[j], xIndex).toString());
xData[j] = value;
}
catch (NumberFormatException ex) {}
}
}
} // else
int n = removeInvalidPlotData(data, xData, yRange);
if (n < data[0].length) {
double[][] dataNew = new double[data.length][n];
for (int i = 0; i < data.length; i++)
System.arraycopy(data[i], 0, dataNew[i], 0, n);
data = dataNew;
if (xData != null) {
double[] xDataNew = new double[n];
System.arraycopy(xData, 0, xDataNew, 0, n);
xData = xDataNew;
}
}
// allow to draw a flat line: all values are the same
if (yRange[0] == yRange[1]) {
yRange[1] += 1;
yRange[0] -= 1;
}
else if (yRange[0] > yRange[1]) {
toolkit.beep();
JOptionPane.showMessageDialog(this,
"Cannot show line plot for the selected data. \n"
+ "Please check the data range: (" + yRange[0] + ", " + yRange[1] + ").",
getTitle(), JOptionPane.ERROR_MESSAGE);
data = null;
return;
}
Chart cv = new Chart((JFrame) viewer, title, Chart.LINEPLOT, data, xData, yRange);
cv.setLineLabels(lineLabels);
String cname = dataValue.getClass().getName();
char dname = cname.charAt(cname.lastIndexOf("[") + 1);
if ((dname == 'B') || (dname == 'S') || (dname == 'I') || (dname == 'J')) {
cv.setTypeToInteger();
}
cv.setVisible(true);
}
/**
* Remove values of NaN, INF from the array.
*
* @param data
* the data array
* @param xData
* the x-axis data points
* @param yRange
* the range of data values
* @return number of data points in the plot data if successful; otherwise,
* returns false.
*/
private int removeInvalidPlotData(double[][] data, double[] xData, double[] yRange) {
int idx = 0;
boolean hasInvalid = false;
if (data == null || yRange == null) return -1;
yRange[0] = Double.POSITIVE_INFINITY;
yRange[1] = Double.NEGATIVE_INFINITY;
for (int i = 0; i < data[0].length; i++) {
hasInvalid = false;
for (int j = 0; j < data.length; j++) {
hasInvalid = Tools.isNaNINF(data[j][i]);
if (xData != null) hasInvalid = hasInvalid || Tools.isNaNINF(xData[i]);
if (hasInvalid)
break;
else {
data[j][idx] = data[j][i];
if (xData != null) xData[idx] = xData[i];
yRange[0] = Math.min(yRange[0], data[j][idx]);
yRange[1] = Math.max(yRange[1], data[j][idx]);
}
}
if (!hasInvalid) idx++;
}
return idx;
}
/**
* Returns the selected data values.
*/
public Object getSelectedData() {
if (dataset instanceof CompoundDS) {
return getSelectedCompoundData();
}
else {
return getSelectedScalarData();
}
}
/**
* Returns the selected data values.
*/
private Object getSelectedScalarData() {
Object selectedData = null;
int[] selectedRows = table.getSelectedRows();
int[] selectedCols = table.getSelectedColumns();
if (selectedRows == null || selectedRows.length <= 0 || selectedCols == null || selectedCols.length <= 0) {
return null;
}
int size = selectedCols.length * selectedRows.length;
// the whole table is selected
if ((table.getColumnCount() == selectedCols.length) && (table.getRowCount() == selectedRows.length)) {
return dataValue;
}
selectedData = null;
if (isRegRef) {
// reg. ref data are stored in strings
selectedData = new String[size];
}
else {
switch (NT) {
case 'B':
selectedData = new byte[size];
break;
case 'S':
selectedData = new short[size];
break;
case 'I':
selectedData = new int[size];
break;
case 'J':
selectedData = new long[size];
break;
case 'F':
selectedData = new float[size];
break;
case 'D':
selectedData = new double[size];
break;
default:
selectedData = null;
break;
}
}
if (selectedData == null) {
toolkit.beep();
JOptionPane.showMessageDialog(this, "Unsupported data type.", getTitle(), JOptionPane.ERROR_MESSAGE);
return null;
}
int r0 = table.getSelectedRow();
int c0 = table.getSelectedColumn();
int w = table.getColumnCount();
int idx_src = 0;
int idx_dst = 0;
for (int i = 0; i < selectedRows.length; i++) {
for (int j = 0; j < selectedCols.length; j++) {
idx_src = selectedRows[i] * w + selectedCols[j];
Array.set(selectedData, idx_dst, Array.get(dataValue, idx_src));
idx_dst++;
}
}
// this only works for continuous cells
// for (int i = 0; i < rows; i++) {
// idx_src = (r0 + i) * w + c0;
// System.arraycopy(dataValue, idx_src, selectedData, idx_dst, cols);
// idx_dst += cols;
// }
return selectedData;
}
/**
* Returns the selected data values.
*/
private Object getSelectedCompoundData() {
Object selectedData = null;
int cols = table.getSelectedColumnCount();
int rows = table.getSelectedRowCount();
if ((cols <= 0) || (rows <= 0)) {
toolkit.beep();
JOptionPane.showMessageDialog(this, "No data is selected.", getTitle(), JOptionPane.ERROR_MESSAGE);
return null;
}
Object colData = null;
try {
colData = ((List) dataset.getData()).get(table.getSelectedColumn());
}
catch (Exception ex) {
return null;
}
int size = Array.getLength(colData);
String cName = colData.getClass().getName();
int cIndex = cName.lastIndexOf("[");
char nt = ' ';
if (cIndex >= 0) {
nt = cName.charAt(cIndex + 1);
}
if (nt == 'B') {
selectedData = new byte[size];
}
else if (nt == 'S') {
selectedData = new short[size];
}
else if (nt == 'I') {
selectedData = new int[size];
}
else if (nt == 'J') {
selectedData = new long[size];
}
else if (nt == 'F') {
selectedData = new float[size];
}
else if (nt == 'D') {
selectedData = new double[size];
}
else {
toolkit.beep();
JOptionPane.showMessageDialog(this, "Unsupported data type.", getTitle(), JOptionPane.ERROR_MESSAGE);
return null;
}
System.arraycopy(colData, 0, selectedData, 0, size);
return selectedData;
}
/**
* Creates a JTable to hold a scalar dataset.
*/
private JTable createTable(ScalarDS d) {
JTable theTable = null;
int rows = 0;
int cols = 0;
int rank = d.getRank();
if (rank <= 0) {
try {
d.init();
}
catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex, "createTable:" + getTitle(), JOptionPane.ERROR_MESSAGE);
dataValue = null;
return null;
}
rank = d.getRank();
}
long[] dims = d.getSelectedDims();
rows = (int) dims[0];
cols = 1;
if (rank > 1) {
rows = d.getHeight();
cols = d.getWidth();
}
dataValue = null;
try {
dataValue = d.getData();
if (dataValue == null) {
JOptionPane.showMessageDialog(this, "No data read", "ScalarDS createTable:" + getTitle(),
JOptionPane.WARNING_MESSAGE);
return null;
}
if (Tools.applyBitmask(dataValue, bitmask, bitmaskOP)) {
isReadOnly = true;
String opName = "Extract bits ";
if (bitmaskOP == ViewProperties.BITMASK_OP.AND) opName = "Apply bitwise AND ";
Border border = BorderFactory.createCompoundBorder(
BorderFactory.createRaisedBevelBorder(),
BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLUE, 1), opName
+ bitmask, TitledBorder.RIGHT, TitledBorder.TOP, this.getFont(), Color.RED));
this.setBorder(border);
}
d.convertFromUnsignedC();
dataValue = d.getData();
if (Array.getLength(dataValue) <= rows) cols = 1;
}
catch (Throwable ex) {
JOptionPane.showMessageDialog(this, ex, "ScalarDS createTable:" + getTitle(), JOptionPane.ERROR_MESSAGE);
dataValue = null;
}
if (dataValue == null) {
return null;
}
fillValue = d.getFillValue();
boolean isUnsigned = d.isUnsigned();
String cName = dataValue.getClass().getName();
int cIndex = cName.lastIndexOf("[");
if (cIndex >= 0) {
NT = cName.charAt(cIndex + 1);
}
boolean isVL = cName.startsWith("[Ljava.lang.String;");
// convert numerical data into char
// only possible cases are byte[] and short[] (converted from unsigned
// byte)
if (isDisplayTypeChar && ((NT == 'B') || (NT == 'S'))) {
int n = Array.getLength(dataValue);
char[] charData = new char[n];
for (int i = 0; i < n; i++) {
if (NT == 'B') {
charData[i] = (char) Array.getByte(dataValue, i);
}
else if (NT == 'S') {
charData[i] = (char) Array.getShort(dataValue, i);
}
}
dataValue = charData;
}
else if ((NT == 'B') && dataset.getDatatype().getDatatypeClass() == Datatype.CLASS_ARRAY) {
Datatype baseType = dataset.getDatatype().getBasetype();
if (baseType.getDatatypeClass() == Datatype.CLASS_STRING) {
dataValue = Dataset.byteToString((byte[]) dataValue, baseType.getDatatypeSize());
}
}
final String columnNames[] = new String[cols];
final int rowCount = rows;
final int colCount = cols;
final long[] startArray = dataset.getStartDims();
final long[] strideArray = dataset.getStride();
int[] selectedIndex = dataset.getSelectedIndex();
final int rowStart = (int) startArray[selectedIndex[0]];
final int rowStride = (int) strideArray[selectedIndex[0]];
int start = 0;
int stride = 1;
if (rank > 1) {
start = (int) startArray[selectedIndex[1]];
stride = (int) strideArray[selectedIndex[1]];
}
for (int i = 0; i < cols; i++) {
columnNames[i] = String.valueOf(start + indexBase + i * stride);
}
AbstractTableModel tm = new AbstractTableModel() {
private static final long serialVersionUID = 254175303655079056L;
private final StringBuffer stringBuffer = new StringBuffer();
private final Datatype dtype = dataset.getDatatype();
private final Datatype btype = dtype.getBasetype();
private final int typeSize = dtype.getDatatypeSize();
private final boolean isArray = (dtype.getDatatypeClass() == Datatype.CLASS_ARRAY);
private final boolean isStr = (NT == 'L');
private final boolean isInt = (NT == 'B' || NT == 'S' || NT == 'I' || NT == 'J');
private final boolean isUINT64 = (dtype.isUnsigned() && (NT == 'J'));
private Object theValue;
boolean isNaturalOrder = (dataset.getRank()==1 ||
(dataset.getSelectedIndex()[0] < dataset.getSelectedIndex()[1]));
public int getColumnCount() {
return columnNames.length;
}
public int getRowCount() {
return rowCount;
}
public String getColumnName(int col) {
return columnNames[col];
}
public Object getValueAt(int row, int column) {
if (startEditing[0]) return "";
if (isArray) {
// ARRAY dataset
int arraySize = dtype.getDatatypeSize() / btype.getDatatypeSize();
stringBuffer.setLength(0); // clear the old string
int i0 = (row * colCount + column) * arraySize;
int i1 = i0 + arraySize;
if (isDisplayTypeChar) {
for (int i = i0; i < i1; i++) {
stringBuffer.append(Array.getChar(dataValue, i));
if (stringBuffer.length() > 0 && i < (i1 - 1)) stringBuffer.append(", ");
}
}
else {
if (isUINT64) {
for (int i = i0; i < i1; i++) {
Long l = (Long) Array.get(dataValue, i);
if (l < 0) {
l = (l << 1) >>> 1;
BigInteger big1 = new BigInteger("9223372036854775808"); // 2^65
BigInteger big2 = new BigInteger(l.toString());
BigInteger big = big1.add(big2);
stringBuffer.append(big.toString());
}
else
stringBuffer.append(Array.get(dataValue, i));
if (stringBuffer.length() > 0 && i < (i1 - 1)) stringBuffer.append(", ");
}
}
else {
for (int i = i0; i < i1; i++) {
stringBuffer.append(Array.get(dataValue, i));
if (stringBuffer.length() > 0 && i < (i1 - 1)) stringBuffer.append(", ");
}
}
}
theValue = stringBuffer;
}
else {
int index = column * rowCount + row;
if (dataset.getRank() > 1) {
if ((isDataTransposed && isNaturalOrder) || (!isDataTransposed && !isNaturalOrder))
index = column * rowCount + row;
else
index = row * colCount + column;
}
theValue = Array.get(dataValue, index);
if (isStr) return theValue;
if (isUINT64) {
Long l = (Long) theValue;
if (l < 0) {
l = (l << 1) >>> 1;
BigInteger big1 = new BigInteger("9223372036854775808"); // 2^65
BigInteger big2 = new BigInteger(l.toString());
BigInteger big = big1.add(big2);
theValue = big.toString();
}
}
else if (showAsHex && isInt) {
// show in Hexadecimal
theValue = Long.toHexString(Long.valueOf(theValue.toString()));
}
else if (showAsBin && isInt) {
theValue = Tools.toBinaryString(Long.valueOf(theValue.toString()), typeSize);
// theValue =
// Long.toBinaryString(Long.valueOf(theValue.toString()));
}
else if (numberFormat != null) {
// show in scientific format
theValue = numberFormat.format(theValue);
}
}
return theValue;
} // getValueAt(int row, int column)
};
theTable = new JTable(tm) {
private static final long serialVersionUID = -145476220959400488L;
private final Datatype dtype = dataset.getDatatype();
private final boolean isArray = (dtype.getDatatypeClass() == Datatype.CLASS_ARRAY);
public boolean isCellEditable(int row, int col) {
if (isReadOnly || isDisplayTypeChar || isArray || showAsBin || showAsHex) {
return false;
}
else {
return true;
}
}
public boolean editCellAt(int row, int column, java.util.EventObject e) {
if (!isCellEditable(row, column)) {
return super.editCellAt(row, column, e);
}
if (e instanceof KeyEvent) {
KeyEvent ke = (KeyEvent) e;
if (ke.getID() == KeyEvent.KEY_PRESSED) {
startEditing[0] = true;
}
}
else if (e instanceof MouseEvent) {
MouseEvent me = (MouseEvent) e;
int mc = me.getClickCount();
if (mc > 1) {
currentEditingCellValue = getValueAt(row, column);
}
}
return super.editCellAt(row, column, e);
}
public void editingStopped(ChangeEvent e) {
int row = getEditingRow();
int col = getEditingColumn();
super.editingStopped(e);
startEditing[0] = false;
Object source = e.getSource();
if (source instanceof CellEditor) {
CellEditor editor = (CellEditor) source;
String cellValue = (String) editor.getCellEditorValue();
try {
updateValueInMemory(cellValue, row, col);
}
catch (Exception ex) {
toolkit.beep();
JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
}
} // if (source instanceof CellEditor)
}
public boolean isCellSelected(int row, int column) {
if ((getSelectedRow() == row) && (getSelectedColumn() == column)) {
cellLabel.setText(String.valueOf(rowStart + indexBase + row * rowStride) + ", "
+ table.getColumnName(column) + " = ");
Object val = getValueAt(row, column);
String strVal = null;
if (isRegRef) {
String reg = (String) val;
String oidStr = reg.substring(reg.indexOf(':') + 1, reg.indexOf(' '));
long oid[] = { -1 };
// decode object ID
try {
oid[0] = Long.valueOf(oidStr);
HObject obj = FileFormat.findObject(dataset.getFileFormat(), oid);
strVal = obj.getFullName() + " " + reg.substring(reg.indexOf("{"));
}
catch (Exception ex) {
strVal = null;
}
}
else if (isObjRef) {
Long ref = (Long) val;
long oid[] = { ref.longValue() };
// decode object ID
try {
HObject obj = FileFormat.findObject(dataset.getFileFormat(), oid);
strVal = obj.getFullName();
}
catch (Exception ex) {
strVal = null;
}
}
if (strVal == null && val != null) strVal = val.toString();
cellValueField.setText(strVal);
}
return super.isCellSelected(row, column);
}
};
theTable.setName("ScalarDS");
return theTable;
}
/**
* Creates a JTable to hold a compound dataset.
*/
private JTable createTable(CompoundDS d) {
JTable theTable = null;
int rank = d.getRank();
if (rank <= 0) {
d.init();
}
long[] startArray = d.getStartDims();
long[] strideArray = d.getStride();
int[] selectedIndex = d.getSelectedIndex();
final int rowStart = (int) startArray[selectedIndex[0]];
final int rowStride = (int) strideArray[selectedIndex[0]];
// use lazy convert for large number of strings
if (d.getHeight() > 10000) {
d.setConvertByteToString(false);
}
dataValue = null;
try {
dataValue = d.getData();
}
catch (Throwable ex) {
toolkit.beep();
JOptionPane.showMessageDialog(this, ex, "TableView" + getTitle(), JOptionPane.ERROR_MESSAGE);
dataValue = null;
}
if ((dataValue == null) || !(dataValue instanceof List)) {
return null;
}
final int rows = d.getHeight();
int cols = d.getSelectedMemberCount();
String[] columnNames = new String[cols];
int idx = 0;
String[] columnNamesAll = d.getMemberNames();
for (int i = 0; i < columnNamesAll.length; i++) {
if (d.isMemberSelected(i)) {
columnNames[idx] = columnNamesAll[i];
columnNames[idx] = columnNames[idx].replaceAll(CompoundDS.separator, "->");
idx++;
}
}
String[] subColumnNames = columnNames;
int columns = d.getWidth();
if (columns > 1) {
// multi-dimension compound dataset
subColumnNames = new String[columns * columnNames.length];
int halfIdx = columnNames.length / 2;
for (int i = 0; i < columns; i++) {
for (int j = 0; j < columnNames.length; j++) {
// display column index only once, in the middle of the
// compound fields
if (j == halfIdx) {
subColumnNames[i * columnNames.length + j] = (i + 1) + "\n " + columnNames[j];
}
else {
subColumnNames[i * columnNames.length + j] = " \n " + columnNames[j];
}
}
}
}
final String[] allColumnNames = subColumnNames;
AbstractTableModel tm = new AbstractTableModel() {
private static final long serialVersionUID = -2176296469630678304L;
CompoundDS compound = (CompoundDS) dataset;
int orders[] = compound.getSelectedMemberOrders();
Datatype types[] = compound.getSelectedMemberTypes();
StringBuffer stringBuffer = new StringBuffer();
int nFields = ((List) dataValue).size();
int nRows = getRowCount();
int nSubColumns = (nFields > 0) ? getColumnCount() / nFields : 0;
public int getColumnCount() {
return allColumnNames.length;
}
public int getRowCount() {
return rows;
}
public String getColumnName(int col) {
return allColumnNames[col];
}
public Object getValueAt(int row, int col) {
if (startEditing[0]) return "";
int fieldIdx = col;
int rowIdx = row;
if (nSubColumns > 1) { // multi-dimension compound dataset
int colIdx = col / nFields;
fieldIdx = col - colIdx * nFields;
// BUG 573: rowIdx = row * orders[fieldIdx] + colIdx * nRows
// * orders[fieldIdx];
rowIdx = row * orders[fieldIdx] * nSubColumns + colIdx * orders[fieldIdx];
;
}
else {
rowIdx = row * orders[fieldIdx];
}
Object colValue = ((List) dataValue).get(fieldIdx);
if (colValue == null) {
return "Null";
}
stringBuffer.setLength(0); // clear the old string
boolean isString = (types[fieldIdx].getDatatypeClass() == Datatype.CLASS_STRING);
if (isString && (colValue instanceof byte[])) {
// strings
int strlen = types[fieldIdx].getDatatypeSize();
String str = new String(((byte[]) colValue), rowIdx * strlen, strlen);
int idx = str.indexOf('\0');
if (idx > 0) {
str = str.substring(0, idx);
}
stringBuffer.append(str.trim());
}
else {
// numerical values
Datatype dtype = types[fieldIdx];
if (dtype.getDatatypeClass() == Datatype.CLASS_ARRAY) dtype = types[fieldIdx].getBasetype();
boolean isUINT64 = false;
if (dtype.isUnsigned()) {
String cName = colValue.getClass().getName();
int cIndex = cName.lastIndexOf("[");
if (cIndex >= 0) {
isUINT64 = (cName.charAt(cIndex + 1) == 'J');
}
}
for (int i = 0; i < orders[fieldIdx]; i++) {
Object theValue = Array.get(colValue, rowIdx + i);
if (isUINT64) {
Long l = (Long) theValue;
if (l < 0) {
l = (l << 1) >>> 1;
BigInteger big1 = new BigInteger("9223372036854775808"); // 2^65
BigInteger big2 = new BigInteger(l.toString());
BigInteger big = big1.add(big2);
theValue = big.toString();
}
}
if (i > 0) stringBuffer.append(", ");
stringBuffer.append(theValue);
}
} // end of else {
return stringBuffer;
}
};
theTable = new JTable(tm) {
private static final long serialVersionUID = 3221288637329958074L;
int lastSelectedRow = -1;
int lastSelectedColumn = -1;
public boolean isCellEditable(int row, int column) {
return !isReadOnly;
}
public boolean editCellAt(int row, int column, java.util.EventObject e) {
if (!isCellEditable(row, column)) {
return super.editCellAt(row, column, e);
}
if (e instanceof KeyEvent) {
KeyEvent ke = (KeyEvent) e;
if (ke.getID() == KeyEvent.KEY_PRESSED) startEditing[0] = true;
}
else if (e instanceof MouseEvent) {
MouseEvent me = (MouseEvent) e;
int mc = me.getClickCount();
if (mc > 1) {
currentEditingCellValue = getValueAt(row, column);
}
}
return super.editCellAt(row, column, e);
}
public void editingStopped(ChangeEvent e) {
int row = getEditingRow();
int col = getEditingColumn();
super.editingStopped(e);
startEditing[0] = false;
Object source = e.getSource();
if (source instanceof CellEditor) {
CellEditor editor = (CellEditor) source;
String cellValue = (String) editor.getCellEditorValue();
try {
updateValueInMemory(cellValue, row, col);
}
catch (Exception ex) {
toolkit.beep();
JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
}
} // if (source instanceof CellEditor)
}
public boolean isCellSelected(int row, int column) {
if ((lastSelectedRow == row) && (lastSelectedColumn == column)) {
return super.isCellSelected(row, column);
}
lastSelectedRow = row;
lastSelectedColumn = column;
if ((getSelectedRow() == row) && (getSelectedColumn() == column)) {
cellLabel.setText(String.valueOf(rowStart + indexBase + row * rowStride) + ", "
+ table.getColumnName(column) + " = ");
cellValueField.setText(getValueAt(row, column).toString());
}
return super.isCellSelected(row, column);
}
};
if (columns > 1) {
// multi-dimension compound dataset
MultiLineHeaderRenderer renderer = new MultiLineHeaderRenderer(columns, columnNames.length);
Enumeration local_enum = theTable.getColumnModel().getColumns();
while (local_enum.hasMoreElements()) {
((TableColumn) local_enum.nextElement()).setHeaderRenderer(renderer);
}
}
theTable.setName("CompoundDS");
return theTable;
} /* createTable */
private void gotoPage(long idx) {
if (dataset.getRank() < 3 || idx == (curFrame - indexBase)) {
return;
}
if (isValueChanged) {
updateValueInFile();
}
long[] start = dataset.getStartDims();
int[] selectedIndex = dataset.getSelectedIndex();
long[] dims = dataset.getDims();
if ((idx < 0) || (idx >= dims[selectedIndex[2]])) {
toolkit.beep();
JOptionPane.showMessageDialog(this,
"Frame number must be between" + indexBase + " and "
+ (dims[selectedIndex[2]] - 1 + indexBase),
getTitle(), JOptionPane.ERROR_MESSAGE);
return;
}
start[selectedIndex[2]] = idx;
curFrame = idx + indexBase;
dataset.clearData();
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
dataValue = dataset.getData();
if (dataset instanceof ScalarDS) {
((ScalarDS) dataset).convertFromUnsignedC();
dataValue = dataset.getData();
}
}
catch (Exception ex) {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
dataValue = null;
JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
return;
}
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
frameField.setText(String.valueOf(curFrame));
updateUI();
}
/** copy data from the spreadsheet to the system clipboard. */
private void copyData() {
StringBuffer sb = new StringBuffer();
int r0 = table.getSelectedRow(); // starting row
int c0 = table.getSelectedColumn(); // starting column
if ((r0 < 0) || (c0 < 0)) {
return;
}
int nr = table.getSelectedRowCount();
int nc = table.getSelectedColumnCount();
int r1 = r0 + nr; // finish row
int c1 = c0 + nc; // finishing column
try {
for (int i = r0; i < r1; i++) {
sb.append(table.getValueAt(i, c0).toString());
for (int j = c0 + 1; j < c1; j++) {
sb.append("\t");
sb.append(table.getValueAt(i, j).toString());
}
sb.append("\n");
}
}
catch (java.lang.OutOfMemoryError err) {
toolkit.beep();
JOptionPane
.showMessageDialog(
(JFrame) viewer,
"Copying data to system clipboard failed. \nUsing \"export/import data\" for copying/pasting large data.",
getTitle(), JOptionPane.ERROR_MESSAGE);
return;
}
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
StringSelection contents = new StringSelection(sb.toString());
cb.setContents(contents, null);
}
/** paste data from the system clipboard to the spreadsheet. */
private void pasteData() {
int pasteDataFlag = JOptionPane.showConfirmDialog(this, "Do you want to paste selected data ?",
this.getTitle(), JOptionPane.YES_NO_OPTION);
if (pasteDataFlag == JOptionPane.NO_OPTION) {
return;
}
int cols = table.getColumnCount();
int rows = table.getRowCount();
int r0 = table.getSelectedRow();
int c0 = table.getSelectedColumn();
if (c0 < 0) {
c0 = 0;
}
if (r0 < 0) {
r0 = 0;
}
int r = r0;
int c = c0;
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
// Transferable content = cb.getContents(this);
String line = "";
try {
String s = (String) cb.getData(DataFlavor.stringFlavor);
StringTokenizer st = new StringTokenizer(s, "\n");
// read line by line
while (st.hasMoreTokens() && (r < rows)) {
line = st.nextToken();
if (fixedDataLength < 1) {
// separate by delimiter
StringTokenizer lt = new StringTokenizer(line, "\t");
while (lt.hasMoreTokens() && (c < cols)) {
try {
updateValueInMemory(lt.nextToken(), r, c);
}
catch (Exception ex) {
continue;
}
c++;
}
r = r + 1;
c = c0;
}
else {
// the data has fixed length
int n = line.length();
String theVal;
for (int i = 0; i < n; i = i + fixedDataLength) {
try {
theVal = line.substring(i, i + fixedDataLength);
updateValueInMemory(theVal, r, c);
}
catch (Exception ex) {
continue;
}
c++;
}
}
}
}
catch (Throwable ex) {
toolkit.beep();
JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
}
table.updateUI();
}
/**
* import data values from text file.
*/
private void importTextData(String fname) {
int pasteDataFlag = JOptionPane.showConfirmDialog(this,
"Do you want to paste selected data ?",
this.getTitle(), JOptionPane.YES_NO_OPTION);
if (pasteDataFlag == JOptionPane.NO_OPTION) {
return;
}
int cols = table.getColumnCount();
int rows = table.getRowCount();
int r0 = table.getSelectedRow();
int c0 = table.getSelectedColumn();
if (c0 < 0) {
c0 = 0;
}
if (r0 < 0) {
r0 = 0;
}
// start at the first column for compound datasets
if (dataset instanceof CompoundDS) c0 = 0;
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(fname));
}
catch (FileNotFoundException ex) {
return;
}
String line = null;
StringTokenizer tokenizer1 = null;
try {
line = in.readLine();
}
catch (IOException ex) {
try {
in.close();
}
catch (IOException ex2) {}
return;
}
String delName = ViewProperties.getDataDelimiter();
String delimiter = "";
// delimiter must include a tab to be consistent with copy/paste for
// compound fields
if (dataset instanceof CompoundDS)
delimiter = "\t";
else {
if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_TAB)) {
delimiter = "\t";
}
else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_SPACE)) {
delimiter = " " + delimiter;
}
else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_COMMA)) {
delimiter = ",";
}
else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_COLON)) {
delimiter = ":";
}
else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_SEMI_COLON)) {
delimiter = ";";
}
}
String token = null;
int r = r0;
int c = c0;
while ((line != null) && (r < rows)) {
if (fixedDataLength > 0) {
// the data has fixed length
int n = line.length();
String theVal;
for (int i = 0; i < n; i = i + fixedDataLength) {
try {
theVal = line.substring(i, i + fixedDataLength);
updateValueInMemory(theVal, r, c);
}
catch (Exception ex) {
continue;
}
c++;
}
}
else {
try {
tokenizer1 = new StringTokenizer(line, delimiter);
while (tokenizer1.hasMoreTokens() && (c < cols)) {
token = tokenizer1.nextToken();
if (dataset instanceof ScalarDS) {
StringTokenizer tokenizer2 = new StringTokenizer(token);
while (tokenizer2.hasMoreTokens() && (c < cols)) {
updateValueInMemory(tokenizer2.nextToken(), r, c);
c++;
}
}
else {
updateValueInMemory(token, r, c);
c++;
}
} // while (tokenizer1.hasMoreTokens() && index < size)
}
catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
try {
in.close();
}
catch (IOException ex2) {}
return;
}
}
try {
line = in.readLine();
}
catch (IOException ex) {
line = null;
}
c = 0;
r++;
} // while ((line != null) && (r < rows))
try {
in.close();
}
catch (IOException ex) {}
table.updateUI();
}
/**
* import data values from binary file.
*/
private void importBinaryData() {
String currentDir = dataset.getFileFormat().getParent();
JFileChooser fchooser = new JFileChooser(currentDir);
fchooser.setFileFilter(DefaultFileFilter.getFileFilterBinary());
int returnVal = fchooser.showOpenDialog(this);
if (returnVal != JFileChooser.APPROVE_OPTION) {
return;
}
File choosedFile = fchooser.getSelectedFile();
if (choosedFile == null) {
return;
}
String fname = choosedFile.getAbsolutePath();
int pasteDataFlag = JOptionPane.showConfirmDialog(this, "Do you want to paste selected data ?",
this.getTitle(), JOptionPane.YES_NO_OPTION);
if (pasteDataFlag == JOptionPane.NO_OPTION) {
return;
}
getBinaryDatafromFile(fname);
}
/** Reads data from a binary file into a buffer and updates table. */
private void getBinaryDatafromFile(String fileName) {
String fname = fileName;
FileInputStream inputFile = null;
BufferedInputStream in = null;
ByteBuffer byteBuffer = null;
try {
inputFile = new FileInputStream(fname);
long fileSize = inputFile.getChannel().size();
in = new BufferedInputStream(inputFile);
Object data = dataset.getData();
int datasetSize = Array.getLength(data);
String cname = data.getClass().getName();
char dname = cname.charAt(cname.lastIndexOf("[") + 1);
if (dname == 'B') {
long datasetByteSize = datasetSize;
byteBuffer = ByteBuffer.allocate(BYTE_BUFFER_SIZE);
if (binaryOrder == 1)
byteBuffer.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN);
int bufferSize = (int) Math.min(fileSize, datasetByteSize);
int remainingSize = (int) bufferSize - (BYTE_BUFFER_SIZE);
int allocValue = 0;
int iterationNumber = 0;
byte[] byteArray = new byte[BYTE_BUFFER_SIZE];
do {
if (remainingSize <= 0) {
allocValue = remainingSize + (BYTE_BUFFER_SIZE);
}
else {
allocValue = (BYTE_BUFFER_SIZE);
}
in.read(byteBuffer.array(), 0, allocValue);
byteBuffer.get(byteArray, 0, allocValue);
System.arraycopy(byteArray, 0, dataValue, (iterationNumber * BYTE_BUFFER_SIZE), allocValue);
byteBuffer.clear();
remainingSize = remainingSize - (BYTE_BUFFER_SIZE);
iterationNumber++;
} while (remainingSize > -(BYTE_BUFFER_SIZE));
isValueChanged = true;
}
else if (dname == 'S') {
long datasetShortSize = datasetSize * 2;
byteBuffer = ByteBuffer.allocate(SHORT_BUFFER_SIZE * 2);
if (binaryOrder == 1)
byteBuffer.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN);
int bufferSize = (int) Math.min(fileSize, datasetShortSize);
int remainingSize = (int) bufferSize - (SHORT_BUFFER_SIZE * 2);
int allocValue = 0;
int iterationNumber = 0;
ShortBuffer sb = byteBuffer.asShortBuffer();
short[] shortArray = new short[SHORT_BUFFER_SIZE];
do {
if (remainingSize <= 0) {
allocValue = remainingSize + (SHORT_BUFFER_SIZE * 2);
}
else {
allocValue = (SHORT_BUFFER_SIZE * 2);
}
in.read(byteBuffer.array(), 0, allocValue);
sb.get(shortArray, 0, allocValue / 2);
System.arraycopy(shortArray, 0, dataValue, (iterationNumber * SHORT_BUFFER_SIZE), allocValue / 2);
byteBuffer.clear();
sb.clear();
remainingSize = remainingSize - (SHORT_BUFFER_SIZE * 2);
iterationNumber++;
} while (remainingSize > -(SHORT_BUFFER_SIZE * 2));
isValueChanged = true;
}
else if (dname == 'I') {
long datasetIntSize = datasetSize * 4;
byteBuffer = ByteBuffer.allocate(INT_BUFFER_SIZE * 4);
if (binaryOrder == 1)
byteBuffer.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN);
int bufferSize = (int) Math.min(fileSize, datasetIntSize);
int remainingSize = (int) bufferSize - (INT_BUFFER_SIZE * 4);
int allocValue = 0;
int iterationNumber = 0;
int[] intArray = new int[INT_BUFFER_SIZE];
byte[] tmpBuf = byteBuffer.array();
IntBuffer ib = byteBuffer.asIntBuffer();
do {
if (remainingSize <= 0) {
allocValue = remainingSize + (INT_BUFFER_SIZE * 4);
}
else {
allocValue = (INT_BUFFER_SIZE * 4);
}
in.read(tmpBuf, 0, allocValue);
ib.get(intArray, 0, allocValue / 4);
System.arraycopy(intArray, 0, dataValue, (iterationNumber * INT_BUFFER_SIZE), allocValue / 4);
byteBuffer.clear();
ib.clear();
remainingSize = remainingSize - (INT_BUFFER_SIZE * 4);
iterationNumber++;
} while (remainingSize > -(INT_BUFFER_SIZE * 4));
isValueChanged = true;
}
else if (dname == 'J') {
long datasetLongSize = datasetSize * 8;
byteBuffer = ByteBuffer.allocate(LONG_BUFFER_SIZE * 8);
if (binaryOrder == 1)
byteBuffer.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN);
int bufferSize = (int) Math.min(fileSize, datasetLongSize);
int remainingSize = (int) bufferSize - (LONG_BUFFER_SIZE * 8);
int allocValue = 0;
int iterationNumber = 0;
long[] longArray = new long[LONG_BUFFER_SIZE];
LongBuffer lb = byteBuffer.asLongBuffer();
do {
if (remainingSize <= 0) {
allocValue = remainingSize + (LONG_BUFFER_SIZE * 8);
}
else {
allocValue = (LONG_BUFFER_SIZE * 8);
}
in.read(byteBuffer.array(), 0, allocValue);
lb.get(longArray, 0, allocValue / 8);
System.arraycopy(longArray, 0, dataValue, (iterationNumber * LONG_BUFFER_SIZE), allocValue / 8);
byteBuffer.clear();
lb.clear();
remainingSize = remainingSize - (LONG_BUFFER_SIZE * 8);
iterationNumber++;
} while (remainingSize > -(LONG_BUFFER_SIZE * 8));
isValueChanged = true;
}
else if (dname == 'F') {
long datasetFloatSize = datasetSize * 4;
byteBuffer = ByteBuffer.allocate(FLOAT_BUFFER_SIZE * 4);
if (binaryOrder == 1)
byteBuffer.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN);
int bufferSize = (int) Math.min(fileSize, datasetFloatSize);
int remainingSize = (int) bufferSize - (FLOAT_BUFFER_SIZE * 4);
int allocValue = 0;
int iterationNumber = 0;
FloatBuffer fb = byteBuffer.asFloatBuffer();
float[] floatArray = new float[FLOAT_BUFFER_SIZE];
do {
if (remainingSize <= 0) {
allocValue = remainingSize + (FLOAT_BUFFER_SIZE * 4);
}
else {
allocValue = (FLOAT_BUFFER_SIZE * 4);
}
in.read(byteBuffer.array(), 0, allocValue);
fb.get(floatArray, 0, allocValue / 4);
System.arraycopy(floatArray, 0, dataValue, (iterationNumber * FLOAT_BUFFER_SIZE), allocValue / 4);
byteBuffer.clear();
fb.clear();
remainingSize = remainingSize - (FLOAT_BUFFER_SIZE * 4);
iterationNumber++;
} while (remainingSize > -(FLOAT_BUFFER_SIZE * 4));
isValueChanged = true;
}
else if (dname == 'D') {
long datasetDoubleSize = datasetSize * 8;
byteBuffer = ByteBuffer.allocate(DOUBLE_BUFFER_SIZE * 8);
if (binaryOrder == 1)
byteBuffer.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) byteBuffer.order(ByteOrder.BIG_ENDIAN);
int bufferSize = (int) Math.min(fileSize, datasetDoubleSize);
int remainingSize = (int) bufferSize - (DOUBLE_BUFFER_SIZE * 8);
int allocValue = 0;
int iterationNumber = 0;
DoubleBuffer db = byteBuffer.asDoubleBuffer();
double[] doubleArray = new double[DOUBLE_BUFFER_SIZE];
do {
if (remainingSize <= 0) {
allocValue = remainingSize + (DOUBLE_BUFFER_SIZE * 8);
}
else {
allocValue = (DOUBLE_BUFFER_SIZE * 8);
}
in.read(byteBuffer.array(), 0, allocValue);
db.get(doubleArray, 0, allocValue / 8);
System.arraycopy(doubleArray, 0, dataValue, (iterationNumber * DOUBLE_BUFFER_SIZE), allocValue / 8);
byteBuffer.clear();
db.clear();
remainingSize = remainingSize - (DOUBLE_BUFFER_SIZE * 8);
iterationNumber++;
} while (remainingSize > -(DOUBLE_BUFFER_SIZE * 8));
isValueChanged = true;
}
}
catch (Exception es) {
es.printStackTrace();
}
finally {
try {
in.close();
inputFile.close();
}
catch (IOException ex) {}
}
table.updateUI();
}
/** Save data as text. */
private void saveAsText() throws Exception {
final JFileChooser fchooser = new JFileChooser(dataset.getFile());
fchooser.setFileFilter(DefaultFileFilter.getFileFilterText());
// fchooser.changeToParentDirectory();
fchooser.setDialogTitle("Save Current Data To Text File --- " + dataset.getName());
File choosedFile = new File(dataset.getName() + ".txt");
fchooser.setSelectedFile(choosedFile);
int returnVal = fchooser.showSaveDialog(this);
if (returnVal != JFileChooser.APPROVE_OPTION) {
return;
}
choosedFile = fchooser.getSelectedFile();
if (choosedFile == null) {
return;
}
String fname = choosedFile.getAbsolutePath();
// check if the file is in use
List fileList = viewer.getTreeView().getCurrentFiles();
if (fileList != null) {
FileFormat theFile = null;
Iterator iterator = fileList.iterator();
while (iterator.hasNext()) {
theFile = (FileFormat) iterator.next();
if (theFile.getFilePath().equals(fname)) {
toolkit.beep();
JOptionPane.showMessageDialog(this,
"Unable to save data to file \"" + fname + "\". \nThe file is being used.",
getTitle(), JOptionPane.ERROR_MESSAGE);
return;
}
}
}
if (choosedFile.exists()) {
int newFileFlag = JOptionPane.showConfirmDialog(this,
"File exists. Do you want to replace it ?",
this.getTitle(), JOptionPane.YES_NO_OPTION);
if (newFileFlag == JOptionPane.NO_OPTION) {
return;
}
}
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(choosedFile)));
String delName = ViewProperties.getDataDelimiter();
String delimiter = "";
// delimiter must include a tab to be consistent with copy/paste for
// compound fields
if (dataset instanceof CompoundDS) delimiter = "\t";
if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_TAB)) {
delimiter = "\t";
}
else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_SPACE)) {
delimiter = " " + delimiter;
}
else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_COMMA)) {
delimiter = "," + delimiter;
}
else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_COLON)) {
delimiter = ":" + delimiter;
}
else if (delName.equalsIgnoreCase(ViewProperties.DELIMITER_SEMI_COLON)) {
delimiter = ";" + delimiter;
}
int cols = table.getColumnCount();
int rows = table.getRowCount();
for (int i = 0; i < rows; i++) {
out.print(table.getValueAt(i, 0));
for (int j = 1; j < cols; j++) {
out.print(delimiter);
out.print(table.getValueAt(i, j));
}
out.println();
}
out.flush();
out.close();
viewer.showStatus("Data save to: " + fname);
}
/** Save data as binary. */
private void saveAsBinary() throws Exception {
final JFileChooser fchooser = new JFileChooser(dataset.getFile());
fchooser.setFileFilter(DefaultFileFilter.getFileFilterBinary());
// fchooser.changeToParentDirectory();
fchooser.setDialogTitle("Save Current Data To Binary File --- " + dataset.getName());
File choosedFile = new File(dataset.getName() + ".bin");
;
fchooser.setSelectedFile(choosedFile);
int returnVal = fchooser.showSaveDialog(this);
if (returnVal != JFileChooser.APPROVE_OPTION) {
return;
}
choosedFile = fchooser.getSelectedFile();
if (choosedFile == null) {
return;
}
String fname = choosedFile.getAbsolutePath();
// check if the file is in use
List fileList = viewer.getTreeView().getCurrentFiles();
if (fileList != null) {
FileFormat theFile = null;
Iterator iterator = fileList.iterator();
while (iterator.hasNext()) {
theFile = (FileFormat) iterator.next();
if (theFile.getFilePath().equals(fname)) {
toolkit.beep();
JOptionPane.showMessageDialog(this, "Unable to save data to file \"" + fname
+ "\". \nThe file is being used.", getTitle(), JOptionPane.ERROR_MESSAGE);
return;
}
}
}
// check if the file exists
if (choosedFile.exists()) {
int newFileFlag = JOptionPane.showConfirmDialog(this, "File exists. Do you want to replace it ?",
this.getTitle(), JOptionPane.YES_NO_OPTION);
if (newFileFlag == JOptionPane.NO_OPTION) {
return;
}
}
FileOutputStream outputFile = new FileOutputStream(choosedFile);
DataOutputStream out = new DataOutputStream(outputFile);
if (dataset instanceof ScalarDS) {
Object data = dataset.getData();
String cname = data.getClass().getName();
char dname = cname.charAt(cname.lastIndexOf("[") + 1);
ByteBuffer bb = null;
int size = Array.getLength(data);
if (dname == 'B') {
byte[] bdata = new byte[size];
bdata = (byte[]) data;
bb = ByteBuffer.allocate(BYTE_BUFFER_SIZE);
if (binaryOrder == 1)
bb.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
bb.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN);
int remainingSize = size - BYTE_BUFFER_SIZE;
int allocValue = 0;
int iterationNumber = 0;
do {
if (remainingSize <= 0) {
allocValue = remainingSize + BYTE_BUFFER_SIZE;
}
else {
allocValue = BYTE_BUFFER_SIZE;
}
bb.clear();
bb.put(bdata, (iterationNumber * BYTE_BUFFER_SIZE), allocValue);
out.write(bb.array(), 0, allocValue);
remainingSize = remainingSize - BYTE_BUFFER_SIZE;
iterationNumber++;
} while (remainingSize > -BYTE_BUFFER_SIZE);
out.flush();
out.close();
}
else if (dname == 'S') {
short[] sdata = new short[size];
sdata = (short[]) data;
bb = ByteBuffer.allocate(SHORT_BUFFER_SIZE * 2);
if (binaryOrder == 1)
bb.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
bb.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN);
ShortBuffer sb = bb.asShortBuffer();
int remainingSize = size - SHORT_BUFFER_SIZE;
int allocValue = 0;
int iterationNumber = 0;
do {
if (remainingSize <= 0) {
allocValue = remainingSize + SHORT_BUFFER_SIZE;
}
else {
allocValue = SHORT_BUFFER_SIZE;
}
bb.clear();
sb.clear();
sb.put(sdata, (iterationNumber * SHORT_BUFFER_SIZE), allocValue);
out.write(bb.array(), 0, allocValue * 2);
remainingSize = remainingSize - SHORT_BUFFER_SIZE;
iterationNumber++;
} while (remainingSize > -SHORT_BUFFER_SIZE);
out.flush();
out.close();
}
else if (dname == 'I') {
int[] idata = new int[size];
idata = (int[]) data;
bb = ByteBuffer.allocate(INT_BUFFER_SIZE * 4);
if (binaryOrder == 1)
bb.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
bb.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN);
IntBuffer ib = bb.asIntBuffer();
int remainingSize = size - INT_BUFFER_SIZE;
int allocValue = 0;
int iterationNumber = 0;
do {
if (remainingSize <= 0) {
allocValue = remainingSize + INT_BUFFER_SIZE;
}
else {
allocValue = INT_BUFFER_SIZE;
}
bb.clear();
ib.clear();
ib.put(idata, (iterationNumber * INT_BUFFER_SIZE), allocValue);
out.write(bb.array(), 0, allocValue * 4);
remainingSize = remainingSize - INT_BUFFER_SIZE;
iterationNumber++;
} while (remainingSize > -INT_BUFFER_SIZE);
out.flush();
out.close();
}
else if (dname == 'J') {
long[] ldata = new long[size];
ldata = (long[]) data;
bb = ByteBuffer.allocate(LONG_BUFFER_SIZE * 8);
if (binaryOrder == 1)
bb.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
bb.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN);
LongBuffer lb = bb.asLongBuffer();
int remainingSize = size - LONG_BUFFER_SIZE;
int allocValue = 0;
int iterationNumber = 0;
do {
if (remainingSize <= 0) {
allocValue = remainingSize + LONG_BUFFER_SIZE;
}
else {
allocValue = LONG_BUFFER_SIZE;
}
bb.clear();
lb.clear();
lb.put(ldata, (iterationNumber * LONG_BUFFER_SIZE), allocValue);
out.write(bb.array(), 0, allocValue * 8);
remainingSize = remainingSize - LONG_BUFFER_SIZE;
iterationNumber++;
} while (remainingSize > -LONG_BUFFER_SIZE);
out.flush();
out.close();
}
else if (dname == 'F') {
float[] fdata = new float[size];
fdata = (float[]) data;
bb = ByteBuffer.allocate(FLOAT_BUFFER_SIZE * 4);
if (binaryOrder == 1)
bb.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
bb.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN);
FloatBuffer fb = bb.asFloatBuffer();
int remainingSize = size - FLOAT_BUFFER_SIZE;
int allocValue = 0;
int iterationNumber = 0;
do {
if (remainingSize <= 0) {
allocValue = remainingSize + FLOAT_BUFFER_SIZE;
}
else {
allocValue = FLOAT_BUFFER_SIZE;
}
bb.clear();
fb.clear();
fb.put(fdata, (iterationNumber * FLOAT_BUFFER_SIZE), allocValue);
out.write(bb.array(), 0, allocValue * 4);
remainingSize = remainingSize - FLOAT_BUFFER_SIZE;
iterationNumber++;
} while (remainingSize > -FLOAT_BUFFER_SIZE);
out.flush();
out.close();
}
else if (dname == 'D') {
double[] ddata = new double[size];
ddata = (double[]) data;
bb = ByteBuffer.allocate(DOUBLE_BUFFER_SIZE * 8);
if (binaryOrder == 1)
bb.order(ByteOrder.nativeOrder());
else if (binaryOrder == 2)
bb.order(ByteOrder.LITTLE_ENDIAN);
else if (binaryOrder == 3) bb.order(ByteOrder.BIG_ENDIAN);
DoubleBuffer db = bb.asDoubleBuffer();
int remainingSize = size - DOUBLE_BUFFER_SIZE;
int allocValue = 0;
int iterationNumber = 0;
do {
if (remainingSize <= 0) {
allocValue = remainingSize + DOUBLE_BUFFER_SIZE;
}
else {
allocValue = DOUBLE_BUFFER_SIZE;
}
bb.clear();
db.clear();
db.put(ddata, (iterationNumber * DOUBLE_BUFFER_SIZE), allocValue);
out.write(bb.array(), 0, allocValue * 8);
remainingSize = remainingSize - DOUBLE_BUFFER_SIZE;
iterationNumber++;
} while (remainingSize > -DOUBLE_BUFFER_SIZE);
out.flush();
out.close();
}
}
viewer.showStatus("Data save to: " + fname);
}
/**
* update dataset value in file. The change will go to file.
*/
public void updateValueInFile() {
if (isReadOnly || showAsBin || showAsHex) {
return;
}
// if (!(dataset instanceof ScalarDS) || !isValueChanged)
if (!isValueChanged) {
return;
}
try {
dataset.write();
}
catch (Exception ex) {
toolkit.beep();
JOptionPane.showMessageDialog(this, ex, getTitle(), JOptionPane.ERROR_MESSAGE);
return;
}
isValueChanged = false;
}
/**
* Selects all rows, columns, and cells in the table.
*/
private void selectAll() throws Exception {
table.selectAll();
}
/**
* Converting selected data based on predefined math functions.
*/
private void mathConversion() throws Exception {
if (isReadOnly) {
return;
}
int cols = table.getSelectedColumnCount();
// if (!(dataset instanceof ScalarDS)) return;
if ((dataset instanceof CompoundDS) && (cols > 1)) {
toolkit.beep();
JOptionPane.showMessageDialog(this,
"Please select one colunm a time for math conversion for compound dataset.", getTitle(),
JOptionPane.ERROR_MESSAGE);
return;
}
Object theData = getSelectedData();
if (theData == null) {
toolkit.beep();
JOptionPane.showMessageDialog(this, "No data is selected.", getTitle(), JOptionPane.ERROR_MESSAGE);
return;
}
MathConversionDialog dialog = new MathConversionDialog((JFrame) viewer, theData);
dialog.setVisible(true);
if (dialog.isConverted()) {
if (dataset instanceof CompoundDS) {
Object colData = null;
try {
colData = ((List) dataset.getData()).get(table.getSelectedColumn());
}
catch (Exception ex) {}
if (colData != null) {
int size = Array.getLength(theData);
System.arraycopy(theData, 0, colData, 0, size);
}
}
else {
int rows = table.getSelectedRowCount();
int r0 = table.getSelectedRow();
int c0 = table.getSelectedColumn();
int w = table.getColumnCount();
int idx_src = 0;
int idx_dst = 0;
for (int i = 0; i < rows; i++) {
idx_dst = (r0 + i) * w + c0;
System.arraycopy(theData, idx_src, dataValue, idx_dst, cols);
idx_src += cols;
}
}
theData = null;
System.gc();
table.updateUI();
isValueChanged = true;
}
}
/**
* update cell value in memory. It does not change the dataset value in
* file.
*
* @param cellValue
* the string value of input.
* @param row
* the row of the editing cell.
* @param col
* the column of the editing cell.
*/
private void updateValueInMemory(String cellValue, int row, int col) throws Exception {
if (currentEditingCellValue != null) {
// data values are the same, no need to change the data
if (currentEditingCellValue.toString().equals(cellValue)) return;
}
if (dataset instanceof ScalarDS) {
updateScalarData(cellValue, row, col);
}
else if (dataset instanceof CompoundDS) {
updateCompoundData(cellValue, row, col);
}
}
/**
* update cell value in memory. It does not change the dataset value in
* file.
*
* @param cellValue
* the string value of input.
* @param row
* the row of the editing cell.
* @param col
* the column of the editing cell.
*/
private void updateScalarData(String cellValue, int row, int col) throws Exception {
if (!(dataset instanceof ScalarDS) || (cellValue == null) || ((cellValue = cellValue.trim()) == null)
|| showAsBin || showAsHex) {
return;
}
int i = 0;
if (isDataTransposed) {
i = col * table.getRowCount() + row;
}
else {
i = row * table.getColumnCount() + col;
}
ScalarDS sds = (ScalarDS) dataset;
boolean isUnsigned = sds.isUnsigned();
String cname = dataset.getOriginalClass().getName();
char dname = cname.charAt(cname.lastIndexOf("[") + 1);
// check data range for unsigned datatype converted sizes!
if (isUnsigned) {
long lvalue = -1;
long maxValue = Long.MAX_VALUE;
if (dname == 'B') {
maxValue = 255;
lvalue = Long.parseLong(cellValue);
if (lvalue < 0) {
throw new NumberFormatException("Negative value for unsigned integer: " + lvalue);
}
if (lvalue > maxValue) {
throw new NumberFormatException("Data value is out of range: " + lvalue);
}
}
else if (dname == 'S') {
maxValue = 65535;
lvalue = Long.parseLong(cellValue);
if (lvalue < 0) {
throw new NumberFormatException("Negative value for unsigned integer: " + lvalue);
}
if (lvalue > maxValue) {
throw new NumberFormatException("Data value is out of range: " + lvalue);
}
}
else if (dname == 'I') {
maxValue = 4294967295L;
lvalue = Long.parseLong(cellValue);
if (lvalue < 0) {
throw new NumberFormatException("Negative value for unsigned integer: " + lvalue);
}
if (lvalue > maxValue) {
throw new NumberFormatException("Data value is out of range: " + lvalue);
}
}
else if (dname == 'J') {
BigInteger Jmax = new BigInteger("18446744073709551615");
BigInteger big = new BigInteger(cellValue);
if (big.compareTo(Jmax) > 0) {
throw new NumberFormatException("Negative value for unsigned integer: " + cellValue);
}
if (big.compareTo(BigInteger.ZERO) < 0) {
throw new NumberFormatException("Data value is out of range: " + cellValue);
}
}
}
switch (NT) {
case 'B':
byte bvalue = 0;
bvalue = Byte.parseByte(cellValue);
Array.setByte(dataValue, i, bvalue);
break;
case 'S':
short svalue = 0;
svalue = Short.parseShort(cellValue);
Array.setShort(dataValue, i, svalue);
break;
case 'I':
int ivalue = 0;
ivalue = Integer.parseInt(cellValue);
Array.setInt(dataValue, i, ivalue);
break;
case 'J':
long lvalue = 0;
if (dname == 'J') {
BigInteger big = new BigInteger(cellValue);
lvalue = big.longValue();
}
else
lvalue = Long.parseLong(cellValue);
Array.setLong(dataValue, i, lvalue);
break;
case 'F':
float fvalue = 0;
fvalue = Float.parseFloat(cellValue);
Array.setFloat(dataValue, i, fvalue);
break;
case 'D':
double dvalue = 0;
dvalue = Double.parseDouble(cellValue);
Array.setDouble(dataValue, i, dvalue);
break;
default:
Array.set(dataValue, i, cellValue);
break;
}
isValueChanged = true;
}
private void updateCompoundData(String cellValue, int row, int col) throws Exception {
if (!(dataset instanceof CompoundDS) || (cellValue == null) || ((cellValue = cellValue.trim()) == null)) {
return;
}
CompoundDS compDS = (CompoundDS) dataset;
List cdata = (List) compDS.getData();
int orders[] = compDS.getSelectedMemberOrders();
Datatype types[] = compDS.getSelectedMemberTypes();
int nFields = cdata.size();
int nSubColumns = table.getColumnCount() / nFields;
int nRows = table.getRowCount();
int column = col;
int offset = 0;
int morder = 1;
if (nSubColumns > 1) { // multi-dimension compound dataset
int colIdx = col / nFields;
column = col - colIdx * nFields;
// //BUG 573: offset = row * orders[column] + colIdx * nRows *
// orders[column];
offset = row * orders[column] * nSubColumns + colIdx * orders[column];
}
else {
offset = row * orders[column];
}
morder = orders[column];
Object mdata = cdata.get(column);
// strings
if (Array.get(mdata, 0) instanceof String) {
Array.set(mdata, offset, cellValue);
isValueChanged = true;
return;
}
else if (types[column].getDatatypeClass() == Datatype.CLASS_STRING) {
// it is string but not converted, still byte array
int strlen = types[column].getDatatypeSize();
offset *= strlen;
byte[] bytes = cellValue.getBytes();
byte[] bData = (byte[]) mdata;
int n = Math.min(strlen, bytes.length);
System.arraycopy(bytes, 0, bData, offset, n);
offset += n;
n = strlen - bytes.length;
// space padding
for (int i = 0; i < n; i++) {
bData[offset + i] = ' ';
}
isValueChanged = true;
return;
}
// Numeric data
char mNT = ' ';
String cName = mdata.getClass().getName();
int cIndex = cName.lastIndexOf("[");
if (cIndex >= 0) {
mNT = cName.charAt(cIndex + 1);
}
StringTokenizer st = new StringTokenizer(cellValue, ",");
if (st.countTokens() < morder) {
toolkit.beep();
JOptionPane.showMessageDialog(this,
"Number of data point < " + morder + ".", getTitle(),
JOptionPane.ERROR_MESSAGE);
return;
}
String token = "";
isValueChanged = true;
switch (mNT) {
case 'B':
byte bvalue = 0;
for (int i = 0; i < morder; i++) {
token = st.nextToken().trim();
bvalue = Byte.parseByte(token);
Array.setByte(mdata, offset + i, bvalue);
}
break;
case 'S':
short svalue = 0;
for (int i = 0; i < morder; i++) {
token = st.nextToken().trim();
svalue = Short.parseShort(token);
Array.setShort(mdata, offset + i, svalue);
}
break;
case 'I':
int ivalue = 0;
for (int i = 0; i < morder; i++) {
token = st.nextToken().trim();
ivalue = Integer.parseInt(token);
Array.setInt(mdata, offset + i, ivalue);
}
break;
case 'J':
long lvalue = 0;
for (int i = 0; i < morder; i++) {
token = st.nextToken().trim();
BigInteger big = new BigInteger(token);
lvalue = big.longValue();
// lvalue = Long.parseLong(token);
Array.setLong(mdata, offset + i, lvalue);
}
break;
case 'F':
float fvalue = 0;
for (int i = 0; i < morder; i++) {
token = st.nextToken().trim();
fvalue = Float.parseFloat(token);
Array.setFloat(mdata, offset + i, fvalue);
}
break;
case 'D':
double dvalue = 0;
for (int i = 0; i < morder; i++) {
token = st.nextToken().trim();
dvalue = Double.parseDouble(token);
Array.setDouble(mdata, offset + i, dvalue);
}
break;
default:
isValueChanged = false;
}
}
private class LineplotOption extends JDialog implements ActionListener, ItemListener {
private static final long serialVersionUID = -3457035832213978906L;
public static final int NO_PLOT = -1;
public static final int ROW_PLOT = 0;
public static final int COLUMN_PLOT = 1;
private int idx_xaxis = -1, nRows = 0, nCols = 0, plotType = -1;
private JRadioButton rowButton, colButton;
private JComboBox rowBox, colBox;
public LineplotOption(JFrame owner, String title, int nrow, int ncol) {
super(owner, title, true);
nRows = nrow;
nCols = ncol;
rowBox = new JComboBox();
rowBox.setEditable(false);
colBox = new JComboBox();
colBox.setEditable(false);
JPanel contentPane = (JPanel) this.getContentPane();
contentPane.setPreferredSize(new Dimension(400, 150));
contentPane.setLayout(new BorderLayout(10, 10));
long[] startArray = dataset.getStartDims();
long[] strideArray = dataset.getStride();
int[] selectedIndex = dataset.getSelectedIndex();
int start = (int) startArray[selectedIndex[0]];
int stride = (int) strideArray[selectedIndex[0]];
rowBox.addItem("array index");
for (int i = 0; i < nrow; i++) {
rowBox.addItem("row " + (start + i * stride));
}
colBox.addItem("array index");
for (int i = 0; i < ncol; i++) {
colBox.addItem("column " + table.getColumnName(i));
}
rowButton = new JRadioButton("Row");
colButton = new JRadioButton("Column", true);
rowButton.addItemListener(this);
colButton.addItemListener(this);
ButtonGroup rgroup = new ButtonGroup();
rgroup.add(rowButton);
rgroup.add(colButton);
JPanel p1 = new JPanel();
p1.setLayout(new GridLayout(2, 1, 5, 5));
p1.add(new JLabel(" Series in:", SwingConstants.RIGHT));
p1.add(new JLabel(" For abscissa use:", SwingConstants.RIGHT));
JPanel p2 = new JPanel();
p2.setLayout(new GridLayout(2, 1, 5, 5));
// p2.setBorder(new LineBorder(Color.lightGray));
p2.add(colButton);
p2.add(colBox);
JPanel p3 = new JPanel();
p3.setLayout(new GridLayout(2, 1, 5, 5));
// p3.setBorder(new LineBorder(Color.lightGray));
p3.add(rowButton);
p3.add(rowBox);
JPanel p = new JPanel();
p.setBorder(new LineBorder(Color.lightGray));
p.setLayout(new GridLayout(1, 3, 20, 5));
p.add(p1);
p.add(p2);
p.add(p3);
JPanel bp = new JPanel();
JButton okButton = new JButton("Ok");
okButton.addActionListener(this);
okButton.setActionCommand("Ok");
bp.add(okButton);
JButton cancelButton = new JButton("Cancel");
cancelButton.addActionListener(this);
cancelButton.setActionCommand("Cancel");
bp.add(cancelButton);
contentPane.add(new JLabel(" Select plot options:"), BorderLayout.NORTH);
contentPane.add(p, BorderLayout.CENTER);
contentPane.add(bp, BorderLayout.SOUTH);
colBox.setEnabled(colButton.isSelected());
rowBox.setEnabled(rowButton.isSelected());
Point l = getParent().getLocation();
l.x += 450;
l.y += 200;
setLocation(l);
pack();
}
int getXindex() {
return idx_xaxis;
}
int getPlotBy() {
return plotType;
}
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
String cmd = e.getActionCommand();
if (cmd.equals("Cancel")) {
plotType = NO_PLOT;
this.dispose(); // terminate the application
}
else if (cmd.equals("Ok")) {
if (colButton.isSelected()) {
idx_xaxis = colBox.getSelectedIndex() - 1;
plotType = COLUMN_PLOT;
}
else {
idx_xaxis = rowBox.getSelectedIndex() - 1;
plotType = ROW_PLOT;
}
this.dispose(); // terminate the application
}
}
public void itemStateChanged(ItemEvent e) {
Object source = e.getSource();
if (source.equals(colButton) || source.equals(rowButton)) {
colBox.setEnabled(colButton.isSelected());
rowBox.setEnabled(rowButton.isSelected());
}
}
}
private class ColumnHeader extends JTableHeader {
private static final long serialVersionUID = -3179653809792147055L;
private int currentColumnIndex = -1;
private int lastColumnIndex = -1;
private JTable parentTable;
public ColumnHeader(JTable theTable) {
super(theTable.getColumnModel());
parentTable = theTable;
setReorderingAllowed(false);
}
protected void processMouseMotionEvent(MouseEvent e) {
super.processMouseMotionEvent(e);
if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
// do not do anything, just resize the column
if (getResizingColumn() != null) return;
int colEnd = columnAtPoint(e.getPoint());
if (colEnd < 0) {
colEnd = 0;
}
if (currentColumnIndex < 0) {
currentColumnIndex = 0;
}
parentTable.clearSelection();
if (colEnd > currentColumnIndex) {
parentTable.setColumnSelectionInterval(currentColumnIndex, colEnd);
}
else {
parentTable.setColumnSelectionInterval(colEnd, currentColumnIndex);
}
parentTable.setRowSelectionInterval(0, parentTable.getRowCount() - 1);
}
}
protected void processMouseEvent(MouseEvent e) {
super.processMouseEvent(e);
int mouseID = e.getID();
if (mouseID == MouseEvent.MOUSE_CLICKED) {
if (currentColumnIndex < 0) {
return;
}
if (e.isControlDown()) {
// select discontinuous columns
parentTable.addColumnSelectionInterval(currentColumnIndex, currentColumnIndex);
}
else if (e.isShiftDown()) {
// select continuous columns
if (lastColumnIndex < 0) {
parentTable.addColumnSelectionInterval(0, currentColumnIndex);
}
else if (lastColumnIndex < currentColumnIndex) {
parentTable.addColumnSelectionInterval(lastColumnIndex, currentColumnIndex);
}
else {
parentTable.addColumnSelectionInterval(currentColumnIndex, lastColumnIndex);
}
}
else {
// clear old selection and set new column selection
parentTable.clearSelection();
parentTable.setColumnSelectionInterval(currentColumnIndex, currentColumnIndex);
}
lastColumnIndex = currentColumnIndex;
parentTable.setRowSelectionInterval(0, parentTable.getRowCount() - 1);
}
else if (mouseID == MouseEvent.MOUSE_PRESSED) {
currentColumnIndex = columnAtPoint(e.getPoint());
}
}
} // private class ColumnHeader
/** RowHeader defines the row header component of the Spreadsheet. */
private class RowHeader extends JTable {
private static final long serialVersionUID = -1548007702499873626L;
private int currentRowIndex = -1;
private int lastRowIndex = -1;
private JTable parentTable;
public RowHeader(JTable pTable, Dataset dset) {
// Create a JTable with the same number of rows as
// the parent table and one column.
// super( pTable.getRowCount(), 1 );
final long[] startArray = dset.getStartDims();
final long[] strideArray = dset.getStride();
final int[] selectedIndex = dset.getSelectedIndex();
final int start = (int) startArray[selectedIndex[0]];
final int stride = (int) strideArray[selectedIndex[0]];
final int rowCount = pTable.getRowCount();
parentTable = pTable;
AbstractTableModel tm = new AbstractTableModel() {
private static final long serialVersionUID = -8117073107569884677L;
public int getColumnCount() {
return 1;
}
public int getRowCount() {
return rowCount;
}
public String getColumnName(int col) {
return " ";
}
public Object getValueAt(int row, int column) {
return String.valueOf(start + indexBase + row * stride);
}
};
this.setModel(tm);
// Get the only table column.
TableColumn col = getColumnModel().getColumn(0);
// Use the cell renderer in the column.
col.setCellRenderer(new RowHeaderRenderer());
}
/** Overridden to return false since the headers are not editable. */
public boolean isCellEditable(int row, int col) {
return false;
}
/** This is called when the selection changes in the row headers. */
public void valueChanged(ListSelectionEvent e) {
if (parentTable == null) {
return;
}
int rows[] = getSelectedRows();
if ((rows == null) || (rows.length == 0)) {
return;
}
parentTable.clearSelection();
parentTable.setRowSelectionInterval(rows[0], rows[rows.length - 1]);
parentTable.setColumnSelectionInterval(0, parentTable.getColumnCount() - 1);
}
protected void processMouseMotionEvent(MouseEvent e) {
if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
int colEnd = rowAtPoint(e.getPoint());
if (colEnd < 0) {
colEnd = 0;
}
if (currentRowIndex < 0) {
currentRowIndex = 0;
}
parentTable.clearSelection();
if (colEnd > currentRowIndex) {
parentTable.setRowSelectionInterval(currentRowIndex, colEnd);
}
else {
parentTable.setRowSelectionInterval(colEnd, currentRowIndex);
}
parentTable.setColumnSelectionInterval(0, parentTable.getColumnCount() - 1);
}
}
protected void processMouseEvent(MouseEvent e) {
int mouseID = e.getID();
if (mouseID == MouseEvent.MOUSE_CLICKED) {
if (currentRowIndex < 0) {
return;
}
if (e.isControlDown()) {
// select discontinuous rows
parentTable.addRowSelectionInterval(currentRowIndex, currentRowIndex);
}
else if (e.isShiftDown()) {
// select contiguous columns
if (lastRowIndex < 0) {
parentTable.addRowSelectionInterval(0, currentRowIndex);
}
else if (lastRowIndex < currentRowIndex) {
parentTable.addRowSelectionInterval(lastRowIndex, currentRowIndex);
}
else {
parentTable.addRowSelectionInterval(currentRowIndex, lastRowIndex);
}
}
else {
// clear old selection and set new column selection
parentTable.clearSelection();
parentTable.setRowSelectionInterval(currentRowIndex, currentRowIndex);
}
lastRowIndex = currentRowIndex;
parentTable.setColumnSelectionInterval(0, parentTable.getColumnCount() - 1);
}
else if (mouseID == MouseEvent.MOUSE_PRESSED) {
currentRowIndex = rowAtPoint(e.getPoint());
}
}
} // private class RowHeader extends JTable
/**
* RowHeaderRenderer is a custom cell renderer that displays cells as
* buttons.
*/
private class RowHeaderRenderer extends JLabel implements TableCellRenderer {
private static final long serialVersionUID = -8963879626159783226L;
public RowHeaderRenderer() {
super();
setHorizontalAlignment(JLabel.CENTER);
setOpaque(true);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
setBackground(Color.lightGray);
}
/** Configures the button for the current cell, and returns it. */
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
setFont(table.getFont());
if (value != null) {
setText(value.toString());
}
return this;
}
} // private class RowHeaderRenderer extends JLabel implements
// TableCellRenderer
private class MultiLineHeaderRenderer extends JList implements TableCellRenderer {
private static final long serialVersionUID = -3697496960833719169L;
private final CompoundBorder subBorder =
new CompoundBorder(new MatteBorder(1, 0, 1, 0, java.awt.Color.darkGray),
new MatteBorder(1, 0, 1, 0, java.awt.Color.white));
private final CompoundBorder majorBorder =
new CompoundBorder(new MatteBorder(1, 1, 1, 0, java.awt.Color.darkGray),
new MatteBorder(1, 2, 1, 0, java.awt.Color.white));
Vector lines = new Vector();
int nMajorcolumns = 1;
int nSubcolumns = 1;
public MultiLineHeaderRenderer(int majorColumns, int subColumns) {
nMajorcolumns = majorColumns;
nSubcolumns = subColumns;
setOpaque(true);
setForeground(UIManager.getColor("TableHeader.foreground"));
setBackground(UIManager.getColor("TableHeader.background"));
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
setFont(table.getFont());
String str = (value == null) ? "" : value.toString();
BufferedReader br = new BufferedReader(new StringReader(str));
String line;
lines.clear();
try {
while ((line = br.readLine()) != null) {
lines.addElement(line);
}
}
catch (IOException ex) {
}
if ((column / nSubcolumns) * nSubcolumns == column) {
setBorder(majorBorder);
}
else {
setBorder(subBorder);
}
setListData(lines);
return this;
}
}
// ////////////////////////////////////////////////////////////////////////
// //
// The code below was added to deal with region references //
// Peter Cao, 4/30/2009 //
// //
// ////////////////////////////////////////////////////////////////////////
public void mouseClicked(MouseEvent e) {
// only deal with reg. ref
if (!(isRegRef || isObjRef)) return;
int eMod = e.getModifiers();
// provide two options here: double click to show data in table, or
// right mouse to choose to show data in table or in image
// right mouse click
if (e.isPopupTrigger()
|| (eMod == InputEvent.BUTTON3_MASK)
|| (System.getProperty("os.name").startsWith("Mac")
&& (eMod == (InputEvent.BUTTON1_MASK | InputEvent.CTRL_MASK)))) {
if (popupMenu != null) {
popupMenu.show((JComponent) e.getSource(), e.getX(), e.getY());
}
}
else if (e.getClickCount() == 2) {
// double click
viewType = ViewType.TABLE;
Object theData = null;
try {
theData = getDataObject();
}
catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), getTitle(), JOptionPane.ERROR_MESSAGE);
}
if (theData == null) {
toolkit.beep();
JOptionPane.showMessageDialog(this, "No data selected.", getTitle(), JOptionPane.ERROR_MESSAGE);
return;
}
int len = Array.getLength(theData);
for (int i = 0; i < len; i++) {
if (isRegRef)
showRegRefData((String) Array.get(theData, i));
else if (isObjRef)
showObjRefData(Array.getLong(theData, i));
}
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
/** creates a popup menu for a right mouse click on a data object */
private JPopupMenu createPopupMenu() {
JPopupMenu menu = new JPopupMenu();
JMenuItem item;
item = new JMenuItem("Show As Table");
item.setMnemonic(KeyEvent.VK_T);
item.addActionListener(this);
item.setActionCommand("Show data as table");
menu.add(item);
item = new JMenuItem("Show As Image");
item.setMnemonic(KeyEvent.VK_I);
item.addActionListener(this);
item.setActionCommand("Show data as image");
menu.add(item);
// item = new JMenuItem( "Show As Text");
// item.setMnemonic(KeyEvent.VK_I);
// item.addActionListener(this);
// item.setActionCommand("Show data as text");
// menu.add(item);
return menu;
}
/**
* Display data pointed by object references. Data of each object is shown
* in a separate spreadsheet.
*
* @param ref
* the array of strings that contain the reg. ref information.
*
*/
private void showObjRefData(long ref) {
long[] oid = { ref };
HObject obj = FileFormat.findObject(dataset.getFileFormat(), oid);
if (obj == null || !(obj instanceof ScalarDS)) return;
ScalarDS dset = (ScalarDS) obj;
ScalarDS dset_copy = null;
// create an instance of the dataset constructor
Constructor constructor = null;
Object[] paramObj = null;
Object data = null;
try {
Class[] paramClass = { FileFormat.class, String.class, String.class };
constructor = dset.getClass().getConstructor(paramClass);
paramObj = new Object[] { dset.getFileFormat(), dset.getName(), dset.getPath() };
dset_copy = (ScalarDS) constructor.newInstance(paramObj);
data = dset_copy.getData();
}
catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex, "Object Reference:" + getTitle(), JOptionPane.ERROR_MESSAGE);
data = null;
}
if (data == null) return;
// load each selection into a separate dataset and display it in
// a separate spreadsheet
StringBuffer titleSB = new StringBuffer();
Font font = this.getFont();
CompoundBorder border = BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(),
BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLUE, 3),
"Data pointed by object reference", TitledBorder.RIGHT, TitledBorder.TOP, font, Color.RED));
JInternalFrame dataView = null;
HashMap map = new HashMap(1);
map.put(ViewProperties.DATA_VIEW_KEY.OBJECT, dset_copy);
switch (viewType) {
case TEXT:
dataView = new DefaultTextView(viewer, map);
break;
case IMAGE:
dataView = new DefaultImageView(viewer, map);
break;
default:
dataView = new DefaultTableView(viewer, map);
break;
}
if (dataView != null) {
viewer.addDataView((DataView) dataView);
titleSB.append(dset_copy.getName());
titleSB.append(" - ");
titleSB.append(dset_copy.getPath());
titleSB.append(" - ");
titleSB.append(dataset.getFile());
dataView.setTitle(titleSB.toString());
dataView.setBorder(border);
}
}
/**
* Display data pointed by region references. Data of each region is shown
* in a separate spreadsheet. The reg. ref. information is stored in strings
* of the format below:
*
*
* - For point selections: "file_id:obj_id {
...) }",
* where is in the form of (location_of_dim0, location_of_dim1,
* ...). For example, 0:800 { (0,1) (2,11) (1,0) (2,4) }
* - For rectangle selections:
* "file_id:obj_id {
... }",
* where is in the form of
* (start_corner)-(oposite_corner). For example, 0:800 { (0,0)-(0,2)
* (0,11)-(0,13) (2,0)-(2,2) (2,11)-(2,13) }
*
*
* @param reg
* the array of strings that contain the reg. ref information.
*
*/
private void showRegRefData(String reg) {
boolean isPointSelection = false;
if (reg == null || reg.length() <= 0) return;
isPointSelection = (reg.indexOf('-') <= 0);
// find the object id
String oidStr = reg.substring(reg.indexOf(':') + 1, reg.indexOf(' '));
long oid[] = { -1 };
// decode object ID
try {
oid[0] = Long.valueOf(oidStr);
}
catch (Exception ex) {
return;
}
// decode the region selection
String regStr = reg.substring(reg.indexOf('{') + 1, reg.indexOf('}'));
if (regStr == null || regStr.length() <= 0) return; // no selection
StringTokenizer st = new StringTokenizer(regStr);
int nSelections = st.countTokens();
if (nSelections <= 0) return; // no selection
HObject obj = FileFormat.findObject(dataset.getFileFormat(), oid);
if (obj == null || !(obj instanceof ScalarDS)) return;
ScalarDS dset = (ScalarDS) obj;
ScalarDS dset_copy = null;
// create an instance of the dataset constructor
Constructor constructor = null;
Object[] paramObj = null;
try {
Class[] paramClass = { FileFormat.class, String.class, String.class };
constructor = dset.getClass().getConstructor(paramClass);
paramObj = new Object[] { dset.getFileFormat(), dset.getName(), dset.getPath() };
}
catch (Exception ex) {
constructor = null;
}
// load each selection into a separate dataset and display it in
// a separate spreadsheet
StringBuffer titleSB = new StringBuffer();
Font font = this.getFont();
CompoundBorder border = BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(),
BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.BLUE, 3),
"Data pointed by region reference", TitledBorder.RIGHT, TitledBorder.TOP, font, Color.RED));
while (st.hasMoreTokens()) {
try {
dset_copy = (ScalarDS) constructor.newInstance(paramObj);
}
catch (Exception ex) {
continue;
}
if (dset_copy == null) continue;
try {
dset_copy.init();
}
catch (Exception ex) {
continue;
}
int rank = dset_copy.getRank();
long start[] = dset_copy.getStartDims();
long count[] = dset_copy.getSelectedDims();
// set the selected dimension sizes based on the region selection
// info.
int idx = 0;
String sizeStr = null;
String token = st.nextToken();
titleSB.setLength(0);
titleSB.append(token);
titleSB.append(" at ");
token = token.replace('(', ' ');
token = token.replace(')', ' ');
if (isPointSelection) {
// point selection
StringTokenizer tmp = new StringTokenizer(token, ",");
while (tmp.hasMoreTokens()) {
count[idx] = 1;
sizeStr = tmp.nextToken().trim();
start[idx] = Long.valueOf(sizeStr);
idx++;
}
}
else {
// rectangle selection
String startStr = token.substring(0, token.indexOf('-'));
String endStr = token.substring(token.indexOf('-') + 1);
StringTokenizer tmp = new StringTokenizer(startStr, ",");
while (tmp.hasMoreTokens()) {
sizeStr = tmp.nextToken().trim();
start[idx] = Long.valueOf(sizeStr);
idx++;
}
idx = 0;
tmp = new StringTokenizer(endStr, ",");
while (tmp.hasMoreTokens()) {
sizeStr = tmp.nextToken().trim();
count[idx] = Long.valueOf(sizeStr) - start[idx] + 1;
idx++;
}
}
Object data = null;
try {
data = dset_copy.getData();
}
catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex, "Region Reference:" + getTitle(), JOptionPane.ERROR_MESSAGE);
data = null;
}
JInternalFrame dataView = null;
HashMap map = new HashMap(1);
map.put(ViewProperties.DATA_VIEW_KEY.OBJECT, dset_copy);
switch (viewType) {
case TEXT:
dataView = new DefaultTextView(viewer, map);
break;
case IMAGE:
dataView = new DefaultImageView(viewer, map);
break;
default:
dataView = new DefaultTableView(viewer, map);
break;
}
if (dataView != null) {
viewer.addDataView((DataView) dataView);
titleSB.append(dset_copy.getName());
titleSB.append(" - ");
titleSB.append(dset_copy.getPath());
titleSB.append(" - ");
titleSB.append(dataset.getFile());
dataView.setTitle(titleSB.toString());
dataView.setBorder(border);
}
} // while (st.hasMoreTokens())
} // private void showRegRefData(String reg)
}