net.pms.medialibrary.gui.shared.FileImportTemplatePanel.java Source code

Java tutorial

Introduction

Here is the source code for net.pms.medialibrary.gui.shared.FileImportTemplatePanel.java

Source

/*
 * PS3 Media Server, for streaming any medias to your PS3.
 * Copyright (C) 2012  Ph.Waeber
 *
 * This program 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; version 2
 * of the License only.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package net.pms.medialibrary.gui.shared;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

import net.pms.Messages;
import net.pms.medialibrary.commons.dataobjects.DOFileImportTemplate;
import net.pms.medialibrary.commons.dataobjects.DOFileScannerEngineConfiguration;
import net.pms.medialibrary.commons.enumarations.FileProperty;
import net.pms.medialibrary.commons.enumarations.FileType;
import net.pms.medialibrary.storage.MediaLibraryStorage;
import net.pms.plugins.FileImportPlugin;
import net.pms.plugins.PluginsFactory;

public class FileImportTemplatePanel extends JPanel {
    private static final long serialVersionUID = -4447691905844747495L;

    private List<ActionListener> repaintListeners = new ArrayList<ActionListener>();

    private JComboBox cbTemplate;
    private JButton bNewTemplate;
    private JButton bDeleteTemplate;
    private JTabbedPane tpProperties;

    private FileImportPropertiesPanel fippsVideo;
    private FileImportPropertiesPanel fippsAudio;
    private FileImportPropertiesPanel fippsPictures;

    public FileImportTemplatePanel(int fileImportTemplateId) {
        prepareComponents(fileImportTemplateId);
    }

    /**
     * Adds notification support when a repaint is needed.
     * This is required to redraw the dialog properly when changing template
     * @param repaintListener
     */
    public void addRepaintListener(ActionListener repaintListener) {
        if (repaintListeners.contains(repaintListener)) {
            repaintListeners.remove(repaintListener);
        }
        repaintListeners.add(repaintListener);
    }

    /**
     * returns the ID of the template having been set. If an error occurs the id=1 
     * corresponding to the default template is being returned
     * @return set template id
     */
    public int getFileImportTemplateId() {
        //the ID of the default template is 1. Keep it as a fail safe if something goes wrong
        //while retrieving the ID from the panel
        int templateId = 1;

        //try to get the real selected template id
        if (cbTemplate.getSelectedItem() != null && cbTemplate.getSelectedItem() instanceof DOFileImportTemplate) {
            templateId = ((DOFileImportTemplate) cbTemplate.getSelectedItem()).getId();
        }

        return templateId;
    }

    /**
     * Sets the 'normal' gui state be enabling the delete template button,
     * making the templates combo box non-editable and selecting the saved template
     * @param template
     */
    public void templateSaved(DOFileImportTemplate template) {
        if (cbTemplate.isEditable()) {
            //restore UI after editing
            bDeleteTemplate.setEnabled(true);
            bNewTemplate.setEnabled(true);

            //refresh all templates
            cbTemplate = getTemplatesComboBox();

            fippsAudio.setFileImportTemplate(template);
            fippsPictures.setFileImportTemplate(template);
            fippsVideo.setFileImportTemplate(template);

            placeComponents();

            //select saved template
            cbTemplate.setSelectedItem(getTemplateInComboBoxById(template.getId()));
        }
        checkDeleteButtonState(template.getId());
    }

    /**
     * Either return a new template if a new one has been created
     * or return the already existing one.
     * If a new template is being returned, its ID will be 0
     * @return the configured template
     */
    public DOFileImportTemplate getDisplayedTemplate() {
        DOFileImportTemplate displayedTemplate = null;

        if (cbTemplate.isEditable()) {
            // it's a new template
            displayedTemplate = new DOFileImportTemplate();

            //get the entered name
            String newName = "";
            if (cbTemplate.getEditor().getItem() != null) {
                newName = cbTemplate.getEditor().getItem().toString();
            }
            displayedTemplate.setName(newName);
        } else if (cbTemplate.getSelectedItem() instanceof DOFileImportTemplate) {
            //take the selected template
            displayedTemplate = (DOFileImportTemplate) cbTemplate.getSelectedItem();
        }

        //merge the configured engines for the different file types
        List<DOFileScannerEngineConfiguration> configuredEngines = new ArrayList<DOFileScannerEngineConfiguration>();
        configuredEngines.addAll(fippsAudio.getConfiguredEngines());
        configuredEngines.addAll(fippsVideo.getConfiguredEngines());
        configuredEngines.addAll(fippsPictures.getConfiguredEngines());
        displayedTemplate.setEngineConfigurations(configuredEngines);

        //merge the active engines for the different file types
        Map<FileType, List<String>> activeEngines = new HashMap<FileType, List<String>>();
        activeEngines.putAll(fippsAudio.getActiveEngines());
        activeEngines.putAll(fippsVideo.getActiveEngines());
        activeEngines.putAll(fippsPictures.getActiveEngines());
        displayedTemplate.setEnabledEngines(activeEngines);

        //merge configured tags per engine
        Map<FileType, Map<String, List<String>>> tagsPerEngine = new HashMap<FileType, Map<String, List<String>>>();
        tagsPerEngine.put(FileType.AUDIO, fippsAudio.getActiveTags());
        tagsPerEngine.put(FileType.VIDEO, fippsVideo.getActiveTags());
        tagsPerEngine.put(FileType.PICTURES, fippsPictures.getActiveTags());
        displayedTemplate.setEnabledTags(tagsPerEngine);

        return displayedTemplate;
    }

    private JComboBox getTemplatesComboBox() {
        //load the available templates from db
        List<DOFileImportTemplate> importTemplates = MediaLibraryStorage.getInstance().getFileImportTemplates();

        //create combo box
        JComboBox cbNew = new JComboBox();

        //sort the entries by their displayed name
        Collections.sort(importTemplates, new Comparator<DOFileImportTemplate>() {
            @Override
            public int compare(DOFileImportTemplate o1, DOFileImportTemplate o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });

        //add the loaded templates as combo box items
        for (DOFileImportTemplate importTemplate : importTemplates) {
            cbNew.addItem(importTemplate);
        }

        //attach listener to update shown file properties according to template
        cbNew.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JComboBox cb = (JComboBox) e.getSource();
                if (cb.getSelectedItem() instanceof DOFileImportTemplate) {
                    DOFileImportTemplate selectedTemplate = (DOFileImportTemplate) cb.getSelectedItem();
                    int selectedTab = tpProperties.getSelectedIndex();
                    updateTabbedPane(selectedTemplate);
                    tpProperties.setSelectedIndex(selectedTab);

                    placeComponents();

                    checkDeleteButtonState(selectedTemplate.getId());
                }
                cb.requestFocus();
            }
        });

        return cbNew;
    }

    private void updateTabbedPane(DOFileImportTemplate template) {
        fippsAudio.setFileImportTemplate(template);
        fippsVideo.setFileImportTemplate(template);
        fippsPictures.setFileImportTemplate(template);

        tpProperties = buildTabbedPane();
    }

    /**
     * Initializes all UI Components. Components being initialized are the combo box containing 
     * the templates, all file properties with their list of engines and the buttons    * 
     * @param allowEdit 
     */
    private void prepareComponents(int fileImportTemplateId) {
        //create and populate template combo box with items of type DOFileImportTemplate
        cbTemplate = getTemplatesComboBox();

        //select the correct template in the combo box
        DOFileImportTemplate activeTemplate = getTemplateInComboBoxById(fileImportTemplateId);

        //create the new template button
        bNewTemplate = new JButton(new ImageIcon(getClass().getResource("/resources/images/tp_add.png")));
        bNewTemplate.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                cbTemplate.setEditable(true);
                cbTemplate.removeAllItems();
                cbTemplate.requestFocus();

                bDeleteTemplate.setEnabled(false);
                bNewTemplate.setEnabled(false);
            }
        });

        //create the delete template button
        bDeleteTemplate = new JButton(new ImageIcon(getClass().getResource("/resources/images/tp_remove.png")));
        bDeleteTemplate.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                deleteSelectedTemplate();
            }
        });

        fippsAudio = new FileImportPropertiesPanel(activeTemplate, FileType.AUDIO);
        fippsAudio.addActivePluginsChangedListener(getActivePluginsChangedListener());
        fippsVideo = new FileImportPropertiesPanel(activeTemplate, FileType.VIDEO);
        fippsVideo.addActivePluginsChangedListener(getActivePluginsChangedListener());
        fippsPictures = new FileImportPropertiesPanel(activeTemplate, FileType.PICTURES);
        fippsPictures.addActivePluginsChangedListener(getActivePluginsChangedListener());

        //create and update list of FileScannerSelectorPanel
        if (activeTemplate != null) {
            updateTabbedPane(activeTemplate);
        }

        //select configured template after all components have been initialized
        //this will also trigger the rest of the UI initialization
        cbTemplate.setSelectedItem(activeTemplate);
    }

    private ActionListener getActivePluginsChangedListener() {
        return new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                DOFileImportTemplate tmpTemplate = getDisplayedTemplate();

                fippsAudio.setFileImportTemplate(tmpTemplate);
                fippsVideo.setFileImportTemplate(tmpTemplate);
                fippsPictures.setFileImportTemplate(tmpTemplate);

                for (ActionListener l : repaintListeners) {
                    l.actionPerformed(new ActionEvent(this, 0, "Repaint"));
                }
            }
        };
    }

    private void checkDeleteButtonState(int templateId) {
        //disable the delete button if it wont be possible to delete the template
        if (MediaLibraryStorage.getInstance().isFileImportTemplateInUse(templateId)) {
            bDeleteTemplate.setEnabled(false);
        } else {
            bDeleteTemplate.setEnabled(true);
        }
    }

    /**
     * Places the visual components correctly in the grid. Components being shown are the combo box containing 
     * the templates, all file properties with their list of engines and the buttons
     */
    private void placeComponents() {
        FormLayout layout = new FormLayout("fill:p:grow, 5px, p, 5px, p, 5px, p", "p, 5px, fill:p:grow");
        PanelBuilder builder = new PanelBuilder(layout);
        builder.setOpaque(true);

        CellConstraints cc = new CellConstraints();

        //create top panel with combo box and and buttons
        builder.addLabel(Messages.getString("ML.FileImportConfigurationPanel.lTemplate"),
                cc.xy(1, 1, CellConstraints.RIGHT, CellConstraints.DEFAULT));
        builder.add(cbTemplate, cc.xy(3, 1));
        builder.add(bNewTemplate, cc.xy(5, 1));
        builder.add(bDeleteTemplate, cc.xy(7, 1));
        builder.add(tpProperties, cc.xyw(1, 3, 7));

        //build the dialog
        setLayout(new GridLayout());
        removeAll();
        add(builder.getPanel());

        for (ActionListener l : repaintListeners) {
            l.actionPerformed(new ActionEvent(this, 0, "Repaint"));
        }
    }

    private JTabbedPane buildTabbedPane() {
        JTabbedPane tp = new JTabbedPane();
        tp.addTab(Messages.getString("ML.FileType.VIDEO"),
                new ImageIcon(getClass().getResource("/resources/images/videofolder-16.png")), fippsVideo);
        tp.addTab(Messages.getString("ML.FileType.AUDIO"),
                new ImageIcon(getClass().getResource("/resources/images/audiofolder-16.png")), fippsAudio);
        tp.addTab(Messages.getString("ML.FileType.PICTURES"),
                new ImageIcon(getClass().getResource("/resources/images/picturesfolder-16.png")), fippsPictures);

        return tp;
    }

    /**
     * Deletes the currently selected DOFileImportTemplate in the combo box. It's being deleted from the DB as 
     * well as removed from the list of available DOFileImportTemplate in the combo box
     * 
     */
    private void deleteSelectedTemplate() {
        if (cbTemplate.getSelectedItem() != null && cbTemplate.getSelectedItem() instanceof DOFileImportTemplate) {
            DOFileImportTemplate template = (DOFileImportTemplate) cbTemplate.getSelectedItem();

            //don't allow to delete the default template
            if (template.getId() == 1) {
                JOptionPane.showMessageDialog(this,
                        Messages.getString("ML.FileImportConfigurationPanel.Msg.NoDeleteDefaultTemplate"));
                return;
            }

            //don't allow to delete a template which is being used by other managed folders
            if (MediaLibraryStorage.getInstance().isFileImportTemplateInUse(template.getId())) {
                JOptionPane.showMessageDialog(this,
                        String.format(Messages.getString("ML.FileImportConfigurationPanel.Msg.DeleteTemplateInUse"),
                                template.getName()));
                return;
            }

            //ask for delete confirmation before deleting
            if (JOptionPane.showConfirmDialog(this,
                    String.format(Messages.getString("ML.FileImportConfigurationPanel.Msg.ConfirmDeleteTemplate"),
                            template.getName())) == JOptionPane.NO_OPTION) {
                return;
            }

            //delete the template from DB and combo box
            MediaLibraryStorage.getInstance().deleteFileImportTemplate(template.getId());
            cbTemplate.removeItem(template);

            //set the default template selected when a template is being deleted
            cbTemplate.setSelectedItem(getTemplateInComboBoxById(1));
        }
    }

    /**
     * Returns the DOFileImportTemplate with the given id if it is contained in the combo box elements, null otherwise
     * @param templateId the id of the template to look for
     * @return the DOFileImportTemplate with the given id or null if not found
     */
    private DOFileImportTemplate getTemplateInComboBoxById(int templateId) {
        DOFileImportTemplate res = null;

        for (int i = 0; i < cbTemplate.getItemCount(); i++) {
            Object currrentItem = cbTemplate.getItemAt(i);
            if (currrentItem instanceof DOFileImportTemplate) {
                if (((DOFileImportTemplate) currrentItem).getId() == templateId) {
                    res = (DOFileImportTemplate) currrentItem;
                    break;
                }
            }
        }

        return res;
    }
}