Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: jmx/util/ReadFilesJButton.java


1   /*
2    * ReadFilesJButton.java 0.1.1.0 20th February 2001
3    *
4    * Copyright (C) 2000 Adam Kirby
5    *
6    * This program is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU General Public License
8    * as published by the Free Software Foundation; either version 2
9    * of the License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
14   *
15   * See the GNU General Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, write to the Free Software
19   * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20   */
21  
22  package jmx.util;
23  
24  import java.awt.Component;
25  import java.awt.event.ActionListener;
26  import java.awt.event.ActionEvent;
27  import java.io.File;
28  import javax.swing.JButton;
29  import javax.swing.JFileChooser;
30  
31  import jm.music.data.Score;
32  
33  /**
34   * A button which allows user to select MIDI and/or jMusic files to import.
35   *
36   * <P>After each successful import of a Score, any registered ReadListeners
37   * are notified and can update and use the score read.  The listeners are
38   * guaranteed to be notified in a LILO (Last In Last Out) order.  As an example,
39   * if you wanted a Score quantised and then analysed, you would the quantising
40   * ReadListener first, then the analysing one. 
41   *
42   * @author Adam Kirby
43   * @version 1.0,Sun Feb 25 18:35:35  2001
44   *
45   * @see ReadListener
46   */
47  public class ReadFilesJButton extends JButton {
48  
49      /**
50       * Constant defining the state of a ReadFileJButton that reads in a
51       * single jm or midi file.
52       */
53      public static final ReadFilesMode SINGLE_FILE_MODE =
54              new ReadFilesMode("Single File");
55  
56      /**
57       * Constant defining the state of a ReadFileJButton that reads in a
58       * selection of jm and/or midi files.
59       */
60      public static final ReadFilesMode MULTIPLE_FILES_MODE =
61              new ReadFilesMode("Multiple Files");
62  
63      /**
64       * Constant defining the state of a ReadFileJButton that reads in a
65       * folder of jm and/or midi files.
66       */
67      public static final ReadFilesMode FOLDER_MODE =
68              new ReadFilesMode("Folder");
69  
70      /**
71       * Class defining the states of a ReadFilesJButton
72       *
73       * @see {@link ReadFilesJButton#setMode
74       */
75      private static class ReadFilesMode {
76          /**
77           * Unique identifier for instances of this class.
78           */
79          private final String name;
80  
81          /**
82           * This constructor has the private access modifier.  Instances of this
83           * class can only be accessed through the constants defined in this
84           * class.  This ensures that no modes, other than the ones defined here,
85           * can be created.
86           *
87           * @param name  Unique identifier for the instance
88           */
89          private ReadFilesMode(String name) {
90              this.name = name;
91          }
92      }
93  
94      /** The current import mode of this button */
95      private ReadFilesMode mode;
96  
97      /** List of ReadListener's associated with this button */
98      private ReadListenerLinkedList readListenerList;
99  
100     /**
101      * JFileChooser that generates the dialogs for selecting the music files
102      * to import
103      */
104     private JFileChooser chooser = new JFileChooser();
105 
106     /**
107      * Parent component for this button.  Control to this component will be
108      * suspended when file chooser dialogs and error dialogs are displayed.
109      */
110     private Component owner;
111 
112     /**
113      * Constructs a JButton for reading in MIDI or jMusic files.  Uses the
114      * default mode of {@link #MULTIPLE_FILES_MODE} which allows
115      * for a selection of files to be imported
116      *
117      * @param owner Component which is the owner of this button.  Access to this
118      *              Component will be suspended when the user is selecting a 
119      *              music file and when error messages are displayed.
120      */
121     public ReadFilesJButton(final Component owner) {
122         this(owner, MULTIPLE_FILES_MODE);
123     }
124 
125     /**
126      * Constructs a JButton for reading in music files using the specified mode
127      *
128      * @param owner     Component which is the owner of this button.  Access to
129      *                  this Component will be suspended when the user is
130      *                  selecting a music file and when error messages are
131      *                  displayed.
132      * @param readMode  ReadFilesMode specified the file/folder selection mode
133      */
134     public ReadFilesJButton(final Component owner,
135                             final ReadFilesMode mode) {
136         super();
137         this.owner = owner;
138         setMode(mode);
139         addActionListener(new ActionListener() {
140             public void actionPerformed(ActionEvent evt) {
141                 Runnable processRun = new Runnable() {
142                     public void run() {
143                         readListenerList.startedReading();
144 
145                         int chooserReturnValue = chooser.showOpenDialog(owner);
146                         if (chooserReturnValue != chooser.APPROVE_OPTION) {
147                             return;
148                         }
149         
150                         if (mode == SINGLE_FILE_MODE) {
151                             processFile(chooser.getSelectedFile());
152                         } else if (mode == MULTIPLE_FILES_MODE) {
153                             processFiles(chooser.getSelectedFiles());
154                         } else if (mode == FOLDER_MODE) {
155                             File file = chooser.getSelectedFile();
156                             if (file.isDirectory()) {
157                                 /*
158                                  * When jMusic supports only JDK1.2 and later,
159                                  * the following code can be simplified to:
160                                  *
161                                  * processFiles(file.listFiles(
162                                  *         new ReadFilenameFilter()));
163                                  */
164                                 String[] filenames = file.list(
165                                         new ReadFilenameFilter());
166                                 for (int i = 0; i < filenames.length; i++) {
167                                     processFile(new File(file.getAbsolutePath(),
168                                                          filenames[i]));
169                                 }
170                             }
171                         }
172                              
173                         if (readListenerList != null) {
174                             readListenerList.finishedReading();
175                         }
176                     }
177                 };
178                 Thread processThread = new Thread(processRun, "processThread");
179                 processThread.start();
180                 
181             }
182         });
183     }
184 
185     /**
186      * Attempts to convert the <CODE>file</CODE> to a score, and if successful
187      * notifies any registered {@link ReadListener ReadListeners}
188      *
189      * <P>The task of file reading and conversion is delegated to {@link
190      * Read.midiOrJmWithSwingMessaging(File, Component)}.
191      *
192      * @param file  File to convert to a score
193      *
194      * @see #processFiles
195      */
196     private void processFile(final File file) {
197         Score score = Read.midiOrJmWithSwingMessaging(file, owner);
198         if (score == null) {
199             return;
200         }
201         if (readListenerList != null) {
202             score = readListenerList.scoreRead(score);
203         }
204     }
205 
206     /**
207      * Attempts to convert the series of <CODE>files</CODE> to scores, notifying
208      * any registered {@link ReadListener ReadListeners} after successful
209      * imports.
210      *
211      * @param file  File to convert to a score
212      *
213      * @see #processFile
214      */
215     private void processFiles(final File[] files) {
216         if (files == null) {
217             return;
218         }
219         for (int i = 0; i < files.length; i++) {
220             processFile(files[i]);
221         }
222     }
223 
224     /**
225      * Sets the mode of this button to <CODE>mode</CODE>
226      *
227      * @param mode  ReadFilesMode for this button
228      *
229      * @see #getMode
230      */
231     public void setMode(ReadFilesMode mode) {
232         this.mode = mode;
233         if (mode == SINGLE_FILE_MODE) {
234             setText("Read File");
235             chooser.setDialogTitle("Select a MIDI or jMusic file to import");
236             chooser.setMultiSelectionEnabled(false);
237             chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
238         } else if (mode == MULTIPLE_FILES_MODE) {
239             setText("Read Files");
240             chooser.setDialogTitle("Select MIDI and/or jMusic files to import");
241             chooser.setMultiSelectionEnabled(true);
242             chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
243         } else if (mode == FOLDER_MODE) {
244             setText("Read Folder");
245             chooser.setDialogTitle("Select a folder of MIDI or jMusic files to "
246                                    + "import");
247             chooser.setMultiSelectionEnabled(false);
248             chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
249         }
250     }
251 
252     /**
253      * Returns the current mode of this button
254      *
255      * @return  the current mode of this button
256      *
257      * @see #setMode
258      */
259     public ReadFilesMode getMode() {
260         return mode;
261     }
262 
263     /**
264      * Registers a ReadListener to recieve successful read notifications
265      *
266      * @param l ReadListener to add
267      *
268      * @see #removeReadListener
269      */
270     public void addReadListener(ReadListener l) {
271         if (l == null) {
272             return;
273         }
274         if (readListenerList == null) {
275             readListenerList = new ReadListenerLinkedList(l);
276         } else {
277             readListenerList.add(l);
278         }
279     }
280 
281     /**
282      * Unregisters a ReadListener from recieving read notifications
283      *
284      * @param l ReadListner to remove
285      *
286      * @see #addReadListener
287      */
288     public void removeReadListener(ReadListener l) {
289         if (readListenerList == null) {
290             return;
291         }
292         if (readListenerList.getListener() == l) {
293             readListenerList = readListenerList.getNext();
294         }
295     }
296 }