/*
* Book Catalog - Catalog your book collection.
*
* Copyright (C) 2009 Joshua Walters
* URL: http://joshwalters.com
*
* This file is part of Book Catalog.
*
* Book Catalog is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Book Catalog 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 for more details.
*
* You should have received a copy of the GNU General Public License
* along with Book Catalog. If not, see .
*/
package com.joshwalters.bookcatalog;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.sql.SQLException;
import java.util.Comparator;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import com.joshwalters.bookcatalog.bookdatabase.BookDatabase;
import com.joshwalters.bookcatalog.isbnlookup.GDataISBNLookup;
import com.joshwalters.bookcatalog.isbnlookup.ISBNLookup;
import com.joshwalters.bookcatalog.table.BookCatalogTableModel;
/**
* Catalogs and organizes your book collection.
*
* @author Josh Walters
*/
public class BookCatalog {
/**
* Performs book lookups using ISBN numbers.
*/
private ISBNLookup bookLookup = null;
/**
* Stores the users book catalog.
*/
private BookDatabase bookDatabase = null;
/**
* Allows user to search book catalog.
*/
private JTextField searchField;
/**
* Allows user to add book to catalog.
*/
private JTextField addBookField;
/**
* Displays the book catalog.
*/
// private JTable bookCatalogTable;
private JTable bookCatalogTable;
/**
* Used for managing the book catalog table.
*/
private BookCatalogTableModel bookCatalogTableModel;
/**
* Displays the title of a book.
*/
private JTextField titleField;
/**
* Displays the author of a book.
*/
private JTextField authorField;
/**
* Displays the publish date of a book.
*/
private JTextField dateField;
/**
* Displays the description of a book.
*/
private JTextArea descriptionArea;
/**
* Displays the ISBN number of a book.
*/
private JTextField ISBNField;
/**
* Displays the price of a book.
*/
private JTextField priceField;
/**
* Displays the publisher of a book.
*/
private JTextField publisherField;
/**
* Displays the subject of a book.
*/
private JTextField subjectField;
/**
* Displays the notes on a book.
*/
private JTextArea notesArea;
/**
* Stores the width of the different text fields/areas.
*/
private static final int FIELD_WIDTH = 20;
/**
* Stores the height of the text areas.
*/
private static final int FIELD_HEIGHT = 5;
/**
* Sets up all the GUI components of the program.
*/
BookCatalog() {
// Setup the book lookup.
bookLookup = new GDataISBNLookup();
// Setup the book database.
bookDatabase = new BookDatabase();
try {
// Connect to the book database.
bookDatabase.connectToDatabase();
} catch (SQLException e) {
// There was an SQL error of some sort.
System.err.println(e.getLocalizedMessage());
} catch (ClassNotFoundException e) {
System.err.println(e.getLocalizedMessage());
}
// Create the window and its label.
JFrame frame = new JFrame("Book Catalog");
// Exit the window on close.
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Set the L&F to Nimbus if possible.
SetLookAndFeel();
// Set the layout.
frame.setLayout(new GridBagLayout());
// The constraints.
GridBagConstraints gridConstraints = new GridBagConstraints();
// The search label.
JLabel searchLabel = new JLabel("Search");
gridConstraints.gridx = 0;
gridConstraints.gridy = 0;
gridConstraints.insets.top = 10;
gridConstraints.insets.left = 20;
frame.add(searchLabel, gridConstraints);
// The search text field
searchField = new JTextField(FIELD_WIDTH);
gridConstraints.gridx = 1;
gridConstraints.gridy = 0;
gridConstraints.insets.top = 10;
gridConstraints.insets.left = 10;
frame.add(searchField, gridConstraints);
// The add book label
JLabel addBookLabel = new JLabel("Add Book");
gridConstraints.gridx = 2;
gridConstraints.gridy = 0;
gridConstraints.insets.top = 10;
gridConstraints.insets.left = 60;
frame.add(addBookLabel, gridConstraints);
// The add book field
addBookField = new JTextField(FIELD_WIDTH);
gridConstraints.gridx = 3;
gridConstraints.gridy = 0;
gridConstraints.insets.top = 10;
gridConstraints.insets.left = 10;
gridConstraints.fill = GridBagConstraints.REMAINDER;
gridConstraints.anchor = GridBagConstraints.WEST;
frame.add(addBookField, gridConstraints);
// Change the grid constraints back to their the normal state.
gridConstraints.fill = GridBagConstraints.NONE;
gridConstraints.anchor = GridBagConstraints.CENTER;
gridConstraints.insets = new Insets(10, 10, 10, 10);
// The book catalog table.
bookCatalogTableModel = new BookCatalogTableModel(bookDatabase);
bookCatalogTable = new JTable(bookCatalogTableModel);
setupTable();
gridConstraints.gridx = 0;
gridConstraints.gridy = 1;
gridConstraints.gridwidth = 4;
gridConstraints.gridheight = 10;
gridConstraints.weightx = 1;
gridConstraints.weighty = 1;
gridConstraints.fill = GridBagConstraints.BOTH;
// The scroll panel will store the book catalog table.
JScrollPane scrollPaneForCatalog = new JScrollPane(bookCatalogTable);
// Add the scroll panel with the table to the frame.
frame.add(scrollPaneForCatalog, gridConstraints);
// Change the grid constraints back to their the normal state.
gridConstraints.gridwidth = 1;
gridConstraints.gridheight = 1;
gridConstraints.weightx = 0;
gridConstraints.weighty = 0;
gridConstraints.fill = GridBagConstraints.NONE;
// The title label
JLabel titleLabel = new JLabel("Title");
gridConstraints.gridx = 5;
gridConstraints.gridy = 1;
frame.add(titleLabel, gridConstraints);
// The title field
titleField = new JTextField(FIELD_WIDTH);
gridConstraints.gridx = 6;
gridConstraints.gridy = 1;
frame.add(titleField, gridConstraints);
// The author label
JLabel authorLabel = new JLabel("Author");
gridConstraints.gridx = 5;
gridConstraints.gridy = 2;
frame.add(authorLabel, gridConstraints);
// The author field
authorField = new JTextField(FIELD_WIDTH);
gridConstraints.gridx = 6;
gridConstraints.gridy = 2;
frame.add(authorField, gridConstraints);
// The date label
JLabel dateLabel = new JLabel("Date");
gridConstraints.gridx = 5;
gridConstraints.gridy = 3;
frame.add(dateLabel, gridConstraints);
// The date field
dateField = new JTextField(FIELD_WIDTH);
gridConstraints.gridx = 6;
gridConstraints.gridy = 3;
frame.add(dateField, gridConstraints);
// The description label
JLabel descriptionLabel = new JLabel("Description");
gridConstraints.gridx = 5;
gridConstraints.gridy = 4;
frame.add(descriptionLabel, gridConstraints);
// The date field
descriptionArea = new JTextArea(FIELD_HEIGHT, FIELD_WIDTH);
descriptionArea.setLineWrap(true);
descriptionArea.setWrapStyleWord(true);
gridConstraints.gridx = 6;
gridConstraints.gridy = 4;
JScrollPane scrollPaneForDescriptionArea = new JScrollPane(
descriptionArea);
frame.add(scrollPaneForDescriptionArea, gridConstraints);
// The ISBN label
JLabel ISBNLabel = new JLabel("ISBN");
gridConstraints.gridx = 5;
gridConstraints.gridy = 5;
frame.add(ISBNLabel, gridConstraints);
// The ISBN field
ISBNField = new JTextField(FIELD_WIDTH);
ISBNField.setEnabled(false);
gridConstraints.gridx = 6;
gridConstraints.gridy = 5;
frame.add(ISBNField, gridConstraints);
// The price label
JLabel priceLabel = new JLabel("Price");
gridConstraints.gridx = 5;
gridConstraints.gridy = 6;
frame.add(priceLabel, gridConstraints);
// The price field
priceField = new JTextField(FIELD_WIDTH);
gridConstraints.gridx = 6;
gridConstraints.gridy = 6;
frame.add(priceField, gridConstraints);
// The publisher label
JLabel publisherLabel = new JLabel("Publisher");
gridConstraints.gridx = 5;
gridConstraints.gridy = 7;
frame.add(publisherLabel, gridConstraints);
// The publisher field
publisherField = new JTextField(FIELD_WIDTH);
gridConstraints.gridx = 6;
gridConstraints.gridy = 7;
frame.add(publisherField, gridConstraints);
// The subject label
JLabel subjectLabel = new JLabel("Subject");
gridConstraints.gridx = 5;
gridConstraints.gridy = 8;
frame.add(subjectLabel, gridConstraints);
// The subject field
subjectField = new JTextField(FIELD_WIDTH);
gridConstraints.gridx = 6;
gridConstraints.gridy = 8;
frame.add(subjectField, gridConstraints);
// The notes label
JLabel ratingLabel = new JLabel("Notes");
gridConstraints.gridx = 5;
gridConstraints.gridy = 9;
frame.add(ratingLabel, gridConstraints);
// The notes field
notesArea = new JTextArea(FIELD_HEIGHT, FIELD_WIDTH);
gridConstraints.gridx = 6;
gridConstraints.gridy = 9;
JScrollPane scrollPaneForNotesArea = new JScrollPane(notesArea);
frame.add(scrollPaneForNotesArea, gridConstraints);
// Listens for search database input.
SearchDatabase searchDatabase = new SearchDatabase(bookCatalogTable,
bookDatabase, searchField);
searchField.getDocument().addDocumentListener(searchDatabase);
// The apply changes button
JButton applyChangesButton = new JButton("Apply Changes");
gridConstraints.gridx = 5;
gridConstraints.gridy = 10;
gridConstraints.anchor = GridBagConstraints.NORTH;
frame.add(applyChangesButton, gridConstraints);
// The delete book button
JButton deleteBookButton = new JButton("Delete Book");
gridConstraints.gridx = 6;
gridConstraints.gridy = 10;
gridConstraints.anchor = GridBagConstraints.NORTH;
frame.add(deleteBookButton, gridConstraints);
// Listens for add book input.
addBookField.addActionListener(new AddBook(bookDatabase, bookLookup,
bookCatalogTable));
// Listens for delete book button press.
deleteBookButton.addActionListener(new DeleteBook(bookDatabase,
titleField, authorField, dateField, descriptionArea, ISBNField,
priceField, publisherField, subjectField, notesArea,
searchDatabase));
// Listens for apply changes button press.
applyChangesButton.addActionListener(new ApplyChanges(bookCatalogTable,
bookDatabase, titleField, authorField, dateField,
descriptionArea, ISBNField, priceField, publisherField,
subjectField, notesArea));
// Set the frame size.
frame.pack();
// Set minimum size for the frame.
Rectangle rect = frame.getBounds();
frame.setMinimumSize(new Dimension(rect.width, rect.height));
// Center the frame.
frame.setLocationRelativeTo(null);
// Show the frame.
frame.setVisible(true);
}
/**
* Sets up the table.
*/
private void setupTable() {
// Make the table fill the scroll pane.
bookCatalogTable.setFillsViewportHeight(true);
// Don't show the grid.
bookCatalogTable.setShowGrid(false);
// Disable focus so that there wont be cell selection box highlights.
bookCatalogTable.setFocusable(false);
// Only allow one row at a time to be selected.
bookCatalogTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// Prevent reordering of the table headers.
bookCatalogTable.getTableHeader().setReorderingAllowed(false);
// Auto sort the rows if the user clicks on the headers.
bookCatalogTable.setAutoCreateRowSorter(true);
// Create a new table sorter object.
TableRowSorter sorter = new TableRowSorter(
bookCatalogTable.getModel());
// Set the table to use this new sorter object.
bookCatalogTable.setRowSorter(sorter);
/*
* Set the comparator for the 5th column (the price column) to handle
* money correctly.
*/
sorter.setComparator(5, new Comparator() {
public int compare(String s1, String s2) {
// Strip the '$' from both of the strings.
s1 = s1.replaceFirst("\\$", "");
s2 = s2.replaceFirst("\\$", "");
Double one = new Double(s1);
Double two = new Double(s2);
return one.compareTo(two);
}
});
// Listens for table row selections.
ListSelectionModel listSelection = bookCatalogTable.getSelectionModel();
// Add the new listener.
listSelection.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent arg0) {
int selectedRow = bookCatalogTable.getSelectedRow();
if (selectedRow != -1) {
/*
* Place the data in the selected row to the corresponding
* text area/field. Also move the caret to the front of the
* text element.
*/
titleField.setText((String) bookCatalogTable.getValueAt(
selectedRow, 0));
titleField.setCaretPosition(0);
;
authorField.setText((String) bookCatalogTable.getValueAt(
selectedRow, 1));
authorField.setCaretPosition(0);
dateField.setText((String) bookCatalogTable.getValueAt(
selectedRow, 2));
dateField.setCaretPosition(0);
descriptionArea.setText((String) bookCatalogTable
.getValueAt(selectedRow, 3));
descriptionArea.setCaretPosition(0);
ISBNField.setText((String) bookCatalogTable.getValueAt(
selectedRow, 4));
ISBNField.setCaretPosition(0);
priceField.setText((String) bookCatalogTable.getValueAt(
selectedRow, 5));
priceField.setCaretPosition(0);
publisherField.setText((String) bookCatalogTable
.getValueAt(selectedRow, 6));
publisherField.setCaretPosition(0);
subjectField.setText((String) bookCatalogTable.getValueAt(
selectedRow, 7));
subjectField.setCaretPosition(0);
notesArea.setText((String) bookCatalogTable.getValueAt(
selectedRow, 8));
notesArea.setCaretPosition(0);
}
}
});
}
/**
* Disconnect from the database upon GC.
*/
protected void finalize() {
bookDatabase.disconnectFromDatabase();
}
/**
* Set the look and feel of the Swing GUI to Nimbus if possible.
*/
private void SetLookAndFeel() {
try {
// UIManager.getSystemLookAndFeelClassName()
UIManager
.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception e) {
// Do nothing. Just use the standard L&F.
}
}
/**
* Run the program.
*
* @param args
*/
public static void main(String args[]) {
new BookCatalog();
}
}