/[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 1767 - (show annotations) (download)
Mon Sep 8 00:19:27 2008 UTC (15 years, 6 months ago) by iliev
File size: 26863 byte(s)
* Added `Copy To' and `Move To' commands to the MIDI bank context menu
  and to the MIDI instrument context menu
* Added commands to the MIDI instrument context menu for moving
  a MIDI instrument to another program
  (right-click on a MIDI instrument and choose `Change Program')
* Added option to choose between zero-based and one-based
  MIDI bank/program numbering
  (choose Edit/Preferences, then click the `Advanced' button)
* Added option to choose whether to include MIDI instrument
  mappings when exporting a sampler configuration to LSCP script.
  (choose Edit/Preferences, then click the `Advanced' button)
* Added option to set the MIDI instrument loading in background
  when exporting MIDI instrument mappings to LSCP script.
  (choose Edit/Preferences, then click the `Advanced' button)
* Implemented an option to change the socket read timeout
  (choose Edit/Preferences, then click the `Backend' tab)
* Updated LscpTree
* Fantasia: Added option to hide the active stream/voice count statistic
  in the sampler channel's small view
  (choose Edit/Preferences, then click the `Channels' tab)
* Fantasia: `Turn off animation effects' checkbox moved to the `View' tab

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.Dimension;
26
27 import java.beans.PropertyChangeEvent;
28 import java.beans.PropertyChangeListener;
29
30 import java.awt.event.ActionEvent;
31 import java.awt.event.ActionListener;
32 import java.awt.event.KeyEvent;
33 import java.awt.event.MouseAdapter;
34 import java.awt.event.MouseEvent;
35
36 import java.util.Vector;
37
38 import javax.swing.AbstractAction;
39 import javax.swing.Action;
40 import javax.swing.Box;
41 import javax.swing.BoxLayout;
42 import javax.swing.JComponent;
43 import javax.swing.JLabel;
44 import javax.swing.JMenu;
45 import javax.swing.JMenuItem;
46 import javax.swing.JPanel;
47 import javax.swing.JPopupMenu;
48 import javax.swing.JScrollPane;
49 import javax.swing.JTable;
50 import javax.swing.JTree;
51 import javax.swing.KeyStroke;
52
53 import javax.swing.event.TreeSelectionEvent;
54 import javax.swing.event.TreeSelectionListener;
55
56 import javax.swing.tree.DefaultMutableTreeNode;
57 import javax.swing.tree.DefaultTreeModel;
58 import javax.swing.tree.TreeSelectionModel;
59
60 import org.jsampler.CC;
61 import org.jsampler.HF;
62 import org.jsampler.MidiInstrument;
63 import org.jsampler.MidiInstrumentMap;
64
65 import org.jsampler.event.MidiInstrumentEvent;
66 import org.jsampler.event.MidiInstrumentListener;
67 import org.jsampler.event.MidiInstrumentMapEvent;
68 import org.jsampler.event.MidiInstrumentMapListener;
69
70 import org.linuxsampler.lscp.MidiInstrumentInfo;
71 import org.linuxsampler.lscp.MidiInstrumentMapInfo;
72
73 import net.sf.juife.OkCancelDialog;
74
75 import static org.jsampler.JSPrefs.FIRST_MIDI_BANK_NUMBER;
76 import static org.jsampler.JSPrefs.FIRST_MIDI_PROGRAM_NUMBER;
77 import static org.jsampler.view.std.StdI18n.i18n;
78
79
80 /**
81 *
82 * @author Grigor Iliev
83 */
84 public class JSMidiInstrumentTree extends JTree {
85 private DefaultTreeModel model;
86 private MidiInstrumentMap midiInstrumentMap;
87 private final ContextMenu contextMenu;
88
89 /**
90 * Creates a new instance of <code>JSMidiInstrumentTree</code>
91 */
92 public
93 JSMidiInstrumentTree() {
94 setRootVisible(false);
95 setShowsRootHandles(true);
96 setEditable(false);
97
98 addMouseListener(new MouseAdapter() {
99 public void
100 mousePressed(MouseEvent e) {
101 if(e.getButton() != e.BUTTON3) return;
102 setSelectionPath(getClosestPathForLocation(e.getX(), e.getY()));
103 }
104
105 public void
106 mouseClicked(MouseEvent e) {
107 if(e.getButton() != e.BUTTON1) return;
108 if(e.getClickCount() > 1) editSelectedInstrument();
109 }
110 });
111
112 setMidiInstrumentMap(null);
113
114 getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
115 contextMenu = new ContextMenu();
116 addMouseListener(contextMenu);
117
118 addTreeSelectionListener(getHandler());
119
120 Action a = new AbstractAction() {
121 public void
122 actionPerformed(ActionEvent e) {
123 removeSelectedInstrumentOrBank();
124 }
125 };
126
127 KeyStroke k = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
128 getInputMap(JComponent.WHEN_FOCUSED).put(k, "removeSelectedInstrumentOrBank");
129 getActionMap().put("removeSelectedInstrumentOrBank", a);
130
131 String s = FIRST_MIDI_BANK_NUMBER;
132 CC.preferences().addPropertyChangeListener(s, new PropertyChangeListener() {
133 public void
134 propertyChange(PropertyChangeEvent e) {
135 model.reload();
136 }
137 });
138
139 s = FIRST_MIDI_PROGRAM_NUMBER;
140 CC.preferences().addPropertyChangeListener(s, new PropertyChangeListener() {
141 public void
142 propertyChange(PropertyChangeEvent e) {
143 model.reload();
144 contextMenu.updateChangeProgramMenu();
145 }
146 });
147 }
148
149 /**
150 * Gets the MIDI instrument map that is represented by this MIDI instrument tree.
151 * @return The MIDI instrument map that is represented by this MIDI instrument tree.
152 */
153 public MidiInstrumentMap
154 getMidiInstrumentMap() { return midiInstrumentMap; }
155
156 /**
157 * Sets the MIDI instrument map to be represented by this MIDI instrument tree.
158 * @param map The MIDI instrument map to be represented by this MIDI instrument tree.
159 */
160 public void
161 setMidiInstrumentMap(MidiInstrumentMap map) {
162 if(getMidiInstrumentMap() != null) {
163 for(MidiInstrument instr : getMidiInstrumentMap().getAllMidiInstruments()) {
164 instr.removeMidiInstrumentListener(getHandler());
165 }
166
167 getMidiInstrumentMap().removeMidiInstrumentMapListener(getHandler());
168 }
169
170 midiInstrumentMap = map;
171
172 DefaultMutableTreeNode root = new DefaultMutableTreeNode() {
173 public boolean
174 isLeaf() { return false; }
175
176 public Object
177 getUserObject() { return "/"; }
178 };
179
180 model = new DefaultTreeModel(root);
181
182 if(map != null) {
183 for(MidiInstrument instr : map.getAllMidiInstruments()) {
184 mapInstrument(instr);
185 instr.addMidiInstrumentListener(getHandler());
186 }
187
188 map.addMidiInstrumentMapListener(getHandler());
189 }
190
191 setEnabled(map != null);
192
193 setModel(model);
194 }
195
196 /**
197 * Adds the specified MIDI instrument to this tree.
198 * @param instr The MIDI instrument to add.
199 */
200 public void
201 mapInstrument(MidiInstrument instr) {
202 MidiBank bank = new MidiBank(instr.getInfo().getMidiBank());
203 DefaultMutableTreeNode bankNode = findBank(bank);
204
205 if(bankNode == null) {
206 bankNode = new BankTreeNode(bank);
207
208 model.insertNodeInto (
209 bankNode,
210 (DefaultMutableTreeNode)model.getRoot(),
211 findBankPosition(bank.getId())
212 );
213 }
214
215 model.insertNodeInto (
216 new InstrTreeNode(instr),
217 bankNode,
218 removeProgram(bankNode, instr.getInfo().getMidiProgram())
219 );
220 }
221
222 /**
223 * Removes the specified MIDI instrument from the tree.
224 * @param instr The MIDI instrument to remove.
225 * @throws IllegalArgumentException If the specified instrument is not found.
226 */
227 public void
228 unmapInstrument(MidiInstrument instr) {
229 MidiBank bank = new MidiBank(instr.getInfo().getMidiBank());
230 DefaultMutableTreeNode bankNode = findBank(bank);
231
232 if(bankNode == null)
233 throw new IllegalArgumentException("Missing MIDI bank: " + bank.getId());
234
235 removeProgram(bankNode, instr.getInfo().getMidiProgram());
236 if(bankNode.getChildCount() == 0) model.removeNodeFromParent(bankNode);
237 }
238
239 /**
240 * Gets the selected MIDI instrument.
241 * @return The selected MIDI instrument, or
242 * <code>null</code> if there is no MIDI instrument selected.
243 */
244 public MidiInstrument
245 getSelectedInstrument() {
246 if(getSelectionCount() == 0) return null;
247 Object obj = getSelectionPath().getLastPathComponent();
248 if(!(obj instanceof InstrTreeNode)) return null;
249 obj = ((InstrTreeNode)obj).getUserObject();
250 return (MidiInstrument)obj;
251 }
252
253 /**
254 * Gets the selected MIDI bank.
255 * @return The selected MIDI bank, or
256 * <code>null</code> if there is no MIDI bank selected.
257 */
258 public MidiBank
259 getSelectedMidiBank() {
260 if(getSelectionCount() == 0) return null;
261
262 Object obj = getSelectionPath().getLastPathComponent();
263 if(!(obj instanceof BankTreeNode)) return null;
264
265 BankTreeNode n = (BankTreeNode)obj;
266 return (MidiBank)n.getUserObject();
267 }
268
269 /**
270 * Removes (on the backend side) the selected MIDI instrument or MIDI bank.
271 */
272 public void
273 removeSelectedInstrumentOrBank() {
274 if(getSelectionCount() == 0) return;
275
276 Object obj = getSelectionPath().getLastPathComponent();
277 if(obj instanceof InstrTreeNode) {
278 obj = ((InstrTreeNode)obj).getUserObject();
279 removeInstrument((MidiInstrument)obj);
280 } else if(obj instanceof BankTreeNode) {
281 BankTreeNode n = (BankTreeNode)obj;
282 int c = n.getChildCount();
283 if(c > 1) {
284 String s;
285 s = i18n.getMessage("JSMidiInstrumentTree.removeInstruments?", c);
286 if(!HF.showYesNoDialog(CC.getMainFrame(), s)) return;
287 }
288
289 for(int i = c - 1; i >= 0; i--) {
290 obj = ((InstrTreeNode)n.getChildAt(i)).getUserObject();
291 removeInstrument((MidiInstrument)obj);
292 }
293 }
294 }
295
296 /**
297 * Removes (on the backend side) the specified MIDI instrument.
298 */
299 private void
300 removeInstrument(MidiInstrument instr) {
301 MidiInstrumentInfo i = instr.getInfo();
302 CC.getSamplerModel().unmapBackendMidiInstrument (
303 i.getMapId(), i.getMidiBank(), i.getMidiProgram()
304 );
305 }
306
307 /**
308 * Returns the position, where the specified bank should be inserted.
309 */
310 private int
311 findBankPosition(int bankID) {
312 DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();
313
314 for(int i = 0; i < root.getChildCount(); i++) {
315 DefaultMutableTreeNode node = (DefaultMutableTreeNode)root.getChildAt(i);
316 MidiBank bank = (MidiBank)node.getUserObject();
317 if(bank.getId() > bankID) return i;
318 }
319
320 return root.getChildCount();
321 }
322
323 /**
324 * If there is already an instrument with MIDI program <code>program</code>,
325 * those instrument is removed from the tree.
326 * @return The position, where the instrument of the specified program should be inserted.
327 */
328 private int
329 removeProgram(DefaultMutableTreeNode bankNode, int program) {
330
331 for(int i = 0; i < bankNode.getChildCount(); i++) {
332 DefaultMutableTreeNode n = (DefaultMutableTreeNode)bankNode.getChildAt(i);
333 MidiInstrument instr = (MidiInstrument)n.getUserObject();
334
335 if(instr.getInfo().getMidiProgram() == program) {
336 model.removeNodeFromParent(n);
337 return i;
338 }
339
340 if(instr.getInfo().getMidiProgram() > program) return i;
341 }
342
343 return bankNode.getChildCount();
344 }
345
346 private DefaultMutableTreeNode
347 findNode(DefaultMutableTreeNode parent, Object obj) {
348 for(int i = 0; i < parent.getChildCount(); i++) {
349 DefaultMutableTreeNode node = (DefaultMutableTreeNode)parent.getChildAt(i);
350 if(node.getUserObject().equals(obj)) return node;
351 }
352
353 return null;
354 }
355
356 private DefaultMutableTreeNode
357 findBank(Object obj) {
358 return findNode((DefaultMutableTreeNode)model.getRoot(), obj);
359 }
360
361 private DefaultMutableTreeNode
362 findInstrument(Object obj) {
363 if(obj == null || !(obj instanceof MidiInstrument)) return null;
364 MidiInstrument i = (MidiInstrument) obj;
365 DefaultMutableTreeNode bank = findBank(new MidiBank(i.getInfo().getMidiBank()));
366 if(bank == null) return null;
367 return findNode(bank, obj);
368 }
369
370
371 private class MidiBank {
372 private int id;
373
374 MidiBank(int id) {
375 this.id = id;
376 }
377
378 public int
379 getId() { return id; }
380
381 public boolean
382 equals(Object obj) {
383 if(obj == null) return false;
384 if(!(obj instanceof MidiBank)) return false;
385 if(getId() == ((MidiBank)obj).getId()) return true;
386 return false;
387 }
388
389 public String
390 toString() {
391 int i = CC.getViewConfig().getFirstMidiBankNumber();
392 return i18n.getLabel("JSMidiInstrumentTree.MidiBank.name", i + id);
393 }
394 }
395
396 protected class BankTreeNode extends DefaultMutableTreeNode {
397 BankTreeNode(Object obj) {
398 super(obj);
399 }
400
401 public void
402 setUserObject(Object userObject) {
403 if(userObject instanceof MidiBank) {
404 super.setUserObject(userObject);
405 return;
406 }
407
408 // If we are here, this means that tree editing occurs.
409 CC.getLogger().info("MidiInstrumentTree: editing not supported");
410 }
411
412 public boolean
413 isLeaf() { return false; }
414 }
415
416 protected class InstrTreeNode extends DefaultMutableTreeNode {
417 InstrTreeNode(Object obj) {
418 super(obj);
419 }
420
421 public void
422 setUserObject(Object userObject) {
423 if(userObject instanceof MidiInstrument) {
424 super.setUserObject(userObject);
425 return;
426 }
427
428 // If we are here, this means that tree editing occurs.
429 CC.getLogger().info("MidiInstrumentTree: editing not supported");
430 }
431
432 public boolean
433 isLeaf() { return true; }
434 }
435
436 private void
437 editSelectedInstrument() {
438 MidiInstrument i = getSelectedInstrument();
439 if(i == null) return;
440 JSEditMidiInstrumentDlg dlg = new JSEditMidiInstrumentDlg(i.getInfo());
441 dlg.setVisible(true);
442
443 if(dlg.isCancelled()) return;
444
445 MidiInstrumentInfo info = dlg.getInstrument();
446 CC.getSamplerModel().mapBackendMidiInstrument (
447 info.getMapId(), info.getMidiBank(), info.getMidiProgram(), info
448 );
449 }
450
451 private void
452 copyMidiBankTo() { copyOrMoveMidiBankTo(true); }
453
454 private void
455 moveMidiBankTo() { copyOrMoveMidiBankTo(false); }
456
457 private void
458 copyOrMoveMidiBankTo(boolean copy) {
459 MidiBank bank = getSelectedMidiBank();
460 if(bank == null) return;
461
462 JSMidiBankChooser dlg = new JSMidiBankChooser();
463
464 if(copy) dlg.setTitle(i18n.getLabel("JSMidiInstrumentTree.copyTo"));
465 else dlg.setTitle(i18n.getLabel("JSMidiInstrumentTree.moveTo"));
466
467 dlg.setSelectedMidiInstrumentMap(getMidiInstrumentMap());
468 dlg.setVisible(true);
469 if(dlg.isCancelled()) return;
470
471 MidiInstrumentMap smap = dlg.getSelectedMidiInstrumentMap();
472
473 if(smap == null) {
474 HF.showErrorMessage(i18n.getMessage("JSMidiInstrumentTree.noMap!"), this);
475 return;
476 }
477
478 if(dlg.getMidiBank() == bank.getId() && smap.getMapId() == getMidiInstrumentMap().getMapId()) {
479 String s = "JSMidiInstrumentTree.sameSourceAndDestination!";
480 HF.showErrorMessage(i18n.getMessage(s), this);
481 return;
482 }
483
484 MidiInstrument[] instrs = getMidiInstrumentMap().getMidiInstruments(bank.getId());
485 int mapId = smap.getMapId();
486 int bnkId = dlg.getMidiBank();
487
488 Vector<MidiInstrument> v = new Vector<MidiInstrument>();
489 for(MidiInstrument i : instrs) {
490 MidiInstrument instr;
491 instr = smap.getMidiInstrument(bnkId, i.getInfo().getMidiProgram());
492 if(instr != null) v.add(instr);
493 }
494
495 if(!v.isEmpty()) {
496 String[] instrumentNames = new String[v.size()];
497 for(int i = 0; i < v.size(); i++) {
498 int base = CC.getViewConfig().getFirstMidiProgramNumber();
499 int p = v.get(i).getInfo().getMidiProgram();
500 instrumentNames[i] = (base + p) + ". " + v.get(i).getName();
501 }
502 JSOverrideInstrumentsConfirmDlg dlg2;
503 dlg2 = new JSOverrideInstrumentsConfirmDlg(instrumentNames);
504 dlg2.setVisible(true);
505 if(dlg2.isCancelled()) return;
506 }
507
508 for(MidiInstrument i : instrs) {
509 int p = i.getInfo().getMidiProgram();
510 CC.getSamplerModel().mapBackendMidiInstrument(mapId, bnkId, p, i.getInfo());
511 }
512
513 if(copy) return;
514
515 mapId = getMidiInstrumentMap().getMapId();
516 bnkId = bank.getId();
517
518 for(MidiInstrument i : instrs) {
519 int p = i.getInfo().getMidiProgram();
520 CC.getSamplerModel().unmapBackendMidiInstrument(mapId, bnkId, p);
521 }
522 }
523
524 private void
525 copyMidiInstrumentTo() { copyOrMoveMidiInstrumentTo(true); }
526
527 private void
528 moveMidiInstrumentTo() { copyOrMoveMidiInstrumentTo(false); }
529
530 private void
531 copyOrMoveMidiInstrumentTo(boolean copy) {
532 MidiInstrument instr = getSelectedInstrument();
533 if(instr == null) return;
534
535 JSMidiBankChooser dlg = new JSMidiBankChooser();
536
537 if(copy) dlg.setTitle(i18n.getLabel("JSMidiInstrumentTree.copyTo"));
538 else dlg.setTitle(i18n.getLabel("JSMidiInstrumentTree.moveTo"));
539
540 dlg.setSelectedMidiInstrumentMap(getMidiInstrumentMap());
541 dlg.setVisible(true);
542 if(dlg.isCancelled()) return;
543
544 MidiInstrumentMap smap = dlg.getSelectedMidiInstrumentMap();
545
546 if(smap == null) {
547 HF.showErrorMessage(i18n.getMessage("JSMidiInstrumentTree.noMap!"), this);
548 return;
549 }
550
551 int bank = instr.getInfo().getMidiBank();
552 if(dlg.getMidiBank() == bank && smap.getMapId() == getMidiInstrumentMap().getMapId()) {
553 String s = "JSMidiInstrumentTree.sameSourceAndDestination!";
554 HF.showErrorMessage(i18n.getMessage(s), this);
555 return;
556 }
557
558 int mapId = smap.getMapId();
559 int bnkId = dlg.getMidiBank();
560 int prgId = instr.getInfo().getMidiProgram();
561 MidiInstrument oldInstr = smap.getMidiInstrument(bnkId, prgId);
562
563 if(oldInstr != null) {
564 String[] iS = new String [1];
565 int base = CC.getViewConfig().getFirstMidiProgramNumber();
566 iS[0] = (base + prgId) + ". " + oldInstr.getName();
567 JSOverrideInstrumentsConfirmDlg dlg2;
568 dlg2 = new JSOverrideInstrumentsConfirmDlg(iS);
569 dlg2.setVisible(true);
570 if(dlg2.isCancelled()) return;
571 }
572
573 CC.getSamplerModel().mapBackendMidiInstrument(mapId, bnkId, prgId, instr.getInfo());
574
575 if(copy) return;
576
577 mapId = getMidiInstrumentMap().getMapId();
578
579 CC.getSamplerModel().unmapBackendMidiInstrument(mapId, bank, prgId);
580 }
581
582 private void
583 moveSelectedInstrumentUp() {
584 MidiInstrument instr = getSelectedInstrument();
585 if(instr == null) return;
586 moveSelectedInstrument(instr.getInfo().getMidiProgram() - 1);
587 }
588
589 private void
590 moveSelectedInstrumentDown() {
591 MidiInstrument instr = getSelectedInstrument();
592 if(instr == null) return;
593 moveSelectedInstrument(instr.getInfo().getMidiProgram() + 1);
594 }
595
596 private void
597 moveSelectedInstrument(int newProgram) {
598 if(newProgram < 0 || newProgram > 127) return;
599 MidiInstrument instr = getSelectedInstrument();
600 if(instr == null) return;
601
602 int bnk = instr.getInfo().getMidiBank();
603 int prg = instr.getInfo().getMidiProgram();
604
605 MidiInstrument oldInstr = getMidiInstrumentMap().getMidiInstrument(bnk, newProgram);
606 if(oldInstr != null) {
607 String[] iS = new String [1];
608 int base = CC.getViewConfig().getFirstMidiProgramNumber();
609 iS[0] = (base + prg) + ". " + oldInstr.getName();
610 JSOverrideInstrumentsConfirmDlg dlg;
611 dlg = new JSOverrideInstrumentsConfirmDlg(iS);
612 dlg.setVisible(true);
613 if(dlg.isCancelled()) return;
614 }
615
616 int map = this.getMidiInstrumentMap().getMapId();
617 CC.getSamplerModel().mapBackendMidiInstrument(map, bnk, newProgram, instr.getInfo());
618 CC.getSamplerModel().unmapBackendMidiInstrument(map, bnk, prg);
619 }
620
621 private final EventHandler eventHandler = new EventHandler();
622
623 private EventHandler
624 getHandler() { return eventHandler; }
625
626 private class EventHandler implements MidiInstrumentListener, MidiInstrumentMapListener,
627 TreeSelectionListener {
628
629 /** Invoked when a MIDI instrument in a MIDI instrument map is changed. */
630 public void
631 instrumentInfoChanged(MidiInstrumentEvent e) {
632 DefaultMutableTreeNode n = findInstrument(e.getSource());
633 if(n != null) model.nodeChanged(n);
634 }
635
636 /** Invoked when the name of MIDI instrument map is changed. */
637 public void nameChanged(MidiInstrumentMapEvent e) { }
638
639 /** Invoked when an instrument is added to a MIDI instrument map. */
640 public void
641 instrumentAdded(MidiInstrumentMapEvent e) {
642 e.getInstrument().addMidiInstrumentListener(getHandler());
643 mapInstrument(e.getInstrument());
644
645 }
646
647 /** Invoked when an instrument is removed from a MIDI instrument map. */
648 public void
649 instrumentRemoved(MidiInstrumentMapEvent e) {
650 unmapInstrument(e.getInstrument());
651 e.getInstrument().removeMidiInstrumentListener(getHandler());
652 }
653
654 public void
655 valueChanged(TreeSelectionEvent e) {
656 MidiInstrument instr = getSelectedInstrument();
657 if(instr != null) {
658 int p = instr.getInfo().getMidiProgram();
659 contextMenu.miMoveInstrumentDown.setEnabled(p < 127);
660 contextMenu.miMoveInstrumentUp.setEnabled(p > 0);
661 }
662 }
663 }
664
665 class ContextMenu extends MouseAdapter {
666 private final JPopupMenu bankMenu = new JPopupMenu();
667
668 private final JPopupMenu instrumentMenu = new JPopupMenu();
669
670 private final JMenu changeProgramMenu =
671 new JMenu(i18n.getMenuLabel("JSMidiInstrumentTree.ContextMenu.changeProgram"));
672
673 private final JMenuItem miMoveInstrumentUp =
674 new JMenuItem(i18n.getMenuLabel("JSMidiInstrumentTree.ContextMenu.moveUp"));
675
676 private final JMenuItem miMoveInstrumentDown =
677 new JMenuItem(i18n.getMenuLabel("JSMidiInstrumentTree.ContextMenu.moveDown"));
678
679 private final JMenu programGroup1Menu = new JMenu();
680 private final JMenu programGroup2Menu = new JMenu();
681 private final JMenu programGroup3Menu = new JMenu();
682 private final JMenu programGroup4Menu = new JMenu();
683 private final JMenu programGroup5Menu = new JMenu();
684 private final JMenu programGroup6Menu = new JMenu();
685 private final JMenu programGroup7Menu = new JMenu();
686 private final JMenu programGroup8Menu = new JMenu();
687
688
689 ContextMenu() {
690 JMenuItem mi = new JMenuItem(i18n.getMenuLabel("JSMidiInstrumentTree.ContextMenu.moveTo"));
691 bankMenu.add(mi);
692 mi.addActionListener(new ActionListener() {
693 public void
694 actionPerformed(ActionEvent e) {
695 moveMidiBankTo();
696 }
697 });
698
699 mi = new JMenuItem(i18n.getMenuLabel("JSMidiInstrumentTree.ContextMenu.copyTo"));
700 bankMenu.add(mi);
701 mi.addActionListener(new ActionListener() {
702 public void
703 actionPerformed(ActionEvent e) {
704 copyMidiBankTo();
705 }
706 });
707
708 bankMenu.addSeparator();
709
710 mi = new JMenuItem(i18n.getMenuLabel("ContextMenu.delete"));
711 bankMenu.add(mi);
712 mi.addActionListener(new ActionListener() {
713 public void
714 actionPerformed(ActionEvent e) {
715 removeSelectedInstrumentOrBank();
716 }
717 });
718
719 // MIDI Instrument Menu
720
721 mi = new JMenuItem(i18n.getMenuLabel("ContextMenu.edit"));
722 instrumentMenu.add(mi);
723 mi.addActionListener(new ActionListener() {
724 public void
725 actionPerformed(ActionEvent e) {
726 editSelectedInstrument();
727 }
728 });
729
730 instrumentMenu.addSeparator();
731
732 mi = new JMenuItem(i18n.getMenuLabel("JSMidiInstrumentTree.ContextMenu.moveTo"));
733 instrumentMenu.add(mi);
734 mi.addActionListener(new ActionListener() {
735 public void
736 actionPerformed(ActionEvent e) {
737 moveMidiInstrumentTo();
738 }
739 });
740
741 mi = new JMenuItem(i18n.getMenuLabel("JSMidiInstrumentTree.ContextMenu.copyTo"));
742 instrumentMenu.add(mi);
743 mi.addActionListener(new ActionListener() {
744 public void
745 actionPerformed(ActionEvent e) {
746 copyMidiInstrumentTo();
747 }
748 });
749
750 instrumentMenu.add(changeProgramMenu);
751
752 changeProgramMenu.add(miMoveInstrumentUp);
753 miMoveInstrumentUp.addActionListener(new ActionListener() {
754 public void
755 actionPerformed(ActionEvent e) {
756 moveSelectedInstrumentUp();
757 }
758 });
759
760 changeProgramMenu.add(miMoveInstrumentDown);
761 miMoveInstrumentDown.addActionListener(new ActionListener() {
762 public void
763 actionPerformed(ActionEvent e) {
764 moveSelectedInstrumentDown();
765 }
766 });
767
768 changeProgramMenu.addSeparator();
769
770 changeProgramMenu.add(programGroup1Menu);
771 addProgramMenuItems(programGroup1Menu, 0, 15);
772 changeProgramMenu.add(programGroup2Menu);
773 addProgramMenuItems(programGroup2Menu, 16, 31);
774 changeProgramMenu.add(programGroup3Menu);
775 addProgramMenuItems(programGroup3Menu, 32, 47);
776 changeProgramMenu.add(programGroup4Menu);
777 addProgramMenuItems(programGroup4Menu, 48, 63);
778 changeProgramMenu.add(programGroup5Menu);
779 addProgramMenuItems(programGroup5Menu, 64, 79);
780 changeProgramMenu.add(programGroup6Menu);
781 addProgramMenuItems(programGroup6Menu, 80, 95);
782 changeProgramMenu.add(programGroup7Menu);
783 addProgramMenuItems(programGroup7Menu, 96, 111);
784 changeProgramMenu.add(programGroup8Menu);
785 addProgramMenuItems(programGroup8Menu, 112, 127);
786
787 instrumentMenu.addSeparator();
788 updateChangeProgramMenu();
789
790 mi = new JMenuItem(i18n.getMenuLabel("ContextMenu.delete"));
791 instrumentMenu.add(mi);
792 mi.addActionListener(new ActionListener() {
793 public void
794 actionPerformed(ActionEvent e) {
795 removeSelectedInstrumentOrBank();
796 }
797 });
798
799 }
800
801 private void
802 addProgramMenuItems(JMenu menu, int prgStart, int prgEnd) {
803 for(int i = prgStart; i <= prgEnd; i++) {
804 menu.add(new ProgramMenuItem(i));
805 }
806 }
807
808 private void
809 updateChangeProgramMenu() {
810 updateProgramGroupMenu(programGroup1Menu, 0, 15);
811 updateProgramGroupMenu(programGroup2Menu, 16, 31);
812 updateProgramGroupMenu(programGroup3Menu, 32, 47);
813 updateProgramGroupMenu(programGroup4Menu, 48, 63);
814 updateProgramGroupMenu(programGroup5Menu, 64, 79);
815 updateProgramGroupMenu(programGroup6Menu, 80, 95);
816 updateProgramGroupMenu(programGroup7Menu, 96, 111);
817 updateProgramGroupMenu(programGroup8Menu, 112, 127);
818 }
819
820 private void
821 updateProgramGroupMenu(JMenu menu, int prgStart, int prgEnd) {
822 int base = CC.getViewConfig().getFirstMidiProgramNumber();
823 String s = "JSMidiInstrumentTree.ContextMenu.programGroup";
824 String grp = "(" + (base + prgStart) + "-" + (base + prgEnd) + ")";
825 menu.setText(i18n.getMenuLabel(s, grp));
826
827 updateProgramGroupMenuItems(menu);
828 }
829
830 private void
831 updateProgramGroupMenuItems(JMenu menu) {
832 for(int i = 0; i < menu.getItemCount(); i++) {
833 ((ProgramMenuItem)menu.getItem(i)).updateProgramNumber();
834 }
835 }
836
837 public void
838 mousePressed(MouseEvent e) {
839 if(e.isPopupTrigger()) show(e);
840 }
841
842 public void
843 mouseReleased(MouseEvent e) {
844 if(e.isPopupTrigger()) show(e);
845 }
846
847 void
848 show(MouseEvent e) {
849 if(getSelectionCount() == 0) return;
850
851 if(getSelectedInstrument() != null) {
852 instrumentMenu.show(e.getComponent(), e.getX(), e.getY());
853 } else {
854 bankMenu.show(e.getComponent(), e.getX(), e.getY());
855 }
856 }
857
858 private class ProgramMenuItem extends JMenuItem implements ActionListener {
859 int program;
860
861 ProgramMenuItem(int program) {
862 this.program = program;
863 updateProgramNumber();
864 addActionListener(this);
865 }
866
867 public void
868 updateProgramNumber() {
869 int base = CC.getViewConfig().getFirstMidiProgramNumber();
870 setText(String.valueOf(base + program));
871 }
872
873 public void
874 actionPerformed(ActionEvent e) {
875 moveSelectedInstrument(program);
876 }
877 }
878 }
879 }
880
881 class JSOverrideInstrumentsConfirmDlg extends OkCancelDialog {
882 private final JLabel lMsg = new JLabel(i18n.getMessage("JSOverrideInstrumentsConfirmDlg.lMsg"));
883 private final JTable table;
884
885 JSOverrideInstrumentsConfirmDlg(String[] instrumentNames) {
886 super(CC.getMainFrame());
887
888 JPanel mainPane = new JPanel();
889 mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
890
891 lMsg.setIcon(CC.getViewConfig().getBasicIconSet().getWarning32Icon());
892 lMsg.setAlignmentX(LEFT_ALIGNMENT);
893 mainPane.add(lMsg);
894
895 mainPane.add(Box.createRigidArea(new Dimension(0, 12)));
896
897 String[][] instrs = new String[instrumentNames.length][1];
898 for(int i = 0; i < instrumentNames.length; i++) {
899 instrs[i][0] = instrumentNames[i];
900 }
901
902 String[] columns = new String[1];
903 columns[0] = "";
904
905 table = new JTable(instrs, columns);
906 JScrollPane sp = new JScrollPane(table);
907 Dimension d = new Dimension(200, 200);
908 sp.setMinimumSize(d);
909 sp.setPreferredSize(d);
910 sp.setAlignmentX(LEFT_ALIGNMENT);
911 mainPane.add(sp);
912
913 setMainPane(mainPane);
914 setMinimumSize(getPreferredSize());
915 setResizable(true);
916 }
917
918 protected void
919 onOk() {
920 if(!btnOk.isEnabled()) return;
921
922 setVisible(false);
923 setCancelled(false);
924 }
925
926 protected void
927 onCancel() { setVisible(false); }
928 }

  ViewVC Help
Powered by ViewVC