42926875ae8abb7d107b1cf9c957344a704346e3
[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     private boolean serviceCanMergeResults = false;
67     private boolean viewResultsImmediatly = true;
68   // tabbed or not
69     public synchronized int addJobPane() {
70       JScrollPane jobpane = new JScrollPane();
71       JTextArea progressText = new JTextArea();
72       progressText.setFont(new java.awt.Font("Verdana", 0, 10));
73       progressText.setBorder(null);
74       progressText.setEditable(false);
75       progressText.setText("WS Job");
76       progressText.setLineWrap(true);
77       progressText.setWrapStyleWord(true);
78       jobpane.setName("JobPane");
79       jobpane.getViewport().add(progressText, null);
80       jobpane.setBorder(null);
81       if (jobPanes==null) {
82         jobPanes = new Vector();
83       }
84       int newpane = jobPanes.size();
85       jobPanes.add(jobpane);
86
87       if (newpane==0) {
88         this.add(jobpane, BorderLayout.CENTER);
89       } else {
90         if (newpane==1) {
91         // revert to a tabbed pane.
92         JScrollPane firstpane;
93         this.remove(firstpane=(JScrollPane) jobPanes.get(0));
94         subjobs=new JTabbedPane();
95           this.add(subjobs, BorderLayout.CENTER);
96           subjobs.add(firstpane);
97           subjobs.setTitleAt(0, firstpane.getName());
98         }
99         subjobs.add(jobpane);
100       }
101       return newpane; // index for accessor methods below
102     }
103     /**
104      * Creates a new WebserviceInfo object.
105      *
106      * @param title short name and job type
107      * @param info reference or other human readable description
108      */
109     public WebserviceInfo(String title, String info)
110     {
111         init(title, info, 520, 500);
112     }
113
114     /**
115      * Creates a new WebserviceInfo object.
116      *
117      * @param title DOCUMENT ME!
118      * @param info DOCUMENT ME!
119      * @param width DOCUMENT ME!
120      * @param height DOCUMENT ME!
121      */
122     public WebserviceInfo(String title, String info, int width, int height)
123     {
124         init(title, info, width, height);
125     }
126
127     /**
128      * DOCUMENT ME!
129      *
130      * @return DOCUMENT ME!
131      */
132     public jalview.ws.WSClientI getthisService()
133     {
134         return thisService;
135     }
136
137     /**
138      * DOCUMENT ME!
139      *
140      * @param newservice DOCUMENT ME!
141      */
142     public void setthisService(jalview.ws.WSClientI newservice)
143     {
144         thisService = newservice;
145         serviceIsCancellable = newservice.isCancellable();
146         frame.setClosable(!serviceIsCancellable);
147         serviceCanMergeResults = newservice.canMergeResults();
148     }
149
150     /**
151      * DOCUMENT ME!
152      *
153      * @param title DOCUMENT ME!
154      * @param info DOCUMENT ME!
155      * @param width DOCUMENT ME!
156      * @param height DOCUMENT ME!
157      */
158     void init(String title, String info, int width, int height)
159     {
160         frame = new JInternalFrame();
161         frame.setContentPane(this);
162         Desktop.addInternalFrame(frame, title, width, height);
163         frame.setClosable(false);
164
165         this.title = title;
166         setInfoText(info);
167
168         java.net.URL url = getClass().getResource("/images/logo.gif");
169         image = java.awt.Toolkit.getDefaultToolkit().createImage(url);
170
171         MediaTracker mt = new MediaTracker(this);
172         mt.addImage(image, 0);
173
174         try
175         {
176             mt.waitForID(0);
177         }
178         catch (Exception ex)
179         {
180         }
181
182         AnimatedPanel ap = new AnimatedPanel();
183         titlePanel.add(ap, BorderLayout.CENTER);
184
185         Thread thread = new Thread(ap);
186         thread.start();
187     }
188
189     /**
190      * DOCUMENT ME!
191      *
192      * @param status integer status from state constants
193      */
194     public void setStatus(int status)
195     {
196         currentStatus = status;
197     }
198     /**
199      * subjob status indicator
200      * @param jobpane
201      * @param status
202      */
203     public void setStatus(int jobpane, int status) {
204       if (jobpane<0 || jobpane>=jobPanes.size()) {
205         throw new Error("setStatus called for non-existent job pane."+jobpane);
206       }
207       switch (status) {
208       case STATE_QUEUING:
209         setProgressName(jobpane+" - QUEUED", jobpane);
210         break;
211       case STATE_RUNNING:
212         setProgressName(jobpane+" - RUNNING", jobpane);
213         break;
214       case STATE_STOPPED_OK:
215         setProgressName(jobpane+" - FINISHED", jobpane);
216       break;
217       case STATE_CANCELLED_OK:
218         setProgressName(jobpane+" - CANCELLED", jobpane);
219         break;
220       case STATE_STOPPED_ERROR:
221         setProgressName(jobpane+" - BROKEN",jobpane);
222         break;
223       case STATE_STOPPED_SERVERERROR:
224         setProgressName(jobpane+" - ALERT", jobpane);
225         break;
226         default:
227           setProgressName(jobpane+" - UNKNOWN STATE", jobpane);
228       }
229     }
230     /**
231      * DOCUMENT ME!
232      *
233      * @return DOCUMENT ME!
234      */
235     public String getInfoText()
236     {
237         return infoText.getText();
238     }
239
240     /**
241      * DOCUMENT ME!
242      *
243      * @param text DOCUMENT ME!
244      */
245     public void setInfoText(String text)
246     {
247         infoText.setText(text);
248     }
249
250     /**
251      * DOCUMENT ME!
252      *
253      * @param text DOCUMENT ME!
254      */
255     public void appendInfoText(String text)
256     {
257         infoText.append(text);
258     }
259     /**
260      * DOCUMENT ME!
261      *
262      * @return DOCUMENT ME!
263      */
264     public String getProgressText(int which)
265     {
266       if (jobPanes == null)
267         addJobPane();
268       return ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport().
269               getComponent(0)).getText();
270     }
271     /**
272      * DOCUMENT ME!
273      *
274      * @param text DOCUMENT ME!
275      */
276     public void setProgressText(int which, String text)
277     {
278       if (jobPanes == null)
279         addJobPane();
280       ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport().
281        getComponent(0)).setText(text);
282     }
283
284     /**
285      * DOCUMENT ME!
286      *
287      * @param text DOCUMENT ME!
288      */
289     public void appendProgressText(int which, String text)
290     {
291       if (jobPanes == null)
292         addJobPane();
293       ( (JTextArea) ( (JScrollPane) jobPanes.get(which)).getViewport().
294        getComponent(0)).append(text);
295     }
296     /**
297      * setProgressText(0, text)
298      */
299     public void setProgressText(String text)
300     {
301       setProgressText(0, text);
302     }
303     /**
304      * appendProgressText(0, text)
305      */
306     public void appendProgressText(String text)
307     {
308       appendProgressText(0, text);
309     }
310     /**
311      * getProgressText(0)
312      */
313     public String getProgressText()
314     {
315       return getProgressText(0);
316     }
317     /**
318      * get the tab title for a subjob
319      * @param which int
320      * @return String
321      */
322     public String getProgressName(int which) {
323       if (jobPanes==null)
324         addJobPane();
325       if (subjobs!=null)
326         return subjobs.getTitleAt(which);
327       else
328         return ((JScrollPane) jobPanes.get(which)).getViewport().getComponent(0).getName();
329     }
330     /**
331      * set the tab title for a subjob
332      * @param name String
333      * @param which int
334      */
335     public void setProgressName(String name, int which) {
336       if (subjobs!=null) {
337         subjobs.setTitleAt(which, name);
338         subjobs.revalidate();
339         subjobs.repaint();
340       }
341       JScrollPane c=(JScrollPane) jobPanes.get(which);
342       c.getViewport().getComponent(0).setName(name);
343       c.repaint();
344     }
345
346     /**
347      * Gui action for cancelling the current job, if possible.
348      *
349      * @param e DOCUMENT ME!
350      */
351     protected void cancel_actionPerformed(ActionEvent e)
352     {
353         if (!serviceIsCancellable)
354         {
355             JOptionPane.showInternalMessageDialog(Desktop.desktop,
356                 "This job cannot be cancelled.\nJust close the window.", "Cancel job",
357                 JOptionPane.WARNING_MESSAGE);
358         }
359         else
360         {
361             thisService.cancelJob();
362         }
363         frame.setClosable(true);
364     }
365     /**
366      * Set up GUI for user to get at results - and possibly automatically display
367      * them if viewResultsImmediatly is set.
368      */
369     public void setResultsReady()
370     {
371       frame.setClosable(true);
372       buttonPanel.remove(cancel);
373       buttonPanel.add(showResultsNewFrame);
374       if (serviceCanMergeResults)
375       {
376         buttonPanel.add(mergeResults);
377         buttonPanel.setLayout(new GridLayout(2, 1, 5, 5));
378       }
379       buttonPanel.validate();
380       validate();
381       if (viewResultsImmediatly)
382         showResultsNewFrame.doClick();
383     }
384
385   /**
386    * called when job has finished but no result objects can be passed back to user
387    */
388   public void setFinishedNoResults()
389   {
390     frame.setClosable(true);
391     buttonPanel.remove(cancel);
392     buttonPanel.validate();
393     validate();
394   }
395
396   class AnimatedPanel extends JPanel implements Runnable
397     {
398         long startTime = 0;
399         BufferedImage offscreen;
400
401         public void run()
402         {
403             startTime = System.currentTimeMillis();
404             Graphics2D g = null;
405
406             while (currentStatus < STATE_STOPPED_OK)
407             {
408                 try
409                 {
410                     Thread.sleep(50);
411
412                     int units = (int) ( (System.currentTimeMillis() - startTime) /
413                                        10f);
414                     angle += units;
415                     angle %= 360;
416                     startTime = System.currentTimeMillis();
417
418                     if (offscreen == null || offscreen.getWidth(this) != getWidth()
419                         || offscreen.getHeight(this) != getHeight())
420                     {
421                       offscreen = new BufferedImage(getWidth(), getHeight(),
422                                                     BufferedImage.TYPE_INT_ARGB);
423                       g = (Graphics2D) offscreen.getGraphics();
424                     }
425
426                     g.setColor(Color.white);
427                     g.fillRect(0, 0, getWidth(), getHeight());
428
429                     g.setFont(new Font("Arial", Font.BOLD, 12));
430                     g.setColor(Color.black);
431
432                     switch (currentStatus)
433                     {
434                       case STATE_QUEUING:
435                         g.drawString(title.concat(" - queuing"), 60, 30);
436
437                         break;
438
439                       case STATE_RUNNING:
440                         g.drawString(title.concat(" - running"), 60, 30);
441
442                         break;
443
444                       case STATE_STOPPED_OK:
445                         g.drawString(title.concat(" - complete"), 60, 30);
446
447                         break;
448
449                       case STATE_CANCELLED_OK:
450                         g.drawString(title.concat(" - job cancelled!"), 60, 30);
451
452                         break;
453
454                       case STATE_STOPPED_ERROR:
455                         g.drawString(title.concat(" - job error!"), 60, 30);
456
457                         break;
458
459                       case STATE_STOPPED_SERVERERROR:
460                         g.drawString(title.concat(" - Server Error! (try later)"),
461                                      60,
462                                      30);
463
464                         break;
465                     }
466
467
468                     if (currentStatus >= STATE_STOPPED_OK)
469                       angle = 0;
470
471                     if (image != null)
472                     {
473                       g.rotate(Math.toRadians(angle), 28, 28);
474                       g.drawImage(image, 10, 10, this);
475                       g.rotate( -Math.toRadians(angle), 28, 28);
476                     }
477
478
479                     repaint();
480                 }
481                 catch (Exception ex)
482                 {
483                 }
484             }
485
486             cancel.setEnabled(false);
487         }
488
489         public void paintComponent(Graphics g1)
490         {
491             g1.drawImage(offscreen, 0,0,this);
492         }
493     }
494 }