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

Contents of /jsampler/trunk/src/org/jsampler/view/fantasia/SmallChannelView.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: 20039 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.Color;
26 import java.awt.Dimension;
27 import java.awt.Graphics;
28 import java.awt.Graphics2D;
29 import java.awt.Insets;
30
31 import java.awt.event.ActionEvent;
32 import java.awt.event.ActionListener;
33 import java.awt.event.MouseAdapter;
34 import java.awt.event.MouseEvent;
35 import java.awt.event.MouseListener;
36
37 import java.beans.PropertyChangeEvent;
38 import java.beans.PropertyChangeListener;
39
40 import java.util.Vector;
41
42 import javax.swing.BorderFactory;
43 import javax.swing.Box;
44 import javax.swing.BoxLayout;
45 import javax.swing.JButton;
46 import javax.swing.JComponent;
47 import javax.swing.JLabel;
48 import javax.swing.JPanel;
49
50 import org.jsampler.CC;
51 import org.jsampler.event.SamplerChannelListEvent;
52 import org.jsampler.event.SamplerChannelListListener;
53
54 import org.jsampler.view.fantasia.basic.FantasiaPainter;
55 import org.jsampler.view.fantasia.basic.PixmapButton;
56 import org.jsampler.view.fantasia.basic.PixmapPane;
57
58 import org.jvnet.substance.utils.SubstanceImageCreator;
59
60 import org.linuxsampler.lscp.SamplerChannel;
61
62 import static org.jsampler.view.fantasia.FantasiaI18n.i18n;
63 import static org.jsampler.view.fantasia.FantasiaPrefs.*;
64 import static org.jsampler.view.fantasia.FantasiaUtils.*;
65
66
67 /**
68 *
69 * @author Grigor Iliev
70 */
71 public class SmallChannelView extends JPanel implements ChannelView {
72 private final Channel channel;
73 private ChannelOptionsView channelOptionsView = null;
74
75 private final ChannelScreen screen;
76 private final Channel.PowerButton btnPower;
77 private final MuteButton btnMute = new MuteButton();
78 private final SoloButton btnSolo = new SoloButton();
79 private final Channel.OptionsButton btnOptions;
80
81 private final Vector<JComponent> components = new Vector<JComponent>();
82
83
84 /** Creates a new instance of <code>SmallChannelView</code> */
85 public
86 SmallChannelView(Channel channel) {
87 components.add(this);
88
89 this.channel = channel;
90
91 screen = new ChannelScreen(channel);
92
93 btnPower = new Channel.PowerButton(channel);
94 components.add(btnPower);
95
96 btnOptions = new Channel.OptionsButton(channel);
97 components.add(btnOptions);
98
99 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
100
101 setBorder(BorderFactory.createEmptyBorder(1, 3, 0, 11));
102
103 add(btnPower);
104 add(Box.createRigidArea(new Dimension(4, 0)));
105
106 add(createVSeparator());
107 add(Box.createRigidArea(new Dimension(3, 0)));
108
109 add(screen);
110
111 add(Box.createRigidArea(new Dimension(2, 0)));
112 add(createVSeparator());
113 add(new FxSendsButton());
114
115 add(createVSeparator());
116 add(Box.createRigidArea(new Dimension(1, 0)));
117
118 components.add(btnMute);
119 components.add(btnSolo);
120
121 add(btnMute);
122 add(btnSolo);
123
124 add(Box.createRigidArea(new Dimension(1, 0)));
125 add(createVSeparator());
126 add(Box.createRigidArea(new Dimension(8, 0)));
127
128 add(btnOptions);
129
130 setPreferredSize(new Dimension(420, 22));
131 setMinimumSize(getPreferredSize());
132 setMaximumSize(getPreferredSize());
133
134 installView();
135 }
136
137 @Override
138 protected void
139 paintComponent(Graphics g) {
140 if(isOpaque()) super.paintComponent(g);
141
142 double h = getSize().getHeight();
143 double w = getSize().getWidth();
144
145 Color c1 = channel.isSelected() ? new Color(0x555555) : new Color(0x888888);
146 Color c2 = channel.isSelected() ? new Color(0x606060) : new Color(0x707070);
147
148 Graphics2D g2 = (Graphics2D)g;
149 FantasiaPainter.paintGradient(g2, 0, 0, w - 1, h - 1, c1, c2);
150 FantasiaPainter.paintOuterBorder(g2, 0, 0, w - 1, h - 1, false, 0.27f, 0.11f, 0.64f, 0.20f);
151 }
152
153 //////////////////////////////////////////////
154 // Implementation of the ChannelView interface
155 //////////////////////////////////////////////
156
157 @Override
158 public Type
159 getType() { return Type.SMALL; }
160
161 @Override
162 public JComponent
163 getComponent() { return this; }
164
165 @Override
166 public void
167 installView() {
168 String vmud = VOL_MEASUREMENT_UNIT_DECIBEL;
169 preferences().addPropertyChangeListener(vmud, new PropertyChangeListener() {
170 public void
171 propertyChange(PropertyChangeEvent e) {
172 boolean b;
173 b = preferences().getBoolProperty(VOL_MEASUREMENT_UNIT_DECIBEL);
174 screen.updateVolumeInfo();
175 }
176 });
177
178 addEnhancedMouseListener(channel.getContextMenu());
179 CC.getSamplerModel().addSamplerChannelListListener(getHandler());
180 addEnhancedMouseListener(getHandler());
181 }
182
183 @Override
184 public void
185 uninstallView() {
186 //removeEnhancedMouseListener(channel.getContextMenu());
187 CC.getSamplerModel().removeSamplerChannelListListener(getHandler());
188 screen.onDestroy();
189 btnOptions.onDestroy();
190 uninstallChannelOptionsView();
191 removeEnhancedMouseListener(getHandler());
192 }
193
194 @Override
195 public void
196 installChannelOptionsView() {
197 if(channelOptionsView != null) return;
198
199 channelOptionsView = new NormalChannelOptionsView(channel);
200 channelOptionsView.installView();
201
202 }
203
204 @Override
205 public void
206 uninstallChannelOptionsView() {
207 if(channelOptionsView == null) return;
208 channelOptionsView.uninstallView();
209 channelOptionsView = null;
210 }
211
212 @Override
213 public ChannelOptionsView
214 getChannelOptionsView() { return channelOptionsView; }
215
216 @Override
217 public void
218 updateChannelInfo() {
219 SamplerChannel sc = channel.getChannelInfo();
220
221 screen.updateScreenInfo(sc);
222 screen.updateVolumeInfo();
223 updateMuteIcon(sc);
224
225 if(sc.isSoloChannel()) btnSolo.setIcon(Res.gfxSoloSmallOn);
226 else btnSolo.setIcon(Res.gfxSoloSmallOff);
227
228 boolean b = sc.getEngine() != null;
229 btnSolo.setEnabled(b);
230 btnMute.setEnabled(b);
231
232 if(getChannelOptionsView() != null) getChannelOptionsView().updateChannelInfo();
233 }
234
235 @Override
236 public void
237 updateStreamCount(int count) { screen.updateStreamCount(count); }
238
239 @Override
240 public void
241 updateVoiceCount(int count) { screen.updateVoiceCount(count); }
242
243 @Override
244 public void
245 expandChannel() {
246 if(btnOptions.isSelected()) return;
247 btnOptions.doClick();
248 }
249
250 @Override
251 public boolean
252 isOptionsButtonSelected() { return btnOptions.isSelected(); }
253
254 @Override
255 public void
256 setOptionsButtonSelected(boolean b) {
257 btnOptions.setSelected(b);
258 }
259
260 @Override
261 public void
262 addEnhancedMouseListener(MouseListener l) {
263 removeEnhancedMouseListener(l);
264
265 for(JComponent c : components) c.addMouseListener(l);
266 screen.addEnhancedMouseListener(l);
267 }
268
269 @Override
270 public void
271 removeEnhancedMouseListener(MouseListener l) {
272 for(JComponent c : components) c.removeMouseListener(l);
273 screen.removeEnhancedMouseListener(l);
274 }
275
276 //////////////////////////////////////////////
277
278
279 /**
280 * Updates the mute button with the proper icon regarding to information obtained
281 * from <code>channel</code>.
282 * @param channel A <code>SamplerChannel</code> instance containing the new settings
283 * for this channel.
284 */
285 private void
286 updateMuteIcon(SamplerChannel channel) {
287 if(channel.isMutedBySolo()) btnMute.setIcon(Res.gfxMutedBySoloSmall);
288 else if(channel.isMuted()) btnMute.setIcon(Res.gfxMuteSmallOn);
289 else btnMute.setIcon(Res.gfxMuteSmallOff);
290 }
291
292 protected JPanel
293 createVSeparator() {
294 PixmapPane p = new PixmapPane(Res.gfxVLine);
295 p.setOpaque(false);
296 p.setPreferredSize(new Dimension(2, 22));
297 p.setMinimumSize(p.getPreferredSize());
298 p.setMaximumSize(p.getPreferredSize());
299 return p;
300 }
301
302
303 private final EventHandler eventHandler = new EventHandler();
304
305 private EventHandler
306 getHandler() { return eventHandler; }
307
308 private class EventHandler extends MouseAdapter implements SamplerChannelListListener {
309 @Override
310 public void
311 channelAdded(SamplerChannelListEvent e) {
312 if(CC.getSamplerModel().getChannelListIsAdjusting()) return;
313 screen.channelInfoPane.updateChannelIndex();
314 }
315
316 @Override
317 public void
318 channelRemoved(SamplerChannelListEvent e) {
319 //if(CC.getSamplerModel().getChannelListIsAdjusting()) return; //TODO:
320
321 screen.channelInfoPane.updateChannelIndex();
322 }
323
324 @Override
325 public void
326 mousePressed(MouseEvent e) {
327 // TAG: channel selection system
328 if(e.getButton() == MouseEvent.BUTTON3 && channel.isSelected()) return;
329
330 CC.getMainFrame().getSelectedChannelsPane().processChannelSelection (
331 channel, e.isControlDown(), e.isShiftDown()
332 );
333 ///////
334 }
335 }
336
337
338 private class MuteButton extends PixmapButton implements ActionListener {
339 MuteButton() {
340 super(Res.gfxMuteSmallOff);
341 setDisabledIcon (
342 SubstanceImageCreator.makeTransparent(this, Res.gfxMuteSmallOff, 0.4)
343 );
344 addActionListener(this);
345 }
346
347 @Override
348 public void
349 actionPerformed(ActionEvent e) {
350 SamplerChannel sc = channel.getChannelInfo();
351 boolean b = true;
352
353 /*
354 * Changing the mute button icon now instead of
355 * leaving the work to the notification mechanism of the LinuxSampler.
356 */
357 if(sc.isMuted() && !sc.isMutedBySolo()) {
358 b = false;
359 boolean hasSolo = CC.getSamplerModel().hasSoloChannel();
360
361 if(sc.isSoloChannel() || !hasSolo) setIcon(Res.gfxMuteSmallOff);
362 else setIcon(Res.gfxMutedBySoloSmall);
363 } else setIcon(Res.gfxMuteSmallOn);
364
365 channel.getModel().setBackendMute(b);
366 }
367
368 //public boolean
369 //contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }
370 }
371
372 private class SoloButton extends PixmapButton implements ActionListener {
373 SoloButton() {
374 super(Res.gfxSoloSmallOff);
375 //setDisabledIcon(Res.gfxMuteSoloDisabled);
376 setDisabledIcon (
377 SubstanceImageCreator.makeTransparent(this, Res.gfxSoloSmallOff, 0.4)
378 );
379 addActionListener(this);
380 }
381
382 @Override
383 public void
384 actionPerformed(ActionEvent e) {
385 SamplerChannel sc = channel.getChannelInfo();
386 boolean b = !sc.isSoloChannel();
387
388 /*
389 * Changing the solo button icon (and related) now instead of
390 * leaving the work to the notification mechanism of the LinuxSampler.
391 */
392 if(b) {
393 setIcon(Res.gfxSoloSmallOn);
394 if(sc.isMutedBySolo()) btnMute.setIcon(Res.gfxMuteSmallOff);
395 } else {
396 setIcon(Res.gfxSoloSmallOff);
397 if(!sc.isMuted() && CC.getSamplerModel().getSoloChannelCount() > 1)
398 btnMute.setIcon(Res.gfxMutedBySoloSmall);
399 }
400
401 channel.getModel().setBackendSolo(b);
402 }
403
404 //public boolean
405 //contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }
406 }
407
408 static class ChannelScreen extends PixmapPane {
409 private final Channel channel;
410
411 private final ChannelInfoPane channelInfoPane;
412
413 private final Channel.StreamVoiceCountPane streamVoiceCountPane;
414
415
416 private final Channel.VolumePane volumePane;
417
418 private JButton btnInstr =
419 createScreenButton(i18n.getButtonLabel("ChannelScreen.btnInstr"));
420
421
422 private static Insets pixmapInsets = new Insets(5, 5, 4, 5);
423
424 private final Vector<JComponent> components = new Vector<JComponent>();
425
426 private final PropertyChangeListener chnNumberingListener;
427 private final PropertyChangeListener showMidiInfoListener;
428 private final PropertyChangeListener showStreamVoiceCountListener;
429
430 private boolean bShowNumbering;
431 private boolean bShowMidiInfo;
432
433 ChannelScreen(final Channel channel) {
434 super(Res.gfxTextField);
435
436 components.add(this);
437
438 this.channel = channel;
439
440 streamVoiceCountPane = new Channel.StreamVoiceCountPane(channel);
441 components.add(streamVoiceCountPane);
442
443 channelInfoPane = new ChannelInfoPane(channel);
444 volumePane = new Channel.VolumePane(channel);
445 components.add(volumePane);
446
447 setPixmapInsets(pixmapInsets);
448 setBorder(BorderFactory.createEmptyBorder(4, 3, 3, 4));
449
450 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
451
452 JPanel p = new JPanel();
453 components.add(p);
454 p.setOpaque(false);
455 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
456
457 p.add(channelInfoPane);
458
459 btnInstr.setRolloverEnabled(false);
460 btnInstr.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
461 btnInstr.setHorizontalAlignment(btnInstr.LEFT);
462
463 int h = btnInstr.getPreferredSize().height;
464 btnInstr.setPreferredSize(new Dimension(100, h));
465 btnInstr.setMinimumSize(btnInstr.getPreferredSize());
466 btnInstr.setMaximumSize(new Dimension(Short.MAX_VALUE, h));
467 components.add(btnInstr);
468
469 p.add(btnInstr);
470 p.add(streamVoiceCountPane);
471
472 h = p.getPreferredSize().height;
473 p.setPreferredSize(new Dimension(201, h));
474 p.setMinimumSize(p.getPreferredSize());
475 p.setMaximumSize(p.getPreferredSize());
476
477 add(p);
478 add(Box.createRigidArea(new Dimension(3, 0)));
479 add(volumePane);
480
481 setPreferredSize(new Dimension(270, getPreferredSize().height));
482 setMinimumSize(getPreferredSize());
483 setMaximumSize(getPreferredSize());
484
485 btnInstr.addActionListener(new ActionListener() {
486 public void
487 actionPerformed(ActionEvent e) { channel.loadInstrument(); }
488 });
489
490 final String s = "channel.smallView.showChannelNumbering";
491
492 chnNumberingListener = new PropertyChangeListener() {
493 public void
494 propertyChange(PropertyChangeEvent e) {
495 bShowNumbering = preferences().getBoolProperty(s);
496 channelInfoPane.setShowNumbering(bShowNumbering);
497 }
498 };
499
500 preferences().addPropertyChangeListener(s, chnNumberingListener);
501
502 bShowNumbering = preferences().getBoolProperty(s);
503 channelInfoPane.setShowNumbering(bShowNumbering);
504
505
506 final String s2 = "channel.smallView.showMidiInfo";
507
508 showMidiInfoListener = new PropertyChangeListener() {
509 public void
510 propertyChange(PropertyChangeEvent e) {
511 bShowMidiInfo = preferences().getBoolProperty(s2);
512 channelInfoPane.setShowMidiInfo(bShowMidiInfo);
513 }
514 };
515
516 preferences().addPropertyChangeListener(s2, showMidiInfoListener);
517
518 bShowMidiInfo = preferences().getBoolProperty(s2);
519 channelInfoPane.setShowMidiInfo(bShowMidiInfo);
520
521
522 final String s3 = "channel.smallView.showStreamVoiceCount";
523
524 showStreamVoiceCountListener = new PropertyChangeListener() {
525 public void
526 propertyChange(PropertyChangeEvent e) {
527 boolean b = preferences().getBoolProperty(s3);
528 streamVoiceCountPane.setVisible(b);
529 }
530 };
531
532 preferences().addPropertyChangeListener(s3, showStreamVoiceCountListener);
533
534 boolean b = preferences().getBoolProperty(s3);
535 streamVoiceCountPane.setVisible(b);
536 }
537
538 public void
539 addEnhancedMouseListener(MouseListener l) {
540 removeEnhancedMouseListener(l);
541 for(JComponent c : components) c.addMouseListener(l);
542 }
543
544 public void
545 removeEnhancedMouseListener(MouseListener l) {
546 for(JComponent c : components) c.removeMouseListener(l);
547 }
548
549 protected void
550 updateVolumeInfo() {
551 float f = channel.getChannelInfo().getVolume() * 100.0f;
552 volumePane.updateVolumeInfo((int)f);
553 }
554
555 /**
556 * Updates the number of active disk streams.
557 * @param count The new number of active disk streams.
558 */
559 protected void
560 updateStreamCount(int count) {
561 streamVoiceCountPane.updateStreamCount(count);
562 }
563
564 /**
565 * Updates the number of active voices.
566 * @param count The new number of active voices.
567 */
568 protected void
569 updateVoiceCount(int count) {
570 streamVoiceCountPane.updateVoiceCount(count);
571 }
572
573 protected void
574 updateScreenInfo(SamplerChannel sc) {
575 String s = btnInstr.getToolTipText();
576
577 int status = sc.getInstrumentStatus();
578 if(status >= 0 && status < 100) {
579 btnInstr.setText(i18n.getLabel("ChannelScreen.loadingInstrument", status));
580 if(s != null) btnInstr.setToolTipText(null);
581 } else if(status == -1) {
582 btnInstr.setText(i18n.getButtonLabel("ChannelScreen.btnInstr"));
583 if(s != null) btnInstr.setToolTipText(null);
584 } else if(status < -1) {
585 btnInstr.setText(i18n.getLabel("ChannelScreen.errorLoadingInstrument"));
586 if(s != null) btnInstr.setToolTipText(null);
587 } else {
588 if(sc.getInstrumentName() != null) btnInstr.setText(sc.getInstrumentName());
589 else btnInstr.setText(i18n.getButtonLabel("ChannelScreen.btnInstr"));
590
591 btnInstr.setToolTipText(sc.getInstrumentName());
592 }
593
594 channelInfoPane.updateChannelInfo();
595 }
596
597 public void
598 onDestroy() {
599 String s = "channel.smallView.showChannelNumbering";
600 preferences().removePropertyChangeListener(s, chnNumberingListener);
601
602 s = "channel.smallView.showMidiInfo";
603 preferences().removePropertyChangeListener(s, showMidiInfoListener);
604
605 s = "channel.smallView.showStreamVoiceCount";
606 preferences().removePropertyChangeListener(s, showStreamVoiceCountListener);
607 }
608 }
609
610 private static class ChannelInfoPane extends JPanel {
611 private final Channel channel;
612 private final JLabel lInfo;
613
614 private int channelIndex = -1;
615
616 private boolean showNumbering;
617 private boolean showMidiInfo;
618
619 ChannelInfoPane(Channel channel) {
620 this.channel = channel;
621
622 setOpaque(false);
623 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
624
625 lInfo = createScreenLabel("");
626 lInfo.setFont(Res.fontScreenMono);
627
628 updateChannelIndex();
629
630 updateLabelLength();
631
632 add(lInfo);
633 }
634
635 private void
636 updateLabelLength() {
637 lInfo.setPreferredSize(null);
638
639 int l = 0;
640 if(getShowNumbering()) l += 4;
641 if(channelIndex > 98) l++;
642 if(getShowMidiInfo()) l += 6;
643
644 StringBuffer sb = new StringBuffer();
645 for(int i = 0; i < l; i++) sb.append("0");
646 lInfo.setText(sb.toString());
647
648 lInfo.setPreferredSize(lInfo.getPreferredSize()); // Don't remove this!
649 lInfo.setMinimumSize(lInfo.getPreferredSize());
650 lInfo.setMaximumSize(lInfo.getPreferredSize());
651 }
652
653 protected void
654 updateChannelInfo() {
655 StringBuffer sb = new StringBuffer();
656
657 if(getShowNumbering()) {
658 if(channelIndex < 9) sb.append(" ");
659 sb.append(channelIndex + 1).append(": ");
660 }
661
662 if(getShowMidiInfo()) {
663 SamplerChannel sc = channel.getChannelInfo();
664 if(sc.getMidiInputDevice() == -1) {
665 sb.append("-/-");
666 } else {
667 sb.append(sc.getMidiInputPort()).append("/");
668
669 if(sc.getMidiInputChannel() == -1) sb.append("All");
670 else sb.append(sc.getMidiInputChannel() + 1);
671 }
672 }
673
674 lInfo.setText(sb.toString());
675 }
676
677 protected void
678 updateChannelIndex() {
679 int i = CC.getMainFrame().getChannelNumber(channel.getModel());
680
681 boolean b = false;
682 if(i > 98 && channelIndex <= 98) b = true;
683 if(i < 99 && channelIndex >= 99) b = true;
684
685 channelIndex = i;
686 if(b) updateLabelLength();
687
688 if(!getShowNumbering()) return;
689
690 updateChannelInfo();
691 }
692
693 protected boolean
694 getShowNumbering() { return showNumbering; }
695
696 protected void
697 setShowNumbering(boolean b) {
698 if(b == showNumbering) return;
699 showNumbering = b;
700
701 updateLabelLength();
702 updateChannelIndex();
703 }
704
705 protected boolean
706 getShowMidiInfo() { return showMidiInfo; }
707
708 protected void
709 setShowMidiInfo(boolean b) {
710 if(b == showMidiInfo) return;
711 showMidiInfo = b;
712
713 String s = b ? i18n.getLabel("SmallChannelView.ttMidiPortChannel") : null;
714 lInfo.setToolTipText(s);
715
716 updateLabelLength();
717 updateChannelInfo();
718 }
719 }
720
721 private class FxSendsButton extends PixmapButton implements ActionListener {
722 FxSendsButton() {
723 super(Res.gfxFx);
724
725 setRolloverIcon(Res.gfxFxRO);
726
727 addActionListener(this);
728 }
729
730 @Override
731 public void
732 actionPerformed(ActionEvent e) { channel.showFxSendsDialog(); }
733
734 @Override
735 public boolean
736 contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }
737 }
738 }

  ViewVC Help
Powered by ViewVC