Java tutorial
// The code in this file (LSForm.java) covers all functionality // surrounding the 'LiteShift' window (home screen). The window displays // a tabbed frame populated by opened Schedules. It serves as a platform for // nearly all of the functionality of LiteShift as a program. That is why it // is referred to as the home screen. /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package liteshiftwindow; import java.awt.Component; import java.awt.Frame; import java.io.BufferedWriter; import java.io.IOException; import java.text.DateFormat; import java.io.File; import java.io.FileWriter; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Date; import jxl.*; import jxl.write.Number; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JViewport; import javax.swing.table.TableModel; import jxl.Workbook; import jxl.format.Colour; import jxl.read.biff.BiffException; import jxl.write.Label; import jxl.write.WritableCellFormat; import jxl.write.WritableFont; import jxl.write.WritableSheet; import jxl.write.WritableWorkbook; import jxl.write.WriteException; import org.joda.time.LocalDate; import org.joda.time.format.DateTimeFormat; import java.util.Collections; /** * * @author Alec, Matthew, Taylor */ public class LSForm extends javax.swing.JFrame { /** * Creates new form LSForm */ public LSForm() { initComponents(); } public boolean firstRun = false; public List employeeList = new ArrayList(); public Employee admin = new Employee(); /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jLabel1 = new javax.swing.JLabel(); jTabbedSchedulePane = new javax.swing.JTabbedPane(); buttonNewSchedule = new javax.swing.JButton(); jDateChooser1 = new com.toedter.calendar.JDateChooser(); labelSelectWeek = new javax.swing.JLabel(); jMenuBar1 = new javax.swing.JMenuBar(); menuTabFile = new javax.swing.JMenu(); menuItemNewSchedule = new javax.swing.JMenuItem(); jSeparator1 = new javax.swing.JPopupMenu.Separator(); menuItemOpen = new javax.swing.JMenuItem(); jMenuItem2 = new javax.swing.JMenuItem(); jMenu3 = new javax.swing.JMenu(); menuItemXLS = new javax.swing.JMenuItem(); menuTabEdit = new javax.swing.JMenu(); menuItemSelectedRoster = new javax.swing.JMenu(); menuItemRosterShifts = new javax.swing.JMenuItem(); menuItemClearRoster = new javax.swing.JMenuItem(); optionDeleteRoster = new javax.swing.JMenuItem(); jSeparator2 = new javax.swing.JPopupMenu.Separator(); menuItemEmployeeRoster = new javax.swing.JMenuItem(); setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); setTitle("LiteShift"); jLabel1.setText("Shift Rosters by Week"); buttonNewSchedule.setText("New Schedule"); buttonNewSchedule.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { buttonNewScheduleActionPerformed(evt); } }); jDateChooser1.setDateFormatString("MM/dd/yyyy"); labelSelectWeek.setForeground(new java.awt.Color(255, 51, 51)); labelSelectWeek.setText("Please select a week"); fetchExistingEmployees(); menuTabFile.setText("File"); menuItemNewSchedule.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.event.InputEvent.CTRL_MASK)); menuItemNewSchedule.setText("New Schedule"); menuItemNewSchedule.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuItemNewScheduleActionPerformed(evt); } }); menuTabFile.add(menuItemNewSchedule); menuTabFile.add(jSeparator1); menuItemOpen.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.event.InputEvent.SHIFT_MASK | java.awt.event.InputEvent.CTRL_MASK)); menuItemOpen.setText("Open"); menuItemOpen.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuItemOpenActionPerformed(evt); } }); menuTabFile.add(menuItemOpen); jMenuItem2.setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK)); jMenuItem2.setText("Save"); jMenuItem2.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jMenuItem2ActionPerformed(evt); } }); menuTabFile.add(jMenuItem2); jMenu3.setText("Export As ..."); menuItemXLS.setText(".xls"); menuItemXLS.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuItemXLSActionPerformed(evt); } }); jMenu3.add(menuItemXLS); menuTabFile.add(jMenu3); jMenuBar1.add(menuTabFile); menuTabEdit.setText("Edit"); menuItemSelectedRoster.setText("Selected Roster"); menuItemSelectedRoster.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuItemSelectedRosterActionPerformed(evt); } }); menuItemRosterShifts.setText("Roster Shifts"); menuItemRosterShifts.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuItemRosterShiftsActionPerformed(evt); } }); menuItemSelectedRoster.add(menuItemRosterShifts); menuItemClearRoster.setText("Clear Roster"); menuItemClearRoster.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuItemClearRosterActionPerformed(evt); } }); menuItemSelectedRoster.add(menuItemClearRoster); optionDeleteRoster.setText("Close Roster"); optionDeleteRoster.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { optionDeleteRosterActionPerformed(evt); } }); menuItemSelectedRoster.add(optionDeleteRoster); menuTabEdit.add(menuItemSelectedRoster); menuTabEdit.add(jSeparator2); menuItemEmployeeRoster.setText("Employee Roster"); menuItemEmployeeRoster.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { menuItemEmployeeRosterActionPerformed(evt); } }); menuTabEdit.add(menuItemEmployeeRoster); jMenuBar1.add(menuTabEdit); setJMenuBar(jMenuBar1); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup().addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jTabbedSchedulePane) .addGroup(layout.createSequentialGroup().addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 582, Short.MAX_VALUE) .addComponent(labelSelectWeek) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jDateChooser1, javax.swing.GroupLayout.PREFERRED_SIZE, 117, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(buttonNewSchedule))) .addContainerGap())); layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup().addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel1).addComponent(buttonNewSchedule) .addComponent(labelSelectWeek)) .addComponent(jDateChooser1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jTabbedSchedulePane, javax.swing.GroupLayout.DEFAULT_SIZE, 211, Short.MAX_VALUE) .addContainerGap())); labelSelectWeek.setVisible(false); pack(); }// </editor-fold>//GEN-END:initComponents // Handling function for clicking File > New Schedule // Exactly mimics the functionality of clicking the "New Schedule" button // next to the calendar widget. private void menuItemNewScheduleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemNewScheduleActionPerformed buttonNewScheduleActionPerformed(evt); }//GEN-LAST:event_menuItemNewScheduleActionPerformed // Does nothing yet. private void jMenuItem2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenuItem2ActionPerformed // TODO add your handling code here: }//GEN-LAST:event_jMenuItem2ActionPerformed public void setfirstRun() { File dirPath = new File("").getAbsoluteFile(); try { String fileContents = new String(Files.readAllBytes(Paths .get(dirPath + ((System.getProperty("os.name").contains("Mac")) ? "/employees/employeeList.txt" : "\\employees\\employeeList.txt")))); firstRun = (fileContents.length() == 0); } catch (IOException e) { System.out.println(e); } } // Handling function for clicking Edit > Selected Roster > Roster Shifts button // This program does not utilize a working Schedule Rostering Algorithm yet. // This function will eventually call this algorithm. // For now, we pretend that we have retrieved a roster. // This function looks at a 2-dimensional array of "shift times" and writes them // to the selected schedule. private void menuItemRosterShiftsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemRosterShiftsActionPerformed List tempEmployeeList = getAllEmployees(); int maxShifts = 10; int numberOfEmployees = tempEmployeeList.size(); //stores the number of employees Employee[] employees = new Employee[tempEmployeeList.size()]; tempEmployeeList.toArray(employees); //Create the schedule using maxShifts for declaring the 3rd dimension Schedule schedule = new Schedule(maxShifts); Schedule bestSchedule = new Schedule(maxShifts); //this is used for holding the greatest schedule MyStack theStack = new MyStack(numberOfEmployees); //integer array implementation of a stack int topScore = 0; /* All of the code within the first for block is the liteShift heuristic. To describe in short, the code will generate X schedules, X being the integer that runTime is compared with. For every schedule generated, several things occur. First, shuffle the employees array containing every employee. Then, for every day, and for every shift of that day, cycle through all employees. If that employee is available and not at capacity (determined by pt/ft status), then two things can occur. If the shift in question is the night shift, then that employee cannot be scheduled in the morning if they are to be scheduled during the night because then they would be working all day, or it would mean that they would have a large mid-day break which goes against our scheduling philosophy. If the employee has not been scheduled for a morning shift then we push them to the stack assuming all else is true. Alternatively, the shift in question is not the night shift, and if the employee is available and not at capacity then they are pushed to the stack. The stack for this problem represents all employees available on a given shift on a given day. We chose to use the stack data structure because it is the most efficient data structure for our problem representation. Using a stack allows us to only use one data structure for temporarily holding all available employees in question. After pushing 'OK' employees to the stack the stack is popped maxShifts times. This will add the proper amount of employees to the actual schedule for shift i on day j. After popping the proper number of employees and adding them to the actual schedule, pop the stack until empty to prepare the stack for the next loop iteration. The next phase of the liteShift heuristic is to score the current schedule. This is done through comparing an employee's soft constraints with what they were actually given. In the case that their soft constraints are satisfied the schedule's score is increased. The score for the current schedule is comapred with that of the highest scoring schedule and kept if it is higher. */ for (int runTime = 0; runTime < 10000; runTime++) { Collections.shuffle(Arrays.asList(employees)); for (int j = 0; j < 7; j++) for (int i = 0; i < 3; i++) { for (int k = 0; k < numberOfEmployees; k++) { if ((employees[k].hardShiftConstraints[j][i] == true) && (!employees[k].isFull())) { if (i == 2) { if (!schedule.scheduledInMorning(j, employees[k].Name(), maxShifts)) theStack.push(k); } else theStack.push(k); } } for (int d = 0; d < maxShifts; d++) if (!theStack.isEmpty()) schedule.updateSchedule(i, j, d, employees[(theStack.pop())]); while (!theStack.isEmpty()) theStack.pop(); } for (int i = 0; i < numberOfEmployees; i++) employees[i].reset(); int score = 0; for (int i = 0; i < 3; i++) for (int j = 0; j < 7; j++) for (int k = 0; k < maxShifts; k++) if (schedule.ScoreCheck(i, j, k)) score += 2; if (score > topScore) { bestSchedule = schedule; topScore = score; } } /* System.out.println(topScore); for(int i = 0; i < 7; i++) { for(int j = 0; j < 3; j++) { for(int k = 0; k < maxShifts;k++) bestSchedule.showName(j, i, k); System.out.println(); } System.out.println("\n"); } */ for (int i = 0; i < 3; i++) for (int j = 0; j < 7; j++) for (int k = 0; k < maxShifts; k++) { if (i == 0) { if (bestSchedule.schedule[i][j][k].actualSchedule[j] == null) { bestSchedule.schedule[i][j][k].actualSchedule[j] = ""; bestSchedule.schedule[i][j][k].actualSchedule[j] += "m"; } } else if (i == 1) { if (bestSchedule.schedule[i][j][k].actualSchedule[j] == null) { bestSchedule.schedule[i][j][k].actualSchedule[j] = ""; bestSchedule.schedule[i][j][k].actualSchedule[j] += "a"; } else bestSchedule.schedule[i][j][k].actualSchedule[j] += "a"; } else { if (bestSchedule.schedule[i][j][k].actualSchedule[j] == null) { bestSchedule.schedule[i][j][k].actualSchedule[j] = ""; bestSchedule.schedule[i][j][k].actualSchedule[j] += "n"; } else bestSchedule.schedule[i][j][k].actualSchedule[j] += "n"; } } /* for(int i = 0; i < numberOfEmployees; i++) { System.out.print(employees[i].Name + " "); for(int j = 0; j < 7; j++) { System.out.print(employees[i].actualSchedule[j] + " "); } System.out.println(); } */ //String [] employeeList = getAllEmployees(); JScrollPane pane = (JScrollPane) jTabbedSchedulePane.getComponentAt(jTabbedSchedulePane.getSelectedIndex()); TableModel jtm = ((JTable) pane.getViewport().getComponent(0)).getModel(); int employeesRostered = 0; /* // A (sample) hard-coded shift roster String [][] shiftRoster = { // Sunday Monday Tuesday Wedmesday Thursday Friday Saturday {"", "1:00pm - 9:00pm", "1:00pm - 9:00pm", "1:00pm - 9:00pm", "1:00pm - 9:00pm", "1:00pm - 9:00pm", "OFF" , "OFF"}, {"", "OFF", "OFF", "OFF", "7:00am - 1:00pm", "OFF", "7:00am - 1:00pm", "7:00am - 1:00pm"}, {"", "7:00am - 1:00pm", "7:00am - 1:00pm", "OFF", "OFF", "7:00am - 1:00pm", "OFF", "OFF"}, {"", "OFF", "OFF", "7:00am - 1:00pm", "OFF", "OFF", "1:00pm - 9:00pm", "1:00pm - 9:00pm"}, {null, null, null, null, null, null, null, null}, {null, null, null, null, null, null, null, null}, {null, null, null, null, null, null, null, null}, {null, null, null, null, null, null, null, null}, {null, null, null, null, null, null, null, null}, {null, null, null, null, null, null, null, null} }; */ String[][] shiftRoster = new String[tempEmployeeList.size()][8]; // Populate each Table Row. First cell = Employee Name for (int i = 0; i < employeeList.size(); i++) { shiftRoster[i][0] = ((Employee) employeeList.get(i)).getName(); } for (int i = 0; i < tempEmployeeList.size(); i++) { for (int j = 0; j < 7; j++) { if ((((Employee) tempEmployeeList.get(i)).actualSchedule[j]) != null) { if ((((Employee) tempEmployeeList.get(i)).actualSchedule[j]).equals("m")) shiftRoster[i][j + 1] = "8:00am - 12:00pm"; else if ((((Employee) tempEmployeeList.get(i)).actualSchedule[j]).equals("a")) shiftRoster[i][j + 1] = "12:00pm - 4:00pm"; else if ((((Employee) tempEmployeeList.get(i)).actualSchedule[j]).equals("n")) shiftRoster[i][j + 1] = "4:00pm - 8:00pm"; else if ((((Employee) tempEmployeeList.get(i)).actualSchedule[j]).equals("ma")) shiftRoster[i][j + 1] = "8:00am - 4:00pm"; else if ((((Employee) tempEmployeeList.get(i)).actualSchedule[j]).equals("an")) shiftRoster[i][j + 1] = "12:00pm - 8:00pm"; } } } for (int i = 0; i < employeeList.size(); i++) { for (int j = 0; j < 8; j++) { employeesRostered++; jtm.setValueAt(shiftRoster[i][j], i, j); } } for (int i = employeesRostered; i < employeeList.size(); i++) { for (int j = 0; j < 8; j++) { jtm.setValueAt(null, i, j); } } }//GEN-LAST:event_menuItemRosterShiftsActionPerformed // Clear the selected schedule roster of all entries, including employee names. public void clearSelectedRoster() { JScrollPane pane = (JScrollPane) jTabbedSchedulePane.getComponentAt(jTabbedSchedulePane.getSelectedIndex()); TableModel jtm = ((JTable) pane.getViewport().getComponent(0)).getModel(); for (int i = 0; i < employeeList.size(); i++) { for (int j = 0; j < 8; j++) { jtm.setValueAt(null, i, j); } } } // Handling function for clicking Edit > Selected Roster > Clear Roster // Utilizes clearSelectedRoster() funciton to clear the selected roster. private void menuItemClearRosterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemClearRosterActionPerformed String tabTitle = jTabbedSchedulePane.getTitleAt(jTabbedSchedulePane.getSelectedIndex()); int choice = JOptionPane.showConfirmDialog(null, "Are you sure you want to clear roster for " + tabTitle + " ?", "Confirm Roster Clear", JOptionPane.YES_NO_OPTION); if (choice == JOptionPane.YES_OPTION) { clearSelectedRoster(); } }//GEN-LAST:event_menuItemClearRosterActionPerformed // Build a name for the schedule: "Month/FirstDay - Month/LastDay" public String getTabName() { // When using the JCalendar widget, its "selected day" output is in MMM dd, yyyy format. // This funciton takes that information, finds the first day of the week that selected day is in // and names the tab after it. // e.g. if the user selected Feb 2, a Monday. The following steps are executed: // 1. Find that the first day of that week is Sunday, Feb 1. // 2. Find that the last day of that week is Saturday, Feb 7. // 3. Return the following string: "02/01 - 02/07" // This returned information is later used in the program to "name" the schedule. org.joda.time.format.DateTimeFormatter MdYFormat = DateTimeFormat.forPattern("MMM dd, yyyy"); Date selectedDay = jDateChooser1.getDate(); if (selectedDay == null) return null; String strDay = DateFormat.getDateInstance().format(selectedDay); LocalDate jodaDate = LocalDate.parse(strDay, MdYFormat); LocalDate Sunday = getSunday(jodaDate); org.joda.time.format.DateTimeFormatter MdFormat = DateTimeFormat.forPattern("MM/dd"); String tabName = Sunday.toString(MdFormat) + " - " + Sunday.plusDays(6).toString(MdFormat); return tabName; } // Function is used when exporting the table to file. // This function is passed days of the week, e.g. "Monday", "Tuesday", etc. // It's job is to find out what day of the year (in MM/dd format) these strings signify // by looking at the week that the exported schedule is for. public String getNumberDate(String inputDay) { org.joda.time.format.DateTimeFormatter MdYFormat = DateTimeFormat.forPattern("MM/dd/yyyy"); org.joda.time.format.DateTimeFormatter MdFormat = DateTimeFormat.forPattern("MM/dd"); String tabName = jTabbedSchedulePane.getTitleAt(jTabbedSchedulePane.getSelectedIndex()); // TODO: year LocalDate jodaDate = LocalDate.parse(tabName.split(" ")[0] + "/2015", MdYFormat); LocalDate Sunday = getSunday(jodaDate); String[] days = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; for (int i = 0; i < 7; i++) { if (inputDay.compareTo(days[i]) == 0) return Sunday.plusDays(i).toString(MdFormat); } return "0/0"; } // The user has the option to choose any day on the calendar when they are prompted // to select a week for a new schedule. // This function finds the first day (Sunday) of the week that the selected day belongs to // and returns that Sunday as a Date object. public LocalDate getSunday(LocalDate selectedDate) { // If the user selected a Sunday, return that sunday. if (selectedDate.dayOfWeek().get() == 7) { return selectedDate; } else { selectedDate = selectedDate.minusWeeks(1); return selectedDate.withDayOfWeek(7); } } // Function returns an array that lists all employees. public List getAllEmployees() { // Hardcoded list of employees for testing List employees = this.employeeList; //String [] employeeList = new String [] {"Jim", "Sue", "Bill", "Sally"}; return employeeList; } // Returns a 'blank template' table, formatted like a schedule. // // Calls getAllEmployees() for a list of employees to print in the // 'Name' column // public JTable newScheduleTemplate() { List employeeList = getAllEmployees(); Object[][] cells = new Object[employeeList.size()][8]; int populatedRows = 0; // Populate a row with "Name", followed by null entires for work times. for (int i = 0; i < employeeList.size(); i++) { if (populatedRows < employeeList.size()) { populatedRows++; cells[i][0] = ((Employee) employeeList.get(i)).getName(); for (int j = 1; j < 8; j++) { cells[i][j] = null; } } else break; } // If there are less than 10 employees, the remaining rows should be blank. for (int i = populatedRows; i < employeeList.size(); i++) { for (int j = 0; j < 8; j++) { cells[i][j] = null; } } javax.swing.JTable newScheduleTable = new javax.swing.JTable(); newScheduleTable.setModel(new javax.swing.table.DefaultTableModel(cells, // Columns new String[] { "Employee", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" })); newScheduleTable.getTableHeader().setReorderingAllowed(false); return newScheduleTable; } // Handler function for the 'New Schedule' button private void buttonNewScheduleActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonNewScheduleActionPerformed // Instantiate a new tab. // Call the newScheduleTemplate() function to instantiate a 'blank-template' schedule table. // Fill the new tab with the new table. if (jDateChooser1.getDate() == null) { labelSelectWeek.setVisible(true); return; } else labelSelectWeek.setVisible(false); JTable newScheduleTable = newScheduleTemplate(); JScrollPane newPane = new javax.swing.JScrollPane(); newPane.setViewportView(newScheduleTable); jTabbedSchedulePane.addTab(getTabName(), newPane); jTabbedSchedulePane.setSelectedIndex(jTabbedSchedulePane.getTabCount() - 1); }//GEN-LAST:event_buttonNewScheduleActionPerformed // Handling code for clicking the Edit > Delete Roster // Deletes the selected schedule. private void optionDeleteRosterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_optionDeleteRosterActionPerformed String tabTitle = jTabbedSchedulePane.getTitleAt(jTabbedSchedulePane.getSelectedIndex()); int choice = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete roster for " + tabTitle + " ?", "Confirm Deletion", JOptionPane.YES_NO_OPTION); if (choice == JOptionPane.YES_OPTION) { jTabbedSchedulePane.remove(jTabbedSchedulePane.getSelectedIndex()); } }//GEN-LAST:event_optionDeleteRosterActionPerformed // Handling code for clicking the File > Save As ... > .xls button // Form a name for the new file from the Title of the schedule's tab // Open (for writing) a new .xls file given this name // Iterate over the selected schedule table, as it reads the contents from the table, write it to the .xls file. // Close/Save the .xls file private void menuItemXLSActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemXLSActionPerformed File dirPath = new File("").getAbsoluteFile(); String tabTitle = jTabbedSchedulePane.getTitleAt(jTabbedSchedulePane.getSelectedIndex()).replace("/", "-"); File newFile = new File( dirPath + ((System.getProperty("os.name").contains("Mac")) ? "/exported/" : "\\exported\\") + tabTitle.split(" ")[0] + ") - (" + tabTitle.split(" ")[2] + ").xls"); JScrollPane pane = (JScrollPane) jTabbedSchedulePane.getComponentAt(jTabbedSchedulePane.getSelectedIndex()); TableModel jtm = ((JTable) pane.getViewport().getComponent(0)).getModel(); String[] HeaderItems = { "Employee", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; // Need to read from current tab's table. WritableWorkbook workbook; try { workbook = Workbook.createWorkbook(newFile); WritableSheet sheet = workbook.createSheet("Schedule", 0); WritableFont arialBlueBoldFont = new WritableFont(WritableFont.ARIAL, 10, WritableFont.BOLD, true); WritableCellFormat arialBlueBoldFormat = new WritableCellFormat(arialBlueBoldFont); arialBlueBoldFormat.setBackground(Colour.PALE_BLUE); WritableFont arialGrayFont = new WritableFont(WritableFont.ARIAL, 10, WritableFont.BOLD, true); WritableCellFormat arialGrayFormat = new WritableCellFormat(arialGrayFont); arialGrayFormat.setBackground(Colour.GRAY_25); WritableFont arialBlueFont = new WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false); WritableCellFormat arialBlueFormat = new WritableCellFormat(arialBlueFont); arialBlueFormat.setBackground(Colour.PALE_BLUE); Label label = new Label(0, 0, "Employee", arialGrayFormat); sheet.addCell(label); sheet.setColumnView(0, 18); // Each cell in the top Row of the outputted table should be "DayOfWeek MM/dd" e.g. "Sunday 02/01" for (int j = 1; j < 8; j++) { label = new Label(j, 0, HeaderItems[j] + " " + getNumberDate(HeaderItems[j]), arialGrayFormat); sheet.addCell(label); sheet.setColumnView(j, 18); } // Copy over the information from LiteShift's schedule table into the .xls table // Format the rows with color and font where necessary. for (int i = 0; i < getAllEmployees().size(); i++) { for (int j = 0; j < 8; j++) { if (jtm.getValueAt(i, j) == null) { if (j == 0) label = new Label(j, i + 1, "OFF", arialBlueBoldFormat); else if (i % 2 == 0) label = new Label(j, i + 1, "OFF", arialBlueFormat); else label = new Label(j, i + 1, "OFF"); } else if (j == 0) label = new Label(j, i + 1, jtm.getValueAt(i, j).toString(), arialBlueBoldFormat); else if (i % 2 == 0) label = new Label(j, i + 1, jtm.getValueAt(i, j).toString(), arialBlueFormat); else label = new Label(j, i + 1, jtm.getValueAt(i, j).toString()); sheet.addCell(label); } } workbook.write(); workbook.close(); } catch (IOException | WriteException ex) { Logger.getLogger(LSForm.class.getName()).log(Level.SEVERE, null, ex); } }//GEN-LAST:event_menuItemXLSActionPerformed // Funtion used in menuItemOpenActionPerformed handling code. // Given a file path, open the file, read it. // Output what is read into a new JTable. // Return the JTable public JTable openNewFile(String filePath) { JTable newScheduleTable = new JTable(); try { Workbook workbook = Workbook.getWorkbook(new File(filePath)); Sheet sheet = workbook.getSheet(0); List employeeList = getAllEmployees(); //String [] employeeList = new String [] {"Jim", "Sue", "Bill", "Sally"}; Object[][] cells = new Object[employeeList.size()][8]; int populatedRows = 0; System.out.println(employeeList.size()); // Populate a row with "Name", followed by null entires for work times. for (int i = 1; i < sheet.getRows(); i++) { if (populatedRows < sheet.getRows()) { populatedRows++; cells[i - 1][0] = sheet.getCell(0, i).getContents(); System.out.println(sheet.getCell(0, i).getContents()); for (int j = 1; j < 8; j++) { cells[i - 1][j] = sheet.getCell(j, i).getContents(); } } else break; } // If there are less than 10 employees, the remaining rows should be blank. for (int i = populatedRows; i < employeeList.size(); i++) { for (int j = 0; j < 8; j++) { cells[i][j] = null; } } newScheduleTable.setModel(new javax.swing.table.DefaultTableModel(cells, // Columns new String[] { "Employee", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" })); newScheduleTable.getTableHeader().setReorderingAllowed(false); } catch (IOException | BiffException ex) { Logger.getLogger(LSForm.class.getName()).log(Level.SEVERE, null, ex); } return newScheduleTable; } // Takes a string as a parameter. The string is in the file path format. // Given some information in the file name, return an appropriate Name for the opened schedule public String getFormattedImportTitle(String filePath) { String[] dirs = filePath.split("\\\\"); filePath = dirs[dirs.length - 1].replace("(", "").replace(")", "").replace("-", "/").replace(" / ", " - ") .replace(".xls", ""); return filePath; } // Handling code for clicking the File > Open button. // Open a File choosing window, get the contents of the selected file // Create a tab for the schedule private void menuItemOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemOpenActionPerformed JFileChooser chooseWindow = new JFileChooser( new File("C:\\Users\\Matthew\\Documents\\NetBeansProjects\\LiteShiftWindow\\dist")); chooseWindow.showOpenDialog(null); File selectedFile = chooseWindow.getSelectedFile(); String filePath = selectedFile.getAbsolutePath(); JTable newScheduleTable = openNewFile(filePath); JScrollPane newPane = new JScrollPane(); newPane.setViewportView(newScheduleTable); jTabbedSchedulePane.addTab(getFormattedImportTitle(filePath), newPane); jTabbedSchedulePane.setSelectedIndex(jTabbedSchedulePane.getTabCount() - 1); }//GEN-LAST:event_menuItemOpenActionPerformed // Handling code for clicking on the Edit > Employee Roster button. // Instantiate a employeeRosterFrame; make it visible. private void menuItemEmployeeRosterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemEmployeeRosterActionPerformed Frame[] frameArray = Frame.getFrames(); for (Frame curFrame : frameArray) { if (curFrame.getTitle().equals("Employee Roster")) { employeeRosterFrame erFrame = (employeeRosterFrame) curFrame; erFrame.setVisible(true); } } }//GEN-LAST:event_menuItemEmployeeRosterActionPerformed public Employee getEmployeeObjectFromString(String empName) { for (int i = 0; i < employeeList.size(); i++) { if ((((Employee) (employeeList.get(i))).Name).equals(empName)) return ((Employee) (employeeList.get(i))); } return null; } // Given an employee name, open their file and convert the file contents // to an Employee object. public Employee getEmployeeObjectFromFile(String empName) { Employee newEmp = new Employee(); newEmp.Name = empName.replace("_", " "); //System.out.println("Name: \"" + empName + "\""); File dirPath = new File("").getAbsoluteFile(); try { String fileContents = new String(Files.readAllBytes(Paths.get( dirPath + ((System.getProperty("os.name").contains("Mac")) ? "/employees/" : "\\employees\\") + empName + ".txt"))); String[] splitLines = fileContents.split("\\r?\\n"); String[] employeeInfo = (splitLines[0]).split(","); // 0 1 2 3 4 5 // Name , Title , hardMinHours , hardMaxHours , softMinHours , softMaxHours newEmp.Title = employeeInfo[1]; newEmp.fullTime = ((newEmp.Title).equals("Manager")); newEmp.hardMinHours = Integer.parseInt(employeeInfo[2]); newEmp.hardMaxHours = Integer.parseInt(employeeInfo[3]); newEmp.softMinHours = Integer.parseInt(employeeInfo[4]); newEmp.softMaxHours = Integer.parseInt(employeeInfo[5]); // 0,1,1, 1,1,1, 1,1,1, 1,1,1, 1,1,1, 1,1,1, 0,1,1 String[] softAvailStrings = (splitLines[1]).split(","); String[] hardAvailStrings = (splitLines[2]).split(","); boolean[][] softAvail = new boolean[7][3]; boolean[][] hardAvail = new boolean[7][3]; for (int i = 0; i < 21; i += 3) { newEmp.softShiftConstraints[i / 3][0] = (softAvailStrings[i].equals("1")); newEmp.softShiftConstraints[i / 3][1] = (softAvailStrings[i + 1].equals("1")); newEmp.softShiftConstraints[i / 3][2] = (softAvailStrings[i + 2].substring(0, 1).equals("1")); } for (int i = 0; i < 21; i += 3) { newEmp.hardShiftConstraints[i / 3][0] = (hardAvailStrings[i].equals("1")); newEmp.hardShiftConstraints[i / 3][1] = (hardAvailStrings[i + 1].equals("1")); newEmp.hardShiftConstraints[i / 3][2] = (hardAvailStrings[i + 2].substring(0, 1).equals("1")); } //System.out.println(fileContents); //populateEmployeeList(fileContents); } catch (IOException e) { System.out.println(e); } return newEmp; } // Populate the employee roster with any existing employees in the 'employees' directory public void populateEmployeeList(String contents) { Employee newEmp = new Employee(); // Interpret an employee name String[] splitNames = contents.split("\\r?\\n"); for (int i = 0; i < splitNames.length; i++) { // Open the employee's personal file & convert to employee object newEmp = getEmployeeObjectFromFile(splitNames[i]); // Add the employee object to the employeeList employeeList.add(newEmp); } //employeeList.add(newEmployee); } // Get the contents of the employeeList file, send it to populateEmployeeList public void fetchExistingEmployees() { File dirPath = new File("").getAbsoluteFile(); try { String fileContents; if (System.getProperty("os.name").contains("Mac")) fileContents = new String(Files.readAllBytes(Paths.get(dirPath + "/employees/employeeList.txt"))); else fileContents = new String(Files.readAllBytes(Paths.get(dirPath + "\\employees\\employeeList.txt"))); if (fileContents.length() != 0) populateEmployeeList(fileContents); } catch (IOException e) { System.out.println(e); } } // Not implemented yet private void menuItemSelectedRosterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_menuItemSelectedRosterActionPerformed // TODO add your handling code here: }//GEN-LAST:event_menuItemSelectedRosterActionPerformed /** * @param args the command line arguments */ public static void main(String args[]) { /* Set the Nimbus look and feel */ //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) "> /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel. * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html */ try { for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { javax.swing.UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (ClassNotFoundException ex) { java.util.logging.Logger.getLogger(LSForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (InstantiationException ex) { java.util.logging.Logger.getLogger(LSForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (IllegalAccessException ex) { java.util.logging.Logger.getLogger(LSForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } catch (javax.swing.UnsupportedLookAndFeelException ex) { java.util.logging.Logger.getLogger(LSForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } //</editor-fold> /* Create and display the form */ java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new LSForm().setVisible(true); } }); } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton buttonNewSchedule; private com.toedter.calendar.JDateChooser jDateChooser1; private javax.swing.JLabel jLabel1; private javax.swing.JMenu jMenu3; private javax.swing.JMenuBar jMenuBar1; private javax.swing.JMenuItem jMenuItem2; private javax.swing.JPopupMenu.Separator jSeparator1; private javax.swing.JPopupMenu.Separator jSeparator2; private javax.swing.JTabbedPane jTabbedSchedulePane; private javax.swing.JLabel labelSelectWeek; private javax.swing.JMenuItem menuItemClearRoster; private javax.swing.JMenuItem menuItemEmployeeRoster; private javax.swing.JMenuItem menuItemNewSchedule; private javax.swing.JMenuItem menuItemOpen; private javax.swing.JMenuItem menuItemRosterShifts; private javax.swing.JMenu menuItemSelectedRoster; private javax.swing.JMenuItem menuItemXLS; private javax.swing.JMenu menuTabEdit; private javax.swing.JMenu menuTabFile; private javax.swing.JMenuItem optionDeleteRoster; // End of variables declaration//GEN-END:variables }