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