/[svn]/jsampler/trunk/src/org/jsampler/view/std/StdChannelsPane.java
ViewVC logotype

Contents of /jsampler/trunk/src/org/jsampler/view/std/StdChannelsPane.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2200 - (show annotations) (download)
Sun Jul 3 22:01:16 2011 UTC (12 years, 9 months ago) by iliev
File size: 12827 byte(s)
* added support for exporting effects to LSCP script
* Sampler Browser (work in progress): initial
  implementation of sampler channels

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2009 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.std;
24
25
26 import java.awt.BorderLayout;
27 import java.awt.Component;
28 import java.awt.Rectangle;
29
30 import java.awt.event.KeyEvent;
31
32 import java.util.Vector;
33
34 import javax.swing.BorderFactory;
35 import javax.swing.JScrollPane;
36 import javax.swing.KeyStroke;
37 import javax.swing.ListSelectionModel;
38
39 import javax.swing.event.ListSelectionEvent;
40 import javax.swing.event.ListSelectionListener;
41
42 import net.sf.juife.ComponentList;
43 import net.sf.juife.ComponentListModel;
44 import net.sf.juife.DefaultComponentListModel;
45
46 import org.jsampler.CC;
47 import org.jsampler.SamplerChannelModel;
48
49 import org.jsampler.view.JSChannel;
50 import org.jsampler.view.JSChannelsPane;
51
52 import static javax.swing.KeyStroke.*;
53
54
55 /**
56 *
57 * @author Grigor Iliev
58 */
59 public abstract class StdChannelsPane extends JSChannelsPane implements ListSelectionListener {
60 protected final ChannelList chnList = createChannelList();
61 protected final ChannelListModel listModel = createChannelListModel();
62
63 protected final JScrollPane scrollPane;
64
65 protected static class ChannelList extends ComponentList { }
66
67 protected static class ChannelListModel extends DefaultComponentListModel<JSChannel> { }
68
69 private final Vector<ListSelectionListener> selListeners = new Vector<ListSelectionListener>();
70
71 /**
72 * Creates a new instance of <code>StdChannelsPane</code> with
73 * the specified <code>title</code>.
74 * @param title The title of this <code>StdChannelsPane</code>
75 */
76 public
77 StdChannelsPane(String title) {
78 super(title);
79
80 setLayout(new BorderLayout());
81
82 chnList.setOpaque(false);
83 //chnList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
84 chnList.setModel(listModel);
85 chnList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
86
87 scrollPane = new JScrollPane(chnList);
88 scrollPane.setBorder(BorderFactory.createEmptyBorder());
89 add(scrollPane);
90
91 setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
92 installListeners();
93 }
94
95 protected void
96 installListeners() {
97 chnList.addListSelectionListener(this);
98
99 KeyStroke k = getKeyStroke(KeyEvent.VK_UP, KeyEvent.ALT_MASK | KeyEvent.SHIFT_MASK);
100 getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(k, "a4n.moveChannelsOnTop");
101 getActionMap().put("a4n.moveChannelsOnTop", getA4n().moveChannelsOnTop);
102
103 k = getKeyStroke(KeyEvent.VK_UP, KeyEvent.ALT_MASK);
104 getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(k, "a4n.moveChannelsUp");
105 getActionMap().put("a4n.moveChannelsUp", getA4n().moveChannelsUp);
106
107 k = getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.ALT_MASK);
108 getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(k, "a4n.moveChannelsDown");
109 getActionMap().put("a4n.moveChannelsDown", getA4n().moveChannelsDown);
110
111 k = getKeyStroke(KeyEvent.VK_DOWN, KeyEvent.ALT_MASK | KeyEvent.SHIFT_MASK);
112 getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(k, "a4n.moveChannelsAtBottom");
113 getActionMap().put("a4n.moveChannelsAtBottom", getA4n().moveChannelsAtBottom);
114
115 }
116
117 public StdA4n
118 getA4n() { return ((StdMainFrame)CC.getMainFrame()).getA4n(); }
119
120 /**
121 * Registers the specified listener for receiving list selection events.
122 * @param listener The <code>ListSelectionListener</code> to register.
123 */
124 @Override
125 public void
126 addListSelectionListener(ListSelectionListener listener) {
127 selListeners.add(listener);
128 }
129
130 /**
131 * Removes the specified listener.
132 * @param listener The <code>ListSelectionListener</code> to remove.
133 */
134 @Override
135 public void
136 removeListSelectionListener(ListSelectionListener listener) {
137 selListeners.remove(listener);
138 }
139
140 /**
141 * Invoked when the selection has changed.
142 * This method implements <code>valueChanged</code>
143 * method of the <code>ListSelectionListener</code> interface.
144 * @param e A <code>ListSelectionEvent</code>
145 * instance providing the event information.
146 */
147 @Override
148 public void
149 valueChanged(ListSelectionEvent e) {
150 ListSelectionEvent e2 = null;
151 for(ListSelectionListener l : selListeners) {
152 if(e2 == null) e2 = new ListSelectionEvent (
153 this,
154 e.getFirstIndex(),
155 e.getLastIndex(),
156 e.getValueIsAdjusting()
157 );
158 l.valueChanged(e2);
159 }
160 }
161
162 protected ChannelList
163 createChannelList() { return new ChannelList(); }
164
165 protected ChannelListModel
166 createChannelListModel() { return new ChannelListModel(); }
167
168 @Override
169 public void
170 setSelectedChannel(JSChannel channel) {
171 chnList.setSelectedComponent(channel, true);
172 }
173
174 /**
175 * Adds new channel to this channels pane.
176 * @param channelModel The sampler channel model to be used by the new channel.
177 */
178 @Override
179 public void
180 addChannel(SamplerChannelModel channelModel) {
181 JSChannel channel = createChannel(channelModel);
182 listModel.add(channel);
183 chnList.setSelectedComponent(channel, true);
184 scrollToBottom();
185
186 firePropertyChange("channelAdded", null, channelModel);
187 }
188
189 protected abstract JSChannel createChannel(SamplerChannelModel channelModel);
190
191 /**
192 * Adds the specified channels to this channels pane.
193 * @param chns The channels to be added.
194 */
195 @Override
196 public void
197 addChannels(JSChannel[] chns) {
198 if(chns == null || chns.length == 0) return;
199
200 for(JSChannel c : chns) listModel.add(c);
201 chnList.setSelectionInterval (
202 listModel.getSize() - chns.length, listModel.getSize() - 1
203 );
204
205 chnList.ensureIndexIsVisible(listModel.getSize() - 1);
206
207 firePropertyChange("channelsAdded", null, chns);
208 }
209
210 /**
211 * Removes the specified channel from this channels pane.
212 * This method is invoked when a sampler channel is removed in the back-end.
213 * @param chn The channel to be removed from this channels pane.
214 */
215 @Override
216 public void
217 removeChannel(JSChannel chn) {
218 listModel.remove(chn);
219
220 firePropertyChange("channelRemoved", null, chn);
221 }
222
223 /**
224 * Gets the first channel in this channels pane.
225 * @return The first channel in this channels pane or <code>null</code> if
226 * the channels pane is empty.
227 */
228 @Override
229 public JSChannel
230 getFirstChannel() { return listModel.size() == 0 ? null : listModel.get(0); }
231
232 /**
233 * Gets the last channel in this channels pane.
234 * @return The last channel in this channels pane or <code>null</code> if
235 * the channels pane is empty.
236 */
237 @Override
238 public JSChannel
239 getLastChannel() {
240 return listModel.size() == 0 ? null : listModel.get(listModel.size() - 1);
241 }
242
243 /**
244 * Gets the channel at the specified index.
245 * @return The channel at the specified index.
246 * @throws ArrayIndexOutOfBoundsException If the index is out of range.
247 */
248 @Override
249 public JSChannel
250 getChannel(int idx) { return listModel.get(idx); }
251
252 /**
253 * Gets an array with all channels in this channels pane.
254 * @return An array with all channels in this channels pane.
255 */
256 @Override
257 public JSChannel[]
258 getChannels() {
259 JSChannel[] chns = new JSChannel[listModel.size()];
260 for(int i = 0; i < listModel.size(); i++) chns[i] = listModel.get(i);
261 return chns;
262 }
263
264 /**
265 * Gets the number of channels in this channels pane.
266 * @return The number of channels in this channels pane.
267 */
268 @Override
269 public int
270 getChannelCount() { return listModel.size(); }
271
272 /**
273 * Determines whether there is at least one selected channel.
274 * @return <code>true</code> if there is at least one selected channel,
275 * <code>false</code> otherwise.
276 */
277 @Override
278 public boolean
279 hasSelectedChannel() { return !chnList.isSelectionEmpty(); }
280
281 /**
282 * Gets the number of the selected channels.
283 * @return The number of the selected channels.
284 */
285 @Override
286 public int
287 getSelectedChannelCount() { return chnList.getSelectedIndices().length; }
288
289 /**
290 * Gets an array with all selected channels.
291 * The channels are sorted in increasing index order.
292 * @return The selected channels or an empty array if nothing is selected.
293 */
294 @Override
295 public JSChannel[]
296 getSelectedChannels() {
297 Component[] cS = chnList.getSelectedComponents();
298 JSChannel[] chns = new JSChannel[cS.length];
299 for(int i = 0; i < cS.length; i++) chns[i] = (JSChannel)cS[i];
300 return chns;
301 }
302
303 /**
304 * Removes all selected channels in this channels pane.
305 * Notice that this method does not remove any channels in the back-end.
306 * It is invoked after the channels are already removed in the back-end.
307 * @return The number of removed channels.
308 */
309 @Override
310 public int
311 removeSelectedChannels() {
312 int[] l = chnList.getSelectedIndices();
313 ComponentListModel model = chnList.getModel();
314
315 for(;;) {
316 int i = chnList.getMinSelectionIndex();
317 if(i == -1) break;
318 model.remove(i);
319 }
320
321 firePropertyChange("channelsRemoved", null, null);
322
323 return l.length;
324 }
325
326 /** Selects all channels. */
327 @Override
328 public void
329 selectAll() { chnList.selectAll(); }
330
331 /** Deselects all selected channels. */
332 @Override
333 public void
334 clearSelection() { chnList.clearSelection(); }
335
336 /**
337 * Determines whether the channel list UI should be automatically updated
338 * when channel is added/removed. The default value is <code>true</code>.
339 * @see updateChannelListUI
340 */
341 @Override
342 public boolean
343 getAutoUpdate() { return chnList.getAutoUpdate(); }
344
345 /**
346 * Determines whether the channel list UI should be automatically updated
347 * when channel is added/removed.
348 * @see updateChannelListUI
349 */
350 @Override
351 public void
352 setAutoUpdate(boolean b) { chnList.setAutoUpdate(b); }
353
354 /**
355 * Updates the channel list UI.
356 * @see setAutoUpdate
357 */
358 @Override
359 public void
360 updateChannelListUI() { chnList.updateList(); }
361
362
363 @Override
364 public void
365 moveSelectedChannelsOnTop() {
366 JSChannel[] chns = getSelectedChannels();
367
368 if(chns.length == 0) {
369 CC.getLogger().info("Can't move channel(s) at the beginning");
370 return;
371 }
372
373 for(int i = chns.length - 1; i >= 0; i--) {
374 listModel.remove(chns[i]);
375 listModel.insert(chns[i], 0);
376 }
377
378 chnList.setSelectionInterval(0, chns.length - 1);
379 chnList.ensureIndexIsVisible(0);
380
381 firePropertyChange("channelsPositionChanged", null, chns);
382 }
383
384 @Override
385 public void
386 moveSelectedChannelsUp() {
387 JSChannel[] chns = getSelectedChannels();
388
389 if(chns.length == 0 || chns[0] == getFirstChannel()) {
390 CC.getLogger().info("Can't move channel(s) up");
391 return;
392 }
393
394 for(int i = 0; i < chns.length; i++) listModel.moveUp(chns[i]);
395
396 int[] si = chnList.getSelectedIndices();
397
398 for(int i = 0; i < si.length; i++) si[i] -= 1;
399
400 chnList.setSelectedIndices(si);
401 chnList.ensureIndexIsVisible(si[0]);
402
403 firePropertyChange("channelsPositionChanged", null, chns);
404 }
405
406 @Override
407 public void
408 moveSelectedChannelsDown() {
409 JSChannel[] chns = getSelectedChannels();
410
411 if(chns.length == 0 || chns[chns.length - 1] == getLastChannel()) {
412 CC.getLogger().info("Can't move channel(s) down");
413 return;
414 }
415
416 for(int i = chns.length - 1; i >= 0; i--) listModel.moveDown(chns[i]);
417
418 int[] si = chnList.getSelectedIndices();
419 for(int i = 0; i < si.length; i++) si[i] += 1;
420 chnList.setSelectedIndices(si);
421 chnList.ensureIndexIsVisible(si[si.length - 1]);
422
423 firePropertyChange("channelsPositionChanged", null, chns);
424 }
425
426 @Override
427 public void
428 moveSelectedChannelsAtBottom() {
429 JSChannel[] chns = getSelectedChannels();
430
431 if(chns.length == 0) {
432 CC.getLogger().info("Can't move channel(s) at the end");
433 return;
434 }
435
436 for(int i = 0; i < chns.length; i++) {
437 listModel.remove(chns[i]);
438 listModel.add(chns[i]);
439 }
440
441 chnList.setSelectionInterval (
442 listModel.getSize() - chns.length, listModel.getSize() - 1
443 );
444 chnList.ensureIndexIsVisible(listModel.getSize() - 1);
445
446 firePropertyChange("channelsPositionChanged", null, chns);
447 }
448
449 @Override
450 public void
451 processChannelSelection(JSChannel c, boolean controlDown, boolean shiftDown) {
452 if(c.isSelected() && !controlDown && !shiftDown) return;
453 chnList.getUI().processSelectionEvent(c, controlDown, shiftDown);
454 }
455
456 private void
457 scrollToBottom() {
458 int h = scrollPane.getViewport().getView().getHeight();
459 scrollPane.getViewport().scrollRectToVisible(new Rectangle(0, h - 2, 1, 1));
460 }
461 }

  ViewVC Help
Powered by ViewVC