Clover icon

Coverage Report

  1. Project Clover database Tue Oct 29 2024 21:36:55 GMT
  2. Package jalview.gui

File WebserviceInfo.java

 

Coverage histogram

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

Code metrics

82
265
44
2
965
618
108
0.41
6.02
22
2.45

Classes

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