1 /********************************************************************
2 *
3 *  This library is free software; you can redistribute it and/or
4 *  modify it under the terms of the GNU Library General Public
5 *  License as published by the Free Software Foundation; either
6 *  version 2 of the License, or (at your option) any later version.
7 *
8 *  This library is distributed in the hope that it will be useful,
9 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 *  Library General Public License for more details.
12 *
13 *  You should have received a copy of the GNU Library General Public
14 *  License along with this library; if not, write to the
15 *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 *  Boston, MA  02111-1307, USA.
17 *
18 *  @author: Copyright (C) Tim Carver
19 *
20 ********************************************************************/
21 
22 
23 package org.emboss.jemboss.draw;
24 
25 import javax.swing.*;
26 import java.awt.*;
27 import java.awt.print.*;
28 import java.awt.event.*;
29 import java.awt.geom.AffineTransform;
30 import java.util.*;
31 import java.awt.datatransfer.*;
32 import java.awt.dnd.*;
33 import java.net.URL;
34 
35 import org.emboss.jemboss.gui.ScrollPanel;
36 import org.emboss.jemboss.gui.Browser;
37 
38 public class DNADraw extends ScrollPanel
39                      implements Printable, DragGestureListener,
40                      DragSourceListener, DropTargetListener
41 {
42 
43   public static JScrollPane jsp;
44   private DNADraw current_dna;
45   private JFrame mainFrame;
46 
47   private Point location    = new Point(75,75);
48   private Dimension border  = new Dimension(150,150);
49   private Dimension panelSize = new Dimension(600,600);
50   private Dimension linearPanelSize = new Dimension(800,350);
51   private Hashtable lineAttr;
52   private Vector minorTicks;
53   private Vector majorTicks;
54   private Vector block;
55   private Vector restrictionEnzyme;
56 
57   private int startTick    = 0;
58   private int minorTick    = 100;
59   private int majorTick    = 500;
60 
61 //
62 // store the tick positions -- there appears to be
63 // a bug in AffineTransform when it comes to using
64 // elements from the matrix when printing
65 //
66   private int[] tickMajorXPositions;
67   private int[] tickMajorYPositions;
68 
69   private int[] tickMinorXPositions;
70   private int[] tickMinorYPositions;
71 
72   private int[] reXPositions;
73   private int[] reYPositions;
74   private boolean close = false;
75 
DNADraw()76   public DNADraw()
77   {
78     super(new BorderLayout());
79     current_dna = this;
80     setBackground(Color.white);
81     setPreferredSize(panelSize);
82     setOpaque(false);
83 
84     DragSource dragSource = DragSource.getDefaultDragSource();
85     dragSource.createDefaultDragGestureRecognizer(
86        this,                             // component where drag originates
87        DnDConstants.ACTION_COPY_OR_MOVE, // actions
88        this);
89     setDropTarget(new DropTarget(this,this));
90     lineAttr = new Hashtable();
91     lineAttr.put("start",new Integer(0));
92     lineAttr.put("end",new Integer(4000));
93     lineAttr.put("lsize",new Integer(5));
94     lineAttr.put("circular",new Boolean(true));
95 
96     MouseListener mouseListener = new MouseAdapter()
97     {
98       public void mouseClicked(MouseEvent me)
99       {
100         if(me.getClickCount() == 2 &&
101            !me.isPopupTrigger())
102         {
103           for(int i=0; i<getComponentCount(); i++)
104           {
105             if(getComponent(i) instanceof Block)
106             {
107               final Block drawBlock = (Block)getComponent(i);
108               if(drawBlock.isOverMe(me.getX(),me.getY()))
109               {
110                 final JFrame f = new JFrame("Properties");
111                 JButton butt = new JButton("Delete");
112                 butt.addActionListener(new ActionListener()
113                 {
114                   public void actionPerformed(ActionEvent e)
115                   {
116                     remove(drawBlock);
117                     current_dna.repaint();
118                     f.setVisible(false);
119                     f.dispose();
120                     Enumeration enumBk = block.elements();
121                     int nelement = 0;
122                     while(enumBk.hasMoreElements())
123                     {
124                       Vector v = (Vector)enumBk.nextElement();
125                       if(v.contains(drawBlock))
126                         block.removeElementAt(nelement);
127                       nelement++;
128                     }
129                   }
130                 });
131                 drawBlock.showProperties(f,DNADraw.this,butt);
132               }
133             }
134           }
135 
136         }
137       }
138     };
139     this.addMouseListener(mouseListener);
140   }
141 
142 
DNADraw(Vector minorTicks, Vector majorTicks, Vector block, Vector restrictionEnzyme)143   public DNADraw(Vector minorTicks, Vector majorTicks,
144                  Vector block,
145                  Vector restrictionEnzyme)
146   {
147     this();
148     this.minorTicks = minorTicks;
149     this.block = block;
150     this.restrictionEnzyme = restrictionEnzyme;
151   }
152 
153 
DNADraw(Vector block, Vector restrictionEnzyme, Hashtable lineAttr, int startTick, int minorTick, int majorTick)154   public DNADraw(Vector block, Vector restrictionEnzyme,
155                  Hashtable lineAttr, int startTick,
156                  int minorTick, int majorTick)
157   {
158     this();
159     this.block = block;
160     this.restrictionEnzyme = restrictionEnzyme;
161     this.lineAttr     = lineAttr;
162     this.startTick    = startTick;
163     this.minorTick    = minorTick;
164     this.majorTick    = majorTick;
165 
166     if(!isCircular())
167       setPreferredSize(linearPanelSize);
168 
169     calculateTickPosistions();
170   }
171 
172 
173   /**
174   *
175   * Get the width/diameter of the DNA map
176   *
177   */
getDiameter()178   protected double getDiameter()
179   {
180     return getWidth()-border.getWidth();
181   }
182 
183 
getLocationPoint()184   protected Point getLocationPoint()
185   {
186     return location;
187   }
188 
189 
zoomIn()190   protected void zoomIn()
191   {
192     int wid = getWidth();
193     wid     = wid+(int)(wid*0.1);
194     int hgt = getHeight();
195     if(isCircular())
196       hgt = hgt+(int)(hgt*0.1);
197     zoom(wid,hgt);
198   }
199 
200 
zoomOut()201   protected void zoomOut()
202   {
203     int wid = getWidth();
204     wid     = wid-(int)(wid*0.1);
205     int hgt = getHeight();
206     if(isCircular())
207       hgt = hgt-(int)(hgt*0.1);
208     zoom(wid,hgt);
209   }
210 
211 
zoom(int wid, int hgt)212   private void zoom(int wid, int hgt)
213   {
214     if(isCircular())
215     {
216       panelSize = new Dimension(wid,hgt);
217       setPreferredSize(panelSize);
218       setSize(panelSize);
219     }
220     else
221     {
222       linearPanelSize = new Dimension(wid,hgt);
223       setPreferredSize(linearPanelSize);
224       setSize(linearPanelSize);
225     }
226     repaint();
227   }
228 
229 
paintComponent(Graphics g)230   protected void paintComponent(Graphics g)
231   {
232     super.paintComponent(g);
233     Graphics2D g2 = (Graphics2D)g;
234 
235     if(isCircular())
236       drawCircularPanel(g2,true);
237     else
238       drawLinearPanel(g2);
239   }
240 
241 
isCircular()242   protected boolean isCircular()
243   {
244     return ((Boolean)lineAttr.get("circular")).booleanValue();
245   }
246 
247 
addBlock(Block b)248   protected void addBlock(Block b)
249   {
250     add(b);
251     validate();
252   }
253 
254 
drawLinearPanel(Graphics2D g2)255   protected void drawLinearPanel(Graphics2D g2)
256   {
257     FontMetrics fm = g2.getFontMetrics();
258     double hgt = fm.getAscent();
259     g2.setColor(Color.black);
260     double widDash = 4;
261 
262     int lineSize = 5;
263     try
264     {
265       lineSize = getLineSize();
266     }
267     catch(NullPointerException npe)
268     {
269       System.out.println("No line size specified using default!");
270     }
271     g2.setStroke(new BasicStroke((float)lineSize));
272 
273     double widthPanel  = getWidth();
274     double ddiameter  = widthPanel-border.getWidth();
275     int diameter = (int)ddiameter;
276     int ymid = getHeight()/2;
277 
278     g2.setStroke(new BasicStroke((float)lineSize));
279     g2.drawLine(location.x,ymid,
280                 diameter,ymid);
281 
282     int start = getStart();
283     int end   = getEnd();
284 
285     g2.setColor(Color.black);
286     g2.setStroke(new BasicStroke(1.f));
287 
288     if(majorTicks == null || minorTicks == null)
289       calculateTickPosistions();
290 
291     Enumeration enumTk = minorTicks.elements();
292     while(enumTk.hasMoreElements())
293     {
294       int tick = ((Integer)enumTk.nextElement()).intValue();
295       int x = ((diameter-location.x)*(tick-start)/(end-start))+location.x;
296       int y = ymid+(int)((lineSize+widDash)/2);
297       g2.drawLine(x,ymid,x,y);
298     }
299 
300     enumTk = majorTicks.elements();
301     while(enumTk.hasMoreElements())
302     {
303       int tick = ((Integer)enumTk.nextElement()).intValue();
304       int x = ((diameter-location.x)*(tick-start)/(end-start))+location.x;
305       int y = ymid+(lineSize/2)+(int)widDash;
306       g2.drawLine(x,ymid,x,y);
307       String label = Integer.toString(tick);
308       x-=(fm.stringWidth(label)/2);
309       y+=hgt;
310       g2.drawString(label,x,y);
311     }
312 
313     if(restrictionEnzyme != null)
314     {
315       enumTk = restrictionEnzyme.elements();
316       while(enumTk.hasMoreElements())
317       {
318         Vector re = (Vector)enumTk.nextElement();
319         String reLabel = (String)re.elementAt(0);
320         int pos = ((Integer)re.elementAt(1)).intValue();
321         g2.setColor((Color)re.elementAt(2));
322         int x = ((diameter-location.x)*(pos-start)/(end-start))+location.x;
323         int y = ymid-(lineSize/2)-(int)widDash;
324         g2.drawLine(x,ymid,x,y);
325         x-=(fm.stringWidth(reLabel)/2);
326         y-=hgt;
327         g2.drawString(reLabel,x,y);
328       }
329     }
330 
331   }
332 
drawCircularPanel(Graphics2D g2, boolean record)333   protected void drawCircularPanel(Graphics2D g2, boolean record)
334   {
335     g2.setColor(Color.black);
336 
337     FontMetrics fm = g2.getFontMetrics();
338     double hgt = fm.getAscent();
339     double widthPanel  = getWidth();
340     double heightPanel = getHeight();
341 
342     double rad = 360.d;
343     double pi  = Math.PI;
344     double widDash = 4;
345 
346     double ddiameter  = widthPanel-border.getWidth();
347     double ddiameter2 = ddiameter/2.d;
348     int diameter = (int)ddiameter;
349 
350     int lineSize = 5;
351     try
352     {
353       lineSize = getLineSize();
354     }
355     catch(NullPointerException npe)
356     {
357       System.out.println("No line size specified using default!");
358     }
359 
360     g2.setStroke(new BasicStroke((float)lineSize));
361     g2.drawArc(location.x,location.y,
362                diameter,diameter,0,360);
363 
364     AffineTransform origin = g2.getTransform();
365     AffineTransform newOrig;
366 
367     if(restrictionEnzyme != null)
368     {
369       if(record)
370       {
371         int nsize = restrictionEnzyme.size();
372         reXPositions = new int[nsize];
373         reYPositions = new int[nsize];
374       }
375       Enumeration enumRes = restrictionEnzyme.elements();
376       while(enumRes.hasMoreElements())
377       {
378         Vector re = (Vector)enumRes.nextElement();
379         String reLabel = (String)re.elementAt(0);
380         int pos = ((Integer)re.elementAt(1)).intValue();
381         g2.setColor((Color)re.elementAt(2));
382         double ang = getAngleFromPosition(pos,rad);
383 
384         newOrig = (AffineTransform)(origin.clone());
385         newOrig.rotate(Math.toRadians(-ang),
386                        widthPanel/2.d,heightPanel/2.d);
387 
388         int widLabel  = (lineSize+fm.stringWidth(reLabel))/2;
389         int widREDash = (int)(widDash+widDash+lineSize)+widLabel;
390 
391         int x = 0;
392         int y = 0;
393         if(record)
394         {
395           x = (int)( ddiameter2 + (newOrig.getScaleX()*
396                        (ddiameter2 + 10 + widLabel + widREDash) ) -
397                        widLabel );
398           y = (int)( ddiameter2 + (newOrig.getShearY()*
399                        (ddiameter2 + 10 + widREDash + (hgt/2.d)) ) +
400                        hgt/2.d );
401 
402           int index = restrictionEnzyme.indexOf(re);
403           reXPositions[index] = x;
404           reYPositions[index] = y;
405         }
406         else
407         {
408           int index = restrictionEnzyme.indexOf(re);
409           x = reXPositions[index];
410           y = reYPositions[index];
411         }
412 
413         g2.drawString(reLabel,location.x+x,location.y+y);
414         g2.setTransform(newOrig);
415         g2.setStroke(new BasicStroke(1.f));
416         int xLine = location.x+(int)(ddiameter);
417         int yLine = location.y+(int)(ddiameter/2.d);
418         g2.drawLine(xLine,yLine,(int)(xLine+widREDash),yLine);
419         g2.setTransform(origin);
420       }
421     }
422 
423     if(majorTicks == null || minorTicks == null)
424       calculateTickPosistions();
425     //major ticks
426     drawCircularTicks(g2,ddiameter,ddiameter2,diameter,origin,
427                       widthPanel,heightPanel,rad,pi,widDash,fm,
428                       lineSize,record,majorTicks,false);
429 
430 
431     //minor ticks
432     drawCircularTicks(g2,ddiameter,ddiameter2,diameter,origin,
433                       widthPanel,heightPanel,rad,pi,widDash/2,fm,
434                       lineSize,record,minorTicks,true);
435   }
436 
437 
drawCircularTicks(Graphics2D g2, double ddiameter, double ddiameter2, int diameter, AffineTransform origin, double widthPanel,double heightPanel, double rad, double pi, double widDash, FontMetrics fm, int lineSize, boolean record, Vector ticks, boolean smallTicks)438   private void drawCircularTicks(Graphics2D g2, double ddiameter,
439             double ddiameter2, int diameter, AffineTransform origin,
440             double widthPanel,double heightPanel, double rad, double pi,
441             double widDash, FontMetrics fm, int lineSize,
442             boolean record, Vector ticks, boolean smallTicks)
443   {
444 
445     double hgt = fm.getAscent();
446 
447     g2.setColor(Color.black);
448     if(record)
449     {
450       int nsize = ticks.size();
451 
452       if(smallTicks)
453       {
454         tickMinorXPositions = new int[nsize];
455         tickMinorYPositions = new int[nsize];
456       }
457       else
458       {
459         tickMajorXPositions = new int[nsize];
460         tickMajorYPositions = new int[nsize];
461       }
462     }
463 
464     AffineTransform newOrig;
465     Enumeration enumTk = ticks.elements();
466     while(enumTk.hasMoreElements())
467     {
468       int tick = ((Integer)enumTk.nextElement()).intValue();
469       double theta = Math.toRadians(-getAngleFromPosition(tick,rad));
470       if(theta > pi)
471         theta = theta - pi*2.d;
472 
473       newOrig = (AffineTransform)(origin.clone());
474 
475       // rotate and add tick mark
476       newOrig.rotate(theta,widthPanel/2.d,heightPanel/2.d);
477       String label = Integer.toString(tick);
478       double wid = fm.stringWidth(label);
479 
480       int x = 0;
481       int y = 0;
482       if(record)
483       {
484         x = (int)( (ddiameter2) + (newOrig.getScaleX()*
485                    (widDash+lineSize+3+(diameter+wid)/2.d)) - (wid/2.d));
486 
487         y = (int)( (ddiameter2) + (newOrig.getShearY()*
488                    (widDash+lineSize+3+(diameter+hgt)/2.d)) + (hgt/2.d));
489 
490         int index = ticks.indexOf(new Integer(tick));
491 
492         if(smallTicks)
493         {
494           tickMinorXPositions[index] = x;
495           tickMinorYPositions[index] = y;
496         }
497         else
498         {
499           tickMajorXPositions[index] = x;
500           tickMajorYPositions[index] = y;
501         }
502       }
503       else    // use stored positions for printing
504       {
505         int index = ticks.indexOf(new Integer(tick));
506         if(smallTicks)
507         {
508           x = tickMinorXPositions[index];
509           y = tickMinorYPositions[index];
510         }
511         {
512           x = tickMajorXPositions[index];
513           y = tickMajorYPositions[index];
514         }
515       }
516 
517       if(!smallTicks)        // add tick label
518         g2.drawString(label,
519                     location.x+x,
520                     location.y+y);
521 
522       g2.setTransform(newOrig);
523 
524       g2.setStroke(new BasicStroke(1.f));
525       int xLine = location.x+(int)(ddiameter);
526       int yLine = location.y+(int)(ddiameter/2.d);
527       g2.drawLine(xLine,yLine,(int)(xLine+lineSize+widDash),yLine);
528 
529 /*
530       System.out.println("THETA "+Math.toDegrees(theta));
531       System.out.println("m00 "+newOrig.getScaleX()+
532                          " m01 "+newOrig.getShearX()+
533                          " m02 "+newOrig.getTranslateX());
534       System.out.println("m10 "+newOrig.getScaleY()+
535                          " m12 "+newOrig.getTranslateY());
536 */
537       g2.setTransform(origin);
538     }
539 
540     return;
541   }
542 
543 
544   /**
545   *
546   * Calculate the tick marks to be drawn
547   *
548   */
calculateTickPosistions()549   protected void calculateTickPosistions()
550   {
551     minorTicks = new Vector();
552     majorTicks = new Vector();
553     int start = getStart();
554     int end   = getEnd();
555 
556     if(majorTick == 0)
557       return;
558 
559     for(int i=startTick; i<end; i+=majorTick)
560       if(i >= start)
561         majorTicks.add(new Integer(i));
562 
563     if(minorTick == 0)
564       return;
565 
566     for(int i=startTick; i<end; i+=minorTick)
567     {
568       Integer tk = new Integer(i);
569       if(i >= start && !majorTicks.contains(tk))
570         minorTicks.add(tk);
571     }
572   }
573 
574 
575   /**
576   *
577   * Return the position tick marks start at
578   *
579   */
getStartTick()580   protected int getStartTick()
581   {
582     return startTick;
583   }
584 
585 
586   /**
587   *
588   * Set the position tick marks start at
589   *
590   */
setStartTick(int startTick)591   protected boolean setStartTick(int startTick)
592   {
593     this.startTick = startTick;
594     if((startTick >= getStart()) && (startTick < getEnd()))
595       return true;
596 
597     return false;
598   }
599 
600 
601   /**
602   *
603   * Return the interval for the tick marks
604   *
605   */
getTickInterval()606   protected int getTickInterval()
607   {
608     return majorTick;
609   }
610 
611 
612   /**
613   *
614   * Set the interval for the tick marks
615   *
616   */
setTickInterval(int majorTick)617   protected boolean setTickInterval(int majorTick)
618   {
619     if(majorTick < (getEnd()-getStart()))
620     {
621       this.majorTick = majorTick;
622       return true;
623     }
624     return false;
625   }
626 
627 
628   /**
629   *
630   * Return the interval for the tick marks
631   *
632   */
getMinorTickInterval()633   protected int getMinorTickInterval()
634   {
635     return minorTick;
636   }
637 
638 
639   /**
640   *
641   * Set the interval for the tick marks
642   *
643   */
setMinorTickInterval(int minorTick)644   protected boolean setMinorTickInterval(int minorTick)
645   {
646     if(minorTick < (getEnd()-getStart()))
647     {
648       this.minorTick = minorTick;
649       return true;
650     }
651     return false;
652   }
653 
654 
655   /**
656   *
657   * Return an angle in degrees
658   *
659   */
getAngleFromPosition(int pos,double rad)660   protected double getAngleFromPosition(int pos,double rad)
661   {
662     int start = getStart();
663     int end   = getEnd();
664     return - ((pos-start)*rad)/(end-start);
665   }
666 
667 
668   /**
669   *
670   * The method @print@ must be implemented for @Printable@ interface.
671   * Parameters are supplied by system.
672   *
673   */
print(Graphics g, PageFormat pf, int pageIndex)674   public int print(Graphics g, PageFormat pf, int pageIndex)
675                                        throws PrinterException
676   {
677     Graphics2D g2 = (Graphics2D)g;
678     g2.setColor(Color.black);    //set default foreground color to black
679 
680     RepaintManager.currentManager(this).setDoubleBufferingEnabled(false);
681     Dimension d = this.getSize();    //get size of document
682     double panelWidth  = d.width;    //width in pixels
683     double panelHeight = d.height;   //height in pixels
684     double pageHeight = pf.getImageableHeight();   //height of printer page
685     double pageWidth  = pf.getImageableWidth();    //width of printer page
686     double scale = pageWidth/panelWidth;
687     int totalNumPages = (int)Math.ceil(scale * panelHeight / pageHeight);
688     // Make sure not print empty pages
689     if(pageIndex >= totalNumPages)
690      return Printable.NO_SUCH_PAGE;
691 
692     // Shift Graphic to line up with beginning of print-imageable region
693     g2.translate(pf.getImageableX(), pf.getImageableY());
694     // Shift Graphic to line up with beginning of next page to print
695     g2.translate(0f, -pageIndex*pageHeight);
696     // Scale the page so the width fits...
697     g2.scale(scale, scale);
698     drawAll(g2,false);
699     return Printable.PAGE_EXISTS;
700   }
701 
drawAll(Graphics2D g2, boolean l)702   public void drawAll(Graphics2D g2, boolean l)
703   {
704     if(((Boolean)lineAttr.get("circular")).booleanValue())
705       drawCircularPanel(g2,l);   //repaint the page for printing
706     else
707       drawLinearPanel(g2);
708     for(int i=0; i<getComponentCount(); i++)
709     {
710       if(getComponent(i) instanceof Block)
711       {
712         System.out.println("Printing block "+i);
713         ((Block)getComponent(i)).draw(g2);
714       }
715     }
716   }
717 
718 
doPrintActions()719   public void doPrintActions()
720   {
721     PrinterJob pj=PrinterJob.getPrinterJob();
722     pj.setPrintable(this);
723     pj.printDialog();
724     try
725     {
726       pj.print();
727     }
728     catch (Exception PrintException) {}
729   }
730 
731 
setRestrictionEnzyme(Vector restrictionEnzyme)732   protected void setRestrictionEnzyme(Vector restrictionEnzyme)
733   {
734     this.restrictionEnzyme = restrictionEnzyme;
735   }
736 
setGeneticMarker(Vector block)737   protected void setGeneticMarker(Vector block)
738   {
739     this.block = block;
740   }
741 
getLineAttributes()742   protected Hashtable getLineAttributes()
743   {
744     return lineAttr;
745   }
746 
747 
setLineAttributes(Hashtable lineAttr)748   protected void setLineAttributes(Hashtable lineAttr)
749   {
750     this.lineAttr = lineAttr;
751   }
752 
753 
setLineSize(int lineSize)754   protected void setLineSize(int lineSize)
755   {
756     lineAttr.put("lsize",new Integer(lineSize));
757   }
758 
759 
getLineSize()760   protected int getLineSize()
761   {
762     return ((Integer)lineAttr.get("lsize")).intValue();
763   }
764 
setPlasmidLocation(int x,int y)765   public void setPlasmidLocation(int x,int y)
766   {
767     location.setLocation(x,y);
768   }
769 
770 
createMenuBar()771   public JMenuBar createMenuBar()
772   {
773     JMenuBar menuBar = new JMenuBar();
774 
775 // file menu
776     JMenu fileMenu = new JMenu("File");
777     fileMenu.setMnemonic(KeyEvent.VK_F);
778     menuBar.add(fileMenu);
779 
780     JMenuItem openMenu = new JMenuItem("Open");
781     openMenu.addActionListener(new ActionListener()
782     {
783       public void actionPerformed(ActionEvent e)
784       {
785         EmbossCirdnaReader dnaRead = new EmbossCirdnaReader();
786         block = dnaRead.getBlock();
787         restrictionEnzyme = dnaRead.getRestrictionEnzyme();
788 
789         lineAttr.put("start",new Integer(dnaRead.getStart()));
790         lineAttr.put("end",new Integer(dnaRead.getEnd()));
791 
792         current_dna = new DNADraw(block,restrictionEnzyme,
793                                   lineAttr,0,100,100);
794         jsp.setViewportView(current_dna);
795       }
796     });
797     fileMenu.add(openMenu);
798     fileMenu.add(new JSeparator());
799 
800 // print
801     JMenu printMenu = new JMenu("Print");
802     fileMenu.add(printMenu);
803 
804     JMenuItem print = new JMenuItem("Print Postscript");
805     print.setToolTipText("Print using available printers in your computer\n" +
806     		"or export image to a postscript file (if you have " +
807     		" installed postscript printers)");
808 
809     print.addActionListener(new ActionListener()
810     {
811       public void actionPerformed(ActionEvent e)
812       {
813         doPrintActions();
814       }
815     });
816     printMenu.add(print);
817 
818     JMenuItem printImage = new JMenuItem("Print png/jpeg Image...");
819     printImage.addActionListener(new ActionListener()
820     {
821       public void actionPerformed(ActionEvent e)
822       {
823         PrintDNAImage pdnai = new PrintDNAImage(current_dna);
824         pdnai.print();
825       }
826     });
827     printMenu.add(printImage);
828 
829 // print preview
830     JMenuItem printPreview = new JMenuItem("Print Preview...");
831     printPreview.addActionListener(new ActionListener()
832     {
833       public void actionPerformed(ActionEvent e)
834       {
835         PrintDNAImage pdnai = new PrintDNAImage(current_dna);
836         pdnai.printPreview();
837       }
838     });
839     fileMenu.add(printPreview);
840     fileMenu.add(new JSeparator());
841 
842 
843     JMenuItem fileMenuExit = new JMenuItem("Exit");
844     fileMenuExit.addActionListener(new ActionListener()
845     {
846       public void actionPerformed(ActionEvent e)
847       {
848         if(!close)
849           System.exit(0);
850         else
851         {
852           mainFrame.setVisible(false);
853           mainFrame.dispose();
854         }
855       }
856     });
857     fileMenu.add(fileMenuExit);
858 
859 // view menu
860     JMenu viewMenu = new JMenu("View");
861     menuBar.add(viewMenu);
862 
863     JMenuItem zoomIn = new JMenuItem("Zoom In");
864     zoomIn.setAccelerator(KeyStroke.getKeyStroke(
865                     KeyEvent.VK_I, ActionEvent.CTRL_MASK));
866     zoomIn.addActionListener(new ActionListener()
867     {
868       public void actionPerformed(ActionEvent e)
869       {
870         zoomIn();
871       }
872     });
873     viewMenu.add(zoomIn);
874 
875     JMenuItem zoomOut = new JMenuItem("Zoom Out");
876     zoomOut.setAccelerator(KeyStroke.getKeyStroke(
877                     KeyEvent.VK_O, ActionEvent.CTRL_MASK));
878     zoomOut.addActionListener(new ActionListener()
879     {
880       public void actionPerformed(ActionEvent e)
881       {
882         zoomOut();
883       }
884     });
885     viewMenu.add(zoomOut);
886 
887 // options menu
888     JMenu optionMenu = new JMenu("Options");
889     menuBar.add(optionMenu);
890 
891 
892     JMenuItem wizard = new JMenuItem("DNA Wizard");
893     wizard.addActionListener(new ActionListener()
894     {
895       public void actionPerformed(ActionEvent e)
896       {
897         Wizard wiz = new Wizard(current_dna);
898         current_dna = wiz.getDNADraw();
899         jsp.setViewportView(current_dna);
900       }
901     });
902     optionMenu.add(wizard);
903     optionMenu.add(new JSeparator());
904 
905     JMenuItem line = new JMenuItem("DNA attributes");
906     line.addActionListener(new ActionListener()
907     {
908       public void actionPerformed(ActionEvent e)
909       {
910         JFrame f = new JFrame("DNA Attributes");
911         LineAttribute la = new LineAttribute(current_dna);
912         JScrollPane laScroll = new JScrollPane(la);
913         JPanel laPane = (JPanel)f.getContentPane();
914         laPane.add(laScroll,BorderLayout.CENTER);
915         f.setJMenuBar(la.createMenuBar(f));
916         f.pack();
917         f.setVisible(true);
918       }
919     });
920     optionMenu.add(line);
921 
922 
923     JMenuItem tickMarks = new JMenuItem("Tick marks");
924     tickMarks.addActionListener(new ActionListener()
925     {
926       public void actionPerformed(ActionEvent e)
927       {
928         JFrame f = new JFrame("Tick Marks");
929         Ticks tk = new Ticks(current_dna,true);
930         JScrollPane tkScroll = new JScrollPane(tk);
931         JPanel tkPane = (JPanel)f.getContentPane();
932         tkPane.add(tkScroll,BorderLayout.CENTER);
933         f.setJMenuBar(tk.createMenuBar(f));
934         f.pack();
935         f.setVisible(true);
936       }
937     });
938     optionMenu.add(tickMarks);
939 
940 
941     JMenuItem gmarker = new JMenuItem("Genetic Features");
942     gmarker.addActionListener(new ActionListener()
943     {
944       public void actionPerformed(ActionEvent e)
945       {
946         JFrame f = new JFrame("Genetic Features");
947         GeneticMarker gm = new GeneticMarker(current_dna,
948                                              block);
949         JScrollPane gmScroll = new JScrollPane(gm);
950         JPanel gmPane = (JPanel)f.getContentPane();
951         gmPane.add(gmScroll,BorderLayout.CENTER);
952         f.setJMenuBar(gm.createMenuBar(f));
953         f.pack();
954         f.setVisible(true);
955       }
956     });
957     optionMenu.add(gmarker);
958 
959     JMenuItem reSites = new JMenuItem("Restriction Enzyme");
960     reSites.addActionListener(new ActionListener()
961     {
962       public void actionPerformed(ActionEvent e)
963       {
964         JFrame f = new JFrame("Restriction Enzyme");
965         RestrictionEnzyme re = new RestrictionEnzyme(current_dna,
966                                               restrictionEnzyme);
967         JScrollPane reScroll = new JScrollPane(re);
968         JPanel rePane = (JPanel)f.getContentPane();
969         rePane.add(reScroll,BorderLayout.CENTER);
970         f.setJMenuBar(re.createMenuBar(f));
971         f.pack();
972         f.setVisible(true);
973       }
974     });
975     optionMenu.add(reSites);
976 
977 // help manu
978     JMenu helpMenu = new JMenu("Help");
979     menuBar.add(helpMenu);
980 
981     JMenuItem aboutMenu = new JMenuItem("About");
982     helpMenu.add(aboutMenu);
983     aboutMenu.addActionListener(new ActionListener()
984     {
985       public void actionPerformed(ActionEvent e)
986       {
987         ClassLoader cl = this.getClass().getClassLoader();
988         try
989         {
990           URL inURL = cl.getResource("resources/readmeDNADraw.html");
991           new Browser(inURL,"resources/readmeAlign.html");
992         }
993         catch (Exception ex)
994         {
995           JOptionPane.showMessageDialog(null,
996                               "Jemboss Alignment Viewer Guide not found!",
997                               "Error", JOptionPane.ERROR_MESSAGE);
998         }
999       }
1000     });
1001 
1002     return menuBar;
1003   }
1004 
1005 
setCloseAndDispose(boolean close, JFrame mainFrame)1006   public void setCloseAndDispose(boolean close, JFrame mainFrame)
1007   {
1008     this.mainFrame = mainFrame;
1009     this.close = close;
1010   }
1011 
getGeneticMarker()1012   protected Vector getGeneticMarker()
1013   {
1014     return block;
1015   }
1016 
1017 
getRestrictionEnzyme()1018   protected Vector getRestrictionEnzyme()
1019   {
1020     return restrictionEnzyme;
1021   }
1022 
1023 
getStart()1024   protected int getStart()
1025   {
1026     return ((Integer)lineAttr.get("start")).intValue();
1027   }
1028 
1029 
getEnd()1030   protected int getEnd()
1031   {
1032     return ((Integer)lineAttr.get("end")).intValue();
1033   }
1034 
1035 
setStart(int start)1036   protected void setStart(int start)
1037   {
1038     lineAttr.put("start",new Integer(start));
1039     calculateTickPosistions();
1040   }
1041 
1042 
setEnd(int end)1043   protected void setEnd(int end)
1044   {
1045     lineAttr.put("end",new Integer(end));
1046     calculateTickPosistions();
1047   }
1048 
1049 ////////////////////
1050 // DRAG AND DROP
1051 ////////////////////
1052 // drag source
dragGestureRecognized(DragGestureEvent e)1053   public void dragGestureRecognized(DragGestureEvent e)
1054   {
1055     // ignore if mouse popup trigger
1056     InputEvent ie = e.getTriggerEvent();
1057     if(ie instanceof MouseEvent)
1058       if(((MouseEvent)ie).isPopupTrigger())
1059         return;
1060 
1061     Point loc = e.getDragOrigin();
1062     Component c = getComponentAt(loc);
1063 
1064     if(c instanceof Block)
1065     {
1066 //    System.out.println("BLOCK DRAG GESTURE");
1067 
1068       for(int i=0; i<getComponentCount(); i++)
1069       {
1070         if(getComponent(i) instanceof Block)
1071         {
1072           Block drawBlock = (Block)getComponent(i);
1073           if(drawBlock.isOverMe(loc.x,loc.y))
1074              e.startDrag(DragSource.DefaultCopyDrop,  // cursor
1075                    (Transferable)drawBlock,           // transferable data
1076                    this);                             // drag source listener
1077         }
1078       }
1079     }
1080   }
1081 
dragDropEnd(DragSourceDropEvent e)1082   public void dragDropEnd(DragSourceDropEvent e) {}
dragEnter(DragSourceDragEvent e)1083   public void dragEnter(DragSourceDragEvent e) {}
dragExit(DragSourceEvent e)1084   public void dragExit(DragSourceEvent e) {}
dragOver(DragSourceDragEvent e)1085   public void dragOver(DragSourceDragEvent e) {}
dropActionChanged(DragSourceDragEvent e)1086   public void dropActionChanged(DragSourceDragEvent e) {}
1087 
1088 // drop sink
dragEnter(DropTargetDragEvent e)1089   public void dragEnter(DropTargetDragEvent e)
1090   {
1091     if(e.isDataFlavorSupported(Block.BLOCK))
1092       e.acceptDrag(DnDConstants.ACTION_COPY_OR_MOVE);
1093   }
1094 
drop(DropTargetDropEvent e)1095   public void drop(DropTargetDropEvent e)
1096   {
1097     Transferable t = e.getTransferable();
1098     if(t.isDataFlavorSupported(Block.BLOCK))
1099     {
1100       try
1101       {
1102         Point loc = e.getLocation();
1103         Block drawBlock = (Block)t.getTransferData(Block.BLOCK);
1104 
1105         for(int i=0; i<getComponentCount(); i++)
1106           if(getComponent(i) instanceof Block)
1107           {
1108             Block c = (Block)getComponent(i);
1109             if( c.getLabel().equals(drawBlock.getLabel()) &&
1110                 c.getStart() == drawBlock.getStart() &&
1111                 c.getEnd() == drawBlock.getEnd() )
1112               c.setBlockLocation(loc.x,loc.y);
1113           }
1114       }
1115       catch(Exception ufe){}
1116     }
1117   }
1118 
dragOver(DropTargetDragEvent e)1119   public void dragOver(DropTargetDragEvent e)
1120   {
1121   }
1122 
dropActionChanged(DropTargetDragEvent e)1123   public void dropActionChanged(DropTargetDragEvent e) {}
dragExit(DropTargetEvent e)1124   public void dragExit(DropTargetEvent e){}
1125 
main(String arg[])1126   public static void main(String arg[])
1127   {
1128     Wizard wiz = new Wizard(null);
1129     DNADraw dna = wiz.getDNADraw();
1130 
1131     JFrame f = new JFrame("DNA Viewer");
1132 
1133     Dimension d = f.getToolkit().getScreenSize();
1134 
1135     Vector minTicks = new Vector();
1136     minTicks.add(new Integer(1200));
1137     minTicks.add(new Integer(1600));
1138     minTicks.add(new Integer(2000));
1139     minTicks.add(new Integer(2500));
1140     minTicks.add(new Integer(3000));
1141     minTicks.add(new Integer(3500));
1142     minTicks.add(new Integer(4070));
1143     minTicks.add(new Integer(4500));
1144     minTicks.add(new Integer(5070));
1145     Vector majTicks = new Vector();
1146 
1147     Vector marker = new Vector();
1148     Vector block = new Vector();
1149     marker.add(new String("CDS"));
1150     marker.add(new Integer(1200));
1151     marker.add(new Integer(1600));
1152     marker.add(Color.red);
1153     marker.add(new Float(10.0f));
1154     marker.add(new Boolean(false));
1155     marker.add(new Boolean(true));
1156     block.add(marker);
1157 
1158     Vector restrictionEnzyme = new Vector();
1159     Vector re = new Vector();
1160     re.add(new String("EcoR1"));
1161     re.add(new Integer(2555));
1162     re.add(Color.blue);
1163     restrictionEnzyme.add(re);
1164     re = new Vector();
1165     re.add(new String("EcoR1"));
1166     re.add(new Integer(3444));
1167     re.add(Color.blue);
1168     restrictionEnzyme.add(re);
1169 
1170 
1171     if(dna == null)
1172       dna = new DNADraw(minTicks,majTicks,block,restrictionEnzyme);
1173     jsp = new JScrollPane(dna);
1174     jsp.getViewport().setBackground(Color.white);
1175     f.getContentPane().add(jsp);
1176     f.setJMenuBar(dna.createMenuBar());
1177 
1178     f.pack();
1179     f.setLocation(((int)d.getWidth()-f.getWidth())/4,
1180                   ((int)d.getHeight()-f.getHeight())/2);
1181 
1182     f.setVisible(true);
1183   }
1184 
1185 }
1186 
1187