/* This file is part of JFLICKS. JFLICKS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. JFLICKS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with JFLICKS. If not, see <http://www.gnu.org/licenses/>. */ package org.jflicks.ui.view.fe.screen.schedule; import java.awt.AWTKeyStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Frame; import java.awt.KeyboardFocusManager; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.HashSet; import java.util.Set; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.AbstractAction; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JLayeredPane; import javax.swing.KeyStroke; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import org.jflicks.job.JobContainer; import org.jflicks.job.JobEvent; import org.jflicks.job.JobListener; import org.jflicks.job.JobManager; import org.jflicks.nms.NMS; import org.jflicks.nms.NMSConstants; import org.jflicks.nms.NMSUtil; import org.jflicks.photomanager.Tag; import org.jflicks.rc.RC; import org.jflicks.tv.Airing; import org.jflicks.tv.Channel; import org.jflicks.tv.RecordingRule; import org.jflicks.tv.Show; import org.jflicks.tv.ShowAiring; import org.jflicks.tv.Upcoming; import org.jflicks.ui.view.fe.AddRuleJob; import org.jflicks.ui.view.fe.AllGuideJob; import org.jflicks.ui.view.fe.ButtonPanel; import org.jflicks.ui.view.fe.Dialog; import org.jflicks.ui.view.fe.GridGuidePanel; import org.jflicks.ui.view.fe.NMSProperty; import org.jflicks.ui.view.fe.ParameterProperty; import org.jflicks.ui.view.fe.RecordingRuleListPanel; import org.jflicks.ui.view.fe.RecordingRulePanel; import org.jflicks.ui.view.fe.RecordingRuleProperty; import org.jflicks.ui.view.fe.ShowDetailPanel; import org.jflicks.ui.view.fe.TagListPanel; import org.jflicks.ui.view.fe.UpcomingListPanel; import org.jflicks.ui.view.fe.UpcomingDetailPanel; import org.jflicks.ui.view.fe.UpcomingProperty; import org.jflicks.ui.view.fe.screen.Screen; import org.jflicks.ui.view.fe.screen.ScreenEvent; import org.jflicks.util.Busy; import org.jflicks.util.Util; import org.jdesktop.swingx.JXLabel; import org.jdesktop.swingx.JXPanel; import org.jdesktop.swingx.painter.MattePainter; /** * A screen to schedule recordings by title, using a guide or just to edit * rules. * * @author Doug Barnum * @version 1.0 */ public class ScheduleScreen extends Screen implements ParameterProperty, NMSProperty, UpcomingProperty, PropertyChangeListener, JobListener, ActionListener, RecordingRuleProperty { private static final String CANCEL = "Cancel"; private static final String BY_TITLE = "By Title"; private static final String BY_GUIDE = "Using Guide"; private static final String UPCOMING_RECORDINGS = "Upcoming Recordings"; private static final int ALL_UPCOMING = 1; private static final int RECORDING_UPCOMING = 2; private static final int NOT_RECORDING_UPCOMING = 3; private static final String ALL_UPCOMING_TEXT = "Showing All"; private static final String RECORDING_UPCOMING_TEXT = "Showing Recording"; private static final String NOT_RECORDING_UPCOMING_TEXT = "Showing Not Recording"; private static final int ALL_CHANNELS = 1; private static final int FAVORITE_CHANNELS = 2; private static final String ALL_CHANNELS_TEXT = "All Channels"; private static final String FAVORITE_CHANNELS_TEXT = "Favorite Channels"; private static final String ADD_FAVORITE = "Add to Favorites"; private static final String SWITCH_TO_FAVORITE = "Switch to Favorites"; private static final String REMOVE_FAVORITE = "Remove from Favorites"; private static final String SWITCH_FROM_FAVORITE = "Switch from Favorites"; private NMS[] nms; private String[] parameters; private String selectedParameter; private boolean updatedParameter; private Upcoming[] upcomings; private RecordingRule[] recordingRules; private HashMap<Channel, ShowAiring[]> guideMap; private JobContainer allGuideJobContainer; private long lastGuide; private HashMap<Tag, TagValue> tagMap; private Channel[] allChannels; private ArrayList<String> favoriteChannelList; private JXPanel waitPanel; private TagListPanel titleTagListPanel; private ShowDetailPanel showDetailPanel; private RecordingRulePanel recordingRulePanel; private GridGuidePanel gridGuidePanel; private RecordingRuleListPanel recordingRuleListPanel; private ShowAiring selectedShowAiring; private RecordingRule selectedRecordingRule; private UpcomingListPanel upcomingListPanel; private UpcomingDetailPanel upcomingDetailPanel; private JXLabel upcomingLabel; private int upcomingState; private JXLabel channelLabel; private int channelState; private ButtonPanel userButtonPanel; private boolean popupEnabled; /** * Simple empty constructor. */ public ScheduleScreen() { setTitle("Schedule"); BufferedImage bi = getImageByName("Schedule"); setDefaultBackgroundImage(bi); setFavoriteChannelList(new ArrayList<String>()); setFocusable(true); requestFocus(); setUpcomingState(ALL_UPCOMING); setUpcomingLabel(new JXLabel(ALL_UPCOMING_TEXT)); setChannelState(ALL_CHANNELS); setChannelLabel(new JXLabel(ALL_CHANNELS_TEXT)); InputMap map = getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); LeftAction leftAction = new LeftAction(); map.put(KeyStroke.getKeyStroke("LEFT"), "left"); getActionMap().put("left", leftAction); RightAction rightAction = new RightAction(); map.put(KeyStroke.getKeyStroke("RIGHT"), "right"); getActionMap().put("right", rightAction); UpAction upAction = new UpAction(); map.put(KeyStroke.getKeyStroke("UP"), "up"); getActionMap().put("up", upAction); DownAction downAction = new DownAction(); map.put(KeyStroke.getKeyStroke("DOWN"), "down"); getActionMap().put("down", downAction); PageUpAction pageUpAction = new PageUpAction(); map.put(KeyStroke.getKeyStroke("PAGE_UP"), "pageup"); getActionMap().put("pageup", pageUpAction); PageDownAction pageDownAction = new PageDownAction(); map.put(KeyStroke.getKeyStroke("PAGE_DOWN"), "pagedown"); getActionMap().put("pagedown", pageDownAction); EnterAction enterAction = new EnterAction(); map.put(KeyStroke.getKeyStroke("ENTER"), "enter"); getActionMap().put("enter", enterAction); InfoAction infoAction = new InfoAction(); map.put(KeyStroke.getKeyStroke("I"), "info"); getActionMap().put("info", infoAction); String[] array = { BY_TITLE, BY_GUIDE, UPCOMING_RECORDINGS }; setParameters(array); setTagMap(new HashMap<Tag, TagValue>()); RecordingRulePanel rrp = new RecordingRulePanel(); HashSet<AWTKeyStroke> set = new HashSet<AWTKeyStroke>(rrp.getFocusTraversalKeys( KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS)); set.clear(); set.add(KeyStroke.getKeyStroke("DOWN")); rrp.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, set); set = new HashSet<AWTKeyStroke>(rrp.getFocusTraversalKeys( KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS)); set.clear(); set.add(KeyStroke.getKeyStroke("UP")); rrp.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, set); setRecordingRulePanel(rrp); } /** * {@inheritDoc} */ public NMS[] getNMS() { NMS[] result = null; if (nms != null) { result = Arrays.copyOf(nms, nms.length); } return (result); } /** * {@inheritDoc} */ public void setNMS(NMS[] array) { if (array != null) { nms = Arrays.copyOf(array, array.length); } else { nms = null; } } /** * {@inheritDoc} */ public String[] getParameters() { String[] result = null; if (parameters != null) { result = Arrays.copyOf(parameters, parameters.length); } return (result); } private void setParameters(String[] array) { if (array != null) { parameters = Arrays.copyOf(array, array.length); } else { parameters = null; } } /** * {@inheritDoc} */ public String getSelectedParameter() { return (selectedParameter); } /** * {@inheritDoc} */ public void setSelectedParameter(String s) { if ((s != null) && (selectedParameter != null)) { setUpdatedParameter(!s.equals(selectedParameter)); } else { setUpdatedParameter(true); } selectedParameter = s; } private boolean isUpdatedParameter() { return (updatedParameter); } private void setUpdatedParameter(boolean b) { updatedParameter = b; } /** * {@inheritDoc} */ public Upcoming[] getUpcomings() { Upcoming[] result = null; if (upcomings != null) { result = Arrays.copyOf(upcomings, upcomings.length); } return (result); } /** * {@inheritDoc} */ public void setUpcomings(Upcoming[] array) { if (array != null) { upcomings = Arrays.copyOf(array, array.length); } else { upcomings = null; } applyUpcoming(); } private ArrayList<String> getFavoriteChannelList() { return (favoriteChannelList); } private void setFavoriteChannelList(ArrayList<String> l) { favoriteChannelList = l; } private Channel[] getAllChannels() { return (allChannels); } private void setAllChannels(Channel[] array) { allChannels = array; } private int getUpcomingState() { return (upcomingState); } private void setUpcomingState(int i) { upcomingState = i; } private int getChannelState() { return (channelState); } private void setChannelState(int i) { channelState = i; } private Upcoming[] filterByRule(Upcoming[] array) { Upcoming[] result = null; RecordingRule rr = getSelectedRecordingRule(); if ((array != null) && (rr != null)) { String name = rr.getName(); if (name.equals("All")) { result = array; } else { String seriesId = rr.getSeriesId(); if (seriesId != null) { // The user has selected a particular rule. ArrayList<Upcoming> l = new ArrayList<Upcoming>(); for (int i = 0; i < array.length; i++) { if (seriesId.equals(array[i].getSeriesId())) { l.add(array[i]); } } if (l.size() > 0) { result = l.toArray(new Upcoming[l.size()]); } } } } return (result); } private void applyUpcoming() { Upcoming[] array = getUpcomings(); UpcomingListPanel ulp = getUpcomingListPanel(); if ((array != null) && (ulp != null)) { array = filterByRule(array); ArrayList<Upcoming> list = new ArrayList<Upcoming>(); int state = getUpcomingState(); switch (state) { case ALL_UPCOMING: default: ulp.setUpcomings(array); if (array == null) { UpcomingDetailPanel dp = getUpcomingDetailPanel(); if (dp != null) { dp.setUpcoming(null); } } break; case RECORDING_UPCOMING: if (array != null) { for (int i = 0; i < array.length; i++) { if (NMSConstants.READY.equals(array[i].getStatus())) { list.add(array[i]); } } } if (list.size() > 0) { array = list.toArray(new Upcoming[list.size()]); ulp.setUpcomings(array); } else { ulp.setUpcomings(null); UpcomingDetailPanel dp = getUpcomingDetailPanel(); if (dp != null) { dp.setUpcoming(null); } } break; case NOT_RECORDING_UPCOMING: if (array != null) { for (int i = 0; i < array.length; i++) { if (!NMSConstants.READY.equals(array[i].getStatus())) { list.add(array[i]); } } } if (list.size() > 0) { array = list.toArray(new Upcoming[list.size()]); ulp.setUpcomings(array); } else { ulp.setUpcomings(null); UpcomingDetailPanel dp = getUpcomingDetailPanel(); if (dp != null) { dp.setUpcoming(null); } } break; } ulp.setSelectedIndex(0); } } private Channel[] filterByFavorite(Channel[] array) { Channel[] result = null; ArrayList<String> favlist = getFavoriteChannelList(); if ((array != null) && (favlist != null)) { ArrayList<Channel> filter = new ArrayList<Channel>(); for (int i = 0; i < favlist.size(); i++) { String tmp = favlist.get(i); if (tmp != null) { for (int j = 0; j < array.length; j++) { if (tmp.equals(array[j].toString())) { filter.add(array[j]); break; } } } } if (filter.size() > 0) { Collections.sort(filter); result = filter.toArray(new Channel[filter.size()]); } } return (result); } private void applyChannels() { GridGuidePanel ggp = getGridGuidePanel(); Channel[] carray = getAllChannels(); JXLabel l = getChannelLabel(); if ((ggp != null) && (carray != null) && (l != null)) { if (getChannelState() == ALL_CHANNELS) { ggp.setChannels(carray); l.setText(ALL_CHANNELS_TEXT); } else if (getChannelState() == FAVORITE_CHANNELS) { Channel[] only = filterByFavorite(carray); if (only != null) { ggp.setChannels(only); l.setText(FAVORITE_CHANNELS_TEXT); } else { setChannelState(ALL_CHANNELS); } } } } /** * {@inheritDoc} */ public RecordingRule[] getRecordingRules() { RecordingRule[] result = null; if (recordingRules != null) { result = Arrays.copyOf(recordingRules, recordingRules.length); } return (result); } /** * {@inheritDoc} */ public void setRecordingRules(RecordingRule[] array) { if (array != null) { recordingRules = Arrays.copyOf(array, array.length); } else { recordingRules = null; } } private boolean isParameterByTitle() { return (BY_TITLE.equals(getSelectedParameter())); } private boolean isParameterByGuide() { return (BY_GUIDE.equals(getSelectedParameter())); } private boolean isParameterUpcomingRecordings() { return (UPCOMING_RECORDINGS.equals(getSelectedParameter())); } private TagListPanel getTitleTagListPanel() { return (titleTagListPanel); } private void setTitleTagListPanel(TagListPanel p) { titleTagListPanel = p; } private GridGuidePanel getGridGuidePanel() { return (gridGuidePanel); } private void setGridGuidePanel(GridGuidePanel p) { gridGuidePanel = p; } private RecordingRuleListPanel getRecordingRuleListPanel() { return (recordingRuleListPanel); } private void setRecordingRuleListPanel(RecordingRuleListPanel p) { recordingRuleListPanel = p; } private ShowDetailPanel getShowDetailPanel() { return (showDetailPanel); } private void setShowDetailPanel(ShowDetailPanel p) { showDetailPanel = p; } private JXPanel getWaitPanel() { return (waitPanel); } private void setWaitPanel(JXPanel p) { waitPanel = p; } private RecordingRulePanel getRecordingRulePanel() { return (recordingRulePanel); } private void setRecordingRulePanel(RecordingRulePanel p) { recordingRulePanel = p; } private UpcomingListPanel getUpcomingListPanel() { return (upcomingListPanel); } private void setUpcomingListPanel(UpcomingListPanel p) { upcomingListPanel = p; } private JXLabel getUpcomingLabel() { return (upcomingLabel); } private void setUpcomingLabel(JXLabel l) { upcomingLabel = l; } private JXLabel getChannelLabel() { return (channelLabel); } private void setChannelLabel(JXLabel l) { channelLabel = l; } private UpcomingDetailPanel getUpcomingDetailPanel() { return (upcomingDetailPanel); } private void setUpcomingDetailPanel(UpcomingDetailPanel p) { upcomingDetailPanel = p; } private ButtonPanel getUserButtonPanel() { return (userButtonPanel); } private void setUserButtonPanel(ButtonPanel p) { userButtonPanel = p; } private JobContainer getAllGuideJobContainer() { return (allGuideJobContainer); } private void setAllGuideJobContainer(JobContainer c) { allGuideJobContainer = c; } private long getLastGuide() { return (lastGuide); } private void setLastGuide(long l) { lastGuide = l; } private ShowAiring getSelectedShowAiring() { return (selectedShowAiring); } private void setSelectedShowAiring(ShowAiring sa) { selectedShowAiring = sa; } private RecordingRule getSelectedRecordingRule() { return (selectedRecordingRule); } private void setSelectedRecordingRule(RecordingRule rr) { selectedRecordingRule = rr; } private boolean isWithinAnHalfHour() { boolean result = false; long l = getLastGuide() + 30 * 60 * 1000; if (System.currentTimeMillis() < l) { result = true; } return (result); } private HashMap<Channel, ShowAiring[]> getGuideMap() { return (guideMap); } private void setGuideMap(HashMap<Channel, ShowAiring[]> m) { guideMap = m; setLastGuide(System.currentTimeMillis()); GridGuidePanel ggp = getGridGuidePanel(); if (ggp != null) { ggp.setGuideMap(guideMap); } } private HashMap<Tag, TagValue> getTagMap() { return (tagMap); } private void setTagMap(HashMap<Tag, TagValue> m) { tagMap = m; } private void clearTagMap() { HashMap<Tag, TagValue> m = getTagMap(); if (m != null) { m.clear(); } } private void add(Tag t, Channel c, ShowAiring sa) { add(t, new TagValue(c, sa)); } private void add(Tag t, TagValue tv) { HashMap<Tag, TagValue> m = getTagMap(); if ((m != null) && (t != null) && (tv != null)) { m.put(t, tv); } } private TagValue getTagValueByTag(Tag t) { TagValue result = null; HashMap<Tag, TagValue> m = getTagMap(); if ((m != null) && (t != null)) { result = m.get(t); } return (result); } private boolean isPopupEnabled() { return (popupEnabled); } protected void setPopupEnabled(boolean b) { popupEnabled = b; } protected void popup(String[] choices) { JLayeredPane pane = getLayeredPane(); if ((pane != null) && (choices != null)) { Dimension d = pane.getSize(); int width = (int) d.getWidth(); int height = (int) d.getHeight(); ButtonPanel bp = new ButtonPanel(); bp.setMediumFont(bp.getLargeFont()); bp.setSmallFont(bp.getLargeFont()); bp.addActionListener(this); bp.setButtons(choices); setUserButtonPanel(bp); d = bp.getPreferredSize(); int bpwidth = (int) d.getWidth(); int bpheight = (int) d.getHeight(); int bpx = (int) ((width - bpwidth) / 2); int bpy = (int) ((height - bpheight) / 2); bp.setBounds(bpx, bpy, bpwidth, bpheight); setPopupEnabled(true); pane.add(bp, Integer.valueOf(300)); bp.requestFocus(); bp.setControl(true); bp.setButtons(choices); } } protected void unpopup() { setPopupEnabled(false); JLayeredPane pane = getLayeredPane(); ButtonPanel bp = getUserButtonPanel(); if ((pane != null) && (bp != null)) { bp.removeActionListener(this); setUserButtonPanel(null); pane.remove(bp); pane.repaint(); } } /** * {@inheritDoc} */ public void save() { ArrayList<String> favlist = getFavoriteChannelList(); if (favlist != null) { StringBuilder sb = new StringBuilder(""); for (int i = 0; i < favlist.size(); i++) { sb.append(favlist.get(i)); sb.append("\n"); } try { File here = new File ("."); Util.writeTextFile(new File(here, "fav-chan.txt"), sb.toString()); } catch (IOException ex) { } } } /** * {@inheritDoc} */ public void commandReceived(String command) { } /** * Override so we can start up the player. * * @param b When true we are ready to start the player. */ public void setVisible(boolean b) { super.setVisible(b); if (b) { // We are being shown so let's read the local channel favorite // text file in case it's been changed since last time we were // here. Each entry is a line that came from a Channel.toString() // call. Since we can dynamically change them here we will read // them into an ArrayList<String>. When this screen ends we // will need to write out the current state in case other screens // need the same info. ArrayList<String> favlist = getFavoriteChannelList(); if (favlist != null) { favlist.clear(); File here = new File ("."); String[] cnames = Util.readTextFile(new File(here, "fav-chan.txt")); if ((cnames != null) && (cnames.length > 0)) { for (int i = 0; i < cnames.length; i++) { favlist.add(cnames[i]); } Collections.sort(favlist); } } if ((isParameterByTitle()) || (isParameterByGuide())) { if (!isWithinAnHalfHour()) { AllGuideJob gjob = new AllGuideJob(getNMS()); gjob.addJobListener(this); JobContainer jc = JobManager.getJobContainer(gjob); setAllGuideJobContainer(jc); jc.start(); updateLayout(true); } else { applyChannels(); updateLayout(false); } } else if (isParameterUpcomingRecordings()) { NMS[] array = getNMS(); RecordingRuleListPanel rrlp = getRecordingRuleListPanel(); if ((array != null) && (array.length > 0) && (rrlp != null)) { RecordingRule[] rules = null; ArrayList<RecordingRule> rlist = new ArrayList<RecordingRule>(); for (int i = 0; i < array.length; i++) { rules = array[i].getRecordingRules(); if (rules != null) { for (int j = 0; j < rules.length; j++) { rlist.add(rules[j]); } } } if (rlist.size() > 0) { Collections.sort(rlist, new RecordingRuleSortByName()); RecordingRule all = new RecordingRule(); all.setName("All"); rlist.add(0, all); rules = rlist.toArray(new RecordingRule[rlist.size()]); int sindex = rrlp.getStartIndex(); int selindex = rrlp.getSelectedIndex(); rrlp.setRecordingRules(rules); rrlp.setStartIndex(sindex); rrlp.setSelectedIndex(selindex); } updateLayout(false); } } else if (isParameterUpcomingRecordings()) { updateLayout(false); } } } /** * {@inheritDoc} */ public void performLayout(Dimension d) { JLayeredPane pane = getLayeredPane(); if ((d != null) && (pane != null)) { float alpha = (float) getPanelAlpha(); int width = (int) d.getWidth(); int height = (int) d.getHeight(); int wspan = (int) (width * 0.03); int listwidth = (width - (2 * wspan)); int halflistwidth = (width - (3 * wspan)) / 2; int onethirdlistwidth = (width - (3 * wspan)) / 3; int twothirdlistwidth = onethirdlistwidth * 2; int hspan = (int) (height * 0.03); int listheight = (int) ((height - (2 * hspan)) / 1.5); int detailwidth = listwidth; int detailheight = (height - (3 * hspan)) - listheight; JXPanel panel = new JXPanel(new BorderLayout()); JXLabel l = new JXLabel("Getting TV data, please wait..."); l.setHorizontalTextPosition(SwingConstants.CENTER); l.setHorizontalAlignment(SwingConstants.CENTER); l.setFont(getLargeFont()); panel.add(l, BorderLayout.CENTER); MattePainter p = new MattePainter(Color.BLACK); panel.setBackgroundPainter(p); panel.setBounds(0, 0, (int) d.getWidth(), (int) d.getHeight()); setWaitPanel(panel); TagListPanel tlp = new TagListPanel(); tlp.setControl(true); tlp.addPropertyChangeListener("SelectedTag", this); tlp.setBounds(wspan, hspan, listwidth, listheight); setTitleTagListPanel(tlp); RecordingRuleListPanel rrlp = new RecordingRuleListPanel(); rrlp.setControl(true); rrlp.addPropertyChangeListener("SelectedRecordingRule", this); setRecordingRuleListPanel(rrlp); ShowDetailPanel sdp = new ShowDetailPanel(); sdp.setBounds(wspan, hspan + listheight + hspan, detailwidth, detailheight); setShowDetailPanel(sdp); UpcomingListPanel ulp = new UpcomingListPanel(); ulp.setControl(false); ulp.setAlpha(alpha); ulp.addPropertyChangeListener("SelectedUpcoming", this); setUpcomingListPanel(ulp); UpcomingDetailPanel dp = new UpcomingDetailPanel(); dp.setAlpha(alpha); setUpcomingDetailPanel(dp); GridGuidePanel ggp = new GridGuidePanel(); ggp.setAlpha(alpha); ggp.addPropertyChangeListener("SelectedShowAiring", this); setGridGuidePanel(ggp); JXLabel label = getChannelLabel(); label.setFont(ggp.getLargeFont()); label.setForeground(ggp.getInfoColor()); label.setHorizontalTextPosition(SwingConstants.CENTER); label.setHorizontalAlignment(SwingConstants.RIGHT); Dimension ldim = label.getPreferredSize(); int labelHeight = (int) ldim.getHeight(); label.setBounds(wspan, hspan, listwidth, labelHeight); ggp.setBounds(wspan, hspan + labelHeight, listwidth, listheight - labelHeight); label = getUpcomingLabel(); label.setFont(ulp.getLargeFont()); label.setForeground(ulp.getInfoColor()); label.setHorizontalTextPosition(SwingConstants.CENTER); label.setHorizontalAlignment(SwingConstants.RIGHT); ldim = label.getPreferredSize(); labelHeight = (int) ldim.getHeight(); label.setBounds(wspan, hspan, listwidth, labelHeight); rrlp.setBounds(wspan, hspan + labelHeight, halflistwidth, listheight - labelHeight); ulp.setBounds(wspan + wspan + halflistwidth, hspan + labelHeight, halflistwidth, listheight - labelHeight); dp.setBounds(wspan, hspan + hspan + listheight, detailwidth, detailheight); setDefaultBackgroundImage( Util.resize(getDefaultBackgroundImage(), width, height)); } } private void updateLayout(boolean wait) { JLayeredPane pane = getLayeredPane(); if (pane != null) { pane.removeAll(); if (wait) { pane.add(getWaitPanel(), Integer.valueOf(100)); } else { if (isParameterByTitle()) { pane.add(getTitleTagListPanel(), Integer.valueOf(100)); pane.add(getShowDetailPanel(), Integer.valueOf(100)); } else if (isParameterByGuide()) { pane.add(getChannelLabel(), Integer.valueOf(110)); pane.add(getGridGuidePanel(), Integer.valueOf(100)); pane.add(getShowDetailPanel(), Integer.valueOf(100)); } else if (isParameterUpcomingRecordings()) { pane.add(getRecordingRuleListPanel(), Integer.valueOf(100)); pane.add(getUpcomingListPanel(), Integer.valueOf(100)); pane.add(getUpcomingLabel(), Integer.valueOf(110)); pane.add(getUpcomingDetailPanel(), Integer.valueOf(100)); } } repaint(); } } private boolean isPaidProgramming(Show s) { boolean result = false; if (s != null) { String type = s.getType(); if ((type != null) && (type.equalsIgnoreCase("Paid Programming"))) { result = true; } } return (result); } private void add(Tag root, Channel c, ShowAiring[] array) { if ((root != null) && (c != null) && (array != null)) { String chantext = c.toString(); for (int i = 0; i < array.length; i++) { Show show = array[i].getShow(); if ((show != null) && (!isPaidProgramming(show))) { //String title = show.getTitle(); String title = Util.toSortableTitle(show.getTitle(), true); if (title != null) { String letter = title.substring(0, 1); letter = letter.toUpperCase(); Tag letterTag = null; if (root.hasChildByName(letter)) { letterTag = root.getChildByName(letter); } else { letterTag = new Tag(); letterTag.setName(letter); root.addChild(letterTag); } if (letterTag != null) { Tag titleTag = null; if (letterTag.hasChildByName(title)) { titleTag = letterTag.getChildByName(title); } else { titleTag = new Tag(); titleTag.setName(title); letterTag.addChild(titleTag); } if (titleTag != null) { Tag channelTag = null; if (titleTag.hasChildByName(chantext)) { channelTag = titleTag.getChildByName(chantext); } else { channelTag = new Tag(); channelTag.setName(chantext); titleTag.addChild(channelTag); } if (channelTag != null) { Tag when = new Tag(); when.setName(array[i].toString()); channelTag.addChild(when); add(when, c, array[i]); } } } } } } } } private Upcoming[] getUpcomings(RecordingRule rr) { Upcoming[] result = null; if (rr != null) { String seriesId = rr.getSeriesId(); int channelId = rr.getChannelId(); String lid = rr.getListingId(); NMS n = NMSUtil.select(getNMS(), rr.getHostPort()); if ((seriesId != null) && (n != null) && (lid != null)) { Channel c = n.getChannelById(channelId, lid); Upcoming[] all = n.getUpcomings(); if ((all != null) && (c != null)) { String cn = c.getName(); if (cn != null) { ArrayList<Upcoming> ul = new ArrayList<Upcoming>(); for (int i = 0; i < all.length; i++) { if ((seriesId.equals(all[i].getSeriesId())) && (cn.equals(all[i].getChannelName()))) { ul.add(all[i]); } } if (ul.size() > 0) { result = ul.toArray(new Upcoming[ul.size()]); } } } } } return (result); } private RecordingRule getRecordingRule(ShowAiring sa) { RecordingRule result = null; if (sa != null) { NMS n = NMSUtil.select(getNMS(), sa.getHostPort()); Show show = sa.getShow(); Airing airing = sa.getAiring(); if ((n != null) && (show != null) && (airing != null)) { int cid = airing.getChannelId(); String seriesId = show.getSeriesId(); RecordingRule[] rules = n.getRecordingRules(); if ((seriesId != null) && (rules != null)) { for (int i = 0; i < rules.length; i++) { ShowAiring rrsa = rules[i].getShowAiring(); if (rrsa != null) { // We have a rule that is a ONCE recording. It // is only our rule to edit if the two ShowAiring // instances are the same. if (rrsa.equals(sa)) { result = rules[i]; break; } } else { if ((cid == rules[i].getChannelId()) && (seriesId.equals(rules[i].getSeriesId()))) { result = rules[i]; break; } } } } } } return (result); } /** * {@inheritDoc} */ @SuppressWarnings("unchecked") public void jobUpdate(JobEvent event) { if (event.getType() == JobEvent.COMPLETE) { Serializable s = event.getState(); if (s instanceof HashMap<?, ?>) { HashMap<Channel, ShowAiring[]> map = (HashMap<Channel, ShowAiring[]>) s; setGuideMap(map); setAllGuideJobContainer(null); TagListPanel tlp = getTitleTagListPanel(); if (tlp != null) { clearTagMap(); Tag root = new Tag(); root.setName("Root"); Set<Map.Entry<Channel, ShowAiring[]>> set = map.entrySet(); Iterator<Map.Entry<Channel, ShowAiring[]>> iter = set.iterator(); while (iter.hasNext()) { Map.Entry<Channel, ShowAiring[]> entry = iter.next(); Channel key = entry.getKey(); ShowAiring[] array = entry.getValue(); add(root, key, array); } tlp.setRootTag(root); } Set<Channel> set = map.keySet(); if (set.size() > 0) { Channel[] chans = set.toArray(new Channel[set.size()]); Arrays.sort(chans); setAllChannels(chans); applyChannels(); } updateLayout(false); requestFocus(); } } } private void updateRecordingStatus() { ShowDetailPanel sdp = getShowDetailPanel(); if (sdp != null) { ShowAiring sa = getSelectedShowAiring(); if (sa != null) { String sadatestr = ""; Airing airing = sa.getAiring(); if (airing != null) { Date d = airing.getAirDate(); if (d != null) { sadatestr = d.toString(); } } RecordingRule rr = getRecordingRule(sa); if (rr != null) { Upcoming[] ups = getUpcomings(rr); if (ups != null) { boolean found = false; int doing = 0; for (int i = 0; i < ups.length; i++) { if (NMSConstants.READY.equals(ups[i].getStatus())) { doing++; if (!found) { found = sadatestr.equals(ups[i].getStart()); } } } String extra = ""; if (doing > 0) { if (found) { extra = " including this one"; } else { extra = " but not this one"; } } sdp.setRecordingStatus("Recording " + doing + " of " + ups.length + extra); } else { sdp.setRecordingStatus("Recording 0 of 0"); } } else { sdp.setRecordingStatus("Not Recording"); } } else { sdp.setRecordingStatus(null); } } } private Frame getFrame() { return (Util.findFrame(this)); } /** * We need to listen for events from the "upcoming override dialog". * * @param event A given event. */ public void actionPerformed(ActionEvent event) { if (event.getSource() == getUserButtonPanel()) { ButtonPanel bp = getUserButtonPanel(); if (isParameterByGuide()) { if ((ADD_FAVORITE.equals(bp.getSelectedButton())) || (REMOVE_FAVORITE.equals(bp.getSelectedButton()))) { GridGuidePanel ggp = getGridGuidePanel(); ArrayList<String> favlist = getFavoriteChannelList(); if ((ggp != null) && (favlist != null)) { Channel chan = ggp.getSelectedChannel(); if (chan != null) { String text = chan.toString(); if (getChannelState() == ALL_CHANNELS) { if (!favlist.contains(text)) { favlist.add(text); Collections.sort(favlist); } } else if (getChannelState() == FAVORITE_CHANNELS) { if (favlist.contains(text)) { favlist.remove(text); Collections.sort(favlist); applyChannels(); } } } } } else if (SWITCH_TO_FAVORITE.equals(bp.getSelectedButton())) { setChannelState(FAVORITE_CHANNELS); applyChannels(); } else if (SWITCH_FROM_FAVORITE.equals( bp.getSelectedButton())) { setChannelState(ALL_CHANNELS); applyChannels(); } } else { UpcomingListPanel ulp = getUpcomingListPanel(); if (ulp != null) { if (!CANCEL.equals(bp.getSelectedButton())) { Upcoming up = ulp.getSelectedUpcoming(); if (up != null) { NMS n = NMSUtil.select(getNMS(), up.getHostPort()); if (n != null) { OverrideUpcomingJob ouj = new OverrideUpcomingJob(n, up); Busy busy = new Busy(getLayeredPane(), ouj); busy.addJobListener(this); busy.execute(); } } } } } unpopup(); } } private void handleFavorite() { GridGuidePanel ggp = getGridGuidePanel(); if ((ggp != null) && (!isPopupEnabled())) { Channel chan = ggp.getSelectedChannel(); if (chan != null) { ArrayList<String> blist = new ArrayList<String>(); if (getChannelState() == ALL_CHANNELS) { blist.add(SWITCH_TO_FAVORITE); blist.add(ADD_FAVORITE); } else { blist.add(SWITCH_FROM_FAVORITE); blist.add(REMOVE_FAVORITE); } blist.add(CANCEL); popup(blist.toArray(new String[blist.size()])); } } } /** * We listen for property change events from the panels that deal * with selecting a show to schedule. * * @param event A given PropertyChangeEvent instance. */ public void propertyChange(PropertyChangeEvent event) { if (event.getPropertyName().equals("SelectedTag")) { ShowDetailPanel sdp = getShowDetailPanel(); if (sdp != null) { TagValue tv = getTagValueByTag((Tag) event.getNewValue()); if (tv != null) { Channel c = tv.getChannel(); ShowAiring sa = tv.getShowAiring(); sdp.setChannel(c); sdp.setShowAiring(sa); setSelectedShowAiring(sa); } else { sdp.setChannel(null); sdp.setShowAiring(null); setSelectedShowAiring(null); } } updateRecordingStatus(); } else if (event.getPropertyName().equals("SelectedShowAiring")) { ShowDetailPanel sdp = getShowDetailPanel(); if (sdp != null) { ShowAiring sa = (ShowAiring) event.getNewValue(); sdp.setShowAiring(sa); setSelectedShowAiring(sa); } updateRecordingStatus(); } else if (event.getPropertyName().equals("SelectedRecordingRule")) { RecordingRule rr = (RecordingRule) event.getNewValue(); setSelectedRecordingRule(rr); applyUpcoming(); } else if (event.getPropertyName().equals("SelectedUpcoming")) { UpcomingDetailPanel dp = getUpcomingDetailPanel(); if (dp != null) { Upcoming u = (Upcoming) event.getNewValue(); dp.setUpcoming(u); } } } class LeftAction extends AbstractAction { public LeftAction() { } public void actionPerformed(ActionEvent e) { if (!isPopupEnabled()) { if (isParameterByTitle()) { TagListPanel tlp = getTitleTagListPanel(); if (tlp != null) { if (tlp.isExpanded()) { tlp.toggle(); } else { Tag selected = tlp.getSelectedTag(); if (selected != null) { Tag parent = selected.getParent(); if ((parent != null) && (!parent.isRoot())) { if (tlp.isExpanded(parent)) { tlp.setSelectedTag(parent); tlp.toggle(); } } } } } } else if (isParameterByGuide()) { GridGuidePanel ggp = getGridGuidePanel(); if (ggp != null) { ggp.left(); } } else if (isParameterUpcomingRecordings()) { RecordingRuleListPanel rrlp = getRecordingRuleListPanel(); if (rrlp != null) { rrlp.setControl(true); } UpcomingListPanel ulp = getUpcomingListPanel(); if (ulp != null) { ulp.setControl(false); } } } fireScreenEvent(ScreenEvent.USER_INPUT); } } class RightAction extends AbstractAction { public RightAction() { } public void actionPerformed(ActionEvent e) { if (!isPopupEnabled()) { if (isParameterByTitle()) { TagListPanel tlp = getTitleTagListPanel(); if (tlp != null) { tlp.toggle(); } } else if (isParameterByGuide()) { GridGuidePanel ggp = getGridGuidePanel(); if (ggp != null) { ggp.right(); } } else if (isParameterUpcomingRecordings()) { RecordingRuleListPanel rrlp = getRecordingRuleListPanel(); if (rrlp != null) { rrlp.setControl(false); } UpcomingListPanel ulp = getUpcomingListPanel(); if (ulp != null) { if (!ulp.isControl()) { ulp.setControl(true); } else { String text = null; int state = getUpcomingState(); switch (state) { default: case ALL_UPCOMING: state = RECORDING_UPCOMING; text = RECORDING_UPCOMING_TEXT; break; case RECORDING_UPCOMING: state = NOT_RECORDING_UPCOMING; text = NOT_RECORDING_UPCOMING_TEXT; break; case NOT_RECORDING_UPCOMING: state = ALL_UPCOMING; text = ALL_UPCOMING_TEXT; break; } JXLabel l = getUpcomingLabel(); if (l != null) { l.setText(text); } setUpcomingState(state); applyUpcoming(); } } } } fireScreenEvent(ScreenEvent.USER_INPUT); } } class UpAction extends AbstractAction { public UpAction() { } public void actionPerformed(ActionEvent e) { if (isPopupEnabled()) { ButtonPanel bp = getUserButtonPanel(); if (bp != null) { bp.moveUp(); } } else { if (isParameterByTitle()) { TagListPanel tlp = getTitleTagListPanel(); if (tlp != null) { tlp.moveUp(); } } else if (isParameterByGuide()) { GridGuidePanel ggp = getGridGuidePanel(); if (ggp != null) { ggp.up(); } } else if (isParameterUpcomingRecordings()) { RecordingRuleListPanel rrlp = getRecordingRuleListPanel(); if ((rrlp != null) && (rrlp.isControl())) { rrlp.moveUp(); } UpcomingListPanel ulp = getUpcomingListPanel(); if ((ulp != null) && (ulp.isControl())) { ulp.moveUp(); } } } fireScreenEvent(ScreenEvent.USER_INPUT); } } class DownAction extends AbstractAction { public DownAction() { } public void actionPerformed(ActionEvent e) { if (isPopupEnabled()) { ButtonPanel bp = getUserButtonPanel(); if (bp != null) { bp.moveDown(); } } else { if (isParameterByTitle()) { TagListPanel tlp = getTitleTagListPanel(); if (tlp != null) { tlp.moveDown(); } } else if (isParameterByGuide()) { GridGuidePanel ggp = getGridGuidePanel(); if (ggp != null) { ggp.down(); } } else if (isParameterUpcomingRecordings()) { RecordingRuleListPanel rrlp = getRecordingRuleListPanel(); if ((rrlp != null) && (rrlp.isControl())) { rrlp.moveDown(); } UpcomingListPanel ulp = getUpcomingListPanel(); if ((ulp != null) && (ulp.isControl())) { ulp.moveDown(); } } } fireScreenEvent(ScreenEvent.USER_INPUT); } } class PageUpAction extends AbstractAction { public PageUpAction() { } public void actionPerformed(ActionEvent e) { if (!isPopupEnabled()) { if (isParameterByTitle()) { TagListPanel tlp = getTitleTagListPanel(); if (tlp != null) { tlp.movePageUp(); } } else if (isParameterByGuide()) { GridGuidePanel ggp = getGridGuidePanel(); if (ggp != null) { ggp.pageUp(); } } else if (isParameterUpcomingRecordings()) { RecordingRuleListPanel rrlp = getRecordingRuleListPanel(); if ((rrlp != null) && (rrlp.isControl())) { rrlp.movePageUp(); } UpcomingListPanel ulp = getUpcomingListPanel(); if ((ulp != null) && (ulp.isControl())) { ulp.movePageUp(); } } } fireScreenEvent(ScreenEvent.USER_INPUT); } } class PageDownAction extends AbstractAction { public PageDownAction() { } public void actionPerformed(ActionEvent e) { if (!isPopupEnabled()) { if (isParameterByTitle()) { TagListPanel tlp = getTitleTagListPanel(); if (tlp != null) { tlp.movePageDown(); } } else if (isParameterByGuide()) { GridGuidePanel ggp = getGridGuidePanel(); if (ggp != null) { ggp.pageDown(); } } else if (isParameterUpcomingRecordings()) { RecordingRuleListPanel rrlp = getRecordingRuleListPanel(); if ((rrlp != null) && (rrlp.isControl())) { rrlp.movePageDown(); } UpcomingListPanel ulp = getUpcomingListPanel(); if ((ulp != null) && (ulp.isControl())) { ulp.movePageDown(); } } } fireScreenEvent(ScreenEvent.USER_INPUT); } } class EnterAction extends AbstractAction implements JobListener { public EnterAction() { } public void jobUpdate(JobEvent event) { if (event.getType() == JobEvent.COMPLETE) { if (isParameterUpcomingRecordings()) { setVisible(true); } } } public void editRule(NMS n, RecordingRulePanel p, RecordingRule rr) { if ((n != null) && (p != null) && (rr != null)) { p.setNMS(n); p.setRecordingRule(rr); p.setFrame(getFrame()); Dialog.showPanel(getFrame(), p, p.getOkButton(), p.getCancelButton()); if (p.isAccept()) { rr = p.getRecordingRule(); AddRuleJob arj = new AddRuleJob(n, rr); Busy busy = new Busy(getLayeredPane(), arj); busy.addJobListener(this); busy.execute(); } else { requestFocus(); } } } public void handleUpcoming() { UpcomingListPanel ulp = getUpcomingListPanel(); if (ulp != null) { Upcoming up = ulp.getSelectedUpcoming(); if (up != null) { ArrayList<String> blist = new ArrayList<String>(); if (NMSConstants.PREVIOUSLY_RECORDED.equals( up.getStatus())) { blist.add("Forget Old Recording"); } else { blist.add("Don't Record"); } blist.add(CANCEL); popup(blist.toArray(new String[blist.size()])); } } } public void actionPerformed(ActionEvent e) { RecordingRulePanel p = getRecordingRulePanel(); if (p != null) { if (isParameterUpcomingRecordings()) { UpcomingListPanel ulp = getUpcomingListPanel(); if ((ulp != null) && (ulp.isControl())) { handleUpcoming(); } else { RecordingRule rr = getSelectedRecordingRule(); if (rr != null) { NMS n = NMSUtil.select(getNMS(), rr.getHostPort()); if (n != null) { editRule(n, p, rr); } } } } else if (isParameterByTitle()) { ShowAiring sa = getSelectedShowAiring(); if (sa != null) { NMS n = NMSUtil.select(getNMS(), sa.getHostPort()); if (n != null) { Show show = sa.getShow(); Airing airing = sa.getAiring(); if ((show != null) && (airing != null)) { RecordingRule rr = getRecordingRule(sa); if (rr == null) { rr = new RecordingRule(); rr.setShowAiring(sa); rr.setType(RecordingRule.SERIES_TYPE); rr.setName(show.getTitle()); rr.setShowId(show.getId()); rr.setSeriesId(show.getSeriesId()); rr.setChannelId(airing.getChannelId()); rr.setListingId(airing.getListingId()); rr.setDuration(airing.getDuration()); rr.setPriority( RecordingRule.NORMAL_PRIORITY); rr.setTasks(n.getTasks()); } editRule(n, p, rr); } } } } else if (isParameterByGuide()) { GridGuidePanel ggp = getGridGuidePanel(); if (ggp != null) { ShowAiring sa = getSelectedShowAiring(); if (sa != null) { NMS n = NMSUtil.select(getNMS(), sa.getHostPort()); if (n != null) { Show show = sa.getShow(); Airing airing = sa.getAiring(); if ((show != null) && (airing != null)) { RecordingRule rr = getRecordingRule(sa); if (rr == null) { rr = new RecordingRule(); rr.setShowAiring(sa); rr.setType(RecordingRule.SERIES_TYPE); rr.setName(show.getTitle()); rr.setShowId(show.getId()); rr.setSeriesId(show.getSeriesId()); rr.setChannelId(airing.getChannelId()); rr.setListingId(airing.getListingId()); rr.setDuration(airing.getDuration()); rr.setPriority( RecordingRule.NORMAL_PRIORITY); rr.setTasks(n.getTasks()); } editRule(n, p, rr); } } } } } } } } class InfoAction extends AbstractAction { public InfoAction() { } public void actionPerformed(ActionEvent e) { if (isParameterByGuide()) { handleFavorite(); } fireScreenEvent(ScreenEvent.USER_INPUT); } } static class TagValue { private Channel channel; private ShowAiring showAiring; public TagValue(Channel c, ShowAiring sa) { setChannel(c); setShowAiring(sa); } public Channel getChannel() { return (channel); } private void setChannel(Channel c) { channel = c; } public ShowAiring getShowAiring() { return (showAiring); } private void setShowAiring(ShowAiring c) { showAiring = c; } } static class RecordingRuleSortByName implements Comparator<RecordingRule>, Serializable { public RecordingRuleSortByName() { } public int compare(RecordingRule rr0, RecordingRule rr1) { String s0 = Util.toSortableTitle(rr0.getName()); String s1 = Util.toSortableTitle(rr1.getName()); return (s0.compareTo(s1)); } } }