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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1347 - (show annotations) (download)
Thu Sep 13 22:20:38 2007 UTC (16 years, 7 months ago) by iliev
File size: 18020 byte(s)
* added support for escape sequences to the instruments database

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

  ViewVC Help
Powered by ViewVC