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

Contents of /jsampler/trunk/src/org/jsampler/view/fantasia/PianoKeyboardPane.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1785 - (show annotations) (download)
Tue Oct 7 00:07:14 2008 UTC (15 years, 6 months ago) by iliev
File size: 16077 byte(s)
* Fantasia: Implemented multiple channels panels
* Fantasia: Refactoring - all basic UI components moved to
  org.jsampler.view.fantasia.basic package

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.fantasia;
24
25 import java.awt.AlphaComposite;
26 import java.awt.Color;
27 import java.awt.Composite;
28 import java.awt.Dimension;
29 import java.awt.GradientPaint;
30 import java.awt.Graphics;
31 import java.awt.Graphics2D;
32 import java.awt.GridBagConstraints;
33 import java.awt.GridBagLayout;
34 import java.awt.Insets;
35 import java.awt.Paint;
36 import java.awt.RenderingHints;
37
38 import java.awt.event.ActionEvent;
39 import java.awt.event.ActionListener;
40 import java.awt.event.FocusEvent;
41 import java.awt.event.FocusListener;
42 import java.awt.event.MouseEvent;
43 import java.awt.event.MouseAdapter;
44
45 import java.awt.geom.Line2D;
46 import java.awt.geom.Rectangle2D;
47
48 import java.beans.PropertyChangeEvent;
49 import java.beans.PropertyChangeListener;
50
51 import javax.swing.BorderFactory;
52 import javax.swing.Box;
53 import javax.swing.BoxLayout;
54 import javax.swing.ImageIcon;
55 import javax.swing.JButton;
56 import javax.swing.JPanel;
57 import javax.swing.JToggleButton;
58
59 import javax.swing.event.ListSelectionEvent;
60 import javax.swing.event.ListSelectionListener;
61
62 import net.sf.juife.event.TaskEvent;
63 import net.sf.juife.event.TaskListener;
64
65 import org.jsampler.CC;
66 import org.jsampler.SamplerChannelModel;
67
68 import org.jsampler.event.SamplerChannelAdapter;
69 import org.jsampler.event.SamplerChannelEvent;
70 import org.jsampler.event.SamplerChannelListListener;
71 import org.jsampler.event.SamplerChannelListEvent;
72
73 import org.jsampler.view.JSChannel;
74 import org.jsampler.view.fantasia.basic.*;
75 import org.jsampler.view.std.JSPianoRoll;
76
77 import org.linuxsampler.lscp.Instrument;
78 import org.linuxsampler.lscp.SamplerChannel;
79
80 import org.linuxsampler.lscp.event.MidiDataEvent;
81 import org.linuxsampler.lscp.event.MidiDataListener;
82
83 import static javax.swing.Action.SMALL_ICON;
84 import static org.jsampler.task.Global.GetFileInstrument;
85 import static org.jsampler.view.fantasia.FantasiaI18n.i18n;
86
87 /**
88 *
89 * @author Grigor Iliev
90 */
91 public class PianoKeyboardPane extends FantasiaPanel
92 implements ListSelectionListener, SamplerChannelListListener {
93
94 protected final JToggleButton btnPower = new PowerButton();
95 private final FantasiaLabel lDisplay = new FantasiaLabel(" ", true);
96 private final JSPianoRoll pianoRoll = new JSPianoRoll();
97 private SamplerChannelModel channel = null;
98
99 private String file = null;
100 private int index = -1;
101
102 public
103 PianoKeyboardPane() {
104 pianoRoll.actionDecreaseKeyNumber.putValue(SMALL_ICON, Res.gfxBtnDecrease);
105 pianoRoll.actionIncreaseKeyNumber.putValue(SMALL_ICON, Res.gfxBtnIncrease);
106 pianoRoll.actionScrollLeft.putValue(SMALL_ICON, Res.gfxBtnScrollLeft);
107 pianoRoll.actionScrollRight.putValue(SMALL_ICON, Res.gfxBtnScrollRight);
108
109 setOpaque(false);
110
111 GridBagLayout gridbag = new GridBagLayout();
112 GridBagConstraints c = new GridBagConstraints();
113
114 setLayout(gridbag);
115
116 setBorder(BorderFactory.createEmptyBorder(0, 3, 5, 3));
117
118 c.fill = GridBagConstraints.NONE;
119
120 c.gridx = 0;
121 c.gridy = 0;
122 c.anchor = GridBagConstraints.NORTHWEST;
123 c.insets = new Insets(3, 3, 3, 3);
124 gridbag.setConstraints(btnPower, c);
125 add(btnPower);
126
127 JPanel p = createVSeparator();
128 c.gridx = 1;
129 c.gridy = 0;
130 c.gridheight = 2;
131 c.insets = new Insets(3, 0, 5, 3);
132 c.fill = GridBagConstraints.VERTICAL;
133 c.weighty = 1.0;
134 gridbag.setConstraints(p, c);
135 add(p);
136
137 p = new KeyRangePropsPane();
138
139 c.gridx = 2;
140 c.gridy = 0;
141 c.gridheight = 1;
142 c.insets = new Insets(0, 0, 0, 0);
143 c.fill = GridBagConstraints.NONE;
144 c.weighty = 0.0;
145 c.anchor = GridBagConstraints.WEST;
146 gridbag.setConstraints(p, c);
147 add(p);
148
149 p = new KeyRangePropsPane();
150
151 c.gridx = 6;
152 c.gridy = 0;
153 c.anchor = GridBagConstraints.EAST;
154 c.insets = new Insets(0, 0, 0, 10);
155 gridbag.setConstraints(p, c);
156 add(p);
157
158 lDisplay.setPreferredSize(new Dimension(300, lDisplay.getPreferredSize().height));
159
160 c.gridx = 4;
161 c.gridy = 0;
162 c.insets = new Insets(3, 3, 3, 12);
163 c.fill = GridBagConstraints.NONE;
164 c.weightx = 0.0;
165 gridbag.setConstraints(lDisplay, c);
166 add(lDisplay);
167
168 p = new JPanel();
169 p.setOpaque(false);
170 c.gridx = 3;
171 c.gridy = 0;
172 c.insets = new Insets(0, 0, 0, 0);
173 c.fill = GridBagConstraints.HORIZONTAL;
174 c.weightx = 1.0;
175 gridbag.setConstraints(p, c);
176 add(p);
177
178 p = new JPanel();
179 p.setOpaque(false);
180 c.gridx = 5;
181 c.gridy = 0;
182 gridbag.setConstraints(p, c);
183 add(p);
184
185 pianoRoll.setFocusable(false);
186 pianoRoll.setBackground(new Color(0x2e2e2e));
187 //pianoRoll.setOpaque(false);
188
189 disablePianoRoll();
190
191 c.gridx = 2;
192 c.gridy = 1;
193 c.gridwidth = 5;
194 c.insets = new Insets(0, 3, 0, 12);
195 c.fill = GridBagConstraints.BOTH;
196 c.weightx = 1.0;
197 c.weighty = 1.0;
198 gridbag.setConstraints(pianoRoll, c);
199 add(pianoRoll);
200
201 CC.getSamplerModel().addSamplerChannelListListener(this);
202 pianoRoll.addMidiDataListener(getHandler());
203
204 updateKeyRange();
205
206 PropertyChangeListener l = new PropertyChangeListener() {
207 public void
208 propertyChange(PropertyChangeEvent e) {
209 updateKeyRange();
210 }
211 };
212
213 CC.preferences().addPropertyChangeListener("midiKeyboard.firstKey", l);
214 CC.preferences().addPropertyChangeListener("midiKeyboard.lastKey", l);
215
216 addFocusListener(getHandler());
217
218 MouseAdapter l2 = new MouseAdapter() {
219 public void
220 mouseClicked(MouseEvent e) { requestFocusInWindow(); }
221 };
222
223 addKeyListener(pianoRoll.getKeyListener());
224 pianoRoll.registerKeys(this);
225
226 addMouseListener(l2);
227 pianoRoll.addMouseListener(l2);
228 lDisplay.addMouseListener(l2);
229 }
230
231 public JSPianoRoll
232 getPianoRoll() { return pianoRoll; }
233
234 private void
235 updateKeyRange() {
236 int firstKey = CC.preferences().getIntProperty("midiKeyboard.firstKey");
237 int lastKey = CC.preferences().getIntProperty("midiKeyboard.lastKey");
238 pianoRoll.setKeyRange(firstKey, lastKey);
239 }
240
241 @Override public void
242 valueChanged(ListSelectionEvent e) {
243 if(e.getValueIsAdjusting()) return;
244
245 JSChannel[] chnS = CC.getMainFrame().getSelectedChannelsPane().getSelectedChannels();
246 if(chnS == null || chnS.length == 0) {
247 disconnectChannel();
248 return;
249 }
250
251 if(chnS[0].getModel() == channel) return;
252 disconnectChannel();
253 connectChannel(chnS[0].getModel());
254 }
255
256 private void
257 updateInstrumentInfo() {
258 final GetFileInstrument i = new GetFileInstrument(file, index);
259
260 i.addTaskListener(new TaskListener() {
261 public void
262 taskPerformed(TaskEvent e) {
263 if(i.doneWithErrors()) return;
264 updatePianoKeyboard(i.getResult());
265 }
266 });
267
268 CC.getTaskQueue().add(i);
269 }
270
271 private void
272 disablePianoRoll() {
273 pianoRoll.reset(true);
274 pianoRoll.setPlayingEnabled(false);
275 }
276
277 private void
278 updatePianoKeyboard(Instrument instr) {
279 // The selected channel may have changed before this update
280 // due to concurency, so also checking whether file is null
281 if(instr == null || file == null) {
282 disablePianoRoll();
283 return;
284 }
285
286 pianoRoll.setPlayingEnabled(true);
287
288 pianoRoll.setShouldRepaint(false);
289 pianoRoll.reset(true);
290 pianoRoll.setDisabled(instr.getKeyMapping(), false);
291 pianoRoll.setKeyswitches(instr.getKeyswitchMapping(), true);
292 pianoRoll.setShouldRepaint(true);
293 pianoRoll.repaint();
294 }
295
296 private void
297 connectChannel(SamplerChannelModel chn) {
298 channel = chn;
299 channel.addMidiDataListener(pianoRoll);
300 channel.addSamplerChannelListener(getHandler());
301
302 updateDisplay();
303
304 file = channel.getChannelInfo().getInstrumentFile();
305 if(file == null) {
306 disablePianoRoll();
307 return;
308 }
309 index = channel.getChannelInfo().getInstrumentIndex();
310 updateInstrumentInfo();
311 }
312
313 private void
314 disconnectChannel() {
315 if(channel != null) {
316 channel.removeMidiDataListener(pianoRoll);
317 channel.removeSamplerChannelListener(getHandler());
318 channel = null;
319 file = null;
320 index = -1;
321 disablePianoRoll();
322 }
323
324 updateDisplay();
325 }
326
327 @Override public void
328 channelAdded(SamplerChannelListEvent e) {
329 updateDisplay();
330 }
331
332 @Override public void
333 channelRemoved(SamplerChannelListEvent e) {
334 if(e.getChannelModel() == channel) {
335 disconnectChannel();
336 }
337
338 updateDisplay();
339 }
340
341 private JPanel
342 createVSeparator() {
343 PixmapPane p = new PixmapPane(Res.gfxVLine);
344 p.setAlignmentY(JPanel.TOP_ALIGNMENT);
345 p.setPreferredSize(new Dimension(2, 60));
346 p.setMaximumSize(new Dimension(2, Short.MAX_VALUE));
347 return p;
348 }
349
350 private Color color1 = new Color(0x7a7a7a);
351 private Color color2 = new Color(0x5e5e5e);
352 private Color color3 = new Color(0x2e2e2e);
353
354 @Override
355 public void
356 paintComponent(Graphics g) {
357 Graphics2D g2 = (Graphics2D)g;
358
359 Paint oldPaint = g2.getPaint();
360 Composite oldComposite = g2.getComposite();
361
362 Insets insets = this.getInsets();
363 double x1 = insets.left;
364 double y1 = insets.top;
365
366 double w = getSize().getWidth();
367 double x2 = w - insets.right - 1;
368 double h = getSize().getHeight();
369 double y2 = h - insets.bottom - 1;
370
371 FantasiaPainter.paintGradient(g2, x1, y1, x2, y2 - 10, color1, color2);
372
373 g2.setRenderingHint (
374 RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF
375 );
376
377 double y3 = y2 - 10;
378 if(y3 < 0) y3 = 0;
379
380 Rectangle2D.Double rect = new Rectangle2D.Double(x1, y3, x2 - x1 + 1, 11);
381
382 GradientPaint gr = new GradientPaint (
383 0.0f, (float)y3, color2,
384 0.0f, (float)h, color3
385 );
386
387 g2.setPaint(gr);
388 g2.fill(rect);
389
390 drawOutBorder(g2, x1, y1, x2, y2);
391
392 double prX = pianoRoll.getLocation().getX();
393 double prY = pianoRoll.getLocation().getY();
394 drawInBorder (
395 g2, prX - 2, prY - 2,
396 prX + pianoRoll.getSize().getWidth() + 1, prY + pianoRoll.getSize().getHeight() - 3
397 );
398
399 g2.setPaint(oldPaint);
400 g2.setComposite(oldComposite);
401 }
402
403 private void
404 drawOutBorder(Graphics2D g2, double x1, double y1, double x2, double y2) {
405 AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.40f);
406 g2.setComposite(ac);
407
408 g2.setPaint(Color.WHITE);
409 Line2D.Double l = new Line2D.Double(x1, y1, x2, y1);
410 g2.draw(l);
411
412 g2.setComposite(ac.derive(0.20f));
413 l = new Line2D.Double(x1, y1 + 1, x2, y1 + 1);
414 g2.draw(l);
415
416 g2.setComposite(ac.derive(0.255f));
417
418 l = new Line2D.Double(x1, y1, x1, y2);
419 g2.draw(l);
420
421 g2.setComposite(ac.derive(0.40f));
422 g2.setPaint(Color.BLACK);
423
424 //l = new Line2D.Double(x1, y2, x2, y2);
425 //g2.draw(l);
426
427 g2.setComposite(ac.derive(0.20f));
428
429 l = new Line2D.Double(x2, y1, x2, y2);
430 g2.draw(l);
431 }
432
433 private void
434 drawInBorder(Graphics2D g2, double x1, double y1, double x2, double y2) {
435 AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.40f);
436 g2.setComposite(ac);
437
438 g2.setPaint(Color.WHITE);
439 Line2D.Double l = new Line2D.Double(x1, y2, x2, y2);
440 //g2.draw(l);
441
442 g2.setComposite(ac.derive(0.255f));
443
444 l = new Line2D.Double(x2 - 1, y1 + 1, x2 - 1, y2 + 1);
445 g2.draw(l);
446
447 g2.setComposite(ac.derive(0.13f));
448
449 l = new Line2D.Double(x2, y1, x2, y2);
450 g2.draw(l);
451
452 g2.setComposite(ac.derive(0.20f));
453 g2.setPaint(Color.BLACK);
454
455 l = new Line2D.Double(x1, y1, x2, y1);
456 g2.draw(l);
457
458 g2.setComposite(ac.derive(0.40f));
459 g2.setPaint(Color.BLACK);
460
461 l = new Line2D.Double(x1 + 1, y1 + 1, x2 - 1, y1 + 1);
462 g2.draw(l);
463
464 g2.setComposite(ac.derive(0.20f));
465
466 l = new Line2D.Double(x1, y1, x1, y2);
467 g2.draw(l);
468
469 g2.setComposite(ac.derive(0.40f));
470
471 l = new Line2D.Double(x1 + 1, y1 + 1, x1 + 1, y2 + 1);
472 g2.draw(l);
473 }
474
475 private void
476 updateDisplay() {
477 // TODO: called too often?
478 if(channel == null) {
479 lDisplay.setText(i18n.getLabel("PianoKeyboardPane.noChannel"));
480 return;
481 }
482
483 SamplerChannel sc = channel.getChannelInfo();
484 String s = CC.getMainFrame().getChannelPath(channel);
485
486 StringBuffer sb = new StringBuffer();
487 sb.append(i18n.getLabel("PianoKeyboardPane.channel", s)).append(" - ");
488
489 int status = sc.getInstrumentStatus();
490 if(status >= 0 && status < 100) {
491 sb.append(i18n.getLabel("ChannelScreen.loadingInstrument", status));
492 } else if(status == -1) {
493 sb.append(i18n.getLabel("PianoKeyboardPane.noInstrument"));
494 } else if(status < -1) {
495 sb.append(i18n.getLabel("ChannelScreen.errorLoadingInstrument"));
496 } else {
497 if(sc.getInstrumentName() != null) sb.append(sc.getInstrumentName());
498 }
499
500 lDisplay.setText(sb.toString());
501 }
502
503
504 class KeyRangePropsPane extends JPanel {
505 private final JButton btnIncrease =
506 new PixmapButton(pianoRoll.actionIncreaseKeyNumber, Res.gfxBtnIncrease);
507
508 private final JButton btnDecrease =
509 new PixmapButton(pianoRoll.actionDecreaseKeyNumber, Res.gfxBtnDecrease);
510
511 private final JButton btnScrollLeft =
512 new PixmapButton(pianoRoll.actionScrollLeft, Res.gfxBtnScrollLeft);
513
514 private final JButton btnScrollRight =
515 new PixmapButton(pianoRoll.actionScrollRight, Res.gfxBtnScrollRight);
516
517 KeyRangePropsPane() {
518 setOpaque(false);
519 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
520
521 btnIncrease.setFocusable(false);
522 btnDecrease.setFocusable(false);
523 btnScrollLeft.setFocusable(false);
524 btnScrollRight.setFocusable(false);
525
526
527 btnDecrease.setPressedIcon(Res.gfxBtnDecreaseRO);
528 add(btnDecrease);
529
530 btnIncrease.setPressedIcon(Res.gfxBtnIncreaseRO);
531 add(btnIncrease);
532
533 add(Box.createRigidArea(new Dimension(6, 0)));
534
535 btnScrollLeft.setPressedIcon(Res.gfxBtnScrollLeftRO);
536 add(btnScrollLeft);
537
538 btnScrollRight.setPressedIcon(Res.gfxBtnScrollRightRO);
539 add(btnScrollRight);
540 }
541 }
542
543
544 public static class PowerButton extends PixmapToggleButton implements ActionListener {
545 PowerButton() {
546 this(Res.gfxPowerOff, Res.gfxPowerOn);
547 }
548
549 PowerButton(ImageIcon defaultIcon, ImageIcon selectedIcon) {
550 super(defaultIcon, selectedIcon);
551
552 setSelected(true);
553 addActionListener(this);
554 }
555
556 @Override
557 public void
558 actionPerformed(ActionEvent e) {
559 boolean b = isSelected();
560 MainFrame frm = (MainFrame)CC.getMainFrame();
561 if(frm == null) return;
562 frm.setMidiKeyboardVisible(b);
563 }
564
565 @Override
566 public boolean
567 contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }
568 }
569
570 private final Handler handler = new Handler();
571
572 private Handler
573 getHandler() { return handler; }
574
575 private class Handler extends SamplerChannelAdapter implements FocusListener, MidiDataListener {
576 @Override
577 public void
578 midiDataArrived(MidiDataEvent e) {
579 if(channel == null) return;
580 channel.sendBackendMidiData(e);
581 }
582
583 @Override
584 public void
585 channelChanged(SamplerChannelEvent e) {
586 updateDisplay();
587
588 String newFile = channel.getChannelInfo().getInstrumentFile();
589 int newIndex = channel.getChannelInfo().getInstrumentIndex();
590
591 if(channel.getChannelInfo().getInstrumentStatus() != 100) {
592 //don't use disablePianoRoll because of unnecessary repainting
593 pianoRoll.setAllKeysPressed(false);
594 pianoRoll.removeAllKeyswitches();
595 pianoRoll.setAllKeysDisabled(true);
596 pianoRoll.setPlayingEnabled(false);
597 return;
598 }
599
600 if(newFile == null) {
601 if(file != null) disablePianoRoll();
602 file = null;
603 index = -1;
604 return;
605 }
606
607 if(newFile.equals(file) && newIndex == index) return;
608
609 file = newFile;
610 index = newIndex;
611 updateInstrumentInfo();
612 }
613
614 @Override
615 public void
616 focusGained(FocusEvent e) {
617
618 }
619
620 @Override
621 public void
622 focusLost(FocusEvent e) {
623
624 }
625 }
626 }

  ViewVC Help
Powered by ViewVC