/[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 1734 - (show annotations) (download)
Sun May 4 18:40:13 2008 UTC (15 years, 11 months ago) by iliev
File size: 26243 byte(s)
* bugfix: JSampler took forever to load a configuration with
  too many sampler channels
* Implemented option to show different channel view when
  the mouse pointer is over sampler channel
  (choose Edit/Preferences, then click the `Defaults' tab)

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

  ViewVC Help
Powered by ViewVC