Clover icon

Coverage Report

  1. Project Clover database Thu Aug 13 2020 12:04:21 BST
  2. Package jalview.gui

File WebserviceInfo.java

 

Coverage histogram

../../img/srcFileCovDistChart0.png
56% of files have more coverage

Code metrics

82
262
41
2
948
604
105
0.4
6.39
20.5
2.56

Classes

Class Line # Actions
WebserviceInfo 61 214 89
0.00%
WebserviceInfo.AnimatedPanel 790 48 16
0.00%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3    * Copyright (C) $$Year-Rel$$ The Jalview Authors
4    *
5    * This file is part of Jalview.
6    *
7    * Jalview is free software: you can redistribute it and/or
8    * modify it under the terms of the GNU General Public License
9    * as published by the Free Software Foundation, either version 3
10    * of the License, or (at your option) any later version.
11    *
12    * Jalview is distributed in the hope that it will be useful, but
13    * WITHOUT ANY WARRANTY; without even the implied warranty
14    * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15    * PURPOSE. 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 Jalview. If not, see <http://www.gnu.org/licenses/>.
19    * The Jalview Authors are detailed in the 'AUTHORS' file.
20    */
21    package jalview.gui;
22   
23    import jalview.jbgui.GWebserviceInfo;
24    import jalview.util.MessageManager;
25    import jalview.ws.WSClientI;
26   
27    import java.awt.BorderLayout;
28    import java.awt.Color;
29    import java.awt.Dimension;
30    import java.awt.Graphics;
31    import java.awt.Graphics2D;
32    import java.awt.GridLayout;
33    import java.awt.Image;
34    import java.awt.MediaTracker;
35    import java.awt.RenderingHints;
36    import java.awt.event.ActionEvent;
37    import java.awt.image.BufferedImage;
38    import java.util.Vector;
39   
40    import javax.swing.JComponent;
41    import javax.swing.JEditorPane;
42    import javax.swing.JInternalFrame;
43    import javax.swing.JPanel;
44    import javax.swing.JScrollPane;
45    import javax.swing.JTabbedPane;
46    import javax.swing.JTextArea;
47    import javax.swing.event.HyperlinkEvent;
48    import javax.swing.event.HyperlinkListener;
49    import javax.swing.event.InternalFrameAdapter;
50    import javax.swing.event.InternalFrameEvent;
51    import javax.swing.text.html.HTMLEditorKit;
52    import javax.swing.text.html.StyleSheet;
53   
54    /**
55    * Base class for web service client thread and gui TODO: create StAX parser to
56    * extract html body content reliably when preparing html formatted job statuses
57    *
58    * @author $author$
59    * @version $Revision$
60    */
 
61    public class WebserviceInfo extends GWebserviceInfo
62    implements HyperlinkListener, IProgressIndicator
63    {
64   
65    /** Job is Queued */
66    public static final int STATE_QUEUING = 0;
67   
68    /** Job is Running */
69    public static final int STATE_RUNNING = 1;
70   
71    /** Job has finished with no errors */
72    public static final int STATE_STOPPED_OK = 2;
73   
74    /** Job has been cancelled with no errors */
75    public static final int STATE_CANCELLED_OK = 3;
76   
77    /** job has stopped because of some error */
78    public static final int STATE_STOPPED_ERROR = 4;
79   
80    /** job has failed because of some unavoidable service interruption */
81    public static final int STATE_STOPPED_SERVERERROR = 5;
82   
83    int currentStatus = STATE_QUEUING;
84   
85    Image image;
86   
87    float angle = 0f;
88   
89    String title = "";
90   
91    jalview.ws.WSClientI thisService;
92   
93    boolean serviceIsCancellable;
94   
95    JInternalFrame frame;
96   
97    private IProgressIndicator progressBar;
98   
 
99  0 toggle @Override
100    public void setVisible(boolean aFlag)
101    {
102  0 super.setVisible(aFlag);
103  0 frame.setVisible(aFlag);
104    }
105   
106    JTabbedPane subjobs = null;
107   
108    java.util.Vector jobPanes = null;
109   
110    private boolean serviceCanMergeResults = false;
111   
112    private boolean viewResultsImmediatly = true;
113   
114    /**
115    * Get
116    *
117    * @param flag
118    * to indicate if results will be shown in a new window as soon as
119    * they are available.
120    */
 
121  0 toggle public boolean isViewResultsImmediatly()
122    {
123  0 return viewResultsImmediatly;
124    }
125   
126    /**
127    * Set
128    *
129    * @param flag
130    * to indicate if results will be shown in a new window as soon as
131    * they are available.
132    */
 
133  0 toggle public void setViewResultsImmediatly(boolean viewResultsImmediatly)
134    {
135  0 this.viewResultsImmediatly = viewResultsImmediatly;
136    }
137   
 
138  0 toggle private StyleSheet getStyleSheet(HTMLEditorKit editorKit)
139    {
140   
141    // Copied blatantly from
142    // http://www.velocityreviews.com/forums/t132265-string-into-htmldocument.html
143  0 StyleSheet myStyleSheet = new StyleSheet();
144   
145  0 myStyleSheet.addStyleSheet(editorKit.getStyleSheet());
146   
147  0 editorKit.setStyleSheet(myStyleSheet);
148   
149    /*
150    * Set the style sheet rules here by reading them from the constants
151    * interface.
152    */
153    /*
154    * for (int ix=0; ix<CSS_RULES.length; ix++) {
155    *
156    * myStyleSheet.addRule(CSS_RULES[ix]);
157    *
158    * }
159    */
160  0 return myStyleSheet;
161   
162    }
163   
164    // tabbed or not
 
165  0 toggle public synchronized int addJobPane()
166    {
167  0 JScrollPane jobpane = new JScrollPane();
168  0 JComponent _progressText;
169  0 if (renderAsHtml)
170    {
171  0 JEditorPane progressText = new JEditorPane("text/html", "");
172  0 progressText.addHyperlinkListener(this);
173  0 _progressText = progressText;
174    // progressText.setFont(new java.awt.Font("Verdana", 0, 10));
175    // progressText.setBorder(null);
176  0 progressText.setEditable(false);
177    /*
178    * HTMLEditorKit myEditorKit = new HTMLEditorKit();
179    *
180    * StyleSheet myStyleSheet = getStyleSheet(myEditorKit);
181    *
182    * HTMLDocument tipDocument = (HTMLDocument)
183    * (myEditorKit.createDefaultDocument());
184    *
185    * progressText.setDocument(tipDocument);
186  0 */progressText.setText("<html><h1>WS Job</h1></html>");
187    }
188    else
189    {
190  0 JTextArea progressText = new JTextArea();
191  0 _progressText = progressText;
192   
193  0 progressText.setFont(new java.awt.Font("Verdana", 0, 10));
194  0 progressText.setBorder(null);
195  0 progressText.setEditable(false);
196  0 progressText.setText("WS Job");
197  0 progressText.setLineWrap(true);
198  0 progressText.setWrapStyleWord(true);
199    }
200  0 jobpane.setName("JobPane");
201  0 jobpane.getViewport().add(_progressText, null);
202  0 jobpane.setBorder(null);
203  0 if (jobPanes == null)
204    {
205  0 jobPanes = new Vector();
206    }
207  0 int newpane = jobPanes.size();
208  0 jobPanes.add(jobpane);
209   
210  0 if (newpane == 0)
211    {
212  0 this.add(jobpane, BorderLayout.CENTER);
213    }
214    else
215    {
216  0 if (newpane == 1)
217    {
218    // revert to a tabbed pane.
219  0 JScrollPane firstpane;
220  0 this.remove(firstpane = (JScrollPane) jobPanes.get(0));
221  0 subjobs = new JTabbedPane();
222  0 this.add(subjobs, BorderLayout.CENTER);
223  0 subjobs.add(firstpane);
224  0 subjobs.setTitleAt(0, firstpane.getName());
225    }
226  0 subjobs.add(jobpane);
227    }
228  0 return newpane; // index for accessor methods below
229    }
230   
231    /**
232    * Creates a new WebserviceInfo object.
233    *
234    * @param title
235    * short name and job type
236    * @param info
237    * reference or other human readable description
238    * @param makeVisible
239    * true to display the webservices window immediatly (otherwise need
240    * to call setVisible(true))
241    */
 
242  0 toggle public WebserviceInfo(String title, String info, boolean makeVisible)
243    {
244  0 init(title, info, 520, 500, makeVisible);
245    }
246   
247    /**
248    * Creates a new WebserviceInfo object.
249    *
250    * @param title
251    * DOCUMENT ME!
252    * @param info
253    * DOCUMENT ME!
254    * @param width
255    * DOCUMENT ME!
256    * @param height
257    * DOCUMENT ME!
258    */
 
259  0 toggle public WebserviceInfo(String title, String info, int width, int height,
260    boolean makeVisible)
261    {
262  0 init(title, info, width, height, makeVisible);
263    }
264   
265    /**
266    * DOCUMENT ME!
267    *
268    * @return DOCUMENT ME!
269    */
 
270  0 toggle public jalview.ws.WSClientI getthisService()
271    {
272  0 return thisService;
273    }
274   
275    /**
276    * Update state of GUI based on client capabilities (like whether the job is
277    * cancellable, whether the 'merge results' button is shown.
278    *
279    * @param newservice
280    * service client to query for capabilities
281    */
 
282  0 toggle public void setthisService(jalview.ws.WSClientI newservice)
283    {
284  0 thisService = newservice;
285  0 serviceIsCancellable = newservice.isCancellable();
286  0 frame.setClosable(!serviceIsCancellable);
287  0 serviceCanMergeResults = newservice.canMergeResults();
288  0 rebuildButtonPanel();
289    }
290   
 
291  0 toggle private void rebuildButtonPanel()
292    {
293  0 if (buttonPanel != null)
294    {
295  0 buttonPanel.removeAll();
296  0 if (serviceIsCancellable)
297    {
298  0 buttonPanel.add(cancel);
299  0 frame.setClosable(false);
300    }
301    else
302    {
303  0 frame.setClosable(true);
304    }
305    }
306    }
307   
308    /**
309    * DOCUMENT ME!
310    *
311    * @param title
312    * DOCUMENT ME!
313    * @param info
314    * DOCUMENT ME!
315    * @param width
316    * DOCUMENT ME!
317    * @param height
318    * DOCUMENT ME!
319    */
 
320  0 toggle void init(String title, String info, int width, int height,
321    boolean makeVisible)
322    {
323  0 frame = new JInternalFrame();
324  0 frame.setContentPane(this);
325  0 Desktop.addInternalFrame(frame, title, makeVisible, width, height);
326  0 frame.setClosable(false);
327   
328  0 progressBar = new ProgressBar(statusPanel, statusBar);
329   
330  0 this.title = title;
331  0 setInfoText(info);
332   
333  0 java.net.URL url = getClass()
334    .getResource("/images/Jalview_Logo_small_with_border.png");
335  0 image = java.awt.Toolkit.getDefaultToolkit().createImage(url);
336   
337  0 MediaTracker mt = new MediaTracker(this);
338  0 mt.addImage(image, 0);
339   
340  0 try
341    {
342  0 mt.waitForID(0);
343    } catch (Exception ex)
344    {
345    }
346   
347  0 AnimatedPanel ap = new AnimatedPanel();
348  0 ap.setPreferredSize(new Dimension(60, 60));
349  0 titlePanel.add(ap, BorderLayout.WEST);
350  0 titlePanel.add(titleText, BorderLayout.CENTER);
351  0 setStatus(currentStatus);
352   
353  0 Thread thread = new Thread(ap);
354  0 thread.start();
355  0 final WebserviceInfo thisinfo = this;
356  0 frame.addInternalFrameListener(
357    new InternalFrameAdapter()
358    {
 
359  0 toggle @Override
360    public void internalFrameClosed(InternalFrameEvent evt)
361    {
362    // System.out.println("Shutting down webservice client");
363  0 WSClientI service = thisinfo.getthisService();
364  0 if (service != null && service.isCancellable())
365    {
366  0 service.cancelJob();
367    }
368    }
369    });
370  0 frame.validate();
371   
372    }
373   
374    /**
375    * DOCUMENT ME!
376    *
377    * @param status
378    * integer status from state constants
379    */
 
380  0 toggle public void setStatus(int status)
381    {
382  0 currentStatus = status;
383   
384  0 String message = null;
385  0 switch (currentStatus)
386    {
387  0 case STATE_QUEUING:
388  0 message = MessageManager.getString("label.state_queueing");
389  0 break;
390   
391  0 case STATE_RUNNING:
392  0 message = MessageManager.getString("label.state_running");
393  0 break;
394   
395  0 case STATE_STOPPED_OK:
396  0 message = MessageManager.getString("label.state_completed");
397  0 break;
398   
399  0 case STATE_CANCELLED_OK:
400  0 message = MessageManager.getString("label.state_job_cancelled");
401  0 break;
402   
403  0 case STATE_STOPPED_ERROR:
404  0 message = MessageManager.getString("label.state_job_error");
405  0 break;
406   
407  0 case STATE_STOPPED_SERVERERROR:
408  0 message = MessageManager.getString("label.server_error_try_later");
409  0 break;
410    }
411  0 titleText.setText(title + (message == null ? "" : " - " + message));
412  0 titleText.repaint();
413    }
414   
415    /**
416    * subjob status indicator
417    *
418    * @param jobpane
419    * @param status
420    */
 
421  0 toggle public void setStatus(int jobpane, int status)
422    {
423  0 if (jobpane < 0 || jobpane >= jobPanes.size())
424    {
425  0 throw new Error(MessageManager.formatMessage(
426    "error.setstatus_called_non_existent_job_pane", new String[]
427    { Integer.valueOf(jobpane).toString() }));
428    }
429  0 switch (status)
430    {
431  0 case STATE_QUEUING:
432  0 setProgressName(jobpane + " - QUEUED", jobpane);
433  0 break;
434  0 case STATE_RUNNING:
435  0 setProgressName(jobpane + " - RUNNING", jobpane);
436  0 break;
437  0 case STATE_STOPPED_OK:
438  0 setProgressName(jobpane + " - FINISHED", jobpane);
439  0 break;
440  0 case STATE_CANCELLED_OK:
441  0 setProgressName(jobpane + " - CANCELLED", jobpane);
442  0 break;
443  0 case STATE_STOPPED_ERROR:
444  0 setProgressName(jobpane + " - BROKEN", jobpane);
445  0 break;
446  0 case STATE_STOPPED_SERVERERROR:
447  0 setProgressName(jobpane + " - ALERT", jobpane);
448  0 break;
449  0 default:
450  0 setProgressName(jobpane + " - UNKNOWN STATE", jobpane);
451    }
452    }
453   
454    /**
455    * DOCUMENT ME!
456    *
457    * @return DOCUMENT ME!
458    */
 
459  0 toggle public String getInfoText()
460    {
461  0 return infoText.getText();
462    }
463   
464    /**
465    * DOCUMENT ME!
466    *
467    * @param text
468    * DOCUMENT ME!
469    */
 
470  0 toggle public void setInfoText(String text)
471    {
472  0 infoText.setText(text);
473    }
474   
475    /**
476    * DOCUMENT ME!
477    *
478    * @param text
479    * DOCUMENT ME!
480    */
 
481  0 toggle public void appendInfoText(String text)
482    {
483  0 infoText.append(text);
484    }
485   
486    /**
487    * DOCUMENT ME!
488    *
489    * @return DOCUMENT ME!
490    */
 
491  0 toggle public String getProgressText(int which)
492    {
493  0 if (jobPanes == null)
494    {
495  0 addJobPane();
496    }
497  0 if (renderAsHtml)
498    {
499  0 return ((JEditorPane) ((JScrollPane) jobPanes.get(which))
500    .getViewport().getComponent(0)).getText();
501    }
502    else
503    {
504  0 return ((JTextArea) ((JScrollPane) jobPanes.get(which)).getViewport()
505    .getComponent(0)).getText();
506    }
507    }
508   
509    /**
510    * DOCUMENT ME!
511    *
512    * @param text
513    * DOCUMENT ME!
514    */
 
515  0 toggle public void setProgressText(int which, String text)
516    {
517  0 if (jobPanes == null)
518    {
519  0 addJobPane();
520    }
521  0 if (renderAsHtml)
522    {
523  0 ((JEditorPane) ((JScrollPane) jobPanes.get(which)).getViewport()
524    .getComponent(0)).setText(ensureHtmlTagged(text));
525    }
526    else
527    {
528  0 ((JTextArea) ((JScrollPane) jobPanes.get(which)).getViewport()
529    .getComponent(0)).setText(text);
530    }
531    }
532   
533    /**
534    * extract content from &lt;body&gt; content &lt;/body&gt;
535    *
536    * @param text
537    * @param leaveFirst
538    * - set to leave the initial html tag intact
539    * @param leaveLast
540    * - set to leave the final html tag intact
541    * @return
542    */
 
543  0 toggle private String getHtmlFragment(String text, boolean leaveFirst,
544    boolean leaveLast)
545    {
546  0 if (text == null)
547    {
548  0 return null;
549    }
550  0 String lowertxt = text.toLowerCase();
551  0 int htmlpos = leaveFirst ? -1 : lowertxt.indexOf("<body");
552   
553  0 int htmlend = leaveLast ? -1 : lowertxt.indexOf("</body");
554  0 int htmlpose = lowertxt.indexOf(">", htmlpos),
555    htmlende = lowertxt.indexOf(">", htmlend);
556  0 if (htmlend == -1 && htmlpos == -1)
557    {
558  0 return text;
559    }
560  0 if (htmlend > -1)
561    {
562  0 return text.substring((htmlpos == -1 ? 0 : htmlpose + 1), htmlend);
563    }
564  0 return text.substring(htmlpos == -1 ? 0 : htmlpose + 1);
565    }
566   
567    /**
568    * very simple routine for adding/ensuring html tags are present in text.
569    *
570    * @param text
571    * @return properly html tag enclosed text
572    */
 
573  0 toggle private String ensureHtmlTagged(String text)
574    {
575  0 if (text == null)
576    {
577  0 return "";
578    }
579  0 String lowertxt = text.toLowerCase();
580  0 int htmlpos = lowertxt.indexOf("<body");
581  0 int htmlend = lowertxt.indexOf("</body");
582  0 int doctype = lowertxt.indexOf("<!doctype");
583  0 int xmltype = lowertxt.indexOf("<?xml");
584  0 if (htmlend == -1)
585    {
586  0 text = text + "</body></html>";
587    }
588  0 if (htmlpos > -1)
589    {
590  0 if ((doctype > -1 && htmlpos > doctype)
591    || (xmltype > -1 && htmlpos > xmltype))
592    {
593  0 text = "<html><head></head><body>\n" + text.substring(htmlpos - 1);
594    }
595    }
596    else
597    {
598  0 text = "<html><head></head><body>\n" + text;
599    }
600  0 if (text.indexOf("<meta") > -1)
601    {
602  0 System.err
603    .println("HTML COntent: \n" + text + "<< END HTML CONTENT\n");
604   
605    }
606  0 return text;
607    }
608   
609    /**
610    * DOCUMENT ME!
611    *
612    * @param text
613    * DOCUMENT ME!
614    */
 
615  0 toggle public void appendProgressText(int which, String text)
616    {
617  0 if (jobPanes == null)
618    {
619  0 addJobPane();
620    }
621  0 if (renderAsHtml)
622    {
623  0 String txt = getHtmlFragment(
624    ((JEditorPane) ((JScrollPane) jobPanes.get(which))
625    .getViewport().getComponent(0)).getText(),
626    true, false);
627  0 ((JEditorPane) ((JScrollPane) jobPanes.get(which)).getViewport()
628    .getComponent(0))
629    .setText(ensureHtmlTagged(
630    txt + getHtmlFragment(text, false, true)));
631    }
632    else
633    {
634  0 ((JTextArea) ((JScrollPane) jobPanes.get(which)).getViewport()
635    .getComponent(0)).append(text);
636    }
637    }
638   
639    /**
640    * setProgressText(0, text)
641    */
 
642  0 toggle public void setProgressText(String text)
643    {
644  0 setProgressText(0, text);
645    }
646   
647    /**
648    * appendProgressText(0, text)
649    */
 
650  0 toggle public void appendProgressText(String text)
651    {
652  0 appendProgressText(0, text);
653    }
654   
655    /**
656    * getProgressText(0)
657    */
 
658  0 toggle public String getProgressText()
659    {
660  0 return getProgressText(0);
661    }
662   
663    /**
664    * get the tab title for a subjob
665    *
666    * @param which
667    * int
668    * @return String
669    */
 
670  0 toggle public String getProgressName(int which)
671    {
672  0 if (jobPanes == null)
673    {
674  0 addJobPane();
675    }
676  0 if (subjobs != null)
677    {
678  0 return subjobs.getTitleAt(which);
679    }
680    else
681    {
682  0 return ((JScrollPane) jobPanes.get(which)).getViewport()
683    .getComponent(0).getName();
684    }
685    }
686   
687    /**
688    * set the tab title for a subjob
689    *
690    * @param name
691    * String
692    * @param which
693    * int
694    */
 
695  0 toggle public void setProgressName(String name, int which)
696    {
697  0 if (subjobs != null)
698    {
699  0 subjobs.setTitleAt(which, name);
700  0 subjobs.revalidate();
701  0 subjobs.repaint();
702    }
703  0 JScrollPane c = (JScrollPane) jobPanes.get(which);
704  0 c.getViewport().getComponent(0).setName(name);
705  0 c.repaint();
706    }
707   
708    /**
709    * Gui action for cancelling the current job, if possible.
710    *
711    * @param e
712    * DOCUMENT ME!
713    */
 
714  0 toggle @Override
715    protected void cancel_actionPerformed(ActionEvent e)
716    {
717  0 if (!serviceIsCancellable)
718    {
719    // JBPNote : TODO: We should REALLY just tell the WSClientI to cancel
720    // anyhow - it has to stop threads and clean up
721    // JBPNote : TODO: Instead of a warning, we should have an optional 'Are
722    // you sure?' prompt
723  0 warnUser(
724    MessageManager.getString(
725    "warn.job_cannot_be_cancelled_close_window"),
726    MessageManager.getString("action.cancel_job"));
727    }
728    else
729    {
730  0 thisService.cancelJob();
731    }
732  0 frame.setClosable(true);
733    }
734   
735    /**
736    * Spawns a thread that pops up a warning dialog box with the given message
737    * and title.
738    *
739    * @param message
740    * @param title
741    */
 
742  0 toggle public void warnUser(final String message, final String title)
743    {
744  0 javax.swing.SwingUtilities.invokeLater(new Runnable()
745    {
 
746  0 toggle @Override
747    public void run()
748    {
749  0 JvOptionPane.showInternalMessageDialog(Desktop.desktop, message,
750    title, JvOptionPane.WARNING_MESSAGE);
751   
752    }
753    });
754    }
755   
756    /**
757    * Set up GUI for user to get at results - and possibly automatically display
758    * them if viewResultsImmediatly is set.
759    */
 
760  0 toggle public void setResultsReady()
761    {
762  0 frame.setClosable(true);
763  0 buttonPanel.remove(cancel);
764  0 buttonPanel.add(showResultsNewFrame);
765  0 if (serviceCanMergeResults)
766    {
767  0 buttonPanel.add(mergeResults);
768  0 buttonPanel.setLayout(new GridLayout(2, 1, 5, 5));
769    }
770  0 buttonPanel.validate();
771  0 validate();
772  0 if (viewResultsImmediatly)
773    {
774  0 showResultsNewFrame.doClick();
775    }
776    }
777   
778    /**
779    * called when job has finished but no result objects can be passed back to
780    * user
781    */
 
782  0 toggle public void setFinishedNoResults()
783    {
784  0 frame.setClosable(true);
785  0 buttonPanel.remove(cancel);
786  0 buttonPanel.validate();
787  0 validate();
788    }
789   
 
790    class AnimatedPanel extends JPanel implements Runnable
791    {
792    long startTime = 0;
793   
794    BufferedImage offscreen;
795   
 
796  0 toggle @Override
797    public void run()
798    {
799  0 startTime = System.currentTimeMillis();
800   
801  0 float invSpeed = 15f;
802  0 float factor = 1f;
803  0 while (currentStatus < STATE_STOPPED_OK)
804    {
805  0 if (currentStatus == STATE_QUEUING)
806    {
807  0 invSpeed = 25f;
808  0 factor = 1f;
809    }
810  0 else if (currentStatus == STATE_RUNNING)
811    {
812  0 invSpeed = 10f;
813  0 factor = (float) (0.5 + 1.5
814    * (0.5 - (0.5 * Math.sin(3.14159 / 180 * (angle + 45)))));
815    }
816  0 try
817    {
818  0 Thread.sleep(50);
819   
820  0 float delta = (System.currentTimeMillis() - startTime) / invSpeed;
821  0 angle += delta * factor;
822  0 angle %= 360;
823  0 startTime = System.currentTimeMillis();
824   
825  0 if (currentStatus >= STATE_STOPPED_OK)
826    {
827  0 park();
828  0 angle = 0;
829    }
830   
831  0 repaint();
832    } catch (Exception ex)
833    {
834    }
835    }
836   
837  0 cancel.setEnabled(false);
838    }
839   
 
840  0 toggle public void park()
841    {
842  0 startTime = System.currentTimeMillis();
843   
844  0 while (angle < 360)
845    {
846  0 float invSpeed = 5f;
847  0 float factor = 1f;
848  0 try
849    {
850  0 Thread.sleep(25);
851   
852  0 float delta = (System.currentTimeMillis() - startTime) / invSpeed;
853  0 angle += delta * factor;
854  0 startTime = System.currentTimeMillis();
855   
856  0 if (angle >= 360)
857    {
858  0 angle = 360;
859    }
860   
861  0 repaint();
862    } catch (Exception ex)
863    {
864    }
865    }
866   
867    }
868   
 
869  0 toggle void drawPanel()
870    {
871  0 if (offscreen == null || offscreen.getWidth(this) != getWidth()
872    || offscreen.getHeight(this) != getHeight())
873    {
874  0 offscreen = new BufferedImage(getWidth(), getHeight(),
875    BufferedImage.TYPE_INT_RGB);
876    }
877   
878  0 Graphics2D g = (Graphics2D) offscreen.getGraphics();
879   
880  0 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
881    RenderingHints.VALUE_ANTIALIAS_ON);
882  0 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
883    RenderingHints.VALUE_INTERPOLATION_BICUBIC);
884  0 g.setRenderingHint(RenderingHints.KEY_RENDERING,
885    RenderingHints.VALUE_RENDER_QUALITY);
886   
887  0 g.setColor(Color.white);
888  0 g.fillRect(0, 0, getWidth(), getHeight());
889   
890  0 if (image != null)
891    {
892  0 int x = image.getWidth(this) / 2, y = image.getHeight(this) / 2;
893  0 g.rotate(3.14159 / 180 * (angle), x, y);
894  0 g.drawImage(image, 0, 0, this);
895  0 g.rotate(-3.14159 / 180 * (angle), x, y);
896    }
897    }
898   
 
899  0 toggle @Override
900    public void paintComponent(Graphics g1)
901    {
902  0 drawPanel();
903   
904  0 g1.drawImage(offscreen, 0, 0, this);
905    }
906    }
907   
908    boolean renderAsHtml = false;
909   
 
910  0 toggle public void setRenderAsHtml(boolean b)
911    {
912  0 renderAsHtml = b;
913    }
914   
 
915  0 toggle @Override
916    public void hyperlinkUpdate(HyperlinkEvent e)
917    {
918  0 Desktop.hyperlinkUpdate(e);
919    }
920   
921    /*
922    * (non-Javadoc)
923    *
924    * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
925    */
 
926  0 toggle @Override
927    public void setProgressBar(String message, long id)
928    {
929  0 progressBar.setProgressBar(message, id);
930    }
931   
 
932  0 toggle @Override
933    public void registerHandler(final long id,
934    final IProgressIndicatorHandler handler)
935    {
936  0 progressBar.registerHandler(id, handler);
937    }
938   
939    /**
940    *
941    * @return true if any progress bars are still active
942    */
 
943  0 toggle @Override
944    public boolean operationInProgress()
945    {
946  0 return progressBar.operationInProgress();
947    }
948    }