/[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 1818 - (show annotations) (download)
Wed Dec 24 17:29:47 2008 UTC (15 years, 3 months ago) by iliev
File size: 29129 byte(s)
* Added support for controlling the global sampler-wide limit of
  maximum voices and disk streams
  (choose Edit/Preferences, then click the `General' tab)
* Fantasia: store the view configuration of audio/MIDI devices and sampler
  channels in the LSCP script when exporting sampler configuration
* Fantasia: Implemented multiple sampler channels' selection
* Fantasia: Added option to move sampler channels up and down
  in the channels list
* Fantasia: Added option to move sampler channels
  to another channels panels

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

  ViewVC Help
Powered by ViewVC