Inital commit
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package sample.spreadsheet.gui;
|
||||
|
||||
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
||||
import com.google.gdata.data.spreadsheet.CellEntry;
|
||||
import com.google.gdata.data.spreadsheet.CellFeed;
|
||||
import com.google.gdata.util.ServiceException;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Point;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
/**
|
||||
* Widget for displaying and editing a spreadsheet.
|
||||
*
|
||||
* This is just for demonstrative purposes, it is not very featureful.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class CellBasedSpreadsheetPanel extends JPanel {
|
||||
|
||||
/** The underlying Google Spreadsheets service. */
|
||||
private SpreadsheetService service;
|
||||
|
||||
/** The URL of the cell feed. */
|
||||
private URL cellFeedUrl;
|
||||
|
||||
private SpreadsheetTableModel model;
|
||||
private JTable table;
|
||||
private JButton refreshButton;
|
||||
|
||||
/**
|
||||
* Creates the cell-based spreadsheet widget.
|
||||
*
|
||||
* @param service the Google Spreadsheets service to connect to
|
||||
* @param cellFeedUrl the URL of the cell feed
|
||||
*/
|
||||
public CellBasedSpreadsheetPanel(
|
||||
SpreadsheetService service, URL cellFeedUrl) {
|
||||
this.service = service;
|
||||
this.cellFeedUrl = cellFeedUrl;
|
||||
model = new SpreadsheetTableModel();
|
||||
initializeGui();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a cell at the specified row and column.
|
||||
*
|
||||
* @return the newly set cell, returned back from the server
|
||||
*/
|
||||
private CellEntry actuallySetCell(int row, int col, String valueOrFormula) {
|
||||
try {
|
||||
// This method ignores collisions. Use update() if you are afraid
|
||||
// of overwriting other users' data.
|
||||
CellEntry entry = new CellEntry(row, col, valueOrFormula);
|
||||
return service.insert(cellFeedUrl, entry);
|
||||
} catch (IOException ioe) {
|
||||
SpreadsheetApiDemo.showErrorBox(ioe);
|
||||
return null;
|
||||
} catch (ServiceException se) {
|
||||
SpreadsheetApiDemo.showErrorBox(se);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all cells.
|
||||
*
|
||||
* This just calls the method getAllCells in cellFellFeedHelper.
|
||||
*/
|
||||
private CellFeed getCellFeed() {
|
||||
try {
|
||||
return service.getFeed(cellFeedUrl, CellFeed.class);
|
||||
} catch (IOException ioe) {
|
||||
SpreadsheetApiDemo.showErrorBox(ioe);
|
||||
return null;
|
||||
} catch (ServiceException se) {
|
||||
SpreadsheetApiDemo.showErrorBox(se);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// -- Mostly GUI code from here on down --
|
||||
|
||||
/**
|
||||
* The Swing model for the spreadsheet.
|
||||
*
|
||||
* This is mostly GUI code.
|
||||
*/
|
||||
private class SpreadsheetTableModel extends AbstractTableModel {
|
||||
|
||||
/** All the cells indexed for easy display purposes. */
|
||||
private Map<Point, CellEntry> cells = new HashMap<Point, CellEntry>();
|
||||
|
||||
/** The last row to display (1-based). */
|
||||
private int maxRow;
|
||||
|
||||
/** The last column to display (1-based). */
|
||||
private int maxCol;
|
||||
|
||||
|
||||
public SpreadsheetTableModel() {
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load all the cells from Google Spreadsheets.
|
||||
*/
|
||||
public synchronized void refresh() {
|
||||
cells.clear();
|
||||
|
||||
CellFeed cellFeed = getCellFeed();
|
||||
|
||||
if (cellFeed != null) {
|
||||
for (CellEntry entry : cellFeed.getEntries()) {
|
||||
doAddCell(entry);
|
||||
}
|
||||
}
|
||||
|
||||
int oldMaxRow = maxRow;
|
||||
int oldMaxCol = maxCol;
|
||||
|
||||
maxRow = cellFeed.getRowCount();
|
||||
maxCol = cellFeed.getColCount();
|
||||
|
||||
fireTableDataChanged();
|
||||
|
||||
if (maxRow != oldMaxRow || maxCol != oldMaxCol) {
|
||||
fireTableStructureChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the Swing method for handling cell edits.
|
||||
*/
|
||||
public void setValueAt(Object value, int screenRow, int screenCol) {
|
||||
int row = screenRow + 1; // account for the fact Swing is 0-indexed
|
||||
int col = screenCol + 1;
|
||||
|
||||
// Pop up a little window to indicate that this is busy.
|
||||
JFrame statusIndicatorFrame = new JFrame();
|
||||
statusIndicatorFrame.getContentPane().add(new JButton("Updating..."));
|
||||
statusIndicatorFrame.setVisible(true);
|
||||
statusIndicatorFrame.setSize(200, 100);
|
||||
|
||||
CellEntry entry = actuallySetCell(row, col, value.toString());
|
||||
|
||||
if (entry != null) {
|
||||
doAddCell(entry);
|
||||
}
|
||||
|
||||
statusIndicatorFrame.dispose();
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
/** Tells Swing how many rows are in this table. */
|
||||
public int getRowCount() {
|
||||
return maxRow; // Allow user to insert up to two rows
|
||||
}
|
||||
|
||||
/** Tells Swing how many columns are in this table. */
|
||||
public int getColumnCount() {
|
||||
return maxCol;
|
||||
}
|
||||
|
||||
/** Gets the cached version of the specified cell. */
|
||||
public CellEntry getCell(int row, int col) {
|
||||
return cells.get(new Point(row, col));
|
||||
}
|
||||
|
||||
/** Tells Swing the value at a particular location. */
|
||||
public Object getValueAt(int screenRow, int screenCol) {
|
||||
CellEntry cell = getCell(screenRow + 1, screenCol + 1);
|
||||
if (cell == null) {
|
||||
return null;
|
||||
} else {
|
||||
return cell.getCell().getValue();
|
||||
}
|
||||
}
|
||||
|
||||
public void addCell(CellEntry entry) {
|
||||
doAddCell(entry);
|
||||
}
|
||||
|
||||
|
||||
private void doAddCell(CellEntry entry) {
|
||||
int row = entry.getCell().getRow();
|
||||
int col = entry.getCell().getCol();
|
||||
|
||||
cells.put(new Point(row, col), entry);
|
||||
}
|
||||
|
||||
/** Tells Swing whether the cell is editable. */
|
||||
public boolean isCellEditable(int screenRow, int screenCol) {
|
||||
CellEntry cell = getCell(screenRow + 1, screenCol + 1);
|
||||
|
||||
if (cell == null) {
|
||||
// Although this can be wrong, assume editable unless told otherwise.
|
||||
return true;
|
||||
} else {
|
||||
return cell.getEditLink() != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static JFrame createWindow(
|
||||
SpreadsheetService service, URL cellFeedUrl) {
|
||||
JFrame frame = new JFrame();
|
||||
frame.setSize(600, 480);
|
||||
frame.getContentPane().add(new CellBasedSpreadsheetPanel(
|
||||
service, cellFeedUrl));
|
||||
frame.setVisible(true);
|
||||
frame.setTitle("Cells Demo - Positional Editing");
|
||||
return frame;
|
||||
}
|
||||
|
||||
private void initializeGui() {
|
||||
table = new JTable(model);
|
||||
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
||||
JScrollPane scrollpane = new JScrollPane(table);
|
||||
setLayout(new BorderLayout());
|
||||
add(scrollpane, BorderLayout.CENTER);
|
||||
refreshButton = new JButton("Refresh");
|
||||
refreshButton.addActionListener(new ActionHandler());
|
||||
add(refreshButton, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
private class ActionHandler implements ActionListener {
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
if (ae.getSource() == refreshButton) {
|
||||
model.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,365 @@
|
||||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package sample.spreadsheet.gui;
|
||||
|
||||
import com.google.gdata.client.spreadsheet.FeedURLFactory;
|
||||
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
||||
import com.google.gdata.data.spreadsheet.SpreadsheetEntry;
|
||||
import com.google.gdata.data.spreadsheet.SpreadsheetFeed;
|
||||
import com.google.gdata.data.spreadsheet.WorksheetEntry;
|
||||
import com.google.gdata.data.spreadsheet.WorksheetFeed;
|
||||
import com.google.gdata.util.ServiceException;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
/**
|
||||
* Window for selecting a spreadsheet.
|
||||
*
|
||||
* This is a little bit of a complicated class, but the main GData
|
||||
* parts to know are:
|
||||
*
|
||||
* - populateSpreadsheetList just makes a few calls in order to
|
||||
* get a list of spreadsheets
|
||||
* - populateWorksheetList will get a list of worksheets within
|
||||
* that spreadsheet
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ChooseSpreadsheetFrame extends JFrame {
|
||||
|
||||
/** The Google Spreadsheets GData service. */
|
||||
private SpreadsheetService service;
|
||||
|
||||
private FeedURLFactory factory;
|
||||
|
||||
private List<SpreadsheetEntry> spreadsheetEntries;
|
||||
|
||||
private JList spreadsheetListBox;
|
||||
|
||||
private List<WorksheetEntry> worksheetEntries;
|
||||
|
||||
private JList worksheetListBox;
|
||||
|
||||
private JTextField ajaxLinkField;
|
||||
|
||||
private JTextField worksheetsFeedUrlField;
|
||||
|
||||
private JTextField cellsFeedUrlField;
|
||||
|
||||
private JTextField listFeedUrlField;
|
||||
|
||||
private JButton viewWorksheetsButton;
|
||||
|
||||
private JButton submitCellsButton;
|
||||
|
||||
private JButton submitListButton;
|
||||
|
||||
|
||||
/** Starts the selection off with a spreadsheet feed helper. */
|
||||
public ChooseSpreadsheetFrame(SpreadsheetService spreadsheetService) {
|
||||
service = spreadsheetService;
|
||||
factory = FeedURLFactory.getDefault();
|
||||
initializeGui();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the list of spreadsheets, and fills the list box.
|
||||
*/
|
||||
private void populateSpreadsheetList() {
|
||||
if (retrieveSpreadsheetList()) {
|
||||
fillSpreadsheetListBox();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks Google Spreadsheets for a list of all the spreadsheets
|
||||
* the user has access to.
|
||||
* @return true if successful
|
||||
*/
|
||||
private boolean retrieveSpreadsheetList() {
|
||||
SpreadsheetFeed feed;
|
||||
|
||||
try {
|
||||
feed = service.getFeed(
|
||||
factory.getSpreadsheetsFeedUrl(), SpreadsheetFeed.class);
|
||||
} catch (IOException e) {
|
||||
SpreadsheetApiDemo.showErrorBox(e);
|
||||
return false;
|
||||
} catch (ServiceException e) {
|
||||
SpreadsheetApiDemo.showErrorBox(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.spreadsheetEntries = feed.getEntries();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills up the list-box of spreadsheets with the already-computed entries.
|
||||
*/
|
||||
private void fillSpreadsheetListBox() {
|
||||
String[] stringsForListbox = new String[spreadsheetEntries.size()];
|
||||
|
||||
for (int i = 0; i < spreadsheetEntries.size(); i++) {
|
||||
SpreadsheetEntry entry = spreadsheetEntries.get(i);
|
||||
|
||||
// Title of Spreadsheet (author, updated 2006-6-20 7:30PM)
|
||||
stringsForListbox[i] =
|
||||
entry.getTitle().getPlainText()
|
||||
+ " (" + entry.getAuthors().get(0).getEmail()
|
||||
+ ", updated " + entry.getUpdated().toUiString()
|
||||
+ ")";
|
||||
}
|
||||
|
||||
spreadsheetListBox.setListData(stringsForListbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of worksheets in the specified spreadsheet,
|
||||
* and fills the list box.
|
||||
* @param spreadsheet the selected spreadsheet
|
||||
*/
|
||||
private void populateWorksheetList(SpreadsheetEntry spreadsheet) {
|
||||
if (retrieveWorksheetList(spreadsheet)) {
|
||||
fillWorksheetListBox(spreadsheet.getTitle().getPlainText());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of worksheets from Google Spreadsheets.
|
||||
* @param spreadsheet the spreadsheet to get a list of worksheets for
|
||||
* @return true if successful
|
||||
*/
|
||||
private boolean retrieveWorksheetList(SpreadsheetEntry spreadsheet) {
|
||||
WorksheetFeed feed;
|
||||
|
||||
try {
|
||||
feed = service.getFeed(
|
||||
spreadsheet.getWorksheetFeedUrl(), WorksheetFeed.class);
|
||||
} catch (IOException e) {
|
||||
SpreadsheetApiDemo.showErrorBox(e);
|
||||
return false;
|
||||
} catch (ServiceException e) {
|
||||
SpreadsheetApiDemo.showErrorBox(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.worksheetEntries = feed.getEntries();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fills up the list-box of worksheets with the already computed entries.
|
||||
*/
|
||||
private void fillWorksheetListBox(String spreadsheetTitle) {
|
||||
String[] stringsForListbox = new String[worksheetEntries.size()];
|
||||
|
||||
for (int i = 0; i < worksheetEntries.size(); i++) {
|
||||
WorksheetEntry entry = worksheetEntries.get(i);
|
||||
|
||||
// Title Of Worksheet (T)
|
||||
stringsForListbox[i] = entry.getTitle().getPlainText()
|
||||
+ " (in " + spreadsheetTitle + ")";
|
||||
}
|
||||
|
||||
worksheetListBox.setListData(stringsForListbox);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles when a user presses the "View Worksheets" button.
|
||||
*
|
||||
*/
|
||||
private void handleViewWorksheetsButton() {
|
||||
int selected = spreadsheetListBox.getSelectedIndex();
|
||||
|
||||
if (spreadsheetEntries != null && selected >= 0) {
|
||||
populateWorksheetList(spreadsheetEntries.get(selected));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles when a user presses a "View Cells Demo" button.
|
||||
*/
|
||||
private void handleSubmitCellsButton() {
|
||||
int selected = worksheetListBox.getSelectedIndex();
|
||||
|
||||
if (worksheetEntries != null && selected >= 0) {
|
||||
CellBasedSpreadsheetPanel.createWindow(
|
||||
service, worksheetEntries.get(selected).getCellFeedUrl());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles when a user presses a "View List Demo" button.
|
||||
*/
|
||||
private void handleSubmitListButton() {
|
||||
int selected = worksheetListBox.getSelectedIndex();
|
||||
|
||||
if (worksheetEntries != null && selected >= 0) {
|
||||
ListBasedSpreadsheetPanel.createWindow(service,
|
||||
worksheetEntries.get(selected).getListFeedUrl());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the feed URL's as you select spreadsheets.
|
||||
*/
|
||||
private void handleSpreadsheetSelection() {
|
||||
int selected = spreadsheetListBox.getSelectedIndex();
|
||||
|
||||
if (spreadsheetEntries != null && selected >= 0) {
|
||||
SpreadsheetEntry entry = spreadsheetEntries.get(selected);
|
||||
|
||||
ajaxLinkField.setText(
|
||||
entry.getHtmlLink().getHref());
|
||||
worksheetsFeedUrlField.setText(
|
||||
entry.getWorksheetFeedUrl().toExternalForm());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the feed URL's as you select worksheets within a spreadsheets.
|
||||
*/
|
||||
private void handleWorksheetSelection() {
|
||||
int selected = worksheetListBox.getSelectedIndex();
|
||||
|
||||
if (worksheetEntries != null && selected >= 0) {
|
||||
WorksheetEntry entry = worksheetEntries.get(selected);
|
||||
|
||||
cellsFeedUrlField.setText(entry.getCellFeedUrl().toExternalForm());
|
||||
listFeedUrlField.setText(entry.getListFeedUrl().toExternalForm());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- GUI code from here on down ----------------------------------------
|
||||
|
||||
private void initializeGui() {
|
||||
setTitle("Choose your Spreadsheet");
|
||||
|
||||
Container panel = getContentPane();
|
||||
panel.setLayout(new GridLayout(2, 1));
|
||||
|
||||
// Top part - choose a spreadsheet
|
||||
|
||||
JPanel spreadsheetPanel = new JPanel();
|
||||
spreadsheetPanel.setLayout(new BorderLayout());
|
||||
|
||||
spreadsheetListBox = new JList();
|
||||
spreadsheetPanel.add(new JScrollPane(spreadsheetListBox),
|
||||
BorderLayout.CENTER);
|
||||
spreadsheetListBox.addListSelectionListener(new ActionHandler());
|
||||
|
||||
Container topButtonsPanel = new JPanel();
|
||||
topButtonsPanel.setLayout(new GridLayout(3, 1));
|
||||
|
||||
viewWorksheetsButton = new JButton("View Worksheets");
|
||||
viewWorksheetsButton.addActionListener(new ActionHandler());
|
||||
topButtonsPanel.add(viewWorksheetsButton);
|
||||
panel.add(spreadsheetPanel);
|
||||
|
||||
ajaxLinkField = new JTextField();
|
||||
ajaxLinkField.setEditable(false);
|
||||
topButtonsPanel.add(ajaxLinkField);
|
||||
worksheetsFeedUrlField = new JTextField();
|
||||
worksheetsFeedUrlField.setEditable(false);
|
||||
topButtonsPanel.add(worksheetsFeedUrlField);
|
||||
|
||||
spreadsheetPanel.add(topButtonsPanel, BorderLayout.SOUTH);
|
||||
panel.add(spreadsheetPanel);
|
||||
|
||||
// Bottom part - choose a worksheet
|
||||
|
||||
JPanel worksheetPanel = new JPanel();
|
||||
worksheetPanel.setLayout(new BorderLayout());
|
||||
|
||||
worksheetListBox = new JList(
|
||||
new String[] { "[Please click 'View Worksheets' for a list.]" });
|
||||
worksheetPanel.add(new JScrollPane(worksheetListBox), BorderLayout.CENTER);
|
||||
worksheetListBox.addListSelectionListener(new ActionHandler());
|
||||
|
||||
Container bottomButtonsPanel = new JPanel();
|
||||
bottomButtonsPanel.setLayout(new GridLayout(4, 1));
|
||||
|
||||
submitCellsButton = new JButton("Cells Demo");
|
||||
submitCellsButton.addActionListener(new ActionHandler());
|
||||
bottomButtonsPanel.add(submitCellsButton);
|
||||
|
||||
cellsFeedUrlField = new JTextField();
|
||||
cellsFeedUrlField.setEditable(false);
|
||||
bottomButtonsPanel.add(cellsFeedUrlField);
|
||||
|
||||
submitListButton = new JButton("List Demo");
|
||||
submitListButton.addActionListener(new ActionHandler());
|
||||
bottomButtonsPanel.add(submitListButton);
|
||||
|
||||
listFeedUrlField = new JTextField();
|
||||
listFeedUrlField.setEditable(false);
|
||||
bottomButtonsPanel.add(listFeedUrlField);
|
||||
|
||||
worksheetPanel.add(bottomButtonsPanel, BorderLayout.SOUTH);
|
||||
panel.add(worksheetPanel);
|
||||
|
||||
populateSpreadsheetList();
|
||||
|
||||
pack();
|
||||
setSize(700, 600);
|
||||
setVisible(true);
|
||||
|
||||
setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
}
|
||||
|
||||
private class ActionHandler
|
||||
implements ActionListener, ListSelectionListener {
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
if (ae.getSource() == viewWorksheetsButton) {
|
||||
handleViewWorksheetsButton();
|
||||
} else if (ae.getSource() == submitCellsButton) {
|
||||
handleSubmitCellsButton();
|
||||
} else if (ae.getSource() == submitListButton) {
|
||||
handleSubmitListButton();
|
||||
}
|
||||
}
|
||||
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
if (e.getSource() == spreadsheetListBox) {
|
||||
handleSpreadsheetSelection();
|
||||
} else if (e.getSource() == worksheetListBox) {
|
||||
handleWorksheetSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,530 @@
|
||||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package sample.spreadsheet.gui;
|
||||
|
||||
import com.google.gdata.client.spreadsheet.ListQuery;
|
||||
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
||||
import com.google.gdata.data.TextContent;
|
||||
import com.google.gdata.data.spreadsheet.CustomElementCollection;
|
||||
import com.google.gdata.data.spreadsheet.ListEntry;
|
||||
import com.google.gdata.data.spreadsheet.ListFeed;
|
||||
import com.google.gdata.util.ServiceException;
|
||||
import com.google.gdata.util.VersionConflictException;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
/**
|
||||
* Widget for displaying and editing a spreadsheet.
|
||||
*
|
||||
* This is just for demonstrative purposes, it is not very featureful.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ListBasedSpreadsheetPanel extends JPanel {
|
||||
|
||||
/** The Google Spreadsheets service. */
|
||||
private SpreadsheetService service;
|
||||
|
||||
/** The list feed URL. */
|
||||
private URL listFeedUrl;
|
||||
|
||||
/** The model that Swing uses to represent the table. */
|
||||
private ListTableModel model;
|
||||
|
||||
/** The table widget. */
|
||||
private JTable table;
|
||||
|
||||
private JButton refreshButton;
|
||||
private JButton deleteOneButton;
|
||||
private JButton revertOneButton;
|
||||
private JButton commitOneButton;
|
||||
private JButton commitAllButton;
|
||||
|
||||
private JTextField fulltextField;
|
||||
private JTextField spreadsheetQueryField;
|
||||
private JTextField orderbyField;
|
||||
|
||||
/**
|
||||
* Creates a list-based spreadsheet editing panel.
|
||||
* @param service the spreadsheet service
|
||||
* @param listFeedUrl the URL of the list feed
|
||||
*/
|
||||
public ListBasedSpreadsheetPanel(
|
||||
SpreadsheetService service, URL listFeedUrl) {
|
||||
this.service = service;
|
||||
this.listFeedUrl = listFeedUrl;
|
||||
model = new ListTableModel();
|
||||
initializeGui();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes the contents of the table, applying any queries the user
|
||||
* specifies.
|
||||
*/
|
||||
private void refreshFromServer() {
|
||||
try {
|
||||
ListQuery query = new ListQuery(listFeedUrl);
|
||||
|
||||
if (!fulltextField.getText().equals("")) {
|
||||
query.setFullTextQuery(fulltextField.getText());
|
||||
}
|
||||
if (!spreadsheetQueryField.getText().equals("")) {
|
||||
query.setSpreadsheetQuery(spreadsheetQueryField.getText());
|
||||
}
|
||||
if (!orderbyField.getText().equals("")) {
|
||||
query.setOrderBy(orderbyField.getText());
|
||||
}
|
||||
|
||||
ListFeed feed = service.query(query, ListFeed.class);
|
||||
|
||||
model.resetEntries(feed.getEntries());
|
||||
} catch (ServiceException e) {
|
||||
SpreadsheetApiDemo.showErrorBox(e);
|
||||
} catch (IOException e) {
|
||||
SpreadsheetApiDemo.showErrorBox(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class models one particular row in the list, tracking both its old
|
||||
* contents and its new contents.
|
||||
*
|
||||
* This is responsible for the "commit/revert/delete" behavior that you
|
||||
* see in the GUI.
|
||||
*/
|
||||
private class ListEntryModel {
|
||||
|
||||
/**
|
||||
* The original entry downloaded.
|
||||
* If this is an entry to add, originalEntry will be null.
|
||||
*/
|
||||
private ListEntry originalEntry = null;
|
||||
|
||||
/**
|
||||
* The new contents to add.
|
||||
* If this is not being edited, this will be null.
|
||||
*/
|
||||
private CustomElementCollection newContents = null;
|
||||
|
||||
/** Makes an existing row to be edited. */
|
||||
public ListEntryModel(ListEntry originalEntry) {
|
||||
this.originalEntry = originalEntry;
|
||||
}
|
||||
|
||||
/** Creates a blank row to be edited. */
|
||||
public ListEntryModel() {
|
||||
}
|
||||
|
||||
/** Gets the visible contents of a particular column. */
|
||||
public String getContents(String column) {
|
||||
String result = null;
|
||||
|
||||
if (newContents != null) {
|
||||
result = newContents.getValue(column);
|
||||
} else if (originalEntry != null) {
|
||||
result = originalEntry.getCustomElements().getValue(column);
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
result = "";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Gets whether this row neither has data nor is being edited. */
|
||||
public boolean isBlank() {
|
||||
return originalEntry == null && newContents == null;
|
||||
}
|
||||
|
||||
/** Gets whether this row is oepn for edit. */
|
||||
public boolean isBeingEdited() {
|
||||
return newContents != null;
|
||||
}
|
||||
|
||||
/** Open the row up for editing. */
|
||||
public void startEdit() {
|
||||
newContents = new CustomElementCollection();
|
||||
if (originalEntry != null) {
|
||||
newContents.replaceWithLocal(originalEntry.getCustomElements());
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets the contents of a particular cell. */
|
||||
public void setContents(String column, String newText) {
|
||||
if (!isBeingEdited()) {
|
||||
startEdit();
|
||||
}
|
||||
|
||||
newContents.setValueLocal(column, newText);
|
||||
}
|
||||
|
||||
/** Loses all changes. */
|
||||
public void revert() {
|
||||
newContents = null;
|
||||
}
|
||||
|
||||
/** Actually adds this new entry to the spreadsheet. */
|
||||
private void doAddNew() throws ServiceException, IOException {
|
||||
ListEntry newEntry = new ListEntry();
|
||||
newEntry.getCustomElements().replaceWithLocal(newContents);
|
||||
originalEntry = service.insert(listFeedUrl, newEntry);
|
||||
newContents = null;
|
||||
}
|
||||
|
||||
/** Actually updates an existing entry on the spreadsheet,
|
||||
* checking for edit conflicts. */
|
||||
private void doUpdateExisting() throws ServiceException, IOException {
|
||||
try {
|
||||
originalEntry.getCustomElements().replaceWithLocal(newContents);
|
||||
originalEntry = originalEntry.update();
|
||||
newContents = null;
|
||||
} catch (VersionConflictException e) {
|
||||
originalEntry = originalEntry.getSelf();
|
||||
TextContent content = (TextContent) originalEntry.getContent();
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"Someone has edited the row in the meantime to:\n"
|
||||
+ originalEntry.getTitle().getPlainText()
|
||||
+ " (" + content.getContent().getPlainText() + ")\n"
|
||||
+ "Commit again to confirm.",
|
||||
"Version Conflict",
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
/** Commits all changes. */
|
||||
public void commit() {
|
||||
if (isBeingEdited()) {
|
||||
boolean success = false;
|
||||
|
||||
try {
|
||||
if (originalEntry != null) {
|
||||
doUpdateExisting();
|
||||
} else {
|
||||
doAddNew();
|
||||
}
|
||||
|
||||
success = true;
|
||||
} catch (ServiceException e) {
|
||||
SpreadsheetApiDemo.showErrorBox(e);
|
||||
} catch (IOException e) {
|
||||
SpreadsheetApiDemo.showErrorBox(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Deletes this entry from the backend, but not from the list. */
|
||||
public void delete() {
|
||||
if (originalEntry != null) {
|
||||
try {
|
||||
originalEntry.delete();
|
||||
} catch (ServiceException e) {
|
||||
SpreadsheetApiDemo.showErrorBox(e);
|
||||
} catch (IOException e) {
|
||||
SpreadsheetApiDemo.showErrorBox(e);
|
||||
}
|
||||
}
|
||||
originalEntry = null;
|
||||
newContents = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Swing model for the spreadsheet.
|
||||
*
|
||||
* This is mostly GUI code.
|
||||
*/
|
||||
private class ListTableModel extends AbstractTableModel {
|
||||
|
||||
/** The name of each column (in the XML). */
|
||||
private List<String> columnNames = new ArrayList<String>();
|
||||
|
||||
/** All entries of the list. */
|
||||
private List<ListEntryModel> list = new ArrayList<ListEntryModel>();
|
||||
|
||||
|
||||
/**
|
||||
* Resets all the entries from a new list.
|
||||
*
|
||||
* This also tries to figure out what the set of valid columns is.
|
||||
*/
|
||||
public synchronized void resetEntries(List<ListEntry> entries) {
|
||||
TreeSet<String> columnSet = new TreeSet<String>();
|
||||
|
||||
list.clear();
|
||||
columnNames.clear();
|
||||
|
||||
for (ListEntry entry : entries) {
|
||||
list.add(new ListEntryModel(entry));
|
||||
columnSet.addAll(entry.getCustomElements().getTags());
|
||||
}
|
||||
|
||||
// Always have an empty row to edit.
|
||||
list.add(new ListEntryModel());
|
||||
|
||||
columnNames.add("(Edit)");
|
||||
columnNames.addAll(columnSet);
|
||||
|
||||
fireTableStructureChanged();
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
/** Writes back all modified entries to the actual spreadsheet. */
|
||||
public synchronized void commitAll() {
|
||||
for (ListEntryModel entryModel : list) {
|
||||
entryModel.commit();
|
||||
}
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
/** Reverts all entries, losing all changes. */
|
||||
public synchronized void revertAll() {
|
||||
for (ListEntryModel entryModel : list) {
|
||||
entryModel.revert();
|
||||
}
|
||||
fireTableDataChanged();
|
||||
}
|
||||
|
||||
/** Delete one entry by index. */
|
||||
public synchronized void deleteOne(int row) {
|
||||
if (!list.get(row).isBeingEdited()) {
|
||||
list.get(row).delete();
|
||||
list.remove(row);
|
||||
fireTableRowsDeleted(row, row);
|
||||
}
|
||||
}
|
||||
|
||||
/** Commit one entry by index. */
|
||||
public synchronized void commitOne(int row) {
|
||||
if (row >= 0 && row < list.size()) {
|
||||
if (list.get(row).isBeingEdited()) {
|
||||
list.get(row).commit();
|
||||
fireTableRowsUpdated(row, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Revert one entry by index. */
|
||||
public synchronized void revertOne(int row) {
|
||||
if (list.get(row).isBeingEdited()) {
|
||||
list.get(row).revert();
|
||||
fireTableRowsUpdated(row, row);
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets whether this is the special column. */
|
||||
private boolean isSpecialColumn(int col) {
|
||||
return col == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the Swing method for handling cell edits.
|
||||
*/
|
||||
public synchronized void setValueAt(Object value, int row, int col) {
|
||||
ListEntryModel entryModel = list.get(row);
|
||||
|
||||
if (isSpecialColumn(col)) {
|
||||
setRowEditing(row, ((Boolean) value).booleanValue());
|
||||
} else {
|
||||
setRowEditing(row, true);
|
||||
entryModel.setContents(columnNames.get(col), value.toString());
|
||||
fireTableCellUpdated(row, col);
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets whether a row is being edited. */
|
||||
private void setRowEditing(int row, boolean edit) {
|
||||
ListEntryModel entryModel = list.get(row);
|
||||
|
||||
if (edit && !entryModel.isBeingEdited()) {
|
||||
if (entryModel.isBlank()) {
|
||||
// Always have at least two blank rows.
|
||||
list.add(new ListEntryModel());
|
||||
fireTableRowsInserted(list.size() - 1, list.size() - 1);
|
||||
}
|
||||
entryModel.startEdit();
|
||||
fireTableRowsUpdated(row, row);
|
||||
} else if (!edit) {
|
||||
commitOne(row);
|
||||
}
|
||||
}
|
||||
|
||||
/** Tells Swing the value at a particular location. */
|
||||
public synchronized Object getValueAt(int row, int col) {
|
||||
ListEntryModel entryModel = list.get(row);
|
||||
|
||||
if (isSpecialColumn(col)) {
|
||||
return Boolean.valueOf(entryModel.isBeingEdited());
|
||||
} else {
|
||||
return entryModel.getContents(columnNames.get(col));
|
||||
}
|
||||
}
|
||||
|
||||
/** Tells Swing whether the cell is editable. */
|
||||
public synchronized boolean isCellEditable(int row, int col) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Gets the column name by index. */
|
||||
public synchronized String getColumnName(int columnIndex) {
|
||||
return columnNames.get(columnIndex);
|
||||
}
|
||||
|
||||
/** Gets the column class for editing. */
|
||||
public synchronized Class<?> getColumnClass(int columnIndex) {
|
||||
if (isSpecialColumn(columnIndex)) {
|
||||
return Boolean.class;
|
||||
} else {
|
||||
return String.class;
|
||||
}
|
||||
}
|
||||
|
||||
/** Tells Swing how many rows are in this table. */
|
||||
public synchronized int getRowCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
/** Tells Swing how many columns are in this table. */
|
||||
public synchronized int getColumnCount() {
|
||||
return columnNames.size();
|
||||
}
|
||||
}
|
||||
|
||||
// GUI code
|
||||
|
||||
public static JFrame createWindow(SpreadsheetService service,
|
||||
URL listFeedUrl) {
|
||||
JFrame frame = new JFrame();
|
||||
frame.setSize(600, 480);
|
||||
frame.getContentPane().add(new ListBasedSpreadsheetPanel(
|
||||
service, listFeedUrl));
|
||||
frame.setVisible(true);
|
||||
frame.setTitle("List Demo - Row-based Editing");
|
||||
return frame;
|
||||
}
|
||||
|
||||
private void initializeGui() {
|
||||
table = new JTable(model);
|
||||
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
|
||||
JScrollPane scrollpane = new JScrollPane(table);
|
||||
setLayout(new BorderLayout());
|
||||
add(scrollpane, BorderLayout.CENTER);
|
||||
|
||||
Container southPanel = new JPanel();
|
||||
southPanel.setLayout(new GridBagLayout());
|
||||
|
||||
deleteOneButton = new JButton("Delete");
|
||||
deleteOneButton.addActionListener(new ActionHandler());
|
||||
southPanel.add(deleteOneButton, getTopConstraints(0));
|
||||
revertOneButton = new JButton("Revert");
|
||||
revertOneButton.addActionListener(new ActionHandler());
|
||||
southPanel.add(revertOneButton, getTopConstraints(1));
|
||||
commitOneButton = new JButton("Commit");
|
||||
commitOneButton.addActionListener(new ActionHandler());
|
||||
southPanel.add(commitOneButton, getTopConstraints(2));
|
||||
commitAllButton = new JButton("Commit All");
|
||||
commitAllButton.addActionListener(new ActionHandler());
|
||||
southPanel.add(commitAllButton, getTopConstraints(3));
|
||||
refreshButton = new JButton("Refresh");
|
||||
refreshButton.addActionListener(new ActionHandler());
|
||||
southPanel.add(refreshButton, getTopConstraints(4));
|
||||
|
||||
southPanel.add(new JLabel("Full text:"), getLeftConstraints(1));
|
||||
fulltextField = new JTextField();
|
||||
southPanel.add(fulltextField, getRightConstraints(1));
|
||||
|
||||
southPanel.add(new JLabel("Structured:"), getLeftConstraints(2));
|
||||
spreadsheetQueryField = new JTextField();
|
||||
southPanel.add(spreadsheetQueryField, getRightConstraints(2));
|
||||
|
||||
southPanel.add(new JLabel("Order By:"), getLeftConstraints(3));
|
||||
orderbyField = new JTextField();
|
||||
southPanel.add(orderbyField, getRightConstraints(3));
|
||||
|
||||
add(southPanel, BorderLayout.SOUTH);
|
||||
|
||||
refreshFromServer();
|
||||
}
|
||||
|
||||
private GridBagConstraints getTopConstraints(int col) {
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
|
||||
c.gridy = 0;
|
||||
c.gridx = col;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
private GridBagConstraints getLeftConstraints(int row) {
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
|
||||
c.gridy = row;
|
||||
c.gridx = 0;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
private GridBagConstraints getRightConstraints(int row) {
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
|
||||
c.gridy = row;
|
||||
c.gridx = 1;
|
||||
c.gridwidth = 4;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
c.weightx = 1.0; // take up as much space as possible
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
private class ActionHandler implements ActionListener {
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
if (ae.getSource() == refreshButton) {
|
||||
refreshFromServer();
|
||||
} else if (ae.getSource() == deleteOneButton) {
|
||||
model.deleteOne(table.getSelectedRow());
|
||||
} else if (ae.getSource() == revertOneButton) {
|
||||
model.revertOne(table.getSelectedRow());
|
||||
} else if (ae.getSource() == commitOneButton) {
|
||||
model.commitOne(table.getSelectedRow());
|
||||
} else if (ae.getSource() == commitAllButton) {
|
||||
model.commitAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package sample.spreadsheet.gui;
|
||||
|
||||
import com.google.gdata.client.spreadsheet.ListQuery;
|
||||
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
||||
import com.google.gdata.data.spreadsheet.ListEntry;
|
||||
import com.google.gdata.data.spreadsheet.ListFeed;
|
||||
import com.google.gdata.util.ServiceException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This class helps you access your spreadsheet like a list or like a
|
||||
* database.
|
||||
*
|
||||
*
|
||||
* In this model, each row is treated like a separate entry, with multiple
|
||||
* fields. Each field is named based on the top row of your speradsheet.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class ListFeedHelper {
|
||||
|
||||
/** The SpreadsheetService to contact Google with. */
|
||||
private SpreadsheetService service;
|
||||
|
||||
/** List feed URL. */
|
||||
private URL feedUrl;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a list feed helper for a particular URL.
|
||||
*
|
||||
* @param inService the SpreadsheetService to contact Google with
|
||||
* @param inFeedUrl the URL of the list feed; to get this URL, you can
|
||||
* use SpreadsheetFeedHelper, or if you have a WorksheetEntry
|
||||
* you can use its method to get the list feed URL
|
||||
*/
|
||||
public ListFeedHelper(SpreadsheetService inService, URL inFeedUrl) {
|
||||
service = inService;
|
||||
feedUrl = inFeedUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new list entry to the spreadsheet.
|
||||
*
|
||||
* @param entry the new entry
|
||||
* @throws IOException if there was a problem contacting Google
|
||||
* @throws ServiceException if there was an error processnig the request
|
||||
*/
|
||||
public ListEntry addListEntry(ListEntry entry)
|
||||
throws IOException, ServiceException {
|
||||
return service.insert(feedUrl, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all the list entries.
|
||||
*
|
||||
* @return a list of all non-empty rows in the spreadsheet
|
||||
* @throws IOException if there was a problem contacting Google
|
||||
* @throws ServiceException if there was an error processnig the request
|
||||
*/
|
||||
public List<ListEntry> getAllListEntries()
|
||||
throws IOException, ServiceException {
|
||||
ListQuery query = new ListQuery(feedUrl);
|
||||
ListFeed feed = service.query(query, ListFeed.class);
|
||||
return feed.getEntries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all entries that match a full-text search.
|
||||
*
|
||||
* Full-text searches look for the keywords you specify, that may
|
||||
* occur in any order in the row. Right now only the simplest syntax
|
||||
* is supported, as a convenience feature.
|
||||
*
|
||||
* @param search the search string like "adam technical writer"
|
||||
* @return all matching entries
|
||||
* @throws IOException if there was a problem contacting Google
|
||||
* @throws ServiceException if there was an error processnig the request
|
||||
*/
|
||||
public List<ListEntry> getFullTextSearch(String search)
|
||||
throws IOException, ServiceException {
|
||||
ListQuery query = new ListQuery(feedUrl);
|
||||
query.setFullTextQuery(search);
|
||||
ListFeed feed = service.query(query, ListFeed.class);
|
||||
return feed.getEntries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all entries that match a structured query.
|
||||
*
|
||||
* Structured queries are in format:
|
||||
* name = 'adam' and (job = 'technical writer' or job = 'artist')
|
||||
*
|
||||
* In short, it is case-insensitive, supporting both SQL-like and
|
||||
* C-like syntaxes for all varieties of new and seasoned programmers.
|
||||
*
|
||||
* @param structuredQuery the search string
|
||||
* @return all matching entries
|
||||
* @throws IOException if there was a problem contacting Google
|
||||
* @throws ServiceException if there was an error processnig the request
|
||||
*/
|
||||
public List<ListEntry> getStructuredQuery(
|
||||
String structuredQuery)
|
||||
throws IOException, ServiceException {
|
||||
ListQuery query = new ListQuery(feedUrl);
|
||||
query.setFullTextQuery(structuredQuery);
|
||||
ListFeed feed = service.query(query, ListFeed.class);
|
||||
return feed.getEntries();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package sample.spreadsheet.gui;
|
||||
|
||||
import com.google.gdata.client.GoogleService.CaptchaRequiredException;
|
||||
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
||||
import com.google.gdata.util.AuthenticationException;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPasswordField;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
/**
|
||||
* A Swing window for logging in to Google Spreadsheets.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class LoginFrame extends JFrame {
|
||||
|
||||
/** The spreadsheet service. */
|
||||
private SpreadsheetService service;
|
||||
|
||||
/** Field for entering username. */
|
||||
private JTextField usernameField;
|
||||
|
||||
/** Field for entering password. */
|
||||
private JPasswordField passwordField;
|
||||
|
||||
/** Image to display as a CAPTCHA (distorted letters to verify human). */
|
||||
private JLabel captchaImage;
|
||||
|
||||
/** Place where user types the captcha answer. */
|
||||
private JTextField captchaAnswerField;
|
||||
|
||||
/** Button to log in. */
|
||||
private JButton submitButton;
|
||||
|
||||
/**
|
||||
* The captcha token that is issued,
|
||||
* null if there was no CAPTCHA challenge.
|
||||
*/
|
||||
private String captchaToken = null;
|
||||
|
||||
|
||||
/**
|
||||
* Starts out the login window, for a particular service and
|
||||
* feed root, with initial username and password (these can
|
||||
* be blank strings).
|
||||
*/
|
||||
public LoginFrame(SpreadsheetService service,
|
||||
String username, String password) {
|
||||
this.service = service;
|
||||
|
||||
initializeGui();
|
||||
|
||||
usernameField.setText(username);
|
||||
passwordField.setText(password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try authenticating the user with the provided username and
|
||||
* password.
|
||||
*/
|
||||
private boolean authenticate(
|
||||
String username, String password) {
|
||||
try {
|
||||
if (captchaToken == null) {
|
||||
|
||||
// No CAPTCHA challenge was presented.
|
||||
// Proceed to the next step.
|
||||
service.setUserCredentials(username, password);
|
||||
} else {
|
||||
|
||||
// Use the CAPTCHA token and answer to help the
|
||||
// authentication.
|
||||
service.setUserCredentials(username, password, captchaToken,
|
||||
captchaAnswerField.getText());
|
||||
}
|
||||
return true;
|
||||
} catch (CaptchaRequiredException e) {
|
||||
|
||||
// Get the CAPTCHA token and display the image.
|
||||
captchaToken = e.getCaptchaToken();
|
||||
try {
|
||||
captchaImage.setIcon(new ImageIcon(new URL(e.getCaptchaUrl())));
|
||||
captchaAnswerField.setText("(Please write the above letters here)");
|
||||
} catch (IOException ioe) {
|
||||
captchaImage.setText("(Error parsing captcha image URL)");
|
||||
}
|
||||
return false;
|
||||
} catch (AuthenticationException e) {
|
||||
SpreadsheetApiDemo.showErrorBox(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the submit button being pressed.
|
||||
*/
|
||||
private void handleSubmitButton() {
|
||||
String username = usernameField.getText();
|
||||
String password = new String(passwordField.getPassword());
|
||||
|
||||
if (authenticate(username, password)) {
|
||||
new ChooseSpreadsheetFrame(service);
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---- GUI code from here on down ----------------------------------------
|
||||
|
||||
/**
|
||||
* Handles all clicks.
|
||||
*/
|
||||
private class ActionHandler implements ActionListener {
|
||||
public void actionPerformed(ActionEvent ae) {
|
||||
if (ae.getSource() == submitButton) {
|
||||
handleSubmitButton();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes all the GUI widgets.
|
||||
*/
|
||||
private void initializeGui() {
|
||||
setTitle("Log in to Google Spreadsheets");
|
||||
|
||||
Container panel = getContentPane();
|
||||
|
||||
panel.setLayout(new BorderLayout());
|
||||
|
||||
JPanel topPanel = new JPanel();
|
||||
topPanel.setLayout(new GridLayout(4, 1));
|
||||
|
||||
topPanel.add(new JLabel("Log in to Google Spreadsheets!"));
|
||||
|
||||
usernameField = new JTextField();
|
||||
topPanel.add(usernameField);
|
||||
|
||||
passwordField = new JPasswordField();
|
||||
topPanel.add(passwordField);
|
||||
|
||||
submitButton = new JButton("Log in!");
|
||||
submitButton.addActionListener(new ActionHandler());
|
||||
topPanel.add(submitButton);
|
||||
|
||||
panel.add(topPanel, BorderLayout.NORTH);
|
||||
|
||||
captchaImage = new JLabel("(A CAPTCHA may appear here)",
|
||||
SwingConstants.CENTER);
|
||||
panel.add(captchaImage, BorderLayout.CENTER);
|
||||
|
||||
captchaAnswerField = new JTextField();
|
||||
captchaAnswerField.setText("(type captcha answer here)");
|
||||
panel.add(captchaAnswerField, BorderLayout.SOUTH);
|
||||
|
||||
setSize(300, 240);
|
||||
setVisible(true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
Google Spreadsheets data API Java Sample - README.txt
|
||||
-----------------------------------------------------
|
||||
|
||||
This is a fairly complete example that shows a possible application of the
|
||||
Google Spreadsheets Data API. This example shows how to handle the login
|
||||
process (including CAPTCHA), how to select a spreadsheet and/or worksheet,
|
||||
and a possible interface for manipulating the spreadsheet.
|
||||
|
||||
This example might be good for experimenting, but is harder to understand.
|
||||
For a more down-to-earth example, see the cell or list demo.
|
||||
|
||||
This can be built an run with Ant:
|
||||
|
||||
1. Edit gdata/java/build-samples/build.properties with your Google Account
|
||||
username, password, and a URL to your Google spreadsheet
|
||||
(in the format ....spreadsheets.google.com/ccc?id=...)
|
||||
|
||||
2. Run the Ant rule:
|
||||
|
||||
ant -f gdata/java/build-samples.xml sample.spreadsheet.guidemo.run
|
||||
|
||||
Alternately, you can compile and run it from the command line:
|
||||
|
||||
java sample.spreadsheet.gui.GuiDemo
|
||||
@@ -0,0 +1,74 @@
|
||||
/* Copyright (c) 2008 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package sample.spreadsheet.gui;
|
||||
|
||||
import com.google.gdata.client.spreadsheet.SpreadsheetService;
|
||||
import com.google.gdata.util.AuthenticationException;
|
||||
import com.google.gdata.util.ServiceException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
/**
|
||||
* Runs the spreadsheets GUI API demo.
|
||||
*/
|
||||
public final class SpreadsheetApiDemo {
|
||||
|
||||
/** Prevents instantiation. */
|
||||
private SpreadsheetApiDemo() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the demo.
|
||||
*
|
||||
* @param args IGNORED
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
new LoginFrame(new SpreadsheetService("SpreadsheetApiDemo-1"),
|
||||
"(username)", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a pop-up dialog box alerting the user of an error.
|
||||
*
|
||||
* @param e the exception
|
||||
*/
|
||||
public static void showErrorBox(Exception e) {
|
||||
if (e instanceof IOException) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"There was an error contacting Google: " + e.getMessage(),
|
||||
"Error contacting Google",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else if (e instanceof AuthenticationException) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"Your username and/or password were rejected: " + e.getMessage(),
|
||||
"Authentication Error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else if (e instanceof ServiceException) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"Google returned the error: " + e.getMessage(),
|
||||
"Google had an error processing the request",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
"There was an unexpected error: " + e.getMessage(),
|
||||
"Unexpected error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user