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

Annotation of /jsampler/trunk/src/org/jsampler/view/classic/MidiInstrumentTree.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: 12886 byte(s)
upgrading to version 0.5a

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

  ViewVC Help
Powered by ViewVC