/* 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.vm; import java.awt.BorderLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Frame; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.AbstractAction; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.JScrollPane; import javax.swing.SpinnerNumberModel; import org.jflicks.metadata.Hit; import org.jflicks.metadata.Metadata; import org.jflicks.metadata.SearchEvent; import org.jflicks.metadata.SearchListener; import org.jflicks.metadata.SearchPanel; import org.jflicks.nms.NMS; import org.jflicks.nms.NMSConstants; import org.jflicks.nms.Video; import org.jflicks.util.Util; /** * Implements a View so a user can control the metadata of videos. * * @author Doug Barnum * @version 1.0 */ public class EditVideoPanel extends BasePanel implements ActionListener, SearchListener { private NMS nms; private Video video; private JComboBox categoryComboBox; private JComboBox subcategoryComboBox; private JTextField subcategoryTextField; private JSpinner seasonSpinner; private JSpinner episodeSpinner; private JTextField titleTextField; private JTextArea descriptionTextArea; private JTextField releasedTextField; private JTextField durationTextField; private JButton saveButton; private JComboBox aspectRatioComboBox; private JCheckBox playIntroCheckBox; private ThumbnailPanel thumbnailPanel; /** * Constructor with three arguments. * * @param n A given NMS instance. * @param v A given Video instance. * @param array An array of Metadata services. */ public EditVideoPanel(NMS n, Video v, Metadata[] array) { JTextField ttf = new JTextField(30); setTitleTextField(ttf); JPanel titlePanel = new JPanel(new BorderLayout()); titlePanel.setBorder(BorderFactory.createTitledBorder("Title")); titlePanel.add(ttf, BorderLayout.CENTER); JTextArea dta = new JTextArea(6, 30); dta.setLineWrap(true); dta.setWrapStyleWord(true); setDescriptionTextArea(dta); JScrollPane taScroll = new JScrollPane(dta, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); JPanel descPanel = new JPanel(new BorderLayout()); descPanel.setBorder(BorderFactory.createTitledBorder("Description")); descPanel.add(taScroll, BorderLayout.CENTER); JTextField releasedtf = new JTextField(30); setReleasedTextField(releasedtf); JPanel releasedPanel = new JPanel(new BorderLayout()); releasedPanel.setBorder(BorderFactory.createTitledBorder("Released")); releasedPanel.add(releasedtf, BorderLayout.CENTER); JComboBox cb = new JComboBox(); cb.setEditable(true); cb.addItem(NMSConstants.VIDEO_MOVIE); cb.addItem(NMSConstants.VIDEO_TV); cb.addItem(NMSConstants.VIDEO_HOME); cb.addItem(NMSConstants.VIDEO_EXERCISE); cb.addActionListener(this); setCategoryComboBox(cb); JPanel catPanel = new JPanel(new BorderLayout()); catPanel.setBorder(BorderFactory.createTitledBorder("Category")); catPanel.add(cb, BorderLayout.CENTER); JComboBox subcb = new JComboBox(); subcb.setEditable(true); subcb.addItem(NMSConstants.ADVENTURE_GENRE); subcb.addItem(NMSConstants.CHRISTMAS_GENRE); subcb.addItem(NMSConstants.COMEDY_GENRE); subcb.addItem(NMSConstants.DRAMA_GENRE); subcb.addItem(NMSConstants.FAMILY_GENRE); subcb.addItem(NMSConstants.HORROR_GENRE); subcb.addItem(NMSConstants.MUSICAL_GENRE); subcb.addItem(NMSConstants.MYSTERY_GENRE); subcb.addItem(NMSConstants.NOW_SHOWING_GENRE); subcb.addItem(NMSConstants.ROMANTIC_COMEDY_GENRE); subcb.addItem(NMSConstants.SCIFI_GENRE); subcb.addItem(NMSConstants.THRILLER_GENRE); subcb.addItem(NMSConstants.WAR_GENRE); subcb.addItem(NMSConstants.WESTERN_GENRE); setSubcategoryComboBox(subcb); JTextField subtf = new JTextField(24); subtf.setEditable(false); setSubcategoryTextField(subtf); SpinnerNumberModel model = new SpinnerNumberModel(1, 1, 20, 1); JSpinner seasonsp = new JSpinner(model); setSeasonSpinner(seasonsp); model = new SpinnerNumberModel(1, 1, 40, 1); JSpinner episodesp = new JSpinner(model); setEpisodeSpinner(episodesp); JTextField durtf = new JTextField(10); setDurationTextField(durtf); JComboBox arcb = new JComboBox(); arcb.setEditable(false); arcb.addItem(NMSConstants.ASPECT_RATIO_16X9); arcb.addItem(NMSConstants.ASPECT_RATIO_4X3); arcb.addItem(NMSConstants.ASPECT_RATIO_235X1); setAspectRatioComboBox(arcb); JCheckBox introcb = new JCheckBox("Play Intro"); setPlayIntroCheckBox(introcb); ThumbnailPanel tp = new ThumbnailPanel(); setThumbnailPanel(tp); setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); add(titlePanel, gbc); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 1.0; gbc.insets = new Insets(4, 4, 4, 4); add(descPanel, gbc); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 2; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); add(releasedPanel, gbc); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 3; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); add(catPanel, gbc); JPanel subcatPanel = new JPanel(); subcatPanel.setBorder(BorderFactory.createTitledBorder("Subcategory")); subcatPanel.setLayout(new GridBagLayout()); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 3; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); subcatPanel.add(subcb, gbc); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); subcatPanel.add(subtf, gbc); gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.gridy = 1; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); subcatPanel.add(seasonsp, gbc); gbc = new GridBagConstraints(); gbc.gridx = 2; gbc.gridy = 1; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); subcatPanel.add(episodesp, gbc); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 4; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); add(subcatPanel, gbc); JPanel durPanel = new JPanel(); durPanel.setBorder( BorderFactory.createTitledBorder("Duration (secs)")); durPanel.setLayout(new GridBagLayout()); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); durPanel.add(durtf, gbc); JPanel arPanel = new JPanel(); arPanel.setBorder(BorderFactory.createTitledBorder("Aspect Ratio")); arPanel.setLayout(new GridBagLayout()); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); arPanel.add(arcb, gbc); JPanel middlePanel = new JPanel(); middlePanel.setLayout(new GridBagLayout()); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); middlePanel.add(introcb, gbc); gbc = new GridBagConstraints(); gbc.gridx = 1; gbc.gridy = 0; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); middlePanel.add(durPanel, gbc); gbc = new GridBagConstraints(); gbc.gridx = 2; gbc.gridy = 0; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); middlePanel.add(arPanel, gbc); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 5; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); add(middlePanel, gbc); gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 6; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.5; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); add(getThumbnailPanel(), gbc); // Now add any Metadata actions we have been given... if ((array != null) && (array.length > 0)) { SearchAction[] sarray = new SearchAction[array.length]; for (int i = 0; i < sarray.length; i++) { sarray[i] = new SearchAction(array[i], this); } JPanel searchPanel = new JPanel(); searchPanel.setLayout(new GridBagLayout()); for (int i = 0; i < sarray.length; i++) { JButton button = new JButton(sarray[i]); gbc = new GridBagConstraints(); gbc.gridx = i; gbc.gridy = 0; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.0; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); searchPanel.add(button, gbc); } gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 7; gbc.gridwidth = 1; gbc.gridheight = 1; gbc.fill = GridBagConstraints.BOTH; gbc.anchor = GridBagConstraints.CENTER; gbc.weightx = 0.0; gbc.weighty = 0.0; gbc.insets = new Insets(4, 4, 4, 4); add(searchPanel, gbc); } setNMS(n); setVideo(v); } private NMS getNMS() { return (nms); } private void setNMS(NMS n) { nms = n; } /** * A Video instance reflecting the current state of the UI. * * @return A Video instance. */ public Video getVideo() { if (video != null) { video.setCategory((String) getCategoryComboBox().getSelectedItem()); video.setTitle(getTitleTextField().getText()); video.setDescription(getDescriptionTextArea().getText()); video.setReleased(getReleasedTextField().getText()); video.setDuration(Util.str2long(getDurationTextField().getText(), video.getDuration())); video.setAspectRatio( (String) getAspectRatioComboBox().getSelectedItem()); video.setPlayIntro(getPlayIntroCheckBox().isSelected()); if (video.isTV()) { video.setSubcategory(video.getTitle() + " Season " + video.getSeason()); Integer iobj = (Integer) getSeasonSpinner().getValue(); if (iobj != null) { video.setSeason(iobj.intValue()); } iobj = (Integer) getEpisodeSpinner().getValue(); if (iobj != null) { video.setEpisode(iobj.intValue()); } } else { video.setSubcategory( (String) getSubcategoryComboBox().getSelectedItem()); } } return (video); } private void setVideo(Video v) { video = v; updateState(v); if (v != null) { if (v.isTV()) { fireSearchEvent(SearchEvent.SEARCH_TV, v.getTitle()); } else { fireSearchEvent(SearchEvent.SEARCH_MOVIE, v.getTitle()); } } } private void updateState(Video v) { if (v != null) { getCategoryComboBox().setSelectedItem(v.getCategory()); updateSubcategoryState(v.isTV(), v); getTitleTextField().setText(v.getTitle()); getDescriptionTextArea().setText(v.getDescription()); getReleasedTextField().setText(v.getReleased()); getDurationTextField().setText(v.getDuration() + ""); getAspectRatioComboBox().setSelectedItem(v.getAspectRatio()); getPlayIntroCheckBox().setSelected(v.isPlayIntro()); getThumbnailPanel().setVideo(v); } } private void updateSubcategoryState(boolean tv, Video v) { if (tv) { getSubcategoryComboBox().setSelectedItem(""); getSubcategoryComboBox().setEnabled(false); getSeasonSpinner().setValue(Integer.valueOf(v.getSeason())); getSeasonSpinner().setEnabled(true); getEpisodeSpinner().setValue(Integer.valueOf(v.getEpisode())); getEpisodeSpinner().setEnabled(true); getSubcategoryTextField().setText(v.getTitle() + " Season " + getSeasonSpinner().getValue()); } else { getSubcategoryComboBox().setSelectedItem(v.getSubcategory()); getSubcategoryComboBox().setEnabled(true); getSeasonSpinner().setValue(Integer.valueOf(1)); getSeasonSpinner().setEnabled(false); getEpisodeSpinner().setValue(Integer.valueOf(1)); getEpisodeSpinner().setEnabled(false); getSubcategoryTextField().setText(""); } } private JComboBox getCategoryComboBox() { return (categoryComboBox); } private void setCategoryComboBox(JComboBox cb) { categoryComboBox = cb; } private JComboBox getSubcategoryComboBox() { return (subcategoryComboBox); } private void setSubcategoryComboBox(JComboBox cb) { subcategoryComboBox = cb; } private JTextField getSubcategoryTextField() { return (subcategoryTextField); } private void setSubcategoryTextField(JTextField tf) { subcategoryTextField = tf; } private JSpinner getSeasonSpinner() { return (seasonSpinner); } private void setSeasonSpinner(JSpinner s) { seasonSpinner = s; } private JSpinner getEpisodeSpinner() { return (episodeSpinner); } private void setEpisodeSpinner(JSpinner s) { episodeSpinner = s; } private JTextField getTitleTextField() { return (titleTextField); } private void setTitleTextField(JTextField tf) { titleTextField = tf; } private JTextArea getDescriptionTextArea() { return (descriptionTextArea); } private void setDescriptionTextArea(JTextArea ta) { descriptionTextArea = ta; } private JTextField getReleasedTextField() { return (releasedTextField); } private void setReleasedTextField(JTextField tf) { releasedTextField = tf; } private JTextField getDurationTextField() { return (durationTextField); } private void setDurationTextField(JTextField tf) { durationTextField = tf; } private JComboBox getAspectRatioComboBox() { return (aspectRatioComboBox); } private void setAspectRatioComboBox(JComboBox cb) { aspectRatioComboBox = cb; } private JCheckBox getPlayIntroCheckBox() { return (playIntroCheckBox); } private void setPlayIntroCheckBox(JCheckBox cb) { playIntroCheckBox = cb; } private ThumbnailPanel getThumbnailPanel() { return (thumbnailPanel); } private void setThumbnailPanel(ThumbnailPanel tp) { thumbnailPanel = tp; } private Frame getFrame() { return (Util.findFrame(this)); } private JPanel getPanel() { return (this); } /** * We listen for category combo box events so we can set the subcategory * state correctly. * * @param event A given ActionEvent. */ public void actionPerformed(ActionEvent event) { if (event.getSource() == getCategoryComboBox()) { JComboBox cb = getCategoryComboBox(); String old = video.getCategory(); String value = (String) cb.getSelectedItem(); if (!Util.equalOrNull(old, value)) { video.setCategory(value); } updateSubcategoryState(NMSConstants.VIDEO_TV.equals(value), video); } } /** * {@inheritDoc} */ public void searchUpdate(SearchEvent event) { if (event.getType() == SearchEvent.UPDATE) { if (isVisible()) { // Extract and update. Hit h = event.getHit(); if ((video != null) && (h != null)) { video.setTitle(h.getTitle()); video.setDescription(h.getDescription()); video.setReleased(h.getReleased()); video.setPosterURL(h.getPosterURL()); video.setFanartURL(h.getFanartURL()); updateState(video); } } } } class SearchAction extends AbstractAction { private Metadata metadata; private EditVideoPanel editVideoPanel; private SearchPanel searchPanel; public SearchAction(Metadata m, EditVideoPanel p) { editVideoPanel = p; metadata = m; if (m != null) { putValue(NAME, m.getTitle()); SearchPanel sp = m.getSearchPanel(); if (sp != null) { sp.addSearchListener(editVideoPanel); editVideoPanel.addSearchListener(sp); searchPanel = sp; } } } public void actionPerformed(ActionEvent e) { if ((metadata != null) && (searchPanel != null)) { Util.showDoneDialog(getFrame(), "Search", searchPanel); } } } }