package unify.gui;
/*
* Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle or the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* TrayIconDemo.java
*/
import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import javax.swing.*;
import unify.ShowLibrary;
import unify.data.Episode;
import unify.data.Search;
import unify.data.Season;
import unify.data.Settings;
import unify.data.Show;
public class SysTrayIcon {
private static SysTrayIcon _instance = null;
final PopupMenu popup;
public final TrayIcon trayIcon;
final SystemTray tray;
private ShowLibrary showLib;
private Settings settings;
private final static Logger LOGGER = Logger.getLogger(SysTrayIcon.class.getName());
private SysTrayIcon() {
this.popup = new PopupMenu();
this.tray = SystemTray.getSystemTray();
this.showLib = ShowLibrary.getInstance();
this.settings = Settings.getInstance();
this.trayIcon = new TrayIcon(Settings.getInstance().getIconImage());
}
public static synchronized SysTrayIcon getInstance() {
if (_instance == null) {
_instance = new SysTrayIcon();
}
return _instance;
}
public void RunIcon() {
/* Use an appropriate Look and Feel */
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
// UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
} catch (UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
} catch (IllegalAccessException ex) {
ex.printStackTrace();
} catch (InstantiationException ex) {
ex.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
/* Turn off metal's use of bold fonts */
UIManager.put("swing.boldMetal", Boolean.FALSE);
// Schedule a job for the event-dispatching thread:
// adding TrayIcon.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
private void createAndShowGUI() {
// Check the SystemTray support
if (!SystemTray.isSupported()) {
LOGGER.severe("SystemTray is not supported");
System.exit(1);
return;
}
generatePopup();
try {
tray.add(trayIcon);
} catch (AWTException e) {
LOGGER.severe("TrayIcon could not be added.");
System.exit(1);
return;
}
trayIcon.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
GUI.main();
}
});
}
/**
* Generates the popup, first erasing all children.
*
*/
public void generatePopup() {
popup.removeAll();
final MenuItem aboutItem = new MenuItem("About");
final MenuItem checkFeedsItem = new MenuItem("Check Feeds Now");
final MenuItem exitItem = new MenuItem("Exit");
final Menu onToday = new Menu("On Today");
final Menu onTomorrow = new Menu("On Tomorrow");
final Menu allShows = new Menu("Available");
final Menu newShows = new Menu("New Shows");
createMenu(onToday, showLib.onToday);
createMenu(onTomorrow, showLib.onTomorrow);
createAllShowsMenu(allShows);
createNewShowsMenu(newShows);
aboutItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String aboutMe = "An internet TV unification program, runs off RSS feeds. Designed and coded by Eruza.";
String myDelay = "Delay currently set to: " + settings.getDelay() + " minutes.";
String myFNS = "Currently find new shows is ";
if(settings.isFindNewShows()) {
myFNS = myFNS + "on.";
}
else {
myFNS = myFNS + "off.";
}
LogManager manager = LogManager.getLogManager();
Enumeration<String> loggers = manager.getLoggerNames();
for (; loggers.hasMoreElements();) {
System.out.println((String) loggers.nextElement());
}
JOptionPane.showMessageDialog(null,
aboutMe + "\n" + myDelay + "\n" + myFNS);
}
});
checkFeedsItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
ShowLibrary.getInstance().checkFeedsNow();
}
});
exitItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
exit(0);
}
});
if(allShows.getItemCount()==0) {
MenuItem noShows = new MenuItem("No shows! Click to add more!");
noShows.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
GUI.main();
}
});
allShows.add(noShows);
}
if(onToday.getItemCount()==0) {
onToday.add("No shows on today!");
}
if(onTomorrow.getItemCount()==0) {
onTomorrow.add("No shows on tomorrow!");
}
popup.add(aboutItem);
popup.add(checkFeedsItem);
popup.addSeparator();
popup.add(onToday);
popup.add(onTomorrow);
popup.add(allShows);
if(newShows.getItemCount()>0) {
popup.add(newShows);
}
popup.addSeparator();
popup.add(exitItem);
trayIcon.setPopupMenu(popup);
}
private void createMenu(Menu menu, ArrayList<Show> shows) {
for(int i=0;i<shows.size();i++) {
Show show = shows.get(i);
Season season = show.getSeason();
for(Episode episode : season.getEpisodes()) {
final Menu showMenu = new Menu(show.getTitle() + " (" + season.getNumber() + "x" + episode.getNumber() + ")");
menu.add(showMenu);
final MenuItem linkItem = new MenuItem(episode.getLinkLabel());
final URI myURL = URI.create(episode.getLink());
linkItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
Desktop.getDesktop().browse(myURL);
} catch (IOException e1) {
LOGGER.warning("IO error " + e1.toString());
}
}
});
showMenu.add(linkItem);
addSearchItems(showMenu, season.formatSeasonEp(episode.getNumber()), show.getTitle());
}
}
}
private void createNewShowsMenu(Menu newShows) {
for(int i=0;i<ShowLibrary.getInstance().newShows.size();i++) {
final Show show = ShowLibrary.getInstance().newShows.get(i);
final String title = show.getTitle();
final Menu showMenu = new Menu(title);
newShows.add(showMenu);
final Season season = show.getSeason();
final Episode episode = season.getEpisode();
String linkLabel = episode.getLinkLabel();
String link = episode.getLink();
//Add menu items add, remove, and link
final MenuItem addItem = new MenuItem("Move to Shows");
final MenuItem removeItem = new MenuItem("Remove & Ignore");
final MenuItem linkItem = new MenuItem(linkLabel);
showMenu.add(addItem);
showMenu.add(removeItem);
showMenu.add(linkItem);
//Add menu item functionality
addItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Show newShow = ShowLibrary.getInstance().addShow(show);
Season season = newShow.addSeason(1);
Episode episode = show.findSeason(1).findEpisode(1);
season.addEpisode(1, episode.getLink(), episode.getLinkLabel());
ShowLibrary.getInstance().newShows.remove(show);
ShowLibrary.getInstance().doUpdates();
GUI.getInstance().refresh();
}
});
//Link menu item functionality
final URI myURL = URI.create(link);
linkItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
Desktop.getDesktop().browse(myURL);
} catch (IOException e1) {
LOGGER.warning("IO error " + e1.toString());
}
}
});
addSearchItems(showMenu, "s01e01", show.getTitle());
//Remove functionality
removeItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int result = JOptionPane.showConfirmDialog(null,"Are you sure you want to remove and ignore " + title, "Remove show " + title + "?", JOptionPane.YES_NO_OPTION);
if(result==0) {
showLib.removeNewShow(show);
generatePopup();
}
}
});
}
}
private void createAllShowsMenu(Menu allShows) {
for(int i=0;i<ShowLibrary.getInstance().shows.size();i++) {
final Show s1 = ShowLibrary.getInstance().shows.get(i);
int numSeasons = s1.seasons.size();
if(numSeasons>0) {
final String title = s1.getTitle();
final Menu showMenu = new Menu(title);
allShows.add(showMenu);
for(Season mySeason : s1.seasons) {
final int mySeasonNum = mySeason.getNumber();
int numEpisodes = mySeason.getEpisodes().size();
for(Episode myEpisode : mySeason.getEpisodes()) {
//Var setup
final int myEpisodeNum = myEpisode.getNumber();
final String myLink;
final String myLabel;
String formattedSeasonEp = mySeason.formatSeasonEp(myEpisodeNum);
myLink = myEpisode.getLink();
myLabel = myEpisode.getLinkLabel();
//Menu setup
MenuItem remove = new MenuItem("Remove");
MenuItem linkItem = new MenuItem(myLabel);
//Link menu item functionality
if(!myLink.equals(" ")) {
final URI myURL = URI.create(myLink);
linkItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
Desktop.getDesktop().browse(myURL);
} catch (IOException e1) {
LOGGER.warning("IO error " + e1.toString());
}
}
});
}
//Remove menu item functionality
final Season season = mySeason;
final Episode episode = myEpisode;
remove.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int result = JOptionPane.showConfirmDialog(null,"Are you sure you want to remove " + title + " season " + mySeasonNum + " episode " + myEpisodeNum, "Remove Episode?", JOptionPane.YES_NO_OPTION);
if(result==0) {
season.removeEpisode(episode);
LOGGER.fine("Removed episode " + episode.getNumber() + " from " + title);
if (season.getEpisodes().size()==0) {
Show show = ShowLibrary.getInstance().getShow(title);
show.removeSeason(season);
LOGGER.fine("Season " + season.getNumber() + " of " + title + " is removed because it was empty.");
}
showLib.doUpdates();
}
}
});
//Algorithm to show the least number of nested menus
Menu activeMenu = showMenu;
Menu episodeMenu;
if(numSeasons>1) {
Menu seasonMenu = new Menu("Season " + mySeasonNum);
episodeMenu = new Menu("Episode " + myEpisodeNum);
activeMenu.add(seasonMenu);
activeMenu = seasonMenu;
}
else {
episodeMenu = new Menu("Episode (" + mySeasonNum + "x" + myEpisodeNum + ")");
}
if(numEpisodes>1) {
activeMenu.add(episodeMenu);
activeMenu = episodeMenu;
}
activeMenu.add(remove);
if(!myLink.equals(" ")) {
activeMenu.add(linkItem);
}
addSearchItems(activeMenu, formattedSeasonEp, s1.getTitle());
if(numSeasons==1 && numEpisodes==1) {
showMenu.setLabel(title + " (" + mySeasonNum + "x" + myEpisodeNum + ")");
}
}
}
}
}
}
//Iterates through searchURLs and adds them to the menu
public void addSearchItems(Menu menu, String formattedSeasonEp, String title) {
for(Search search : Settings.getInstance().getSearches()) {
String label = search.getLabel();
String url = search.getLink().replaceAll("#showtitle#", title.replaceAll("\\s", "+") + "+" + formattedSeasonEp);
final URI uri = URI.create(url);
MenuItem searchItem = new MenuItem(label);
searchItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
Desktop.getDesktop().browse(uri);
} catch (IOException ex) {
LOGGER.warning("IO error " + ex.toString());
}
}
});
menu.add(searchItem);
}
}
public void showMessages(ArrayList<String> pending) {
final ArrayList<String> messages = new ArrayList<String>();
messages.addAll(pending);
Runnable showMessagesRunnable = new Runnable(){
public void run() {
for(int i=0;i<messages.size();i=i+5) {
String message = "";
for(int j=0;j<5 && j+i<messages.size();j++) {
message = message + messages.get(i+j) + "\n";
}
trayIcon.displayMessage("Unify Update", message, TrayIcon.MessageType.INFO);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
LOGGER.severe(e.toString());
System.exit(1);
}
}
}
};
Thread newThread = new Thread(showMessagesRunnable);
newThread.start();
}
public void exit(int i) {
tray.remove(trayIcon);
System.exit(i);
}
}