/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.dlect.ui.panel;
import com.google.common.collect.BiMap;
import com.google.common.collect.EnumHashBiMap;
import com.google.common.collect.HashBiMap;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JSeparator;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import org.dlect.controller.MainController;
import org.dlect.controller.event.ControllerType;
import org.dlect.controller.helper.ControllerStateHelper;
import org.dlect.controller.helper.subject.SubjectInformation;
import org.dlect.controller.worker.ErrorDisplayable;
import org.dlect.controller.worker.LectureWorker;
import org.dlect.controller.worker.download.DownloadErrorDisplayable;
import org.dlect.controller.worker.download.DownloadWorkerHelper;
import org.dlect.event.util.EventIdListings;
import org.dlect.events.Event;
import org.dlect.events.EventListener;
import org.dlect.events.wrapper.Wrappers;
import org.dlect.exception.DLectExceptionCause;
import org.dlect.helper.SubjectHelper;
import org.dlect.model.Lecture;
import org.dlect.model.LectureDownload;
import org.dlect.model.Stream;
import org.dlect.model.Subject;
import org.dlect.model.formatter.DownloadType;
import org.dlect.ui.LeftRightCheck;
import org.dlect.ui.decorator.DownloadButtonDotter;
import org.dlect.ui.helper.ControllerErrorBoxHelper;
import org.dlect.ui.layout.TableConstraints;
import org.dlect.ui.layout.TableLayout;
import org.dlect.ui.subject.settings.AdvancedSubjectPreferencesDialog;
import static org.dlect.controller.helper.subject.SubjectDataHelper.DownloadState.ALL_DOWNLOADED;
import static org.dlect.controller.helper.subject.SubjectDataHelper.DownloadState.NONE_SELECTED;
/**
*
* @author lee
*/
public final class CourseDetailPanel extends javax.swing.JPanel implements EventListener, ErrorDisplayable, DownloadErrorDisplayable {
private static final long serialVersionUID = 1L;
private Subject subject;
private final BiMap<Stream, LeftRightCheck> lectureStreams = HashBiMap.create();
private final BiMap<DownloadType, JCheckBox> downloadTypeCheckBoxes = EnumHashBiMap.create(DownloadType.class);
private JButton downloadButton;
private JSeparator leftSeperator;
private JSeparator rightSeperator;
private JButton advancedButton;
private JCheckBox selectAllCheckbox;
private final MainController controller;
private final DownloadButtonDotter dbd;
private LectureWorker worker;
public CourseDetailPanel(MainController controller) {
this.controller = controller;
initComponents();
dbd = new DownloadButtonDotter(downloadButton);
Wrappers.addSwingListenerTo(this, this.controller.getControllerStateHelper(), ControllerStateHelper.class);
refresh();
}
public void setSubject(final Subject course) {
if (subject == course || course == null) {
return;
}
if (subject != null) {
Wrappers.removeSwingListenerFrom(this, subject);
}
subject = course;
Wrappers.addSwingListenerTo(this, subject, Subject.class, Lecture.class, LectureDownload.class, Stream.class);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
refresh();
}
});
}
private void initComponents() {
TableConstraints co;
leftSeperator = new JSeparator();
rightSeperator = new JSeparator();
downloadButton = new JButton();
advancedButton = new JButton();
selectAllCheckbox = new JCheckBox();
setLayout(new TableLayout());
leftSeperator.setOrientation(SwingConstants.VERTICAL);
leftSeperator.setMinimumSize(new Dimension(0, 5));
leftSeperator.setPreferredSize(new Dimension(10, 10));
co = TableConstraints.create(1);
add(leftSeperator, co);
selectAllCheckbox.setText("Select All");
co = TableConstraints.create(2, 0);
add(selectAllCheckbox, co);
selectAllCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
boolean b = selectAllCheckbox.isSelected();
SubjectHelper.setEnabled(subject, b);
}
});
rightSeperator.setOrientation(SwingConstants.VERTICAL);
rightSeperator.setMinimumSize(new Dimension(0, 5));
rightSeperator.setPreferredSize(new Dimension(10, 10));
co = TableConstraints.create(3);
add(rightSeperator, co);
downloadButton.setText("Download");
co = TableConstraints.create(5, 0);
downloadButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DownloadWorkerHelper.downloadAllSelectedIn(CourseDetailPanel.this, controller, subject);
}
});
add(downloadButton, co);
advancedButton.setText("Advanced...");
advancedButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new AdvancedSubjectPreferencesDialog(
SwingUtilities.windowForComponent(CourseDetailPanel.this),
subject,
controller
).setVisible(true);
}
});
co = TableConstraints.create(5, 1);
add(advancedButton, co);
}
@Override
public void processEvent(Event e) {
if (subject == null) {
return;
}
SubjectInformation i = controller.getSubjectDataHelper().getSubjectInformation(e);
if (EventIdListings.DOWNLOAD_UPDATE_EVENT_IDS.contains(e.getEventID())) {
updateDownloadButton(i);
}
if (EventIdListings.LECTURE_STREAM_UPDATE_EVENT_IDS.contains(e.getEventID())) {
updateLectureStreams(i);
}
if (EventIdListings.DOWNLOAD_TYPE_UPDATE_EVENT_IDS.contains(e.getEventID())) {
updateDownloadTypeChecks(i);
}
}
public void refresh() {
if (subject == null) {
return;
}
SubjectInformation i = new SubjectInformation();
i.setSubject(subject);
updateDownloadButton(i);
updateLectureStreams(i);
updateDownloadTypeChecks(i);
}
private void updateDownloadButton(SubjectInformation si) {
ControllerStateHelper csh = controller.getControllerStateHelper();
if (!csh.hasCompleted(ControllerType.LECTURE, subject)) {
dbd.updateAndStart("Loading Data");
} else if (csh.isDownloading(subject)) {
dbd.updateAndStart("Downloading");
} else if (subject.getLectures().isEmpty()) {
dbd.stop();
downloadButton.setText("None Detected");
downloadButton.setEnabled(false);
this.validate();
} else {
si.setSubject(subject);
switch (si.getDownloadedStatus()) {
case ALL_DOWNLOADED:
dbd.stop();
downloadButton.setText("All Downloaded");
downloadButton.setEnabled(false);
break;
case NONE_SELECTED:
dbd.stop();
downloadButton.setText("None Selected");
downloadButton.setEnabled(false);
break;
default:
dbd.stop();
downloadButton.setText("Download");
}
this.validate();
}
}
private void updateDownloadTypeChecks(SubjectInformation si) {
si.setSubject(subject);
if (downloadTypeCheckBoxes.isEmpty()) {
addDownloadTypeCheckBoxes(si);
} else {
for (Map.Entry<DownloadType, JCheckBox> entry : downloadTypeCheckBoxes.entrySet()) {
entry.getValue().setSelected(si.isDownloadTypeEnabled(entry.getKey()));
}
}
}
private void addDownloadTypeCheckBoxes(SubjectInformation si) {
int row = 1;
for (final DownloadType dt : DownloadType.values()) {
final JCheckBox c = new JCheckBox();
c.setSelected(si.isDownloadTypeEnabled(dt));
// TODO(Later) change case. \/
c.setText(dt.toString()); // TODO(Later) i18n
c.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SubjectHelper.setDownloadTypeEnabled(subject, dt, c.isSelected());
}
});
TableConstraints co = TableConstraints.create(0, row++);
add(c, co);
downloadTypeCheckBoxes.put(dt, c);
}
}
private void updateLectureStreams(SubjectInformation si) {
si.setSubject(subject);
Set<Stream> changedStreams = new HashSet<>(subject.getStreams());
changedStreams.removeAll(lectureStreams.keySet());
if (changedStreams.isEmpty()) {
for (Map.Entry<Stream, LeftRightCheck> entry : lectureStreams.entrySet()) {
Stream stream = entry.getKey();
LeftRightCheck leftRightCheck = entry.getValue();
updateExistingLectureStreams(stream, leftRightCheck, si);
}
} else {
cleanLectureStreams();
GridBagConstraints check = new GridBagConstraints();
check.gridx = 2;
check.fill = GridBagConstraints.HORIZONTAL;
check.anchor = GridBagConstraints.EAST;
int i = 1;
for (Stream stream : subject.getStreams()) {
LeftRightCheck lect = createCheckbox(stream, si);
lectureStreams.put(stream, lect);
check.gridy = i;
CourseDetailPanel.this.add(lect, check);
i++;
}
}
}
private LeftRightCheck createCheckbox(final Stream stream, SubjectInformation si) {
final LeftRightCheck check = new LeftRightCheck();
check.setRightForeground(whiten(check.getForeground(), 0.5));
check.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SubjectHelper.setStreamEnabled(subject, stream, check.isSelected());
}
});
updateExistingLectureStreams(stream, check, si);
return check;
}
private Color whiten(Color c, double percentage) {
float[] hsb = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null);
hsb[2] += percentage;
return Color.getHSBColor(hsb[0], hsb[1], hsb[2]);
}
private void cleanLectureStreams() {
Iterator<LeftRightCheck> ilrc = lectureStreams.values().iterator();
while (ilrc.hasNext()) {
this.remove(ilrc.next());
ilrc.remove();
}
}
private void updateExistingLectureStreams(final Stream stream, LeftRightCheck check, SubjectInformation si) {
int streamCount = si.getStreamLectureCount().count(stream);
String lectureCount = String.format("%d Lecture%s", streamCount, (streamCount == 1 ? "" : "s"));
check.setRightText(lectureCount);
check.setText(stream.getName());
check.setSelected(si.isStreamEnabled(stream));
}
public void loadLectures() {
if (worker == null) {
doLoadLecture();
}
}
public void doLoadLecture() {
worker = new LectureWorker(this, controller, subject);
worker.execute();
}
@Override
public void showErrorBox(ControllerType type, Object parameter, DLectExceptionCause get) {
// TODO(Later) Show retry/try again .
ControllerErrorBoxHelper.showErrorBox(this, type, parameter, get);
}
@Override
public void showDownloadError(Subject subject, Lecture lecture, DownloadType downloadType, DLectExceptionCause failureCause) {
ControllerErrorBoxHelper.showDownloadError(this, subject, lecture, downloadType, failureCause);
}
}