Source code: com/virtuosotechnologies/asaph/maingui/CommandManagerImpl.java
1 /*
2 ================================================================================
3
4 FILE: CommandManagerImpl.java
5
6 PROJECT:
7
8 Asaph
9
10 CONTENTS:
11
12 Implementation of main menu commands
13
14 PROGRAMMERS:
15
16 Daniel Azuma (DA) <dazuma@kagi.com>
17
18 COPYRIGHT:
19
20 Copyright (C) 2003 Daniel Azuma (dazuma@kagi.com)
21
22 This program is free software; you can redistribute it and/or
23 modify it under the terms of the GNU General Public License as
24 published by the Free Software Foundation; either version 2
25 of the License, or (at your option) any later version.
26
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
31
32 You should have received a copy of the GNU General Public
33 License along with this program; if not, write to
34 Free Software Foundation, Inc.
35 59 Temple Place, Suite 330
36 Boston, MA 02111-1307 USA
37
38 ================================================================================
39 */
40
41
42 package com.virtuosotechnologies.asaph.maingui;
43
44
45 import java.util.Iterator;
46 import java.util.Set;
47 import java.util.List;
48 import java.util.ArrayList;
49 import javax.swing.JComponent;
50 import javax.swing.JOptionPane;
51
52 import com.virtuosotechnologies.lib.command.CommandEvent;
53 import com.virtuosotechnologies.lib.command.CommandNode;
54 import com.virtuosotechnologies.lib.basiccommand.BasicCommandNode;
55 import com.virtuosotechnologies.lib.basiccommand.BasicContainerCommandNode;
56 import com.virtuosotechnologies.lib.basiccommand.BasicGroupCommandNode;
57 import com.virtuosotechnologies.lib.basiccommand.BasicItemCommandNode;
58 import com.virtuosotechnologies.lib.basiccommand.BasicSeparatorCommandNode;
59 import com.virtuosotechnologies.lib.platform.PlatformListener;
60 import com.virtuosotechnologies.lib.platform.PlatformEvent;
61 import com.virtuosotechnologies.lib.platform.PlatformUtils;
62 import com.virtuosotechnologies.lib.swing.DetailedMessageDialog;
63 import com.virtuosotechnologies.lib.swing.SwingUtils;
64 import com.virtuosotechnologies.lib.util.ExceptionUtils;
65 import com.virtuosotechnologies.lib.util.ObjectUtils;
66 import com.virtuosotechnologies.lib.propertyset.PropertySet;
67
68 import com.virtuosotechnologies.asaph.model.Song;
69 import com.virtuosotechnologies.asaph.model.SongID;
70 import com.virtuosotechnologies.asaph.model.SongDatabase;
71 import com.virtuosotechnologies.asaph.model.SongDatabaseFailedException;
72 import com.virtuosotechnologies.asaph.modelutils.SongUtils;
73 import com.virtuosotechnologies.asaph.launch.Launcher;
74
75
76 /**
77 * Implementation of main menu commands
78 */
79 /*package*/ class CommandManagerImpl
80 implements CommandManager
81 {
82 private static final String STR_Menu_Database_GetInfoUnnamedItem =
83 ResourceAccess.Strings.buildString("Menu_Database_GetInfoUnnamedItem");
84 private static final String STR_Menu_Database_CloseUnnamedItem =
85 ResourceAccess.Strings.buildString("Menu_Database_CloseUnnamedItem");
86 private static final String STR_Menu_Song_AddSongUnnamedItem =
87 ResourceAccess.Strings.buildString("Menu_Song_AddSongUnnamedItem");
88 private static final String STR_Dialog_DatabaseErrorTitle =
89 ResourceAccess.Strings.buildString("Dialog_DatabaseErrorTitle");
90 private static final String STR_Dialog_ErrorHeader =
91 ResourceAccess.Strings.buildString("Dialog_ErrorHeader");
92 private static final String STR_Dialog_FirstExceptionTemplate =
93 ResourceAccess.Strings.buildString("Dialog_FirstExceptionTemplate");
94 private static final String STR_Dialog_NextExceptionTemplate =
95 ResourceAccess.Strings.buildString("Dialog_NextExceptionTemplate");
96 private static final String STR_Message_InternalError =
97 ResourceAccess.Strings.buildString("Message_InternalError");
98 private static final String STR_Message_CopySongFailed =
99 ResourceAccess.Strings.buildString("Message_CopySongFailed");
100 private static final String STR_Message_PasteSongFailed =
101 ResourceAccess.Strings.buildString("Message_PasteSongFailed");
102 private static final String STR_Message_AddSongFailed =
103 ResourceAccess.Strings.buildString("Message_AddSongFailed");
104 private static final String STR_Message_ConfirmDeletePrompt =
105 ResourceAccess.Strings.buildString("Message_ConfirmDeletePrompt");
106 private static final String STR_Dialog_DeleteConfirmTitle =
107 ResourceAccess.Strings.buildString("Dialog_DeleteConfirmTitle");
108 private static final String STR_Message_ContinuePrompt =
109 ResourceAccess.Strings.buildString("Message_ContinuePrompt");
110 private static final String STR_Message_ContinuePrompt_ContinueButton =
111 ResourceAccess.Strings.buildString("Message_ContinuePrompt_ContinueButton");
112 private static final String STR_Message_ContinuePrompt_StopButton =
113 ResourceAccess.Strings.buildString("Message_ContinuePrompt_StopButton");
114
115
116 private BasicCommandNode menuBarRoot_;
117 private BasicCommandNode toolBarRoot_;
118 private BasicCommandNode openDatabaseGroup_;
119 private BasicCommandNode saveDatabaseGroup_;
120 private BasicCommandNode songMenuNode_;
121 private BasicCommandNode publishMenuNode_;
122 private BasicCommandNode windowsMenuNode_;
123 private BasicCommandNode dbInfoNode_;
124 private BasicCommandNode closeNode_;
125 private BasicCommandNode refreshSongListNode_;
126 private BasicCommandNode addSongNode_;
127 private BasicCommandNode deleteSongNode_;
128 private BasicCommandNode copySongNode_;
129 private BasicCommandNode pasteSongNode_;
130 private BasicCommandNode findSongsNode_;
131 private BasicCommandNode findAllSongsNode_;
132 private BasicCommandNode songGroup_;
133 private BasicCommandNode defaultSongGroup_;
134
135 private CommandNode defaultSongNode_;
136 private int defaultSongPriority_;
137
138 private int lastUntitledNumber_;
139
140 private PlatformListener platformHandler_;
141 private SelectionListener selectionListener_;
142
143 private JComponent dialogParent_;
144 private Launcher launcher_;
145 private DatabaseManagerImpl databaseManager_;
146 private GuiEnvironmentManager guiEnviron_;
147 private ListsImpl listsImpl_;
148 private PaneManagerImpl paneManager_;
149 private PrefsWindowManagerImpl prefsWindowManager_;
150 private MainGuiPlugin plugin_;
151
152 private SearchGui searchGui_;
153
154 private Song[] songClipboard_;
155 private SongDatabase songClipboardSource_;
156
157
158 /*package*/ CommandManagerImpl(
159 JComponent dialogParent,
160 Launcher launcher,
161 SongUtils songUtils,
162 DatabaseManagerImpl databaseManager,
163 GuiEnvironmentManager guiEnviron,
164 ListsImpl listsImpl,
165 PaneManagerImpl paneManager,
166 PrefsWindowManagerImpl prefsWindowManager,
167 MainGuiPlugin plugin)
168 {
169 dialogParent_ = dialogParent;
170 launcher_ = launcher;
171 databaseManager_ = databaseManager;
172 listsImpl_ = listsImpl;
173 paneManager_ = paneManager;
174 prefsWindowManager_ = prefsWindowManager;
175 plugin_ = plugin;
176
177 songClipboard_ = new Song[0];
178 songClipboardSource_ = null;
179
180 searchGui_ = new SearchGui(guiEnviron, listsImpl, songUtils);
181
182 menuBarRoot_ = new BasicContainerCommandNode();
183 toolBarRoot_ = new BasicContainerCommandNode();
184 openDatabaseGroup_ = new BasicGroupCommandNode();
185 saveDatabaseGroup_ = new BasicGroupCommandNode();
186 songGroup_ = new BasicGroupCommandNode();
187 defaultSongGroup_ = new BasicGroupCommandNode();
188 defaultSongNode_ = null;
189 BasicCommandNode node;
190
191 BasicCommandNode asaphMenuNode = new BasicContainerCommandNode();
192 asaphMenuNode.setNameProperty(ResourceAccess.Strings.buildString("Menu_AsaphTitle"));
193 if (!PlatformUtils.isUsingMacOSXScreenMenuBar())
194 {
195 menuBarRoot_.addChild(asaphMenuNode);
196 }
197
198 BasicCommandNode fileMenuNode = new BasicContainerCommandNode();
199 fileMenuNode.setNameProperty(ResourceAccess.Strings.buildString("Menu_DatabaseTitle"));
200 menuBarRoot_.addChild(fileMenuNode);
201
202 songMenuNode_ = new BasicContainerCommandNode();
203 songMenuNode_.setNameProperty(ResourceAccess.Strings.buildString("Menu_SongTitle"));
204 menuBarRoot_.addChild(songMenuNode_);
205
206 publishMenuNode_ = new BasicContainerCommandNode();
207 publishMenuNode_.setNameProperty(ResourceAccess.Strings.buildString("Menu_ToolsTitle"));
208 menuBarRoot_.addChild(publishMenuNode_);
209
210 windowsMenuNode_ = new BasicContainerCommandNode();
211 windowsMenuNode_.setNameProperty(ResourceAccess.Strings.buildString("Menu_WindowsTitle"));
212 menuBarRoot_.addChild(windowsMenuNode_);
213
214 // Create asaph menu
215 node = new BasicItemCommandNode()
216 {
217 public void commandInvoked(
218 CommandEvent ev)
219 {
220 doAbout();
221 }
222 };
223 node.setNameProperty(ResourceAccess.Strings.buildString("Menu_Asaph_AboutItem"));
224 asaphMenuNode.addChild(node);
225
226 asaphMenuNode.addChild(BasicSeparatorCommandNode.getInstance());
227
228 node = new BasicItemCommandNode()
229 {
230 public void commandInvoked(
231 CommandEvent ev)
232 {
233 doPrefs();
234 }
235 };
236 node.setNameProperty(ResourceAccess.Strings.buildString("Menu_Asaph_PrefsItem"));
237 asaphMenuNode.addChild(node);
238
239 asaphMenuNode.addChild(BasicSeparatorCommandNode.getInstance());
240
241 node = new BasicItemCommandNode()
242 {
243 public void commandInvoked(
244 CommandEvent ev)
245 {
246 doSafeQuit();
247 }
248 };
249 node.setNameProperty(ResourceAccess.Strings.buildString("Menu_Asaph_QuitItem"));
250 node.setAcceleratorKeystrokeProperty(SwingUtils.buildAcceleratorKeyStroke(
251 ResourceAccess.Strings.buildString("Menu_Asaph_QuitKeyStroke")));
252 asaphMenuNode.addChild(node);
253
254 // Create file menu
255 fileMenuNode.addChild(openDatabaseGroup_);
256
257 fileMenuNode.addChild(BasicSeparatorCommandNode.getInstance());
258
259 dbInfoNode_ = new BasicItemCommandNode()
260 {
261 public void commandInvoked(
262 CommandEvent ev)
263 {
264 doGetDBInfo();
265 }
266 };
267 dbInfoNode_.setNameProperty(STR_Menu_Database_GetInfoUnnamedItem);
268 dbInfoNode_.setDisabledProperty(true);
269 fileMenuNode.addChild(dbInfoNode_);
270
271 closeNode_ = new BasicItemCommandNode()
272 {
273 public void commandInvoked(
274 CommandEvent ev)
275 {
276 doSafeClose();
277 }
278 };
279 closeNode_.setNameProperty(STR_Menu_Database_CloseUnnamedItem);
280 closeNode_.setAcceleratorKeystrokeProperty(SwingUtils.buildAcceleratorKeyStroke(
281 ResourceAccess.Strings.buildString("Menu_Database_CloseKeyStroke")));
282 closeNode_.setDisabledProperty(true);
283 fileMenuNode.addChild(closeNode_);
284
285 fileMenuNode.addChild(BasicSeparatorCommandNode.getInstance());
286
287 fileMenuNode.addChild(saveDatabaseGroup_);
288
289 fileMenuNode.addChild(BasicSeparatorCommandNode.getInstance());
290
291 refreshSongListNode_ = new BasicItemCommandNode()
292 {
293 public void commandInvoked(
294 CommandEvent ev)
295 {
296 doRefreshIndex();
297 }
298 };
299 refreshSongListNode_.setNameProperty(
300 ResourceAccess.Strings.buildString("Menu_Database_RefreshItem"));
301 refreshSongListNode_.setAcceleratorKeystrokeProperty(SwingUtils.buildAcceleratorKeyStroke(
302 ResourceAccess.Strings.buildString("Menu_Database_RefreshKeyStroke")));
303 refreshSongListNode_.setDisabledProperty(true);
304 fileMenuNode.addChild(refreshSongListNode_);
305
306 // Create song menu
307 addSongNode_ = new BasicItemCommandNode()
308 {
309 public void commandInvoked(
310 CommandEvent ev)
311 {
312 doAddSong();
313 }
314 };
315 addSongNode_.setNameProperty(STR_Menu_Song_AddSongUnnamedItem);
316 addSongNode_.setAcceleratorKeystrokeProperty(SwingUtils.buildAcceleratorKeyStroke(
317 ResourceAccess.Strings.buildString("Menu_Song_AddSongKeyStroke")));
318 addSongNode_.setDisabledProperty(true);
319 songMenuNode_.addChild(addSongNode_);
320
321 deleteSongNode_ = new BasicItemCommandNode()
322 {
323 public void commandInvoked(
324 CommandEvent ev)
325 {
326 doDeleteSongs();
327 }
328 };
329 deleteSongNode_.setNameProperty(
330 ResourceAccess.Strings.buildString("Menu_Song_DeleteSongsItem"));
331 deleteSongNode_.setDisabledProperty(true);
332 songMenuNode_.addChild(deleteSongNode_);
333
334 copySongNode_ = new BasicItemCommandNode()
335 {
336 public void commandInvoked(
337 CommandEvent ev)
338 {
339 doCopySongs();
340 }
341 };
342 copySongNode_.setNameProperty(
343 ResourceAccess.Strings.buildString("Menu_Song_CopySongsItem"));
344 copySongNode_.setDisabledProperty(true);
345 songMenuNode_.addChild(copySongNode_);
346
347 pasteSongNode_ = new BasicItemCommandNode()
348 {
349 public void commandInvoked(
350 CommandEvent ev)
351 {
352 doPasteSongs();
353 }
354 };
355 pasteSongNode_.setNameProperty(
356 ResourceAccess.Strings.buildString("Menu_Song_PasteSongsItemDisabled"));
357 pasteSongNode_.setDisabledProperty(true);
358 songMenuNode_.addChild(pasteSongNode_);
359
360 songMenuNode_.addChild(BasicSeparatorCommandNode.getInstance());
361
362 findSongsNode_ = new BasicItemCommandNode()
363 {
364 public void commandInvoked(
365 CommandEvent ev)
366 {
367 searchGui_.doFindSongs();
368 }
369 };
370 findSongsNode_.setNameProperty(
371 ResourceAccess.Strings.buildString("Menu_Song_FindSongsItem"));
372 findSongsNode_.setDisabledProperty(true);
373 songMenuNode_.addChild(findSongsNode_);
374
375 findAllSongsNode_ = new BasicItemCommandNode()
376 {
377 public void commandInvoked(
378 CommandEvent ev)
379 {
380 searchGui_.doFindAllSongs();
381 }
382 };
383 findAllSongsNode_.setNameProperty(
384 ResourceAccess.Strings.buildString("Menu_Song_FindAllSongsItem"));
385 findAllSongsNode_.setDisabledProperty(true);
386 songMenuNode_.addChild(findAllSongsNode_);
387
388 songMenuNode_.addChild(BasicSeparatorCommandNode.getInstance());
389 defaultSongGroup_.setDisabledProperty(true);
390 songMenuNode_.addChild(defaultSongGroup_);
391 songMenuNode_.addChild(BasicSeparatorCommandNode.getInstance());
392 songGroup_.setDisabledProperty(true);
393 songMenuNode_.addChild(songGroup_);
394
395 // Platform events (currently only affects Mac OS X)
396 platformHandler_ = new PlatformListener()
397 {
398 public void platformEventHappened(
399 PlatformEvent ev)
400 {
401 if (ev.getType() == PlatformUtils.QUIT_EVENT)
402 {
403 doSafeQuit();
404 }
405 else if (ev.getType() == PlatformUtils.OPEN_ABOUTBOX_EVENT)
406 {
407 doAbout();
408 ev.setHandled();
409 }
410 else if (ev.getType() == PlatformUtils.OPEN_PREFERENCES_EVENT)
411 {
412 doPrefs();
413 ev.setHandled();
414 }
415 }
416 };
417 PlatformUtils.addPlatformListener(platformHandler_);
418 PlatformUtils.setSystemPreferencesMenuItemEnabled(true);
419
420 listsImpl_.addSelectionListener(
421 selectionListener_ = new SelectionListener()
422 {
423 public void databaseSelectionChanged(
424 DatabaseSelectionEvent ev)
425 {
426 if (ev.getNewSelection() == null)
427 {
428 dbInfoNode_.setDisabledProperty(true);
429 dbInfoNode_.setNameProperty(STR_Menu_Database_GetInfoUnnamedItem);
430 closeNode_.setDisabledProperty(true);
431 closeNode_.setNameProperty(STR_Menu_Database_CloseUnnamedItem);
432 refreshSongListNode_.setDisabledProperty(true);
433 findSongsNode_.setDisabledProperty(true);
434 findAllSongsNode_.setDisabledProperty(true);
435 addSongNode_.setDisabledProperty(true);
436 addSongNode_.setNameProperty(STR_Menu_Song_AddSongUnnamedItem);
437 pasteSongNode_.setNameProperty(ResourceAccess.Strings.buildString(
438 "Menu_Song_PasteSongsItemDisabled"));
439 pasteSongNode_.setDisabledProperty(true);
440 saveDatabaseGroup_.setDisabledProperty(true);
441 }
442 else
443 {
444 SongDatabase newSelection = ev.getNewSelection();
445 PropertySet properties = databaseManager_.getDatabaseProperties(newSelection);
446 String name = (String)properties.getValue(DatabaseManager.DATABASE_NAME_KEY);
447 dbInfoNode_.setDisabledProperty(false);
448 dbInfoNode_.setNameProperty(ResourceAccess.Strings.buildString(
449 "Menu_Database_GetInfoNamedItem", name));
450 closeNode_.setDisabledProperty(false);
451 closeNode_.setNameProperty(ResourceAccess.Strings.buildString(
452 "Menu_Database_CloseNamedItem", name));
453 refreshSongListNode_.setDisabledProperty(false);
454 findSongsNode_.setDisabledProperty(false);
455 findAllSongsNode_.setDisabledProperty(false);
456 addSongNode_.setDisabledProperty(!newSelection.isWritable());
457 addSongNode_.setNameProperty(ResourceAccess.Strings.buildString(
458 "Menu_Song_AddSongNamedItem", name));
459 if (songClipboardSource_ == null || songClipboardSource_.equals(newSelection))
460 {
461 pasteSongNode_.setNameProperty(ResourceAccess.Strings.buildString(
462 "Menu_Song_PasteSongsItemDisabled"));
463 pasteSongNode_.setDisabledProperty(true);
464 }
465 else
466 {
467 pasteSongNode_.setNameProperty(ResourceAccess.Strings.buildString(
468 "Menu_Song_PasteSongsItem", new Integer(songClipboard_.length), name));
469 pasteSongNode_.setDisabledProperty(false);
470 }
471 saveDatabaseGroup_.setDisabledProperty(false);
472 }
473 }
474
475 public void songSelectionChanged(
476 SongSelectionEvent ev)
477 {
478 if (ev.getNewSelection().isEmpty())
479 {
480 deleteSongNode_.setDisabledProperty(true);
481 defaultSongGroup_.setDisabledProperty(true);
482 songGroup_.setDisabledProperty(true);
483 copySongNode_.setDisabledProperty(true);
484 }
485 else
486 {
487 deleteSongNode_.setDisabledProperty(!ev.getDatabase().isWritable());
488 defaultSongGroup_.setDisabledProperty(true);
489 songGroup_.setDisabledProperty(false);
490 copySongNode_.setDisabledProperty(false);
491 }
492 }
493 });
494 }
495
496
497 /*package*/ BasicCommandNode getMenuBarRoot()
498 {
499 return menuBarRoot_;
500 }
501
502
503 /*package*/ BasicCommandNode getToolBarRoot()
504 {
505 return toolBarRoot_;
506 }
507
508
509 /*package*/ BasicCommandNode getWindowsMenuNode()
510 {
511 return windowsMenuNode_;
512 }
513
514
515 private void doAbout()
516 {
517 launcher_.openAboutBox(dialogParent_);
518 }
519
520
521 private void doHelp()
522 {
523 // TODO
524 }
525
526
527 private void doPrefs()
528 {
529 prefsWindowManager_.openPrefsWindow();
530 }
531
532
533 /*package*/ void doSafeQuit()
534 {
535 if (!paneManager_.shutDown())
536 {
537 return;
538 }
539 if (!databaseManager_.shutDown())
540 {
541 return;
542 }
543 prefsWindowManager_.closePrefsWindow();
544 plugin_.shutDown();
545 System.exit(0);
546 }
547
548
549 private void doGetDBInfo()
550 {
551 listsImpl_.getSelectedDatabaseHandler().handleDatabaseGetInfo();
552 }
553
554
555 /*package*/ void doDefaultSongCommand()
556 {
557 if (defaultSongNode_ != null)
558 {
559 defaultSongNode_.commandInvoked(new CommandEvent(defaultSongNode_));
560 }
561 }
562
563
564 private void doSafeClose()
565 {
566 databaseManager_.removeDatabase(listsImpl_.getSelectedDatabase());
567 }
568
569
570 private void doRefreshIndex()
571 {
572 SongDatabase database = listsImpl_.getSelectedDatabase();
573 try
574 {
575 listsImpl_.refreshDatabaseIndex(database);
576 }
577 catch (SongDatabaseFailedException ex)
578 {
579 PropertySet properties = databaseManager_.getDatabaseProperties(database);
580 String name = (String)properties.getValue(DatabaseManager.DATABASE_NAME_KEY);
581 DetailedMessageDialog dialog = DetailedMessageDialog.create(
582 dialogParent_, STR_Dialog_DatabaseErrorTitle,
583 ResourceAccess.Strings.buildString("Message_FetchIndexFailed", name),
584 STR_Dialog_ErrorHeader,
585 ExceptionUtils.getDescriptionFor(ex,
586 STR_Dialog_FirstExceptionTemplate, STR_Dialog_NextExceptionTemplate),
587 null);
588 dialog.show();
589 }
590 }
591
592
593 private void doAddSong()
594 {
595 SongDatabase database = listsImpl_.getSelectedDatabase();
596 try
597 {
598 SongID songID = database.addEmptySong(
599 ResourceAccess.Strings.buildString("InitialSongTitle",
600 Integer.toString(++lastUntitledNumber_)), null);
601 listsImpl_.reportSongAdded(songID);
602 databaseManager_.setDatabaseDirtyBit(database);
603 }
604 catch (SongDatabaseFailedException ex)
605 {
606 DetailedMessageDialog dialog = DetailedMessageDialog.create(
607 dialogParent_, STR_Dialog_DatabaseErrorTitle,
608 STR_Message_AddSongFailed, STR_Dialog_ErrorHeader,
609 ExceptionUtils.getDescriptionFor(ex,
610 STR_Dialog_FirstExceptionTemplate, STR_Dialog_NextExceptionTemplate),
611 null);
612 dialog.show();
613 }
614 }
615
616
617 private void doDeleteSongs()
618 {
619 int option = JOptionPane.showConfirmDialog(dialogParent_,
620 STR_Message_ConfirmDeletePrompt, STR_Dialog_DeleteConfirmTitle,
621 JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
622 if (option == JOptionPane.YES_OPTION)
623 {
624 SongDatabase database = listsImpl_.getSelectedDatabase();
625 Set selectedSongs = listsImpl_.getSelectedSongSet();
626 for (Iterator iter = selectedSongs.iterator(); iter.hasNext(); )
627 {
628 SongID songID = (SongID)iter.next();
629 try
630 {
631 database.removeSong(songID);
632 listsImpl_.reportSongRemoved(songID);
633 databaseManager_.setDatabaseDirtyBit(database);
634 }
635 catch (SongDatabaseFailedException ex)
636 {
637 if (!iter.hasNext())
638 {
639 DetailedMessageDialog dialog = DetailedMessageDialog.create(
640 dialogParent_, STR_Dialog_DatabaseErrorTitle,
641 ResourceAccess.Strings.buildString("Message_DeleteSongFailed",
642 listsImpl_.getNameForSongID(songID)),
643 STR_Dialog_ErrorHeader,
644 ExceptionUtils.getDescriptionFor(ex,
645 STR_Dialog_FirstExceptionTemplate, STR_Dialog_NextExceptionTemplate),
646 null);
647 dialog.show();
648 }
649 else
650 {
651 DetailedMessageDialog dialog = DetailedMessageDialog.create(
652 dialogParent_, STR_Dialog_DatabaseErrorTitle,
653 ResourceAccess.Strings.buildString("Message_DeleteSongFailed",
654 listsImpl_.getNameForSongID(songID)),
655 STR_Dialog_ErrorHeader,
656 ExceptionUtils.getDescriptionFor(ex,
657 STR_Dialog_FirstExceptionTemplate, STR_Dialog_NextExceptionTemplate),
658 STR_Message_ContinuePrompt,
659 new String[]{STR_Message_ContinuePrompt_ContinueButton,
660 STR_Message_ContinuePrompt_StopButton});
661 dialog.show();
662 if (!ObjectUtils.safeEquals(dialog.getSelection(),
663 STR_Message_ContinuePrompt_ContinueButton))
664 {
665 break;
666 }
667 }
668 }
669 }
670 }
671 }
672
673
674 private void doCopySongs()
675 {
676 SongDatabase database = listsImpl_.getSelectedDatabase();
677 Set selectedSongs = listsImpl_.getSelectedSongSet();
678 try
679 {
680 List list = new ArrayList();
681 for (Iterator iter = selectedSongs.iterator(); iter.hasNext(); )
682 {
683 SongID songID = (SongID)iter.next();
684 list.add(database.checkOutSong(songID));
685 }
686 if (list.isEmpty())
687 {
688 songClipboard_ = new Song[0];
689 songClipboardSource_ = null;
690 }
691 else
692 {
693 songClipboard_ = new Song[list.size()];
694 list.toArray(songClipboard_);
695 songClipboardSource_ = database;
696 }
697 }
698 catch (SongDatabaseFailedException ex)
699 {
700 DetailedMessageDialog dialog = DetailedMessageDialog.create(
701 dialogParent_, STR_Dialog_DatabaseErrorTitle,
702 STR_Message_CopySongFailed, STR_Dialog_ErrorHeader,
703 ExceptionUtils.getDescriptionFor(ex,
704 STR_Dialog_FirstExceptionTemplate, STR_Dialog_NextExceptionTemplate),
705 null);
706 dialog.show();
707 }
708 }
709
710
711 private void doPasteSongs()
712 {
713 SongDatabase database = listsImpl_.getSelectedDatabase();
714 try
715 {
716 for (int i=0; i<songClipboard_.length; ++i)
717 {
718 SongID songID = database.addCopyOfSong(songClipboard_[i]);
719 listsImpl_.reportSongAdded(songID);
720 databaseManager_.setDatabaseDirtyBit(database);
721 }
722 }
723 catch (SongDatabaseFailedException ex)
724 {
725 DetailedMessageDialog dialog = DetailedMessageDialog.create(
726 dialogParent_, STR_Dialog_DatabaseErrorTitle,
727 STR_Message_PasteSongFailed, STR_Dialog_ErrorHeader,
728 ExceptionUtils.getDescriptionFor(ex,
729 STR_Dialog_FirstExceptionTemplate, STR_Dialog_NextExceptionTemplate),
730 null);
731 dialog.show();
732 }
733 }
734
735
736 /**
737 * Returns a group-flavored CommandNode that can be filled with commands
738 * which a plugin wants to submit to the menu system.
739 * Commands are separated into categories, identified by the constants
740 * OPEN_COMMANDS, SAVE_COMMANDS, SONG_COMMANDS and TOOL_COMMANDS.
741 * See the comments for the various key constants for more information
742 * about command categories.
743 *
744 * @param category a category for the command
745 * @return a group-flavored CommandNode, or null if category not recognized
746 */
747 public CommandNode createCommandGroup(
748 CommandCategory category)
749 {
750 if (category == OPEN_COMMANDS)
751 {
752 BasicCommandNode node = new BasicGroupCommandNode();
753 openDatabaseGroup_.addChild(node);
754 return node;
755 }
756 if (category == SAVE_COMMANDS)
757 {
758 BasicCommandNode node = new BasicGroupCommandNode();
759 saveDatabaseGroup_.addChild(node);
760 return node;
761 }
762 if (category == SONG_COMMANDS)
763 {
764 BasicCommandNode node = new BasicGroupCommandNode();
765 songGroup_.addChild(node);
766 return node;
767 }
768 if (category == TOOL_COMMANDS)
769 {
770 BasicCommandNode node = new BasicGroupCommandNode();
771 publishMenuNode_.addChild(node);
772 return node;
773 }
774 return null;
775 }
776
777
778 /**
779 * Sets the default song command. If a command is already present, the one with
780 * the higher priority will be taken.
781 * Returns true if the command was set, or false if not.
782 *
783 * @param node a CommandNode for the default song command
784 * @param priority priority of this command
785 * @return true if successful
786 */
787 public boolean setDefaultSongCommand(
788 CommandNode node,
789 int priority)
790 {
791 if (defaultSongNode_ != null)
792 {
793 if (priority <= defaultSongPriority_)
794 {
795 return false;
796 }
797 else
798 {
799 defaultSongGroup_.removeAllChildren();
800 }
801 }
802 defaultSongNode_ = node;
803 defaultSongPriority_ = priority;
804 defaultSongGroup_.addChild(defaultSongNode_);
805 return true;
806 }
807 }