/[svn]/jsampler/trunk/src/org/jsampler/view/InstrumentsDbTreeModel.java
ViewVC logotype

Annotation of /jsampler/trunk/src/org/jsampler/view/InstrumentsDbTreeModel.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1729 - (hide annotations) (download)
Tue Apr 29 22:22:40 2008 UTC (16 years ago) by iliev
File size: 18947 byte(s)
* Added support for handling lost files in the Instruments Database
  (In the Instruments Database window choose Actions/Check For Lost Files)
* Fantasia: Added option to show the Instruments Database
  on the Right-Side Pane of the Fantasia's main window
  (choose Edit/Preferences, then click the `View' tab)
* Added new menu item in the Instruments Database window: Edit/Find
* Some minor bugfixes and enhancements

1 iliev 1204 /*
2     * JSampler - a java front-end for LinuxSampler
3     *
4     * Copyright (C) 2005-2007 Grigor Iliev <grigor@grigoriliev.com>
5     *
6     * This file is part of JSampler.
7     *
8     * JSampler is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License version 2
10     * as published by the Free Software Foundation.
11     *
12     * JSampler is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with JSampler; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20     * MA 02111-1307 USA
21     */
22    
23     package org.jsampler.view;
24    
25     import java.awt.event.ActionEvent;
26     import java.awt.event.ActionListener;
27    
28     import java.util.Vector;
29    
30     import javax.swing.SwingUtilities;
31    
32     import javax.swing.event.TreeModelEvent;
33     import javax.swing.event.TreeModelListener;
34    
35     import javax.swing.tree.TreeModel;
36     import javax.swing.tree.TreePath;
37    
38     import net.sf.juife.event.TaskEvent;
39     import net.sf.juife.event.TaskListener;
40    
41     import org.jsampler.CC;
42    
43     import org.jsampler.task.InstrumentsDb;
44    
45     import org.linuxsampler.lscp.DbDirectoryInfo;
46     import org.linuxsampler.lscp.DbInstrumentInfo;
47    
48     import org.linuxsampler.lscp.event.InstrumentsDbEvent;
49     import org.linuxsampler.lscp.event.InstrumentsDbListener;
50    
51 iliev 1347 import static org.linuxsampler.lscp.Parser.*;
52    
53    
54 iliev 1204 /**
55     *
56     * @author Grigor Iliev
57     */
58     public class InstrumentsDbTreeModel implements TreeModel {
59     private DbDirectoryTreeNode root = null;
60     private Vector<TreeModelListener> listeners = new Vector<TreeModelListener>();
61    
62     /**
63     * Creates a new instance of <code>InstrumentsDbTreeModel</code>.
64     */
65     public
66     InstrumentsDbTreeModel() { this(null); }
67    
68     /**
69     * Creates a new instance of <code>InstrumentsDbTreeModel</code>.
70     * @param l A listener that will be notified when the root
71     * directory content is loaded.
72     */
73     public
74     InstrumentsDbTreeModel(final ActionListener l) {
75 iliev 1355 // TODO: This shouldn't be done in the event-dispatcing thread
76     CC.getClient().addInstrumentsDbListener(getHandler());
77     ///////
78    
79     initDb(l);
80     }
81    
82 iliev 1729 /**
83     * Creates a new instance of <code>InstrumentsDbTreeModel</code>.
84     */
85     public
86     InstrumentsDbTreeModel(boolean dummy) {
87     if(dummy) return;
88     // TODO: This shouldn't be done in the event-dispatcing thread
89     CC.getClient().addInstrumentsDbListener(getHandler());
90     ///////
91    
92     initDb(null);
93     }
94    
95 iliev 1355 private void
96     initDb(final ActionListener l) {
97 iliev 1204 final InstrumentsDb.GetDrectory gdi = new InstrumentsDb.GetDrectory("/");
98     final InstrumentsDb.GetDrectories gd = new InstrumentsDb.GetDrectories("/");
99     final InstrumentsDb.GetInstruments gi = new InstrumentsDb.GetInstruments("/");
100    
101     gdi.addTaskListener(new TaskListener() {
102     public void
103     taskPerformed(TaskEvent e) {
104     if(gdi.doneWithErrors()) return;
105     root = new DbDirectoryTreeNode(gdi.getResult());
106     fireNodeStructureChanged(root);
107    
108     CC.getTaskQueue().add(gd);
109     CC.getTaskQueue().add(gi);
110     }
111     });
112    
113     gd.addTaskListener(new TaskListener() {
114     public void
115     taskPerformed(TaskEvent e) {
116     root.setConnected(true);
117     if(gd.doneWithErrors()) return;
118     updateDirectoryContent(root, gd.getResult());
119    
120     for(int i = 0; i < root.getChildCount(); i++) {
121     DbDirectoryTreeNode node = root.getChildAt(i);
122     node.setConnected(true);
123 iliev 1347 updateDirectoryContent(node, "/" + toEscapedFileName(node));
124 iliev 1204 }
125    
126     if(l != null) l.actionPerformed(null);
127     }
128     });
129    
130     gi.addTaskListener(new TaskListener() {
131     public void
132     taskPerformed(TaskEvent e) {
133     if(gi.doneWithErrors()) return;
134     updateDirectoryContent(root, gi.getResult());
135     }
136     });
137    
138     CC.getTaskQueue().add(gdi);
139     }
140    
141     public void
142     treeWillExpand(TreePath path) {
143     DbDirectoryTreeNode node = (DbDirectoryTreeNode)path.getLastPathComponent();
144    
145     if(!node.isConnected()) {
146     node.setConnected(true);
147     updateDirectoryContent(node, node.getInfo().getDirectoryPath());
148     }
149    
150     for(int i = 0; i < node.getChildCount(); i++) {
151     DbDirectoryTreeNode child = node.getChildAt(i);
152     if(child.isConnected()) continue;
153     child.setConnected(true);
154     String pathName = getPathName(path.getPath());
155     if(pathName.length() > 1) pathName += "/";
156 iliev 1347 updateDirectoryContent(child, pathName + toEscapedFileName(child));
157 iliev 1204 }
158     }
159    
160     // Tree model methods
161     public void
162     addTreeModelListener(TreeModelListener l) {
163     listeners.add(l);
164     }
165    
166     public void
167     removeTreeModelListener(TreeModelListener l) {
168     listeners.remove(l);
169     }
170    
171     public Object
172     getChild(Object parent, int index) {
173     return ((DbDirectoryTreeNode)parent).getChildAt(index);
174     }
175    
176     public int
177     getChildCount(Object parent) {
178     return ((DbDirectoryTreeNode)parent).getChildCount();
179     }
180    
181     public Object
182     getRoot() { return root; }
183    
184     public int
185     getIndexOfChild(Object parent, Object child) {
186     if(parent == null || child == null) return -1;
187     return ((DbDirectoryTreeNode)parent).getIndex((DbDirectoryTreeNode)child);
188     }
189    
190     public boolean
191     isLeaf(Object node) { return ((DbDirectoryTreeNode)node).isLeaf(); }
192    
193     public void
194     valueForPathChanged(TreePath path, Object newValue) {
195    
196     }
197     ///////
198    
199     /**
200     * Schedules an update of the directory content for the specified directory node.
201     */
202     private void
203     updateDirectoryContent(final DbDirectoryTreeNode dirNode, String dirPath) {
204     updateDirectoryContent(dirNode, dirPath, null);
205     }
206    
207     /**
208     * Schedules an update of the directory content for the specified directory node.
209     * @param l A listener that will be notified when the subdirectory list is updated.
210     */
211     private void
212     updateDirectoryContent (
213     final DbDirectoryTreeNode dirNode, String dirPath, final ActionListener l
214     ) {
215     final InstrumentsDb.GetDrectories gd = new InstrumentsDb.GetDrectories(dirPath);
216    
217     gd.addTaskListener(new TaskListener() {
218     public void
219     taskPerformed(TaskEvent e) {
220     if(gd.doneWithErrors()) {
221     if(l != null) l.actionPerformed(null);
222     return;
223     }
224     updateDirectoryContent(dirNode, gd.getResult());
225     if(l != null) l.actionPerformed(null);
226     }
227     });
228     CC.scheduleTask(gd);
229    
230     final InstrumentsDb.GetInstruments gi = new InstrumentsDb.GetInstruments(dirPath);
231    
232     gi.addTaskListener(new TaskListener() {
233     public void
234     taskPerformed(TaskEvent e) {
235     if(gi.doneWithErrors()) return;
236     updateDirectoryContent(dirNode, gi.getResult());
237     }
238     });
239     CC.scheduleTask(gi);
240     }
241    
242     private void
243     updateDirectoryContent(DbDirectoryTreeNode parent, DbDirectoryInfo[] children) {
244     boolean found = false;
245     Vector<DbDirectoryTreeNode> removedNodes = new Vector<DbDirectoryTreeNode>();
246     for(int i = 0; i < parent.getChildCount(); i++) {
247     for(int j = 0; j < children.length; j++) {
248     if(children[j] == null) continue;
249     if(children[j].getName().equals(parent.getChildAt(i).toString())) {
250     children[j] = null;
251     found = true;
252     break;
253     }
254     }
255     if(!found) removedNodes.add(parent.getChildAt(i));
256     found = false;
257     }
258    
259     for(DbDirectoryTreeNode node : removedNodes) {
260     int i = parent.getIndex(node);
261     parent.removeDirectory(i);
262     fireNodeRemoved(parent, node, i);
263     }
264    
265     for(DbDirectoryInfo info : children) {
266     if(info == null) continue;
267     DbDirectoryTreeNode node = new DbDirectoryTreeNode(info);
268     parent.addDirectory(node);
269     fireNodeInserted(node, parent.getIndex(node));
270     if(parent.getParent() == null) {
271     node.setConnected(true);
272     updateDirectoryContent(node, info.getDirectoryPath());
273     } else if(parent.isConnected()) {
274     updateDirectoryContent(node, info.getDirectoryPath());
275     }
276     }
277     }
278    
279     private void
280     updateDirectoryContent(DbDirectoryTreeNode parent, DbInstrumentInfo[] children) {
281     boolean found = false;
282     Vector<DbInstrumentInfo> removedNodes = new Vector<DbInstrumentInfo>();
283     for(int i = 0; i < parent.getInstrumentCount(); i++) {
284     String name = parent.getInstrumentAt(i).getName();
285    
286     for(int j = 0; j < children.length; j++) {
287     if(children[j] == null) continue;
288     if(children[j].getName().equals(name)) {
289     children[j] = null;
290     found = true;
291     break;
292     }
293     }
294     if(!found) removedNodes.add(parent.getInstrumentAt(i));
295     found = false;
296     }
297    
298     for(DbInstrumentInfo info : removedNodes) {
299     int i = parent.getInstrumentIndex(info);
300     parent.removeInstrument(i);
301     }
302    
303     for(DbInstrumentInfo info : children) {
304     if(info == null) continue;
305     parent.addInstrument(info);
306     }
307     }
308    
309     /**
310     * Schedules a task for refreshing the directory content of the specified directory.
311     * Note that the specified directory is expected to be connected.
312     * @param dir The absolute path name of the directory to refresh.
313     */
314     public void
315     refreshDirectoryContent(String dir) {
316     final DbDirectoryTreeNode node = getNodeByPath(dir);
317     if(node == null) return;
318    
319     node.removeAllDirectories();
320     fireNodeStructureChanged(node);
321     node.removeAllInstruments();
322    
323     final InstrumentsDb.GetDrectories gd = new InstrumentsDb.GetDrectories(dir);
324    
325     gd.addTaskListener(new TaskListener() {
326     public void
327     taskPerformed(TaskEvent e) {
328     if(gd.doneWithErrors()) return;
329    
330     for(DbDirectoryInfo info : gd.getResult()) {
331     DbDirectoryTreeNode n = new DbDirectoryTreeNode(info);
332     node.addDirectory(n);
333     fireNodeInserted(n, node.getIndex(n));
334     n.setConnected(true);
335     updateDirectoryContent(n, n.getInfo().getDirectoryPath());
336     }
337     }
338     });
339     CC.scheduleTask(gd);
340    
341     final InstrumentsDb.GetInstruments gi = new InstrumentsDb.GetInstruments(dir);
342    
343     gi.addTaskListener(new TaskListener() {
344     public void
345     taskPerformed(TaskEvent e) {
346     if(gi.doneWithErrors()) return;
347    
348     for(DbInstrumentInfo info : gi.getResult()) {
349     node.addInstrument(info);
350     }
351     }
352     });
353     CC.scheduleTask(gi);
354     }
355    
356     protected Object[]
357     getPathToRoot(DbDirectoryTreeNode node) {
358     Vector v = new Vector();
359    
360     while(node != null) {
361     v.insertElementAt(node, 0);
362     if(node == getRoot()) break;
363     node = node.getParent();
364     }
365    
366     return v.toArray(new Object[v.size()]);
367     }
368    
369     protected String
370     getPathName(Object[] objs) {
371     if(objs.length == 1) return "/";
372    
373     StringBuffer sb = new StringBuffer();
374     for(int i = 1; i < objs.length; i++) {
375 iliev 1347 sb.append('/').append(toEscapedFileName(objs[i]));
376 iliev 1204 }
377    
378     return sb.toString();
379     }
380    
381     private void
382     fireNodeInserted(DbDirectoryTreeNode node, int index) {
383     Object[] path = getPathToRoot(node.getParent());
384     int[] idxs = { index };
385     Object[] objs = { node };
386     TreeModelEvent e = new TreeModelEvent(this, path, idxs, objs);
387     for(TreeModelListener l : listeners) {
388     l.treeNodesInserted(e);
389     }
390     }
391    
392     private void
393     fireNodeChanged(DbDirectoryTreeNode node, int index) {
394     Object[] path = getPathToRoot(node.getParent());
395     int[] idxs = { index };
396     Object[] objs = { node };
397     TreeModelEvent e = new TreeModelEvent(this, path, idxs, objs);
398     for(TreeModelListener l : listeners) {
399     l.treeNodesChanged(e);
400     }
401     }
402    
403     private void
404     fireNodeRemoved(DbDirectoryTreeNode parent, DbDirectoryTreeNode node, int index) {
405     Object[] path = getPathToRoot(parent);
406     int[] idxs = { index };
407     Object[] objs = { node };
408     TreeModelEvent e = new TreeModelEvent(this, path, idxs, objs);
409     for(int i = listeners.size() - 1; i >=0; i--) {
410     listeners.get(i).treeNodesRemoved(e);
411     }
412     }
413    
414     private void
415     fireNodeStructureChanged(DbDirectoryTreeNode node) {
416     Object[] path = getPathToRoot(node);
417     Object[] objs = { node };
418     TreeModelEvent e = new TreeModelEvent(this, path);
419     for(TreeModelListener l : listeners) {
420     l.treeStructureChanged(e);
421     }
422     }
423    
424     public DbDirectoryTreeNode
425     getNodeByPath(String path) {
426 iliev 1347 String[] dirs = getDirectoryList(path);
427 iliev 1204 if(dirs == null) return null;
428     if(dirs.length == 1) return root;
429 iliev 1355 if(root == null) return null;
430 iliev 1204 DbDirectoryTreeNode node = root;
431     boolean found = false;
432     for(int i = 1; i < dirs.length; i++) {
433     for(int k = 0; k < node.getChildCount(); k++) {
434 iliev 1347 String s = toNonEscapedFileName(dirs[i]);
435     if(s.equals(node.getChildAt(k).toString())) {
436 iliev 1204 node = node.getChildAt(k);
437     found = true;
438     break;
439     }
440     }
441    
442     if(!found) return null;
443     found = false;
444     }
445    
446     return node;
447     }
448    
449     public String
450     getPathByNode(DbDirectoryTreeNode node) {
451     if(node == null) return null;
452     return getPathName(getPathToRoot(node));
453     }
454    
455     /**
456     * @param l A listener which will be notified when the operation is completed.
457     */
458     public void
459     loadPath(String path, final ActionListener l) {
460     // TODO: This method is lazily implemented. Should be optimized.
461 iliev 1347 final String[] dirs = getDirectoryList(path);
462 iliev 1204 if(dirs == null) {
463     l.actionPerformed(null);
464     return;
465     }
466    
467     final ActionListener listener = new ActionListener() {
468     public void
469     actionPerformed(ActionEvent e) {
470     String s = "";
471     DbDirectoryTreeNode node = null;
472     for(int i = 0; i < dirs.length; i++) {
473     if(i > 1) s += "/" + dirs[i];
474     else s += dirs[i];
475     node = getNodeByPath(s);
476     if(node == null) {
477     if(l != null) l.actionPerformed(null);
478     return;
479     }
480    
481     if(!node.isConnected()) {
482     node.setConnected(true);
483     updateDirectoryContent(node, s, this);
484     return;
485     }
486     }
487    
488     if(l != null) l.actionPerformed(null);
489     }
490     };
491    
492     listener.actionPerformed(null);
493     }
494    
495 iliev 1688 /** Resets this model. */
496     public void
497     reset() {
498     DbDirectoryTreeNode oldRoot = root;
499     root = null;
500     TreeModelEvent e = new TreeModelEvent(this, (TreePath)null);
501     for(TreeModelListener l : listeners) {
502     l.treeStructureChanged(e);
503     }
504     }
505    
506 iliev 1204 private final EventHandler eventHandler = new EventHandler();
507    
508     private EventHandler
509     getHandler() { return eventHandler; }
510    
511     private class EventHandler implements InstrumentsDbListener {
512     /**
513     * Invoked when the number of instrument
514     * directories in a specific directory has changed.
515     */
516     public void
517     directoryCountChanged(final InstrumentsDbEvent e) {
518     SwingUtilities.invokeLater(new Runnable() {
519     public void
520 iliev 1355 run() { updateDirectoryCount(e); }
521 iliev 1204 });
522     }
523    
524 iliev 1355 private void
525     updateDirectoryCount(InstrumentsDbEvent e) {
526     if(e.getPathName().equals("/") && root == null) {
527     /*
528     * If the directory tree failed to load due to a database
529     * corruption it may work now if the db has been formatted
530     */
531     initDb(null);
532     }
533    
534     DbDirectoryTreeNode node = getNodeByPath(e.getPathName());
535     if(node == null) return;
536     if(!node.isConnected()) return;
537    
538     updateDirectoryContent(node, e.getPathName());
539     }
540    
541 iliev 1204 /**
542     * Invoked when the settings of an instrument directory are changed.
543     */
544     public void
545     directoryInfoChanged(final InstrumentsDbEvent e) {
546     SwingUtilities.invokeLater(new Runnable() {
547     public void
548     run() { updateDirectoryInfo(e); }
549     });
550     }
551    
552     private void
553     updateDirectoryInfo(InstrumentsDbEvent e) {
554     final DbDirectoryTreeNode node = getNodeByPath(e.getPathName());
555     if(node == null) return;
556    
557     final InstrumentsDb.GetDrectory t =
558     new InstrumentsDb.GetDrectory(e.getPathName());
559    
560     t.addTaskListener(new TaskListener() {
561     public void
562     taskPerformed(TaskEvent e) {
563     if(t.doneWithErrors()) return;
564     if(node.getParent() != null) {
565     node.getParent().updateDirectory(t.getResult());
566     fireNodeChanged(node, node.getParent().getIndex(node));
567     }
568     }
569     });
570    
571     CC.getTaskQueue().add(t);
572     }
573    
574     /**
575     * Invoked when an instrument directory is renamed.
576     */
577     public void
578     directoryNameChanged(final InstrumentsDbEvent e) {
579     SwingUtilities.invokeLater(new Runnable() {
580     public void
581     run() { directoryRenamed(e); }
582     });
583     }
584    
585     private void
586     directoryRenamed(InstrumentsDbEvent e) {
587     DbDirectoryTreeNode node = getNodeByPath(e.getPathName());
588     if(node == null) {
589     // If the directory is renamed by this frontend the
590     // directory should already be with the new name
591     String s = getParentDirectory(e.getPathName());
592 iliev 1347 if(s.length() == 1) s += toEscapedFileName(e.getNewName());
593     else s += "/" + toEscapedFileName(e.getNewName());
594 iliev 1204 node = getNodeByPath(s);
595     }
596     if(node == null || node.getParent() == null) {
597     CC.getLogger().warning("Invalid path: " + e.getPathName());
598     return;
599     }
600    
601 iliev 1352 node.setName(e.getNewName());
602 iliev 1204 DbDirectoryTreeNode parent = node.getParent();
603    
604     int i = parent.getIndex(node);
605     parent.removeDirectory(i);
606     fireNodeRemoved(parent, node, i);
607    
608     parent.addDirectory(node);
609     fireNodeInserted(node, parent.getIndex(node));
610     }
611    
612     /**
613     * Invoked when the number of instruments
614     * in a specific directory has changed.
615     */
616     public void
617     instrumentCountChanged(final InstrumentsDbEvent e) {
618     SwingUtilities.invokeLater(new Runnable() {
619     public void
620     run() {
621     DbDirectoryTreeNode node = getNodeByPath(e.getPathName());
622     if(node == null) {
623     return;
624     }
625     if(!node.isConnected()) {
626     return;
627     }
628    
629     updateDirectoryContent(node, e.getPathName());
630     }
631     });
632     }
633    
634     /**
635     * Invoked when the settings of an instrument are changed.
636     */
637     public void
638     instrumentInfoChanged(final InstrumentsDbEvent e) {
639     SwingUtilities.invokeLater(new Runnable() {
640     public void
641     run() { updateInstrumentInfo(e); }
642     });
643     }
644    
645     /**
646     * Invoked when an instrument is renamed.
647     */
648     public void
649     instrumentNameChanged(final InstrumentsDbEvent e) {
650     SwingUtilities.invokeLater(new Runnable() {
651     public void
652     run() { instrumentRenamed(e); }
653     });
654     }
655    
656     private void
657     updateInstrumentInfo(InstrumentsDbEvent e) {
658     String dir = getParentDirectory(e.getPathName());
659     final DbDirectoryTreeNode node = getNodeByPath(dir);
660     if(node == null) return;
661     if(!node.isConnected()) return;
662    
663     final InstrumentsDb.GetInstrument t =
664     new InstrumentsDb.GetInstrument(e.getPathName());
665    
666     t.addTaskListener(new TaskListener() {
667     public void
668     taskPerformed(TaskEvent e) {
669     if(t.doneWithErrors()) return;
670     node.updateInstrument(t.getResult());
671     }
672     });
673    
674     CC.getTaskQueue().add(t);
675     }
676    
677     private void
678     instrumentRenamed(InstrumentsDbEvent e) {
679     String dir = getParentDirectory(e.getPathName());
680     DbDirectoryTreeNode node = getNodeByPath(dir);
681     if(node == null) return;
682    
683 iliev 1347 String instr = getFileName(e.getPathName());
684     if(instr == null) return;
685 iliev 1204
686 iliev 1352 DbInstrumentInfo info = node.getInstrument(toNonEscapedFileName(instr));
687 iliev 1204
688     if(info == null) {
689     // If the instrument is renamed by this frontend the
690     // instrument should already be with the new name
691     info = node.getInstrument(e.getNewName());
692     }
693     if(info == null) {
694     CC.getLogger().warning("Invalid path: " + e.getPathName());
695     return;
696     }
697    
698     info.setName(e.getNewName());
699     node.removeInstrument(node.getInstrumentIndex(info));
700     node.addInstrument(info);
701     }
702    
703     /** Invoked when the status of particular job has changed. */
704     public void
705     jobStatusChanged(InstrumentsDbEvent e) { }
706     }
707     }

  ViewVC Help
Powered by ViewVC