ensure that close widget is available for jobs that cannot be
[jalview.git] / src / jalview / gui / WebserviceInfo.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer
3  * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18  */
19 package jalview.gui;
20
21 import java.util.*;
22
23 import java.awt.*;
24 import java.awt.event.*;
25 import java.awt.image.*;
26 import javax.swing.*;
27
28 import jalview.jbgui.*;
29
30
31 /**
32  * Base class for web service client thread and gui
33  *
34  * @author $author$
35  * @version $Revision$
36  */
37 public class WebserviceInfo extends GWebserviceInfo
38 {
39
40     /** Job is Queued */
41     public static final int STATE_QUEUING = 0;
42
43     /** Job is Running */
44     public static final int STATE_RUNNING = 1;
45
46     /** Job has finished with no errors */
47     public static final int STATE_STOPPED_OK = 2;
48
49     /** Job has been cancelled with no errors */
50     public static final int STATE_CANCELLED_OK = 3;
51
52     /** job has stopped because of some error */
53     public static final int STATE_STOPPED_ERROR = 4;
54
55     /** job has failed because of some unavoidable service interruption */
56     public static final int STATE_STOPPED_SERVERERROR = 5;
57     int currentStatus = STATE_QUEUING;
58     Image image;
59     int angle = 0;
60     String title = "";
61     jalview.ws.WSClientI thisService;
62     boolean serviceIsCancellable;
63     JInternalFrame frame;
64     JTabbedPane subjobs=null;
65     java.util.Vector jobPanes = null;
66     // tabbed or not
67     public synchronized int addJobPane() {
68       JScrollPane jobpane = new JScrollPane();
69       JTextArea progressText = new JTextArea();
70       progressText.setFont(new java.awt.Font("Verdana", 0, 10));
71       progressText.setBorder(null);
72       progressText.setEditable(false);
73       progressText.setText("WS Job");
74       progressText.setLineWrap(true);
75       progressText.setWrapStyleWord(true);
76       jobpane.setName("JobPane");
77       jobpane.getViewport().add(progressText, null);
78       jobpane.setBorder(null);
79       if (jobPanes==null) {
80         jobPanes = new Vector();
81       }
82       int newpane = jobPanes.size();
83       jobPanes.add(jobpane);
84
85       if (newpane==0) {
86         this.add(jobpane, BorderLayout.CENTER);
87       } else {
88         if (newpane==1) {
89         // revert to a tabbed pane.
90         JScrollPane firstpane;
91         this.remove(firstpane=(JScrollPane) jobPanes.get(0));
92         subjobs=new JTabbedPane();
93           this.add(subjobs, BorderLayout.CENTER);
94           subjobs.add(firstpane);
95           subjobs.setTitleAt(0, firstpane.getName());
96         }
97         subjobs.add(jobpane);
98       }
99       return newpane; // index for accessor methods below
100     }
101     /**
102      * Creates a new WebserviceInfo object.
103      *
104      * @param title short name and job type
105      * @param info reference or other human readable description
106      */
107     public WebserviceInfo(String title, String info)
108     {
109         init(title, info, 520, 500);
110     }
111
112     /**
113      * Creates a new WebserviceInfo object.
114      *
115      * @param title DOCUMENT ME!
116      * @param info DOCUMENT ME!
117      * @param width DOCUMENT ME!
118      * @param height DOCUMENT ME!
119      */
120     public WebserviceInfo(String title, String info, int width, int height)
121     {
122         init(title, info, width, height);
123     }
124
125     /**
126      * DOCUMENT ME!
127      *
128      * @return DOCUMENT ME!
129      */
130     public jalview.ws.WSClientI getthisService()
131     {
132         return thisService;
133     }
134
135     /**
136      * DOCUMENT ME!
137      *
138      * @param newservice DOCUMENT ME!
139      */
140     public void setthisService(jalview.ws.WSClientI newservice)
141     {
142         thisService = newservice;
143         serviceIsCancellable = newservice.isCancellable();
144         frame.setClosable(!serviceIsCancellable);
145     }
146
147     /**
148      * DOCUMENT ME!
149      *
150      * @param title DOCUMENT ME!
151      * @param info DOCUMENT ME!
152      * @param width DOCUMENT ME!
153      * @param height DOCUMENT ME!
154      */
155     void init(String title, String info, int width, int height)
156     {
157         frame = new JInternalFrame();
158         frame.setContentPane(this);
159         Desktop.addInternalFrame(frame, title, width, height);
160         frame.setClosable(false);
161
162         this.title = title;
163         setInfoText(info);
164
165         java.net.URL url = getClass().getResource("/images/logo.gif");
166         image = java.awt.Toolkit.getDefaultToolkit().createImage(url);
167
168         MediaTracker mt = new MediaTracker(this);
169         mt.addImage(image, 0);
170
171         try
172         {
173             mt.waitForID(0);
174         }
175         catch (Exception ex)
176         {
177         }
178
179         AnimatedPanel ap = new AnimatedPanel();
180         titlePanel.add(ap, BorderLayout.CENTER);
181
182         Thread thread = new Thread(ap);
183         thread.start();
184     }
185
186     /**
187      * DOCUMENT ME!
188      *
189      * @param status integer status from state constants
190      */
191     public void setStatus(int status)
192     {
193         currentStatus = status;
194     }
195     /**
196      * subjob status indicator
197      * @param jobpane
198      * @param status
199      */
200     public void setStatus(int jobpane, int status) {
201       if (jobpane<0 || jobpane>=jobPanes.size()) {
202         throw new Error("setStatus called for non-existent job pane."+jobpane);
203       }
204       switch (status) {
205       case STATE_QUEUING:
206         setProgressName(jobpane+" - QUEUED", jobpane);
207         break;
208       case STATE_RUNNING:
209         setProgressName(jobpane+" - RUNNING", jobpane);
210         break;
211       case STATE_STOPPED_OK:
212         setProgressName(jobpane+" - FINISHED", jobpane);
213       break;
214       case STATE_CANCELLED_OK:
215         setProgressName(jobpane+" - CANCELLED", jobpane);
216         break;
217       case STATE_STOPPED_ERROR:
218         setProgressName(jobpane+" - BROKEN",jobpane);
219         break;
220       case STATE_STOPPED_SERVERERROR:
221         setProgressName(jobpane+" - ALERT", jobpane);
222         break;
223         default:
224           setProgressName(jobpane+" - UNKNOWN STATE", jobpane);
225       }
226     }
227     /**
228      * DOCUMENT ME!
229      *
230      * @return DOCUMENT ME!
231      */
232     public String getInfoText()
233     {
234         return infoText.getText();
235     }
236
237     /**
238      * DOCUMENT ME!
239      *
240      * @param text DOCUMENT ME!
241      */
242     public void setInfoText(String text)
243     {
244         infoText.setText(text);
245     }
246
247     /**
248      * DOCUMENT ME!
249      *
250      * @param text DOCUMENT ME!
251      */
252     public void appendInfoText(String text)
253     {
254         infoText.append(text);
255     }
256     /**
257      * DOCUMENT ME!
258      *
259      * @return DOCUMENT ME!
260      */
261     public String getProgressText(int which)
262     {
263       if (jobPanes == null)
264         addJobPane();
265       return ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport().
266               getComponent(0)).getText();
267     }
268     /**
269      * DOCUMENT ME!
270      *
271      * @param text DOCUMENT ME!
272      */
273     public void setProgressText(int which, String text)
274     {
275       if (jobPanes == null)
276         addJobPane();
277       ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport().
278        getComponent(0)).setText(text);
279     }
280
281     /**
282      * DOCUMENT ME!
283      *
284      * @param text DOCUMENT ME!
285      */
286     public void appendProgressText(int which, String text)
287     {
288       if (jobPanes == null)
289         addJobPane();
290       ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport().
291        getComponent(0)).append(text);
292     }
293     /**
294      * setProgressText(0, text)
295      */
296     public void setProgressText(String text)
297     {
298       setProgressText(0, text);
299     }
300     /**
301      * appendProgressText(0, text)
302      */
303     public void appendProgressText(String text)
304     {
305       appendProgressText(0, text);
306     }
307     /**
308      * getProgressText(0)
309      */
310     public String getProgressText()
311     {
312       return getProgressText(0);
313     }
314     /**
315      * get the tab title for a subjob
316      * @param which int
317      * @return String
318      */
319     public String getProgressName(int which) {
320       if (jobPanes==null)
321         addJobPane();
322       if (subjobs!=null)
323         return subjobs.getTitleAt(which);
324       else
325         return ((JScrollPane) jobPanes.get(which)).getViewport().getComponent(0).getName();
326     }
327     /**
328      * set the tab title for a subjob
329      * @param name String
330      * @param which int
331      */
332     public void setProgressName(String name, int which) {
333       if (subjobs!=null) {
334         subjobs.setTitleAt(which, name);
335         subjobs.revalidate();
336         subjobs.repaint();
337       }
338       JScrollPane c=(JScrollPane) jobPanes.get(which);
339       c.getViewport().getComponent(0).setName(name);
340       c.repaint();
341     }
342
343     /**
344      * Gui action for cancelling the current job, if possible.
345      *
346      * @param e DOCUMENT ME!
347      */
348     protected void cancel_actionPerformed(ActionEvent e)
349     {
350         if (!serviceIsCancellable)
351         {
352             JOptionPane.showInternalMessageDialog(Desktop.desktop,
353                 "This job cannot be cancelled.\nJust close the window.", "Cancel job",
354                 JOptionPane.WARNING_MESSAGE);
355         }
356         else
357         {
358             thisService.cancelJob();
359         }
360         frame.setClosable(true);
361     }
362
363     public void setResultsReady()
364     {
365       frame.setClosable(true);
366       buttonPanel.remove(cancel);
367       buttonPanel.add(showResultsNewFrame);
368       buttonPanel.add(mergeResults);
369       buttonPanel.setLayout(new GridLayout(2,1,5,5));
370       buttonPanel.validate();
371       validate();
372     }
373
374   /**
375    * called when job has finished but no result objects can be passed back to user
376    */
377   public void setFinishedNoResults()
378   {
379     frame.setClosable(true);
380     buttonPanel.remove(cancel);
381     buttonPanel.validate();
382     validate();
383   }
384
385   class AnimatedPanel extends JPanel implements Runnable
386     {
387         long startTime = 0;
388         BufferedImage offscreen;
389
390         public void run()
391         {
392             startTime = System.currentTimeMillis();
393             Graphics2D g = null;
394
395             while (currentStatus < STATE_STOPPED_OK)
396             {
397                 try
398                 {
399                     Thread.sleep(50);
400
401                     int units = (int) ( (System.currentTimeMillis() - startTime) /
402                                        10f);
403                     angle += units;
404                     angle %= 360;
405                     startTime = System.currentTimeMillis();
406
407                     if (offscreen == null || offscreen.getWidth(this) != getWidth()
408                         || offscreen.getHeight(this) != getHeight())
409                     {
410                       offscreen = new BufferedImage(getWidth(), getHeight(),
411                                                     BufferedImage.TYPE_INT_ARGB);
412                       g = (Graphics2D) offscreen.getGraphics();
413                     }
414
415                     g.setColor(Color.white);
416                     g.fillRect(0, 0, getWidth(), getHeight());
417
418                     g.setFont(new Font("Arial", Font.BOLD, 12));
419                     g.setColor(Color.black);
420
421                     switch (currentStatus)
422                     {
423                       case STATE_QUEUING:
424                         g.drawString(title.concat(" - queuing"), 60, 30);
425
426                         break;
427
428                       case STATE_RUNNING:
429                         g.drawString(title.concat(" - running"), 60, 30);
430
431                         break;
432
433                       case STATE_STOPPED_OK:
434                         g.drawString(title.concat(" - complete"), 60, 30);
435
436                         break;
437
438                       case STATE_CANCELLED_OK:
439                         g.drawString(title.concat(" - job cancelled!"), 60, 30);
440
441                         break;
442
443                       case STATE_STOPPED_ERROR:
444                         g.drawString(title.concat(" - job error!"), 60, 30);
445
446                         break;
447
448                       case STATE_STOPPED_SERVERERROR:
449                         g.drawString(title.concat(" - Server Error! (try later)"),
450                                      60,
451                                      30);
452
453                         break;
454                     }
455
456
457                     if (currentStatus >= STATE_STOPPED_OK)
458                       angle = 0;
459
460                     if (image != null)
461                     {
462                       g.rotate(Math.toRadians(angle), 28, 28);
463                       g.drawImage(image, 10, 10, this);
464                       g.rotate( -Math.toRadians(angle), 28, 28);
465                     }
466
467
468                     repaint();
469                 }
470                 catch (Exception ex)
471                 {
472                 }
473             }
474
475             cancel.setEnabled(false);
476         }
477
478         public void paintComponent(Graphics g1)
479         {
480             g1.drawImage(offscreen, 0,0,this);
481         }
482     }
483 }