View Javadoc

1   package fr.ove.openmath.mathematica;
2   
3   import javax.swing.*;
4   import javax.swing.event.*;
5   import java.awt.*;
6   import java.util.*;
7   import fr.ove.openmath.mathematica.*;
8   import fr.ove.utils.*;
9   import java.io.*;
10  import fr.inria.openmath.omapi.*;
11  import fr.inria.openmath.omapi.implementation.*;
12  import fr.ove.openmath.mathematica.omparser.PipeParserHandler;
13  
14  /***
15  * A work book.
16  * Is intended to be used to access different inner frames in a Desktop by means
17  * labelled tabs.
18  */
19  public class WorkBook extends JComponent implements InternalFrameListener, Savable {
20      /***
21      * The tabbed pane to acces the different elements
22      */
23      private JTabbedPane tabbedPane;
24      
25      /***
26      * The Desktop.
27      */
28      private Desktop desktop;
29      
30      /***
31      * Indicates if the instance need to be saved.
32      */
33      private boolean needed = true;
34      
35      /***
36       * The list of listeners of the instance.
37       */
38      private EventListenerList listeners = new EventListenerList();
39      
40      /***
41       * Only one ChangeEvent is needed per WorkBook instance since the
42       * event's only (read-only) state is the source property.  The source
43       * of events generated here is always "this".
44       */
45      private transient ChangeEvent changeEvent = null;
46      
47      /***
48      * A connection factory.
49      */
50      ConnectionFactory factory;
51      
52      /***
53      * A file chooser
54      */
55      private WorkSheetFileChooser chooser;
56      
57      /***
58      * A status bar
59      */
60      private StatusBar statusBar;
61      
62      /***
63      * The Constructor.
64      */
65      public WorkBook(ConnectionFactory factory, StatusBar statusBar) {
66          setLayout(new BorderLayout());
67          desktop = new Desktop();
68          
69          chooser = new WorkSheetFileChooser(this);
70          this.factory = factory;
71          this.statusBar = statusBar;
72          addChangeListener(statusBar);
73          
74          add(desktop, BorderLayout.CENTER);
75          
76          tabbedPane = new JTabbedPane(JTabbedPane.BOTTOM);
77          tabbedPane.addChangeListener(
78              new ChangeListener() {
79                  public void stateChanged(ChangeEvent ce) {
80                      JDesktopPaneWrapper comp = (JDesktopPaneWrapper) tabbedPane.getSelectedComponent();
81                      if (comp != null) {
82                          if (comp.getComponentCount() == 0)
83                              comp.setJDesktopPane();
84                          
85                          int index = tabbedPane.getSelectedIndex();
86                          String title = tabbedPane.getTitleAt(index);
87                          desktop.setSelected(title);
88                      }
89                  }
90              }
91          );
92      }
93      
94      /***
95      * Adds a new tab (i.e. a new inner frame into the Desktop) to the WorkBook.
96      */
97      public void addTab() {
98          if (getComponent(0) == desktop) {
99              remove(desktop);
100             add(tabbedPane, BorderLayout.CENTER);
101         }
102         
103         JInternalFrame jif = desktop.addNewInternalFrame(new OMWorkSheet(this, factory));
104         jif.addInternalFrameListener(this);
105         jif.addVetoableChangeListener(chooser);
106         tabbedPane.addTab(jif.getTitle(), new JDesktopPaneWrapper(desktop));
107         tabbedPane.setSelectedIndex(tabbedPane.getTabCount() - 1);
108         fireStateChanged();
109         validate();
110     }
111     
112     /***
113     * Adds a new palette to the desktop.
114     * @param paletteIdentifier the palette identfier.
115     * @param contentPan the palette (i.e. the content pane for the inner frame opened in the desktop)
116     */
117     public void addPalette(String paletteIdentifier, Container contentPane) {
118         desktop.addNewPaletteContentPane(paletteIdentifier, contentPane);
119     }
120     /***
121     * Shows the palette with the specified name identfier.
122     * @param identifier the palette identifier.
123     */
124     public void showPalette(String identifier) {
125         desktop.showPalette(identifier);
126     }
127     
128     /***
129     * Removes the tab with the specified name.
130     * @param name the name of the tab.
131     */
132     public void removeTab(String name) {
133         JInternalFrame jif = desktop.removeInternalFrame(name);
134         if (jif != null) {
135             jif.removeInternalFrameListener(this);
136             int index = tabbedPane.indexOfTab(name);
137             tabbedPane.removeTabAt(index);
138             fireStateChanged();
139         }
140     }
141     
142     /***
143     * Returns the active inner frame in the work book.
144     */
145     public JInternalFrame getActiveInternalFrame() {
146         return desktop.getActiveInternalFrame();
147     }
148     
149     /***
150     * Returns the number of tab (i.e. inner frames) in the instance.
151     */
152     public int getTabCount() {
153         return tabbedPane.getTabCount();
154     }
155     /***
156      * Adds a ChangeListener to the instance.
157      * @param l the ChangeListener to add
158      * @see #fireStateChanged
159      * @see #removeChangeListener
160      */
161     public void addChangeListener(ChangeListener l) {
162         listeners.add(ChangeListener.class, l);
163     }
164     
165     /***
166     * Cascade the frame in the desktop.
167     */
168     public void cascade() {
169         desktop.cascade();
170     }
171     
172     /***
173     * Closes all the frames in the desktop.
174     */
175     public void closeAll() {
176         desktop.closeAll();
177     }
178     
179     /***
180      * Removes a ChangeListener from the instance.
181      * @param l the ChangeListener to remove
182      * @see #fireStateChanged
183      * @see #addChangeListener
184      */
185     public void removeChangeListener(ChangeListener l) {
186         listeners.remove(ChangeListener.class, l);
187     }
188     
189     /***
190      * Send a ChangeEvent, whose source is this tabbedpane, to
191      * each listener.  This method method is called each time 
192      * a ChangeEvent is received from the model.
193      * @see #addChangeListener
194      * @see EventListenerList
195      */
196     protected void fireStateChanged() {
197         // Guaranteed to return a non-null array
198         Object[] tabListeners = listeners.getListenerList();
199         // Process the listeners last to first, notifying
200         // those that are interested in this event
201         for (int i = tabListeners.length - 2; i >= 0; i -= 2) {
202             if (tabListeners[i] == ChangeListener.class) {
203                 // Lazily create the event:
204                 if (changeEvent == null)
205                     changeEvent = new ChangeEvent(this);
206                     
207                 ((ChangeListener) tabListeners[i+1]).stateChanged(changeEvent);
208             }          
209         }
210     }
211     
212     /***
213     * Returns the status bar.
214     */
215     public StatusBar getStatusBar() {
216         return statusBar;
217     }
218     
219     /***
220     * Returns the icon with the specified image filename.
221     * @param filename the image filename
222     */
223     private ImageIcon getIcon(String filename) {
224         ImageIcon icon = null;
225         
226         java.net.URL iconURL = ClassLoader.getSystemResource(filename);
227         if (iconURL != null)
228             icon = new ImageIcon(iconURL);
229             
230         return icon;
231     }
232     
233     
234     
235     // ######  InternalFrameListener interface implementation
236     
237     public void internalFrameActivated(InternalFrameEvent e) {
238         JInternalFrame src = (JInternalFrame) e.getSource();
239         int index = tabbedPane.indexOfTab(src.getTitle());
240         tabbedPane.setSelectedIndex(index);
241         fireStateChanged();
242     }
243     
244     public void internalFrameClosed(InternalFrameEvent e) {
245         JInternalFrame src = (JInternalFrame) e.getSource();
246         String name = src.getTitle();
247         
248         removeTab(name);
249         JDesktopPaneWrapper wrapper = (JDesktopPaneWrapper) tabbedPane.getSelectedComponent();
250         if (wrapper != null) {
251             wrapper.setJDesktopPane();
252             int index = tabbedPane.getSelectedIndex();
253             name = tabbedPane.getTitleAt(index);
254             desktop.setSelected(name);
255         }
256         else {
257             // Possible that src was the last inner frame.
258             // If so, remove the tabbed pane and put the desktop itself.
259             //JInternalFrame[] frames = desktop.getAllFramesInLayer(JLayeredPane.DEFAULT_LAYER.intValue());
260             //if (frames.length == 1) {
261                 remove(tabbedPane);
262                 add(desktop, BorderLayout.CENTER);
263             //}
264         }
265         fireStateChanged();
266     }
267 
268     public void internalFrameClosing(InternalFrameEvent e) {
269     }
270 
271     public void internalFrameDeactivated(InternalFrameEvent e) {
272         fireStateChanged();
273     }
274 
275     public void internalFrameDeiconified(InternalFrameEvent e) {
276     }
277 
278     public void internalFrameIconified(InternalFrameEvent e) {
279     }
280 
281     public void internalFrameOpened(InternalFrameEvent e) {
282     }
283     
284     // ### Savable interface implementation
285         
286     /***
287     * Saves the instance.
288     * @returns the result of the save action. Should be <CODE>null</CODE> if nothing
289     * is expected after the save operation. The saved object otherwise.
290     * The instance is saved as the concatenation of all the OpenMath object request contained.
291     */
292     public Object save() {
293         MyJInternalFrame jif = (MyJInternalFrame) desktop.getActiveInternalFrame();
294         if (jif.isSaveNeeded()) {
295             File file;
296             String title = jif.getTitle();
297             
298             statusBar.setStatus("Save " + title,
299                                 getIcon("fr/ove/openmath/mathematica/images/save.gif")
300             );
301             
302             
303             if (title.startsWith("Untitled")) {
304                 int state = chooser.showSave();
305                 file = chooser.getSelectedFile();
306                 if ((file != null) && (state == JFileChooser.APPROVE_OPTION)) {
307                     statusBar.setStatus("Please wait while saving the work sheet...",
308                                         getIcon("fr/ove/openmath/mathematica/images/sablier.gif")
309                     );
310                     
311                     jif.save(file);
312                     setSaveNeeded(false);
313                     
314                     try {
315                         desktop.rename(title, file.getName());
316                     }
317                     catch (Exception e) {
318                     }
319                     
320                     tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), file.getName());
321                     
322                     statusBar.setStatus("", getIcon("fr/ove/openmath/mathematica/images/worksheet.gif"));
323                 }
324             }
325             else {
326                 statusBar.setStatus("Please wait while saving the work sheet...",
327                                     getIcon("fr/ove/openmath/mathematica/images/sablier.gif")
328                 );
329                     
330                 file = new File(title);
331                 jif.save(file);
332                 setSaveNeeded(false);
333                 
334                 statusBar.setStatus("", getIcon("fr/ove/openmath/mathematica/images/worksheet.gif"));
335             }
336         }
337         
338         return null;
339     }
340     
341     /***
342     * Saves the instance into the specified file.
343     * @returns the result of the save action. Should be <CODE>null</CODE> if nothing
344     * is expected after the save operation. The saved object otherwise.
345     */
346     public Object save(File file) {
347         return null;
348     }
349         
350     /***
351     * Saves the instance with the specified name.
352     * @param name the specified name.
353     * @returns the result of the save action. Should be <CODE>null</CODE> if nothing
354     * is expected after the save operation. The saved object otherwise.
355     */
356     public Object saveAs(String name) {
357         return null;
358     }
359         
360     /***
361     * Checks if the instance need to be saved.
362     * @return <CODE>true</CODE> if the instance need to be saved. <CODE>false</CODE> otherwise.
363     */
364     public boolean isSaveNeeded() {
365         return needed;
366     }
367         
368     /***
369     * Sets if the instance need to be saved.
370     * @param needed <CODE>true</CODE> if the instance need to be saved. <CODE>false</CODE> otherwise.
371     */
372     public void setSaveNeeded(boolean needed) {
373         this.needed = needed;
374     }
375     
376     /***
377     * Opens a file.
378     */
379     public void open() {
380         statusBar.setStatus("Select a work sheet to open...",
381                             getIcon("fr/ove/openmath/mathematica/images/open.gif")
382         );
383         
384         int state = chooser.showOpen();
385         File file = chooser.getSelectedFile();
386         if ((file != null) && (state == JFileChooser.APPROVE_OPTION)) {
387             statusBar.setStatus("Please wait while opening the work sheet...",
388                                 getIcon("fr/ove/openmath/mathematica/images/sablier.gif")
389             );
390             
391             PipeParserHandler handler = new PipeParserHandler();
392             XMLParser parser = new XMLParser(handler);
393             
394             Vector elems = new Vector(); 
395             try {
396                 FileInputStream fis = new FileInputStream(file);
397                 try {
398                     String parsed;
399                     while (fis.available() != 0) {
400                         parser.initParse(fis);
401                         parser.parseObject(fis);
402                         
403                         parsed = handler.getOmObjectParsed();
404                         
405                         if ((parsed != null) && (!parsed.equals("")))
406                             elems.addElement(parsed);
407                     }
408                     fis.close();
409                     
410                     addTab();
411                     MyJInternalFrame jif = (MyJInternalFrame) desktop.getActiveInternalFrame();
412                     try {
413                         desktop.rename(jif.getTitle(), file.getName());
414                     }
415                     catch (Exception e) {
416                     }
417                     tabbedPane.setTitleAt(tabbedPane.getSelectedIndex(), file.getName());
418 
419                     if (elems.size() != 0) {
420                         OMWorkSheet worksheet = (OMWorkSheet) jif.getContentPane();
421                         boolean addNewElement = false;
422                         for (Enumeration e = elems.elements(); e.hasMoreElements(); ) {
423                             if (addNewElement)
424                                 worksheet.addNewElement();
425                             worksheet.getCurrentElement().setOpenMathRequest((String) e.nextElement());
426                             addNewElement = true;
427                         }
428                         jif.setSaveNeeded(false);
429                         worksheet.setSaveNeeded(false);
430                     }
431                     
432                     statusBar.setStatus("", getIcon("fr/ove/openmath/mathematica/images/worksheet.gif"));
433                     
434                 }
435                 catch (IOException ioe) {
436                     statusBar.setStatus("Something wrong occurs while reading the worksheet.", 
437                                         getIcon("fr/ove/openmath/mathematica/images/oups.gif"));
438                 }
439             }
440             catch (FileNotFoundException fnfe) {
441                 statusBar.setStatus("Couldn't find the specified the worksheet.", 
442                                     getIcon("fr/ove/openmath/mathematica/images/oups.gif"));
443             }
444         }
445         else {
446             if (getTabCount() != 0)
447                 statusBar.setStatus("", getIcon("fr/ove/openmath/mathematica/images/worksheet.gif"));
448             else
449                 statusBar.clear();
450         }
451     }
452 }