JAL-3026 srcjar files for VARNA and log4j
[jalview.git] / srcjar / fr / orsay / lri / varna / applications / templateEditor / TemplatePanel.java
1 /**
2  * 
3  */
4 package fr.orsay.lri.varna.applications.templateEditor;
5
6 import java.awt.BasicStroke;
7 import java.awt.Color;
8 import java.awt.Dimension;
9 import java.awt.Graphics;
10 import java.awt.Graphics2D;
11 import java.awt.Point;
12 import java.awt.Polygon;
13 import java.awt.Rectangle;
14 import java.awt.RenderingHints;
15 import java.awt.Stroke;
16 import java.awt.geom.Point2D;
17 import java.io.File;
18 import java.util.ArrayList;
19 import java.util.HashMap;
20 import java.util.Hashtable;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Stack;
25
26 import javax.swing.JOptionPane;
27 import javax.swing.JPanel;
28 import javax.swing.undo.UndoManager;
29
30 import fr.orsay.lri.varna.applications.templateEditor.GraphicalTemplateElement.RelativePosition;
31 import fr.orsay.lri.varna.controlers.ControleurMolette;
32 import fr.orsay.lri.varna.exceptions.ExceptionInvalidRNATemplate;
33 import fr.orsay.lri.varna.exceptions.ExceptionXmlLoading;
34 import fr.orsay.lri.varna.models.templates.RNATemplate;
35 import fr.orsay.lri.varna.models.templates.RNATemplate.RNATemplateElement;
36 import fr.orsay.lri.varna.models.templates.RNATemplate.RNATemplateHelix;
37 import fr.orsay.lri.varna.models.templates.RNATemplate.RNATemplateUnpairedSequence;
38 import fr.orsay.lri.varna.models.templates.RNATemplate.RNATemplateElement.EdgeEndPoint;
39
40
41
42
43 /**
44  * @author ponty
45  *
46  */
47 public class TemplatePanel extends JPanel {
48   /**
49          * 
50          */
51         private static final long serialVersionUID = 3162771335587335679L;
52         
53         
54         private ArrayList<GraphicalTemplateElement> _RNAComponents;
55         private ArrayList<Connection> _RNAConnections;
56         private Hashtable<Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>,Connection> _helixToConnection;
57         private TemplateEditorPanelUI _ui;
58         
59         private RNATemplate _template;
60
61         
62         private static Color[] BackgroundColors = {Color.blue,Color.red,Color.cyan,Color.green,Color.lightGray,Color.magenta,Color.PINK};
63
64         private int _nextBackgroundColor = 0;
65         
66         private static double scaleFactorDefault = 0.7;
67         private double scaleFactor = scaleFactorDefault;
68         
69         
70         private TemplateEditor _editor;
71         
72         
73         public double getScaleFactor() {
74                 return scaleFactor;
75         }
76
77         public void setScaleFactor(double scaleFactor) {
78                 this.scaleFactor = scaleFactor;
79         }
80
81         public Color nextBackgroundColor()
82         {
83                 Color c = BackgroundColors[_nextBackgroundColor++];
84                 _nextBackgroundColor = _nextBackgroundColor % BackgroundColors.length;
85                 return new Color(c.getRed(),c.getBlue(),c.getGreen(),50);
86         }
87         
88         public TemplatePanel(TemplateEditor parent)
89         {
90                 _editor = parent;
91                 init();
92         }
93
94         public RNATemplate getTemplate()
95         {
96                 return _template;
97         }
98         
99         List<GraphicalTemplateElement> getRNAComponents() {
100                 return _RNAComponents;
101         }
102         
103         private void init()
104         {
105                 _ui = new TemplateEditorPanelUI(this); 
106                 
107                 _RNAComponents = new ArrayList<GraphicalTemplateElement>();
108                 _RNAConnections = new ArrayList<Connection>();
109                 _helixToConnection = new Hashtable<Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>,Connection>();
110                 
111                 _template = new RNATemplate();
112                 
113                 setBackground(Color.WHITE);
114                 MouseControler mc = new MouseControler(this,_ui); 
115                 addMouseListener(mc);
116                 addMouseMotionListener(mc);
117                 addMouseWheelListener(mc);
118                 _solidStroke = new BasicStroke(1.5f, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND, 3.0f);
119                 float[] dash = { 5.0f, 5.0f };
120                 _dashedStroke = new BasicStroke(1.5f, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND, 3.0f, dash, 0);
121         }
122         
123         public void addUndoableEditListener(UndoManager manager)
124         {
125                 _ui.addUndoableEditListener(manager);
126         }
127         
128         public TemplateEditorPanelUI getTemplateUI()
129         {
130                 return _ui;
131         }
132
133         
134         public void flip(Helix h)
135         { 
136                 h.toggleFlipped(); 
137         }
138         
139         public void addElement(GraphicalTemplateElement h)
140         { 
141                 _RNAComponents.add(h); 
142         }
143
144         public void removeElement(GraphicalTemplateElement h)
145         { 
146                 _RNAComponents.remove(h);
147                 try {
148                         _template.removeElement(h.getTemplateElement());
149                 } catch (ExceptionInvalidRNATemplate e) {
150                         //e.printStackTrace();
151                 }
152         }
153
154         private GraphicalTemplateElement _selected = null;
155         
156         public GraphicalTemplateElement getSelected()
157         {
158                 return _selected;
159         }
160
161         public void setSelected(GraphicalTemplateElement sel)
162         {
163                 _selected = sel;
164                 if (_selected instanceof Helix) {
165                         _editor.flipButtonEnable();
166                 } else {
167                         _editor.flipButtonDisable();
168                 }
169         }
170
171         Helix.RelativePosition _relpos = Helix.RelativePosition.RP_OUTER;
172         
173         public void setSelectedEdge(Helix.RelativePosition rel)
174         {
175                 _relpos = rel;
176         }
177
178         public void unselectEdge(Helix.RelativePosition rel)
179         {
180                 _relpos = rel;
181         }
182         
183         Point2D.Double _mousePos = new Point2D.Double();
184
185         public void setPointerPos(Point2D.Double p)
186         {
187                 _mousePos = p;
188         }       
189         
190         public void Unselect()
191         {
192                 _editor.flipButtonDisable();
193                 _selected = null;
194         }
195
196         public GraphicalTemplateElement getElement(RNATemplateElement t)
197         {
198                 for(GraphicalTemplateElement t2: _RNAComponents)
199                         if (t==t2.getTemplateElement())
200                                 return t2;
201                 return null;
202         }
203
204         
205         public GraphicalTemplateElement getElementAt(double x, double y)
206         {
207                 return getElementAt(x, y, null);
208         }
209         public GraphicalTemplateElement getElementAt(double x, double y, GraphicalTemplateElement excluded)
210         {
211                 GraphicalTemplateElement h = null;
212                 for (int i=0; i<_RNAComponents.size();i++)
213                 {
214                         GraphicalTemplateElement h2 = _RNAComponents.get(i);
215                         if ((
216                                            (h2.getRelativePosition(x, y)== Helix.RelativePosition.RP_CONNECT_END3)
217                                         || (h2.getRelativePosition(x, y)== Helix.RelativePosition.RP_CONNECT_END5)
218                                         || (h2.getRelativePosition(x, y)== Helix.RelativePosition.RP_CONNECT_START3)
219                                         || (h2.getRelativePosition(x, y)== Helix.RelativePosition.RP_CONNECT_START5))
220                                 && (excluded!=h2))
221                         {
222                                 h = h2;
223                         }
224                 }
225                 if (h==null)
226                 { h = getElementCloseTo(x, y, excluded);};
227                 return h;
228         }
229
230         public GraphicalTemplateElement getElementCloseTo(double x, double y)
231         {
232                 return getElementCloseTo(x, y, null);
233         }
234         public GraphicalTemplateElement getElementCloseTo(double x, double y, GraphicalTemplateElement excluded)
235         {
236                 GraphicalTemplateElement h = null;
237                 for (int i=0; i<_RNAComponents.size();i++)
238                 {
239                         GraphicalTemplateElement h2 = _RNAComponents.get(i);
240                         if ((h2.getRelativePosition(x, y) != Helix.RelativePosition.RP_OUTER)
241                                 && (excluded!=h2))
242                         {
243                                 h = h2;
244                         }
245                 }
246                 return h;
247         }
248         
249         public void addConnection(Connection c)
250         {
251                 _RNAConnections.add(c);
252                 _helixToConnection.put(new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(c._h1,c._edge1), c);
253                 _helixToConnection.put(new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(c._h2,c._edge2), c);
254                         try {
255                                 c._h1.attach(c._h2, c._edge1, c._edge2);
256                                 c._h2.attach(c._h1, c._edge2, c._edge1);
257                         } catch (ExceptionInvalidRNATemplate e) {
258                                 System.out.println(e.toString());// TODO Auto-generated catch block
259                 }
260
261         }
262
263         public Connection addConnection(GraphicalTemplateElement h1, GraphicalTemplateElement.RelativePosition edge1,GraphicalTemplateElement h2, GraphicalTemplateElement.RelativePosition edge2)
264         {
265                 if ((h1!=h2)&&(getPartner(h1,edge1)==null)&&(getPartner(h2,edge2)==null))
266                 {
267                         Connection c = new Connection(h1,edge1,h2,edge2);
268                         addConnection(c);
269                         return c;
270                 }
271                 return null;
272         }
273         
274         /**
275          * When there is already a connection in the underlying RNATemplate
276          * and we want to create one at the graphical level.
277          */
278         public void addGraphicalConnection(GraphicalTemplateElement h1, GraphicalTemplateElement.RelativePosition edge1,GraphicalTemplateElement h2, GraphicalTemplateElement.RelativePosition edge2) {
279                 //System.out.println("Connecting " + h1 + " " + edge1 + " to " + h2 + " " + edge2);
280                 Connection c = new Connection(h1,edge1,h2,edge2);
281                 _RNAConnections.add(c);
282                 _helixToConnection.put(new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(c._h1,c._edge1), c);
283                 _helixToConnection.put(new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(c._h2,c._edge2), c);
284                 c._h1.graphicalAttach(c._h2, c._edge1, c._edge2);
285                 c._h2.graphicalAttach(c._h1, c._edge2, c._edge1);
286         }
287         
288
289         public void removeConnection(Connection c)
290         {
291                 _RNAConnections.remove(c);
292                 _helixToConnection.remove(new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(c._h1,c._edge1));
293                 _helixToConnection.remove(new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(c._h2,c._edge2));
294                 System.out.println("[A]"+c);
295                 c._h1.detach(c._edge1);
296         }
297         
298         public boolean isInCycle(GraphicalTemplateElement el, GraphicalTemplateElement.RelativePosition edge)
299         {
300                 Stack<Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> > p = new Stack<Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>>();
301                 Hashtable<Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>,Integer> alreadySeen = new Hashtable<Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>,Integer>(); 
302                 p.add(new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(el,edge));
303                 while(!p.empty())
304                 {
305                         Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> c2 = p.pop();
306                         if (alreadySeen.containsKey(c2))
307                         {
308                                 return true;
309                         }
310                         else
311                         {
312                                 alreadySeen.put(c2, new Integer(1));
313                         }
314                         GraphicalTemplateElement.RelativePosition next = c2.first.getConnectedEdge(c2.second);
315                         Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> otherEnd = new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(c2.first,next);
316                         if (!alreadySeen.containsKey(otherEnd))
317                         {
318                                 p.push(otherEnd);
319                         }
320                         else
321                         {
322                                 Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> child =  getPartner(c2.first,c2.second);
323                                 if (child!=null)
324                                 {
325                                         p.push(child);
326                                 }
327                         }
328                         
329                 }
330                 
331                 return false;   
332         }
333         
334         private static Color[] _colors = {Color.gray,Color.pink,Color.cyan,Color.RED,Color.green,Color.orange};
335         
336         public static Color getIndexedColor(int n)
337         {
338                 return _colors[n%_colors.length];
339         }
340         
341         public HashMap<Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>,Integer> buildConnectedComponents()
342         {
343                 HashMap<Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>,Integer> alreadySeen = new HashMap<Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>,Integer>();
344                 int numConnectedComponents = 0;
345                 for (GraphicalTemplateElement el : this._RNAComponents)
346                 {
347                         for (GraphicalTemplateElement.RelativePosition edge : el.getConnectedEdges())
348                         {
349                                 Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> c = new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(el,edge);
350                                 if (!alreadySeen.containsKey(c))
351                                 {
352                                         Stack<Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> > p = new Stack<Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>>();
353                                         p.add(c);
354                                         p.add(new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(el,el.getConnectedEdge(edge)));
355                                         while(!p.empty())
356                                         {
357                                                 Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> c2 = p.pop();
358                                                 if (!alreadySeen.containsKey(c2))
359                                                 {
360                                                         //System.out.println("  "+numConnectedComponents+"  "+c2);
361                                                         c2.first.setMainColor(c2.second, getIndexedColor(numConnectedComponents));
362                                                         alreadySeen.put(c2, new Integer(numConnectedComponents));
363                                                         GraphicalTemplateElement.RelativePosition next = c2.first.getConnectedEdge(c2.second);
364                                                         Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> otherEnd = new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(c2.first,next);
365                                                         p.push(otherEnd);
366                                                         Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> child =  getPartner(c2.first,c2.second);
367                                                         if (child!=null)
368                                                         { p.push(child); }
369                                                 }       
370                                         }
371                                         numConnectedComponents += 1;
372                                 }
373                         }
374                 }
375                 return alreadySeen;
376         }
377         
378         public boolean isInCycle(Connection c)
379         {
380                 return isInCycle(c._h1,c._edge1); 
381         }
382         
383         public Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> getPartner(GraphicalTemplateElement h, GraphicalTemplateElement.RelativePosition edge)
384         {
385                 Connection c = getConnection(h, edge);
386                 if (c != null)
387                 {
388                           if ((c._h1==h)&&(c._edge1==edge))
389                           {  return new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(c._h2,c._edge2);  }
390                           else 
391                           {  return new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(c._h1,c._edge1); }
392                 }
393                 else
394                 {
395                         return null;
396                 }
397         }
398
399         public Connection getConnection(GraphicalTemplateElement h, Helix.RelativePosition edge)
400         {
401                 Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> target = new Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition>(h,edge);
402                 if (_helixToConnection.containsKey(target))
403                 {
404                         return _helixToConnection.get(target);
405                 }
406                 else
407                 { return null; }
408         }
409         
410         private boolean isConnected(Helix h, GraphicalTemplateElement.RelativePosition edge)
411         {
412                 Couple<GraphicalTemplateElement,GraphicalTemplateElement.RelativePosition> partner = getPartner(h,edge);
413                 return partner!=null;
414         }
415         
416
417         // Aspects graphiques
418         
419         private static final Color  CYCLE_COLOR = Color.red;
420         private static final Color  NON_EXISTANT_COLOR = Color.gray.brighter();
421         private static final Color  CONTROL_COLOR = Color.gray.darker();
422         private static final Color  BACKGROUND_COLOR = Color.white;
423         
424         private Stroke  _solidStroke;
425         private Stroke  _dashedStroke;
426         
427
428         
429         
430         private void drawConnections(Graphics2D g2d, Connection c)
431         {
432                 GraphicalTemplateElement h1 = c._h1;
433                 GraphicalTemplateElement.RelativePosition edge1 = c._edge1;
434                 Point2D.Double p1 = h1.getEdgePosition(edge1);
435                 GraphicalTemplateElement h2 = c._h2;
436                 GraphicalTemplateElement.RelativePosition edge2 = c._edge2;
437                 Point2D.Double p2 = h2.getEdgePosition(edge2);
438                 if (isInCycle(c))
439                 {
440                         g2d.setColor(CYCLE_COLOR);
441                 }
442                 else
443                 {
444                         g2d.setColor(GraphicalTemplateElement.BACKBONE_COLOR);
445                 }
446                 g2d.drawLine((int)p1.x,(int)p1.y,(int)p2.x,(int)p2.y);
447         }
448         
449
450         public void paintComponent(Graphics g)
451         {
452                 //rescale();
453                 
454                 // Debug code to show drawing area
455 //              g.setColor(Color.red);
456 //              g.fillRect(0,0,getWidth(),getHeight());
457 //              g.setColor(Color.white);
458 //              g.fillRect(10,10,getWidth()-20,getHeight()-20);
459                 
460                 g.setColor(Color.white);
461                 g.fillRect(0,0,getWidth(),getHeight());
462                 
463                 Graphics2D g2d = (Graphics2D) g;
464                 g2d.scale(scaleFactor, scaleFactor);
465                 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
466                                 RenderingHints.VALUE_ANTIALIAS_ON);
467                 removeAll();
468                 //super.paintComponent(g2d);
469
470                 buildConnectedComponents();
471                 
472                 if (_selected!=null)
473                 {
474                         if (_relpos != GraphicalTemplateElement.RelativePosition.RP_OUTER)
475                         {       
476                         Point2D.Double p = _selected.getEdgePosition(_relpos);
477                         g2d.setStroke(_solidStroke);
478                         g2d.drawLine((int)_mousePos.x, (int)_mousePos.y, (int)p.x, (int)p.y);
479                         }
480                 }
481                 for (int i=0;i<_RNAConnections.size();i++)
482                 {
483                         Connection c = _RNAConnections.get(i);
484                         drawConnections(g2d,c);
485                 }
486                 for (int i=0;i<_RNAComponents.size();i++)
487                 {
488                         GraphicalTemplateElement elem = _RNAComponents.get(i);
489                         //g2d.setColor(elem.getDominantColor());
490                         //g2d.fill(elem.getArea());
491                         if (_selected == elem)
492                         {  
493                                 elem.draw(g2d,true); 
494                         }
495                         else
496                         {  elem.draw(g2d,false);  }
497                 }
498         }
499         
500         /**
501          * Get the bounding rectangle of the RNA components, always including the origin (0,0).
502          */
503         public Rectangle getBoundingRectange() {
504                 int minX = 0;
505                 int maxX = 0;
506                 int minY = 0;
507                 int maxY = 0;
508                 for(int i=0;i<this._RNAComponents.size();i++)
509                 {
510                         GraphicalTemplateElement h = _RNAComponents.get(i);
511                         Polygon p = h.getBoundingPolygon();
512                         Rectangle r = p.getBounds();
513                         minX = Math.min(minX,r.x);
514                         maxX = Math.max(maxX,r.x+r.width);
515                         minY = Math.min(minY,r.y);
516                         maxY = Math.max(maxY,r.y+r.height);
517                 }
518                 Rectangle res = new Rectangle();
519                 res.x = minX;
520                 res.y = minY;
521                 res.width = maxX - minX;
522                 res.height = maxY - minY;
523                 return res;
524         }
525
526         public void rescale()
527         {
528                 Rectangle rect = getBoundingRectange();
529                 
530                 if (rect.x < 0 || rect.y < 0) {
531             for(int i=0;i<this._RNAComponents.size();i++)
532             {
533                     GraphicalTemplateElement h = _RNAComponents.get(i);
534                     h.translate(rect.x<0 ? -rect.x : 0, rect.y<0 ? -rect.y : 0);
535             }
536             rect = getBoundingRectange();
537                 }
538                 
539                 // areaW and H are width and height, in pixels, of the drawing area
540                 // including the "outside" parts available with scrolling
541                 int areaW = (int) ((rect.width + 100) * scaleFactor);
542                 int areaH = (int) ((rect.height + 100) * scaleFactor);
543                 // make it cover at least the space visible in the window
544                 //areaW = Math.max(areaW, (int) (_editor.getJp().getViewport().getViewSize().width));
545                 //areaH = Math.max(areaH, (int) (_editor.getJp().getViewport().getViewSize().height));
546                 //System.out.println(areaW + " x " + areaH);
547                 setPreferredSize(new Dimension(areaW, areaH));
548                 revalidate();
549         }
550
551         public void clearTemplate() {
552                 loadTemplate(new RNATemplate());
553         }
554
555         /**
556          * Load an existing RNATemplate object in this panel.
557          */
558         public void loadTemplate(RNATemplate template) {
559                 _template = template;
560                 _RNAComponents.clear();
561                 _RNAConnections.clear();
562                 _helixToConnection.clear();
563                 
564                 // We need a template element -> graphical template element mapping
565                 Map<RNATemplateElement, GraphicalTemplateElement> map = new HashMap<RNATemplateElement, GraphicalTemplateElement>();
566                 
567                 // First, we load elements
568                 {
569                         Iterator<RNATemplateElement> iter = template.classicIterator();
570                         while (iter.hasNext()) {
571                                 RNATemplateElement templateElement = iter.next();
572                                 if (templateElement instanceof RNATemplateHelix) {
573                                         RNATemplateHelix templateHelix = (RNATemplateHelix) templateElement;
574                                         Helix graphicalHelix = new Helix(templateHelix);
575                                         graphicalHelix.setDominantColor(nextBackgroundColor());
576                                         _RNAComponents.add(graphicalHelix);
577                                         map.put(templateHelix, graphicalHelix);
578                                 } else if (templateElement instanceof RNATemplateUnpairedSequence) {
579                                         RNATemplateUnpairedSequence templateSequence = (RNATemplateUnpairedSequence) templateElement;
580                                         UnpairedRegion graphicalSequence = new UnpairedRegion(templateSequence);
581                                         graphicalSequence.setDominantColor(nextBackgroundColor());
582                                         _RNAComponents.add(graphicalSequence);
583                                         map.put(templateSequence, graphicalSequence);
584                                 }
585                         }
586                 }
587                 
588                 // Now, we load edges
589                 {
590                         Iterator<EdgeEndPoint> iter = template.makeEdgeList().iterator();
591                         while (iter.hasNext()) {
592                                 EdgeEndPoint v1 = iter.next();
593                                 EdgeEndPoint v2 = v1.getOtherEndPoint();
594                                 GraphicalTemplateElement gte1 = map.get(v1.getElement());
595                                 GraphicalTemplateElement gte2 = map.get(v2.getElement());
596                                 RelativePosition rp1 = gte1.relativePositionFromEdgeEndPointPosition(v1.getPosition());
597                                 RelativePosition rp2 = gte2.relativePositionFromEdgeEndPointPosition(v2.getPosition());
598                                 addGraphicalConnection(gte1, rp1, gte2, rp2);
599                         }
600                 }
601                 
602                 zoomFit();
603                 //repaint();
604         }
605
606         /**
607          * Load a template from an XML file.
608          */
609         public void loadFromXmlFile(File filename) {
610                 try {
611                         RNATemplate newTemplate = RNATemplate.fromXMLFile(filename);
612                         loadTemplate(newTemplate);
613                 } catch (ExceptionXmlLoading e) {
614                         e.printStackTrace();
615                         JOptionPane.showMessageDialog(this, e.getMessage(), "Template loading error", JOptionPane.ERROR_MESSAGE);
616                 }
617         }
618         
619         private void zoomFinish() {
620                 rescale();
621                 repaint();
622         }
623         
624         public void zoomIn() {
625                 scaleFactor *= 1.2;
626                 zoomFinish();
627         }
628         
629         public void zoomOut() {
630                 scaleFactor /= 1.2;
631                 zoomFinish();
632         }
633         
634         public void zoomReset() {
635                 scaleFactor = scaleFactorDefault;
636                 zoomFinish();
637         }
638         
639         public void zoomFit() {
640                 if (_RNAComponents.isEmpty()) {
641                         zoomReset();
642                 } else {
643                         Rectangle rect = getBoundingRectange();
644                         double areaW = (rect.width + 100);
645                         double areaH = (rect.height + 100);
646                         // make it cover at least the space visible in the window
647                         scaleFactor = 1;
648                         scaleFactor = Math.min(scaleFactor, _editor.getJp().getViewport().getSize().width / areaW);
649                         scaleFactor = Math.min(scaleFactor, _editor.getJp().getViewport().getSize().height / areaH);
650                         zoomFinish();
651                 }
652         }
653         
654         public void translateView(Point trans) {
655                 int newX = _editor.getJp().getHorizontalScrollBar().getValue() - trans.x;
656                 int newY = _editor.getJp().getVerticalScrollBar().getValue() - trans.y;
657                 newX = Math.max(0, Math.min(newX, _editor.getJp().getHorizontalScrollBar().getMaximum()));
658                 newY = Math.max(0, Math.min(newY, _editor.getJp().getVerticalScrollBar().getMaximum()));
659                 _editor.getJp().getHorizontalScrollBar().setValue(newX);
660                 _editor.getJp().getVerticalScrollBar().setValue(newY);
661         }
662 }