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

Contents of /jsampler/trunk/src/org/jsampler/view/std/JSMidiInstrumentTree.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1746 - (show annotations) (download)
Mon Jun 2 03:33:11 2008 UTC (15 years, 10 months ago) by iliev
File size: 13145 byte(s)
* Orchestras, orchestra instruments, MIDI maps and MIDI instruments
  can now be removed using the `Delete' key from the keyboard
* Fantasia: Aligned the numbering of sampler channel 10

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2008 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.std;
24
25 import java.awt.event.ActionEvent;
26 import java.awt.event.ActionListener;
27 import java.awt.event.KeyEvent;
28 import java.awt.event.MouseAdapter;
29 import java.awt.event.MouseEvent;
30
31 import javax.swing.AbstractAction;
32 import javax.swing.Action;
33 import javax.swing.JComponent;
34 import javax.swing.JMenuItem;
35 import javax.swing.JPopupMenu;
36 import javax.swing.JTree;
37 import javax.swing.KeyStroke;
38
39 import javax.swing.event.TreeSelectionEvent;
40 import javax.swing.event.TreeSelectionListener;
41
42 import javax.swing.tree.DefaultMutableTreeNode;
43 import javax.swing.tree.DefaultTreeModel;
44 import javax.swing.tree.TreeSelectionModel;
45
46 import org.jsampler.CC;
47 import org.jsampler.HF;
48 import org.jsampler.MidiInstrument;
49 import org.jsampler.MidiInstrumentMap;
50
51 import org.jsampler.event.MidiInstrumentEvent;
52 import org.jsampler.event.MidiInstrumentListener;
53 import org.jsampler.event.MidiInstrumentMapEvent;
54 import org.jsampler.event.MidiInstrumentMapListener;
55
56 import org.linuxsampler.lscp.MidiInstrumentInfo;
57 import org.linuxsampler.lscp.MidiInstrumentMapInfo;
58
59 import static org.jsampler.view.std.StdI18n.i18n;
60
61
62 /**
63 *
64 * @author Grigor Iliev
65 */
66 public class JSMidiInstrumentTree extends JTree {
67 private DefaultTreeModel model;
68 private MidiInstrumentMap midiInstrumentMap;
69
70 /**
71 * Creates a new instance of <code>JSMidiInstrumentTree</code>
72 */
73 public
74 JSMidiInstrumentTree() {
75 setRootVisible(false);
76 setShowsRootHandles(true);
77 setEditable(false);
78
79 addMouseListener(new MouseAdapter() {
80 public void
81 mousePressed(MouseEvent e) {
82 if(e.getButton() != e.BUTTON3) return;
83 setSelectionPath(getClosestPathForLocation(e.getX(), e.getY()));
84 }
85
86 public void
87 mouseClicked(MouseEvent e) {
88 if(e.getButton() != e.BUTTON1) return;
89 if(e.getClickCount() > 1) editSelectedInstrument();
90 }
91 });
92
93 setMidiInstrumentMap(null);
94
95 getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
96 ContextMenu contextMenu = new ContextMenu();
97 addMouseListener(contextMenu);
98 addTreeSelectionListener(contextMenu);
99
100 Action a = new AbstractAction() {
101 public void
102 actionPerformed(ActionEvent e) {
103 removeSelectedInstrumentOrBank();
104 }
105 };
106
107 KeyStroke k = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
108 getInputMap(JComponent.WHEN_FOCUSED).put(k, "removeSelectedInstrumentOrBank");
109 getActionMap().put("removeSelectedInstrumentOrBank", a);
110 }
111
112 /**
113 * Gets the MIDI instrument map that is represented by this MIDI instrument tree.
114 * @return The MIDI instrument map that is represented by this MIDI instrument tree.
115 */
116 public MidiInstrumentMap
117 getMidiInstrumentMap() { return midiInstrumentMap; }
118
119 /**
120 * Sets the MIDI instrument map to be represented by this MIDI instrument tree.
121 * @param map The MIDI instrument map to be represented by this MIDI instrument tree.
122 */
123 public void
124 setMidiInstrumentMap(MidiInstrumentMap map) {
125 if(getMidiInstrumentMap() != null) {
126 for(MidiInstrument instr : getMidiInstrumentMap().getAllMidiInstruments()) {
127 instr.removeMidiInstrumentListener(getHandler());
128 }
129
130 getMidiInstrumentMap().removeMidiInstrumentMapListener(getHandler());
131 }
132
133 midiInstrumentMap = map;
134
135 DefaultMutableTreeNode root = new DefaultMutableTreeNode() {
136 public boolean
137 isLeaf() { return false; }
138
139 public Object
140 getUserObject() { return "/"; }
141 };
142
143 model = new DefaultTreeModel(root);
144
145 if(map != null) {
146 for(MidiInstrument instr : map.getAllMidiInstruments()) {
147 mapInstrument(instr);
148 instr.addMidiInstrumentListener(getHandler());
149 }
150
151 map.addMidiInstrumentMapListener(getHandler());
152 }
153
154 setEnabled(map != null);
155
156 setModel(model);
157 }
158
159 /**
160 * Adds the specified MIDI instrument to this tree.
161 * @param instr The MIDI instrument to add.
162 */
163 public void
164 mapInstrument(MidiInstrument instr) {
165 MidiBank bank = new MidiBank(instr.getInfo().getMidiBank());
166 DefaultMutableTreeNode bankNode = findBank(bank);
167
168 if(bankNode == null) {
169 bankNode = new BankTreeNode(bank);
170
171 model.insertNodeInto (
172 bankNode,
173 (DefaultMutableTreeNode)model.getRoot(),
174 findBankPosition(bank.getID())
175 );
176 }
177
178 model.insertNodeInto (
179 new InstrTreeNode(instr),
180 bankNode,
181 removeProgram(bankNode, instr.getInfo().getMidiProgram())
182 );
183 }
184
185 /**
186 * Removes the specified MIDI instrument from the tree.
187 * @param instr The MIDI instrument to remove.
188 * @throws IllegalArgumentException If the specified instrument is not found.
189 */
190 public void
191 unmapInstrument(MidiInstrument instr) {
192 MidiBank bank = new MidiBank(instr.getInfo().getMidiBank());
193 DefaultMutableTreeNode bankNode = findBank(bank);
194
195 if(bankNode == null)
196 throw new IllegalArgumentException("Missing MIDI bank: " + bank.getID());
197
198 removeProgram(bankNode, instr.getInfo().getMidiProgram());
199 if(bankNode.getChildCount() == 0) model.removeNodeFromParent(bankNode);
200 }
201
202 /**
203 * Gets the selected MIDI instrument.
204 * @return The selected MIDI instrument, or
205 * <code>null</code> if there is no MIDI instrument selected.
206 */
207 public MidiInstrument
208 getSelectedInstrument() {
209 if(getSelectionCount() == 0) return null;
210 Object obj = getSelectionPath().getLastPathComponent();
211 if(!(obj instanceof InstrTreeNode)) return null;
212 obj = ((InstrTreeNode)obj).getUserObject();
213 return (MidiInstrument)obj;
214 }
215
216 /**
217 * Removes (on the backend side) the selected MIDI instrument or MIDI bank.
218 */
219 public void
220 removeSelectedInstrumentOrBank() {
221 if(getSelectionCount() == 0) return;
222
223 Object obj = getSelectionPath().getLastPathComponent();
224 if(obj instanceof InstrTreeNode) {
225 obj = ((InstrTreeNode)obj).getUserObject();
226 removeInstrument((MidiInstrument)obj);
227 } else if(obj instanceof BankTreeNode) {
228 BankTreeNode n = (BankTreeNode)obj;
229 int c = n.getChildCount();
230 if(c > 1) {
231 String s;
232 s = i18n.getMessage("JSMidiInstrumentTree.removeInstruments?", c);
233 if(!HF.showYesNoDialog(CC.getMainFrame(), s)) return;
234 }
235
236 for(int i = c - 1; i >= 0; i--) {
237 obj = ((InstrTreeNode)n.getChildAt(i)).getUserObject();
238 removeInstrument((MidiInstrument)obj);
239 }
240 }
241 }
242
243 /**
244 * Removes (on the backend side) the specified MIDI instrument.
245 */
246 private void
247 removeInstrument(MidiInstrument instr) {
248 MidiInstrumentInfo i = instr.getInfo();
249 CC.getSamplerModel().unmapBackendMidiInstrument (
250 i.getMapId(), i.getMidiBank(), i.getMidiProgram()
251 );
252 }
253
254 /**
255 * Returns the position, where the specified bank should be inserted.
256 */
257 private int
258 findBankPosition(int bankID) {
259 DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();
260
261 for(int i = 0; i < root.getChildCount(); i++) {
262 DefaultMutableTreeNode node = (DefaultMutableTreeNode)root.getChildAt(i);
263 MidiBank bank = (MidiBank)node.getUserObject();
264 if(bank.getID() > bankID) return i;
265 }
266
267 return root.getChildCount();
268 }
269
270 /**
271 * If there is already an instrument with MIDI program <code>program</code>,
272 * those instrument is removed from the tree.
273 * @return The position, where the instrument of the specified program should be inserted.
274 */
275 private int
276 removeProgram(DefaultMutableTreeNode bankNode, int program) {
277
278 for(int i = 0; i < bankNode.getChildCount(); i++) {
279 DefaultMutableTreeNode n = (DefaultMutableTreeNode)bankNode.getChildAt(i);
280 MidiInstrument instr = (MidiInstrument)n.getUserObject();
281
282 if(instr.getInfo().getMidiProgram() == program) {
283 model.removeNodeFromParent(n);
284 return i;
285 }
286
287 if(instr.getInfo().getMidiProgram() > program) return i;
288 }
289
290 return bankNode.getChildCount();
291 }
292
293 private DefaultMutableTreeNode
294 findNode(DefaultMutableTreeNode parent, Object obj) {
295 for(int i = 0; i < parent.getChildCount(); i++) {
296 DefaultMutableTreeNode node = (DefaultMutableTreeNode)parent.getChildAt(i);
297 if(node.getUserObject().equals(obj)) return node;
298 }
299
300 return null;
301 }
302
303 private DefaultMutableTreeNode
304 findBank(Object obj) {
305 return findNode((DefaultMutableTreeNode)model.getRoot(), obj);
306 }
307
308 private DefaultMutableTreeNode
309 findInstrument(Object obj) {
310 if(obj == null || !(obj instanceof MidiInstrument)) return null;
311 MidiInstrument i = (MidiInstrument) obj;
312 DefaultMutableTreeNode bank = findBank(new MidiBank(i.getInfo().getMidiBank()));
313 if(bank == null) return null;
314 return findNode(bank, obj);
315 }
316
317
318 private class MidiBank {
319 int id;
320
321 MidiBank(int id) {
322 this.id = id;
323 }
324
325 public int
326 getID() { return id; }
327
328 public boolean
329 equals(Object obj) {
330 if(obj == null) return false;
331 if(!(obj instanceof MidiBank)) return false;
332 if(getID() == ((MidiBank)obj).getID()) return true;
333 return false;
334 }
335
336 public String
337 toString() { return i18n.getLabel("JSMidiInstrumentTree.MidiBank.name", id); }
338 }
339
340 protected class BankTreeNode extends DefaultMutableTreeNode {
341 BankTreeNode(Object obj) {
342 super(obj);
343 }
344
345 public void
346 setUserObject(Object userObject) {
347 if(userObject instanceof MidiBank) {
348 super.setUserObject(userObject);
349 return;
350 }
351
352 // If we are here, this means that tree editing occurs.
353 CC.getLogger().info("MidiInstrumentTree: editing not supported");
354 }
355
356 public boolean
357 isLeaf() { return false; }
358 }
359
360 protected class InstrTreeNode extends DefaultMutableTreeNode {
361 InstrTreeNode(Object obj) {
362 super(obj);
363 }
364
365 public void
366 setUserObject(Object userObject) {
367 if(userObject instanceof MidiInstrument) {
368 super.setUserObject(userObject);
369 return;
370 }
371
372 // If we are here, this means that tree editing occurs.
373 CC.getLogger().info("MidiInstrumentTree: editing not supported");
374 }
375
376 public boolean
377 isLeaf() { return true; }
378 }
379
380 private void
381 editSelectedInstrument() {
382 MidiInstrument i = getSelectedInstrument();
383 if(i == null) return;
384 JSEditMidiInstrumentDlg dlg = new JSEditMidiInstrumentDlg(i.getInfo());
385 dlg.setVisible(true);
386
387 if(dlg.isCancelled()) return;
388
389 MidiInstrumentInfo info = dlg.getInstrument();
390 CC.getSamplerModel().mapBackendMidiInstrument (
391 info.getMapId(), info.getMidiBank(), info.getMidiProgram(), info
392 );
393 }
394
395 private final EventHandler eventHandler = new EventHandler();
396
397 private EventHandler
398 getHandler() { return eventHandler; }
399
400 private class EventHandler implements MidiInstrumentListener, MidiInstrumentMapListener {
401
402 /** Invoked when a MIDI instrument in a MIDI instrument map is changed. */
403 public void
404 instrumentInfoChanged(MidiInstrumentEvent e) {
405 DefaultMutableTreeNode n = findInstrument(e.getSource());
406 if(n != null) model.nodeChanged(n);
407 }
408
409 /** Invoked when the name of MIDI instrument map is changed. */
410 public void nameChanged(MidiInstrumentMapEvent e) { }
411
412 /** Invoked when an instrument is added to a MIDI instrument map. */
413 public void
414 instrumentAdded(MidiInstrumentMapEvent e) {
415 e.getInstrument().addMidiInstrumentListener(getHandler());
416 mapInstrument(e.getInstrument());
417
418 }
419
420 /** Invoked when an instrument is removed from a MIDI instrument map. */
421 public void
422 instrumentRemoved(MidiInstrumentMapEvent e) {
423 unmapInstrument(e.getInstrument());
424 e.getInstrument().removeMidiInstrumentListener(getHandler());
425 }
426 }
427
428 class ContextMenu extends MouseAdapter implements TreeSelectionListener {
429 private final JPopupMenu cmenu = new JPopupMenu();
430 JMenuItem miEdit = new JMenuItem(i18n.getMenuLabel("ContextMenu.edit"));
431
432 ContextMenu() {
433 cmenu.add(miEdit);
434 miEdit.addActionListener(new ActionListener() {
435 public void
436 actionPerformed(ActionEvent e) {
437 editSelectedInstrument();
438 }
439 });
440
441 JMenuItem mi = new JMenuItem(i18n.getMenuLabel("ContextMenu.delete"));
442 cmenu.add(mi);
443 mi.addActionListener(new ActionListener() {
444 public void
445 actionPerformed(ActionEvent e) {
446 removeSelectedInstrumentOrBank();
447 }
448 });
449
450 }
451
452 public void
453 mousePressed(MouseEvent e) {
454 if(e.isPopupTrigger()) show(e);
455 }
456
457 public void
458 mouseReleased(MouseEvent e) {
459 if(e.isPopupTrigger()) show(e);
460 }
461
462 void
463 show(MouseEvent e) {
464 if(getSelectionCount() == 0) return;
465 cmenu.show(e.getComponent(), e.getX(), e.getY());
466 }
467
468 public void
469 valueChanged(TreeSelectionEvent e) {
470 miEdit.setVisible(getSelectedInstrument() != null);
471 }
472 }
473 }

  ViewVC Help
Powered by ViewVC