/* * Copyright (c) 2008, 2009, 2010, 2011 Denis Tulskiy * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3 along with this work. If not, see <http://www.gnu.org/licenses/>. */ package com.tulskiy.musique.gui.library; import com.tulskiy.musique.gui.SearchWorker; import com.tulskiy.musique.gui.components.SearchField; import com.tulskiy.musique.gui.dialogs.OptionsDialog; import com.tulskiy.musique.gui.dialogs.ProgressDialog; import com.tulskiy.musique.gui.dialogs.Task; import com.tulskiy.musique.gui.dnd.LibraryTransferHandler; import com.tulskiy.musique.gui.menu.LibraryMenu; import com.tulskiy.musique.images.Images; import com.tulskiy.musique.library.Library; import com.tulskiy.musique.playlist.Playlist; import com.tulskiy.musique.playlist.PlaylistManager; import com.tulskiy.musique.system.Application; import com.tulskiy.musique.system.configuration.Configuration; import com.tulskiy.musique.util.Util; import javax.swing.*; import javax.swing.border.TitledBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.tree.DefaultTreeModel; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.HashMap; /** * Author: Denis Tulskiy * Date: 10/31/10 */ public class LibraryView extends JPanel { private Application app = Application.getInstance(); private Configuration config = app.getConfiguration(); private LibraryTree tree; private Library library; private Playlist libraryPlaylist; private PlaylistManager playlistManager; private SearchWorker searchWorker; private Library libraryView; public LibraryView() { playlistManager = app.getPlaylistManager(); library = playlistManager.getLibrary(); for (Playlist playlist : playlistManager.getPlaylists()) { if (playlist.isLibraryView()) { libraryPlaylist = playlist; break; } } initComponents(); initListeners(); initDND(); } private void initDND() { tree.setDragEnabled(true); tree.setTransferHandler(new LibraryTransferHandler()); } private void initComponents() { setLayout(new BorderLayout(5, 5)); tree = new LibraryTree(); tree.setRootNode(library.getRootNode()); JScrollPane scrollPane = new JScrollPane(tree); scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); add(scrollPane, BorderLayout.CENTER); final SearchField searchField = new SearchField(); Box viewBox = Box.createHorizontalBox(); JComboBox viewCombo = new JComboBox(new Object[]{"By Album Artist"}); JPanel p1 = new JPanel(new BorderLayout()); p1.add(viewCombo); p1.setMaximumSize(new Dimension(200, 100)); p1.setBorder(BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), "View", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.TOP, new Font("Sans Serif", 0, 11))); viewBox.add(p1); JPanel p2 = new JPanel(new BorderLayout()); p2.add(searchField); p2.setBorder(BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(), "Filter", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.TOP, new Font("Sans Serif", 0, 11))); viewBox.add(p2); add(viewBox, BorderLayout.PAGE_END); searchField.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { if (searchWorker != null && !searchWorker.isDone()) { searchWorker.cancel(true); } searchWorker = new SearchWorker(library.getData(), searchField.getText(), true) { @Override protected void done() { try { Playlist result = get(); if (result != null) { libraryView = new Library(result); tree.setRootNode(libraryView.getRootNode()); } else { libraryView = null; } } catch (Exception ignored) { } } }; searchWorker.execute(); } }); } private void initListeners() { tree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() { @SuppressWarnings({"unchecked"}) @Override public void valueChanged(TreeSelectionEvent e) { if (config.getBoolean("library.libraryView", false)) fillLibraryView(); } }); config.addPropertyChangeListener("library.libraryView", new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { if (config.getBoolean(evt.getPropertyName(), false)) { createLibraryView(false); } else { for (Playlist playlist : playlistManager.getPlaylists()) { if (playlist.isLibraryView()) { playlistManager.removePlaylist(playlist); break; } } } } }); tree.addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { show(e); } @Override public void mouseReleased(MouseEvent e) { show(e); } public void show(MouseEvent e) { if (e.isPopupTrigger() && tree.selectRowAt(e.getPoint())) { LibraryMenu menu = new LibraryMenu(); JPopupMenu popup = menu.create( tree, library.getData(), tree.getSelectedTracks(false)); System.out.println(e.getPoint()); popup.show(tree, e.getX(), e.getY()); } } }); } private void fillLibraryView() { createLibraryView(true); libraryPlaylist.clear(); libraryPlaylist.addAll(tree.getSelectedTracks(false)); libraryPlaylist.firePlaylistChanged(); } private void createLibraryView(boolean setVisible) { if (libraryPlaylist == null) { libraryPlaylist = playlistManager.addPlaylist("Library"); libraryPlaylist.setLibraryView(true); } if (!playlistManager.getPlaylists().contains(libraryPlaylist)) { playlistManager.addPlaylist(libraryPlaylist); } if (setVisible) playlistManager.setVisiblePlaylist(libraryPlaylist); } public void addMenu(JMenuBar menuBar) { JMenu menu = new JMenu("Library"); menuBar.add(menu); JMenuItem configure = menu.add("Configure "); configure.setIcon(Images.getEmptyIcon()); configure.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { new OptionsDialog(getRootPane(), "Library").setVisible(true); } }); menu.add("Rescan").addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { ProgressDialog progressDialog = new ProgressDialog(getRootPane(), "Library Rescan"); progressDialog.show(new Task() { HashMap<String, Object> map = new HashMap<String, Object>(); @Override public String getStatus() { return "Scanning library\n" + String.valueOf(map.get("processing.file")); } @Override public void abort() { map.put("processing.stop", true); } @Override public void start() { int[] selectionRows = tree.getSelectionRows(); library.rescan(map); ((DefaultTreeModel) tree.getModel()).reload(); tree.revalidate(); tree.repaint(); if (selectionRows != null) tree.setSelectionRows(selectionRows); } }); } }); Util.fixIconTextGap(menu); } }