/[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 1688 - (hide annotations) (download)
Thu Feb 14 16:52:36 2008 UTC (16 years, 2 months ago) by iliev
File size: 18643 byte(s)
* Implemented a backend list with option to manually choose a backend
  to connect on startup(Edit/Preferences, then click the `Backend' tab)
  and option to change the backend without restarting JSampler
  (Actions/Change Backend or Ctrl + B)

* Added confirmation messages for removing sampler channels and
  audio/MIDI devices (Edit/Preferences, then click the `View' tab)

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

  ViewVC Help
Powered by ViewVC