1119 lines
53 KiB
Java
1119 lines
53 KiB
Java
package pickMaint;
|
|
|
|
import static pickMaint.ExcelExporter.exportJTableToFile;
|
|
import static pickMaint.ExcelExporter.openInExcel;
|
|
|
|
import java.awt.BorderLayout;
|
|
import java.awt.Color;
|
|
import java.awt.Component;
|
|
import java.awt.event.ActionEvent;
|
|
import java.awt.event.ActionListener;
|
|
import java.awt.event.MouseAdapter;
|
|
import java.awt.event.MouseEvent;
|
|
import java.awt.event.WindowAdapter;
|
|
import java.awt.event.WindowEvent;
|
|
import java.io.IOException;
|
|
import java.math.BigDecimal;
|
|
import java.math.RoundingMode;
|
|
import java.sql.SQLException;
|
|
import java.text.DateFormat;
|
|
import java.text.NumberFormat;
|
|
import java.text.ParseException;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Calendar;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
|
|
import javax.swing.JCheckBox;
|
|
import javax.swing.JComboBox;
|
|
import javax.swing.JFrame;
|
|
import javax.swing.JLabel;
|
|
import javax.swing.JMenu;
|
|
import javax.swing.JMenuBar;
|
|
import javax.swing.JMenuItem;
|
|
import javax.swing.JOptionPane;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JPasswordField;
|
|
import javax.swing.JPopupMenu;
|
|
import javax.swing.JScrollPane;
|
|
import javax.swing.JTabbedPane;
|
|
import javax.swing.JTable;
|
|
import javax.swing.JTextField;
|
|
import javax.swing.KeyStroke;
|
|
import javax.swing.event.DocumentEvent;
|
|
import javax.swing.event.DocumentListener;
|
|
import javax.swing.table.TableCellRenderer;
|
|
|
|
import com.toedter.calendar.JDateChooser;
|
|
|
|
import net.miginfocom.swing.MigLayout;
|
|
|
|
public class Editor extends JFrame {
|
|
|
|
private static final long serialVersionUID = 1L;
|
|
|
|
private final AS400Interface as400;
|
|
private HashMap<String, LoomDSRecord[]> loadedShifts = new HashMap<String, LoomDSRecord[]>(); //Holds data for all loaded tabs. Key format: MM/dd/yyy-shift ex: 02/03/14-2
|
|
private HashMap<String, JTable> loadedTables = new HashMap<String, JTable>();
|
|
private HashMap<String, LoomDSTableModel> loadedTableModels = new HashMap<String, LoomDSTableModel>();
|
|
private HashMap<String, JScrollPane> loadedScrollPanes = new HashMap<String, JScrollPane>();
|
|
|
|
private final JTabbedPane tabbedPane;
|
|
private final Editor self;
|
|
|
|
private JMenuBar topMenu = new JMenuBar();
|
|
private JMenu fileMenu = new JMenu("File");
|
|
private JMenuItem newTab = new JMenuItem("New Tab");
|
|
private JMenu toolsMenu = new JMenu("Tools");
|
|
private JMenuItem newRecord = new JMenuItem("Add New Record");
|
|
private JMenuItem openInExcel = new JMenuItem("Export Current Tab to Excel");
|
|
private JMenuItem shiftSummary = new JMenuItem("Shift Summary");
|
|
|
|
/**
|
|
* Dispatches a Runnable to the EDT that builds/displays a login prompt.
|
|
* The credentials entered in this prompt are used to create an AS400Interface object.
|
|
* This AS400Interface object is used to create/display a new Editor.
|
|
*
|
|
* @param args - Not used.
|
|
* @throws SQLException - Shouldn't happen :)
|
|
*/
|
|
public static void main(String[] args) {
|
|
java.awt.EventQueue.invokeLater(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
JPanel loginPrompt = new JPanel(new MigLayout("fill"));
|
|
|
|
final JComboBox<String> users = new JComboBox<String>(new String[]{ "WRAY", "AARON", "CALEB"});
|
|
JLabel userLabel = new JLabel("User:");
|
|
loginPrompt.add(userLabel, "grow");
|
|
loginPrompt.add(users, "grow, wrap");
|
|
|
|
final JPasswordField passwordField = new JPasswordField(10);
|
|
passwordField.addAncestorListener(new RequestFocusListener());
|
|
JLabel passLabel = new JLabel("Password:");
|
|
loginPrompt.add(passLabel, "grow");
|
|
loginPrompt.add(passwordField, "grow, wrap");
|
|
|
|
final JComboBox<String> dataSet = new JComboBox<String>(new String[]{"PRODUCTION", "TEST"});
|
|
loginPrompt.add(dataSet, "grow, span 2 1, wrap");
|
|
|
|
int option = JOptionPane.showOptionDialog(null, loginPrompt, "Pick Maintenance Login - " + (new SimpleDateFormat("MM/dd/yyyy - HH:mm").format(Calendar.getInstance().getTime())),
|
|
JOptionPane.NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{ "Login!", "Quit" }, "Login!");
|
|
if(option == 0)
|
|
java.awt.EventQueue.invokeLater(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
AS400Interface connection = null;
|
|
boolean productionData = dataSet.getSelectedIndex() == 0;
|
|
try {
|
|
connection = new AS400Interface((String)users.getSelectedItem(), new String(passwordField.getPassword()), productionData);
|
|
new Editor(connection);
|
|
} catch (SQLException e) {
|
|
e.printStackTrace();
|
|
System.exit(ERROR); //Not much else we can do here. Are you connected to the network?
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
public Editor(AS400Interface as400) throws SQLException {
|
|
super("Pick Maintenance"); //Call super constructor, set title
|
|
this.as400 = as400; //Save a reference to the AS400Interface
|
|
self = this; //Store reference to this Editor object for accessing within anonymous inner classes
|
|
|
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Exit program gracefully when user closes JFrame
|
|
setSize(1440, 810); //Set size of the JFrame
|
|
|
|
this.addWindowListener(new WindowAdapter(){
|
|
public void windowClosing(WindowEvent e) {
|
|
self.as400.close();
|
|
super.windowClosing(e);
|
|
}
|
|
});
|
|
|
|
//Create action for "New Tab" menu option
|
|
newTab.addActionListener(new ActionListener(){
|
|
private final Logger LOGGER = Logger.getLogger(LoomDSRecord.class.getName());
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
try {
|
|
//Create prompt to get date and shift from user
|
|
JPanel newTabPrompt = new JPanel();
|
|
JDateChooser dateChooser = new JDateChooser(new Date(), "MM/dd/yy");
|
|
JTextField shiftInput = new JTextField(3);
|
|
shiftInput.addAncestorListener(new RequestFocusListener());
|
|
shiftInput.addFocusListener(new SelectAllOnFocusListener());
|
|
newTabPrompt.add(dateChooser);
|
|
newTabPrompt.add(new JLabel("Shift"));
|
|
newTabPrompt.add(shiftInput);
|
|
|
|
//Display prompt
|
|
int option = JOptionPane.showOptionDialog(self, newTabPrompt, "New Tab", JOptionPane.NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{ "Add", "Cancel" }, "Add");
|
|
if(option == 0){
|
|
//If user clicked "Add" add a tab for the date and shift selected
|
|
addTab(dateChooser.getDate(), Integer.parseInt(shiftInput.getText()));
|
|
}
|
|
} catch (SQLException e1) {
|
|
JOptionPane.showMessageDialog(rootPane, e1.getMessage(), "Error Getting Data From AS400", JOptionPane.ERROR_MESSAGE);
|
|
} catch(NumberFormatException e2){
|
|
LOGGER.log(Level.SEVERE, "Error parsing user input. Nothing loaded. See exception message for details.", e2);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rError parsing user input. Nothing loaded. See exception message for details.", "Whoops!", JOptionPane.ERROR_MESSAGE);
|
|
}
|
|
}
|
|
});
|
|
|
|
newRecord.addActionListener(new ActionListener() {
|
|
private final Logger LOGGER = Logger.getLogger(LoomDSRecord.class.getName());
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
String[] parse = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex()).split(" ");
|
|
int shift = 0;
|
|
try { shift = Integer.parseInt(parse[2].substring(0, 1)); } catch(Exception e1) { LOGGER.log(Level.SEVERE, "Failed to build key for date/shift. Better luck next time.", e1); return; }
|
|
DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
|
|
Date date = null;
|
|
try { date = formatter.parse(parse[0]); } catch (ParseException e1) { LOGGER.log(Level.SEVERE, "Failed to build key for date/shift. Better luck next time.", e1); return; }
|
|
|
|
JPanel prompt = new JPanel(new MigLayout("fill"));
|
|
|
|
JDateChooser dateDisp = new JDateChooser(date, "MM/dd/yy"); //Date chooser just for displaying date, not editable
|
|
dateDisp.setEnabled(false);
|
|
JTextField shiftDisp = new JTextField("" + shift); //Text field for displaying shift, not editable
|
|
shiftDisp.setEnabled(false);
|
|
final JTextField loomInp = new JTextField(4);
|
|
loomInp.addAncestorListener(new RequestFocusListener()); //Yield focus to the loom input field when dialog displayed
|
|
loomInp.addFocusListener(new SelectAllOnFocusListener()); //Select any text currently in the field on focus
|
|
JTextField weaverInp = new JTextField(4);
|
|
weaverInp.addFocusListener(new SelectAllOnFocusListener()); //Select any text currently in the field on focus
|
|
JComboBox<String> styleInp = new JComboBox<String>(new String[]{" ", " BLN", " TRL", " SAM"});
|
|
final JTextField hoursInp = new JTextField(4);
|
|
hoursInp.addFocusListener(new SelectAllOnFocusListener()); //Select any text currently in the field on focus
|
|
final JTextField picksInp = new JTextField(4);
|
|
picksInp.addFocusListener(new SelectAllOnFocusListener()); //Select any text currently in the field on focus
|
|
JComboBox<String> dtInp = new JComboBox<String>(AS400Interface.getDtCodeChoices());
|
|
JTextField cutInp = new JTextField(4);
|
|
cutInp.addFocusListener(new SelectAllOnFocusListener()); //Select any text currently in the field on focus
|
|
JTextField cutSuffixInp = new JTextField(4);
|
|
cutSuffixInp.addFocusListener(new SelectAllOnFocusListener()); //Select any text currently in the field on focus
|
|
JComboBox<String> typeInp = new JComboBox<String>(new String[]{"B", "T"});
|
|
JCheckBox bonusInp = new JCheckBox();
|
|
|
|
hoursInp.getDocument().addDocumentListener(new DocumentListener() {
|
|
@Override
|
|
public void removeUpdate(DocumentEvent e) {
|
|
update();
|
|
}
|
|
@Override
|
|
public void insertUpdate(DocumentEvent e) {
|
|
update();
|
|
}
|
|
@Override
|
|
public void changedUpdate(DocumentEvent e) {
|
|
update();
|
|
}
|
|
private void update(){
|
|
try {
|
|
float pph = AS400Interface.loomSpeedLookup(Integer.parseInt(loomInp.getText())); //Get max picks per hour for user entered loom
|
|
double hours = Double.parseDouble(hoursInp.getText()); //get user entered hours
|
|
picksInp.setText("" + (int) (pph * hours)); //Multiply, set pick input to product
|
|
} catch(Exception e){ } //If we don't have all the required information: do nothing.
|
|
}
|
|
});
|
|
|
|
loomInp.getDocument().addDocumentListener(new DocumentListener() {
|
|
@Override
|
|
public void removeUpdate(DocumentEvent e) {
|
|
update();
|
|
}
|
|
@Override
|
|
public void insertUpdate(DocumentEvent e) {
|
|
update();
|
|
}
|
|
@Override
|
|
public void changedUpdate(DocumentEvent e) {
|
|
update();
|
|
}
|
|
private void update(){
|
|
try {
|
|
float pph = AS400Interface.loomSpeedLookup(Integer.parseInt(loomInp.getText())); //Get max picks per hour for user entered loom
|
|
double hours = Double.parseDouble(hoursInp.getText()); //get user entered hours
|
|
picksInp.setText("" + (int) (pph * hours)); //Multiply, set pick input to product
|
|
} catch(Exception e){ } //If we don't have all the required information: do nothing.
|
|
}
|
|
});
|
|
|
|
prompt.add(new JLabel("Date"), "align right, grow");
|
|
prompt.add(dateDisp, "align left, grow, wrap");
|
|
prompt.add(new JLabel("Shift"), "align right, grow");
|
|
prompt.add(shiftDisp, "align left, grow, wrap");
|
|
prompt.add(new JLabel("Loom"), "align right, grow");
|
|
prompt.add(loomInp, "align left, grow, wrap");
|
|
prompt.add(new JLabel("Weaver"), "align right, grow");
|
|
prompt.add(weaverInp, "align left, grow, wrap");
|
|
prompt.add(new JLabel("Style"), "align right, grow");
|
|
prompt.add(styleInp, "align left, grow, wrap");
|
|
prompt.add(new JLabel("Hours"), "align right, grow");
|
|
prompt.add(hoursInp, "align left, grow, wrap");
|
|
prompt.add(new JLabel("Picks"), "align right, grow");
|
|
prompt.add(picksInp, "align left, grow, wrap");
|
|
prompt.add(new JLabel("Down Time Code"), "align right, grow");
|
|
prompt.add(dtInp, "align left, grow, wrap");
|
|
prompt.add(new JLabel("Cut Number"), "align right, grow");
|
|
prompt.add(cutInp, "align left, grow, wrap");
|
|
prompt.add(new JLabel("Cut Suffix"), "align right, grow");
|
|
prompt.add(cutSuffixInp, "align left, grow, wrap");
|
|
prompt.add(new JLabel("Type Code"), "align right, grow");
|
|
prompt.add(typeInp, "align left, grow, wrap");
|
|
prompt.add(new JLabel("No Bonus"), "align right, grow");
|
|
prompt.add(bonusInp, "align left, grow, wrap");
|
|
|
|
int option = JOptionPane.showOptionDialog(self, prompt, "New Record", JOptionPane.NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{ "Add", "Cancel" }, "Add");
|
|
if(option == 0){
|
|
int loom = 0;
|
|
int weaver = 0;
|
|
String style1 = "";
|
|
int picks = 0;
|
|
double hours = 0;
|
|
String dtCode = "";
|
|
int cut1 = 0;
|
|
String cut2 = "";
|
|
String typeCode = "";
|
|
boolean noBonus = false;
|
|
try {
|
|
loom = Integer.parseInt(loomInp.getText());
|
|
if(loom < 201 || loom > 317)
|
|
throw new NumberFormatException("Loom number out of range: " + loom);
|
|
weaver = Integer.parseInt(weaverInp.getText());
|
|
if(AS400Interface.weaverLookup(weaver) == null)
|
|
throw new NumberFormatException("Weaver doesn't exist: " + weaver);
|
|
style1 = (String) styleInp.getSelectedItem();
|
|
picks = Integer.parseInt(picksInp.getText());
|
|
if(picks < 0 || picks > 250)
|
|
throw new NumberFormatException("Picks value not sane: " + picks);
|
|
hours = Double.parseDouble(hoursInp.getText());
|
|
if(hours < 0 || hours > 12)
|
|
throw new NumberFormatException("Hours Value not sane: " + hours);
|
|
dtCode = ((String) dtInp.getSelectedItem()).split(" ")[0];
|
|
if(dtCode.equalsIgnoreCase("NONE"))
|
|
dtCode = " ";
|
|
cut1 = Integer.parseInt(cutInp.getText());
|
|
if(cut1 < 0 || cut1 > 999)
|
|
throw new NumberFormatException("Cut number is out of range: " + cut1);
|
|
if(cutSuffixInp.getText().length() > 2)
|
|
cut2 = cutSuffixInp.getText().substring(0, 2);
|
|
else
|
|
cut2 = cutSuffixInp.getText();
|
|
typeCode = ((String) typeInp.getSelectedItem());
|
|
noBonus = bonusInp.isSelected();
|
|
} catch(NumberFormatException e2){
|
|
LOGGER.log(Level.SEVERE, "Error parsing user input. Nothing added. See exception message for details.", e2);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rError parsing user input. Nothing added. See exception message for details.", "Whoops!", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
try {
|
|
self.as400.addRecord(date, loom, shift, weaver, style1, hours, picks, dtCode, cut1, cut2, typeCode, noBonus);
|
|
reloadTab(makeKey(date, shift));
|
|
} catch(SQLException e2) {
|
|
LOGGER.log(Level.SEVERE, "Error writing record to database. Better luck next time", e2);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rA databse transaction error occured. Nothing added. See exception message for details.", "Whoops!", JOptionPane.ERROR_MESSAGE);
|
|
} catch (ParseException e2) {
|
|
LOGGER.log(Level.SEVERE, "Error reloading tab. Add it manually. See exception message for details.", e2);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rError reloading tab. Add it manually. See exception message for details.", "Whoops!", JOptionPane.ERROR_MESSAGE);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
openInExcel.addActionListener(new ActionListener() {
|
|
private final Logger LOGGER = Logger.getLogger(LoomDSRecord.class.getName());
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
String[] parse = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex()).split(" ");
|
|
int shift = 0;
|
|
try { shift = Integer.parseInt(parse[2].substring(0, 1)); } catch(Exception e1) { LOGGER.log(Level.SEVERE, "Failed to build key for date/shift. Better luck next time.", e1); return; }
|
|
DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
|
|
Date date = null;
|
|
try { date = formatter.parse(parse[0]); } catch (ParseException e1) { LOGGER.log(Level.SEVERE, "Failed to build key for date/shift. Better luck next time.", e1); return; }
|
|
try {
|
|
exportJTableToFile(loadedTables.get(makeKey(date, shift)), "out.xls");
|
|
openInExcel("out.xls");
|
|
} catch (IOException e1) {
|
|
LOGGER.log(Level.SEVERE, "Some kind of file I/O took a dump while exporting table. Sorry.", e1);
|
|
return;
|
|
}
|
|
}
|
|
});
|
|
|
|
shiftSummary.addActionListener(new ActionListener(){
|
|
private final Logger LOGGER = Logger.getLogger(LoomDSRecord.class.getName());
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
NumberFormat percentFormat = NumberFormat.getPercentInstance();
|
|
percentFormat.setMaximumFractionDigits(3);
|
|
|
|
String[] parse = tabbedPane.getTitleAt(tabbedPane.getSelectedIndex()).split(" ");
|
|
int shift = 0;
|
|
try { shift = Integer.parseInt(parse[2].substring(0, 1)); } catch(Exception e1) { LOGGER.log(Level.SEVERE, "Failed to build key for date/shift. Better luck next time.", e1); return; }
|
|
DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
|
|
Date date = null;
|
|
try { date = formatter.parse(parse[0]); } catch (ParseException e1) { LOGGER.log(Level.SEVERE, "Failed to build key for date/shift. Better luck next time.", e1); return; }
|
|
|
|
float shiftLength = -1;
|
|
float prodLoomHrs = 0;
|
|
int prodLoomPicks = 0;
|
|
float noBonHours = 0;
|
|
int noBonPicks = 0;
|
|
float sampHours = 0;
|
|
int sampPicks = 0;
|
|
float shiftEff = 0;
|
|
try {
|
|
prodLoomHrs = self.as400.getProductionLoomHours(date, shift);
|
|
prodLoomPicks = self.as400.getProductionPicks(date, shift);
|
|
noBonHours = self.as400.getNoBonusLoomHours(date, shift);
|
|
noBonPicks = self.as400.getNoBonusPicks(date, shift);
|
|
sampHours = self.as400.getSampleLoomHours(date, shift);
|
|
sampPicks = self.as400.getSamplePicks(date, shift);
|
|
shiftLength = self.as400.getShiftLength(date, shift);
|
|
shiftEff = self.as400.getShiftEfficiency(date, shift);
|
|
} catch (SQLException e1) {
|
|
LOGGER.log(Level.SEVERE, "Something broke.", e1);
|
|
}
|
|
float prodLooms = prodLoomHrs / shiftLength;
|
|
float sampPicksPct = (float) sampPicks / prodLoomPicks;
|
|
float sampHrsPct = sampHours / prodLoomHrs;
|
|
|
|
JPanel dialog = new JPanel(new MigLayout("fill"));
|
|
|
|
dialog.add(new JLabel("Shift Efficiency:"), "grow, align right");
|
|
dialog.add(new JLabel(percentFormat.format(shiftEff)), "grow, wrap");
|
|
dialog.add(new JLabel("Shift Length:"), "grow, align right");
|
|
dialog.add(new JLabel(shiftLength + " hours"), "grow, wrap");
|
|
dialog.add(new JLabel("Production Loom Hours:"), "grow, align right");
|
|
dialog.add(new JLabel(prodLoomHrs + " hours"), "grow, wrap");
|
|
dialog.add(new JLabel("Number of Looms:"), "grow, align right");
|
|
dialog.add(new JLabel("" + prodLooms), "grow, wrap");
|
|
dialog.add(new JLabel("Production Picks:"), "grow, align right");
|
|
dialog.add(new JLabel("" + prodLoomPicks), "grow, wrap");
|
|
dialog.add(new JLabel("Sample Hours:"), "grow, align right");
|
|
dialog.add(new JLabel(sampHours + " hours (" + percentFormat.format(sampHrsPct) + ")"), "grow, wrap");
|
|
dialog.add(new JLabel("Sample Picks:"), "grow, align right");
|
|
dialog.add(new JLabel(sampPicks + " (" + percentFormat.format(sampPicksPct) + ")"), "grow, wrap");
|
|
dialog.add(new JLabel("No Bonus Looms:"), "grow, align right");
|
|
dialog.add(new JLabel((noBonHours / 8.0) + ""), "grow, wrap");
|
|
dialog.add(new JLabel("No Bonus Picks:"), "grow, align right");
|
|
dialog.add(new JLabel(noBonPicks + ""), "grow, wrap");
|
|
|
|
JOptionPane.showOptionDialog(self, dialog, "Shift Summary", JOptionPane.NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{ "Ok" }, "Ok");
|
|
}
|
|
});
|
|
|
|
JPanel contentPane = new JPanel(new BorderLayout()); //Main Panel - Everything gets added to this
|
|
|
|
newTab.setAccelerator(KeyStroke.getKeyStroke('t'));
|
|
newRecord.setAccelerator(KeyStroke.getKeyStroke('n'));
|
|
shiftSummary.setAccelerator(KeyStroke.getKeyStroke('s'));
|
|
|
|
//Set up menu bar
|
|
fileMenu.add(newTab);
|
|
toolsMenu.add(newRecord);
|
|
toolsMenu.add(openInExcel);
|
|
toolsMenu.addSeparator();
|
|
toolsMenu.add(shiftSummary);
|
|
topMenu.add(fileMenu);
|
|
topMenu.add(toolsMenu);
|
|
contentPane.add(topMenu, BorderLayout.NORTH); //Add menu bar to the top of the UI
|
|
|
|
//Set up tabbed pane
|
|
tabbedPane = new JTabbedPane();
|
|
|
|
//Add tabs for last three shifts that ran
|
|
loadMostRecentDataByShift(1);
|
|
loadMostRecentDataByShift(2);
|
|
loadMostRecentDataByShift(3);
|
|
|
|
contentPane.add(tabbedPane, BorderLayout.CENTER); //Add tabbed pane to the center of the UI
|
|
|
|
setContentPane(contentPane); //Set the content pane of the JFrame to our JPanel we've created
|
|
setLocationRelativeTo(null);
|
|
setVisible(true); //Display the UI
|
|
}
|
|
|
|
private void loadMostRecentDataByShift(int shift) {
|
|
Calendar cal = Calendar.getInstance();
|
|
boolean done = false;
|
|
int dayOfWeek = -1;
|
|
while (!done) {
|
|
try {
|
|
addTab(cal.getTime(), shift); //an SQL exception is thrown for an empty result set dropping us into the catch block below
|
|
done = true; //No exception thrown, tab must've loaded okay set done = true; to exit loop
|
|
} catch (SQLException e) {
|
|
/*
|
|
* In here we basically want to set the calendar to the previous day so we can try to load that. There some extra logic to
|
|
* avoid Saturday and Sunday dates to help minimize pointless database transactions.
|
|
*/
|
|
do {
|
|
cal.add(Calendar.DAY_OF_MONTH, -1); //Subtract a day from the current date
|
|
dayOfWeek = cal.get(Calendar.DAY_OF_WEEK); //Store day of the week
|
|
} while (dayOfWeek == Calendar.SATURDAY //if Saturday or Sunday: repeat.
|
|
|| dayOfWeek == Calendar.SUNDAY);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create new tab for the specified date and shift
|
|
* @param date - integer date in yyMMdd format. Ex: 140203 = Feb. 3, 2014
|
|
* @param shift - integer shift should be in the set [1, 2, 3]
|
|
* @throws SQLException
|
|
*/
|
|
@SuppressWarnings("unused")
|
|
private void addTab(int date, int shift) throws SQLException{
|
|
loadShiftDetail(date, shift); //Query server for data
|
|
String key = makeKey(date, shift); //Form key to retrieve objects from HashMaps
|
|
JScrollPane c = loadedScrollPanes.get(key); //Grab the ScrollPane from HashMap
|
|
tabbedPane.add(formatKeyForDisplay(key), c); //Add ScrollPane to TabbedPane
|
|
tabbedPane.setSelectedComponent(c); //Set focus to newly added ScrollPane
|
|
tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(c), new ButtonTabComponent(tabbedPane, this)); //Add close button to tab
|
|
}
|
|
|
|
/**
|
|
* Overloaded version to take a Java.util.Date for first arg instead of an integer.
|
|
* @param date - Java.util.Date object representing the desired date
|
|
* @param shift - integer shift should be in the set [1, 2, 3]
|
|
* @throws SQLException
|
|
*/
|
|
private void addTab(Date date, int shift) throws SQLException{
|
|
loadShiftDetail(date, shift); //Query server for data
|
|
String key = makeKey(date, shift); //Form key to retrieve objects from HashMaps
|
|
JScrollPane c = loadedScrollPanes.get(key); //Grab the ScrollPane from HashMap
|
|
tabbedPane.add(formatKeyForDisplay(key), c); //Add ScrollPane to TabbedPane
|
|
tabbedPane.setSelectedComponent(c); //Set focus to newly added ScrollPane
|
|
tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(c), new ButtonTabComponent(tabbedPane, this)); //Add close button to tab
|
|
}
|
|
|
|
/**
|
|
* Overloaded to accept a single integer date. Creates a Java.util.Date object via
|
|
* a static utility method and calls loadShiftDetail(Date, intDate, shift)
|
|
* @param date - integer date in yyMMdd format. Ex: 140203 = Feb. 3, 2014
|
|
* @param shift - integer shift should be in the set [1, 2, 3]
|
|
* @throws SQLException
|
|
*/
|
|
private void loadShiftDetail(int date, int shift) throws SQLException{
|
|
loadShiftDetail(AS400Interface.intToDate(date), date, shift);
|
|
}
|
|
|
|
/**
|
|
* Overloaded to accept a single java.util.Date. Creates an integer representation of the
|
|
* date in yyMMdd format and calls loadShiftDetail(Date, intDate, shift)
|
|
* @param date - Java.util.Date object representing the desired date
|
|
* @param shift - integer shift should be in the set [1, 2, 3]
|
|
* @throws SQLException
|
|
*/
|
|
private void loadShiftDetail(Date date, int shift) throws SQLException{
|
|
loadShiftDetail(date, AS400Interface.dateToInt(date), shift);
|
|
}
|
|
|
|
/**
|
|
* Never called directly; use one of the overloaded helper methods instead.
|
|
* This method first creates the String key used by all hashmaps for this date/shift combo.
|
|
* The shift detail is then fetched from the server in the form of a LoomDSRecord[].
|
|
* A reference to this array is stored in the loadedShifts HashMap
|
|
* A LoomDSTableModel is created and loaded with the LoomDSRecord[]
|
|
* A JTable is created using this TableModel
|
|
* A Mouse listener is added to the JTable to facilitate right clicking of table rows
|
|
* A ScrollPane is created using this JTable. This gets added to the new tab
|
|
* A reference to the TableModel, JTable, and ScrollPane is stored in the respective HashMaps.
|
|
*
|
|
* Key format for the hash maps is "MM/dd/yyyy-SHIFT" so 3rd shift on Feb. 3, 2014 would be "02/03/2014-3"
|
|
* @param date - A java.util.Date object for the desired date
|
|
* @param intDate - an integer representation of date in yyMMdd format
|
|
* @param shift - integer shift should be in the set [1, 2, 3]
|
|
* @throws SQLException
|
|
*/
|
|
private void loadShiftDetail(Date date, int intDate, int shift) throws SQLException{
|
|
//Create Key
|
|
final String key = new SimpleDateFormat("MM/dd/yyyy-").format(date) + shift;
|
|
|
|
//Check if tab is already loaded
|
|
if(loadedShifts.get(key) != null){
|
|
JOptionPane.showMessageDialog(self, "Tab already loaded!", "Whoops!", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
|
|
//Get data from server, store in HashMap
|
|
loadedShifts.put(key, as400.getShiftDetail(intDate, shift));
|
|
|
|
LoomDSTableModel tableModel = new LoomDSTableModel(); //Create new TableModel
|
|
tableModel.loadTable(loadedShifts.get(key)); //Load with data from server
|
|
|
|
final JTable table = new JTable(tableModel){
|
|
private static final long serialVersionUID = 7479372430475297633L;
|
|
private final Color HILIGHTED_ROW = new Color(184,207,229); //Got this with a color picker, hopefully it doesn't change on me
|
|
private int lastRowDrawn = 0;
|
|
|
|
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
|
|
Component c = super.prepareRenderer(renderer, row, column);
|
|
|
|
if(c.getBackground().equals(HILIGHTED_ROW)) //Check if current bg color is the blue for a highlighted row
|
|
return c; //Do nothing if it is
|
|
|
|
LoomDSTableModel model = (LoomDSTableModel) getModel();
|
|
if(model.highlightSample(row)){
|
|
lastRowDrawn = row;
|
|
c.setBackground(new Color(255,248,220));
|
|
} else if(model.highlightZero(row)) {
|
|
lastRowDrawn = row;
|
|
c.setBackground(new Color(255,202,202));
|
|
} else if(!model.bonus(row) && row != lastRowDrawn){
|
|
lastRowDrawn = row;
|
|
if(row % 2 == 0){
|
|
c.setBackground(Color.LIGHT_GRAY);
|
|
} else {
|
|
c.setBackground(new Color(205,201,201));
|
|
}
|
|
}
|
|
else if(row != lastRowDrawn){
|
|
lastRowDrawn = row;
|
|
c.setBackground(new Color(255,255,255));
|
|
}
|
|
|
|
return c;
|
|
}
|
|
};
|
|
table.addMouseListener(new MouseAdapter() {
|
|
/*
|
|
* This class enables row selection with the right mouse button. It also displays our
|
|
* JPopupMenu on right click.
|
|
*/
|
|
private String hashKey = key;
|
|
|
|
@Override
|
|
public void mouseReleased(MouseEvent e) {
|
|
int r = table.rowAtPoint(e.getPoint());
|
|
if (r >= 0 && r < table.getRowCount()) {
|
|
table.setRowSelectionInterval(r, r);
|
|
} else {
|
|
table.clearSelection();
|
|
}
|
|
|
|
int rowindex = table.getSelectedRow();
|
|
if (rowindex < 0)
|
|
return;
|
|
if (e.isPopupTrigger() && e.getComponent() instanceof JTable ) {
|
|
JPopupMenu popup = createRightClickMenu(table, r, hashKey);
|
|
popup.show(e.getComponent(), e.getX(), e.getY());
|
|
}
|
|
}
|
|
});
|
|
|
|
JScrollPane scrollPane = new JScrollPane(table); //Create ScrollPane for JTable
|
|
|
|
loadedTables.put(key, table); //Store JTable in HashMap
|
|
loadedTableModels.put(key, tableModel); //Store TableModel in HashMap
|
|
loadedScrollPanes.put(key, scrollPane); //Store ScrollPane in HashMap
|
|
}
|
|
|
|
/**
|
|
* Overloaded to accept a single integer date.
|
|
*
|
|
* First removes the tab associated with the key formed by the date and shift provided.
|
|
* Then, Removes all objects from all HashMaps associated with the key formed by the date and shift provided.
|
|
*
|
|
* @param date - integer date in yyMMdd format. Ex: 140203 = Feb. 3, 2014
|
|
* @param shift - integer shift should be in the set [1, 2, 3]
|
|
* @throws SQLException
|
|
*/
|
|
public void unloadShiftDetail(int date, int shift){
|
|
unloadShiftDetail(makeKey(date, shift));
|
|
}
|
|
|
|
/**
|
|
* Overloaded version to take a java.util.Date and an integer shift
|
|
*
|
|
* @param date - A java.util.Date object for the desired date
|
|
* @param shift - integer shift should be in the set [1, 2, 3]
|
|
*/
|
|
public void unloadShiftDetail(Date date, int shift){
|
|
unloadShiftDetail(makeKey(date, shift));
|
|
}
|
|
|
|
/**
|
|
* First removes the tab associated with the key formed by the date and shift provided.
|
|
* Then, Removes all objects from all HashMaps associated with the key formed by the date and shift provided.
|
|
*
|
|
* @param key - The HashMap key for the objects to unload
|
|
*/
|
|
public void unloadShiftDetail(String key){
|
|
tabbedPane.remove(loadedScrollPanes.get(key)); //Destroy Tab, if it exists
|
|
loadedShifts.remove(key); //Remove LoomDSRecord[] from HashMap
|
|
loadedTables.remove(key); //Remove JTable from HashMap
|
|
loadedTableModels.remove(key); //Remove TableModel from HashMap
|
|
loadedScrollPanes.remove(key); //Remove ScrollPane from HashMap
|
|
}
|
|
|
|
/**
|
|
* Overloaded to take an integer date in yyMMdd format. Returns the array of LoomDSRecord objects
|
|
* associated with the provided date/shift combination.
|
|
* @param date - integer date in yyMMdd format. Ex: 140203 = Feb. 3, 2014
|
|
* @param shift - integer shift should be in the set [1, 2, 3]
|
|
* @return An array of LoomDSRecord objects
|
|
*/
|
|
@SuppressWarnings("unused")
|
|
private LoomDSRecord[] getLoadedDetail(int date, int shift){
|
|
return loadedShifts.get(makeKey(date, shift));
|
|
}
|
|
|
|
/**
|
|
* Returns the array of LoomDSRecord objects associated with the provided date/shift combination.
|
|
* @param date - A java.util.Date object for the desired date
|
|
* @param shift - integer shift should be in the set [1, 2, 3]
|
|
* @return An array of LoomDSRecord objects
|
|
*/
|
|
@SuppressWarnings("unused")
|
|
private LoomDSRecord[] getLoadedDetail(Date date, int shift){
|
|
return loadedShifts.get(makeKey(date, shift));
|
|
}
|
|
|
|
/**
|
|
* Overloaded to take an integer date in yyMMdd format.
|
|
* Creates the string key needed to retrieve an objects from the hash maps out of the supplied
|
|
* date and shift.
|
|
* @param date - integer date in yyMMdd format. Ex: 140203 = Feb. 3, 2014
|
|
* @param shift - integer shift should be in the set [1, 2, 3]
|
|
* @return String HashMap key
|
|
*/
|
|
private String makeKey(int date, int shift){
|
|
return makeKey(AS400Interface.intToDate(date), shift);
|
|
}
|
|
|
|
/**
|
|
* Creates the string key needed to retrieve an objects from the hash maps out of the supplied
|
|
* date and shift.
|
|
* @param date - A java.util.Date object for the desired date
|
|
* @param shift - integer shift should be in the set [1, 2, 3]
|
|
* @return String HashMap key
|
|
*/
|
|
private String makeKey(Date date, int shift){
|
|
return new SimpleDateFormat("MM/dd/yyyy-").format(date) + shift;
|
|
}
|
|
|
|
/**
|
|
* Totally destroys tab associated with the supplied key and then reloads it.
|
|
*
|
|
* @param key - The HashMap key for the tab to be destroyed/loaded
|
|
* @throws ParseException
|
|
* @throws SQLException
|
|
*/
|
|
private void reloadTab(String key) throws ParseException, SQLException{
|
|
String[] parse = key.split("-");
|
|
int shift = Integer.parseInt(parse[1]);
|
|
DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
|
|
Date date = formatter.parse(parse[0]);
|
|
unloadShiftDetail(key);
|
|
addTab(date, shift);
|
|
}
|
|
|
|
/**
|
|
* Reloads the data into the table model for the given key.
|
|
* This is used to refresh the data in the table model to reflect changes made to any
|
|
* LoomDSRecord objects associated with it.
|
|
* @param key
|
|
*/
|
|
private void refreshTable(String key){
|
|
loadedTableModels.get(key).loadTable(loadedShifts.get(key));
|
|
}
|
|
|
|
/**
|
|
* Takes the supplied HashMap key and formats it to be used as the title for a tab.
|
|
* @param key - String HashMap key
|
|
* @return Formatted key string
|
|
*/
|
|
private String formatKeyForDisplay(String key){
|
|
String[] derp = key.split("-");
|
|
int shift = Integer.parseInt(derp[1]);
|
|
return derp[0] + " - " + ((shift == 1) ? "1st" : (shift == 2) ? "2nd" : (shift == 3) ? "3rd" : "" + shift) + " Shift";
|
|
}
|
|
|
|
private static double round(double value, int places) {
|
|
if (places < 0) throw new IllegalArgumentException();
|
|
|
|
BigDecimal bd = new BigDecimal(value);
|
|
bd = bd.setScale(places, RoundingMode.HALF_UP);
|
|
return bd.doubleValue();
|
|
}
|
|
|
|
/**
|
|
* This method creates a JPopupMenu to display when a row of a table is right clicked.
|
|
*
|
|
* This is a long one... 6 anonymous inner classes for each of the menu options.
|
|
*
|
|
* @param table - The table object that was right-clicked
|
|
* @param row - the row of the table that was right clicked
|
|
* @param key - the key needed for getting objects from the HashMaps for this table.
|
|
* @return the JPopupMenu
|
|
*/
|
|
private JPopupMenu createRightClickMenu(JTable table, int row, final String key){
|
|
final LoomDSRecord record = loadedShifts.get(key)[row];
|
|
|
|
JPopupMenu ret = new JPopupMenu("Loom " + table.getValueAt(row, 0));
|
|
|
|
JMenuItem adjPicks = new JMenuItem("Adjust Picks (Loom " + table.getValueAt(row, 0) + ")");
|
|
JMenuItem adjHours = new JMenuItem("Adjust Hours (Loom " + table.getValueAt(row, 0) + ")");
|
|
JMenuItem addSamp = new JMenuItem("Add Sample Cut (Loom " + table.getValueAt(row, 0) + ")");
|
|
JMenuItem chgWeav = new JMenuItem("Change Weaver (Loom " + table.getValueAt(row, 0) + ")");
|
|
JMenuItem setDT = new JMenuItem("Set Down Time Code (Loom " + table.getValueAt(row, 0) + ")");
|
|
JMenuItem delete = new JMenuItem("Delete Record (Loom " + table.getValueAt(row, 0) + ")");
|
|
|
|
adjPicks.addActionListener(new ActionListener(){
|
|
private final Logger LOGGER = Logger.getLogger(LoomDSRecord.class.getName());
|
|
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
int max = record.getMaxPicks();
|
|
double hours = record.getHours();
|
|
JLabel msg = new JLabel("The maximum picks for " + hours + " hours is " + max);
|
|
JLabel label = new JLabel("Picks:");
|
|
JTextField input = new JTextField("" + record.getPicks(), 4);
|
|
input.addAncestorListener(new RequestFocusListener());
|
|
input.addFocusListener(new SelectAllOnFocusListener());
|
|
JPanel pane = new JPanel(new MigLayout("fill"));
|
|
pane.add(msg, "span 2, align center, wrap");
|
|
pane.add(label, "align right");
|
|
pane.add(input, "align left, wrap");
|
|
int option = JOptionPane.showOptionDialog(self, pane, "Adjust Picks - Loom " + record.getLoomNumber(),
|
|
JOptionPane.NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{ "Change", "Cancel" }, "Change");
|
|
if(option == 0){
|
|
int backup = record.getPicks();
|
|
try {
|
|
int picks = Integer.parseInt(input.getText());
|
|
|
|
if(picks < 0 || picks > 250)
|
|
throw new NumberFormatException("Pick value is not sane."); //Insane amount of picks, exit
|
|
if(backup == picks)
|
|
return; //Might as well not hit the server with a transaction if we're not actually changing anything
|
|
|
|
record.setPicks(picks); //Change the picks in the LoomDSRecord object
|
|
|
|
} catch(NumberFormatException e2){
|
|
JOptionPane.showMessageDialog(self, "Non-negative integer values <= 250 please!\n\rNo changes made.", "Bogus Input", JOptionPane.ERROR_MESSAGE);
|
|
LOGGER.log(Level.SEVERE, "User passed us bogus input. Ignoring..", e2);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
as400.adjustPicks(record); //This actually commits the changes to the server
|
|
refreshTable(key); //If the changes were committed successfully, reload the table
|
|
} catch (SQLException e1) {
|
|
LOGGER.log(Level.SEVERE, "Database transaction failed when attempting to update picks. Reverting Changes.", e1);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rSomething went wrong when applying this change to the AS400", "Update Failed", JOptionPane.ERROR_MESSAGE);
|
|
record.setPicks(backup); //Revert picks in LoomDSRecord object to previous value since DB transaction failed
|
|
}
|
|
}
|
|
}
|
|
});
|
|
chgWeav.addActionListener(new ActionListener(){
|
|
private final Logger LOGGER = Logger.getLogger(LoomDSRecord.class.getName());
|
|
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
int backup = record.getWeaverNumber();
|
|
JLabel msg = new JLabel("Current Weaver is: " + record.getWeaverNameDisplay());
|
|
JLabel label = new JLabel("New Weaver #");
|
|
JTextField input = new JTextField("" + record.getWeaverNumber(), 4);
|
|
input.addAncestorListener(new RequestFocusListener());
|
|
input.addFocusListener(new SelectAllOnFocusListener());
|
|
JPanel prompt = new JPanel(new MigLayout("fill"));
|
|
prompt.add(msg, "span 2, wrap");
|
|
prompt.add(label, "align right");
|
|
prompt.add(input, "align left, wrap");
|
|
int option = JOptionPane.showOptionDialog(self, prompt, "Change Weaver - Loom " + record.getLoomNumber(),
|
|
JOptionPane.NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{ "Change", "Cancel" }, "Change");
|
|
if(option == 0){
|
|
try {
|
|
int newWeav = Integer.parseInt(input.getText());
|
|
if(AS400Interface.weaverLookup(newWeav) == null)
|
|
throw new NumberFormatException("Weaver number doesn't exist. Did you add it after you launched this application?");
|
|
record.setWeaverNumber(newWeav);
|
|
} catch(NumberFormatException e2){
|
|
LOGGER.log(Level.WARNING, "User passed us bogus input. Ignoring.", e2);
|
|
JOptionPane.showMessageDialog(self, "Weaver Number Doesn't Exist!\n\rDid you add it after you launched this application?", "Bogus Input", JOptionPane.ERROR_MESSAGE);
|
|
return;
|
|
}
|
|
try {
|
|
as400.changeWeaver(record, backup); //This actually commits the changes to the server
|
|
refreshTable(key); //If the changes were committed successfully, reload the table
|
|
} catch (SQLException e1) {
|
|
LOGGER.log(Level.SEVERE, "Database transaction failed when attempting to update weaver. Reverting Changes.", e1);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rSomething went wrong when applying this change to the AS400", "Update Failed", JOptionPane.ERROR_MESSAGE);
|
|
record.setWeaverNumber(backup); //Revert weaver in LoomDSRecord object to previous value since DB transaction failed
|
|
}
|
|
}
|
|
}
|
|
});
|
|
setDT.addActionListener(new ActionListener(){
|
|
private final Logger LOGGER = Logger.getLogger(LoomDSRecord.class.getName());
|
|
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
boolean updateHours = false;
|
|
String backup = record.getDownTimeCode();
|
|
double hrsBackup = record.getHours();
|
|
final int pksBackup = record.getPicks();
|
|
JComboBox<String> choice = new JComboBox<String>(AS400Interface.getDtCodeChoices());
|
|
JLabel msg = new JLabel();
|
|
final JTextField hrsAdjustment = new JTextField(4);
|
|
String dialogTitle = "";
|
|
String[] dialogOptions = new String[2];
|
|
|
|
dialogOptions[1] = "Cancel";
|
|
if(backup.length() == 0) {
|
|
msg.setText("Add a down time reason code to loom " + record.getLoomNumber());
|
|
dialogTitle = "Set Down Time Reason Code - Loom ";
|
|
dialogOptions[0] = "Set";
|
|
} else {
|
|
msg.setText("Down time reason code is currently: " + record.getformattedDowntimeReason());
|
|
dialogTitle = "Change Down Time Reason Code - Loom ";
|
|
dialogOptions[0] = "Change";
|
|
}
|
|
JPanel prompt = new JPanel(new MigLayout("fill"));
|
|
prompt.add(msg, "span 2, align center, wrap");
|
|
prompt.add(choice, "span 2, align center, wrap");
|
|
prompt.add(new JLabel("Hours"), "align right, grow");
|
|
prompt.add(hrsAdjustment, "align left");
|
|
|
|
int option = JOptionPane.showOptionDialog(self, prompt, dialogTitle + record.getLoomNumber(),
|
|
JOptionPane.NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, dialogOptions, dialogOptions[0]);
|
|
if(option == 0){
|
|
if(((String) choice.getSelectedItem()).equalsIgnoreCase("NONE") && backup.length() == 0)
|
|
return;
|
|
String newDtCode = ((String) choice.getSelectedItem()).split(" ")[0];
|
|
if(backup.equalsIgnoreCase(newDtCode))
|
|
return;
|
|
if(newDtCode.equalsIgnoreCase("NONE"))
|
|
newDtCode = "";
|
|
|
|
record.setDownTimeCode(newDtCode);
|
|
|
|
try {
|
|
double adj = Double.parseDouble(hrsAdjustment.getText()); // Attempt to parse duration of downtime from input box
|
|
record.setHours(hrsBackup - adj); // Subtract length of downtime from loom's total hours
|
|
record.setPicks(Math.min(pksBackup, record.getMaxPicks())); // Adjust total picks to the lesser of: new maximum for the new amount of looms hours - or - what was already entered
|
|
updateHours = true;
|
|
} catch (NumberFormatException e3) {
|
|
updateHours = false;
|
|
}
|
|
try {
|
|
as400.changeDtCode(record); //This actually commits the changes to the server
|
|
if(updateHours) {
|
|
as400.adjustHours(record);
|
|
as400.adjustPicks(record);
|
|
}
|
|
refreshTable(key); //If the changes were committed successfully, reload the table
|
|
} catch (SQLException e1) {
|
|
LOGGER.log(Level.SEVERE, "Database transaction failed when attempting to update DT code. Reverting Changes.", e1);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rSomething went wrong when applying this change to the AS400", "Update Failed", JOptionPane.ERROR_MESSAGE);
|
|
record.setDownTimeCode(backup); //Revert dt code in LoomDSRecord object to previous value since DB transaction failed
|
|
record.setHours(hrsBackup);
|
|
record.setPicks(pksBackup);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
adjHours.addActionListener(new ActionListener() {
|
|
private final Logger LOGGER = Logger.getLogger(LoomDSRecord.class.getName());
|
|
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
double backup = record.getHours();
|
|
JLabel label = new JLabel("Hours");
|
|
JTextField input = new JTextField("" + record.getHours(), 5);
|
|
input.addAncestorListener(new RequestFocusListener());
|
|
input.addFocusListener(new SelectAllOnFocusListener());
|
|
JPanel prompt = new JPanel(new MigLayout("fill"));
|
|
prompt.add(label, "align right, grow");
|
|
prompt.add(input, "align left, grow, wrap");
|
|
int option = JOptionPane.showOptionDialog(self, prompt, "Adjust Hours - Loom " + record.getLoomNumber(),
|
|
JOptionPane.NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{ "Change", "Cancel" }, "Change");
|
|
if(option == 0){
|
|
try{
|
|
double hours = Double.parseDouble(input.getText());
|
|
if(hours < 0 || hours > 12.0)
|
|
throw new NumberFormatException("Hours value not sane.");
|
|
if(hours == backup)
|
|
return;
|
|
record.setHours(hours);
|
|
record.setPicks(Math.min(record.getPicks(), record.getMaxPicks()));
|
|
} catch(NumberFormatException e2){
|
|
JOptionPane.showMessageDialog(self, "Non-negative decimal values <= 12.0 please!\n\rNo changes made.", "Bogus Input", JOptionPane.ERROR_MESSAGE);
|
|
LOGGER.log(Level.SEVERE, "User passed us bogus input. Ignoring..", e2);
|
|
return;
|
|
}
|
|
try {
|
|
as400.adjustHours(record); //This actually commits the changes to the server
|
|
as400.adjustPicks(record);
|
|
refreshTable(key); //If the changes were committed successfully, reload the table
|
|
} catch (SQLException e1) {
|
|
LOGGER.log(Level.SEVERE, "Database transaction failed when attempting to update hours. Reverting Changes.", e1);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rSomething went wrong when applying this change to the AS400", "Update Failed", JOptionPane.ERROR_MESSAGE);
|
|
record.setHours(backup); //Revert hours in LoomDSRecord object to previous value since DB transaction failed
|
|
}
|
|
}
|
|
}
|
|
});
|
|
addSamp.addActionListener(new ActionListener() {
|
|
private final Logger LOGGER = Logger.getLogger(LoomDSRecord.class.getName());
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
final double hrsBackup = record.getHours();
|
|
final int pksBackup = record.getPicks();
|
|
final int distanceFromMax = record.getMaxPicks() - record.getPicks();
|
|
final JTextField pksInput = new JTextField(4);
|
|
pksInput.addFocusListener(new SelectAllOnFocusListener());
|
|
final JTextField hrsInput = new JTextField("" + hrsBackup, 5);
|
|
int derp = ((int) (record.getPicksPerHourNoBonus() * Double.parseDouble(hrsInput.getText())));
|
|
final JLabel msg = new JLabel("<html>Enter hours and picks for sample cut.<br>Values cannot exceed " + hrsBackup + " hours, " + pksBackup + " picks<br><br>Range that will not affect total picks: " + Math.max((derp - distanceFromMax), 0) + " - " + derp);
|
|
pksInput.setText("" + ((int) (record.getPicksPerHourNoBonus() * Double.parseDouble(hrsInput.getText()))));
|
|
hrsInput.addAncestorListener(new RequestFocusListener());
|
|
hrsInput.addFocusListener(new SelectAllOnFocusListener());
|
|
hrsInput.getDocument().addDocumentListener(new DocumentListener() {
|
|
public void changedUpdate(DocumentEvent e) {
|
|
update();
|
|
}
|
|
public void removeUpdate(DocumentEvent e) {
|
|
update();
|
|
}
|
|
public void insertUpdate(DocumentEvent e) {
|
|
update();
|
|
}
|
|
private void update(){
|
|
try {
|
|
int maxSampPicks;
|
|
if(hrsInput.getText().startsWith("m")) {
|
|
double minutes = (double) Integer.parseInt(hrsInput.getText().substring(1));
|
|
maxSampPicks = (int) (record.getPicksPerHourNoBonus() * round(minutes / 60.0, 2));
|
|
} else {
|
|
maxSampPicks = (int) (record.getPicksPerHourNoBonus() * Double.parseDouble(hrsInput.getText()));
|
|
}
|
|
pksInput.setText("" + maxSampPicks);
|
|
msg.setText("<html>Enter hours and picks for sample cut.<br>Values cannot exceed " + hrsBackup + " hours, " + pksBackup + " picks<br><br>Range that will not affect total picks: " + Math.max((maxSampPicks - distanceFromMax), 0) + " - " + maxSampPicks);
|
|
} catch(Exception e){
|
|
|
|
}
|
|
}
|
|
});
|
|
JTextField cut1Input = new JTextField(3);
|
|
cut1Input.addFocusListener(new SelectAllOnFocusListener());
|
|
JTextField cut2Input = new JTextField(3);
|
|
cut2Input.addFocusListener(new SelectAllOnFocusListener());
|
|
JPanel prompt = new JPanel(new MigLayout("fill"));
|
|
prompt.add(msg, "span 4, align center, wrap");
|
|
prompt.add(new JLabel("Hours"), "align right, grow");
|
|
prompt.add(hrsInput, "align left, grow");
|
|
prompt.add(new JLabel("Picks"), "align left, grow");
|
|
prompt.add(pksInput, "align right, grow, wrap");
|
|
prompt.add(new JLabel("Cut #"), "align right, grow");
|
|
prompt.add(cut1Input, "align left, grow");
|
|
prompt.add(new JLabel("Cut Suffix"), "align right, grow");
|
|
prompt.add(cut2Input, "align left, grow, wrap");
|
|
int option = JOptionPane.showOptionDialog(self, prompt, "Add Sample Cut - Loom " + record.getLoomNumber(),
|
|
JOptionPane.NO_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{ "Add", "Cancel" }, "Add");
|
|
if(option == 0){
|
|
int cutNumber = 0;
|
|
double sampHours = 0;
|
|
int sampPicks = 0;
|
|
String cutSuffix = "";
|
|
if(cut2Input.getText().length() > 2)
|
|
cutSuffix = cut2Input.getText().substring(0, 2).toUpperCase();
|
|
else
|
|
cutSuffix = cut2Input.getText().toUpperCase();
|
|
try{
|
|
if(hrsInput.getText().startsWith("m")) {
|
|
double minutes = (double) Integer.parseInt(hrsInput.getText().substring(1));
|
|
sampHours = round(minutes / 60.0, 2);
|
|
} else {
|
|
sampHours = Double.parseDouble(hrsInput.getText());
|
|
}
|
|
sampPicks = Integer.parseInt(pksInput.getText());
|
|
cutNumber = Integer.parseInt(cut1Input.getText());
|
|
|
|
if(sampHours <= 0)
|
|
throw new NumberFormatException("User passed a negative/zero hours value. Aint nobody got time fo dat.");
|
|
else if(sampHours > hrsBackup)
|
|
throw new NumberFormatException("Not enough hours to cut in sample! Orig Record: " + hrsBackup + " User Entered: " + sampHours);
|
|
if(sampPicks <= 0)
|
|
throw new NumberFormatException("User passed a negative/zero picks value. Aint nobody got time fo dat.");
|
|
else if(sampPicks > pksBackup)
|
|
throw new NumberFormatException("Not enough picks to cut in sample! Orig Record: " + pksBackup + " User Entered: " + sampPicks);
|
|
if(cutNumber < 1 || cutNumber > 999)
|
|
throw new NumberFormatException("Invalid cut number: " + cutNumber + ". Valid range [1 - 999]");
|
|
|
|
record.setHours(hrsBackup - sampHours);
|
|
record.setPicks(Math.min((pksBackup - sampPicks), record.getMaxPicks())); //By adjusting the hours first on the previous line; getMaxPicks() will return the new maximum picks that we do not wish to exceed
|
|
//record.setPicks(pksBackup - sampPicks);
|
|
//record.setHours(hrsBackup - sampHours);
|
|
} catch(NumberFormatException e2){
|
|
JOptionPane.showMessageDialog(self, "Non-negative decimal values please!\n\rNo changes made.", "Bogus Input", JOptionPane.ERROR_MESSAGE);
|
|
LOGGER.log(Level.SEVERE, "User passed us bogus input. Ignoring..", e2);
|
|
return;
|
|
}
|
|
try {
|
|
as400.adjustHoursPicks(record); //Decrease hours and picks of target record
|
|
as400.addSampleCut(record, cutNumber, cutSuffix, sampHours, sampPicks); //Add new SAM record to LOOMDS with desired hours/picks
|
|
reloadTab(key);
|
|
} catch (SQLException e1) {
|
|
LOGGER.log(Level.SEVERE, "Database transaction failed when attempting to cut in sample. Reverting Changes.", e1);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rSomething went wrong when applying this change to the AS400", "Update Failed", JOptionPane.ERROR_MESSAGE);
|
|
record.setHours(hrsBackup); //Revert hours in LoomDSRecord object to previous value since DB transaction failed
|
|
record.setPicks(pksBackup); //Revert picks in LoomDSRecord object to previous value since DB transaction failed
|
|
} catch (ParseException e1) {
|
|
LOGGER.log(Level.WARNING, "Failed to reload shift detail after record insert. Re-open the tab manually", e1);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rFailed to reload shift detail after record insert\n\rRe-open tab manually", "Whoops!", JOptionPane.WARNING_MESSAGE);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
delete.addActionListener(new ActionListener() {
|
|
private final Logger LOGGER = Logger.getLogger(LoomDSRecord.class.getName());
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
String msg = "<html>Are you absolutely sure you want to DELETE this record?<br>This _CANNOT_ be un-done!<br>";
|
|
msg = msg + "Loom: " + record.getLoomNumber() + "<br>";
|
|
msg = msg + "Weaver: " + record.getWeaverNameDisplay() + "<br>";
|
|
msg = msg + "Style: " + record.getLdStyle() + "<br>";
|
|
msg = msg + "Hours: " + record.getHours() + "<br>";
|
|
msg = msg + "Picks: " + record.getPicks() + "<br>";
|
|
msg = msg + "Down Time: " + record.getformattedDowntimeReason() + "<br>";
|
|
msg = msg + "Cut: " + record.getFormattedCutNumber() + "<br>";
|
|
msg = msg + "Type Code: " + record.getTypeCode();
|
|
int proceed = JOptionPane.showConfirmDialog(self, msg, "Delete Record", JOptionPane.OK_CANCEL_OPTION);
|
|
if(proceed == 0){
|
|
try {
|
|
as400.delRecord(record);
|
|
reloadTab(key);
|
|
} catch (SQLException e1) {
|
|
LOGGER.log(Level.SEVERE, "Database transaction failed when attempting to delete record..", e1);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rSomething went wrong when applying this change to the AS400", "Update Failed", JOptionPane.ERROR_MESSAGE);
|
|
} catch (ParseException e1) {
|
|
LOGGER.log(Level.WARNING, "Failed to reload shift detail after record deletion. Re-open the tab manually", e1);
|
|
JOptionPane.showMessageDialog(self, "Uh-oh..\n\rFailed to reload shift detail after record deletion\n\rRe-open tab manually", "Whoops!", JOptionPane.WARNING_MESSAGE);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
ret.add(adjPicks);
|
|
ret.add(adjHours);
|
|
ret.addSeparator();
|
|
ret.add(addSamp);
|
|
ret.addSeparator();
|
|
ret.add(chgWeav);
|
|
ret.add(setDT);
|
|
ret.addSeparator();
|
|
ret.add(delete);
|
|
|
|
return ret;
|
|
}
|
|
} |