8197554: Create test for SwingSet TableDemo
Reviewed-by: serb
This commit is contained in:
parent
a359ed6dcf
commit
e6587461a4
349
test/jdk/sanity/client/SwingSet/src/TableDemoTest.java
Normal file
349
test/jdk/sanity/client/SwingSet/src/TableDemoTest.java
Normal file
@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import static com.sun.swingset3.demos.table.TableDemo.COLUMN1_NAME;
|
||||
import static com.sun.swingset3.demos.table.TableDemo.COLUMN2_NAME;
|
||||
import static com.sun.swingset3.demos.table.TableDemo.COLUMN3_NAME;
|
||||
import static com.sun.swingset3.demos.table.TableDemo.COLUMN4_NAME;
|
||||
import static com.sun.swingset3.demos.table.TableDemo.DEMO_TITLE;
|
||||
import static com.sun.swingset3.demos.table.TableDemo.ROW_HEIGHT;
|
||||
import static org.jemmy2ext.JemmyExt.EXACT_STRING_COMPARATOR;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JTable;
|
||||
|
||||
import org.jtregext.GuiTestListener;
|
||||
import org.netbeans.jemmy.ClassReference;
|
||||
import org.netbeans.jemmy.operators.JCheckBoxOperator;
|
||||
import org.netbeans.jemmy.operators.JFrameOperator;
|
||||
import org.netbeans.jemmy.operators.JTableHeaderOperator;
|
||||
import org.netbeans.jemmy.operators.JTableOperator;
|
||||
import org.netbeans.jemmy.operators.JTextFieldOperator;
|
||||
import org.testng.annotations.Listeners;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.sun.swingset3.demos.table.OscarCandidate;
|
||||
import com.sun.swingset3.demos.table.OscarTableModel;
|
||||
import com.sun.swingset3.demos.table.TableDemo;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @key headful
|
||||
* @summary Verifies SwingSet3 TableDemo page by checking different properties
|
||||
* of the JTable like number of row, number of columns and actions like
|
||||
* selection of cell, sorting based on column, filtering based on text and
|
||||
* moving of the column
|
||||
*
|
||||
* @library /sanity/client/lib/jemmy/src
|
||||
* @library /sanity/client/lib/Extensions/src
|
||||
* @library /sanity/client/lib/SwingSet3/src
|
||||
* @modules java.desktop
|
||||
* java.logging
|
||||
* @build org.jemmy2ext.JemmyExt
|
||||
* @build com.sun.swingset3.demos.table.TableDemo
|
||||
* @run testng TableDemoTest
|
||||
*/
|
||||
@Listeners(GuiTestListener.class)
|
||||
public class TableDemoTest {
|
||||
|
||||
private final static int MAX_ROW_COUNT = 524;
|
||||
private final static int MAX_COL_COUNT = 4;
|
||||
|
||||
private final static String FILTER_TEXT = "Sunrise";
|
||||
private final static String FILTER_RESET_TEXT = "";
|
||||
|
||||
private final static int [] SELECT_ROW_INDICES ={10, 11, 18};
|
||||
|
||||
private final static int MOVE_COL_START_INDEX = 1;
|
||||
private final static int MOVE_COL_END_INDEX = 2;
|
||||
private final static String MOVE_COL_VAL_TEXT1 = "Sunrise";
|
||||
private final static String MOVE_COL_VAL_TEXT2 = "Most Unique Artistic Picture";
|
||||
private final static int MOVE_COL_VAL_ROW = 0;
|
||||
|
||||
private final static int SORT_COL = 1;
|
||||
private final static int[] SORT_VAL_ROWS =new int[] {0, 250, 523};
|
||||
private final static String[][] ASC_PRE_SORT_ROW_VAL = new String[][] {
|
||||
{"1928", "Best Actor", "The Way of All Flesh", "[Emil Jannings]"},
|
||||
{"1933", "Best Director", "Cavalcade", "[Frank Lloyd]"},
|
||||
{"1936", "Best Engineering Effects", "My Man Godfrey", "[Eric Hatch, Morris Ryskind]"}};
|
||||
private final static String[][] ASC_POST_SORT_ROW_VAL = new String[][] {
|
||||
{"1928", "Best Actor", "The Way of All Flesh", "[Emil Jannings]"},
|
||||
{"1936", "Best Director", "My Man Godfrey", "[Gregory La Cava]"},
|
||||
{"1928", "Most Unique Artistic Picture", "The Crowd", "[]"}};
|
||||
private final static String[][] DESC_POST_SORT_ROW_VAL = new String[][] {
|
||||
{"1928", "Most Unique Artistic Picture", "Sunrise", "[]"},
|
||||
{"1934", "Best Engineering Effects", "Viva Villa!", "[Ben Hecht]"},
|
||||
{"1936", "Best Actor", "San Francisco", "[Spencer Tracy]"}};
|
||||
|
||||
/**
|
||||
* Tests the different properties of JTable like number of rows, number
|
||||
* of columns and actions like selection of cell, sorting based on column,
|
||||
* filtering based on text and moving of the column.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
|
||||
new ClassReference(TableDemo.class.getCanonicalName()).startApplication();
|
||||
|
||||
JFrameOperator frameOperator = new JFrameOperator(DEMO_TITLE);
|
||||
frameOperator.setComparator(EXACT_STRING_COMPARATOR);
|
||||
frameOperator.setVerification(true);
|
||||
JTableOperator tableOperator = new JTableOperator(frameOperator);
|
||||
JTableHeaderOperator tableHeaderOperator = new JTableHeaderOperator(frameOperator);
|
||||
|
||||
checkTableBasicProperties(tableOperator);
|
||||
checkCellSelection(tableOperator);
|
||||
checkSortTable(tableOperator, tableHeaderOperator);
|
||||
checkMoveColumn(tableOperator, tableHeaderOperator);
|
||||
checkFilterTable(frameOperator, tableOperator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the table basic properties number of columns, rows and row height
|
||||
*
|
||||
* @param tableOperator
|
||||
*/
|
||||
private void checkTableBasicProperties(JTableOperator tableOperator) {
|
||||
tableOperator.waitStateOnQueue(comp
|
||||
-> MAX_COL_COUNT == ((JTable)comp).getColumnCount());
|
||||
waitRowCount(tableOperator, MAX_ROW_COUNT);
|
||||
tableOperator.waitStateOnQueue(comp
|
||||
-> ROW_HEIGHT == ((JTable)comp).getRowHeight());
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects one table cell and verifies the selected cell's row number and column number
|
||||
*
|
||||
* @param tableOperator
|
||||
*/
|
||||
private void checkCellSelection(JTableOperator tableOperator) {
|
||||
int noOfColumns = tableOperator.getColumnCount();
|
||||
for (int i = 0; i < SELECT_ROW_INDICES.length; i++) {
|
||||
int rowIndex = SELECT_ROW_INDICES[i];
|
||||
for (int j = 0; j < noOfColumns; j++) {
|
||||
int colIndex = j;
|
||||
tableOperator.clickOnCell(rowIndex, colIndex);
|
||||
tableOperator.waitStateOnQueue(comp
|
||||
-> rowIndex == ((JTable)comp).getSelectedRow() &&
|
||||
colIndex == ((JTable)comp).getSelectedColumn());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter table based on specific text and winners check box, and verifies row count
|
||||
*
|
||||
* @param frameOperator
|
||||
* @param tableOperator
|
||||
*/
|
||||
private void checkFilterTable(JFrameOperator frameOperator,
|
||||
JTableOperator tableOperator) {
|
||||
|
||||
int [] filterRowCount = getFilteredCount(tableOperator, FILTER_TEXT);
|
||||
JTextFieldOperator filterField = new JTextFieldOperator(frameOperator);
|
||||
JCheckBoxOperator winnersCheckbox = new JCheckBoxOperator(frameOperator);
|
||||
|
||||
// Filtering based on FILTER_TEXT
|
||||
filterField.setText(FILTER_TEXT);
|
||||
waitRowCount(tableOperator, filterRowCount[0]);
|
||||
|
||||
// Filtering based on WinnersCheckbox
|
||||
winnersCheckbox.setSelected(true);
|
||||
waitRowCount(tableOperator, filterRowCount[1]);
|
||||
|
||||
// Resets the winners check box
|
||||
winnersCheckbox.setSelected(false);
|
||||
waitRowCount(tableOperator, filterRowCount[0]);
|
||||
|
||||
// Resets the filter text field
|
||||
filterField.setText(FILTER_RESET_TEXT);
|
||||
waitRowCount(tableOperator, MAX_ROW_COUNT);
|
||||
|
||||
}
|
||||
|
||||
private int[] getFilteredCount(JTableOperator tableOperator, String filterText){
|
||||
OscarTableModel tableModel = (OscarTableModel)tableOperator.getModel();
|
||||
int noOfRows = tableModel.getRowCount();
|
||||
int filteredRowCount = 0;
|
||||
int filteredWinnersRowCount = 0;
|
||||
for (int i = 0; i < noOfRows; i++) {
|
||||
OscarCandidate candidate = tableModel.getCandidate(i);
|
||||
if(isMovieOrPersonsContainsText(candidate, filterText)){
|
||||
filteredRowCount++;
|
||||
if(candidate.isWinner()) {
|
||||
filteredWinnersRowCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new int[] {filteredRowCount, filteredWinnersRowCount};
|
||||
}
|
||||
|
||||
private boolean isMovieOrPersonsContainsText(
|
||||
OscarCandidate candidate, String filterText){
|
||||
String movie = candidate.getMovieTitle();
|
||||
if(movie != null && movie.contains(filterText)) {
|
||||
return true;
|
||||
} else {
|
||||
List<String> persons = candidate.getPersons();
|
||||
for (String person : persons) {
|
||||
if(person != null && person.contains(filterText)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves to swap the columns, move again to reset back, verify column name
|
||||
* and cell values in both the scenarios.
|
||||
*
|
||||
* @param tableOperator
|
||||
* @param tableHeaderOperator
|
||||
*/
|
||||
private void checkMoveColumn(JTableOperator tableOperator,
|
||||
JTableHeaderOperator tableHeaderOperator) {
|
||||
|
||||
String[] columnNames = {COLUMN1_NAME, COLUMN3_NAME, COLUMN2_NAME, COLUMN4_NAME};
|
||||
// Moving the column from 'start index' to 'end index'
|
||||
moveColumn(tableOperator, tableHeaderOperator, columnNames,
|
||||
MOVE_COL_START_INDEX, MOVE_COL_END_INDEX);
|
||||
|
||||
// Resets the columns to original position(from 'end index' to 'start index')
|
||||
columnNames[1] = COLUMN2_NAME;
|
||||
columnNames[2] = COLUMN3_NAME;
|
||||
moveColumn(tableOperator, tableHeaderOperator, columnNames,
|
||||
MOVE_COL_END_INDEX, MOVE_COL_START_INDEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves to swap the columns, verify column name and cell values.
|
||||
*
|
||||
* @param tableOperator
|
||||
* @param tableHeaderOperator
|
||||
* @param columnNames
|
||||
* @param moveCol
|
||||
* @param moveToCol
|
||||
*/
|
||||
private void moveColumn(JTableOperator tableOperator, JTableHeaderOperator tableHeaderOperator,
|
||||
String[] columnNames, int moveCol, int moveToCol){
|
||||
|
||||
tableHeaderOperator.moveColumn(moveCol, moveToCol);
|
||||
checkColumnNames(tableOperator, columnNames);
|
||||
tableOperator.waitCell(MOVE_COL_VAL_TEXT1, MOVE_COL_VAL_ROW, moveCol);
|
||||
tableOperator.waitCell(MOVE_COL_VAL_TEXT2, MOVE_COL_VAL_ROW, moveToCol);
|
||||
}
|
||||
|
||||
private void checkColumnNames(JTableOperator tableOperator, String[] columnNames) {
|
||||
for (int i = 0; i < tableOperator.getColumnCount(); i++) {
|
||||
int columnIndex = i;
|
||||
tableOperator.waitStateOnQueue(comp -> columnNames[columnIndex].equals(
|
||||
((JTable)comp).getColumnModel().getColumn(columnIndex).getHeaderValue()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the table based on one particular column in ascending and descending order,
|
||||
* and verifies cell values
|
||||
*
|
||||
* @param tableOperator
|
||||
* @param tableHeaderOperator
|
||||
*/
|
||||
private void checkSortTable(JTableOperator tableOperator,
|
||||
JTableHeaderOperator tableHeaderOperator) {
|
||||
|
||||
// Verifying the row values before sort
|
||||
checkTableRows(tableOperator, ASC_PRE_SORT_ROW_VAL);
|
||||
|
||||
// Getting all award category values before stating the sort
|
||||
// to prepare the expected result
|
||||
ArrayList<String> awardCats = new ArrayList<>();
|
||||
for (int i = 0; i < tableOperator.getRowCount(); i++) {
|
||||
awardCats.add((String) tableOperator.getValueAt(i, SORT_COL));
|
||||
}
|
||||
// Sorting awardCats(expected result) in ascending order
|
||||
awardCats.sort((s1, s2) -> s1.compareTo(s2));
|
||||
|
||||
// Sorting table based on column 'Award Category' in ascending order
|
||||
sortTable(tableOperator, tableHeaderOperator, awardCats,
|
||||
ASC_POST_SORT_ROW_VAL);
|
||||
|
||||
// Sorting awardCats(expected result) in descending order
|
||||
awardCats.sort((s1, s2) -> s2.compareTo(s1));
|
||||
// Sorting table based on column 'Award Category' in descending order
|
||||
sortTable(tableOperator, tableHeaderOperator, awardCats,
|
||||
DESC_POST_SORT_ROW_VAL);
|
||||
|
||||
}
|
||||
|
||||
private void checkColumnSorted(JTableOperator tableOperator,
|
||||
ArrayList<String> awardCatExp){
|
||||
ArrayList<String> awardCatActual = new ArrayList<>();
|
||||
for (int i = 0; i < tableOperator.getRowCount(); i++) {
|
||||
awardCatActual.add((String) tableOperator.getValueAt(i, SORT_COL));
|
||||
}
|
||||
tableOperator.waitStateOnQueue(comp -> awardCatExp.equals(awardCatActual));
|
||||
}
|
||||
|
||||
private void checkTableRows(JTableOperator tableOperator, String[][] rowValues) {
|
||||
for (int i = 0; i < SORT_VAL_ROWS.length; i++) {
|
||||
tableOperator.waitCell(rowValues[i][0], SORT_VAL_ROWS[i], 0);
|
||||
tableOperator.waitCell(rowValues[i][1], SORT_VAL_ROWS[i], 1);
|
||||
tableOperator.waitCell(rowValues[i][2], SORT_VAL_ROWS[i], 2);
|
||||
tableOperator.waitCell(rowValues[i][3], SORT_VAL_ROWS[i], 3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts the table based on one particular column and verifies cell values
|
||||
*
|
||||
* @param tableOperator
|
||||
* @param tableHeaderOperator
|
||||
* @param awardCatExp
|
||||
* @param rowValues
|
||||
*/
|
||||
private void sortTable(JTableOperator tableOperator, JTableHeaderOperator tableHeaderOperator,
|
||||
ArrayList<String> awardCatExp, String[][] rowValues) {
|
||||
|
||||
tableHeaderOperator.selectColumn(SORT_COL);
|
||||
checkColumnSorted(tableOperator, awardCatExp);
|
||||
// Verifying the row values after sort
|
||||
checkTableRows(tableOperator, rowValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits the number of rows on table equal to the count specified
|
||||
*
|
||||
* @param tableOperator
|
||||
* @param count
|
||||
*/
|
||||
private void waitRowCount(JTableOperator tableOperator, int count) {
|
||||
tableOperator.waitStateOnQueue(comp
|
||||
-> count == ((JTable)comp).getRowCount());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,326 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.swingset3.demos.table;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
import com.sun.swingset3.demos.JHyperlink;
|
||||
|
||||
/**
|
||||
* Table renderer which renders cell value as hyperlink with optional rollover underline.
|
||||
*
|
||||
* @author aim
|
||||
*/
|
||||
public class HyperlinkCellRenderer extends JHyperlink implements TableCellRenderer {
|
||||
private JTable table;
|
||||
private final ArrayList<Integer> columnModelIndeces = new ArrayList<Integer>();
|
||||
|
||||
private Color rowColors[];
|
||||
private Color foreground;
|
||||
private Color visitedForeground;
|
||||
private Border focusBorder;
|
||||
private Border noFocusBorder;
|
||||
|
||||
private boolean underlineOnRollover = true;
|
||||
|
||||
private transient int hitColumnIndex = -1;
|
||||
private transient int hitRowIndex = -1;
|
||||
|
||||
private HashMap<Object, int[]> visitedCache;
|
||||
|
||||
public HyperlinkCellRenderer(Action action, boolean underlineOnRollover) {
|
||||
setAction(action);
|
||||
setHorizontalAlignment(JHyperlink.LEFT);
|
||||
rowColors = new Color[1];
|
||||
rowColors[0] = UIManager.getColor("Table.background");
|
||||
this.underlineOnRollover = underlineOnRollover;
|
||||
applyDefaults();
|
||||
}
|
||||
|
||||
public void setRowColors(Color[] colors) {
|
||||
this.rowColors = colors;
|
||||
}
|
||||
|
||||
public void updateUI() {
|
||||
super.updateUI();
|
||||
applyDefaults();
|
||||
}
|
||||
|
||||
protected void applyDefaults() {
|
||||
setOpaque(true);
|
||||
setBorderPainted(false);
|
||||
foreground = UIManager.getColor("Hyperlink.foreground");
|
||||
visitedForeground = UIManager.getColor("Hyperlink.visitedForeground");
|
||||
|
||||
// Make sure border used on non-focussed cells is same size as focussed border
|
||||
focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
|
||||
if (focusBorder != null) {
|
||||
Insets insets = focusBorder.getBorderInsets(this);
|
||||
noFocusBorder = new EmptyBorder(insets.top, insets.left, insets.bottom, insets.right);
|
||||
} else {
|
||||
focusBorder = noFocusBorder = new EmptyBorder(1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
if (this.table == null) {
|
||||
this.table = table;
|
||||
HyperlinkMouseListener hyperlinkListener = new HyperlinkMouseListener();
|
||||
table.addMouseMotionListener(hyperlinkListener);
|
||||
table.addMouseListener(hyperlinkListener);
|
||||
}
|
||||
int columnModelIndex = table.getColumnModel().getColumn(column).getModelIndex();
|
||||
if (!columnModelIndeces.contains(columnModelIndex)) {
|
||||
columnModelIndeces.add(columnModelIndex);
|
||||
}
|
||||
|
||||
if (value instanceof Link) {
|
||||
Link link = (Link) value;
|
||||
setText(link.getDisplayText());
|
||||
setToolTipText(link.getDescription());
|
||||
} else {
|
||||
setText(value != null ? value.toString() : "");
|
||||
}
|
||||
setVisited(isCellLinkVisited(value, row, column));
|
||||
setDrawUnderline(!underlineOnRollover ||
|
||||
(row == hitRowIndex && column == hitColumnIndex));
|
||||
|
||||
if (!isSelected) {
|
||||
setBackground(rowColors[row % rowColors.length]);
|
||||
//setForeground(isCellLinkVisited(value, row, column)?
|
||||
// visitedForeground : foreground);
|
||||
setForeground(foreground);
|
||||
setVisitedForeground(visitedForeground);
|
||||
} else {
|
||||
setBackground(table.getSelectionBackground());
|
||||
setForeground(table.getSelectionForeground());
|
||||
setVisitedForeground(table.getSelectionForeground());
|
||||
}
|
||||
//setBorder(hasFocus? focusBorder : noFocusBorder);
|
||||
//System.out.println("border insets="+getBorder().getBorderInsets(this));
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
protected void setCellLinkVisited(Object value, int row, int column) {
|
||||
if (!isCellLinkVisited(value, row, column)) {
|
||||
if (value instanceof Link) {
|
||||
((Link) value).setVisited(true);
|
||||
} else {
|
||||
if (visitedCache == null) {
|
||||
visitedCache = new HashMap<Object, int[]>();
|
||||
}
|
||||
int position[] = new int[2];
|
||||
position[0] = table.convertRowIndexToModel(row);
|
||||
position[1] = table.convertColumnIndexToModel(column);
|
||||
visitedCache.put(value, position);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isCellLinkVisited(Object value, int row, int column) {
|
||||
if (value instanceof Link) {
|
||||
return ((Link) value).isVisited();
|
||||
}
|
||||
if (visitedCache != null) {
|
||||
int position[] = visitedCache.get(value);
|
||||
if (position != null) {
|
||||
return position[0] == table.convertRowIndexToModel(row) &&
|
||||
position[1] == table.convertColumnIndexToModel(column);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getActiveHyperlinkRow() {
|
||||
return hitRowIndex;
|
||||
}
|
||||
|
||||
public int getActiveHyperlinkColumn() {
|
||||
return hitColumnIndex;
|
||||
}
|
||||
|
||||
// overridden because the AbstractButton's version forces the source of the event
|
||||
// to be the AbstractButton and we want a little more freedom to configure the
|
||||
// event
|
||||
@Override
|
||||
protected void fireActionPerformed(ActionEvent event) {
|
||||
// Guaranteed to return a non-null array
|
||||
Object[] listeners = listenerList.getListenerList();
|
||||
|
||||
// Process the listeners last to first, notifying
|
||||
// those that are interested in this event
|
||||
for (int i = listeners.length - 2; i >= 0; i -= 2) {
|
||||
if (listeners[i] == ActionListener.class) {
|
||||
((ActionListener) listeners[i + 1]).actionPerformed(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
}
|
||||
|
||||
public void revalidate() {
|
||||
}
|
||||
|
||||
public void repaint(long tm, int x, int y, int width, int height) {
|
||||
}
|
||||
|
||||
public void repaint(Rectangle r) {
|
||||
}
|
||||
|
||||
public void repaint() {
|
||||
}
|
||||
|
||||
private class HyperlinkMouseListener extends MouseAdapter {
|
||||
private transient Rectangle cellRect;
|
||||
private final transient Rectangle iconRect = new Rectangle();
|
||||
private final transient Rectangle textRect = new Rectangle();
|
||||
private transient Cursor tableCursor;
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent event) {
|
||||
// This should only be called if underlineOnRollover is true
|
||||
JTable table = (JTable) event.getSource();
|
||||
|
||||
// Locate the table cell under the event location
|
||||
int oldHitColumnIndex = hitColumnIndex;
|
||||
int oldHitRowIndex = hitRowIndex;
|
||||
|
||||
checkIfPointInsideHyperlink(event.getPoint());
|
||||
|
||||
if (hitRowIndex != oldHitRowIndex ||
|
||||
hitColumnIndex != oldHitColumnIndex) {
|
||||
if (hitRowIndex != -1) {
|
||||
if (tableCursor == null) {
|
||||
tableCursor = table.getCursor();
|
||||
}
|
||||
table.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
} else {
|
||||
table.setCursor(tableCursor);
|
||||
}
|
||||
|
||||
// repaint the cells affected by rollover
|
||||
Rectangle repaintRect;
|
||||
if (hitRowIndex != -1 && hitColumnIndex != -1) {
|
||||
// we need to repaint new cell with rollover underline
|
||||
// cellRect already contains rect of hit cell
|
||||
if (oldHitRowIndex != -1 && oldHitColumnIndex != -1) {
|
||||
// we also need to repaint previously underlined hyperlink cell
|
||||
// to remove the underline
|
||||
repaintRect = cellRect.union(
|
||||
table.getCellRect(oldHitRowIndex, oldHitColumnIndex, false));
|
||||
} else {
|
||||
// we don't have a previously underlined hyperlink, so just repaint new one'
|
||||
repaintRect = table.getCellRect(hitRowIndex, hitColumnIndex, false);
|
||||
}
|
||||
} else {
|
||||
// we just need to repaint previously underlined hyperlink cell
|
||||
//to remove the underline
|
||||
repaintRect = table.getCellRect(oldHitRowIndex, oldHitColumnIndex, false);
|
||||
}
|
||||
table.repaint(repaintRect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent event) {
|
||||
if (checkIfPointInsideHyperlink(event.getPoint())) {
|
||||
|
||||
ActionEvent actionEvent = new ActionEvent(new Integer(hitRowIndex),
|
||||
ActionEvent.ACTION_PERFORMED,
|
||||
"hyperlink");
|
||||
|
||||
HyperlinkCellRenderer.this.fireActionPerformed(actionEvent);
|
||||
|
||||
setCellLinkVisited(table.getValueAt(hitRowIndex, hitColumnIndex),
|
||||
hitRowIndex, hitColumnIndex);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean checkIfPointInsideHyperlink(Point p) {
|
||||
hitColumnIndex = table.columnAtPoint(p);
|
||||
hitRowIndex = table.rowAtPoint(p);
|
||||
|
||||
if (hitColumnIndex != -1 && hitRowIndex != -1 &&
|
||||
columnModelIndeces.contains(table.getColumnModel().
|
||||
getColumn(hitColumnIndex).getModelIndex())) {
|
||||
// We know point is within a hyperlink column, however we do further hit testing
|
||||
// to see if point is within the text bounds on the hyperlink
|
||||
TableCellRenderer renderer = table.getCellRenderer(hitRowIndex, hitColumnIndex);
|
||||
JHyperlink hyperlink = (JHyperlink) table.prepareRenderer(renderer, hitRowIndex, hitColumnIndex);
|
||||
|
||||
// Convert the event to the renderer's coordinate system
|
||||
cellRect = table.getCellRect(hitRowIndex, hitColumnIndex, false);
|
||||
hyperlink.setSize(cellRect.width, cellRect.height);
|
||||
p.translate(-cellRect.x, -cellRect.y);
|
||||
cellRect.x = cellRect.y = 0;
|
||||
iconRect.x = iconRect.y = iconRect.width = iconRect.height = 0;
|
||||
textRect.x = textRect.y = textRect.width = textRect.height = 0;
|
||||
SwingUtilities.layoutCompoundLabel(
|
||||
hyperlink.getFontMetrics(hyperlink.getFont()),
|
||||
hyperlink.getText(), hyperlink.getIcon(),
|
||||
hyperlink.getVerticalAlignment(),
|
||||
hyperlink.getHorizontalAlignment(),
|
||||
hyperlink.getVerticalTextPosition(),
|
||||
hyperlink.getHorizontalTextPosition(),
|
||||
cellRect, iconRect, textRect, hyperlink.getIconTextGap());
|
||||
|
||||
if (textRect.contains(p)) {
|
||||
// point is within hyperlink text bounds
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// point is not within a hyperlink's text bounds
|
||||
hitRowIndex = -1;
|
||||
hitColumnIndex = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.swingset3.demos.table;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Class used to support converting a movie title string into an IMDB URI
|
||||
* corresponding to that movie's IMDB entry. Since IMDB encodes entries with
|
||||
* an alpha-numeric key (rather than title), we have to use Yahoo search on the
|
||||
* title and then screenscrape the search results to find the IMDB key.
|
||||
*
|
||||
* @author aim
|
||||
*/
|
||||
public class IMDBLink {
|
||||
|
||||
private IMDBLink() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param movieTitle the title of the movie
|
||||
* @param year the year the movie was nominated for the oscar
|
||||
* @return String containing URI for movie's IMDB entry or null if URI could not be found
|
||||
*/
|
||||
public static String getMovieURIString(String movieTitle, int year) throws IOException {
|
||||
ArrayList<String> matches = new ArrayList<String>();
|
||||
URL url;
|
||||
BufferedReader reader;
|
||||
|
||||
// btw, google rejects the request with a 403 return code!
|
||||
// URL url = new URL("http://www.google.com/search?q=Dazed+and+confused");
|
||||
// Thank you, yahoo, for granting our search request :-)
|
||||
try {
|
||||
String urlKey = URLEncoder.encode(movieTitle, "UTF-8");
|
||||
url = new URL("http://search.yahoo.com/search?ei=utf-8&fr=sfp&p=imdb+" +
|
||||
urlKey + "&iscqry=");
|
||||
} catch (Exception ex) {
|
||||
System.err.println(ex);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
URLConnection conn = url.openConnection();
|
||||
conn.connect();
|
||||
|
||||
// Get the response from Yahoo search query
|
||||
reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
|
||||
// Parse response a find each imdb/titleString result
|
||||
String line;
|
||||
String imdbString = ".imdb.com";
|
||||
String titleStrings[] = {"/title", "/Title"};
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
for (String titleString : titleStrings) {
|
||||
String scrapeKey = imdbString + titleString;
|
||||
int index = line.indexOf(scrapeKey);
|
||||
if (index != -1) {
|
||||
// The IMDB key looks something like "tt0032138"
|
||||
// so we look for the 9 characters after the scrape key
|
||||
// to construct the full IMDB URI.
|
||||
// e.g. http://www.imdb.com/title/tt0032138
|
||||
int len = scrapeKey.length();
|
||||
String imdbURL = "http://www" +
|
||||
line.substring(index, index + len) +
|
||||
line.substring(index + len, index + len + 10);
|
||||
|
||||
if (!matches.contains(imdbURL)) {
|
||||
matches.add(imdbURL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
|
||||
// Since imdb contains entries for multiple movies of the same titleString,
|
||||
// use the year to find the right entry
|
||||
if (matches.size() > 1) {
|
||||
for (String matchURL : matches) {
|
||||
if (verifyYear(matchURL, year)) {
|
||||
return matchURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return matches.isEmpty()? null : matches.get(0);
|
||||
}
|
||||
|
||||
|
||||
private static boolean verifyYear(String imdbURL, int movieYear) throws IOException {
|
||||
boolean yearMatches = false;
|
||||
|
||||
URLConnection conn = new URL(imdbURL).openConnection();
|
||||
conn.connect();
|
||||
|
||||
// Get the response
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
int index = line.indexOf("</title>");
|
||||
if (index != -1) {
|
||||
// looking for "<title>movie title (YEAR)</title>"
|
||||
try {
|
||||
int year = Integer.parseInt(line.substring(index - 5, index - 1));
|
||||
// Movie may have been made the year prior to oscar award
|
||||
yearMatches = year == movieYear || year == movieYear - 1;
|
||||
|
||||
} catch (NumberFormatException ex) {
|
||||
// ignore title lines that have other formatting
|
||||
}
|
||||
break; // only interested in analyzing the one line
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
|
||||
return yearMatches;
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.swingset3.demos.table;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* Class representing the state of a hyperlink
|
||||
* This class may be used in conjunction with HyperlinkCellRenderer,
|
||||
* but it is not required.
|
||||
*
|
||||
* @author aim
|
||||
*/
|
||||
public class Link {
|
||||
protected String displayText;
|
||||
private URI uri;
|
||||
private String description;
|
||||
private boolean visited;
|
||||
|
||||
/**
|
||||
* Creates a new instance of Link
|
||||
*/
|
||||
public Link(String text) {
|
||||
setDisplayText(text);
|
||||
}
|
||||
|
||||
public Link(String text, URI uri) {
|
||||
this(text);
|
||||
setUri(uri);
|
||||
}
|
||||
|
||||
public String getDisplayText() {
|
||||
return displayText;
|
||||
}
|
||||
|
||||
public void setDisplayText(String text) {
|
||||
this.displayText = text;
|
||||
}
|
||||
|
||||
public URI getUri() {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public void setUri(URI uri) {
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description != null ? description :
|
||||
uri != null ? uri.getPath() : null;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public boolean isVisited() {
|
||||
return visited;
|
||||
}
|
||||
|
||||
public void setVisited(boolean visited) {
|
||||
this.visited = visited;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.swingset3.demos.table;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aim
|
||||
*/
|
||||
public class OscarCandidate {
|
||||
|
||||
private String category;
|
||||
private Integer year;
|
||||
private boolean winner = false;
|
||||
private String movie;
|
||||
private URI imdbURI;
|
||||
private final ArrayList<String> persons = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* Creates a new instance of OscarCandidate
|
||||
*/
|
||||
public OscarCandidate(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public Integer getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public void setYear(Integer year) {
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public boolean isWinner() {
|
||||
return winner;
|
||||
}
|
||||
|
||||
public void setWinner(boolean winner) {
|
||||
this.winner = winner;
|
||||
}
|
||||
|
||||
public String getMovieTitle() {
|
||||
return movie;
|
||||
}
|
||||
|
||||
public void setMovieTitle(String movie) {
|
||||
this.movie = movie;
|
||||
}
|
||||
|
||||
public URI getIMDBMovieURI() {
|
||||
return imdbURI;
|
||||
}
|
||||
|
||||
public void setIMDBMovieURI(URI uri) {
|
||||
this.imdbURI = uri;
|
||||
}
|
||||
|
||||
public List<String> getPersons() {
|
||||
return persons;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.swingset3.demos.table;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Font;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableModel;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aim
|
||||
*/
|
||||
public class OscarCellRenderers {
|
||||
|
||||
//<snip>Render table rows with alternating colors
|
||||
public static class RowRenderer extends DefaultTableCellRenderer {
|
||||
private Color rowColors[];
|
||||
|
||||
public RowRenderer() {
|
||||
// initialize default colors from look-and-feel
|
||||
rowColors = new Color[1];
|
||||
rowColors[0] = UIManager.getColor("Table.background");
|
||||
}
|
||||
|
||||
public RowRenderer(Color colors[]) {
|
||||
super();
|
||||
setRowColors(colors);
|
||||
}
|
||||
|
||||
public void setRowColors(Color colors[]) {
|
||||
rowColors = colors;
|
||||
}
|
||||
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
setText(value != null ? value.toString() : "unknown");
|
||||
if (!isSelected) {
|
||||
setBackground(rowColors[row % rowColors.length]);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isOpaque() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//<snip>
|
||||
|
||||
//<snip>Render "year" table column with font representing style of decade
|
||||
// currently only used on OS X because fonts are Mac centric.
|
||||
|
||||
public static class YearRenderer extends RowRenderer {
|
||||
private HashMap<String, Font> eraFonts;
|
||||
|
||||
public YearRenderer() {
|
||||
setHorizontalAlignment(JLabel.CENTER);
|
||||
|
||||
if (System.getProperty("os.name").equals("Mac OS X")) {
|
||||
eraFonts = new HashMap<String, Font>();
|
||||
eraFonts.put("192"/*1920's*/, new Font("Jazz LET", Font.PLAIN, 12));
|
||||
eraFonts.put("193"/*1930's*/, new Font("Mona Lisa Solid ITC TT", Font.BOLD, 18));
|
||||
eraFonts.put("194"/*1940's*/, new Font("American Typewriter", Font.BOLD, 12));
|
||||
eraFonts.put("195"/*1950's*/, new Font("Britannic Bold", Font.PLAIN, 12));
|
||||
eraFonts.put("196"/*1960's*/, new Font("Cooper Black", Font.PLAIN, 14));
|
||||
eraFonts.put("197"/*1970's*/, new Font("Syncro LET", Font.PLAIN, 14));
|
||||
eraFonts.put("198"/*1980's*/, new Font("Mistral", Font.PLAIN, 18));
|
||||
eraFonts.put("199"/*1990's*/, new Font("Papyrus", Font.BOLD, 14));
|
||||
eraFonts.put("200"/*2000's*/, new Font("Calisto MT", Font.PLAIN, 14));
|
||||
}
|
||||
}
|
||||
|
||||
public YearRenderer(Color colors[]) {
|
||||
this();
|
||||
setRowColors(colors);
|
||||
}
|
||||
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
|
||||
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
|
||||
String year = table.getValueAt(row,
|
||||
table.convertColumnIndexToView(OscarTableModel.YEAR_COLUMN)).toString();
|
||||
if (eraFonts != null && year != null && year.length() == 4) {
|
||||
String era = year.substring(0, 3);
|
||||
Font eraFont = eraFonts.get(era);
|
||||
setFont(eraFont);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
//</snip>
|
||||
|
||||
//<snip>Render "nominee" table column with special icon for winners
|
||||
|
||||
public static class NomineeRenderer extends RowRenderer {
|
||||
private final ImageIcon winnerIcon;
|
||||
private final ImageIcon nomineeIcon; // nice way of saying "loser" :)
|
||||
|
||||
public NomineeRenderer() {
|
||||
winnerIcon = new ImageIcon(
|
||||
getClass().getResource("resources/images/goldstar.png"));
|
||||
nomineeIcon = new ImageIcon(
|
||||
getClass().getResource("resources/images/nominee.png"));
|
||||
setHorizontalTextPosition(JLabel.TRAILING);
|
||||
}
|
||||
|
||||
public NomineeRenderer(Color colors[]) {
|
||||
this();
|
||||
setRowColors(colors);
|
||||
}
|
||||
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
|
||||
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
|
||||
|
||||
TableModel model = table.getModel();
|
||||
boolean winner = ((Boolean) model.getValueAt(table.convertRowIndexToModel(row),
|
||||
OscarTableModel.WINNER_COLUMN)).booleanValue();
|
||||
|
||||
List<String> persons = (List<String>) value;
|
||||
String text = persons != null && !persons.isEmpty() ? persons.get(0) : "name unknown";
|
||||
if (persons != null && persons.size() > 1) {
|
||||
int personCount = persons.size();
|
||||
setText(text + " + more...");
|
||||
StringBuffer winners = new StringBuffer("");
|
||||
for (int i = 0; i < personCount; i++) {
|
||||
String person = persons.get(i);
|
||||
winners.append(" " + person + (i < personCount - 1 ? ", " : ""));
|
||||
}
|
||||
setToolTipText((winner ? "Winners:" : "Nominees:") + winners);
|
||||
} else {
|
||||
setText(text);
|
||||
setToolTipText(winner ? "Winner!" : "Nominee");
|
||||
}
|
||||
|
||||
setIcon(winner ? winnerIcon : nomineeIcon);
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
//</snip>
|
||||
|
||||
public static class MovieRenderer extends HyperlinkCellRenderer {
|
||||
public MovieRenderer(Action action, boolean underlineOnRollover, Color rowColors[]) {
|
||||
super(action, underlineOnRollover);
|
||||
setRowColors(rowColors);
|
||||
}
|
||||
|
||||
public Component getTableCellRendererComponent(JTable table, Object value,
|
||||
boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
super.getTableCellRendererComponent(table, value, isSelected,
|
||||
hasFocus, row, column);
|
||||
if (value != null) {
|
||||
setToolTipText("http://www.imdb.com/" + "\"" + value + "\"");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.swingset3.demos.table;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
public abstract class OscarDataParser extends DefaultHandler {
|
||||
private static final String[] CATEGORIES_IN = {
|
||||
"actor", "actress", "bestPicture",
|
||||
"actorSupporting", "actressSupporting", "artDirection",
|
||||
"assistantDirector", "director", "cinematography",
|
||||
"costumeDesign", "danceDirection", "docFeature",
|
||||
"docShort", "filmEditing", "foreignFilm",
|
||||
"makeup", "musicScore", "musicSong",
|
||||
"screenplayAdapted", "screenplayOriginal", "shortAnimation",
|
||||
"shortLiveAction", "sound", "soundEditing",
|
||||
"specialEffects", "visualEffects", "writing",
|
||||
"engEffects", "uniqueArtisticPicture"
|
||||
};
|
||||
|
||||
private static final String[] CATEGORIES_OUT = {
|
||||
"Best Actor", "Best Actress", "Best Picture",
|
||||
"Best Supporting Actor", "Best Supporting Actress", "Best Art Direction",
|
||||
"Best Assistant Director", "Best Director", "Best Cinematography",
|
||||
"Best Costume Design", "Best Dance Direction", "Best Feature Documentary",
|
||||
"Best Short Documentary", "Best Film Editing", "Best Foreign Film",
|
||||
"Best Makeup", "Best Musical Score", "Best Song",
|
||||
"Best Adapted Screenplay", "Best Original Screenplay", "Best Animation Short",
|
||||
"Best Live Action Short", "Best Sound", "Best Sound Editing",
|
||||
"Best Special Effects", "Best Visual Effects", "Best Engineering Effects",
|
||||
"Best Writing", "Most Unique Artistic Picture"
|
||||
};
|
||||
|
||||
|
||||
private String tempVal;
|
||||
|
||||
//to maintain context
|
||||
private OscarCandidate tempOscarCandidate;
|
||||
|
||||
private int count = 0;
|
||||
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void parseDocument(URL oscarURL) {
|
||||
//get a factory
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
|
||||
try {
|
||||
//get a new instance of parser
|
||||
SAXParser sp = spf.newSAXParser();
|
||||
|
||||
//parse the file and also register this class for call backs
|
||||
InputStream is = new BufferedInputStream(oscarURL.openStream());
|
||||
sp.parse(is, this);
|
||||
System.out.println("done parsing count="+count);
|
||||
is.close();
|
||||
|
||||
} catch (SAXException se) {
|
||||
se.printStackTrace();
|
||||
} catch (ParserConfigurationException pce) {
|
||||
pce.printStackTrace();
|
||||
} catch (IOException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
//Event Handlers
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
//reset
|
||||
tempVal = "";
|
||||
for (int i = 0; i < CATEGORIES_IN.length; i++) {
|
||||
if (qName.equalsIgnoreCase(CATEGORIES_IN[i])) {
|
||||
tempOscarCandidate = new OscarCandidate(CATEGORIES_OUT[i]);
|
||||
tempOscarCandidate.setYear(Integer.parseInt(attributes.getValue("year")));
|
||||
if (CATEGORIES_IN[i].equals("screenplayOriginal") &&
|
||||
tempOscarCandidate.getYear() == 2007) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
tempVal = new String(ch, start, length);
|
||||
}
|
||||
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
if (qName.equalsIgnoreCase("won")) {
|
||||
tempOscarCandidate.setWinner(true);
|
||||
} else if (qName.equalsIgnoreCase("lost")) {
|
||||
tempOscarCandidate.setWinner(false);
|
||||
} else if (qName.equalsIgnoreCase("movie")) {
|
||||
tempOscarCandidate.setMovieTitle(tempVal);
|
||||
} else if (qName.equalsIgnoreCase("person")) {
|
||||
tempOscarCandidate.getPersons().add(tempVal);
|
||||
} else {
|
||||
// find category
|
||||
for (String category : CATEGORIES_IN) {
|
||||
if (qName.equalsIgnoreCase(category)) {
|
||||
//add it to the list
|
||||
count++;
|
||||
addCandidate(tempOscarCandidate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(SAXParseException ex) throws SAXException {
|
||||
TableDemo.logger.log(Level.SEVERE, "error parsing oscar data ", ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatalError(SAXParseException ex) throws SAXException {
|
||||
TableDemo.logger.log(Level.SEVERE, "fatal error parsing oscar data ", ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warning(SAXParseException ex) {
|
||||
TableDemo.logger.log(Level.WARNING, "warning occurred while parsing oscar data ", ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDocument() throws SAXException {
|
||||
TableDemo.logger.log(Level.FINER, "parsed to end of oscar data.");
|
||||
}
|
||||
|
||||
protected abstract void addCandidate(OscarCandidate candidate);
|
||||
}
|
||||
|
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.swingset3.demos.table;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
/**
|
||||
* Data model for oscar candidate data: a list of OscarCandidate beans.
|
||||
*
|
||||
* @author aim
|
||||
*/
|
||||
|
||||
public class OscarTableModel extends AbstractTableModel {
|
||||
public static final int CATEGORY_COLUMN = 0;
|
||||
public static final int YEAR_COLUMN = 1;
|
||||
public static final int WINNER_COLUMN = 2;
|
||||
public static final int MOVIE_COLUMN = 3;
|
||||
public static final int PERSONS_COLUMN = 4;
|
||||
public static final int COLUMN_COUNT = 5;
|
||||
|
||||
private final List<OscarCandidate> candidates = new ArrayList<OscarCandidate>();
|
||||
|
||||
public void add(List<OscarCandidate> newCandidates) {
|
||||
int first = candidates.size();
|
||||
int last = first + newCandidates.size() - 1;
|
||||
candidates.addAll(newCandidates);
|
||||
fireTableRowsInserted(first, last);
|
||||
}
|
||||
|
||||
public void add(OscarCandidate candidate) {
|
||||
int index = candidates.size();
|
||||
candidates.add(candidate);
|
||||
fireTableRowsInserted(index, index);
|
||||
}
|
||||
|
||||
public int getRowCount() {
|
||||
return candidates.size();
|
||||
}
|
||||
|
||||
public int getColumnCount() {
|
||||
return COLUMN_COUNT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getColumnClass(int column) {
|
||||
return getValueAt(0, column).getClass();
|
||||
}
|
||||
|
||||
public OscarCandidate getCandidate(int row) {
|
||||
return candidates.get(row);
|
||||
}
|
||||
|
||||
public Object getValueAt(int row, int column) {
|
||||
OscarCandidate oscarCandidate = candidates.get(row);
|
||||
switch (column) {
|
||||
case CATEGORY_COLUMN:
|
||||
return oscarCandidate.getCategory();
|
||||
case YEAR_COLUMN:
|
||||
return oscarCandidate.getYear();
|
||||
case MOVIE_COLUMN:
|
||||
return oscarCandidate.getMovieTitle();
|
||||
case WINNER_COLUMN:
|
||||
return oscarCandidate.isWinner() ? Boolean.TRUE : Boolean.FALSE;
|
||||
case PERSONS_COLUMN:
|
||||
return oscarCandidate.getPersons();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,623 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.swingset3.demos.table;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.RowFilter;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.TitledBorder;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.event.TableModelEvent;
|
||||
import javax.swing.event.TableModelListener;
|
||||
import javax.swing.table.DefaultTableColumnModel;
|
||||
import javax.swing.table.JTableHeader;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import javax.swing.table.TableColumn;
|
||||
import javax.swing.table.TableColumnModel;
|
||||
import javax.swing.table.TableRowSorter;
|
||||
import javax.swing.text.Document;
|
||||
|
||||
import com.sun.swingset3.DemoProperties;
|
||||
import com.sun.swingset3.demos.DemoUtilities;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aim
|
||||
*/
|
||||
@DemoProperties(
|
||||
value = "JTable Demo",
|
||||
category = "Data",
|
||||
description = "Demonstrates use of Swing's data grid component, JTable, including asynchronous loading and sorting/filtering.",
|
||||
sourceFiles = {
|
||||
"com/sun/swingset3/demos/table/TableDemo.java",
|
||||
"com/sun/swingset3/demos/table/HyperlinkCellRenderer.java",
|
||||
"com/sun/swingset3/demos/table/IMDBLink.java",
|
||||
"com/sun/swingset3/demos/table/Link.java",
|
||||
"com/sun/swingset3/demos/table/OscarCandidate.java",
|
||||
"com/sun/swingset3/demos/table/OscarCellRenderers.java",
|
||||
"com/sun/swingset3/demos/table/OscarDataParser.java",
|
||||
"com/sun/swingset3/demos/table/OscarTableModel.java",
|
||||
"com/sun/swingset3/demos/DemoUtilities.java",
|
||||
"com/sun/swingset3/demos/JHyperlink.java",
|
||||
"com/sun/swingset3/demos/table/resources/bestpicture",
|
||||
//"com/sun/swingset3/demos/table/resources/oscars.xml", file too large!!
|
||||
"com/sun/swingset3/demos/table/resources/TableDemo.properties",
|
||||
"com/sun/swingset3/demos/table/resources/images/goldstar.png",
|
||||
"com/sun/swingset3/demos/table/resources/images/nominee.png",
|
||||
"com/sun/swingset3/demos/table/resources/images/TableDemo.gif"
|
||||
}
|
||||
)
|
||||
public class TableDemo extends JPanel {
|
||||
static final Logger logger = Logger.getLogger(TableDemo.class.getName());
|
||||
public static final String DEMO_TITLE = TableDemo.class.getAnnotation(DemoProperties.class).value();
|
||||
public static final int ROW_HEIGHT = 26;
|
||||
public static final String COLUMN1_NAME = "Year";
|
||||
public static final String COLUMN2_NAME = "Award Category";
|
||||
public static final String COLUMN3_NAME = "Movie Title";
|
||||
public static final String COLUMN4_NAME = "Nominees";
|
||||
|
||||
private OscarTableModel oscarModel;
|
||||
|
||||
private JPanel controlPanel;
|
||||
private JTable oscarTable;
|
||||
private JCheckBox winnersCheckbox;
|
||||
private JTextField filterField;
|
||||
private Box statusBarLeft;
|
||||
private JLabel actionStatus;
|
||||
private JLabel tableStatus;
|
||||
|
||||
private Color[] rowColors;
|
||||
private String statusLabelString;
|
||||
private String searchLabelString;
|
||||
|
||||
private boolean showOnlyWinners = false;
|
||||
private String filterString = null;
|
||||
|
||||
private TableRowSorter sorter;
|
||||
private RowFilter<OscarTableModel, Integer> winnerFilter;
|
||||
private RowFilter<OscarTableModel, Integer> searchFilter;
|
||||
|
||||
// Resource bundle for internationalized and accessible text
|
||||
private ResourceBundle bundle = null;
|
||||
|
||||
public TableDemo() {
|
||||
initModel();
|
||||
initComponents();
|
||||
initSortingFiltering();
|
||||
}
|
||||
|
||||
protected void initModel() {
|
||||
oscarModel = new OscarTableModel();
|
||||
}
|
||||
|
||||
protected void initComponents() {
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
controlPanel = createControlPanel();
|
||||
add(controlPanel, BorderLayout.NORTH);
|
||||
|
||||
//<snip>Create JTable
|
||||
oscarTable = new JTable(oscarModel);
|
||||
//</snip>
|
||||
|
||||
//</snip>Set JTable display properties
|
||||
oscarTable.setColumnModel(createColumnModel());
|
||||
oscarTable.setAutoCreateRowSorter(true);
|
||||
oscarTable.setRowHeight(ROW_HEIGHT);
|
||||
oscarTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
|
||||
oscarTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
oscarTable.setIntercellSpacing(new Dimension(0, 0));
|
||||
//</snip>
|
||||
|
||||
//<snip>Initialize preferred size for table's viewable area
|
||||
Dimension viewSize = new Dimension();
|
||||
viewSize.width = oscarTable.getColumnModel().getTotalColumnWidth();
|
||||
viewSize.height = 10 * oscarTable.getRowHeight();
|
||||
oscarTable.setPreferredScrollableViewportSize(viewSize);
|
||||
//</snip>
|
||||
|
||||
//<snip>Customize height and alignment of table header
|
||||
JTableHeader header = oscarTable.getTableHeader();
|
||||
header.setPreferredSize(new Dimension(30, 26));
|
||||
TableCellRenderer headerRenderer = header.getDefaultRenderer();
|
||||
if (headerRenderer instanceof JLabel) {
|
||||
((JLabel) headerRenderer).setHorizontalAlignment(JLabel.CENTER);
|
||||
}
|
||||
//</snip>
|
||||
|
||||
JScrollPane scrollpane = new JScrollPane(oscarTable);
|
||||
add(scrollpane, BorderLayout.CENTER);
|
||||
|
||||
add(createStatusBar(), BorderLayout.SOUTH);
|
||||
|
||||
}
|
||||
|
||||
protected JPanel createControlPanel() {
|
||||
JPanel controlPanel = new JPanel();
|
||||
GridBagLayout gridbag = new GridBagLayout();
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
controlPanel.setLayout(gridbag);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 1;
|
||||
c.gridheight = 1;
|
||||
c.insets = new Insets(20, 10, 0, 10);
|
||||
c.anchor = GridBagConstraints.SOUTHWEST;
|
||||
JLabel searchLabel = new JLabel(getString("TableDemo.searchLabel",
|
||||
"Search Titles and Recipients"));
|
||||
controlPanel.add(searchLabel, c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 2;
|
||||
c.weightx = 1.0;
|
||||
c.insets.top = 0;
|
||||
c.insets.bottom = 12;
|
||||
c.anchor = GridBagConstraints.SOUTHWEST;
|
||||
//c.fill = GridBagConstraints.HORIZONTAL;
|
||||
filterField = new JTextField(24);
|
||||
filterField.getDocument().addDocumentListener(new SearchFilterListener());
|
||||
controlPanel.add(filterField, c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 2;
|
||||
c.gridwidth = GridBagConstraints.REMAINDER;
|
||||
//c.insets.right = 24;
|
||||
//c.insets.left = 12;
|
||||
c.weightx = 0.0;
|
||||
c.anchor = GridBagConstraints.EAST;
|
||||
c.fill = GridBagConstraints.NONE;
|
||||
winnersCheckbox = new JCheckBox(getString("TableDemo.winnersLabel",
|
||||
"Show Only Winners"));
|
||||
winnersCheckbox.addChangeListener(new ShowWinnersListener());
|
||||
controlPanel.add(winnersCheckbox, c);
|
||||
|
||||
return controlPanel;
|
||||
}
|
||||
|
||||
protected Container createStatusBar() {
|
||||
statusLabelString = getString("TableDemo.rowCountLabel",
|
||||
"Showing ");
|
||||
searchLabelString = getString("TableDemo.searchCountLabel",
|
||||
"Search found ");
|
||||
|
||||
Box statusBar = Box.createHorizontalBox();
|
||||
|
||||
// Left status area
|
||||
statusBar.add(Box.createRigidArea(new Dimension(10, 22)));
|
||||
statusBarLeft = Box.createHorizontalBox();
|
||||
statusBar.add(statusBarLeft);
|
||||
actionStatus = new JLabel(getString("TableDemo.noDataStatusLabel",
|
||||
"No data loaded"));
|
||||
actionStatus.setHorizontalAlignment(JLabel.LEADING);
|
||||
statusBarLeft.add(actionStatus);
|
||||
|
||||
// Middle (should stretch)
|
||||
statusBar.add(Box.createHorizontalGlue());
|
||||
statusBar.add(Box.createHorizontalGlue());
|
||||
statusBar.add(Box.createVerticalGlue());
|
||||
|
||||
// Right status area
|
||||
tableStatus = new JLabel(statusLabelString + "0");
|
||||
statusBar.add(tableStatus);
|
||||
statusBar.add(Box.createHorizontalStrut(12));
|
||||
|
||||
//<snip>Track number of rows currently displayed
|
||||
oscarModel.addTableModelListener(new TableModelListener() {
|
||||
public void tableChanged(TableModelEvent e) {
|
||||
// Get rowCount from *table*, not model, as the view row count
|
||||
// may be different from the model row count due to filtering
|
||||
tableStatus.setText((hasFilterString() ? searchLabelString : statusLabelString) +
|
||||
oscarTable.getRowCount());
|
||||
}
|
||||
});
|
||||
//</snip>
|
||||
|
||||
return statusBar;
|
||||
}
|
||||
|
||||
private Color[] getTableRowColors() {
|
||||
if (rowColors == null) {
|
||||
rowColors = new Color[2];
|
||||
rowColors[0] = UIManager.getColor("Table.background");
|
||||
rowColors[1] = new Color((int) (rowColors[0].getRed() * .9),
|
||||
(int) (rowColors[0].getGreen() * .9),
|
||||
(int) (rowColors[0].getBlue() * .9));
|
||||
}
|
||||
return rowColors;
|
||||
}
|
||||
|
||||
// returns appropriate string from resource bundle
|
||||
protected String getString(String key, String fallback) {
|
||||
String value = fallback;
|
||||
if (bundle == null) {
|
||||
String bundleName = getClass().getPackage().getName() + ".resources." + getClass().getSimpleName();
|
||||
bundle = ResourceBundle.getBundle(bundleName);
|
||||
}
|
||||
try {
|
||||
value = bundle != null ? bundle.getString(key) : key;
|
||||
|
||||
} catch (MissingResourceException ex) {
|
||||
logger.log(Level.WARNING, "couldn't find resource value for: " + key, ex);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if (oscarModel.getRowCount() == 0) {
|
||||
loadData("resources/oscars.xml");
|
||||
}
|
||||
}
|
||||
|
||||
//<snip>Initialize table columns
|
||||
protected TableColumnModel createColumnModel() {
|
||||
DefaultTableColumnModel columnModel = new DefaultTableColumnModel();
|
||||
|
||||
TableCellRenderer cellRenderer = new OscarCellRenderers.RowRenderer(getTableRowColors());
|
||||
|
||||
TableColumn column = new TableColumn();
|
||||
column.setModelIndex(OscarTableModel.YEAR_COLUMN);
|
||||
column.setHeaderValue(COLUMN1_NAME);
|
||||
column.setPreferredWidth(26);
|
||||
column.setCellRenderer(new OscarCellRenderers.YearRenderer(getTableRowColors()));
|
||||
columnModel.addColumn(column);
|
||||
|
||||
column = new TableColumn();
|
||||
column.setModelIndex(OscarTableModel.CATEGORY_COLUMN);
|
||||
column.setHeaderValue(COLUMN2_NAME);
|
||||
column.setPreferredWidth(100);
|
||||
column.setCellRenderer(cellRenderer);
|
||||
columnModel.addColumn(column);
|
||||
|
||||
column = new TableColumn();
|
||||
column.setModelIndex(OscarTableModel.MOVIE_COLUMN);
|
||||
column.setHeaderValue(COLUMN3_NAME);
|
||||
column.setPreferredWidth(180);
|
||||
column.setCellRenderer(cellRenderer);
|
||||
columnModel.addColumn(column);
|
||||
|
||||
column = new TableColumn();
|
||||
column.setModelIndex(OscarTableModel.PERSONS_COLUMN);
|
||||
column.setHeaderValue(COLUMN4_NAME);
|
||||
column.setPreferredWidth(120);
|
||||
column.setCellRenderer(new OscarCellRenderers.NomineeRenderer(getTableRowColors()));
|
||||
columnModel.addColumn(column);
|
||||
|
||||
return columnModel;
|
||||
}
|
||||
//</snip>
|
||||
|
||||
protected void initSortingFiltering() {
|
||||
//<snip>Setup filtering for winners
|
||||
sorter = new TableRowSorter(oscarModel);
|
||||
oscarTable.setRowSorter(sorter);
|
||||
winnerFilter = new RowFilter<OscarTableModel, Integer>() {
|
||||
public boolean include(Entry<? extends OscarTableModel, ? extends Integer> entry) {
|
||||
OscarTableModel oscarModel = entry.getModel();
|
||||
OscarCandidate candidate = oscarModel.getCandidate(entry.getIdentifier().intValue());
|
||||
if (candidate.isWinner()) {
|
||||
// Returning true indicates this row should be shown.
|
||||
return true;
|
||||
}
|
||||
// loser
|
||||
return false;
|
||||
}
|
||||
};
|
||||
//</snip>
|
||||
|
||||
//<snip>Setup search filter
|
||||
searchFilter = new RowFilter<OscarTableModel, Integer>() {
|
||||
public boolean include(Entry<? extends OscarTableModel, ? extends Integer> entry) {
|
||||
OscarTableModel oscarModel = entry.getModel();
|
||||
OscarCandidate candidate = oscarModel.getCandidate(entry.getIdentifier().intValue());
|
||||
boolean matches = false;
|
||||
Pattern p = Pattern.compile(filterString + ".*", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
String movie = candidate.getMovieTitle();
|
||||
if (movie != null) {
|
||||
if (movie.startsWith("The ")) {
|
||||
movie = movie.replace("The ", "");
|
||||
} else if (movie.startsWith("A ")) {
|
||||
movie = movie.replace("A ", "");
|
||||
}
|
||||
// Returning true indicates this row should be shown.
|
||||
matches = p.matcher(movie).matches();
|
||||
}
|
||||
List<String> persons = candidate.getPersons();
|
||||
for (String person : persons) {
|
||||
if (p.matcher(person).matches()) {
|
||||
matches = true;
|
||||
}
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
};
|
||||
//</snip>
|
||||
}
|
||||
|
||||
public void setShowOnlyWinners(boolean showOnlyWinners) {
|
||||
boolean oldShowOnlyWinners = this.showOnlyWinners;
|
||||
this.showOnlyWinners = showOnlyWinners;
|
||||
configureFilters();
|
||||
tableStatus.setText(statusLabelString + oscarTable.getRowCount());
|
||||
firePropertyChange("showOnlyWinners", oldShowOnlyWinners, showOnlyWinners);
|
||||
}
|
||||
|
||||
public boolean getShowOnlyWinners() {
|
||||
return showOnlyWinners;
|
||||
}
|
||||
|
||||
public void setFilterString(String filterString) {
|
||||
String oldFilterString = this.filterString;
|
||||
this.filterString = filterString;
|
||||
configureFilters();
|
||||
firePropertyChange("filterString", oldFilterString, filterString);
|
||||
}
|
||||
|
||||
protected boolean hasFilterString() {
|
||||
return filterString != null && !filterString.equals("");
|
||||
}
|
||||
|
||||
protected void configureFilters() {
|
||||
if (showOnlyWinners && hasFilterString()) {
|
||||
List<RowFilter<OscarTableModel, Integer>> filters =
|
||||
new ArrayList<RowFilter<OscarTableModel, Integer>>(2);
|
||||
filters.add(winnerFilter);
|
||||
filters.add(searchFilter);
|
||||
RowFilter<OscarTableModel, Integer> comboFilter = RowFilter.andFilter(filters);
|
||||
sorter.setRowFilter(comboFilter);
|
||||
} else if (showOnlyWinners) {
|
||||
sorter.setRowFilter(winnerFilter);
|
||||
} else if (hasFilterString()) {
|
||||
sorter.setRowFilter(searchFilter);
|
||||
} else {
|
||||
sorter.setRowFilter(null);
|
||||
}
|
||||
tableStatus.setText((hasFilterString() ? searchLabelString : statusLabelString)
|
||||
+ oscarTable.getRowCount());
|
||||
|
||||
}
|
||||
|
||||
private class ShowWinnersListener implements ChangeListener {
|
||||
public void stateChanged(ChangeEvent event) {
|
||||
setShowOnlyWinners(winnersCheckbox.isSelected());
|
||||
}
|
||||
}
|
||||
|
||||
//<snip>Setup search filter
|
||||
protected class SearchFilterListener implements DocumentListener {
|
||||
protected void changeFilter(DocumentEvent event) {
|
||||
Document document = event.getDocument();
|
||||
try {
|
||||
setFilterString(document.getText(0, document.getLength()));
|
||||
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
System.err.println(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
changeFilter(e);
|
||||
}
|
||||
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
changeFilter(e);
|
||||
}
|
||||
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
changeFilter(e);
|
||||
}
|
||||
}
|
||||
//</snip>
|
||||
|
||||
//<snip>Use SwingWorker to asynchronously load the data
|
||||
|
||||
public void loadData(String dataPath) {
|
||||
// create SwingWorker which will load the data on a separate thread
|
||||
OscarDataLoader loader = new OscarDataLoader(
|
||||
TableDemo.class.getResource(dataPath), oscarModel);
|
||||
|
||||
actionStatus.setText(getString("TableDemo.loadingStatusLabel",
|
||||
"Loading data: "));
|
||||
|
||||
// display progress bar while data loads
|
||||
final JProgressBar progressBar = new JProgressBar();
|
||||
statusBarLeft.add(progressBar);
|
||||
loader.addPropertyChangeListener(new PropertyChangeListener() {
|
||||
public void propertyChange(PropertyChangeEvent event) {
|
||||
if (event.getPropertyName().equals("progress")) {
|
||||
int progress = ((Integer) event.getNewValue()).intValue();
|
||||
progressBar.setValue(progress);
|
||||
|
||||
if (progress == 100) {
|
||||
statusBarLeft.remove(progressBar);
|
||||
actionStatus.setText("");
|
||||
revalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
loader.execute();
|
||||
|
||||
}
|
||||
//</snip>
|
||||
|
||||
protected void showMessage(String title, String message) {
|
||||
JOptionPane.showMessageDialog(this, message, title, JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
|
||||
//<snip>Use SwingWorker to asynchronously load the data
|
||||
private class OscarDataLoader extends javax.swing.SwingWorker<List<OscarCandidate>, OscarCandidate> {
|
||||
private final URL oscarData;
|
||||
private final OscarTableModel oscarModel;
|
||||
private final List<OscarCandidate> candidates = new ArrayList<OscarCandidate>();
|
||||
private JLabel credits;
|
||||
|
||||
private OscarDataLoader(URL oscarURL, OscarTableModel oscarTableModel) {
|
||||
this.oscarData = oscarURL;
|
||||
this.oscarModel = oscarTableModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OscarCandidate> doInBackground() {
|
||||
OscarDataParser parser = new OscarDataParser() {
|
||||
@Override
|
||||
protected void addCandidate(OscarCandidate candidate) {
|
||||
candidates.add(candidate);
|
||||
if (candidates.size() % 3 == 0) {
|
||||
try { // slow it down so we can see progress :-)
|
||||
Thread.sleep(1);
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
}
|
||||
publish(candidate);
|
||||
setProgress(100 * candidates.size() / 524);
|
||||
}
|
||||
};
|
||||
parser.parseDocument(oscarData);
|
||||
return candidates;
|
||||
}
|
||||
|
||||
// for OS X older Java 6
|
||||
/*
|
||||
protected void process(List<OscarCandidate>... moreCandidates) {
|
||||
for(List<OscarCandidate> newCandidates: moreCandidates) {
|
||||
oscarModel.add(newCandidates);
|
||||
}
|
||||
}*/
|
||||
|
||||
//@Override
|
||||
|
||||
protected void process(List<OscarCandidate> moreCandidates) {
|
||||
if (credits == null) {
|
||||
showCredits();
|
||||
}
|
||||
oscarModel.add(moreCandidates);
|
||||
}
|
||||
|
||||
// For older Java 6 on OS X
|
||||
protected void process(OscarCandidate... moreCandidates) {
|
||||
for (OscarCandidate candidate : moreCandidates) {
|
||||
oscarModel.add(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
private void showCredits() {
|
||||
credits = new JLabel(getString("TableDemo.credits",
|
||||
"<html><p align=\"center\">Academy Award data<br>courtesy of Howard Katz</p></html>"));
|
||||
credits.setFont(UIManager.getFont("Table.font").deriveFont(24f));
|
||||
credits.setHorizontalAlignment(JLabel.CENTER);
|
||||
credits.setBorder(new CompoundBorder(new TitledBorder(""),
|
||||
new EmptyBorder(20,20,20,20)));
|
||||
}
|
||||
@Override
|
||||
protected void done() {
|
||||
setProgress(100);
|
||||
}
|
||||
|
||||
}
|
||||
//</snip>
|
||||
|
||||
private class IMDBLinkAction extends AbstractAction {
|
||||
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
int row = ((Integer) event.getSource()).intValue();
|
||||
OscarCandidate candidate = oscarModel.getCandidate(oscarTable.convertRowIndexToModel(row));
|
||||
|
||||
try {
|
||||
URI imdbURI = candidate.getIMDBMovieURI();
|
||||
if (imdbURI == null) {
|
||||
String imdbString = IMDBLink.getMovieURIString(candidate.getMovieTitle(),
|
||||
candidate.getYear());
|
||||
if (imdbString != null) {
|
||||
imdbURI = new URI(imdbString);
|
||||
candidate.setIMDBMovieURI(imdbURI);
|
||||
}
|
||||
}
|
||||
if (imdbURI != null) {
|
||||
DemoUtilities.browse(imdbURI);
|
||||
} else {
|
||||
showMessage("IMDB Link",
|
||||
getString("TableDemo.imdbLinkNotFound",
|
||||
"Unable to locate IMDB URL for") + "\n" +
|
||||
candidate.getMovieTitle());
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
|
||||
javax.swing.SwingUtilities.invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
JFrame frame = new JFrame("JTable Demo");
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
TableDemo demo = new TableDemo();
|
||||
frame.add(demo);
|
||||
frame.setSize(700, 400);
|
||||
frame.setVisible(true);
|
||||
demo.start();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
# Table Demo Properties
|
||||
|
||||
TableDemo.accessible_description=Advanced Table Demo
|
||||
TableDemo.name=Advanced Table Demo
|
||||
TableDemo.title=Academy Awards Results
|
||||
TableDemo.credits=<html><p align="center">Academy Award data<br>courtesy of Howard Katz</p></html>
|
||||
|
||||
TableDemo.searchLabel=Search Titles and Recipients
|
||||
TableDemo.winnersLabel=Show Only Winners
|
||||
|
||||
TableDemo.noDataStatusLabel=No data loaded
|
||||
TableDemo.loadingStatusLabel=Loading data:
|
||||
TableDemo.rowCountLabel=Showing
|
||||
TableDemo.searchCountLabel=Search found
|
||||
|
||||
TableDemo.yearColumnTitle=Year
|
||||
TableDemo.categoryColumnTitle=Award Category
|
||||
TableDemo.movieTitleColumnTitle=Movie Title
|
||||
TableDemo.nomineesColumnTitle=Nominee(s)
|
||||
|
||||
TableDemo.imdbLinkNotFound=Unable to locate IMDB URL for
|
||||
|
@ -0,0 +1,397 @@
|
||||
|
||||
1927/28 (1st)
|
||||
OUTSTANDING PICTURE
|
||||
*
|
||||
Paramount Famous Lasky -- Wings
|
||||
|
||||
1928/29 (2nd)
|
||||
OUTSTANDING PICTURE
|
||||
*
|
||||
Metro-Goldwyn-Mayer -- The Broadway Melody
|
||||
[NOTE: THIS IS NOT AN OFFICIAL NOMINATION. There were no announcements of nominations, no certificates of nomination or honorable mention, and only the winners (*) were revealed during the awards banquet on April 3, 1930.]
|
||||
|
||||
1929/30 (3rd)
|
||||
OUTSTANDING PRODUCTION
|
||||
*
|
||||
All Quiet on the Western Front -- Universal
|
||||
|
||||
1930/31 (4th)
|
||||
OUTSTANDING PRODUCTION
|
||||
*
|
||||
Cimarron -- RKO Radio
|
||||
|
||||
1931/32 (5th)
|
||||
OUTSTANDING PRODUCTION
|
||||
*
|
||||
Grand Hotel -- Metro-Goldwyn-Mayer
|
||||
|
||||
1932/33 (6th)
|
||||
OUTSTANDING PRODUCTION
|
||||
*
|
||||
Cavalcade -- Fox
|
||||
|
||||
1934 (7th)
|
||||
OUTSTANDING PRODUCTION
|
||||
*
|
||||
It Happened One Night -- Columbia
|
||||
|
||||
1935 (8th)
|
||||
OUTSTANDING PRODUCTION
|
||||
*
|
||||
Mutiny on the Bounty -- Metro-Goldwyn-Mayer
|
||||
|
||||
1936 (9th)
|
||||
OUTSTANDING PRODUCTION
|
||||
*
|
||||
The Great Ziegfeld -- Metro-Goldwyn-Mayer
|
||||
|
||||
1937 (10th)
|
||||
OUTSTANDING PRODUCTION
|
||||
*
|
||||
The Life of Emile Zola -- Warner Bros.
|
||||
|
||||
1938 (11th)
|
||||
OUTSTANDING PRODUCTION
|
||||
*
|
||||
You Can't Take It with You -- Columbia
|
||||
|
||||
1939 (12th)
|
||||
OUTSTANDING PRODUCTION
|
||||
*
|
||||
Gone with the Wind -- Selznick International Pictures
|
||||
|
||||
1940 (13th)
|
||||
OUTSTANDING PRODUCTION
|
||||
*
|
||||
Rebecca -- Selznick International Pictures
|
||||
|
||||
1941 (14th)
|
||||
OUTSTANDING MOTION PICTURE
|
||||
*
|
||||
How Green Was My Valley -- 20th Century-Fox
|
||||
|
||||
1942 (15th)
|
||||
OUTSTANDING MOTION PICTURE
|
||||
*
|
||||
Mrs. Miniver -- Metro-Goldwyn-Mayer
|
||||
|
||||
1943 (16th)
|
||||
OUTSTANDING MOTION PICTURE
|
||||
*
|
||||
Casablanca -- Warner Bros.
|
||||
|
||||
1944 (17th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
Going My Way -- Paramount
|
||||
|
||||
1945 (18th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
The Lost Weekend -- Paramount
|
||||
|
||||
1946 (19th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
The Best Years of Our Lives -- Samuel Goldwyn Productions
|
||||
|
||||
1947 (20th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
Gentleman's Agreement -- 20th Century-Fox
|
||||
|
||||
1948 (21st)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
Hamlet -- J. Arthur Rank-Two Cities Films
|
||||
|
||||
1949 (22nd)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
All the King's Men -- Robert Rossen Productions
|
||||
|
||||
1950 (23rd)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
All about Eve -- 20th Century-Fox
|
||||
|
||||
1951 (24th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
An American in Paris -- Arthur Freed, Producer
|
||||
|
||||
1952 (25th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
The Greatest Show on Earth -- Cecil B. DeMille, Producer
|
||||
|
||||
1953 (26th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
From Here to Eternity -- Buddy Adler, Producer
|
||||
|
||||
1954 (27th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
On the Waterfront -- Sam Spiegel, Producer
|
||||
|
||||
1955 (28th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
Marty -- Harold Hecht, Producer
|
||||
|
||||
1956 (29th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
Around the World in 80 Days -- Michael Todd, Producer
|
||||
|
||||
1957 (30th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
The Bridge on the River Kwai -- Sam Spiegel, Producer
|
||||
|
||||
1958 (31st)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
Gigi -- Arthur Freed, Producer
|
||||
|
||||
1959 (32nd)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
Ben-Hur -- Sam Zimbalist, Producer
|
||||
|
||||
1960 (33rd)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
The Apartment -- Billy Wilder, Producer
|
||||
|
||||
1961 (34th)
|
||||
BEST MOTION PICTURE
|
||||
*
|
||||
West Side Story -- Robert Wise, Producer
|
||||
|
||||
1962 (35th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Lawrence of Arabia -- Sam Spiegel, Producer
|
||||
|
||||
1963 (36th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Tom Jones -- Tony Richardson, Producer
|
||||
|
||||
1964 (37th)
|
||||
BEST PICTURE
|
||||
*
|
||||
My Fair Lady -- Jack L. Warner, Producer
|
||||
|
||||
1965 (38th)
|
||||
BEST PICTURE
|
||||
*
|
||||
The Sound of Music -- Robert Wise, Producer
|
||||
|
||||
1966 (39th)
|
||||
BEST PICTURE
|
||||
*
|
||||
A Man for All Seasons -- Fred Zinnemann, Producer
|
||||
|
||||
1967 (40th)
|
||||
BEST PICTURE
|
||||
*
|
||||
In the Heat of the Night -- Walter Mirisch, Producer
|
||||
|
||||
1968 (41st)
|
||||
BEST PICTURE
|
||||
*
|
||||
Oliver! -- John Woolf, Producer
|
||||
|
||||
1969 (42nd)
|
||||
BEST PICTURE
|
||||
*
|
||||
Midnight Cowboy -- Jerome Hellman, Producer
|
||||
|
||||
1970 (43rd)
|
||||
BEST PICTURE
|
||||
*
|
||||
Patton -- Frank McCarthy, Producer
|
||||
|
||||
1971 (44th)
|
||||
BEST PICTURE
|
||||
*
|
||||
The French Connection -- Philip D'Antoni, Producer
|
||||
|
||||
1972 (45th)
|
||||
BEST PICTURE
|
||||
*
|
||||
The Godfather -- Albert S. Ruddy, Producer
|
||||
|
||||
1973 (46th)
|
||||
BEST PICTURE
|
||||
*
|
||||
The Sting -- Tony Bill, Michael Phillips and Julia Phillips, Producers
|
||||
|
||||
1974 (47th)
|
||||
BEST PICTURE
|
||||
*
|
||||
The Godfather Part II -- Francis Ford Coppola, Producer; Gray Frederickson and Fred Roos, Co-Producers
|
||||
|
||||
1975 (48th)
|
||||
BEST PICTURE
|
||||
*
|
||||
One Flew over the Cuckoo's Nest -- Saul Zaentz and Michael Douglas, Producers
|
||||
|
||||
1976 (49th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Rocky -- Irwin Winkler and Robert Chartoff, Producers
|
||||
|
||||
1977 (50th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Annie Hall -- Charles H. Joffe, Producer
|
||||
|
||||
1978 (51st)
|
||||
BEST PICTURE
|
||||
*
|
||||
The Deer Hunter -- Barry Spikings, Michael Deeley, Michael Cimino and John Peverall, Producers
|
||||
|
||||
1979 (52nd)
|
||||
BEST PICTURE
|
||||
*
|
||||
Kramer vs. Kramer -- Stanley R. Jaffe, Producer
|
||||
|
||||
1980 (53rd)
|
||||
BEST PICTURE
|
||||
*
|
||||
Ordinary People -- Ronald L. Schwary, Producer
|
||||
|
||||
1981 (54th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Chariots of Fire -- David Puttnam, Producer
|
||||
|
||||
1982 (55th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Gandhi -- Richard Attenborough, Producer
|
||||
|
||||
1983 (56th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Terms of Endearment -- James L. Brooks, Producer
|
||||
|
||||
1984 (57th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Amadeus -- Saul Zaentz, Producer
|
||||
|
||||
1985 (58th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Out of Africa -- Sydney Pollack, Producer
|
||||
|
||||
1986 (59th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Platoon -- Arnold Kopelson, Producer
|
||||
|
||||
1987 (60th)
|
||||
BEST PICTURE
|
||||
*
|
||||
The Last Emperor -- Jeremy Thomas, Producer
|
||||
|
||||
1988 (61st)
|
||||
BEST PICTURE
|
||||
*
|
||||
Rain Man -- Mark Johnson, Producer
|
||||
|
||||
1989 (62nd)
|
||||
BEST PICTURE
|
||||
*
|
||||
Driving Miss Daisy -- Richard D. Zanuck and Lili Fini Zanuck, Producers
|
||||
|
||||
1990 (63rd)
|
||||
BEST PICTURE
|
||||
*
|
||||
Dances With Wolves -- Jim Wilson and Kevin Costner, Producers
|
||||
|
||||
1991 (64th)
|
||||
BEST PICTURE
|
||||
*
|
||||
The Silence of the Lambs -- Edward Saxon, Kenneth Utt and Ron Bozman, Producers
|
||||
|
||||
1992 (65th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Unforgiven -- Clint Eastwood, Producer
|
||||
|
||||
1993 (66th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Schindler's List -- Steven Spielberg, Gerald R. Molen and Branko Lustig, Producers
|
||||
|
||||
1994 (67th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Forrest Gump -- Wendy Finerman, Steve Tisch and Steve Starkey, Producers
|
||||
|
||||
1995 (68th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Braveheart -- Mel Gibson, Alan Ladd, Jr. and Bruce Davey, Producers
|
||||
|
||||
1996 (69th)
|
||||
BEST PICTURE
|
||||
*
|
||||
The English Patient -- Saul Zaentz, Producer
|
||||
|
||||
1997 (70th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Titanic -- James Cameron and Jon Landau, Producers
|
||||
|
||||
1998 (71st)
|
||||
BEST PICTURE
|
||||
*
|
||||
Shakespeare in Love -- David Parfitt, Donna Gigliotti, Harvey Weinstein, Edward Zwick and Marc Norman, Producers
|
||||
|
||||
1999 (72nd)
|
||||
BEST PICTURE
|
||||
*
|
||||
American Beauty -- Bruce Cohen and Dan Jinks, Producers
|
||||
|
||||
2000 (73rd)
|
||||
BEST PICTURE
|
||||
*
|
||||
Gladiator -- Douglas Wick, David Franzoni and Branko Lustig, Producers
|
||||
|
||||
2001 (74th)
|
||||
BEST PICTURE
|
||||
*
|
||||
A Beautiful Mind -- Brian Grazer and Ron Howard, Producers
|
||||
|
||||
2002 (75th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Chicago -- Martin Richards, Producer
|
||||
|
||||
2003 (76th)
|
||||
BEST PICTURE
|
||||
*
|
||||
The Lord of the Rings: The Return of the King -- Barrie M. Osborne, Peter Jackson and Fran Walsh, Producers
|
||||
|
||||
2004 (77th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Million Dollar Baby -- Clint Eastwood, Albert S. Ruddy and Tom Rosenberg, Producers
|
||||
|
||||
2005 (78th)
|
||||
BEST PICTURE
|
||||
*
|
||||
Crash -- Paul Haggis and Cathy Schulman, Producers
|
||||
|
||||
2006 (79th)
|
||||
BEST PICTURE
|
||||
*
|
||||
The Departed -- Graham King, Producer
|
||||
© Academy of Motion Picture Arts and Sciences
|
Binary file not shown.
After Width: | Height: | Size: 222 B |
Binary file not shown.
After Width: | Height: | Size: 4.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user