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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1767 - (show annotations) (download)
Mon Sep 8 00:19:27 2008 UTC (15 years, 7 months ago) by iliev
File size: 28861 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.fantasia;
24
25 import java.awt.Container;
26 import java.awt.Dimension;
27 import java.awt.Rectangle;
28
29 import java.awt.event.ActionEvent;
30 import java.awt.event.ActionListener;
31 import java.awt.event.MouseAdapter;
32 import java.awt.event.MouseEvent;
33
34 import java.beans.PropertyChangeEvent;
35 import java.beans.PropertyChangeListener;
36
37 import java.text.NumberFormat;
38
39 import javax.swing.AbstractAction;
40 import javax.swing.Action;
41 import javax.swing.BoxLayout;
42 import javax.swing.ButtonGroup;
43 import javax.swing.DefaultListCellRenderer;
44 import javax.swing.ImageIcon;
45 import javax.swing.JButton;
46 import javax.swing.JComponent;
47 import javax.swing.JLabel;
48 import javax.swing.JMenuItem;
49 import javax.swing.JPanel;
50 import javax.swing.JPopupMenu;
51 import javax.swing.JRadioButtonMenuItem;
52 import javax.swing.JScrollPane;
53 import javax.swing.JToggleButton;
54 import javax.swing.JToolBar;
55
56 import net.sf.juife.InformationDialog;
57 import net.sf.juife.TitleBar;
58
59 import org.jdesktop.swingx.JXCollapsiblePane;
60
61 import org.jsampler.CC;
62 import org.jsampler.HF;
63 import org.jsampler.SamplerChannelModel;
64
65 import org.jsampler.event.SamplerChannelEvent;
66 import org.jsampler.event.SamplerChannelListEvent;
67 import org.jsampler.event.SamplerChannelListListener;
68 import org.jsampler.event.SamplerChannelListener;
69
70 import org.jsampler.view.JSChannel;
71 import org.jsampler.view.JSChannelsPane;
72
73 import org.jsampler.view.std.JSChannelOutputRoutingDlg;
74 import org.jsampler.view.std.JSFxSendsDlg;
75 import org.jsampler.view.std.JSFxSendsPane;
76 import org.jsampler.view.std.JSInstrumentChooser;
77 import org.jsampler.view.std.JSVolumeEditorPopup;
78
79 import org.linuxsampler.lscp.SamplerChannel;
80
81 import static org.jsampler.view.fantasia.FantasiaI18n.i18n;
82 import static org.jsampler.view.fantasia.FantasiaPrefs.*;
83 import static org.jsampler.view.fantasia.FantasiaUtils.*;
84 import static org.jsampler.view.std.JSVolumeEditorPopup.VolumeType;
85
86
87 /**
88 *
89 * @author Grigor Iliev
90 */
91 public class Channel extends JSChannel {
92 private final JXCollapsiblePane mainPane;
93 private final ChannelOptionsPane optionsPane = new ChannelOptionsPane();
94
95 private final ViewTracker viewTracker;
96
97 private JSFxSendsDlg fxSendsDlg = null;
98
99 private final ContextMenu contextMenu;
100
101 private boolean selected = false;
102
103 private AnimatedPorpetyListener animatedPorpetyListener = new AnimatedPorpetyListener();
104
105 class AnimatedPorpetyListener implements PropertyChangeListener {
106 public void
107 propertyChange(PropertyChangeEvent e) {
108 mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
109 }
110 }
111
112 ////////////////////////////////
113 // ******* Mouse tracker *******
114 ////////////////////////////////
115 private static int mouseOverChannelId = -1;
116 private static boolean mousePressed = false;
117
118 private static ActionListener guiListener = null;
119
120 private static Channel oldMouseOverChannel = null;
121 private static Channel newMouseOverChannel = null;
122
123
124 private static void
125 mouseMoved() {
126 //TODO: do this for all channels panes
127 JSChannelsPane cp = CC.getMainFrame().getChannelsPane(0);
128 for(int i = 0; i < cp.getChannelCount(); i++) {
129 mouseMoved((Channel)cp.getChannel(i));
130 }
131
132 if(oldMouseOverChannel == newMouseOverChannel) return;
133
134 if(oldMouseOverChannel != null) oldMouseOverChannel.mouseExited();
135
136 if(newMouseOverChannel != null) {
137 mouseOverChannelId = newMouseOverChannel.getChannelId();
138 newMouseOverChannel.mouseEntered();
139 }
140
141 oldMouseOverChannel = newMouseOverChannel = null;
142 }
143
144 private static void
145 mouseMoved(Channel c) {
146 int id = c.getChannelId();
147 if(c.mainPane.getMousePosition(true) != null) {
148 newMouseOverChannel = c;
149 } else if(id == mouseOverChannelId) {
150 oldMouseOverChannel = c;
151 }
152 }
153
154 ////////////////////////////////
155
156
157 /**
158 * Creates a new instance of <code>Channel</code> using the specified
159 * non-<code>null</code> channel model.
160 * @param model The model to be used by this channel.
161 * @throws IllegalArgumentException If the model is <code>null</code>.
162 */
163 public
164 Channel(SamplerChannelModel model) {
165 this(model, null);
166 }
167
168 /**
169 * Creates a new instance of <code>Channel</code> using the specified
170 * non-<code>null</code> channel model.
171 * @param model The model to be used by this channel.
172 * @param listener A listener which is notified when the newly created
173 * channel is fully expanded on the screen.
174 * @throws IllegalArgumentException If the model is <code>null</code>.
175 */
176 public
177 Channel(SamplerChannelModel model, final ActionListener listener) {
178 super(model);
179
180 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
181 optionsPane.setAlignmentX(JPanel.CENTER_ALIGNMENT);
182
183 mainPane = new JXCollapsiblePane();
184 viewTracker = new ViewTracker();
185 contextMenu = new ContextMenu();
186
187 mainPane.getContentPane().setLayout (
188 new BoxLayout(mainPane.getContentPane(), BoxLayout.Y_AXIS)
189 );
190
191 int viewIdx = preferences().getIntProperty(DEFAULT_CHANNEL_VIEW);
192 if(viewIdx == 0) {
193 viewTracker.setView(new SmallChannelView(Channel.this));
194 } else if(viewIdx == 1) {
195 viewTracker.setView(new NormalChannelView(Channel.this));
196 } else {
197 viewTracker.setView(new NormalChannelView(Channel.this));
198 }
199
200 setOpaque(false);
201
202 getModel().addSamplerChannelListener(getHandler());
203
204 updateChannelInfo();
205
206 add(mainPane);
207
208 if(listener != null) {
209 final String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
210 mainPane.addPropertyChangeListener(s, new PropertyChangeListener() {
211 public void
212 propertyChange(PropertyChangeEvent e) {
213 if(e.getNewValue() == "expanded") {
214 // TODO: this should be done regardles the listener != null?
215 mainPane.removePropertyChangeListener(s, this);
216 ///////
217 listener.actionPerformed(null);
218 ensureChannelIsVisible();
219 } else if(e.getNewValue() == "expanding/collapsing") {
220 ensureChannelIsVisible();
221 }
222 }
223 });
224 }
225
226 mainPane.setAnimated(false);
227 mainPane.setCollapsed(true);
228 mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
229 mainPane.setCollapsed(false);
230
231 preferences().addPropertyChangeListener(ANIMATED, animatedPorpetyListener);
232
233 if(listener != null) {
234 javax.swing.SwingUtilities.invokeLater(new Runnable() {
235 public void
236 run() { listener.actionPerformed(null); }
237 });
238 }
239
240 CC.getSamplerModel().addSamplerChannelListListener(getHandler());
241
242 installGuiListener();
243 }
244
245 private static void
246 installGuiListener() {
247 if(guiListener != null) return;
248
249 guiListener = new ActionListener() {
250 public void
251 actionPerformed(ActionEvent e) {
252 mouseMoved();
253 }
254 };
255
256 ((MainFrame)CC.getMainFrame()).getGuiTimer().addActionListener(guiListener);
257 }
258
259 private void
260 mouseEntered() {
261 viewTracker.mouseEntered();
262 }
263
264 private void
265 mouseExited() {
266 viewTracker.mouseExited();
267 }
268
269 private void
270 ensureChannelIsVisible() {
271 Container p = getParent();
272 JScrollPane sp = null;
273 while(p != null) {
274 if(p instanceof JScrollPane) {
275 sp = (JScrollPane)p;
276 break;
277 }
278 p = p.getParent();
279 }
280 if(sp == null) return;
281 int h = sp.getViewport().getView().getHeight();
282 sp.getViewport().scrollRectToVisible(new Rectangle(0, h - 2, 1, 1));
283 }
284
285 /**
286 * Determines whether the channel is selected.
287 * @return <code>true</code> if the channel is selected, <code>false</code> otherwise.
288 */
289 public boolean isSelected() { return selected; }
290
291 /**
292 * Sets the selection state of this channel.
293 * This method is invoked when the selection state of the channel has changed.
294 * @param select Specifies the new selection state of this channel;
295 * <code>true</code> to select the channel, <code>false</code> otherwise.
296 */
297 public void
298 setSelected(boolean select) {
299
300 selected = select;
301 }
302
303 /** Shows the channel properties. */
304 public void
305 expandChannel() { expandChannel(optionsPane.isAnimated()); }
306
307 /** Shows the channel properties. */
308 public void
309 expandChannel(boolean animated) {
310 boolean b = optionsPane.isAnimated();
311 optionsPane.setAnimated(animated);
312 viewTracker.getCurrentView().expandChannel();
313 optionsPane.setAnimated(b);
314 }
315
316 /**
317 * Updates the channel settings. This method is invoked when changes to the
318 * channel were made.
319 */
320 private void
321 updateChannelInfo() {
322 viewTracker.getCurrentView().updateChannelInfo();
323 }
324
325 public void
326 loadInstrument() {
327 JSInstrumentChooser dlg = FantasiaUtils.createInstrumentChooser(CC.getMainFrame());
328 dlg.setVisible(true);
329
330 if(!dlg.isCancelled()) {
331 SamplerChannelModel m = getModel();
332 m.loadBackendInstrument(dlg.getInstrumentFile(), dlg.getInstrumentIndex());
333 }
334 }
335
336 public void
337 fallbackToOriginalView() {
338 viewTracker.fallbackToOriginalView();
339 }
340
341 public boolean
342 isUsingOriginalView() {
343 return viewTracker.isUsingOriginalView();
344 }
345
346 protected void
347 onDestroy() {
348 CC.getSamplerModel().removeSamplerChannelListListener(getHandler());
349 preferences().removePropertyChangeListener(ANIMATED, animatedPorpetyListener);
350 if(fxSendsDlg != null) fxSendsDlg.dispose();
351 viewTracker.onDestroy();
352 }
353
354 public void
355 remove() {
356 if(!mainPane.isAnimated()) {
357 CC.getSamplerModel().removeBackendChannel(getChannelId());
358 return;
359 }
360
361 String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
362 mainPane.addPropertyChangeListener(s, getHandler());
363 mainPane.setCollapsed(true);
364 }
365
366 public void
367 showOptionsPane(boolean show) { optionsPane.showOptionsPane(show); }
368
369 public void
370 showFxSendsDialog() {
371 if(fxSendsDlg != null && fxSendsDlg.isVisible()) {
372 fxSendsDlg.toFront();
373 return;
374 }
375
376 fxSendsDlg = new JSFxSendsDlg(new FxSendsPane(getModel()));
377 fxSendsDlg.setVisible(true);
378 }
379
380 private final EventHandler eventHandler = new EventHandler();
381
382 private EventHandler
383 getHandler() { return eventHandler; }
384
385 private class EventHandler implements SamplerChannelListener,
386 SamplerChannelListListener, PropertyChangeListener {
387 /**
388 * Invoked when changes are made to a sampler channel.
389 * @param e A <code>SamplerChannelEvent</code> instance
390 * containing event information.
391 */
392 public void
393 channelChanged(SamplerChannelEvent e) { updateChannelInfo(); }
394
395 /**
396 * Invoked when the number of active disk streams has changed.
397 * @param e A <code>SamplerChannelEvent</code> instance
398 * containing event information.
399 */
400 public void
401 streamCountChanged(SamplerChannelEvent e) {
402 viewTracker.getCurrentView().updateStreamCount(getModel().getStreamCount());
403 }
404
405 /**
406 * Invoked when the number of active voices has changed.
407 * @param e A <code>SamplerChannelEvent</code> instance
408 * containing event information.
409 */
410 public void
411 voiceCountChanged(SamplerChannelEvent e) {
412 viewTracker.getCurrentView().updateVoiceCount(getModel().getVoiceCount());
413 }
414
415 /**
416 * Invoked when a new sampler channel is created.
417 * @param e A <code>SamplerChannelListEvent</code>
418 * instance providing the event information.
419 */
420 public void
421 channelAdded(SamplerChannelListEvent e) { }
422
423 /**
424 * Invoked when a sampler channel is removed.
425 * @param e A <code>SamplerChannelListEvent</code>
426 * instance providing the event information.
427 */
428 public void
429 channelRemoved(SamplerChannelListEvent e) {
430 // Some cleanup when the channel is removed.
431 if(e.getChannelModel().getChannelId() == getChannelId()) {
432 onDestroy();
433 }
434 }
435
436 public void
437 propertyChange(PropertyChangeEvent e) {
438 if(e.getNewValue() == "collapsed") {
439 CC.getSamplerModel().removeBackendChannel(getChannelId());
440 }
441 }
442 }
443
444 public ViewTracker
445 getViewTracker() { return viewTracker; }
446
447 class ViewTracker extends MouseAdapter implements PropertyChangeListener {
448 private ChannelView originalView;
449 private ChannelView mouseOverView;
450 private ChannelView currentView;
451
452 private ChannelView.Type mouseOverViewType = null;
453
454 ViewTracker() {
455
456
457 updateMouseOverViewType();
458
459 String s = DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER;
460 preferences().addPropertyChangeListener(s, this);
461
462 s = CHANNEL_VIEW_ON_MOUSE_OVER;
463 preferences().addPropertyChangeListener(s, this);
464 }
465
466 public boolean
467 isUsingOriginalView() {
468 return currentView == originalView;
469 }
470
471 private void
472 installListeners() {
473
474 }
475
476 private void
477 uninstallListeners() {
478
479 }
480
481 private void
482 updateMouseOverViewType() {
483 if(mouseOverView != null) {
484 mouseOverView.removeEnhancedMouseListener(this);
485 }
486
487 mouseOverView = null;
488
489 boolean b;
490 b = preferences().getBoolProperty(DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER);
491 if(!b) {
492 mouseOverViewType = null;
493 uninstallListeners();
494 return;
495 }
496
497 int i = preferences().getIntProperty(CHANNEL_VIEW_ON_MOUSE_OVER);
498
499 switch(i) {
500 case 0: mouseOverViewType = ChannelView.Type.SMALL; break;
501 case 1: mouseOverViewType = ChannelView.Type.NORMAL; break;
502 default:mouseOverViewType = null;
503 }
504
505 if(mouseOverViewType != null) {
506 installListeners();
507 }
508 }
509
510 public ChannelView
511 getMouseOverView() {
512 if(mouseOverViewType == null) return null;
513
514 if(mouseOverView == null) {
515 Channel channel = Channel.this;
516
517 switch(mouseOverViewType) {
518 case SMALL: mouseOverView = new SmallChannelView(channel); break;
519 case NORMAL: mouseOverView = new NormalChannelView(channel); break;
520 default: mouseOverView = new NormalChannelView(channel);
521 }
522
523 mouseOverView.addEnhancedMouseListener(this);
524 }
525
526 return mouseOverView;
527 }
528
529 public ChannelView
530 getCurrentView() { return currentView; }
531
532 public ChannelView
533 getOriginalView() { return originalView; }
534
535 public void
536 setView(ChannelView view) {
537 setView(view, true);
538 }
539
540 public void
541 setView(ChannelView view, boolean manual) {
542 boolean selected = false;
543 if(currentView != null) selected = currentView.isOptionsButtonSelected();
544
545 if(manual) {
546 if(originalView != null) {
547 originalView.removeEnhancedMouseListener(this);
548 }
549
550 if(originalView != currentView) destroyOriginalView();
551 if(currentView != null && currentView.getType() == view.getType()) {
552 originalView = currentView;
553 originalView.addEnhancedMouseListener(this);
554 destroyView(view);
555 return;
556 }
557
558 removeCurrentView();
559
560 originalView = view;
561 originalView.addEnhancedMouseListener(this);
562 currentView = view;
563 } else {
564 if(view.getType() == getCurrentView().getType()) {
565 destroyView(view);
566 return;
567 }
568
569 removeCurrentView();
570 currentView = view;
571 }
572
573 currentView.setOptionsButtonSelected(selected);
574
575 updateView();
576 }
577
578 private void
579 updateView() {
580 ChannelOptionsView view = getCurrentView().getChannelOptionsView();
581 if(view != null) optionsPane.setContentPane(view.getComponent());
582
583 updateChannelInfo();
584
585 mainPane.add(getCurrentView().getComponent());
586 mainPane.add(optionsPane);
587 mainPane.validate();
588 mainPane.revalidate();
589 mainPane.repaint();
590 }
591
592 public void
593 fallbackToOriginalView() {
594 if(currentView == originalView) return;
595
596 boolean selected = false;
597 if(currentView != null) selected = currentView.isOptionsButtonSelected();
598
599 removeCurrentView();
600 currentView = originalView;
601 currentView.setOptionsButtonSelected(selected);
602
603 updateView();
604 }
605
606 private void
607 removeCurrentView() { removeView(currentView); }
608
609 private void
610 destroyCurrentView() { destroyView(currentView); }
611
612 private void
613 removeOriginalView() { removeView(originalView); }
614
615 private void
616 destroyOriginalView() { destroyView(originalView); }
617
618 private void
619 removeView(ChannelView view) {
620 if(view == null) return;
621
622 mainPane.remove(view.getComponent());
623 mainPane.remove(optionsPane);
624
625 destroyView(view);
626 }
627
628 private void
629 destroyView(ChannelView view) {
630 if(view == null) return;
631
632 view.uninstallView();
633
634 view = null;
635 }
636
637 public boolean
638 isMouseOverEnabled() { return mouseOverViewType != null; }
639
640 private void
641 mouseEntered() {
642 if(!isMouseOverEnabled()) return;
643 if(getCurrentView().getType() == getMouseOverView().getType()) return;
644
645 JSChannel[] channels = CC.getMainFrame().getChannelsPane(0).getChannels();
646 for(JSChannel c : channels) {
647 if(c == Channel.this) continue;
648
649 Channel chn = (Channel)c;
650 if(!(chn).isUsingOriginalView()) chn.fallbackToOriginalView();
651 }
652
653 setView(getMouseOverView(), false);
654 }
655
656 private void
657 mouseExited() {
658 if(!isMouseOverEnabled()) return;
659 if(getCurrentView().getType() == originalView.getType()) return;
660
661 fallbackToOriginalView();
662 }
663
664 public void
665 mouseEntered(MouseEvent e) {
666 guiListener.actionPerformed(null);
667 }
668
669 public void
670 mouseExited(MouseEvent e) {
671 guiListener.actionPerformed(null);
672 }
673
674 public void
675 mousePressed(MouseEvent e) {
676 mousePressed = true;
677 }
678
679 public void
680 mouseReleased(MouseEvent e) {
681 mousePressed = false;
682 }
683
684 public void
685 onDestroy() {
686 destroyCurrentView();
687 destroyOriginalView();
688
689 uninstallListeners();
690
691 if(currentView != null) {
692 currentView.removeEnhancedMouseListener(this);
693 }
694
695 if(mouseOverView != null) {
696 mouseOverView.removeEnhancedMouseListener(this);
697 }
698
699 String s = DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER;
700 preferences().removePropertyChangeListener(s, this);
701
702 s = CHANNEL_VIEW_ON_MOUSE_OVER;
703 preferences().removePropertyChangeListener(s, this);
704 }
705
706 public void
707 propertyChange(PropertyChangeEvent e) {
708 updateMouseOverViewType();
709 }
710 }
711
712 class EditInstrumentAction extends AbstractAction implements SamplerChannelListener {
713 EditInstrumentAction() {
714 super(i18n.getMenuLabel("channels.editInstrument"));
715 channelChanged(null);
716 getModel().addSamplerChannelListener(this);
717 }
718
719 public void
720 actionPerformed(ActionEvent e) {
721 CC.getSamplerModel().editBackendInstrument(getChannelId());
722 }
723
724 public void
725 channelChanged(SamplerChannelEvent e) {
726 boolean b = getChannelInfo().getInstrumentStatus() == 100;
727 setEnabled(b);
728 }
729
730 public void
731 streamCountChanged(SamplerChannelEvent e) { }
732
733 public void
734 voiceCountChanged(SamplerChannelEvent e) { }
735 }
736
737 class FxSendsAction extends AbstractAction {
738 FxSendsAction() {
739 super(i18n.getMenuLabel("channels.fxSends"));
740 }
741
742 public void
743 actionPerformed(ActionEvent e) {
744 showFxSendsDialog();
745 }
746 }
747
748 class ChannelRoutingAction extends AbstractAction implements SamplerChannelListener {
749 ChannelRoutingAction() {
750 super(i18n.getMenuLabel("channels.channelRouting"));
751 channelChanged(null);
752 getModel().addSamplerChannelListener(this);
753 }
754
755 public void
756 actionPerformed(ActionEvent e) {
757 SamplerChannel c = getChannelInfo();
758 new JSChannelOutputRoutingDlg(CC.getMainFrame(), c).setVisible(true);
759 }
760
761 public void
762 channelChanged(SamplerChannelEvent e) {
763 boolean b = getChannelInfo().getAudioOutputDevice() != -1;
764 setEnabled(b);
765 }
766
767 public void
768 streamCountChanged(SamplerChannelEvent e) { }
769
770 public void
771 voiceCountChanged(SamplerChannelEvent e) { }
772 }
773
774 class SetSmallViewAction extends AbstractAction {
775 SetSmallViewAction() {
776 super(i18n.getMenuLabel("channels.smallView"));
777 }
778
779 public void
780 actionPerformed(ActionEvent e) {
781 viewTracker.setView(new SmallChannelView(Channel.this));
782 }
783 }
784
785 class SetNormalViewAction extends AbstractAction {
786 SetNormalViewAction() {
787 super(i18n.getMenuLabel("channels.normalView"));
788 }
789
790 public void
791 actionPerformed(ActionEvent e) {
792 viewTracker.setView(new NormalChannelView(Channel.this));
793 }
794 }
795
796 public ContextMenu
797 getContextMenu() { return contextMenu; }
798
799 class ContextMenu extends MouseAdapter {
800 private JPopupMenu menu = null;
801
802 protected JRadioButtonMenuItem rbmiSmallView;
803 protected JRadioButtonMenuItem rbmiNormalView;
804
805 ContextMenu() {
806
807 }
808
809 private void
810 createMenu() {
811 menu = new JPopupMenu();
812 menu.add(new JMenuItem(new EditInstrumentAction()));
813 menu.addSeparator();
814
815 rbmiSmallView = new JRadioButtonMenuItem(new SetSmallViewAction());
816 rbmiNormalView = new JRadioButtonMenuItem(new SetNormalViewAction());
817 if(viewTracker.getOriginalView() instanceof SmallChannelView) {
818 rbmiSmallView.setSelected(true);
819 } else if(viewTracker.getOriginalView() instanceof NormalChannelView) {
820 rbmiNormalView.setSelected(true);
821 }
822
823 ButtonGroup group = new ButtonGroup();
824 group.add(rbmiSmallView);
825 group.add(rbmiNormalView);
826
827 menu.add(rbmiSmallView);
828 menu.add(rbmiNormalView);
829
830 menu.addSeparator();
831 menu.add(new JMenuItem(new FxSendsAction()));
832 menu.add(new JMenuItem(new ChannelRoutingAction()));
833 }
834
835 private JPopupMenu
836 getMenu() {
837 if(menu == null) createMenu();
838 return menu;
839 }
840
841 public void
842 mousePressed(MouseEvent e) {
843 if(e.isPopupTrigger()) show(e);
844 }
845
846 public void
847 mouseReleased(MouseEvent e) {
848 if(e.isPopupTrigger()) show(e);
849 }
850
851 void
852 show(MouseEvent e) {
853 getMenu().show(e.getComponent(), e.getX(), e.getY());
854 }
855 }
856
857 class FxSendsPane extends JSFxSendsPane {
858 FxSendsPane(SamplerChannelModel model) {
859 super(model);
860
861 actionAddFxSend.putValue(Action.SMALL_ICON, Res.iconNew16);
862 actionRemoveFxSend.putValue(Action.SMALL_ICON, Res.iconDelete16);
863 }
864
865 protected JToolBar
866 createToolBar() {
867 JToolBar tb = new JToolBar();
868 Dimension d = new Dimension(Short.MAX_VALUE, tb.getPreferredSize().height);
869 tb.setMaximumSize(d);
870 tb.setFloatable(false);
871 tb.setAlignmentX(JPanel.RIGHT_ALIGNMENT);
872
873 tb.add(new ToolbarButton(actionAddFxSend));
874 tb.add(new ToolbarButton(actionRemoveFxSend));
875
876 return tb;
877 }
878 }
879
880 public static class StreamVoiceCountPane extends JPanel {
881 private final Channel channel;
882
883 private final JLabel lStreams = createScreenLabel(" --");
884 private final JLabel lSlash = createScreenLabel("/");
885 private final JLabel lVoices = createScreenLabel("-- ");
886
887 public
888 StreamVoiceCountPane(Channel channel) {
889 this.channel = channel;
890
891 setOpaque(false);
892 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
893 lStreams.setFont(Res.fontScreenMono);
894 lStreams.setHorizontalAlignment(JLabel.RIGHT);
895 lStreams.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
896
897 Dimension d = lStreams.getPreferredSize();
898 lStreams.setMinimumSize(d);
899 lStreams.setPreferredSize(d);
900 lStreams.setMaximumSize(d);
901 add(lStreams);
902
903 lSlash.setFont(Res.fontScreenMono);
904 lSlash.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
905 add(lSlash);
906
907 lVoices.setFont(Res.fontScreenMono);
908 lVoices.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
909
910 d = lStreams.getPreferredSize();
911 lVoices.setMinimumSize(d);
912 lVoices.setPreferredSize(d);
913 lVoices.setMaximumSize(d);
914 add(lVoices);
915
916 lStreams.addMouseListener(channel.getContextMenu());
917 lSlash.addMouseListener(channel.getContextMenu());
918 lVoices.addMouseListener(channel.getContextMenu());
919 }
920
921 public void
922 updateStreamCount(int count) {
923 lStreams.setText(count == 0 ? " --" : String.valueOf(count));
924 }
925
926 public void
927 updateVoiceCount(int count) {
928 lVoices.setText(count == 0 ? "-- " : String.valueOf(count));
929 }
930 }
931
932 public static class VolumePane extends JPanel {
933 private final Channel channel;
934 private final JButton btnVolume = createScreenButton("");
935 private JSVolumeEditorPopup popupVolume;
936
937 private static NumberFormat numberFormat = NumberFormat.getInstance();
938 static { numberFormat.setMaximumFractionDigits(1); }
939
940 public
941 VolumePane(final Channel channel) {
942 this.channel = channel;
943 setOpaque(false);
944 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
945
946 btnVolume.setIcon(Res.iconVolume14);
947 btnVolume.setIconTextGap(2);
948 btnVolume.setAlignmentX(RIGHT_ALIGNMENT);
949 btnVolume.setHorizontalAlignment(btnVolume.LEFT);
950 updateVolumeInfo(100);
951 Dimension d = btnVolume.getPreferredSize();
952 d.width = 57;
953 btnVolume.setPreferredSize(d);
954 btnVolume.setMinimumSize(d);
955
956 add(btnVolume);
957
958 btnVolume.addActionListener(new ActionListener() {
959 public void
960 actionPerformed(ActionEvent e) {
961 if(popupVolume.isVisible()) {
962 popupVolume.commit();
963 popupVolume.hide();
964 } else {
965 float vol = channel.getModel().getChannelInfo().getVolume();
966 popupVolume.setCurrentVolume(vol);
967 popupVolume.show();
968 }
969 }
970 });
971
972 popupVolume = new JSVolumeEditorPopup(btnVolume, VolumeType.CHANNEL);
973
974 popupVolume.addActionListener(new ActionListener() {
975 public void
976 actionPerformed(ActionEvent e) {
977 channel.getModel().setBackendVolume(popupVolume.getVolumeFactor());
978 }
979 });
980
981 btnVolume.addMouseListener(channel.getContextMenu());
982 }
983
984 public void
985 updateVolumeInfo(int volume) {
986 if(CC.getViewConfig().isMeasurementUnitDecibel()) {
987 String s = numberFormat.format(HF.percentsToDecibels(volume));
988 btnVolume.setText(s + "dB");
989 } else {
990 btnVolume.setText(String.valueOf(volume) + "%");
991 }
992 }
993 }
994
995 public static class PowerButton extends PixmapToggleButton implements ActionListener {
996 private final Channel channel;
997
998 PowerButton(Channel channel) {
999 this(channel, Res.gfxPowerOff, Res.gfxPowerOn);
1000 }
1001
1002 PowerButton(Channel channel, ImageIcon defaultIcon, ImageIcon selectedIcon) {
1003 super(defaultIcon, selectedIcon);
1004
1005 this.channel = channel;
1006
1007 setSelected(true);
1008 addActionListener(this);
1009 setToolTipText(i18n.getButtonLabel("Channel.ttRemoveChannel"));
1010 }
1011
1012 public void
1013 actionPerformed(ActionEvent e) {
1014 boolean b = preferences().getBoolProperty(CONFIRM_CHANNEL_REMOVAL);
1015 if(b) {
1016 String s = i18n.getMessage("Channel.remove?", channel.getChannelId());
1017 if(!HF.showYesNoDialog(channel, s)) {
1018 setSelected(true);
1019 return;
1020 }
1021 }
1022 channel.remove();
1023 }
1024
1025 public boolean
1026 contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }
1027 }
1028
1029 public static class OptionsButton extends PixmapToggleButton
1030 implements ActionListener, PropertyChangeListener {
1031
1032 private final Channel channel;
1033
1034 OptionsButton(Channel channel) {
1035 super(Res.gfxOptionsOff, Res.gfxOptionsOn);
1036
1037 this.channel = channel;
1038
1039 setRolloverIcon(Res.gfxOptionsOffRO);
1040 this.setRolloverSelectedIcon(Res.gfxOptionsOnRO);
1041 addActionListener(this);
1042 setToolTipText(i18n.getButtonLabel("Channel.ttShowOptions"));
1043 }
1044
1045 public void
1046 actionPerformed(ActionEvent e) {
1047 ChannelView view = channel.viewTracker.getCurrentView();
1048
1049 if(isSelected() && view.getChannelOptionsView() == null) {
1050 view.installChannelOptionsView();
1051 JComponent c = view.getChannelOptionsView().getComponent();
1052 channel.optionsPane.setContentPane(c);
1053 }
1054
1055 channel.showOptionsPane(isSelected());
1056
1057 String s;
1058 if(isSelected()) s = i18n.getButtonLabel("Channel.ttHideOptions");
1059 else s = i18n.getButtonLabel("Channel.ttShowOptions");
1060
1061 setToolTipText(s);
1062
1063 s = JXCollapsiblePane.ANIMATION_STATE_KEY;
1064 channel.optionsPane.addPropertyChangeListener(s, this);
1065 }
1066
1067 public void
1068 propertyChange(PropertyChangeEvent e) {
1069 if(e.getNewValue() == "collapsed") {
1070 ChannelView view = channel.viewTracker.getCurrentView();
1071 view.uninstallChannelOptionsView();
1072 channel.optionsPane.setContentPane(new JPanel());
1073 }
1074 }
1075
1076 public void
1077 onDestroy() {
1078 String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
1079 channel.optionsPane.removePropertyChangeListener(s, this);
1080 }
1081
1082 public boolean
1083 contains(int x, int y) { return super.contains(x, y) & y < 13; }
1084 }
1085 }
1086
1087 class ChannelOptionsPane extends JXCollapsiblePane {
1088 ChannelOptionsPane() {
1089 setAnimated(false);
1090 setCollapsed(true);
1091 setAnimated(preferences().getBoolProperty(ANIMATED));
1092
1093 preferences().addPropertyChangeListener(ANIMATED, new PropertyChangeListener() {
1094 public void
1095 propertyChange(PropertyChangeEvent e) {
1096 setAnimated(preferences().getBoolProperty(ANIMATED));
1097 }
1098 });
1099 }
1100
1101 public void
1102 showOptionsPane(boolean show) { setCollapsed(!show); }
1103 }

  ViewVC Help
Powered by ViewVC