📄 table.java
字号:
package org.uispec4j;
import junit.framework.Assert;
import junit.framework.AssertionFailedError;
import org.uispec4j.assertion.Assertion;
import org.uispec4j.utils.ArrayUtils;
import org.uispec4j.utils.ColorUtils;
import org.uispec4j.utils.Utils;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import java.awt.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* Wrapper for JTable components.<p/>
* The contents of the underlying table can be usually checked with String or Boolean values,
* as in the following example:
* <pre><code>
* assertTrue(table.contentEquals(new String[]{
* {"Bart", "Simpson"},
* {"Marge", "Simpson"}
* }));
* </code></pre>
* The conversion between the values (Strings) given in the test and the values
* actually displayed by the table renderer is performed by a dedicated
* {@link TableCellValueConverter}, which retrieves the graphical component that draws
* the table cells and determines the displayed value accordingly.
* A {@link DefaultTableCellValueConverter} is used by default by the Table component.
*/
public class Table extends AbstractUIComponent {
public static final String TYPE_NAME = "table";
public static final Class[] SWING_CLASSES = {JTable.class};
private JTable jTable;
private Header header = new Header();
private TableCellValueConverter defaultCellValueConverter = new DefaultTableCellValueConverter();
private Map cellValuesConvertersByColumn = new HashMap();
public Table(JTable table) {
this.jTable = table;
}
public String getDescriptionTypeName() {
return TYPE_NAME;
}
public Component getAwtComponent() {
return jTable;
}
public JTable getJTable() {
return jTable;
}
/**
* Returns a helper interface which gives access to the table header.
*/
public Header getHeader() {
return header;
}
/**
* Sets a new converter for analyzing the table cells content.
*/
public void setDefaultCellValueConverter(TableCellValueConverter cellValueConverter) {
this.defaultCellValueConverter = cellValueConverter;
}
/**
* Sets a new converter for analyzing the cells of a given column.
*/
public void setCellValueConverter(int column, TableCellValueConverter tableCellValueConverter) {
cellValuesConvertersByColumn.put(new Integer(column), tableCellValueConverter);
}
public void click(int row, int column) {
click(row, column, Key.Modifier.NONE);
}
public void click(int row, int column, Key.Modifier modifier) {
Rectangle rect = jTable.getCellRect(row, column, false);
Mouse.doClickInRectangle(this, rect, false, modifier);
}
public void rightClick(int row, int column) {
Rectangle rect = jTable.getCellRect(row, column, false);
Mouse.doClickInRectangle(this, rect, true, Key.Modifier.NONE);
}
public void doubleClick(int row, int column) {
Rectangle rect = jTable.getCellRect(row, column, false);
Mouse.doClickInRectangle(this, rect, false, Key.Modifier.NONE);
Mouse.doDoubleClickInRectangle(this, rect);
}
public Trigger triggerClick(final int row, final int column, final Key.Modifier modifier) {
return new Trigger() {
public void run() throws Exception {
click(row, column, modifier);
}
};
}
public Trigger triggerRightClick(final int row, final int column) {
return new Trigger() {
public void run() throws Exception {
rightClick(row, column);
}
};
}
public Trigger triggerDoubleClick(final int row, final int column) {
return new Trigger() {
public void run() throws Exception {
doubleClick(row, column);
}
};
}
public int getRowCount() {
return jTable.getRowCount();
}
public int getColumnCount() {
return jTable.getColumnCount();
}
/**
* Returns the object (String or Boolean) displayed in a given cell.<p/>
* The returned object is that returned by the current TableCellValueConverter
* used by the table.
*
* @see #setCellValueConverter(int, TableCellValueConverter)
* @see #setDefaultCellValueConverter(TableCellValueConverter)
*/
public Object getContentAt(int row, int column) {
return getValueAt(row, column);
}
/**
* Returns the displayed in a given cell using a specific converter.
*/
public Object getContentAt(int row, int column, TableCellValueConverter converter) {
return converter.getValue(row, column,
getComponent(row, column),
jTable.getValueAt(row, column));
}
/**
* Returns a {@link Cell} object for interacting with the content of an individual table cell.<p/>
* Sample usage:
* <pre><code>
* ComboBox comboBox = table.editCell(0, 0).getComboBox();
* assertTrue(comboBox.contentEquals(choices));
* comboBox.select("b");
* </code></pre>
*/
public Cell editCell(int row, int column) {
Assert.assertTrue("Cell (" + row + "," + column + ") is not editable",
jTable.isCellEditable(row, column));
Component cellEditor = getSwingEditorComponentAt(row, column);
JPanel cellPanel = new JPanel();
cellPanel.add(cellEditor);
return new Cell(cellPanel);
}
/**
* Represents a table cell. This class extends Panel, so that all the component searching
* methods available in Panel can be used to access the specific component displayed in the cell.
*/
public class Cell extends Panel {
public Cell(Container container) {
super(container);
}
}
/**
* Inputs some text in a given cell.<p/>
* This method only works when the underlying editor is a JTextField or a JComboBox -
* it will throw an exception if this is not the case, or if the cell is not editable.
* Please refer to {@link #editCell(int, int)} for a more flexible edition method.<p/>
*/
public void editCell(int row, int column, String value, boolean validateChange) {
if (!jTable.isCellEditable(row, column)) {
throw new RuntimeException("Cell (" + row + ", " + column + ") is not editable");
}
Component cellEditor = getSwingEditorComponentAt(row, column);
if (JTextField.class.isInstance(cellEditor)) {
JTextField textField = ((JTextField) cellEditor);
textField.setText(value);
if (validateChange) {
textField.postActionEvent();
}
}
else {
if (JComboBox.class.isInstance(cellEditor)) {
JComboBox jCombo = (JComboBox) cellEditor;
if (validateChange) {
ComboBox comboBox = new ComboBox(jCombo);
comboBox.select(value);
}
}
else {
throw new RuntimeException("Unexpected editor at (" + row + ", " + column + "): " + cellEditor.getClass().getName());
}
}
}
/**
* Checks that no header is displayed for this table.
*/
public Assertion hasHeader() {
return new Assertion() {
public void check() {
if (jTable.getTableHeader() == null) {
Assert.fail("The table contains an header");
}
}
};
}
/**
* Checks the values displayed in the table.<p/>
* Sample usage:
* <pre><code>
* assertTrue(table.contentEquals(new Object[][]{
* {"a", Boolean.TRUE, "3"},
* {"c", Boolean.FALSE, "4"}
* }));
* </code></pre>
* The conversion between the displayed values and the objects to
* be given in the array can be customized with
* {@link #setCellValueConverter(int, TableCellValueConverter)}
*/
public Assertion contentEquals(final Object[][] expected) {
return new Assertion() {
public void check() {
try {
Assert.assertEquals(expected.length, jTable.getRowCount());
for (int i = 0; i < expected.length; i++) {
checkRow(i, expected[i]);
}
}
catch (AssertionFailedError e) {
Assert.assertEquals(ArrayUtils.toString(expected), getContent());
throw e;
}
}
};
}
/**
* Checks the values displayed in the table for a given set of columns.
* @see #contentEquals(Object[][])
*/
public Assertion contentEquals(final String[] columnNames, final Object[][] expected) {
return new Assertion() {
public void check() throws Exception {
int rowCount = jTable.getRowCount();
if (expected.length != rowCount) {
throwError("Expected " + expected.length + " rows but found " + rowCount,
columnNames, expected);
}
for (int rowIndex = 0; rowIndex < expected.length; rowIndex++) {
Object[] row = expected[rowIndex];
if (columnNames.length != row.length) {
Assert.fail("Expected array should have " + columnNames.length + " elements for each row " +
"- invalid row " + rowIndex + ": " + ArrayUtils.toString(row));
}
for (int columnIndex = 0; columnIndex < columnNames.length; columnIndex++) {
int actualIndex = findColumnIndex(columnNames[columnIndex]);
if (!Utils.equals(expected[rowIndex][columnIndex], getValueAt(rowIndex, actualIndex))) {
throwError("Error at (" + rowIndex + ", " + columnIndex + ")", columnNames, expected);
}
}
}
}
};
}
private void throwError(String message, String[] columnNames, Object[][] expected) {
String actualContent = getContent(columnNames);
Assert.assertEquals(message, ArrayUtils.toString(expected), actualContent);
Assert.fail("Actual: " + actualContent);// in case the string comparison didn't fail
}
public Assertion rowEquals(final int rowIndex, final Object[] expectedRow) {
return new Assertion() {
public void check() {
if (rowIndex < 0) {
Assert.fail("Row index should be positive");
}
if (rowIndex >= jTable.getRowCount()) {
Assert.fail("Table contains only " + jTable.getRowCount() + " rows, unable to access row " + rowIndex);
}
try {
checkRow(rowIndex, expectedRow);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -