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