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

Contents of /jsampler/trunk/src/org/jsampler/view/JSMainFrame.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: 14309 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;
24
25 import java.awt.Dialog;
26 import java.awt.Frame;
27
28 import java.awt.event.ActionEvent;
29 import java.awt.event.KeyEvent;
30 import java.awt.event.WindowAdapter;
31 import java.awt.event.WindowEvent;
32
33 import java.util.Vector;
34 import java.util.logging.Level;
35
36 import javax.swing.AbstractAction;
37 import javax.swing.JComponent;
38 import javax.swing.JFrame;
39 import javax.swing.KeyStroke;
40
41 import javax.swing.event.ListSelectionEvent;
42 import javax.swing.event.ListSelectionListener;
43
44 import org.jsampler.CC;
45 import org.jsampler.JSampler;
46 import org.jsampler.LSConsoleModel;
47 import org.jsampler.SamplerChannelModel;
48 import org.jsampler.Server;
49
50 import org.jsampler.event.SamplerChannelListEvent;
51 import org.jsampler.event.SamplerChannelListListener;
52
53 import org.jsampler.view.SessionViewConfig.ChannelConfig;
54
55
56 /**
57 * Defines the skeleton of a JSampler's main frame.
58 * @author Grigor Iliev
59 */
60 public abstract class JSMainFrame extends JFrame {
61 private final Vector<JSChannelsPane> chnPaneList = new Vector<JSChannelsPane>();
62 private boolean autoUpdateChannelListUI = true;
63
64 /** Creates a new instance of <code>JSMainFrame</code>. */
65 public
66 JSMainFrame() {
67 super(JSampler.NAME + ' ' + JSampler.VERSION);
68
69 setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
70 addWindowListener(new WindowAdapter() {
71 public void
72 windowClosing(WindowEvent we) { onWindowClose(); }
73 });
74
75 CC.getSamplerModel().addSamplerChannelListListener(new EventHandler());
76
77 getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put (
78 KeyStroke.getKeyStroke(KeyEvent.VK_G, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK),
79 "RunGarbageCollector"
80 );
81
82 getRootPane().getActionMap().put ("RunGarbageCollector", new AbstractAction() {
83 public void
84 actionPerformed(ActionEvent e) {
85 System.gc();
86 }
87 });
88 }
89
90 /**
91 * Invoked when this window is about to close.
92 * Don't forget to call <code>super.onWindowClose()</code> at the end,
93 * when override this method.
94 */
95 public void
96 onWindowClose() {
97 CC.cleanExit();
98 }
99
100 /**
101 * Invoked on startup when no JSampler home directory is specified
102 * or the specified JSampler home directory doesn't exist.
103 * This method should ask the user to specify a JSampler
104 * home directory and then set the specified JSampler home directory using
105 * {@link org.jsampler.CC#setJSamplerHome} method.
106 * @see org.jsampler.CC#getJSamplerHome
107 * @see org.jsampler.CC#setJSamplerHome
108 */
109 public abstract void installJSamplerHome();
110
111 /**
112 * Shows a detailed error information about the specified exception.
113 */
114 public abstract void showDetailedErrorMessage(Frame owner, String err, String details);
115
116 /**
117 * Shows a detailed error information about the specified exception.
118 */
119 public abstract void showDetailedErrorMessage(Dialog owner, String err, String details);
120
121 public abstract void handleConnectionFailure();
122
123 protected Vector<ListSelectionListener> channelsPaneListeners =
124 new Vector<ListSelectionListener>();
125
126 /**
127 * Registers the specified listener for receiving event messages.
128 * @param l The <code>ListSelectionListener</code> to register.
129 */
130 public void
131 addChannelsPaneSelectionListener(ListSelectionListener l) {
132 channelsPaneListeners.add(l);
133 }
134
135 /**
136 * Removes the specified listener.
137 * @param l The <code>ListSelectionListener</code> to remove.
138 */
139 public void
140 removeChannelsPaneSelectionListener(ListSelectionListener l) {
141 channelsPaneListeners.remove(l);
142 }
143
144 protected void
145 fireChannelsPaneSelectionChanged() {
146 int i = getChannelsPaneIndex(getSelectedChannelsPane());
147 ListSelectionEvent e = new ListSelectionEvent(this, i, i, false);
148 for(ListSelectionListener l : channelsPaneListeners) l.valueChanged(e);
149 }
150
151 /**
152 * Returns a list containing all <code>JSChannelsPane</code>s added to the view.
153 * @return A list containing all <code>JSChannelsPane</code>s added to the view.
154 * @see #addChannelsPane
155 * @see #removeChannelsPane
156 */
157 public Vector<JSChannelsPane>
158 getChannelsPaneList() { return chnPaneList; }
159
160 /**
161 * Return the <code>JSChannelsPane</code> at the specified position.
162 * @param idx The position of the <code>JSChannelsPane</code> to be returned.
163 * @return The <code>JSChannelsPane</code> at the specified position.
164 */
165 public JSChannelsPane
166 getChannelsPane(int idx) { return chnPaneList.get(idx); }
167
168 /**
169 * Adds the specified <code>JSChannelsPane</code> to the view.
170 * @param chnPane The <code>JSChannelsPane</code> to be added.
171 */
172 public void
173 addChannelsPane(JSChannelsPane chnPane) {
174 chnPaneList.add(chnPane);
175 firePropertyChange("channelLaneAdded", null, chnPane);
176 }
177
178 /**
179 * Removes the specified <code>JSChannelsPane</code> from the view.
180 * Override this method to remove <code>chnPane</code> from the view,
181 * and don't forget to call <code>super.removeChannelsPane(chnPane);</code>.
182 * @param chnPane The <code>JSChannelsPane</code> to be removed.
183 * @return <code>true</code> if the specified code>JSChannelsPane</code>
184 * is actually removed from the view, <code>false</code> otherwise.
185 */
186 public boolean
187 removeChannelsPane(JSChannelsPane chnPane) {
188 boolean b = chnPaneList.remove(chnPane);
189 firePropertyChange("channelLaneRemoved", null, chnPane);
190 return b;
191 }
192
193 /**
194 * Gets the current number of <code>JSChannelsPane</code>s added to the view.
195 * @return The current number of <code>JSChannelsPane</code>s added to the view.
196 */
197 public int
198 getChannelsPaneCount() { return chnPaneList.size(); }
199
200 /**
201 * Returns the index of the specified channels pane, or -1 if
202 * the specified channels pane is not found.
203 */
204 public int
205 getChannelsPaneIndex(JSChannelsPane chnPane) {
206 return chnPaneList.indexOf(chnPane);
207 }
208
209 /**
210 * Inserts the specified <code>JSChannelsPane</code> at the specified position
211 * in the view and in the <code>JSChannelsPane</code> list.
212 * Where and how this pane will be shown depends on the view/GUI implementation.
213 * Note that some GUI implementation may have only one pane containing sampler channels.
214 * @param pane The <code>JSChannelsPane</code> to be inserted.
215 * @param idx Specifies the position of the <code>JSChannelsPane</code>.
216 * @see #getChannelsPaneList
217 */
218 public abstract void insertChannelsPane(JSChannelsPane pane, int idx);
219
220 /**
221 * Gets the <code>JSChannelsPane</code> that is currently shown,
222 * or has the focus if more than one channels' panes are shown.
223 * If the GUI implementation has only one pane containing sampler channels,
224 * than this method should always return that pane (the <code>JSChannelsPane</code>
225 * with index 0).
226 * @return The selected <code>JSChannelsPane</code>.
227 */
228 public abstract JSChannelsPane getSelectedChannelsPane();
229
230 /**
231 * Gets the server address to which to connect. If the server should be
232 * manually selected, a dialog asking the user to choose a server is displayed.
233 */
234 public abstract Server getServer();
235
236 /**
237 * Gets the server address to which to connect. If the server should be
238 * manually selected, a dialog asking the user to choose a server is displayed.
239 * @param manualSelect Determines whether the server should be manually selected.
240 */
241 public abstract Server getServer(boolean manualSelect);
242
243 /**
244 * Gets the LS Console model.
245 * @return The LS Console model or <code>null</code>.
246 */
247 public LSConsoleModel
248 getLSConsoleModel() { return null; }
249
250 /**
251 * Sets the <code>JSChannelsPane</code> to be selected.
252 * Note that all registered listeners should be notified
253 * when the selection is changed.
254 * @param pane The <code>JSChannelsPane</code> to be shown.
255 * @see #fireChannelsPaneSelectionChanged
256 */
257 public abstract void setSelectedChannelsPane(JSChannelsPane pane);
258
259 private class EventHandler implements SamplerChannelListListener {
260 /**
261 * Invoked when a new sampler channel is created.
262 * @param e A <code>SamplerChannelListEvent</code>
263 * instance providing the event information.
264 */
265 @Override
266 public void
267 channelAdded(SamplerChannelListEvent e) {
268 if(e.getChannelModel() == null) return;
269 Integer id = e.getChannelModel().getChannelId();
270 if(findChannel(id) != null) {
271 CC.getLogger().log(Level.WARNING, "JSMainFrame.channelExist!", id);
272 return;
273 }
274
275 ChannelConfig config = null;
276 JSViewConfig viewConfig = CC.getViewConfig();
277 if(viewConfig != null && viewConfig.getSessionViewConfig() != null) {
278 config = viewConfig.getSessionViewConfig().pollChannelConfig();
279 }
280
281 if(config == null) {
282 getSelectedChannelsPane().addChannel(e.getChannelModel());
283 } else {
284 int i = config.channelsPanel;
285 if(i >= 0 && i < getChannelsPaneCount()) {
286 getChannelsPane(i).addChannel(e.getChannelModel(), config);
287 } else {
288 getSelectedChannelsPane().addChannel(e.getChannelModel(), config);
289 }
290 }
291 }
292
293 /**
294 * Invoked when a sampler channel is removed.
295 * @param e A <code>SamplerChannelListEvent</code>
296 * instance providing the event information.
297 */
298 @Override
299 public void
300 channelRemoved(SamplerChannelListEvent e) {
301 removeChannel(e.getChannelModel().getChannelId());
302 }
303 }
304
305 /**
306 * Searches for the first occurence of a channel with numerical ID <code>id</code>.
307 * @return The first occurence of a channel with numerical ID <code>id</code> or
308 * <code>null</code> if there is no channel with numerical ID <code>id</code>.
309 */
310 public JSChannel
311 findChannel(int id) {
312 if(id < 0) return null;
313
314 for(JSChannelsPane cp : getChannelsPaneList()) {
315 for(JSChannel c : cp.getChannels()) if(c.getChannelId() == id) return c;
316 }
317
318 return null;
319 }
320
321 /**
322 * Removes the first occurrence of a channel with numerical ID <code>id</code>.
323 * This method is invoked when a sampler channel is removed in the back-end.
324 * @return The removed channel or <code>null</code>
325 * if there is no channel with numerical ID <code>id</code>.
326 */
327 public JSChannel
328 removeChannel(int id) {
329 if(id < 0) return null;
330
331 for(JSChannelsPane cp : getChannelsPaneList()) {
332 for(JSChannel c : cp.getChannels()) {
333 if(c.getChannelId() == id) {
334 cp.removeChannel(c);
335 firePropertyChange("channelRemoved", null, c);
336 return c;
337 }
338 }
339 }
340
341 return null;
342 }
343
344 /**
345 * Gets the zero-based position of the specified sampler channel
346 * in the channels pane, to which the channel is added.
347 * Note that the position may change when adding/removing sampler channels.
348 * @return The zero-based position of the specified sampler channel
349 * in the channels pane, or -1 if the specified channels is not found.
350 */
351 public int
352 getChannelNumber(SamplerChannelModel channel) {
353 if(channel == null) return -1;
354
355 for(int i = 0; i < getChannelsPaneCount(); i++) {
356 JSChannelsPane chnPane = getChannelsPane(i);
357 for(int j = 0; j < chnPane.getChannelCount(); j++) {
358 if(chnPane.getChannel(j).getChannelId() == channel.getChannelId()) {
359 return j;
360 }
361 }
362 }
363
364 return -1;
365 }
366
367 /**
368 * Returns a string in the format <code>channelPaneNumber.channelNumber</code>,
369 * where <code>channelPaneNumber</code> is the one-based number of the channels
370 * pane containing the specified channel and <code>channelNumber</code> is the
371 * one-based number of the channel's position in the channels pane.
372 * Note that this path may change when adding/removing channels/channels panes.
373 * @return The channels path, or <code>null</code> if the specified channels is not found.
374 */
375 public String
376 getChannelPath(SamplerChannelModel channel) {
377 if(channel == null) return null;
378
379 for(int i = 0; i < getChannelsPaneCount(); i++) {
380 JSChannelsPane chnPane = getChannelsPane(i);
381 for(int j = 0; j < chnPane.getChannelCount(); j++) {
382 if(chnPane.getChannel(j).getChannelId() == channel.getChannelId()) {
383 return (i + 1) + "." + (j + 1);
384 }
385 }
386 }
387
388 return null;
389 }
390
391 /**
392 * Gets the zero-based number of the channels pane,
393 * to which the specified sampler channel is added.
394 * Note that the can be moved from one channels pane to another.
395 * @return The zero-based index of the channels pane,
396 * to which the specified sampler channel is added, or
397 * -1 if the specified channels is not found.
398 */
399 public int
400 getChannelsPaneNumber(SamplerChannelModel channel) {
401 if(channel == null) return -1;
402
403 for(int i = 0; i < getChannelsPaneCount(); i++) {
404 JSChannelsPane chnPane = getChannelsPane(i);
405 for(int j = 0; j < chnPane.getChannelCount(); j++) {
406 if(chnPane.getChannel(j).getChannelId() == channel.getChannelId()) {
407 return i;
408 }
409 }
410 }
411
412 return -1;
413 }
414
415 /**
416 * Sends the specified script to the backend.
417 * @param script The file name of the script to run.
418 */
419 public abstract void runScript(String script);
420
421 /**
422 * Determines whether the channel list UI should be automatically updated
423 * when channel is added/removed. The default value is <code>true</code>.
424 */
425 public boolean
426 getAutoUpdateChannelListUI() { return autoUpdateChannelListUI; }
427
428 /**
429 * Determines whether the channel list UI should be automatically updated
430 * when channel is added/removed.
431 */
432 public void
433 setAutoUpdateChannelListUI(boolean b) {
434 if(b == autoUpdateChannelListUI) return;
435
436 autoUpdateChannelListUI = b;
437 for(JSChannelsPane cp : getChannelsPaneList()) {
438 cp.setAutoUpdate(b);
439 }
440 }
441
442 /**
443 * Updates the channel list UI.
444 */
445 public void
446 updateChannelListUI() {
447 for(JSChannelsPane cp : getChannelsPaneList()) {
448 cp.updateChannelListUI();
449 }
450 }
451 }

  ViewVC Help
Powered by ViewVC