Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/virtuosotechnologies/asaph/standardgui/SongEditor.java


1   /*
2   ================================================================================
3   
4     FILE:  SongEditor.java
5     
6     PROJECT:
7     
8       Asaph
9     
10    CONTENTS:
11    
12      Song editor pane implementation
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.standardgui;
43  
44  
45  import java.awt.GridBagLayout;
46  import java.awt.GridBagConstraints;
47  import java.awt.BorderLayout;
48  import java.awt.Insets;
49  import java.util.logging.Logger;
50  import javax.swing.BorderFactory;
51  import javax.swing.JTabbedPane;
52  import javax.swing.JComponent;
53  import javax.swing.JPanel;
54  import javax.swing.JSeparator;
55  import javax.swing.JScrollPane;
56  import javax.swing.JTextArea;
57  import javax.swing.SingleSelectionModel;
58  import javax.swing.undo.UndoManager;
59  import javax.swing.undo.UndoableEdit;
60  import javax.swing.undo.AbstractUndoableEdit;
61  import javax.swing.undo.CannotUndoException;
62  import javax.swing.undo.CannotRedoException;
63  import javax.swing.event.UndoableEditListener;
64  import javax.swing.event.UndoableEditEvent;
65  import javax.swing.event.ChangeListener;
66  import javax.swing.event.ChangeEvent;
67  
68  import com.virtuosotechnologies.lib.command.CommandNode;
69  import com.virtuosotechnologies.lib.command.CommandEvent;
70  import com.virtuosotechnologies.lib.basiccommand.BasicCommandNode;
71  import com.virtuosotechnologies.lib.basiccommand.BasicGroupCommandNode;
72  import com.virtuosotechnologies.lib.basiccommand.BasicContainerCommandNode;
73  import com.virtuosotechnologies.lib.basiccommand.BasicItemCommandNode;
74  import com.virtuosotechnologies.lib.basiccommand.BasicSeparatorCommandNode;
75  import com.virtuosotechnologies.lib.swing.ScrollablePanel;
76  import com.virtuosotechnologies.lib.swing.SwingUtils;
77  import com.virtuosotechnologies.lib.asyncjob.AsyncJobRunner;
78  import com.virtuosotechnologies.lib.platform.PlatformUtils;
79  
80  import com.virtuosotechnologies.asaph.model.StringListField;
81  import com.virtuosotechnologies.asaph.model.SongID;
82  import com.virtuosotechnologies.asaph.model.Song;
83  import com.virtuosotechnologies.asaph.model.Variation;
84  import com.virtuosotechnologies.asaph.model.ChordSet;
85  import com.virtuosotechnologies.asaph.modelutils.SongUtils;
86  import com.virtuosotechnologies.asaph.maingui.GuiEnvironmentManager;
87  
88  
89  /**
90   * Song editor pane implementation
91   */
92  /*package*/ class SongEditor
93  {
94    private static final String STR_menu_EditTitle =
95      ResourceAccess.Strings.buildString("menu_EditTitle");
96    private static final String STR_menu_Edit_UndoItem =
97      ResourceAccess.Strings.buildString("menu_Edit_UndoItem");
98    private static final String STR_menu_Edit_RedoItem =
99      ResourceAccess.Strings.buildString("menu_Edit_RedoItem");
100   private static final String STR_menu_Edit_CutItem =
101     ResourceAccess.Strings.buildString("menu_Edit_CutItem");
102   private static final String STR_menu_Edit_CopyItem =
103     ResourceAccess.Strings.buildString("menu_Edit_CopyItem");
104   private static final String STR_menu_Edit_PasteItem =
105     ResourceAccess.Strings.buildString("menu_Edit_PasteItem");
106   private static final String STR_menu_Edit_DeleteItem =
107     ResourceAccess.Strings.buildString("menu_Edit_DeleteItem");
108   
109   private static final String STR_menu_Edit_UndoKeyStroke =
110     ResourceAccess.Strings.buildString("menu_Edit_UndoKeyStroke");
111   private static final String STR_menu_Edit_RedoKeyStroke =
112     ResourceAccess.Strings.buildString("menu_Edit_RedoKeyStroke");
113   private static final String STR_menu_Edit_CutKeyStroke =
114     ResourceAccess.Strings.buildString("menu_Edit_CutKeyStroke");
115   private static final String STR_menu_Edit_CopyKeyStroke =
116     ResourceAccess.Strings.buildString("menu_Edit_CopyKeyStroke");
117   private static final String STR_menu_Edit_PasteKeyStroke =
118     ResourceAccess.Strings.buildString("menu_Edit_PasteKeyStroke");
119   
120   private static final String STR_SongEditor_FieldsTab =
121     ResourceAccess.Strings.buildString("SongEditor_FieldsTab");
122   private static final String STR_SongEditor_AltTitlesLabel =
123     ResourceAccess.Strings.buildString("SongEditor_AltTitlesLabel");
124   private static final String STR_SongEditor_KeywordsLabel =
125     ResourceAccess.Strings.buildString("SongEditor_KeywordsLabel");
126   private static final String STR_SongEditor_VersionsTab =
127     ResourceAccess.Strings.buildString("SongEditor_VersionsTab");
128   private static final String STR_SongEditor_BodyTab =
129     ResourceAccess.Strings.buildString("SongEditor_BodyTab");
130   private static final String STR_SongEditor_NotesTab =
131     ResourceAccess.Strings.buildString("SongEditor_NotesTab");
132   
133   
134   private Logger logger_;
135   
136   private EditorPrefs editorPrefs_;
137   
138   private SongUtils songUtils_;
139   private SongWindow window_;
140   private AsyncJobRunner jobRunner_;
141   
142   private SongID songID_;
143   private Song song_;
144   
145   private BasicCommandNode commandGroup_;
146   private BasicCommandNode undoCommand_;
147   private BasicCommandNode redoCommand_;
148   private BasicCommandNode cutCommand_;
149   private BasicCommandNode copyCommand_;
150   private BasicCommandNode pasteCommand_;
151   private BasicCommandNode deleteCommand_;
152   private BasicCommandNode formClipboardGroup_;
153   private BasicCommandNode bodyEditorEditGroup_;
154   private BasicCommandNode bodyEditorMenuGroup_;
155   
156   private JTabbedPane tabbedPane_;
157   private boolean showingBodyEditor_;
158   private UndoManager undoManager_;
159   private SongBodyEditorPane bodyEditor_;
160   
161   
162   /**
163    * Constructor
164    */
165   /*package*/ SongEditor(
166     SongWindow window,
167     SongUtils songUtils,
168     EditorPrefs editorPrefs,
169     GuiEnvironmentManager guiEnvironmentManager,
170     AsyncJobRunner jobRunner,
171     SongID songID,
172     Song song)
173   {
174     logger_ = Logger.getLogger("com.virtuosotechnologies.asaph.standardgui");
175     
176     editorPrefs_ = editorPrefs;
177     songUtils_ = songUtils;
178     window_ = window;
179     jobRunner_ = jobRunner;
180     songID_ = songID;
181     song_ = song;
182     
183     undoManager_ = new UndoManager();
184     
185     // Create menus
186     buildMenus();
187     
188     // Create tabs
189     tabbedPane_ = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
190     buildFieldsTab();
191     buildVersionsTab();
192     buildSongTab(guiEnvironmentManager);
193     buildNotesTab();
194   }
195   
196   
197   /**
198    * Dispose the editor
199    */
200   /*package*/ void dispose()
201   {
202     if (showingBodyEditor_)
203     {
204       // Anything need to be done?
205     }
206   }
207   
208   
209   /*package*/ void setUndoLevels(
210     int levels)
211   {
212     undoManager_.setLimit(levels);
213   }
214   
215   
216   /**
217    * Get the component
218    */
219   /*package*/ JComponent getJComponent()
220   {
221     return tabbedPane_;
222   }
223   
224   
225   /**
226    * Get the toplevel command node
227    */
228   /*package*/ CommandNode getCommandNode()
229   {
230     return commandGroup_;
231   }
232   
233   
234   /*package*/ void markDirty()
235   {
236     window_.markDirty();
237     undoCommand_.setDisabledProperty(false);
238   }
239   
240   
241   /*package*/ void commitCurrentField()
242   {
243     StringUpdater.commitCurrent();
244   }
245   
246   
247   /*package*/ void updateFieldClipboardMenus(
248     int level)
249   {
250     cutCommand_.setDisabledProperty(level != 2);
251     copyCommand_.setDisabledProperty(level != 2);
252     pasteCommand_.setDisabledProperty(level == 0);
253     deleteCommand_.setDisabledProperty(level != 2);
254   }
255   
256   
257   private void buildMenus()
258   {
259     // Toplevel
260     commandGroup_ = new BasicGroupCommandNode();
261     
262     // Edit menu
263     BasicCommandNode editMenu = new BasicContainerCommandNode();
264     editMenu.setNameProperty(STR_menu_EditTitle);
265     commandGroup_.addChild(editMenu);
266     
267     undoCommand_ = new BasicItemCommandNode()
268     {
269       public void commandInvoked(
270         CommandEvent ev)
271       {
272         commitCurrentField();
273         if (undoManager_.canUndo())
274         {
275           undoManager_.undo();
276         }
277       }
278     };
279     undoCommand_.setNameProperty(STR_menu_Edit_UndoItem);
280     undoCommand_.setDisabledProperty(true);
281     undoCommand_.setAcceleratorKeystrokeProperty(SwingUtils.buildAcceleratorKeyStroke(
282       STR_menu_Edit_UndoKeyStroke));
283     editMenu.addChild(undoCommand_);
284     
285     redoCommand_ = new BasicItemCommandNode()
286     {
287       public void commandInvoked(
288         CommandEvent ev)
289       {
290         commitCurrentField();
291         if (undoManager_.canRedo())
292         {
293           undoManager_.redo();
294         }
295       }
296     };
297     redoCommand_.setNameProperty(STR_menu_Edit_RedoItem);
298     redoCommand_.setDisabledProperty(true);
299     redoCommand_.setAcceleratorKeystrokeProperty(SwingUtils.buildAcceleratorKeyStroke(
300       STR_menu_Edit_RedoKeyStroke));
301     editMenu.addChild(redoCommand_);
302     
303     editMenu.addChild(BasicSeparatorCommandNode.getInstance());
304     formClipboardGroup_ = new BasicGroupCommandNode();
305     editMenu.addChild(formClipboardGroup_);
306     
307     cutCommand_ = new BasicItemCommandNode()
308     {
309       public void commandInvoked(
310         CommandEvent ev)
311       {
312         StringUpdater.cutCurrent();
313       }
314     };
315     cutCommand_.setNameProperty(STR_menu_Edit_CutItem);
316     cutCommand_.setDisabledProperty(true);
317     cutCommand_.setAcceleratorKeystrokeProperty(SwingUtils.buildAcceleratorKeyStroke(
318       STR_menu_Edit_CutKeyStroke));
319     formClipboardGroup_.addChild(cutCommand_);
320     
321     copyCommand_ = new BasicItemCommandNode()
322     {
323       public void commandInvoked(
324         CommandEvent ev)
325       {
326         StringUpdater.copyCurrent();
327       }
328     };
329     copyCommand_.setNameProperty(STR_menu_Edit_CopyItem);
330     copyCommand_.setDisabledProperty(true);
331     copyCommand_.setAcceleratorKeystrokeProperty(SwingUtils.buildAcceleratorKeyStroke(
332       STR_menu_Edit_CopyKeyStroke));
333     formClipboardGroup_.addChild(copyCommand_);
334     
335     pasteCommand_ = new BasicItemCommandNode()
336     {
337       public void commandInvoked(
338         CommandEvent ev)
339       {
340         StringUpdater.pasteCurrent();
341       }
342     };
343     pasteCommand_.setNameProperty(STR_menu_Edit_PasteItem);
344     pasteCommand_.setDisabledProperty(true);
345     pasteCommand_.setAcceleratorKeystrokeProperty(SwingUtils.buildAcceleratorKeyStroke(
346       STR_menu_Edit_PasteKeyStroke));
347     formClipboardGroup_.addChild(pasteCommand_);
348     
349     deleteCommand_ = new BasicItemCommandNode()
350     {
351       public void commandInvoked(
352         CommandEvent ev)
353       {
354         StringUpdater.deleteCurrent();
355       }
356     };
357     deleteCommand_.setNameProperty(STR_menu_Edit_DeleteItem);
358     deleteCommand_.setDisabledProperty(true);
359     formClipboardGroup_.addChild(deleteCommand_);
360     
361     formClipboardGroup_.addChild(BasicSeparatorCommandNode.getInstance());
362     
363     bodyEditorEditGroup_ = new BasicGroupCommandNode();
364     editMenu.addChild(bodyEditorEditGroup_);
365     
366     bodyEditorMenuGroup_ = new BasicGroupCommandNode();
367     commandGroup_.addChild(bodyEditorMenuGroup_);
368   }
369   
370   
371   private void performCommonOperations()
372   {
373     window_.markDirty();
374     undoCommand_.setDisabledProperty(!undoManager_.canUndo());
375     redoCommand_.setDisabledProperty(!undoManager_.canRedo());
376   }
377   
378   
379   private void addTabSwitchingEdit(
380     final UndoableEdit delegate,
381     final JComponent component)
382   {
383     addTabSwitchingEdit(delegate, component, null);
384   }
385   
386   
387   private void addTabSwitchingEdit(
388     final UndoableEdit delegate,
389     final JComponent component,
390     final SongBodyEditorPane bodyEditorPane)
391   {
392     final Variation variation =
393       (bodyEditorPane == null ? null : bodyEditorPane.getCurVariation());
394     final ChordSet chordSet =
395       (bodyEditorPane == null ? null : bodyEditorPane.getCurChordSet());
396     undoManager_.addEdit(
397       new AbstractUndoableEdit()
398       {
399         public void undo()
400         throws CannotUndoException
401         {
402           super.undo();
403           tabbedPane_.setSelectedComponent(component);
404           if (bodyEditorPane != null)
405           {
406             bodyEditorPane.setCurVariation(variation);
407             bodyEditorPane.setCurChordSet(chordSet);
408           }
409           delegate.undo();
410           performCommonOperations();
411         }
412         
413         public void redo()
414         throws CannotRedoException
415         {
416           super.redo();
417           tabbedPane_.setSelectedComponent(component);
418           if (bodyEditorPane != null)
419           {
420             bodyEditorPane.setCurVariation(variation);
421             bodyEditorPane.setCurChordSet(chordSet);
422           }
423           delegate.redo();
424           performCommonOperations();
425         }
426       });
427     performCommonOperations();
428   }
429   
430   
431   private void buildFieldsTab()
432   {
433     final JPanel mainPanel = new JPanel(new GridBagLayout());
434 //    ScrollablePanel viewportPanel = new ScrollablePanel(new BorderLayout());
435 //    viewportPanel.add(mainPanel, BorderLayout.NORTH);
436 //    final JScrollPane fieldsComponent = new JScrollPane(viewportPanel);
437     final JPanel fieldsComponent = new JPanel(new BorderLayout());
438     fieldsComponent.add(mainPanel, BorderLayout.NORTH);
439     tabbedPane_.add(STR_SongEditor_FieldsTab, fieldsComponent);
440     
441     GridBagConstraints gbc = new GridBagConstraints();
442     gbc.gridx = 0;
443     gbc.weightx = 1;
444     gbc.weighty = 1;
445     gbc.fill = GridBagConstraints.HORIZONTAL;
446     gbc.insets = new Insets(0, 5, 0, 5);
447     
448     final MainFieldsEditor mainFieldsEditor = new MainFieldsEditor(song_, this,
449       new UndoableEditListener()
450       {
451         public void undoableEditHappened(
452           UndoableEditEvent ev)
453         {
454           addTabSwitchingEdit(ev.getEdit(), fieldsComponent);
455         }
456       });
457     mainFieldsEditor.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
458     mainPanel.add(mainFieldsEditor, gbc);
459     
460     mainPanel.add(new JSeparator(), gbc);
461     
462     final StringListEditor altTitlesEditor = new StringListEditor(STR_SongEditor_AltTitlesLabel,
463       (StringListField)song_.getNamedField(Song.ALTERNATETITLELIST_FIELD), this,
464       new UndoableEditListener()
465       {
466         public void undoableEditHappened(
467           UndoableEditEvent ev)
468         {
469           addTabSwitchingEdit(ev.getEdit(), fieldsComponent);
470         }
471       });
472     altTitlesEditor.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
473     mainPanel.add(altTitlesEditor, gbc);
474     
475     mainPanel.add(new JSeparator(), gbc);
476     
477     final StringListEditor keywordsEditor = new StringListEditor(STR_SongEditor_KeywordsLabel,
478       (StringListField)song_.getNamedField(Song.KEYWORDLIST_FIELD), this,
479       new UndoableEditListener()
480       {
481         public void undoableEditHappened(
482           UndoableEditEvent ev)
483         {
484           addTabSwitchingEdit(ev.getEdit(), fieldsComponent);
485         }
486       });
487     keywordsEditor.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
488     mainPanel.add(keywordsEditor, gbc);
489   }
490   
491   
492   private void buildVersionsTab()
493   {
494     final JPanel mainPanel = new JPanel(new GridBagLayout());
495 //    ScrollablePanel viewportPanel = new ScrollablePanel(new BorderLayout());
496 //    viewportPanel.add(mainPanel, BorderLayout.NORTH);
497 //    final JScrollPane versionsComponent = new JScrollPane(viewportPanel);
498     final JPanel versionsComponent = new JPanel(new BorderLayout());
499     versionsComponent.add(mainPanel, BorderLayout.NORTH);
500     tabbedPane_.add(STR_SongEditor_VersionsTab, versionsComponent);
501     
502     GridBagConstraints gbc = new GridBagConstraints();
503     gbc.gridx = 0;
504     gbc.weightx = 1;
505     gbc.weighty = 1;
506     gbc.fill = GridBagConstraints.HORIZONTAL;
507     gbc.insets = new Insets(0, 5, 0, 5);
508     
509     final ChordSetListEditor chordSetsEditor = new ChordSetListEditor(
510       window_.getSongUtils(), window_.getNotationManager(), song_, this,
511       new UndoableEditListener()
512       {
513         public void undoableEditHappened(
514           UndoableEditEvent ev)
515         {
516           addTabSwitchingEdit(ev.getEdit(), versionsComponent);
517         }
518       });
519     chordSetsEditor.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
520     mainPanel.add(chordSetsEditor, gbc);
521     
522     mainPanel.add(new JSeparator(), gbc);
523     
524     final VariationListEditor variationsEditor = new VariationListEditor(
525       song_, this, new UndoableEditListener()
526       {
527         public void undoableEditHappened(
528           UndoableEditEvent ev)
529         {
530           addTabSwitchingEdit(ev.getEdit(), versionsComponent);
531         }
532       });
533     variationsEditor.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
534     mainPanel.add(variationsEditor, gbc);
535   }
536   
537   
538   private void buildSongTab(
539     GuiEnvironmentManager guiEnvironmentManager)
540   {
541     bodyEditor_ = new SongBodyEditorPane(jobRunner_, songID_, song_,
542       bodyEditorEditGroup_, editorPrefs_, guiEnvironmentManager,
543       window_.getSongUtils(), window_.getDataTransferUtils(),
544       window_.getNotationManager());
545     final JComponent component = bodyEditor_.getJComponent();
546     bodyEditor_.setUndoableEditListener(
547       new UndoableEditListener()
548       {
549         public void undoableEditHappened(
550           UndoableEditEvent ev)
551         {
552           addTabSwitchingEdit(ev.getEdit(), component, bodyEditor_);
553         }
554       });
555     tabbedPane_.add(STR_SongEditor_BodyTab, component);
556     showingBodyEditor_ = false;
557     final SingleSelectionModel tabModel = tabbedPane_.getModel();
558     tabModel.addChangeListener(
559       new ChangeListener()
560       {
561         public void stateChanged(
562           ChangeEvent ev)
563         {
564           boolean newShowing = 
565             (tabbedPane_.getComponentAt(tabModel.getSelectedIndex()) == component);
566           if (newShowing != showingBodyEditor_)
567           {
568             showingBodyEditor_ = newShowing;
569             if (showingBodyEditor_)
570             {
571               commitCurrentField();
572               bodyEditor_.activatePane(bodyEditorMenuGroup_);
573               bodyEditorEditGroup_.setHiddenProperty(false);
574               formClipboardGroup_.setHiddenProperty(true);
575             }
576             else
577             {
578               bodyEditorMenuGroup_.removeAllChildren();
579               bodyEditorEditGroup_.setHiddenProperty(true);
580               formClipboardGroup_.setHiddenProperty(false);
581             }
582           }
583         }
584       });
585   }
586   
587   
588   private void buildNotesTab()
589   {
590     StringListField field = (StringListField)song_.getNamedField(Song.NOTESLIST_FIELD);
591     final JTextArea textArea = new JTextArea(songUtils_.getMultiLineString(field));
592     textArea.setLineWrap(true);
593     textArea.setWrapStyleWord(true);
594     textArea.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
595     final JScrollPane scroller = new JScrollPane(textArea);
596     StringUpdater.install(textArea, field, songUtils_, this,
597       new UndoableEditListener()
598       {
599         public void undoableEditHappened(
600           UndoableEditEvent ev)
601         {
602           addTabSwitchingEdit(ev.getEdit(), scroller);
603         }
604       });
605     tabbedPane_.add(STR_SongEditor_NotesTab, scroller);
606   }
607 }