/[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 1204 - (hide annotations) (download)
Thu May 24 21:43:45 2007 UTC (16 years, 11 months ago) by iliev
File size: 18907 byte(s)
upgrading to version 0.5a

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

  ViewVC Help
Powered by ViewVC