/*
* TableOfImages.java
*
* Created on June 29, 2006, 2:51 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package edu.mbl.jif.gui.imaging.array;
import edu.mbl.jif.gui.imaging.FrameImageDisplay;
import edu.mbl.jif.imaging.api.SeriesOfImages;
import edu.mbl.jif.imaging.series.SeriesOfImagesMultipageTiff;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableOfImages
extends JPanel // implements ListSelectionListener
{
JTable table;
JPopupMenu popup;
JMenuItem menuItem;
SeriesOfImages series;
public TableOfImages(SeriesOfImages series, int sampling, int sizeOfThumbs) {
int colWidth = sizeOfThumbs;
int rowHeight = sizeOfThumbs;
int nT = series.getTimeIntervals();
int nZ = series.getZSections();
Dimension dim = series.getImageDimensions();
if (dim.getWidth() >= dim.getHeight()) {
sampling = 1 + (int) dim.getWidth() / sizeOfThumbs;
colWidth = sizeOfThumbs;
rowHeight = (int) (sizeOfThumbs * dim.getHeight()
/ (float) dim.getWidth());
} else {
sampling = (int) dim.getHeight() / sizeOfThumbs;
rowHeight = sizeOfThumbs;
colWidth = (int) (sizeOfThumbs * dim.getWidth()
/ (float) dim.getHeight());
}
System.out.println(nT + " : " + nZ);
Object[][] data =
new Object[nZ][nT];
for (int t = 0; t < series.getTimeIntervals(); t++) {
for (int z = 0; z < series.getZSections(); z++) {
data[z][t] =
new ImageIcon(series.getAsThumbnail(t * nZ + z,
sampling));
}
}
// Column headers
Object[] column = new Object[nT];
for (int i = 0; i < nT; i++) {
column[i] = "t=" + String.valueOf(i + 1);
}
// Row headers
String[] rowHeaders = new String[nZ];
for (int i = 0; i < nZ; i++) {
rowHeaders[i] = "z=" + String.valueOf(i + 1);
}
createTableOfImages(data, column, colWidth, rowHeaders, rowHeight);
}
private void createTableOfImages(final Object[][] data, final Object[] column,
int colWidth, final String[] rowHeaders, int rowHeight) {
AbstractTableModel model = new AbstractTableModel() {
public int getColumnCount() {
return column.length;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return (String) column[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public Class getColumnClass(int col) {
return ImageIcon.class;
}
};
table = new JTable(model);
setImageObserver(table);
// Size
table.setRowHeight(rowHeight + 1);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); // makes horiz scrollable
// set all columns fixed width
colWidth = colWidth + 1;
int numCols = table.getColumnModel().getColumnCount();
for (int i = 0; i < numCols; i++) {
table.getColumnModel().getColumn(i).setPreferredWidth(colWidth);
table.getColumnModel().getColumn(i).setMinWidth(colWidth);
table.getColumnModel().getColumn(i).setMaxWidth(colWidth);
}
table.setIntercellSpacing(new Dimension(0, 0));
// Selection
table.setSelectionBackground(Color.gray);
table.setCellSelectionEnabled(true);
table.setRowSelectionAllowed(true);
table.setColumnSelectionAllowed(true);
//table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
//table.setDefaultRenderer(Object.class, new BorderCellRenderer());
// Add responses to actions
//ListSelectionModel listMod = table.getSelectionModel();
//listMod.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
//listMod.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
//listMod.addListSelectionListener(this);
SelectionListener listener = new SelectionListener(table);
table.getSelectionModel().addListSelectionListener(listener);
table.getColumnModel().getSelectionModel().addListSelectionListener(listener);
// Mouse Events
table.addMouseListener(new MouseAdapter() { // add DoubleClickability
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
System.out.println(" double click");
int r = table.getSelectedRow();
int c = table.getSelectedColumn();
System.out.println(r + "," + c);
// Open the image in viewer...
openImageViewer(series, r, c);
}
// Popup Menu
if (SwingUtilities.isRightMouseButton(e)) {
//int index = list.locationToIndex(e.getPoint());
popup.show(e.getComponent(), e.getX(), e.getY());
}
}
});
// PopUp Menus
ActionListener popupActionListener =
new ActionListener() {
public void actionPerformed(ActionEvent e) {
JMenuItem source = (JMenuItem) (e.getSource());
String action = source.getText();
if (action == "Open") {
//opPanel.openInViewer();
}
if (action == "Delete") {
//opPanel.delete();
}
}
};
popup = new JPopupMenu();
menuItem = new JMenuItem("Open");
menuItem.addActionListener(popupActionListener);
popup.add(menuItem);
menuItem = new JMenuItem("Delete");
menuItem.addActionListener(popupActionListener);
popup.add(menuItem);
// Row Headers
ListModel lmRHeader = new AbstractListModel() {
// String headers[] = {
// "a", "b", "c", "d", "e", "f", "g", "h", "i"};
public int getSize() {
return rowHeaders.length;
}
public Object getElementAt(int index) {
return rowHeaders[index];
}
};
JList rowHeader = new JList(lmRHeader);
rowHeader.setFixedCellWidth(20);
rowHeader.setFixedCellHeight(table.getRowHeight() + table.getRowMargin());
// + table.getIntercellSpacing().height);
rowHeader.setCellRenderer(new RowHeaderRenderer(table));
// Scroll Panel
JScrollPane pane = new JScrollPane(table);
pane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
pane.setRowHeaderView(rowHeader);
this.setLayout(new BorderLayout());
add(pane, BorderLayout.CENTER);
}
private void openImageViewer(SeriesOfImages series, int r, int c) {
int n = r + c * series.getZSections();
String title = "" + series.getFilename() + ": " + r + ", " + c + " (" + n + ")";
BufferedImage img = series.getImage(n);
(new FrameImageDisplay(img, title)).setVisible(true);
}
//------------------------------------------------------
private void setImageObserver(JTable table) {
TableModel model = table.getModel();
int colCount = model.getColumnCount();
int rowCount = model.getRowCount();
for (int col = 0; col < colCount; col++) {
if (ImageIcon.class == model.getColumnClass(col)) {
for (int row = 0; row < rowCount; row++) {
ImageIcon icon = (ImageIcon) model.getValueAt(row, col);
if (icon != null) {
icon.setImageObserver(new CellImageObserver(table, row,
col));
}
}
}
}
}
//--------------------------------------------------------------------
class CellImageObserver
implements ImageObserver {
JTable table;
int row, col;
CellImageObserver(JTable table, int row, int col) {
this.table = table;
this.row = row;
this.col = col;
}
public boolean imageUpdate(Image img, int flags,
int x, int y, int w, int h) {
if ((flags & (FRAMEBITS | ALLBITS)) != 0) {
Rectangle rect = table.getCellRect(row, col, false);
table.repaint(rect);
}
return (flags & (ALLBITS | ABORT)) == 0;
}
}
//------------------------------------------------------
// public void valueChanged (ListSelectionEvent e) {
// int maxRows;
// int[] selRows;
// int[] selCols;
// Object value;
// System.out.println(e.toString());
// if (!e.getValueIsAdjusting()) {
// selRows = table.getSelectedRows();
// selCols = table.getSelectedColumns();
// for (int i = 0; i < selRows.length; i++) {
// System.out.print(selRows[i] + ", ");
// }
// System.out.println("");
// for (int i = 0; i < selCols.length; i++) {
// System.out.println(selCols[i] + ", ");
// }
//
// }
// if (selRows.length > 0) {
// for (int i = 0; i < 3; i++) {
// // get Table data
// TableModel tm = table.getModel();
// value = tm.getValueAt(selRows[0], i);
// System.out.println("Selection : " + value);
// }
// System.out.println();
// }
// }
//-------------------------------------------------------------------
class SelectionListener
implements ListSelectionListener {
JTable table;
// It is necessary to keep the table since it is not possible
// to determine the table from the event's source
SelectionListener(final JTable table) {
this.table = table;
}
public void valueChanged(ListSelectionEvent e) {
// If cell selection is enabled, both row and column change events are fired
System.out.println(e.toString());
if (e.getSource() == table.getSelectionModel() && table.getRowSelectionAllowed()) {
// Column selection changed
int first = e.getFirstIndex();
int last = e.getLastIndex();
System.out.println("Col: " + first + " - " + last);
} else if (e.getSource() == table.getColumnModel().getSelectionModel()
&& table.getColumnSelectionAllowed()) {
// Row selection changed
int first = e.getFirstIndex();
int last = e.getLastIndex();
System.out.println("Row: " + first + " - " + last);
}
if (e.getValueIsAdjusting()) {
// The mouse button has not yet been released
}
}
}
//--------------------------------------------------------------------------
class RowHeaderRenderer
extends JLabel
implements ListCellRenderer {
RowHeaderRenderer(JTable table) {
JTableHeader header = table.getTableHeader();
setOpaque(true);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
setHorizontalAlignment(CENTER);
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
public Component getListCellRendererComponent(JList list,
Object value, int index, boolean isSelected,
boolean cellHasFocus) {
setText((value == null) ? "" : value.toString());
return this;
}
}
//--------------------------------------------------------------------
public static void main(String[] args) {
// @todo open selected image on double click.
//String FILE = "./test-images/Z5_T10.tif";
//String FILE = "xyzt-200x200x10x15.tif";
//"Series_TZ\\STAPS_04_0621_1451_54.tif";
//"Series_TZ\\xyzt-200x200x10x15_b.tif";
// "Series_TZ\\31Aug95.Newt3Lamellap.tif";
String FILE = "./test-images/HyperStack.tif";
int zSections = 5; // Number of Z-sections
int sampling = 3; // for thumbnails
int sizeOfThumbs = 256;
SeriesOfImages series = new SeriesOfImagesMultipageTiff(FILE, zSections);
TableOfImages table = new TableOfImages(series, sampling, sizeOfThumbs);
JFrame frame = new JFrame("ImageTableTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(table, BorderLayout.CENTER);
frame.setSize(300, 150);
frame.setVisible(true);
}
}//=================================================================================
/*
e941. Programmatically Making Selections in a JTable Component
To select columns, setColumnSelectionInterval(), addColumnSelectionInterval(), and removeColumnSelectionInterval() are available. However, these only work if columnSelectionAllowed is true and rowSelectionAllowed is false. This also applies to rows.
To select individual cells or blocks of cells, use changeSelection(). However, both columnSelectionAllowed and rowSelectionAllowed must be false.
These selection methods observe the setting of the selection mode. For example, if the selection mode is SINGLE_SELECTION, only a single row, column, or cell can be made. See e940 Enabling Single or Multiple Selections in a JTable Component for more information on selection modes.
int rows = 10;
int cols = 5;
JTable table = new JTable(rows, cols);
// Use this mode to demonstrate the following examples
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
// The following column selection methods work only if these
// properties are set this way
table.setColumnSelectionAllowed(true);
table.setRowSelectionAllowed(false);
// Select a column - column 0
table.setColumnSelectionInterval(0, 0);
// Select an additional range of columns - columns 1 to 2
table.addColumnSelectionInterval(1, 2);
// Deselect a range of columns - columns 0 to 1
table.removeColumnSelectionInterval(0, 1);
// The following row selection methods work only if these
// properties are set this way
table.setColumnSelectionAllowed(false);
table.setRowSelectionAllowed(true);
// Select a row - row 0
table.setRowSelectionInterval(0, 0);
// Select an additional range of rows - rows 1 to 2
table.addRowSelectionInterval(1, 2);
// Deselect a range of rows - rows 0 to 1
table.removeRowSelectionInterval(0, 1);
// The following cell selection methods work only if these
// properties are set this way
table.setColumnSelectionAllowed(true);
table.setRowSelectionAllowed(true);
// Select a cell: cell (2,1)
int row = 2;
int col = 1;
boolean toggle = false;
boolean extend = false;
table.changeSelection(row, col, toggle, extend);
// Extend the selection to include all cells between (2,1) to (5,3)
row = 5;
col = 3;
toggle = false;
extend = true;
table.changeSelection(row, col, toggle, extend);
// Deselect a cell: cell (3,2)
// All cells in the row and column containing (3,2) are deselected.
row = 3;
col = 2;
toggle = true;
extend = false;
table.changeSelection(row, col, toggle, extend);
// This method actually toggles the selection state so that
// if it were called again, it exactly reverses the first call.
// Select cell (3,2) as well as the other cells that
// were deselected in the first call.
toggle = true;
extend = false;
table.changeSelection(row, col, toggle, extend);
// Select all cells
table.selectAll();
// Deselect all cells
table.clearSelection();
*/
/*
e964. Listening for Selection Events in a JTable Component
To listen for selection changes, you need to add a listener to both the JTable's table model and to the table column model.
A selection change event has a first and last property that specifies the range of affected rows (or columns). For example, if the 5th row is selected and the user selects the 7th row, the first property is 4 and the last is property 6. There is not enough information in the event to determine exactly which cells have changed. See e942 Getting the Selected Cells in a JTable Component for an example of how to determine the selected cells.
Changing the selection programmatically (see e941 Programmatically Making Selections in a JTable Component) causes selection change events to be fired.
SelectionListener listener = new SelectionListener(table);
table.getSelectionModel().addListSelectionListener(listener);
table.getColumnModel().getSelectionModel()
.addListSelectionListener(listener);
public class SelectionListener implements ListSelectionListener {
JTable table;
// It is necessary to keep the table since it is not possible
// to determine the table from the event's source
SelectionListener(JTable table) {
this.table = table;
}
public void valueChanged(ListSelectionEvent e) {
// If cell selection is enabled, both row and column change events are fired
if (e.getSource() == table.getSelectionModel()
&& table.getRowSelectionAllowed()) {
// Column selection changed
int first = e.getFirstIndex();
int last = e.getLastIndex();
} else if (e.getSource() == table.getColumnModel().getSelectionModel()
&& table.getColumnSelectionAllowed() ){
// Row selection changed
int first = e.getFirstIndex();
int last = e.getLastIndex();
}
if (e.getValueIsAdjusting()) {
// The mouse button has not yet been released
}
}
}
*/
/*
e967. Listening for Clicks on a Column Header in a JTable Component
int rows = 10;
int cols = 5;
JTable table = new JTable(rows, cols);
JTableHeader header = table.getTableHeader();
header.addMouseListener(new ColumnHeaderListener());
public class ColumnHeaderListener extends MouseAdapter {
public void mouseClicked(MouseEvent evt) {
JTable table = ((JTableHeader)evt.getSource()).getTable();
TableColumnModel colModel = table.getColumnModel();
// The index of the column whose header was clicked
int vColIndex = colModel.getColumnIndexAtX(evt.getX());
int mColIndex = table.convertColumnIndexToModel(vColIndex);
// Return if not clicked on any column header
if (vColIndex == -1) {
return;
}
// Determine if mouse was clicked between column heads
Rectangle headerRect = table.getTableHeader().getHeaderRect(vColIndex);
if (vColIndex == 0) {
headerRect.width -= 3; // Hard-coded constant
} else {
headerRect.grow(-3, 0); // Hard-coded constant
}
if (!headerRect.contains(evt.getX(), evt.getY())) {
// Mouse was clicked between column heads
// vColIndex is the column head closest to the click
// vLeftColIndex is the column head to the left of the click
int vLeftColIndex = vColIndex;
if (evt.getX() < headerRect.x) {
vLeftColIndex--;
}
}
}
}
*/
/*
e942. Getting the Selected Cells in a JTable Component
The method for determining the selected cells depends on whether column, row, or cell selection is enabled.
JTable table = new JTable();
if (table.getColumnSelectionAllowed()
&& !table.getRowSelectionAllowed()) {
// Column selection is enabled
// Get the indices of the selected columns
int[] vColIndices = table.getSelectedColumns();
} else if (!table.getColumnSelectionAllowed()
&& table.getRowSelectionAllowed()) {
// Row selection is enabled
// Get the indices of the selected rows
int[] rowIndices = table.getSelectedRows();
} else if (table.getCellSelectionEnabled()) {
// Individual cell selection is enabled
// In SINGLE_SELECTION mode, the selected cell can be retrieved using
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
int rowIndex = table.getSelectedRow();
int colIndex = table.getSelectedColumn();
// In the other modes, the set of selected cells can be retrieved using
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
// Get the min and max ranges of selected cells
int rowIndexStart = table.getSelectedRow();
int rowIndexEnd = table.getSelectionModel().getMaxSelectionIndex();
int colIndexStart = table.getSelectedColumn();
int colIndexEnd = table.getColumnModel().getSelectionModel()
.getMaxSelectionIndex();
// Check each cell in the range
for (int r=rowIndexStart; r<=rowIndexEnd; r++) {
for (int c=colIndexStart; c<=colIndexEnd; c++) {
if (table.isCellSelected(r, c)) {
// cell is selected
}
}
}
}
*/
/*
e940. Enabling Single or Multiple Selections in a JTable Component
By default, a table component allows multiple selections. To control the selection behavior, see e939 Enabling Row, Column, or Cell Selections in a JTable Component.
JTable table = new JTable();
// Get default selection mode
int selMode = table.getSelectionModel().getSelectionMode();
// MULTIPLE_INTERVAL_SELECTION
// Allow only single a selection
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// Allow selection to span one contiguous set of rows,
// visible columns, or block of cells
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
// Allow multiple selections of rows, visible columns, or cell blocks (default)
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
*///---------------------------------------------------------------------------
// Row Headers
/*
package tame.examples;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.AbstractListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
// derived from @author Nobuo Tamemasa @version 1.0 11/09/98
public class RowHeaderExample extends JFrame {
public RowHeaderExample() {
super( "Row Header Example" );
setSize( 300, 150 );
ListModel lm = new AbstractListModel() {
String headers[] = {"a", "b", "c", "d", "e", "f", "g", "h", "i"};
public int getSize() { return headers.length; }
public Object getElementAt(int index) {
return headers[index];
}
};
DefaultTableModel dm = new DefaultTableModel(lm.getSize(),10);
JTable table = new JTable( dm );
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JList rowHeader = new JList(lm);
rowHeader.setFixedCellWidth(50);
rowHeader.setFixedCellHeight(table.getRowHeight()
+ table.getRowMargin());
// + table.getIntercellSpacing().height);
rowHeader.setCellRenderer(new RowHeaderRenderer(table));
JScrollPane scroll = new JScrollPane( table );
scroll.setRowHeaderView(rowHeader);
getContentPane().add(scroll, BorderLayout.CENTER);
}
public static void main(String[] args) {
RowHeaderExample frame = new RowHeaderExample();
frame.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit(0);
}
});
frame.setVisible(true);
}
}
class RowHeaderRenderer extends JLabel implements ListCellRenderer {
RowHeaderRenderer(JTable table) {
JTableHeader header = table.getTableHeader();
setOpaque(true);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
setHorizontalAlignment(CENTER);
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
public Component getListCellRendererComponent( JList list,
Object value, int index, boolean isSelected, boolean cellHasFocus) {
setText((value == null) ? "" : value.toString());
return this;
}
}
*/