/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package org.lee.echo360.tray; import java.awt.MenuItem; import java.awt.PopupMenu; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.TimeUnit; import javax.swing.Timer; import org.apache.commons.lang3.StringUtils; import org.lee.echo360.control.ControllerAction; import org.lee.echo360.control.ControllerListener; import org.lee.echo360.control.controllers.DownloadProgressListener; import org.lee.echo360.control.controllers.MainController; import org.lee.echo360.model.ActionResult; import org.lee.echo360.model.Blackboard; import org.lee.echo360.model.DownloadType; import org.lee.echo360.model.Lecture; import org.lee.echo360.model.Subject; import org.lee.echo360.ui.AboutDialog; /** * * @author lee */ public class PopupManager implements ControllerListener, DownloadProgressListener, ActionListener { //TODO Write /* * LAYOUT: * * | %Signed In: s42... % * | %Last Check: Just Now % * | %Downloading 1 of 3 % * | ----------------------- * | CSSE2002 > * -\ 2012-05-07 12:00 * | DECO2500 > * -\ 2012-05-06 08:00 * | MATH2000 > * -\ L1 > * -\ 2012-05-07 12:00 * -\ L2 > * -\ 2012-02-27 16:00 * | ----------------------- * | Preferences * | About * | Quit */ private final PopupMenu menu; private final MenuItem userStatus; private final MenuItem lastCheck; private final MenuItem currentProcess; private final Map<Subject, SubjectMenu> subjectMenus; private final List<Subject> downloadsInProgress; private final MenuItem noSubjects; private final MenuItem preferences; private final MenuItem about; private final MenuItem quit; private final MainController ctl; private long lastUpdateTime = Long.MAX_VALUE; private boolean processing = true; private ActionResult loginStatus = ActionResult.SUCCEDED; private AboutDialog aboutDialog = new AboutDialog() { @Override public String getProductName() { return "DLect Tray Icon"; } @Override public String getDescription() { return "The DLect Tray Icon is designed to provide you" + " with easy access to all your lectures and" + " will automatically download any new ones."; } }; public PopupManager(MainController ctl) { this.ctl = ctl; this.ctl.addControllerListener(this); this.ctl.addDownloadProgressListener(this); this.subjectMenus = new TreeMap<Subject, SubjectMenu>(); this.downloadsInProgress = new ArrayList<Subject>(4); this.menu = new PopupMenu(); userStatus = new MenuItem("Not Signed In"); userStatus.setEnabled(false); lastCheck = new MenuItem("Next Check: Now"); lastCheck.setEnabled(false); currentProcess = new MenuItem("Starting Up"); currentProcess.setEnabled(false); updateUserStatus(); noSubjects = new MenuItem("No Subjects Yet"); noSubjects.setEnabled(false); preferences = new MenuItem("Preferences"); preferences.addActionListener(this); about = new MenuItem("About DLect"); about.addActionListener(this); quit = new MenuItem("Quit"); quit.addActionListener(this); menu.add(userStatus); menu.add(lastCheck); menu.add(currentProcess); menu.addSeparator(); updateCourseMap(); // This adds the bottom part of the menu Timer t = new Timer(60 * 1000, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { long currTime = System.currentTimeMillis(); long millisPast = currTime - lastUpdateTime; if (!processing && millisPast > 0) { lastCheck.setLabel("Last Check: " + toNiceString(millisPast)); } else { lastCheck.setLabel("Last Check: Just Now"); } } }); t.start(); } public PopupMenu getPopup() { return menu; } @Override public void start(ControllerAction action) { updateLastUpdateTime(); processing = true; switch (action) { case LOGIN: lastCheck.setLabel("Just Now"); currentProcess.setLabel("Logging In..."); break; case COURSES: currentProcess.setLabel("Finding Courses..."); break; case LECTURES: currentProcess.setLabel("Finding Lectures..."); break; default: throw new AssertionError(); } } @Override public void finished(ControllerAction action, ActionResult r) { updateLastUpdateTime(); processing = false; switch (action) { case LOGIN: loginStatus = r; updateUserStatus(); break; case COURSES: updateCourses(r); currentProcess.setLabel("Finding Lectures..."); break; case LECTURES: currentProcess.setLabel("Download Starting"); break; default: throw new AssertionError(); } } @Override public void error(Throwable e) { } @Override public void downloadingStarted(Subject subject) { updateLastUpdateTime(); currentProcess.setLabel("Downloading"); downloadsInProgress.add(subject); } @Override public void downloadingFinished(Subject subject) { updateLastUpdateTime(); downloadsInProgress.remove(subject); if (downloadsInProgress.isEmpty()) { currentProcess.setLabel("Idle"); } } @Override public void downloadStarting(Subject s, Lecture l, DownloadType t) { updateLastUpdateTime(); } @Override public void downloadCompleted(Subject s, Lecture l, DownloadType t) { updateLastUpdateTime(); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource().equals(preferences)) { // TODO open Preferences } else if (e.getSource().equals(about)) { aboutDialog.setVisible(true); } else if (e.getSource().equals(quit)) { System.exit(0); // TODO change this to be more graceful. } } private void updateCourses(ActionResult r) { switch (r) { case SUCCEDED: updateCourseMap(); break; default: loginStatus = r; updateUserStatus(); } } private void updateCourseMap() { try { Set<Subject> s = ctl.getPropertiesController().getBlackboard().getSubjects(); for (Subject subject : s) { if (!subjectMenus.containsKey(subject)) { subjectMenus.put(subject, SubjectMenu.createMenuFor(subject, ctl)); } } while (menu.getItemCount() > 4) { menu.remove(4); } subjectMenus.keySet().retainAll(s); // Keep all the newer ones for (Map.Entry<Subject, SubjectMenu> entry : subjectMenus.entrySet()) { menu.add(entry.getValue().getMenu()); } addMenuBottom(); } catch (Throwable t) { t.printStackTrace(); } } private void addMenuBottom() { menu.addSeparator(); menu.add(preferences); menu.add(about); menu.add(quit); } private void updateUserStatus() { ctl.getPropertiesController().initBlackboard(); Blackboard b = ctl.getPropertiesController().getBlackboard(); if (b == null || b.getUsername().isEmpty() || b.getPassword().isEmpty()) { userStatus.setLabel("Not Signed In"); } switch (loginStatus) { case NOT_LOGGED_IN: userStatus.setLabel("Not Signed In"); break; case SUCCEDED: userStatus.setLabel("Signed In: " + b.getUsername()); break; case FATAL: case FAILED: case INVALID_CREDENTIALS: userStatus.setLabel("Bad Credentials"); break; case NOT_CONNECTED: userStatus.setLabel("No Connection"); default: throw new AssertionError(); } } private String toNiceString(long millisPast) { long mins = TimeUnit.MILLISECONDS.toMinutes(millisPast); long hrs = TimeUnit.MILLISECONDS.toHours(millisPast); StringBuilder b = new StringBuilder(); if (hrs > 0) { b.append(hrs).append(" Hour"); if (hrs > 1) { b.append('s'); } if (mins > 0) { b.append(", "); } } if (mins > 0) { b.append(mins).append(" Minute"); if (mins > 1) { b.append('s'); } } if (b.length() == 0) { b.append("1 Minute"); } b.append(" Ago"); return b.toString(); } public void updateLastUpdateTime() { lastUpdateTime = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(1); } }