1 package com.melloware.jukes.gui.tool;
2
3 import java.awt.Component;
4 import java.awt.Desktop;
5 import java.awt.EventQueue;
6 import java.awt.Frame;
7 import java.awt.event.ActionEvent;
8 import java.io.File;
9 import java.io.FileInputStream;
10 import java.io.FileOutputStream;
11 import java.io.IOException;
12 import java.net.URI;
13 import java.net.URL;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.Iterator;
18 import java.util.prefs.Preferences;
19
20 import javax.swing.JComponent;
21 import javax.swing.JFileChooser;
22 import javax.swing.JList;
23 import javax.swing.JOptionPane;
24 import javax.swing.JTable;
25 import javax.swing.JTextArea;
26 import javax.swing.JToggleButton;
27 import javax.swing.JTree;
28 import javax.swing.UIManager;
29 import javax.swing.filechooser.FileFilter;
30 import javax.swing.text.JTextComponent;
31 import javax.swing.tree.TreePath;
32
33 import javazoom.jlgui.basicplayer.BasicPlayer;
34 import net.sf.jasperreports.engine.JRException;
35 import net.sf.jasperreports.engine.JasperFillManager;
36 import net.sf.jasperreports.engine.JasperPrint;
37 import net.sf.jasperreports.view.JasperViewer;
38
39 import org.apache.commons.io.FileUtils;
40 import org.apache.commons.lang.StringUtils;
41 import org.apache.commons.lang.SystemUtils;
42 import org.apache.commons.logging.Log;
43 import org.apache.commons.logging.LogFactory;
44 import org.hibernate.HibernateException;
45 import org.hibernate.exception.JDBCConnectionException;
46
47 import com.jgoodies.uif.application.Application;
48 import com.jgoodies.uifextras.convenience.DefaultAboutDialog;
49 import com.jgoodies.uifextras.convenience.SetupManager;
50 import com.jgoodies.uifextras.convenience.TipOfTheDayDialog;
51 import com.l2fprod.common.swing.JDirectoryChooser;
52 import com.melloware.jukes.db.Database;
53 import com.melloware.jukes.db.HibernateDao;
54 import com.melloware.jukes.db.HibernateUtil;
55 import com.melloware.jukes.db.orm.Track;
56 import com.melloware.jukes.exception.InfrastructureException;
57 import com.melloware.jukes.file.FileUtil;
58 import com.melloware.jukes.file.Playlist;
59 import com.melloware.jukes.file.filter.FilterFactory;
60 import com.melloware.jukes.gui.view.FilterPanel;
61 import com.melloware.jukes.gui.view.MainFrame;
62 import com.melloware.jukes.gui.view.PlaylistPanel;
63 import com.melloware.jukes.gui.view.component.AlbumImage;
64 import com.melloware.jukes.gui.view.dialogs.DifferenceToolDialog;
65 import com.melloware.jukes.gui.view.dialogs.DiscAddDialog;
66 import com.melloware.jukes.gui.view.dialogs.DiscFindDialog;
67 import com.melloware.jukes.gui.view.dialogs.DiscRemoveDialog;
68 import com.melloware.jukes.gui.view.dialogs.LocationChangeDialog;
69 import com.melloware.jukes.gui.view.dialogs.MemoryDialog;
70 import com.melloware.jukes.gui.view.dialogs.SearchDialog;
71 import com.melloware.jukes.gui.view.dialogs.SearchTableModel;
72 import com.melloware.jukes.gui.view.dialogs.StatisticsDialog;
73 import com.melloware.jukes.gui.view.editor.AbstractEditor;
74 import com.melloware.jukes.gui.view.node.AbstractTreeNode;
75 import com.melloware.jukes.gui.view.preferences.PreferencesDialog;
76 import com.melloware.jukes.util.GuiUtil;
77 import com.melloware.jukes.util.JukesValidationMessage;
78 import com.melloware.jukes.util.MessageUtil;
79
80
81
82
83
84
85
86
87
88
89 public final class MainController {
90
91 private static final Log LOG = LogFactory.getLog(MainController.class);
92 private static final String LINE_BREAK = "\n\n";
93 private static final String ERROR_WRITING_FILE = "Error writing file: ";
94 private static final String ERROR_URL = " Enter this url in your browser: ";
95
96
97
98
99
100
101 private final MainModule mainModule;
102
103
104
105
106
107
108
109
110
111
112 public MainController(final MainModule mainModule) {
113 this.mainModule = mainModule;
114
115 }
116
117
118
119
120
121
122 @SuppressWarnings("deprecation")
123 public void backupTool(final ActionEvent aEvent) {
124 LOG.debug("Backup Database");
125 if (MessageUtil.confirmBackup(getDefaultParentFrame())) {
126 final File zip = MainModule.SETTINGS.getFileBackup();
127
128 Database.backupDatabase(HibernateUtil.getSession().connection(), zip.getAbsolutePath());
129
130 MessageUtil.showTaskCompleted(getDefaultParentFrame());
131 }
132
133 }
134
135
136
137
138
139
140
141
142
143 public void checkForOpenTipOfTheDayDialog() {
144 if ((SetupManager.usageCount() > 1) && (TipOfTheDayDialog.isShowingTips())) {
145 EventQueue.invokeLater(new Runnable() {
146 public void run() {
147 openTipOfTheDayDialog();
148 }
149 });
150 }
151 }
152
153
154
155
156
157
158 public void chooseDirectory(final ActionEvent aEvent) {
159 final JComponent button = (JComponent) aEvent.getSource();
160 final JTextComponent text = (JTextComponent) button.getClientProperty(Resources.TEXT_COMPONENT);
161 final JDirectoryChooser chooser = new JDirectoryChooser();
162 final JTextArea accessory = new JTextArea("Select Directory");
163 chooser.setSelectedFile(new File(text.getText()));
164 accessory.setLineWrap(true);
165 accessory.setWrapStyleWord(true);
166 accessory.setEditable(false);
167 accessory.setOpaque(false);
168 accessory.setFont(UIManager.getFont("Tree.font"));
169 chooser.setAccessory(accessory);
170 chooser.setMultiSelectionEnabled(false);
171
172 final int choice = chooser.showOpenDialog(button);
173 if (choice == JDirectoryChooser.APPROVE_OPTION) {
174 final File dir = chooser.getSelectedFile();
175 LOG.debug("Directory selected: " + dir.getAbsolutePath());
176 text.setText(dir.getAbsolutePath());
177 }
178 }
179
180
181
182
183
184
185 public void chooseFile(final ActionEvent aEvent) {
186 final JComponent button = (JComponent) aEvent.getSource();
187 final JTextComponent text = (JTextComponent) button.getClientProperty(Resources.TEXT_COMPONENT);
188 final JFileChooser chooser = new JFileChooser();
189 chooser.setDialogTitle((String) button.getClientProperty(Resources.FILE_CHOOSER_TITLE));
190 chooser.setFileFilter((FileFilter) button.getClientProperty(Resources.FILE_CHOOSER_FILTER));
191 chooser.setMultiSelectionEnabled(false);
192 chooser.setFileHidingEnabled(true);
193 final int returnVal = chooser.showOpenDialog(this.getDefaultParentFrame());
194 if (returnVal != JFileChooser.APPROVE_OPTION) {
195 return;
196 }
197 final File file = chooser.getSelectedFile();
198 text.setText(file.getAbsolutePath());
199 if (LOG.isDebugEnabled()) {
200 LOG.debug(file.getAbsolutePath());
201
202 }
203 }
204
205
206
207
208
209
210 public void commit(final ActionEvent aEvent) {
211 LOG.debug("Commit Changes");
212 final JComponent button = (JComponent) aEvent.getSource();
213 final AbstractEditor editor = (AbstractEditor) button.getClientProperty(Resources.EDITOR_COMPONENT);
214 editor.commit();
215 }
216
217
218
219
220
221
222 @SuppressWarnings("deprecation")
223 public void connect(final ActionEvent aEvent) {
224 LOG.debug("Connecting to database.");
225 try {
226
227 HibernateUtil.shutdown();
228 Database.shutdown();
229
230
231 String dbLocation = MainModule.SETTINGS.getDatabaseLocation().getAbsolutePath();
232 dbLocation = dbLocation + SystemUtils.FILE_SEPARATOR + Resources.APPLICATION_LOCATION;
233
234
235 Database.startup(dbLocation, Resources.APPLICATION_LOCATION);
236
237
238 HibernateUtil.initialize();
239 HibernateUtil.getSession().clear();
240
241
242 Database.setWriteDelay(HibernateUtil.getSession().connection(), "FALSE");
243
244
245 getMainModule().refreshTree();
246 } catch (JDBCConnectionException ex) {
247 LOG.error("Not a valid connection URL. Please try another URL.");
248 } catch (Exception ex) {
249 LOG.error("Error trying to connect to the database.", ex);
250 System.exit(1);
251 }
252 }
253
254
255
256
257
258
259 public void contactUs(final ActionEvent aEvent) {
260 LOG.debug("Contact Us");
261 try {
262 if (Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
263 Desktop.getDesktop().browse(new URI(Resources.APPLICATION_URL));
264 }
265 } catch (UnsupportedOperationException ex) {
266 LOG.warn(ex.getMessage() + LINE_BREAK + ERROR_URL + Resources.APPLICATION_URL);
267 } catch (Exception ex) {
268 LOG.warn(ex.getMessage() + LINE_BREAK + ERROR_URL + Resources.APPLICATION_URL);
269 }
270 }
271
272
273
274
275
276
277
278 public void delete(final ActionEvent aEvent) {
279 LOG.debug("Delete Item");
280 final JComponent source = (JComponent) aEvent.getSource();
281 final Object editor = (Object) source.getClientProperty(Resources.EDITOR_COMPONENT);
282 if (editor == null) {
283 return;
284 }
285
286 if (editor instanceof AbstractEditor) {
287 ((AbstractEditor) editor).delete();
288 } else if (editor instanceof JTree) {
289 final JTree tree = (JTree) editor;
290 final TreePath path = tree.getSelectionPath();
291
292
293 if (path.getLastPathComponent() instanceof AbstractTreeNode) {
294 LOG.debug("Tree Node Delete");
295 ((AbstractTreeNode) path.getLastPathComponent()).delete();
296 }
297 }
298
299 }
300
301
302
303
304
305
306 public void differenceTool(final ActionEvent aEvent) {
307 LOG.debug("Difference Tool Dialog");
308 new DifferenceToolDialog(getDefaultParentFrame(), MainModule.SETTINGS).open();
309
310 }
311
312
313
314
315
316
317 public void discAdd(final ActionEvent aEvent) {
318 LOG.debug("Add New Disc");
319 final JFileChooser openDialog = new JFileChooser();
320 openDialog.setDialogTitle("Add New Disc");
321 final File currentDir = MainModule.SETTINGS.getStartInDirectory();
322 openDialog.setCurrentDirectory(currentDir);
323 openDialog.setFileFilter(FilterFactory.musicFileFilter());
324 openDialog.setMultiSelectionEnabled(false);
325 openDialog.setSelectedFile(null);
326 final int returnVal = openDialog.showOpenDialog(this.getDefaultParentFrame());
327 if (returnVal != JFileChooser.APPROVE_OPTION) {
328 return;
329 }
330 final File file = openDialog.getSelectedFile();
331
332 LOG.debug(file.getAbsolutePath());
333
334 new DiscAddDialog(getDefaultParentFrame(), MainModule.SETTINGS, file).open();
335 }
336
337
338
339
340
341
342 public void discAddComments(final ActionEvent aEvent) {
343 LOG.debug("Update comments all at once.");
344 final JComponent button = (JComponent) aEvent.getSource();
345 final Object editor = (Object) button.getClientProperty(Resources.EDITOR_COMPONENT);
346 if ((editor != null) && (editor instanceof DiscAddDialog)) {
347 ((DiscAddDialog) editor).updateComments();
348 }
349 }
350
351
352
353
354
355
356 public void discAddResetFromFilename(final ActionEvent aEvent) {
357 LOG.debug("Reset Titles from filenames.");
358 final JComponent button = (JComponent) aEvent.getSource();
359 final Object editor = (Object) button.getClientProperty(Resources.EDITOR_COMPONENT);
360 if ((editor != null) && (editor instanceof DiscAddDialog)) {
361 ((DiscAddDialog) editor).resetFromFilenames();
362 }
363 }
364
365
366
367
368
369
370 public void discAddResetTrackNumbers(final ActionEvent aEvent) {
371 LOG.debug("Reset Track Numbers.");
372 final JComponent button = (JComponent) aEvent.getSource();
373 final Object editor = (Object) button.getClientProperty(Resources.EDITOR_COMPONENT);
374 if ((editor != null) && (editor instanceof DiscAddDialog)) {
375 ((DiscAddDialog) editor).resetTrackNumbers();
376 }
377 }
378
379
380
381
382
383
384 public void discAddTitleCase(final ActionEvent aEvent) {
385 LOG.debug("Title case all tracks.");
386 final JComponent button = (JComponent) aEvent.getSource();
387 final Object editor = (Object) button.getClientProperty(Resources.EDITOR_COMPONENT);
388 if ((editor != null) && (editor instanceof DiscAddDialog)) {
389 ((DiscAddDialog) editor).titleCase();
390 }
391 }
392
393
394
395
396
397
398 public void discCoverImage(final ActionEvent aEvent) {
399 LOG.debug("Finding new cover image");
400 final JComponent button = (JComponent) aEvent.getSource();
401
402 final Object editor = (Object) button.getClientProperty(Resources.EDITOR_COMPONENT);
403 LOG.debug(editor);
404 if (editor != null) {
405 if (editor instanceof AbstractEditor) {
406 ((AbstractEditor) editor).findCover();
407 } else if (editor instanceof DiscAddDialog) {
408 ((DiscAddDialog) editor).findCover();
409 }
410 }
411 }
412
413
414
415
416
417
418 public void discFinder(final ActionEvent aEvent) {
419 LOG.debug("Disc Finder Dialog");
420 new DiscFindDialog(getDefaultParentFrame(), MainModule.SETTINGS).open();
421 }
422
423
424
425
426
427
428 public void discRemover(final ActionEvent aEvent) {
429 LOG.debug("Disc Remover Dialog");
430 new DiscRemoveDialog(getDefaultParentFrame()).open();
431 }
432
433
434
435
436
437
438 public void discWebSearch(final ActionEvent aEvent) {
439 LOG.debug("Web Search");
440 final JComponent button = (JComponent) aEvent.getSource();
441 final Object editor = (Object) button.getClientProperty(Resources.EDITOR_COMPONENT);
442 if (editor != null) {
443 if (editor instanceof AbstractEditor) {
444 ((AbstractEditor) editor).webSearch();
445 } else if (editor instanceof DiscAddDialog) {
446 ((DiscAddDialog) editor).webSearch();
447 }
448 }
449 }
450
451
452
453
454 public void donate() {
455 try {
456 if (Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
457 Desktop.getDesktop().browse(new URL(Resources.APPLICATION_DONATE_URL).toURI());
458 }
459 } catch (UnsupportedOperationException ex) {
460 LOG.warn(ex.getMessage() + LINE_BREAK + ERROR_URL + Resources.APPLICATION_DONATE_URL);
461 } catch (Exception ex) {
462 LOG.warn(ex.getMessage() + LINE_BREAK + ERROR_URL + Resources.APPLICATION_DONATE_URL);
463 }
464 }
465
466
467
468
469
470
471 @SuppressWarnings("unchecked")
472 public void exportCatalog(final ActionEvent aEvent) {
473 LOG.debug("Export Catalog");
474 final JFileChooser chooser = new JFileChooser();
475 chooser.setDialogTitle("Export Catalog");
476 chooser.setFileFilter(FilterFactory.textFileFilter());
477 chooser.setMultiSelectionEnabled(false);
478 chooser.setFileHidingEnabled(true);
479 final int returnVal = chooser.showSaveDialog(this.getDefaultParentFrame());
480 if (returnVal != JFileChooser.APPROVE_OPTION) {
481 return;
482 }
483 File file = chooser.getSelectedFile();
484 if (LOG.isDebugEnabled()) {
485 LOG.debug(file.getAbsolutePath());
486 }
487
488
489 file = FilterFactory.forceTextExtension(file);
490
491 try {
492
493 final ArrayList results = new ArrayList();
494 final Collection discs = HibernateDao.findByQuery(Resources.getString("hql.export.catalog"));
495
496 for (final Iterator iter = discs.iterator(); iter.hasNext();) {
497 final Object[] disc = (Object[]) iter.next();
498
499 results.add(disc[0] + Resources.TAB + disc[1]);
500 }
501
502 FileUtils.writeLines(file, null, results);
503
504 MessageUtil.showInformation(getDefaultParentFrame(), "Catalog exported successfully.");
505 } catch (IOException ex) {
506 LOG.error(ERROR_WRITING_FILE + LINE_BREAK + ex.getMessage(), ex);
507 } catch (InfrastructureException ex) {
508 LOG.error(ERROR_WRITING_FILE + LINE_BREAK + ex.getMessage(), ex);
509 } catch (Exception ex) {
510 LOG.error("Unexpected error writing file.", ex);
511 }
512 }
513
514
515
516
517
518
519 public void fileRename(final ActionEvent aEvent) {
520 LOG.debug("Renaming File");
521 final JComponent button = (JComponent) aEvent.getSource();
522 final Object editor = (Object) button.getClientProperty(Resources.EDITOR_COMPONENT);
523 if (editor != null) {
524 if (editor instanceof AbstractEditor) {
525 ((AbstractEditor) editor).renameFiles();
526 } else if (editor instanceof DiscAddDialog) {
527 ((DiscAddDialog) editor).renameFiles();
528 }
529 }
530 }
531
532
533
534
535
536
537 public void filter(final ActionEvent aEvent) {
538 LOG.debug("Filter applied.");
539 final JToggleButton button = (JToggleButton) aEvent.getSource();
540 final FilterPanel editor = (FilterPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
541 if (button.isSelected()) {
542 LOG.debug("Button Selected");
543 editor.applyFilter();
544 } else {
545 LOG.debug("Button Deselected");
546 editor.removeFilter();
547 }
548 }
549
550
551
552
553
554
555 public void filterClear(final ActionEvent aEvent) {
556 LOG.debug("Filter cleared.");
557 final JComponent button = (JComponent) aEvent.getSource();
558 final FilterPanel editor = (FilterPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
559 editor.clearFilter();
560
561 }
562
563
564
565
566
567
568 public void filterClose(final ActionEvent aEvent) {
569 LOG.debug("Close Filter.");
570 getMainFrame().getMainPageBuilder().setFilterVisible(false);
571 }
572
573
574
575
576
577
578 public void filterDisplay(final ActionEvent aEvent) {
579 LOG.debug("Filter displayed/hidden.");
580 final boolean visible = !getMainFrame().getMainPageBuilder().isFilterVisible();
581 getMainFrame().getMainPageBuilder().setFilterVisible(visible);
582 }
583
584
585
586
587 public void forums() {
588 try {
589 if (Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
590 Desktop.getDesktop().browse(new URI(Resources.APPLICATION_FORUMS_URL));
591 }
592 } catch (UnsupportedOperationException ex) {
593 LOG.warn(ex.getMessage() + LINE_BREAK + ERROR_URL + Resources.APPLICATION_FORUMS_URL);
594 } catch (Exception ex) {
595 LOG.warn(ex.getMessage() + LINE_BREAK + ERROR_URL + Resources.APPLICATION_FORUMS_URL);
596 }
597 }
598
599
600
601
602 public void hideMainWindow() {
603 if (SystemUtils.IS_OS_WINDOWS) {
604 final MainFrame mainframe = (MainFrame) getDefaultParentFrame();
605 mainframe.getTrayIcon().hideWindow();
606 }
607 }
608
609
610
611
612
613
614
615 public void language(final ActionEvent aEvent, final String aLanguage) {
616 LOG.debug("Language change to " + aLanguage);
617
618
619 MainModule.SETTINGS.setLocale(aLanguage);
620 getMainModule().storeState();
621 MessageUtil.showInformation(getDefaultParentFrame(), Resources.getString("messages.update.language"));
622 }
623
624
625
626
627
628
629 public void locationTool(final ActionEvent aEvent) {
630 LOG.debug("Location Tool Dialog");
631 new LocationChangeDialog(getDefaultParentFrame(), MainModule.SETTINGS).open();
632 }
633
634
635
636
637
638
639 public void memory(final ActionEvent aEvent) {
640 LOG.debug("Memory Dialog");
641 new MemoryDialog(getDefaultParentFrame()).open();
642
643 }
644
645
646
647
648
649
650 public void playerNext(final ActionEvent aEvent) {
651 LOG.debug("Player Next");
652 final Runnable update = new Runnable() {
653 public void run() {
654 final Playlist playlist = getMainFrame().getPlaylist();
655 if (playlist.hasNext()) {
656 final Track track = (Track) playlist.getNext();
657 if (track.isValid()) {
658 getMainFrame().getPlayer().play(track.getTrackUrl());
659 }
660
661 }
662 }
663 };
664 EventQueue.invokeLater(update);
665 }
666
667
668
669
670
671
672 public void playerPause(final ActionEvent aEvent) {
673 LOG.debug("Player Pause/Resume");
674 final Runnable update = new Runnable() {
675 public void run() {
676 final MainFrame mainFrame = (MainFrame) getDefaultParentFrame();
677 mainFrame.getPlayer().pause();
678 }
679 };
680 EventQueue.invokeLater(update);
681 }
682
683
684
685
686
687
688 public void playerPlay(final ActionEvent aEvent) {
689 LOG.debug("Player Play");
690 final Runnable update = new Runnable() {
691 public void run() {
692 final MainFrame mainFrame = (MainFrame) getDefaultParentFrame();
693 LOG.debug("Status: " + mainFrame.getPlayer().getStatus());
694 if (mainFrame.getPlayer().getStatus() == -1) {
695 playerNext(null);
696 } else {
697 mainFrame.getPlayer().play();
698 }
699 }
700 };
701 EventQueue.invokeLater(update);
702
703 }
704
705
706
707
708
709
710 public void playerPrevious(final ActionEvent aEvent) {
711 LOG.debug("Player Previous");
712 final Runnable update = new Runnable() {
713 public void run() {
714 final Playlist playlist = getMainFrame().getPlaylist();
715 if (playlist.hasPrevious()) {
716 final Track trackCurrent = (Track) playlist.getPrevious();
717
718
719 if (getMainFrame().getPlayer().getElapsedTime() > 2000) {
720 LOG.debug("Player Previous: REPLAY current song");
721 playerNext(null);
722 } else {
723 final Track trackPrevious = (Track) playlist.getPrevious();
724 if ((trackPrevious != null) && (trackPrevious.isValid())) {
725 LOG.debug("Player Previous: PLAY previous song in playlist");
726 playerNext(null);
727 } else if ((trackCurrent != null) && (trackCurrent.isValid())) {
728 playerNext(null);
729 }
730 }
731 }
732 }
733 };
734 EventQueue.invokeLater(update);
735
736 }
737
738
739
740
741
742
743 public void playerStop(final ActionEvent aEvent) {
744 LOG.debug("Player Stop");
745 final Runnable update = new Runnable() {
746 public void run() {
747 MainFrame mainFrame = (MainFrame) getDefaultParentFrame();
748 mainFrame.getPlayer().stop();
749 }
750 };
751 EventQueue.invokeLater(update);
752 }
753
754
755
756
757
758
759 public void playImmediately(final ActionEvent aEvent) {
760 LOG.debug("Play Immediately");
761 final JComponent source = (JComponent) aEvent.getSource();
762 final Object editor = (Object) source.getClientProperty(Resources.EDITOR_COMPONENT);
763 final Runnable update = new Runnable() {
764 public void run() {
765
766 if (editor != null) {
767 final Player player = getMainFrame().getPlayer();
768 final Playlist playlist = getMainFrame().getPlaylist();
769 if (editor instanceof JTree) {
770 final JTree tree = (JTree) editor;
771 for (int i = 0; i < tree.getSelectionPaths().length; i++) {
772 final TreePath path = tree.getSelectionPaths()[i];
773 if (path.getLastPathComponent() instanceof AbstractTreeNode) {
774 final AbstractTreeNode node = (AbstractTreeNode) path.getLastPathComponent();
775 playlist.addNext(node.getModel());
776 }
777 }
778 }
779 if (editor instanceof JList) {
780 final JList list = (JList) editor;
781 final Object[] selections = list.getSelectedValues();
782 for (int i = selections.length - 1; i >= 0; i--) {
783 Track track = null;
784 if (selections[i] instanceof JukesValidationMessage) {
785 final JukesValidationMessage message = (JukesValidationMessage) selections[i];
786 track = (Track) message.getDomainObject();
787 playlist.addNext(track);
788 } else if (selections[i] instanceof Track) {
789 track = (Track) selections[i];
790 playlist.addNext(track);
791 }
792 }
793 }
794 if (editor instanceof JTable) {
795 final JTable table = (JTable) editor;
796 final int[] selections = table.getSelectedRows();
797 final SearchTableModel model = (SearchTableModel) table.getModel();
798 for (int i = 0; i < selections.length; i++) {
799 int selectedRow = selections[i];
800 selectedRow = table.getRowSorter().convertRowIndexToModel(selectedRow);
801 Track track = (Track) model.getData()[selectedRow];
802 playlist.addNext(track);
803 }
804 }
805 if (editor instanceof AlbumImage) {
806 final AlbumImage image = (AlbumImage) editor;
807 if (image.getDisc() != null) {
808 playlist.addNext(image.getDisc());
809 }
810 }
811 final Track next = (Track) playlist.getNextImmediate();
812 if (next != null) {
813 player.play(next.getTrackUrl());
814 }
815
816 }
817 }
818 };
819 EventQueue.invokeLater(update);
820 }
821
822
823
824
825
826
827 public void playlistClose(final ActionEvent aEvent) {
828 LOG.debug("Close Playlist.");
829 getMainFrame().getMainPageBuilder().setPlaylistVisible(false);
830
831 }
832
833
834
835
836
837
838 public void playlistDisplay(final ActionEvent aEvent) {
839 LOG.debug("Playlist displayed/hidden.");
840 final boolean visible = !getMainFrame().getMainPageBuilder().isPlaylistVisible();
841 getMainFrame().getMainPageBuilder().setPlaylistVisible(visible);
842
843 }
844
845
846
847
848
849
850 public void playlistGoto(final ActionEvent aEvent) {
851 LOG.debug("Playlist goto.");
852 final JComponent button = (JComponent) aEvent.getSource();
853 final JList editor = (JList) button.getClientProperty(Resources.EDITOR_COMPONENT);
854 try {
855 GuiUtil.setBusyCursor(getDefaultParentFrame(), true);
856 if (editor.getSelectedValue() != null) {
857 getMainModule().selectNodeInTree(editor.getSelectedValue());
858 }
859 } finally {
860 GuiUtil.setBusyCursor(getDefaultParentFrame(), false);
861 }
862 }
863
864
865
866
867
868
869 public void playlistLoad(final ActionEvent aEvent) {
870 LOG.debug("Load Playlist");
871 final JComponent button = (JComponent) aEvent.getSource();
872 final PlaylistPanel editor = (PlaylistPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
873 editor.load();
874 }
875
876
877
878
879
880
881 public void playlistMoveDown(final ActionEvent aEvent) {
882 LOG.debug("Move down playlist");
883 final JComponent button = (JComponent) aEvent.getSource();
884 final PlaylistPanel editor = (PlaylistPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
885 editor.moveDown();
886
887 }
888
889
890
891
892
893
894 public void playlistMoveOver(final ActionEvent aEvent) {
895 LOG.debug("Move over playlist");
896 final JComponent button = (JComponent) aEvent.getSource();
897 final PlaylistPanel editor = (PlaylistPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
898 editor.moveOver();
899
900 }
901
902
903
904
905
906
907 public void playlistMoveUp(final ActionEvent aEvent) {
908 LOG.debug("Move up playlist");
909 final JComponent button = (JComponent) aEvent.getSource();
910 final PlaylistPanel editor = (PlaylistPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
911 editor.moveUp();
912 }
913
914
915
916
917
918
919 public void playlistRemoveTracks(final ActionEvent aEvent) {
920 LOG.debug("Remove tracks from playlist");
921 final JComponent button = (JComponent) aEvent.getSource();
922 final PlaylistPanel editor = (PlaylistPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
923 editor.removeTracks();
924 getMainFrame().getMainPageBuilder().refreshUI();
925 }
926
927
928
929
930
931
932 public void playlistClear(ActionEvent aEvent) {
933 LOG.debug("Clear tracks from playlist");
934 final JComponent button = (JComponent) aEvent.getSource();
935 final PlaylistPanel editor = (PlaylistPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
936 editor.removeAllTracks();
937 getMainFrame().getMainPageBuilder().refreshUI();
938
939 }
940
941
942
943
944
945
946 public void playlistSave(final ActionEvent aEvent) {
947 LOG.debug("Save playlist.");
948 final JComponent button = (JComponent) aEvent.getSource();
949 final PlaylistPanel editor = (PlaylistPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
950 editor.save();
951 }
952
953
954
955
956
957
958 public void playlistShuffleCatalog(final ActionEvent aEvent) {
959 LOG.debug("Shuffle catalog.");
960 final JToggleButton button = (JToggleButton) aEvent.getSource();
961 final PlaylistPanel editor = (PlaylistPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
962 editor.shuffleCatalog(button.isSelected());
963
964 if (button.isSelected()) {
965 final Player player = getMainFrame().getPlayer();
966
967 if ((player.getStatus() == BasicPlayer.STOPPED) || (player.getStatus() == BasicPlayer.UNKNOWN)) {
968 playerNext(null);
969 }
970 }
971 }
972
973
974
975
976
977
978 public void playlistShuffleList(final ActionEvent aEvent) {
979 LOG.debug("Shuffle playlist.");
980 final JToggleButton button = (JToggleButton) aEvent.getSource();
981 final PlaylistPanel editor = (PlaylistPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
982 editor.shufflePlaylist(button.isSelected());
983 }
984
985
986
987
988
989
990 public void playlistToggle(final ActionEvent aEvent) {
991 LOG.debug("Toggle playlist.");
992 final JToggleButton button = (JToggleButton) aEvent.getSource();
993 final PlaylistPanel editor = (PlaylistPanel) button.getClientProperty(Resources.EDITOR_COMPONENT);
994 editor.toggle(!button.isSelected());
995 }
996
997
998
999
1000
1001
1002 public void preferencesExport(final ActionEvent aEvent) {
1003 LOG.debug("Export Preferences");
1004 final JFileChooser chooser = new JFileChooser();
1005 chooser.setDialogTitle("Export Preferences");
1006 chooser.setFileFilter(FilterFactory.xmlFileFilter());
1007 chooser.setMultiSelectionEnabled(false);
1008 chooser.setFileHidingEnabled(true);
1009 final int returnVal = chooser.showSaveDialog(this.getDefaultParentFrame());
1010 if (returnVal != JFileChooser.APPROVE_OPTION) {
1011 return;
1012 }
1013 File file = chooser.getSelectedFile();
1014 if (LOG.isDebugEnabled()) {
1015 LOG.debug(file.getAbsolutePath());
1016 }
1017
1018
1019 file = FilterFactory.forceXmlExtension(file);
1020
1021
1022 try {
1023 final Preferences prefs = Application.getUserPreferences();
1024 final FileOutputStream stream = new FileOutputStream(file);
1025 prefs.exportSubtree(stream);
1026
1027 MessageUtil.showInformation(getDefaultParentFrame(), "Preferences exported successfully.");
1028 } catch (IOException ex) {
1029 LOG.error(ERROR_WRITING_FILE + LINE_BREAK + ex, ex);
1030 } catch (Exception ex) {
1031 LOG.error("Unexpected error writing file.", ex);
1032 }
1033 }
1034
1035
1036
1037
1038
1039
1040 public void preferencesImport(final ActionEvent aEvent) {
1041 LOG.debug("Import Preferences");
1042 final JFileChooser chooser = new JFileChooser();
1043 chooser.setDialogTitle("Import Preferences");
1044 chooser.setFileFilter(FilterFactory.xmlFileFilter());
1045 chooser.setMultiSelectionEnabled(false);
1046 chooser.setFileHidingEnabled(true);
1047 final int returnVal = chooser.showOpenDialog(this.getDefaultParentFrame());
1048 if (returnVal != JFileChooser.APPROVE_OPTION) {
1049 return;
1050 }
1051 final File file = chooser.getSelectedFile();
1052 if (LOG.isDebugEnabled()) {
1053 LOG.debug(file.getAbsolutePath());
1054 }
1055
1056
1057 try {
1058 final FileInputStream stream = new FileInputStream(file);
1059 Preferences.importPreferences(stream);
1060 MainModule.SETTINGS.restoreFrom(Application.getUserPreferences());
1061
1062 MessageUtil.showInformation(getDefaultParentFrame(), "Preferences imported successfully.");
1063 } catch (IOException ex) {
1064 LOG.error(ERROR_WRITING_FILE + LINE_BREAK + ex.getMessage(), ex);
1065 } catch (Exception ex) {
1066 LOG.error("Unexpected error writing file.", ex);
1067 }
1068 }
1069
1070
1071
1072
1073
1074
1075 public void queue(final ActionEvent aEvent) {
1076 LOG.debug("Queue");
1077 final JComponent source = (JComponent) aEvent.getSource();
1078 final Component editor = (Component) source.getClientProperty(Resources.EDITOR_COMPONENT);
1079 if (editor != null) {
1080 final Player player = getMainFrame().getPlayer();
1081 final Playlist playlist = getMainFrame().getPlaylist();
1082
1083
1084
1085 final boolean startPlaying = (playlist.sizeNext() == 0);
1086
1087 if (editor instanceof JTree) {
1088 final JTree tree = (JTree) editor;
1089 for (int i = 0; i < tree.getSelectionPaths().length; i++) {
1090 final TreePath path = tree.getSelectionPaths()[i];
1091 if (path.getLastPathComponent() instanceof AbstractTreeNode) {
1092 final AbstractTreeNode node = (AbstractTreeNode) path.getLastPathComponent();
1093 playlist.add(node.getModel());
1094 }
1095 }
1096 }
1097 if (editor instanceof JList) {
1098 final JList list = (JList) editor;
1099 final Object[] selections = list.getSelectedValues();
1100 for (int i = 0; i < selections.length; i++) {
1101 final JukesValidationMessage message = (JukesValidationMessage) selections[i];
1102 playlist.add(message.getDomainObject());
1103 }
1104 }
1105 if (editor instanceof JTable) {
1106 final JTable table = (JTable) editor;
1107 final int[] selections = table.getSelectedRows();
1108 final SearchTableModel model = (SearchTableModel) table.getModel();
1109 for (int i = 0; i < selections.length; i++) {
1110 int selectedRow = selections[i];
1111 selectedRow = table.getRowSorter().convertRowIndexToModel(selectedRow);
1112 playlist.add(model.getData()[selectedRow]);
1113 }
1114 }
1115 if (editor instanceof AlbumImage) {
1116 final AlbumImage image = (AlbumImage) editor;
1117 if (image.getDisc() != null) {
1118 playlist.add(image.getDisc());
1119 }
1120 }
1121
1122
1123 if (((player.getStatus() == BasicPlayer.STOPPED) || (player.getStatus() == BasicPlayer.UNKNOWN))
1124 && (startPlaying)) {
1125 playerNext(null);
1126 }
1127 getMainFrame().getMainPageBuilder().refreshUI();
1128 }
1129 }
1130
1131
1132
1133
1134
1135
1136 public void queueNext(final ActionEvent aEvent) {
1137 LOG.debug("Queue Next");
1138 final JComponent source = (JComponent) aEvent.getSource();
1139 final Component editor = (Component) source.getClientProperty(Resources.EDITOR_COMPONENT);
1140 if (editor != null) {
1141 final Player player = getMainFrame().getPlayer();
1142 final Playlist playlist = getMainFrame().getPlaylist();
1143
1144
1145
1146 final boolean startPlaying = (playlist.sizeNext() == 0);
1147
1148 if (editor instanceof JTree) {
1149 final JTree tree = (JTree) editor;
1150 for (int i = tree.getSelectionPaths().length - 1; i >= 0; i--) {
1151 final TreePath path = tree.getSelectionPaths()[i];
1152 if (path.getLastPathComponent() instanceof AbstractTreeNode) {
1153 final AbstractTreeNode node = (AbstractTreeNode) path.getLastPathComponent();
1154 playlist.addNext(node.getModel());
1155 }
1156 }
1157 }
1158 if (editor instanceof JList) {
1159 final JList list = (JList) editor;
1160 final Object[] selections = list.getSelectedValues();
1161 for (int i = selections.length - 1; i >= 0; i--) {
1162 final JukesValidationMessage message = (JukesValidationMessage) selections[i];
1163 playlist.addNext(message.getDomainObject());
1164 }
1165 }
1166 if (editor instanceof JTable) {
1167 final JTable table = (JTable) editor;
1168 final int[] selections = table.getSelectedRows();
1169 final SearchTableModel model = (SearchTableModel) table.getModel();
1170 for (int i = 0; i < selections.length; i++) {
1171 int selectedRow = selections[i];
1172 selectedRow = table.getRowSorter().convertRowIndexToModel(selectedRow);
1173 playlist.addNext(model.getData()[selectedRow]);
1174 }
1175 }
1176 if (editor instanceof AlbumImage) {
1177 final AlbumImage image = (AlbumImage) editor;
1178 if (image.getDisc() != null) {
1179 playlist.addNext(image.getDisc());
1180 }
1181 }
1182
1183
1184 if (((player.getStatus() == BasicPlayer.STOPPED) || (player.getStatus() == BasicPlayer.UNKNOWN))
1185 && (startPlaying)) {
1186 playerNext(null);
1187 }
1188
1189 getMainFrame().getMainPageBuilder().refreshUI();
1190 }
1191 }
1192
1193
1194
1195
1196
1197
1198 public void refresh(final ActionEvent aEvent) {
1199 LOG.debug("Refreshing Data.");
1200 GuiUtil.setBusyCursor(getDefaultParentFrame(), true);
1201
1202
1203
1204
1205 getMainModule().refreshTree();
1206 GuiUtil.setBusyCursor(getDefaultParentFrame(), false);
1207 }
1208
1209
1210
1211
1212
1213
1214 public void rollback(final ActionEvent aEvent) {
1215 LOG.debug(