/[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 1737 - (show annotations) (download)
Thu May 8 17:26:19 2008 UTC (15 years, 11 months ago) by iliev
File size: 28928 byte(s)
* Major memory optimizations when too many sampler channels are present

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

  ViewVC Help
Powered by ViewVC