8197554: Create test for SwingSet TableDemo

Reviewed-by: serb
This commit is contained in:
Abdul Kolarkunnu 2018-03-16 14:12:12 +05:30
parent a359ed6dcf
commit e6587461a4
15 changed files with 2499 additions and 0 deletions

View 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());
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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();
}
});
}
}

View File

@ -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

View File

@ -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