package edu.pdx.cs410J.grader;
import edu.pdx.cs410J.ParserException;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
/**
* This panel is used to display and edit <code>Assignment</code>s.
*/
@SuppressWarnings("serial")
public class AssignmentPanel extends JPanel {
private static final String QUIZ = "Quiz";
private static final String PROJECT = "Project";
private static final String OTHER = "Other";
private static final String OPTIONAL = "Optional";
private static final String POA = "POA";
static final String DATE_TIME_FORMAT_PATTERN = "M/d/yyyy h:mm a";
static final DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormatter.ofPattern(DATE_TIME_FORMAT_PATTERN);
// GUI components we care about
private JTextField nameField;
private JComboBox<String> typeBox;
private JTextField pointsField;
private JTextField descriptionField;
private JTextField dueDateField;
private NotesPanel notes;
/**
* Creates and adds GUI components to a new
* <code>AssignmentPanel</code>.
*/
public AssignmentPanel(boolean canCreate) {
this.setLayout(new BorderLayout());
// Panel containing information about an assignment
JPanel infoPanel = new JPanel();
infoPanel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
infoPanel.setLayout(new BorderLayout());
addAssignmentInformationWidgets(infoPanel);
this.add(infoPanel, BorderLayout.NORTH);
if (!canCreate) {
this.nameField.setEditable(false);
}
// Add a NotePanel
this.notes = new NotesPanel();
this.notes.setNotable(new Notable() {
private ArrayList<String> notes = new ArrayList<>();
@Override
public java.util.List<String> getNotes() {
return notes;
}
@Override
public void addNote(String note) {
notes.add(note);
}
@Override
public void removeNote(String note) {
notes.remove(note);
}
});
this.add(notes, BorderLayout.CENTER);
}
private void addAssignmentInformationWidgets(JPanel infoPanel) {
JPanel labels = new JPanel();
labels.setLayout(new GridLayout(0, 1));
labels.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 2));
labels.add(new JLabel("Name:"));
labels.add(new JLabel("Max points:"));
labels.add(new JLabel("Type:"));
labels.add(new JLabel("Description:"));
labels.add(new JLabel("Due date:"));
JPanel fields = new JPanel();
fields.setLayout(new GridLayout(0, 1));
this.nameField = new JTextField(8);
fields.add(this.nameField);
this.pointsField = new JTextField(5);
fields.add(this.pointsField);
addTypeBox(fields);
this.descriptionField = new JTextField(20);
fields.add(this.descriptionField);
this.dueDateField = new JTextField(22);
fields.add(this.dueDateField);
infoPanel.add(labels, BorderLayout.WEST);
infoPanel.add(fields, BorderLayout.CENTER);
}
private void addTypeBox(JPanel fields) {
this.typeBox = new JComboBox<>();
this.typeBox.addItem(QUIZ);
this.typeBox.addItem(PROJECT);
this.typeBox.addItem(POA);
this.typeBox.addItem(OTHER);
this.typeBox.addItem(OPTIONAL);
fields.add(this.typeBox);
}
/**
* Creates a new <code>Assignment</code> based on the contents of
* this <code>AssignmentPanel</code>.
*/
public Assignment createAssignment() {
// Get the name and max points of the assignment
String name = nameField.getText();
if (isNullOrEmpty(name)) {
return error("No assignment name specified");
}
String points = pointsField.getText();
if (isNullOrEmpty(points)) {
return error("No points value specified");
}
// Create a new Assignment object
try {
double d = Double.parseDouble(points);
Assignment newAssign = new Assignment(name, d);
this.notes.getNotable().getNotes().forEach(newAssign::addNote);
updateAssignment(newAssign);
this.notes.setNotable(newAssign);
return newAssign;
} catch (NumberFormatException ex) {
return error(points + " is not a number");
}
}
private boolean isNullOrEmpty(String name) {
return name == null || name.equals("");
}
private Assignment error(String message) {
JOptionPane.showMessageDialog(AssignmentPanel.this,
new String[]{message},
"Error",
JOptionPane.ERROR_MESSAGE);
return null;
}
/**
* Displays the contents of a given <code>Assignment</code> in this
* <code>AssignmentPanel</code>.
*/
public void displayAssignment(Assignment assign) {
this.nameField.setText(assign.getName());
this.pointsField.setText(String.valueOf(assign.getPoints()));
Assignment.AssignmentType type = assign.getType();
if (type == Assignment.AssignmentType.QUIZ) {
this.typeBox.setSelectedItem(QUIZ);
} else if (type == Assignment.AssignmentType.PROJECT) {
this.typeBox.setSelectedItem(PROJECT);
} else if (type == Assignment.AssignmentType.OTHER) {
this.typeBox.setSelectedItem(OTHER);
} else if (type == Assignment.AssignmentType.OPTIONAL) {
this.typeBox.setSelectedItem(OPTIONAL);
} else if (type == Assignment.AssignmentType.POA) {
this.typeBox.setSelectedItem(POA);
} else {
String s = "Invalid assignment type: " + type;
throw new IllegalArgumentException(s);
}
String description = assign.getDescription();
if (isNotEmpty(description)) {
this.descriptionField.setText(description);
} else {
this.descriptionField.setText("");
}
LocalDateTime dueDate = assign.getDueDate();
if (dueDate != null) {
this.dueDateField.setText(DATE_TIME_FORMAT.format(dueDate));
} else {
this.dueDateField.setText("");
}
this.notes.setNotable(assign);
}
/**
* Fills in the contents of an <code>Assignment</code> based on the
* contents of this <code>AssignmentPanel</code>.
*/
public void updateAssignment(Assignment assign) {
String points = pointsField.getText();
if (isNullOrEmpty(points)) {
error("No points value specified");
return;
}
try {
double d = Double.parseDouble(points);
assign.setPoints(d);
} catch (NumberFormatException ex) {
error(points + " is not a number");
return;
}
setAssignmentType(assign);
String description = this.descriptionField.getText();
if (isNotEmpty(description)) {
assign.setDescription(description);
}
String dueDate = this.dueDateField.getText();
if (isNotEmpty(dueDate)) {
try {
assign.setDueDate(LocalDateTime.parse(dueDate.trim(), DATE_TIME_FORMAT));
} catch (DateTimeParseException ex) {
error(dueDate + " is not a validate date (" + DATE_TIME_FORMAT_PATTERN + ")");
}
} else {
assign.setDueDate(null);
}
// Adding notes is taken care of by the NotesPanel
}
private void setAssignmentType(Assignment assign) {
String type = (String) this.typeBox.getSelectedItem();
switch (type) {
case QUIZ:
assign.setType(Assignment.AssignmentType.QUIZ);
break;
case PROJECT:
assign.setType(Assignment.AssignmentType.PROJECT);
break;
case OTHER:
assign.setType(Assignment.AssignmentType.OTHER);
break;
case OPTIONAL:
assign.setType(Assignment.AssignmentType.OPTIONAL);
break;
case POA:
assign.setType(Assignment.AssignmentType.POA);
break;
default:
String s = "Unknown assignment type: " + type;
throw new IllegalArgumentException(s);
}
}
private boolean isNotEmpty(String description) {
return description != null && !description.equals("");
}
/**
* Test program
*/
public static void main(String[] args) {
String fileName = args[0];
String assignName = args[1];
GradeBook book = null;
try {
XmlGradeBookParser parser = new XmlGradeBookParser(fileName);
book = parser.parse();
} catch (FileNotFoundException ex) {
System.err.println("** Could not find file: " + ex.getMessage());
System.exit(1);
} catch (IOException ex) {
System.err.println("** IOException during parsing: " + ex.getMessage());
System.exit(1);
} catch (ParserException ex) {
System.err.println("** Error during parsing: " + ex);
System.exit(1);
}
Assignment assign = book.getAssignment(assignName);
if (assign == null) {
System.err.println("Not such assignment: " + assignName);
System.exit(1);
}
AssignmentPanel assignPanel = new AssignmentPanel(false);
assignPanel.displayAssignment(assign);
JFrame frame = new JFrame("AssignmentPanel test");
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(1);
}
});
frame.getContentPane().add(assignPanel);
frame.pack();
frame.setVisible(true);
}
}