/[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 2288 - (show annotations) (download)
Wed Nov 23 21:19:44 2011 UTC (12 years, 5 months ago) by iliev
File size: 29183 byte(s)
* Added option to select a sampler engine in Add/Edit Instrument dialog
* Moved all Swing dependent code outside the JSampler core

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

  ViewVC Help
Powered by ViewVC