/* * Copyright (c) 2008, 2009, 2010 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.dialogs; import com.tulskiy.musique.audio.player.Player; import com.tulskiy.musique.gui.SearchWorker; import com.tulskiy.musique.gui.playlist.PlaylistColumn; import com.tulskiy.musique.gui.playlist.PlaylistTable; import com.tulskiy.musique.playlist.PlaybackOrder; import com.tulskiy.musique.playlist.Playlist; import com.tulskiy.musique.playlist.Track; import com.tulskiy.musique.system.Application; import com.tulskiy.musique.util.Util; import javax.swing.*; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; /** * Author: Denis Tulskiy * Date: Jun 9, 2010 */ public class SearchDialog extends JDialog { private final String[] fields = { "artist", "title", "album", "albumArtist", "fileName" }; private JTextField searchField; private PlaylistTable table; private Playlist view = new Playlist(); private ArrayList<Integer> viewToModel = new ArrayList<Integer>(); private Playlist playlist; private Timer timer; private SearchWorker searchWorker; public SearchDialog(final PlaylistTable playlistTable) { super(playlistTable.getParentFrame(), "Search", false); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setSize(600, 300); setLocationRelativeTo(playlistTable.getParentFrame()); setDefaultLookAndFeelDecorated(false); setLayout(new BorderLayout()); searchField = new JTextField(); ArrayList<PlaylistColumn> columns = new ArrayList<PlaylistColumn>(); columns.add(new PlaylistColumn(" ", 20, "$isPlaying()")); columns.add(new PlaylistColumn("Name", 400, "[%artist% - ]$if3(%title%,%fileName%)")); columns.add(new PlaylistColumn("Length", 60, "%length%")); columns.add(new PlaylistColumn("Album", 100, "%album%")); playlist = playlistTable.getPlaylist(); table = new PlaylistTable(view, columns); table.setTrackSelection(false); add(searchField, BorderLayout.NORTH); add(new JScrollPane(table), BorderLayout.CENTER); final ListSelectionListener listener = new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { int[] rows = table.getSelectedRows(); int[] toSelect = new int[rows.length]; for (int i = 0; i < rows.length; i++) { toSelect[i] = viewToModel.get(rows[i]); } playlistTable.clearSelection(); if (toSelect.length > 0) playlistTable.scrollToRow(toSelect[0]); for (int row : toSelect) { playlistTable.addRowSelectionInterval(row, row); } } }; table.getSelectionModel().addListSelectionListener(listener); table.addKeyboardAction(KeyStroke.getKeyStroke("ESCAPE"), "escape", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { hideDialog(); } }); table.addKeyboardAction(KeyStroke.getKeyStroke("ENTER"), "playSelected", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { playlistTable.runAction("playSelected"); } }); final Player player = Application.getInstance().getPlayer(); table.getActionMap().put("enqueue", new AbstractAction("Add to Queue ") { @Override public void actionPerformed(ActionEvent e) { for (Track track : table.getSelectedSongs()) { PlaybackOrder order = player.getPlaybackOrder(); order.enqueue(track, playlist); } table.update(); playlistTable.update(); } }); table.addKeyboardAction(KeyStroke.getKeyStroke("shift ENTER"), "playAndClose", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { playlistTable.runAction("playSelected"); hideDialog(); } }); timer = new Timer(100, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (searchWorker != null && !searchWorker.isDone()) { searchWorker.cancel(true); } searchWorker = new SearchWorker(playlist, searchField.getText(), false) { @Override protected void done() { try { Playlist result = get(); if (result != null) { viewToModel.clear(); viewToModel.addAll(viewToModelList); view.clear(); view.addAll(result); table.update(); if (result.size() > 0) { table.clearSelection(); table.getSelectionModel().setSelectionInterval(0, 0); } result.clear(); result.trimToSize(); viewToModelList.clear(); viewToModelList.trimToSize(); } } catch (Exception ignored) { } } }; searchWorker.execute(); timer.stop(); } }); searchField.getDocument().addDocumentListener(new DocumentListener() { @Override public void insertUpdate(DocumentEvent e) { filter(); } @Override public void removeUpdate(DocumentEvent e) { filter(); } @Override public void changedUpdate(DocumentEvent e) { filter(); } private void filter() { timer.restart(); } }); searchField.addKeyListener(new KeyAdapter() { @Override public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_DOWN) { searchField.transferFocus(); if (!view.isEmpty()) table.setRowSelectionInterval(0, 0); } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { hideDialog(); } } }); searchField.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { playlistTable.runAction("playSelected"); } }); } private void hideDialog() { table.dispose(); setVisible(false); dispose(); } }