1 /*
2  *
3  * created: Wed Aug 3 2004
4  *
5  * This file is part of Artemis
6  *
7  * Copyright(C) 2000  Genome Research Limited
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or(at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  */
24 
25 package uk.ac.sanger.artemis.editor;
26 
27 import java.util.StringTokenizer;
28 import java.util.Vector;
29 import javax.swing.border.*;
30 import javax.swing.event.*;
31 import javax.swing.text.html.*;
32 import javax.swing.text.Document;
33 import javax.swing.*;
34 import java.awt.*;
35 import java.awt.event.*;
36 import java.io.BufferedReader;
37 import java.io.StringReader;
38 import java.io.IOException;
39 import javax.swing.text.BadLocationException;
40 import java.net.URL;
41 
42 public class Annotation extends JEditorPane
43                         implements HyperlinkListener
44 {
45   /** */
46   private static final long serialVersionUID = 1L;
47   private int startRange;
48   //private int endRange;
49   /** busy cursor */
50   private Cursor cbusy = new Cursor(Cursor.WAIT_CURSOR);
51   /** done cursor */
52   private Cursor cdone = new Cursor(Cursor.DEFAULT_CURSOR);
53   /** desktop pane */
54   private JDesktopPane desktop = null;
55   /** back option */
56   private Vector back = new Vector();
57   /** popup menu */
58   private JPopupMenu popup;
59   /** known qualifiers */
60   private Vector qualifier = new Vector();
61 
Annotation(JDesktopPane desktop)62   public Annotation(JDesktopPane desktop)
63   {
64     super();
65     this.desktop = desktop;
66 
67     setEditable(false);
68     setContentType("text/html");
69     setFont(BigPane.font);
70     addHyperlinkListener(this);
71   }
72 
73 
Annotation(URL url)74   public Annotation(URL url) throws IOException
75   {
76     super(url);
77 
78     setEditable(false);
79     addHyperlinkListener(this);
80 
81 // popup
82     addMouseListener(new PopupListener());
83     popup = new JPopupMenu();
84     JMenuItem backMenu = new JMenuItem("Back");
85     popup.add(backMenu);
86     backMenu.addActionListener(new ActionListener()
87     {
88       public void actionPerformed(ActionEvent e)
89       {
90         goBack();
91       }
92     });
93     back.add(url);
94   }
95 
setAnnotation(String text)96   protected void setAnnotation(String text)
97   {
98 //  setText("<html><body>"+text+"</html></body>");
99 //  reportHTML();
100 //  startRange = getDocument().getLength();
101     String line = null;
102 
103 // record qualifiers used
104     try
105     {
106       BufferedReader buffRead = new BufferedReader(new StringReader(text));
107       while((line = buffRead.readLine()) != null)
108       {
109         int ind = line.indexOf("=");
110         if(ind > -1)
111           qualifier.add(line.substring(0,ind+1).toLowerCase());
112       }
113     }
114     catch(IOException ioe){}
115     qualifier.add("/similarity=");
116     qualifier.add("/gene=");
117     qualifier.add("/GO_component=");
118     qualifier.add("/product=");
119     qualifier.add("/EC_number=");
120     qualifier.add("/note=");
121 
122     text = getDatabaseHTML(text,"SWALL:");
123     text = getDatabaseHTML(text,"UniProt:");
124     text = getDatabaseHTML(text,"EMBL:");
125     setText("<html><body><font size=3>"+text+"</font></html></body>");
126     startRange = getDocument().getLength();
127   }
128 
129 
reportHTML()130   protected void reportHTML()
131   {
132     try
133     {
134       String txt = ((HTMLDocument)getDocument()).getText(0,getDocument().getLength());
135       System.out.println("TXT:\n"+txt);
136       System.out.println("\nHTML:\n"+getText()+"\n\n");
137     }
138     catch(BadLocationException ble)
139     {
140       ble.printStackTrace();
141     }
142   }
143 
144 
getFeatureText()145   protected String getFeatureText()
146   {
147     String txt = "";
148     try
149     {
150       txt = ((HTMLDocument)getDocument()).getText(0,getDocument().getLength()).trim();
151 
152       StringBuffer buff = new StringBuffer();
153       StringTokenizer tok = new StringTokenizer(txt,"/");
154       int ntok = 0;
155 
156       while(tok.hasMoreTokens())
157       {
158         String tokTxt = "/"+tok.nextToken().trim();
159 
160         int ind = tokTxt.indexOf("=");
161 
162         if(ntok != 0 && ind > -1 && qualifier.contains(tokTxt.substring(0,ind+1)))
163           buff.append("\n"+tokTxt);
164         else
165           buff.append(tokTxt);
166 
167         ntok++;
168       }
169 
170       txt = buff.toString();
171     }
172     catch(BadLocationException ble)
173     {
174       ble.printStackTrace();
175     }
176 
177     return txt;
178   }
179 
180 
insert(String s, boolean ortholog)181   protected void insert(String s, boolean ortholog)
182   {
183     s = getDatabaseHTML(s,"SWALL:");
184     s = getDatabaseHTML(s,"UniProt:");
185     s = getDatabaseHTML(s,"EMBL:");
186     s = getGeneDBHTML(s);
187 
188 //  int ind = s.indexOf("/gene");
189 
190     Document doc = getDocument();
191     int offset = doc.getLength();
192     if(ortholog)
193       offset = startRange;
194 
195     insert(s,offset);
196 
197     setCaretPosition(doc.getLength());
198 //  reportHTML();
199   }
200 
201 
insert(String s, int offset)202   protected void insert(String s, int offset)
203   {
204     try
205     {
206       HTMLEditorKit edKit = (HTMLEditorKit)getEditorKit();
207 //    ((HTMLDocument)getDocument()).insertString(offset,"\n",null);
208       edKit.insertHTML((HTMLDocument)getDocument(),offset,"<BR>\n"+s,0,0,HTML.Tag.BR);
209 //    HTMLEditorKit.InsertHTMLTextAction("similarity",s,HTML.Tag.BODY,HTML.Tag.P);
210     }
211     catch(BadLocationException ble)
212     {
213       System.out.println("Offset "+offset);
214       ble.printStackTrace();
215     }
216     catch(Exception exp)
217     {
218       exp.printStackTrace();
219     }
220   }
221 
222 
getGeneDBHTML(String s)223   private String getGeneDBHTML(String s)
224   {
225     int ind = s.indexOf("GeneDB");
226     if(ind>-1)
227     {
228       String startStr = s.substring(0,ind);
229       int ind2 = s.indexOf(";",ind);
230 
231       String midStr = s.substring(ind,ind2);
232       String endStr = s.substring(ind2);
233 
234       ind2 = midStr.indexOf(":")+1;
235 
236       String db = midStr.substring(7,8)+".+"+
237                   midStr.substring(8,ind2-1);
238       String genedb = "http://www.genedb.org/genedb/Search?name="+
239                       midStr.substring(ind2)+
240                       "&organism="+db;
241 
242       s = startStr + "<a href=\""+genedb+"\">" +
243           midStr   + "</a>" + endStr;
244     }
245     return s;
246   }
247 
248 
getDatabaseHTML(String s, String db)249   private String getDatabaseHTML(String s, String db)
250   {
251 //  int ind = s.indexOf(db);
252 
253 //  if(ind == -1)
254 //    ind = s.indexOf(db.toLowerCase());
255 
256 //  if(ind>-1)
257 //  {
258 //    s = setHyperLinks(s,ind);
259 //    String startStr = s.substring(0,ind);
260 //    int ind2 = s.indexOf(" ",ind);
261 //    int ind3 = s.indexOf(")",ind);
262 //    if(ind3>-1 && ind3<ind2)
263 //      ind2 = ind3;
264 //    ind3 = s.indexOf(";",ind);
265 //    if(ind3>-1 && ind3<ind2)
266 //      ind2 = ind3;
267 
268 //    String midStr = s.substring(ind,ind2);
269 //    String endStr = s.substring(ind2);
270 
271 //    String srscmd = "http://srs.sanger.ac.uk/srsbin/cgi-bin/wgetz?-e+" +
272 //                    "["+midStr+"]";
273 
274 //    s = startStr + "<a href=\""+srscmd+"\">" +
275 //        midStr   + "</a>" + endStr;
276 //  }
277 
278     int ind = 0;
279     while((ind = s.indexOf(db, ind)) > -1)
280     {
281       s = setHyperLinks(s,ind);
282       ind = s.lastIndexOf("</a>");
283     }
284 
285     db = db.toLowerCase();
286     ind = 0;
287     while((ind = s.indexOf(db+":", ind)) > -1)
288     {
289       s = setHyperLinks(s,ind);
290       ind = s.lastIndexOf("</a>");
291     }
292 
293     return s;
294   }
295 
setHyperLinks(String s, int ind)296   private String setHyperLinks(String s, int ind)
297   {
298     String startStr = s.substring(0,ind);
299     int ind2 = s.indexOf(" ",ind);
300     if(ind2 == -1)
301       ind2 = s.indexOf(";",ind);
302 
303     int ind3 = s.indexOf(")",ind);
304     if(ind3>-1 && ind3<ind2)
305       ind2 = ind3;
306     ind3 = s.indexOf(";",ind);
307     if(ind3>-1 && ind3<ind2)
308       ind2 = ind3;
309     ind3 = s.indexOf("\"",ind);
310     if(ind3>-1 && ind3<ind2)
311       ind2 = ind3;
312 
313     String midStr = s.substring(ind,ind2);
314     String endStr = s.substring(ind2);
315     String srscmd = DataCollectionPane.srs_url+"/wgetz?-e+["+midStr+"]";
316 
317     // link to uniprot accession
318     if( (ind2 = srscmd.indexOf("UniProt:")) > -1)
319       srscmd = srscmd.substring(0,ind2+7)+"-acc:"+
320                srscmd.substring(ind2+8);
321 
322     if(srscmd.indexOf("ebi.ac.uk") > -1)
323       srscmd = srscmd + "+-vn+2";
324 
325     return  startStr + "<a href=\""+srscmd+"\">" +
326             midStr   + "</a>" + endStr;
327   }
328 
329   /*private void replaceRange(String newStr,int start,int end)
330   {
331     HTMLDocument doc = (HTMLDocument)getDocument();
332 
333     try
334     {
335       doc.remove(start,(end-start));
336       insert(newStr,start);
337     }
338     catch(BadLocationException ble)
339     {
340       ble.printStackTrace();
341     }
342     setDocument(doc);
343   }*/
344 
345 
346   /**
347   *
348   * Deletes the annotation line that contains an ID.
349   *
350   */
deleteGo(String id, String go_id)351   protected void deleteGo(String id, String go_id)
352   {
353     String txt = getText();
354     int ind1  = 0;
355     int ind2  = 0;
356     int indID = 0;
357 
358     while((ind2 = txt.indexOf("<br>",ind1)) > -1 ||
359           (ind2 = txt.indexOf("</body>",ind1)) > -1)
360     {
361       String line = txt.substring(ind1,ind2);
362 
363       if( ((indID = line.indexOf(id)) > -1) &&
364           (line.indexOf(go_id) > -1) )
365         break;
366       else
367         ind1 = ind2+1;
368     }
369 
370 //  ind2 = txt.indexOf("<br>",indID);
371 
372     if(ind2 == -1 || ind2 > txt.length())
373       ind2 = txt.length();
374 
375     if(ind1 == 0)
376       return;
377 
378     setText(txt.substring(0,ind1-1)+txt.substring(ind2));
379   }
380 
381   /**
382   *
383   * Deletes the annotation similarity line that contains an ID.
384   *
385   */
delete(String id, boolean ortholog)386   protected void delete(String id, boolean ortholog)
387   {
388     String txt = getText();
389 
390     int ind1  = 0;
391     int ind2  = 0;
392     int indID = 0;
393     String line = null;
394 
395     while((ind2 = txt.indexOf("<br>",ind1)) > -1 ||
396           (ind2 = txt.indexOf("</body>",ind1)) > -1)
397     {
398       line = txt.substring(ind1,ind2);
399 
400       if((line.indexOf("/similarity=") > -1) &&
401          ((indID = line.indexOf(id)) > -1) &&
402          (line.indexOf("GO:") == -1) )
403         break;
404       else
405         ind1 = ind2+1;
406     }
407 
408     // if ortholog then delete gene and product lines as well
409     if(ortholog)
410     {
411       if(ind1 > -1)
412         ind2 = txt.indexOf("/product=",ind1);
413       else
414         ind2 = txt.indexOf("/product=");
415 
416       if(ind2 > -1)
417         ind2 = txt.indexOf("<br>",ind2+4);
418     }
419 
420     if(ind2 == -1 || ind2 > txt.length())
421       ind2 = txt.length();
422 
423     if(ind1 == 0)
424       return;
425 
426     setText(txt.substring(0,ind1-1)+txt.substring(ind2));
427   }
428 
429 
430 
431   /**
432   *
433   * Deletes the annotation note line that contains an ID.
434   *
435   */
deleteNote()436   protected void deleteNote()
437   {
438     String txt = getText();
439 
440     int ind1  = 0;
441     int ind2  = 0;
442     int indID = 0;
443     String line = null;
444 
445     while((ind2 = txt.indexOf("<br>",ind1)) > -1 ||
446           (ind2 = txt.indexOf("</body>",ind1)) > -1)
447     {
448       line = txt.substring(ind1,ind2);
449 
450       if(line.indexOf("/note=&quot;Similar to ") > -1)
451         break;
452       else
453         ind1 = ind2+1;
454     }
455 
456     if(ind2 == -1 || ind2 > txt.length())
457       ind2 = txt.length();
458 
459     if(ind1 == 0)
460       return;
461 
462     setText(txt.substring(0,ind1-1)+txt.substring(ind2));
463   }
464 
465 
setUpSRSFrame(URL url, String search)466   protected void setUpSRSFrame(URL url, String search)
467                  throws IOException
468   {
469     if(BigPane.srsFrame == null)
470     {
471       BigPane.setUpSRSFrame((2*desktop.getHeight())/3,desktop);
472       Border loweredbevel = BorderFactory.createLoweredBevelBorder();
473       Border raisedbevel = BorderFactory.createRaisedBevelBorder();
474       Border compound = BorderFactory.createCompoundBorder(raisedbevel,loweredbevel);
475 
476       JTextField statusField = new JTextField();
477       statusField.setBorder(compound);
478       statusField.setEditable(false);
479       BigPane.srsFrame.getContentPane().add(statusField, BorderLayout.SOUTH);
480     }
481 
482     Annotation edPane = new Annotation(url);
483     JScrollPane jsp = new JScrollPane(edPane);
484     JTabbedPane jtab = (JTabbedPane)BigPane.srsFrame.getContentPane().getComponent(0);
485     jtab.insertTab(search, null,jsp,null,0);
486     BigPane.srsFrame.setVisible(true);
487   }
488 
goBack()489   protected void goBack()
490   {
491     if(back.size() < 2)
492       return;
493 
494     try
495     {
496       URL url = (URL)back.get(back.size()-2);
497       back.remove(back.size()-1);
498       setPage(url);
499     }
500     catch(IOException ioe)
501     {
502       ioe.printStackTrace();
503     }
504   }
505 
506   /**
507   *
508   * Method to handle hyper link events.
509   * @param event        hyper link event
510   *
511   */
hyperlinkUpdate(HyperlinkEvent event)512   public void hyperlinkUpdate(HyperlinkEvent event)
513   {
514     if(event.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
515     {
516       setCursor(cbusy);
517       try
518       {
519         URL url = event.getURL();
520 
521         int ind1 = event.getDescription().indexOf("[");
522         int ind2 = event.getDescription().lastIndexOf("]");
523 
524         String search = "";
525         if(ind1 > -1 && ind2 > -1)
526           search = event.getDescription().substring(ind1+1,ind2);
527         else
528         {
529           ind1 = event.getDescription().indexOf("=")+1; // genedb
530           if(ind1 > -1)
531             search = event.getDescription().substring(ind1);
532         }
533 
534         if(desktop != null)
535         {
536           if(BigPane.srsTabPane.isSelected())
537             setUpSRSFrame(url,search);
538 
539           if(BigPane.srsWin.isSelected())
540           {
541             int hgt = (2*desktop.getHeight())/3;
542             Annotation edPane = new Annotation(url);
543             JScrollPane jsp = new JScrollPane(edPane);
544             JInternalFrame jif = new JInternalFrame("SRS "+search,
545                                                    true, //resizable
546                                                    true, //closable
547                                                    true, //maximizable
548                                                    true);//iconifiable);
549             JMenuBar menuBar = new JMenuBar();
550             menuBar.add(new CommonMenu(jif));
551             jif.setJMenuBar(menuBar);
552             jif.getContentPane().add(jsp);
553             jif.setLocation(0,0);
554             jif.setSize(800,hgt);
555             jif.setVisible(true);
556             desktop.add(jif);
557           }
558 
559           if(BigPane.srsBrowser.isSelected())
560             BrowserControl.displayURL(event.getDescription());
561         }
562         else
563         {
564           setPage(url);
565           back.add(url);
566         }
567       }
568       catch(IOException ioe)
569       {
570         String msg = event.getDescription();
571         if(msg.length() > 50)
572           msg = msg.substring(0,50)+"....";
573 
574         JOptionPane.showMessageDialog(this,
575                        "Cannot reach URL:\n"+msg,
576                        "Cannot Connect",
577                        JOptionPane.INFORMATION_MESSAGE);
578 //      ioe.printStackTrace();
579 //      ("Can't follow link to " +
580 //                event.getURL().toExternalForm() );
581       }
582 
583       setCursor(cdone);
584     }
585     else if(event.getEventType() == HyperlinkEvent.EventType.ENTERED)
586     {
587       try
588       {
589         JTextField statusField = (JTextField)BigPane.srsFrame.getContentPane().getComponent(1);
590         statusField.setText(event.getDescription());
591       }
592       catch(Exception exp){}
593 
594     }
595     else if(event.getEventType() == HyperlinkEvent.EventType.EXITED)
596     {
597       try
598       {
599         JTextField statusField = (JTextField)BigPane.srsFrame.getContentPane().getComponent(1);
600         statusField.setText("");
601       }
602       catch(Exception exp){}
603 
604     }
605 
606   }
607 
608   /**
609   *
610   * Popup menu listener
611   *
612   */
613   class PopupListener extends MouseAdapter
614   {
mousePressed(MouseEvent e)615     public void mousePressed(MouseEvent e)
616     {
617       maybeShowPopup(e);
618     }
619 
mouseReleased(MouseEvent e)620     public void mouseReleased(MouseEvent e)
621     {
622       maybeShowPopup(e);
623     }
624 
maybeShowPopup(MouseEvent e)625     private void maybeShowPopup(MouseEvent e)
626     {
627       if(e.isPopupTrigger() && back.size() > 1)
628         popup.show(e.getComponent(),
629                 e.getX(), e.getY());
630     }
631   }
632 
633 }
634 
635