/[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 1883 - (show annotations) (download)
Sun Apr 5 09:15:35 2009 UTC (15 years ago) by iliev
File size: 14116 byte(s)
* fixed the channel order when exporting sampler configuration
* don't mute channels muted by solo channel when exporting
   sampler configuration
* don't ask whether to replace a file on Mac OS when using
  native file choosers

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) { chnPaneList.add(chnPane); }
174
175 /**
176 * Removes the specified <code>JSChannelsPane</code> from the view.
177 * Override this method to remove <code>chnPane</code> from the view,
178 * and don't forget to call <code>super.removeChannelsPane(chnPane);</code>.
179 * @param chnPane The <code>JSChannelsPane</code> to be removed.
180 * @return <code>true</code> if the specified code>JSChannelsPane</code>
181 * is actually removed from the view, <code>false</code> otherwise.
182 */
183 public boolean
184 removeChannelsPane(JSChannelsPane chnPane) { return chnPaneList.remove(chnPane); }
185
186 /**
187 * Gets the current number of <code>JSChannelsPane</code>s added to the view.
188 * @return The current number of <code>JSChannelsPane</code>s added to the view.
189 */
190 public int
191 getChannelsPaneCount() { return chnPaneList.size(); }
192
193 /**
194 * Returns the index of the specified channels pane, or -1 if
195 * the specified channels pane is not found.
196 */
197 public int
198 getChannelsPaneIndex(JSChannelsPane chnPane) {
199 return chnPaneList.indexOf(chnPane);
200 }
201
202 /**
203 * Inserts the specified <code>JSChannelsPane</code> at the specified position
204 * in the view and in the code>JSChannelsPane</code> list.
205 * Where and how this pane will be shown depends on the view/GUI implementation.
206 * Note that some GUI implementation may have only one pane containing sampler channels.
207 * @param pane The <code>JSChannelsPane</code> to be inserted.
208 * @param idx Specifies the position of the <code>JSChannelsPane</code>.
209 * @see #getChannelsPaneList
210 */
211 public abstract void insertChannelsPane(JSChannelsPane pane, int idx);
212
213 /**
214 * Gets the <code>JSChannelsPane</code> that is currently shown,
215 * or has the focus if more than one channels' panes are shown.
216 * If the GUI implementation has only one pane containing sampler channels,
217 * than this method should always return that pane (the <code>JSChannelsPane</code>
218 * with index 0).
219 * @return The selected <code>JSChannelsPane</code>.
220 */
221 public abstract JSChannelsPane getSelectedChannelsPane();
222
223 /**
224 * Gets the server address to which to connect. If the server should be
225 * manually selected, a dialog asking the user to choose a server is displayed.
226 */
227 public abstract Server getServer();
228
229 /**
230 * Gets the server address to which to connect. If the server should be
231 * manually selected, a dialog asking the user to choose a server is displayed.
232 * @param manualSelect Determines whether the server should be manually selected.
233 */
234 public abstract Server getServer(boolean manualSelect);
235
236 /**
237 * Gets the LS Console model.
238 * @return The LS Console model or <code>null</code>.
239 */
240 public LSConsoleModel
241 getLSConsoleModel() { return null; }
242
243 /**
244 * Sets the <code>JSChannelsPane</code> to be selected.
245 * Note that all registered listeners should be notified
246 * when the selection is changed.
247 * @param pane The <code>JSChannelsPane</code> to be shown.
248 * @see #fireChannelsPaneSelectionChanged
249 */
250 public abstract void setSelectedChannelsPane(JSChannelsPane pane);
251
252 private class EventHandler implements SamplerChannelListListener {
253 /**
254 * Invoked when a new sampler channel is created.
255 * @param e A <code>SamplerChannelListEvent</code>
256 * instance providing the event information.
257 */
258 @Override
259 public void
260 channelAdded(SamplerChannelListEvent e) {
261 if(e.getChannelModel() == null) return;
262 Integer id = e.getChannelModel().getChannelId();
263 if(findChannel(id) != null) {
264 CC.getLogger().log(Level.WARNING, "JSMainFrame.channelExist!", id);
265 return;
266 }
267
268 ChannelConfig config = null;
269 JSViewConfig viewConfig = CC.getViewConfig();
270 if(viewConfig != null && viewConfig.getSessionViewConfig() != null) {
271 config = viewConfig.getSessionViewConfig().pollChannelConfig();
272 }
273
274 if(config == null) {
275 getSelectedChannelsPane().addChannel(e.getChannelModel());
276 } else {
277 int i = config.channelsPanel;
278 if(i >= 0 && i < getChannelsPaneCount()) {
279 getChannelsPane(i).addChannel(e.getChannelModel(), config);
280 } else {
281 getSelectedChannelsPane().addChannel(e.getChannelModel(), config);
282 }
283 }
284 }
285
286 /**
287 * Invoked when a sampler channel is removed.
288 * @param e A <code>SamplerChannelListEvent</code>
289 * instance providing the event information.
290 */
291 @Override
292 public void
293 channelRemoved(SamplerChannelListEvent e) {
294 removeChannel(e.getChannelModel().getChannelId());
295 }
296 }
297
298 /**
299 * Searches for the first occurence of a channel with numerical ID <code>id</code>.
300 * @return The first occurence of a channel with numerical ID <code>id</code> or
301 * <code>null</code> if there is no channel with numerical ID <code>id</code>.
302 */
303 public JSChannel
304 findChannel(int id) {
305 if(id < 0) return null;
306
307 for(JSChannelsPane cp : getChannelsPaneList()) {
308 for(JSChannel c : cp.getChannels()) if(c.getChannelId() == id) return c;
309 }
310
311 return null;
312 }
313
314 /**
315 * Removes the first occurence of a channel with numerical ID <code>id</code>.
316 * This method is invoked when a sampler channel is removed in the back-end.
317 * @return The removed channel or <code>null</code>
318 * if there is no channel with numerical ID <code>id</code>.
319 */
320 public JSChannel
321 removeChannel(int id) {
322 if(id < 0) return null;
323
324 for(JSChannelsPane cp : getChannelsPaneList()) {
325 for(JSChannel c : cp.getChannels()) {
326 if(c.getChannelId() == id) {
327 cp.removeChannel(c);
328 return c;
329 }
330 }
331 }
332
333 return null;
334 }
335
336 /**
337 * Gets the zero-based position of the specified sampler channel
338 * in the channels pane, to which the channel is added.
339 * Note that the position may change when adding/removing sampler channels.
340 * @return The zero-based position of the specified sampler channel
341 * in the channels pane, or -1 if the specified channels is not found.
342 */
343 public int
344 getChannelNumber(SamplerChannelModel channel) {
345 if(channel == null) return -1;
346
347 for(int i = 0; i < getChannelsPaneCount(); i++) {
348 JSChannelsPane chnPane = getChannelsPane(i);
349 for(int j = 0; j < chnPane.getChannelCount(); j++) {
350 if(chnPane.getChannel(j).getChannelId() == channel.getChannelId()) {
351 return j;
352 }
353 }
354 }
355
356 return -1;
357 }
358
359 /**
360 * Returns a string in the format <code>channelPaneNumber/channelNumber</code>,
361 * where <code>channelPaneNumber</code> is the one-based number of the channels
362 * pane containing the specified channel and <code>channelNumber</code> is the
363 * one-based number of the channel's position in the channels pane.
364 * Note that this path may change when adding/removing channels/channels panes.
365 * @return The channels path, or <code>null</code> if the specified channels is not found.
366 */
367 public String
368 getChannelPath(SamplerChannelModel channel) {
369 if(channel == null) return null;
370
371 for(int i = 0; i < getChannelsPaneCount(); i++) {
372 JSChannelsPane chnPane = getChannelsPane(i);
373 for(int j = 0; j < chnPane.getChannelCount(); j++) {
374 if(chnPane.getChannel(j).getChannelId() == channel.getChannelId()) {
375 return (i + 1) + "." + (j + 1);
376 }
377 }
378 }
379
380 return null;
381 }
382
383 /**
384 * Gets the zero-based number of the channels pane,
385 * to which the specified sampler channel is added.
386 * Note that the can be moved from one channels pane to another.
387 * @return The zero-based index of the channels pane,
388 * to which the specified sampler channel is added, or
389 * -1 if the specified channels is not found.
390 */
391 public int
392 getChannelsPaneNumber(SamplerChannelModel channel) {
393 if(channel == null) return -1;
394
395 for(int i = 0; i < getChannelsPaneCount(); i++) {
396 JSChannelsPane chnPane = getChannelsPane(i);
397 for(int j = 0; j < chnPane.getChannelCount(); j++) {
398 if(chnPane.getChannel(j).getChannelId() == channel.getChannelId()) {
399 return i;
400 }
401 }
402 }
403
404 return -1;
405 }
406
407 /**
408 * Sends the specified script to the backend.
409 * @param script The file name of the script to run.
410 */
411 public abstract void runScript(String script);
412
413 /**
414 * Determines whether the channel list UI should be automatically updated
415 * when channel is added/removed. The default value is <code>true</code>.
416 */
417 public boolean
418 getAutoUpdateChannelListUI() { return autoUpdateChannelListUI; }
419
420 /**
421 * Determines whether the channel list UI should be automatically updated
422 * when channel is added/removed.
423 */
424 public void
425 setAutoUpdateChannelListUI(boolean b) {
426 if(b == autoUpdateChannelListUI) return;
427
428 autoUpdateChannelListUI = b;
429 for(JSChannelsPane cp : getChannelsPaneList()) {
430 cp.setAutoUpdate(b);
431 }
432 }
433
434 /**
435 * Updates the channel list UI.
436 */
437 public void
438 updateChannelListUI() {
439 for(JSChannelsPane cp : getChannelsPaneList()) {
440 cp.updateChannelListUI();
441 }
442 }
443 }

  ViewVC Help
Powered by ViewVC