View Part 2 - Create Manufacturer WindowS2C Home « View Part 2 - Create Manufacturer Window
We finish the section and complete the coding for the Manufacturer application by coding the ManufacturerWindow
class and uncommenting the instantiations of the ManufacturerServerStartupWindow
and ManufacturerWindow
objects within the ManufacturerApplicationStartup
class.
Create Manufacturer WindowTop
In the final lesson of the section we complete the coding for the Manufacturer application by coding the ManufacturerWindow
class which allows users to view and interact with the
Manufacturer file in an application window. We also uncomment the instantiations of the ManufacturerServerStartupWindow
and ManufacturerWindow
objects within the
ManufacturerApplicationStartup
class.
Compiling The ManufacturerWindow
Class Top
The ManufacturerWindow
class allows users to view and interact with the Manufacturer file in an application window. This is the view element of the MVC paradigm.
Cut and paste the following code into your text editor and save it in the c:\_Case_Study\src\client directory.
package view;
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.util.Set;
import java.util.TreeSet;
import java.util.logging.*;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import model.StockingException;
import services.*;
/**
* This class allows users to view and interact with the Manufacturer file
* in an application window. This is the view element of the MVC paradigm.
*
* The class is invoked via the following run modes:
* "client" - non-networked client mode.
* "" - Networked client mode (no mode entered).
*
* @author Charlie
* @version 1.0
*
*/
public class ManufacturerWindow extends JFrame implements ListSelectionListener {
/**
* The Logger instance through which all log messages from this class are
* routed. Logger namespace is s2cCaseStudy
.
*/
private static Logger log = Logger.getLogger("s2cCaseStudy"); // Log output
/**
* A version number for the ManufacturerWindow class so that serialisation can
* occur without worrying about the underlying class changing between
* serialisation and deserialisation.
*/
private static final long serialVersionUID = 2498052502L;
/**
* The strings for the buttons in the Manufacturer window.
*/
private static final String SEARCH = "Search";
private static final String SEARCHALL = "Search All";
private static final String STOCK = "Stock";
private static final String UNSTOCK = "Unstock";
/**
* The internal reference to the Services controller.
*/
private Services services;
/**
* The JTable
that displays the Manufacturers stored on the
* Manufacturer file.
*/
private JTable manufacturerTable = new JTable();
/**
* Holds a copy of the combo boxes used so we can get selected items to use
* in our search criteria.
*/
private JComboBox<?> chooseName;
private JComboBox<?> chooseLocation;
/**
* Buttons for the Manufacturer window.
*/
private JButton searchButton = new JButton(SEARCH);
private JButton searchAllButton = new JButton(SEARCHALL);
private JButton stockButton = new JButton(STOCK);
private JButton unstockButton = new JButton(UNSTOCK);
/**
* The internal reference to the the currently displayed table of Manufacturer
* data.
*/
private ManufacturerTableModel tableData;
/**
* Builds and displays the Manufacturer application window. The constructor
* begins by building the connection selection dialog box. The user mode is
* selected and the Manufacturer file located. A reference is then
* acquired for the Services Singleton and the Manufacturer window is
* populated using an empty search (returns all). The constructed window is
* then centred in middle of screen and displayed.
*
* @param args specifying the following modes:
* "client" - Non-Network client.
* "" - Network client (no mode entered).
*/
public ManufacturerWindow(String[] args) {
super("Stocking Goods Limited: Manufacturer Stock System");
log.entering("ManufacturerWindow", "ManufacturerWindow");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/*
* Setup an Enum Constant for access mode entered for use throughout
* the application.
*/
RunMode runMode = (args.length == 0) ? RunMode.NETWORK_CLIENT
: RunMode.NON_NETWORK_CLIENT;
// Locate the Manufacturer file
RunModeDialog manufacturerFileLocation = new RunModeDialog(this, runMode);
// User terminated Manufacturer file location dialog box so exit application
if (manufacturerFileLocation.userCancelled()) {
System.exit(0);
}
// Get a reference to the Services singleton
try {
services = (Services) ServicesImpl.getServicesImplInstance(runMode,
manufacturerFileLocation.getLocation(),
manufacturerFileLocation.getPort());
} catch (ServicesException se) {
log.log(Level.SEVERE, "Connecting to the server caused a fatal error: "
+ "\n" + se);
ManufacturerApplicationStartup.handleException(
"Failed to connect to Manufacturer file");
System.exit(0);
}
// Handle the table listener
ListSelectionModel selectionModel = manufacturerTable.getSelectionModel();
selectionModel.addListSelectionListener( this );
// Use an empty search to initially populate Manufacturer table data
try {
tableData = services.searchManufacturers("", "");
setupManufacturerTable();
} catch (IOException se) {
ManufacturerApplicationStartup.handleException(
"Failed to acquire initial Manufacturer information."
+ "\nPlease check the Manufacturer Database connection.");
}
this.add(new ManufacturerScreen());
this.pack();
this.setSize(900, 400);
// Centre on screen
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((d.getWidth() - this.getWidth()) / 2);
int y = (int) ((d.getHeight() - this.getHeight()) / 2);
this.setLocation(x, y);
this.setVisible(true);
log.exiting("ManufacturerWindow", "ManufacturerWindow");
}
/**
* Try to store last selection. Refresh the manufacturerTable
* from the tableData
member. Reselect the previous item if it
* still exists.
*/
private void setupManufacturerTable() {
log.entering("ManufacturerWindow", "setupManufacturerTable");
// Store previous selection
int index = manufacturerTable.getSelectedRow();
String prevSelected = (index >= 0) ? (String) manufacturerTable.getValueAt(index, 0)
+ (String) manufacturerTable.getValueAt(index, 1)
: "";
// Reset the table data
this.manufacturerTable.setModel(this.tableData);
// Disable the stocking button
stockButton.setEnabled(false);
// Disable the unstocking button
unstockButton.setEnabled(false);
// Reselect the previous item if it still exists
for (int i = 0; i < this.manufacturerTable.getRowCount(); i++) {
String selectedManufacturer = (String) manufacturerTable.getValueAt(i, 0)
+ (String) manufacturerTable.getValueAt(i, 1);
if (selectedManufacturer.equals(prevSelected)) {
this.manufacturerTable.setRowSelectionInterval(i, i);
String stockOrdered = (String) manufacturerTable.getValueAt(i, 5);
// If there is stock ordered enable the unstock button and disable
// the stock button, otherwise enable the stock button
if (stockOrdered.equals("")) {
stockButton.setEnabled(true);
} else {
stockButton.setEnabled(false);
unstockButton.setEnabled(true);
}
break;
}
}
log.exiting("ManufacturerWindow", "setupManufacturerTable");
}
/**
* Setup the panels of the Manufacturer application. Having this here helps
*
* @author Charlie
* @version 1.0
*
*/
private class ManufacturerScreen extends JPanel {
/**
* A version number for the ManufacturerScreen class so that serialisation
* can occur without worrying about the underlying class changing
* between serialisation and deserialisation.
*/
private static final long serialVersionUID = 2498052502L;
// Set up border titles
private static final String SEARCHTITLE = "Search Manufacturer File";
private static final String TABLETITLE = "Manufacturer Information";
private static final String ACTIONTITLE = "Actions";
/**
* Constructs the main panel for the Manufacturer application.
*/
public ManufacturerScreen() {
this.setLayout(new BorderLayout());
/*
* Search Panel 1 components
*/
// Name Combo box
Set<String> manufacturerNames = new TreeSet<String>();
manufacturerNames.add("---ANY---");
// Populate search on Manufacturer names combo box
for (int i = 0; i < manufacturerTable.getRowCount(); i++) {
manufacturerNames.add((String) manufacturerTable.getValueAt(i, 0));
}
Object[] nameObj = manufacturerNames.toArray();
chooseName = JComboBoxFromObj(nameObj);
// Create Search panel 1
JPanel searchPanel1 = new JPanel(new FlowLayout(FlowLayout.LEFT));
JLabel manufacturerLabel = new JLabel("Manufacturer Name ");
searchPanel1.add(manufacturerLabel);
searchPanel1.add(chooseName);
/*
* Search panel 2 components
*/
// Location Combo box
Set<String> locations = new TreeSet<String>();
locations.add("---ANY---");
// Populate search on locations combo box
for (int i = 0; i < manufacturerTable.getRowCount(); i++) {
locations.add((String) manufacturerTable.getValueAt(i, 1));
}
Object[] locationObj = locations.toArray();
chooseLocation = JComboBoxFromObj(locationObj);
// Create Search panel 2
JPanel searchPanel2 = new JPanel(new FlowLayout(FlowLayout.LEFT));
JLabel locationLabel = new JLabel("Manufacturer Location");
searchPanel2.add(locationLabel);
searchPanel2.add(chooseLocation);
/*
* Search panel 3 components
*/
// Search and search all buttons
searchButton.addActionListener(new SearchManufacturers());
searchButton.setMnemonic(KeyEvent.VK_S);
searchAllButton.addActionListener(new SearchAll());
searchAllButton.setMnemonic(KeyEvent.VK_R);
// Create Search panel 3
JPanel searchPanel3 = new JPanel(new FlowLayout(FlowLayout.LEFT));
searchPanel3.add(searchButton);
searchPanel3.add(searchAllButton);
// combine the 3 search panes into 1
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.setBorder(BorderFactory.createTitledBorder(SEARCHTITLE));
topPanel.add(searchPanel1, BorderLayout.NORTH);
topPanel.add(searchPanel2, BorderLayout.CENTER);
topPanel.add(searchPanel3, BorderLayout.SOUTH);
// Add the top panel to the main window
this.add(topPanel, BorderLayout.NORTH);
// Add the manufacturer table to the main window
JScrollPane tableScroll = new JScrollPane(manufacturerTable);
tableScroll.setBorder(BorderFactory.createTitledBorder(TABLETITLE));
tableScroll.setSize(500, 250);
this.add(tableScroll, BorderLayout.CENTER);
// Setup stocking button
stockButton.addActionListener(new StockFromManufacturer());
stockButton.setMnemonic(KeyEvent.VK_B);
// Disable the stocking button
stockButton.setEnabled(false);
// Set the stocking button to refuse focus
stockButton.setRequestFocusEnabled(false);
// Setup unstocking button
unstockButton.addActionListener(new UnstockBackToManufacturer());
unstockButton.setMnemonic(KeyEvent.VK_U);
// Disable the unstocking button
unstockButton.setEnabled(false);
// Set the unstocking button to refuse focus
unstockButton.setRequestFocusEnabled(false);
// Create a panel for stocking and unstocking buttons
JPanel stockingPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
stockingPanel.setBorder(BorderFactory.createTitledBorder(ACTIONTITLE));
stockingPanel.add(stockButton);
stockingPanel.add(unstockButton);
// Add the stocking panel to the main window
this.add(stockingPanel, BorderLayout.SOUTH);
// Set table properties
manufacturerTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
manufacturerTable.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
// Add Tool Tips
chooseName.setToolTipText(
"Select a value from the combo box for the name of the manufacturer.");
chooseLocation.setToolTipText(
"Select a value from the combo box for the location of the manufacturer.");
searchButton.setToolTipText("Manufacturer search.");
searchAllButton.setToolTipText("Show all Manufacturers");
manufacturerTable.setToolTipText("Select a Manufacturer to stock/unstock from.");
stockButton.setToolTipText("Stock product from the selected Manufacturer");
unstockButton.setToolTipText("Unstock product back to the selected Manufacturer");
}
/**
* Private method that allows us to convert our object array into a
* comboBox.
*
* @see JComboBox
*/
private JComboBox<?> JComboBoxFromObj(Object[] obj) {
JComboBox<?> comboBox = new JComboBox<Object>(obj);
return comboBox;
}
}
/**
* Handles all Manufacturer search events.
*
* @author Charlie
* @version 1.0
*/
private class SearchManufacturers implements ActionListener {
/**
* Handles the actionPerformed event for the search button.
*
* @param ae The event initiated by the Search button.
*/
public void actionPerformed(ActionEvent ae) {
try {
String name = (String) chooseName.getSelectedItem();
if (name == "---ANY---") {
name = "";
}
String location = (String) chooseLocation.getSelectedItem();
if (location == "---ANY---") {
location = "";
}
tableData = services.searchManufacturers(name, location);
setupManufacturerTable();
} catch (IOException se) {
String msg = "Problem with search - operation failed.";
ManufacturerApplicationStartup.handleException(msg);
}
}
}
/**
* Resets Manufacturer search.
*
* @author Charlie
* @version 1.0
*/
private class SearchAll implements ActionListener {
/**
* Handles the actionPerformed event for the search all button.
*
* @param ae The event initiated by the SearchAll button.
*/
public void actionPerformed(ActionEvent ae) {
try {
chooseName.setSelectedIndex(0);
String name = "";
chooseLocation.setSelectedIndex(0);
repaint();
String location = "";
tableData = services.searchManufacturers(name, location);
setupManufacturerTable();
} catch (IOException se) {
String msg = "Problem with search - operation failed.";
ManufacturerApplicationStartup.handleException(msg);
}
}
}
/**
* Handles all Manufacturer stocking events.
*
* @author Charlie
* @version 1.0
*/
private class StockFromManufacturer implements ActionListener {
private String stockOrdered; // Used for validation
private int stockOrd; // Used for calculations
private int stockLvl; // Calculated stock level
/**
* Handles the actionPerformed event for the stock order button.
*
* @param ae The event initiated by the book button.
*/
public void actionPerformed(ActionEvent ae) {
int index = manufacturerTable.getSelectedRow();
if (index >= 0) {
/*
* Display a dialog box for stock entry that validates
* stock order entered or exits on user cancel
*/
boolean exitLoop = false;
while (!exitLoop) {
stockOrdered = (String) JOptionPane.showInputDialog(rootPane,
"Please enter stock amount (1-999) to order",
"Requesting stock order", JOptionPane.PLAIN_MESSAGE,
null, null, "");
// null indicates user pressed cancel or exited window
if (stockOrdered == null) {
break;
// validate user entry
} else if (validStockOrdered(stockOrdered)) {
exitLoop = true;
}
}
if (exitLoop) {
// Get record number using unique name/location fields
String name = (String) manufacturerTable.getValueAt(index, 0);
String location = (String) manufacturerTable.getValueAt(index, 1);
try {
//Call services
services.stockFromManufacturer(name, location, stockLvl, stockOrd);
// Update column and row with stoclLevel and stockOrdered
String stockLevelStr = "" + stockLvl;
manufacturerTable.setValueAt(stockLevelStr, index, 4);
String stockOrderedStr = "" + stockOrd;
manufacturerTable.setValueAt(stockOrderedStr, index, 5);
// Disable the stocking button
stockButton.setEnabled(false);
// Enable the unstocking button
unstockButton.setEnabled(true);
setupManufacturerTable();
manufacturerTable.repaint();
} catch (IOException se) {
String msg = "Problem with stocking - operation failed.";
ManufacturerApplicationStartup.handleException(msg);
} catch (StockingException e) {
String msg = "Stocking already set by another user - operation failed. "
+ " Press the 'Search' button to refresh table.";
ManufacturerApplicationStartup.handleException(msg);
}
}
}
}
/**
* Validate stock order entered in dialog box.
*
* @param stockOrdered The amount of stock ordered.
* @return A boolean
indicating whether stockOrdered is valid.
*/
private boolean validStockOrdered(String stockOrdered) {
int index = manufacturerTable.getSelectedRow();
try {
stockOrd = Integer.parseInt(stockOrdered);
} catch (NumberFormatException e) {
// Stock ordered must be numeric
JOptionPane.showMessageDialog(rootPane,
"Stock order must be numeric. Please try again. ");
return false;
}
if (stockOrd < 1 || stockOrdered.length() > 3) {
// Stock ordered must be in range (1-999)
JOptionPane.showMessageDialog(rootPane,
"Stock order valid range 1 - 999. Please try again. ");
return false;
} else {
// Stock ordered must not exceed stock amount
String stock = (String) manufacturerTable.getValueAt(index, 4);
int stockLevel = 0;
try {
stockLevel = Integer.parseInt(stock);
if (stockLevel < stockOrd) {
JOptionPane.showMessageDialog(rootPane,
"You cannot order more stock than is available. Please try again");
return false;
} else {
stockLvl = stockLevel - stockOrd;
return true;
}
} catch (NumberFormatException e) {
log.log(Level.INFO, "Stocking problem: " + stock +
", passed stock was not numeric. ");
JOptionPane.showMessageDialog(rootPane,
"Stock level must be numeric. Please try again");
return false;
}
}
}
}
/**
* Handles all Manufacturer unstocking events.
*
* @author Charlie
* @version 1.0
*/
private class UnstockBackToManufacturer implements ActionListener {
/**
* Handles the actionPerformed event for the unstock button.
*
* @param ae The event initiated by the unstock button.
*/
public void actionPerformed(ActionEvent ae) {
int index = manufacturerTable.getSelectedRow();
if (index >= 0) {
String name = (String) manufacturerTable.getValueAt(index, 0);
String location = (String) manufacturerTable.getValueAt(index, 1);
String stockLevel = (String) manufacturerTable.getValueAt(index, 4);
String stockOrdered = (String) manufacturerTable.getValueAt(index, 5);
int manStockLevel = 0;
int stockOrd = 0;
try {
manStockLevel = Integer.parseInt(stockLevel);
try {
stockOrd = Integer.parseInt(stockOrdered);
} catch (NumberFormatException e) {
log.log(Level.INFO, "Manufacturer: " + name + ", " + location +
" stock ordered wasn't numeric.");
}
} catch (NumberFormatException e) {
log.log(Level.INFO, "Manufacturer: " + name + ", " + location +
" stock level wasn't numeric.");
} finally {
try {
//We can restock manufacturer
services.unstockBackToManufacturer(name, location, stockOrd);
// Disable the unstocking button
unstockButton.setEnabled(false);
// Enable the stocking button
stockButton.setEnabled(true);
// Update Stock level and stock ordered
manStockLevel = manStockLevel + stockOrd;
String strStock = "" + manStockLevel;
manufacturerTable.setValueAt(strStock, index, 4);
manufacturerTable.setValueAt("", index, 5);
setupManufacturerTable();
manufacturerTable.repaint();
} catch (IOException se) {
String msg = "Problem with unstocking - operation failed.";
ManufacturerApplicationStartup.handleException(msg);
}
}
}
}
}
public void valueChanged(ListSelectionEvent e) {
// See if this is a valid table selection
if( e.getSource() == manufacturerTable.getSelectionModel()
&& e.getFirstIndex() >= 0 ) {
// Enable the Stocking button);
int index = manufacturerTable.getSelectedRow();
if (index >= 0) {
String stockOrdered = (String) manufacturerTable.getValueAt(index, 5);
if (stockOrdered.equals("")) {
stockButton.setEnabled(true);
unstockButton.setEnabled(false);
} else {
stockButton.setEnabled(false);
unstockButton.setEnabled(true);
}
}
}
}
}
Compiling Our Source File With the -cp
and -d
Options
Open your command line editor:
Change to directory cd c:\_Case_Study\src\client
Compile ManufacturerWindow.java
using the java compiler with the -cp
and -d
options
javac -cp ..\..\classes -d ..\..\classes ManufacturerWindow.java
Updating The ManufacturerApplicationStartup
ClassTop
The last thing we need to do is uncomment the instantiations of the ManufacturerServerStartupWindow
and ManufacturerWindow
objects within the ManufacturerApplicationStartup
class.
Open the ManufacturerApplicationStartup
class in your text editor.
Uncomment the instantiations and remove the System.out.println
lines, near the end of the the ManufacturerApplicationStartup
constructor, to look like the following
snippet and save it in the c:\_Case_Study\src\client directory.
if (args.length == 0 || "client".equalsIgnoreCase(args[0])) {
// Create an instance of the Manufacturer application window
new ManufacturerWindow(args);
} else if ("server".equalsIgnoreCase(args[0])) {
// Create an instance of the Manufacturer server startup application window
new ManufacturerServerStartupWindow();
} else {
Compiling Our Source File With the -cp
and -d
Options
Open your command line editor:
Change to directory cd c:\_Case_Study\src\client
Compile ManufacturerApplicationStartup.java
using the java compiler with the -cp
and -d
options
javac -cp ..\..\classes -d ..\..\classes ManufacturerApplicationStartup.java
The following screenshot shows that we get a clean compile on the above class and also that the ManufacturerWindow
and ManufacturerApplicationStartup
classes are now compiled into the classes\client
directory.
This completes the coding for the Manufacturer application.
Lesson 17 Complete
In this lesson we coded the View elements of the MVC pattern that relate to the manufacturer window.
Related Java Tutorials
Beginning Java - Primitive Variables
Beginning Java - Conditional Statements
Beginning Java - Loop Statements
Objects & Classes - Arrays
Objects & Classes - Class Structure and Syntax
Objects & Classes - Reference Variables
Objects & Classes - Methods
Objects & Classes - Instance Variables & Scope
Objects & Classes - Constructors
Objects & Classes - Static Members
Objects & Classes - Enumerations
OO Concepts - Encapsulation
OO Concepts - Inheritance Concepts - Using the super
keyword
Exceptions - Handling Exceptions
API Contents - Inheritance - Using the package
keyword
API Contents - Inheritance - Using the import
keyword
API Contents - Java I/O Overview - The java.io.File
Class
Concurrency - Synchronization - Synchronized Blocks
Swing - RMI - Serialization
Swing - Components
What's Next?
In the next section we commence testing of the model aspects of the MVC paradigm.