JAL-3026 srcjar files for VARNA and log4j
[jalview.git] / srcjar / fr / orsay / lri / varna / applications / templateEditor / Helix.java
1 package fr.orsay.lri.varna.applications.templateEditor;
2
3 import java.awt.Graphics2D;
4 import java.awt.Polygon;
5 import java.awt.Shape;
6 import java.awt.geom.Point2D;
7 import java.util.ArrayList;
8 import java.util.HashSet;
9 import java.util.List;
10 import java.util.Set;
11
12 import fr.orsay.lri.varna.exceptions.ExceptionInvalidRNATemplate;
13 import fr.orsay.lri.varna.models.rna.RNA;
14 import fr.orsay.lri.varna.models.templates.RNATemplate;
15 import fr.orsay.lri.varna.models.templates.RNATemplate.EdgeEndPointPosition;
16 import fr.orsay.lri.varna.models.templates.RNATemplate.RNATemplateHelix;
17 import fr.orsay.lri.varna.models.templates.RNATemplate.RNATemplateElement.EdgeEndPoint;
18
19
20 public class Helix extends GraphicalTemplateElement{
21         
22   RNATemplateHelix _h;
23   
24   public Helix(double x, double y, RNATemplate tmp, List<GraphicalTemplateElement> existingRNAElements)
25   {
26           this(x,y,getNextAutomaticCaption(existingRNAElements),tmp);
27   }
28   
29   public Helix(double x, double y, String cap, RNATemplate tmp)
30   {
31           _h = tmp.new RNATemplateHelix(cap);
32           _h.setStartPosition(new Point2D.Double(x,y));
33           _h.setEndPosition(new Point2D.Double(x,y));
34           _h.setLength(1);
35           _h.setCaption(cap);
36   }
37   
38   public Helix(RNATemplateHelix templateHelix) {
39           _h = templateHelix;
40   }
41   
42   
43   private static String getNextAutomaticCaption(List<GraphicalTemplateElement> existingRNAElements) {
44           // Find which captions are already used
45           Set<String> captions = new HashSet<String>();
46           for (GraphicalTemplateElement element: existingRNAElements) {
47                   if (element instanceof Helix) {
48                           Helix helix = (Helix) element;
49                           if (helix.getCaption() != null) {
50                                   captions.add(helix.getCaption());
51                           }
52                   }
53           }
54           // Find a non-conflicting name for this helix
55           for (int i=1;;i++) {
56                   String candidateCaption = "H" + i;
57                   if (! captions.contains(candidateCaption)) {
58                           return candidateCaption;
59                   }
60           }
61   }
62   
63   public void toggleFlipped()
64   {
65           _h.setFlipped(!_h.isFlipped());
66           updateAttachedUnpairedRegions();
67   }
68   
69
70   /**
71    * When an helix is moved/resized/etc... it is necessary to update
72    * the positions of endpoints from unpaired regions that are attached
73    * to the helix. This function updates the endpoints positions of
74    * attached unpaired regions.
75    */
76   public void updateAttachedUnpairedRegions() {
77           for (RelativePosition rpos: getConnectedEdges()) {
78                   Couple<RelativePosition,GraphicalTemplateElement> c = getAttachedElement(rpos);
79                   if (c != null && c.second instanceof UnpairedRegion) {
80                           UnpairedRegion unpairedRegion = (UnpairedRegion) c.second;
81                           Point2D.Double pos = getEdgePosition(rpos);
82                           if (c.first == RelativePosition.RP_CONNECT_START5) {
83                                   unpairedRegion.setEdge5(pos);
84                           } else if (c.first == RelativePosition.RP_CONNECT_END3) {
85                                   unpairedRegion.setEdge3(pos);
86                           }
87                   }
88           }
89   }
90
91   public double getPosX()
92   {
93           return _h.getStartPosition().x;
94   }
95
96   public String getCaption()
97   {
98           return _h.getCaption();
99   }
100   
101   public double getPosY()
102   {
103           return _h.getStartPosition().y;
104   }
105   
106   public RNATemplateHelix getTemplateElement()
107   {
108           return _h;
109   }
110
111   public void setX(double x)
112   {
113           _h.getStartPosition().x = x;
114   }
115   
116   public void setY(double y)
117   {
118           _h.getStartPosition().y = y;
119   }
120
121   public void setPos(Point2D.Double p)
122   {
123          _h.setStartPosition(p);
124           updateLength();
125   }
126
127   public void setPos(double x, double y)
128   {
129           setPos(new Point2D.Double(x,y));
130   }
131
132   public Point2D.Double getPos()
133   {
134           return _h.getStartPosition();
135   }
136
137   public void moveCenter(double x, double y)
138   {
139           Point2D.Double center = new Point2D.Double((_h.getStartPosition().x+_h.getEndPosition().x)/2.0,(_h.getStartPosition().y+_h.getEndPosition().y)/2.0);
140           double dx = x-center.x;
141           double dy = y-center.y;
142           _h.setStartPosition(new Point2D.Double(_h.getStartPosition().x+dx,_h.getStartPosition().y+dy));
143           _h.setEndPosition(new Point2D.Double(_h.getEndPosition().x+dx,_h.getEndPosition().y+dy));
144   }
145
146   
147   public void setExtent(double x, double y)
148   {
149          setExtent(new Point2D.Double(x,y));
150   }
151
152   private void updateLength()
153   {
154           _h.setLength(getNbBP());
155   }
156   
157   public void setExtent(Point2D.Double p)
158   {
159          _h.setEndPosition(p);
160           updateLength();
161   }
162
163   public double getExtentX()
164   {
165           return _h.getEndPosition().x;
166   }
167
168   public Point2D.Double getExtent()
169   {
170           return _h.getEndPosition();
171   }
172
173   public double getExtentY()
174   {
175           return _h.getEndPosition().y;
176   }
177   
178         public static final double BASE_PAIR_DISTANCE = RNA.BASE_PAIR_DISTANCE;
179         public static final double LOOP_DISTANCE = RNA.LOOP_DISTANCE;
180         public static final double SELECTION_RADIUS = 15.0;
181         
182         
183         
184
185         public Point2D.Double getAbsStart5()
186         {
187                 double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
188                 double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
189                 double nx = dy;
190                 double ny = -dx;
191                 Point2D.Double start5 = new Point2D.Double((getPosX()-Helix.BASE_PAIR_DISTANCE*nx/2.0),(getPosY()-Helix.BASE_PAIR_DISTANCE*ny/2.0)); 
192                 return start5;
193         }
194
195         public Point2D.Double getAbsStart3()
196         {
197                 double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
198                 double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
199                 double nx = dy;
200                 double ny = -dx;
201                 Point2D.Double start3 = new Point2D.Double((getPosX()+Helix.BASE_PAIR_DISTANCE*nx/2.0),(getPosY()+Helix.BASE_PAIR_DISTANCE*ny/2.0)); 
202                 return start3;
203         }
204
205         public Point2D.Double getAbsEnd5()
206         {
207                 double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
208                 double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
209                 double nx = dy;
210                 double ny = -dx;
211                 Point2D.Double end5 = new Point2D.Double((getExtentX()-Helix.BASE_PAIR_DISTANCE*nx/2.0),(getExtentY()-Helix.BASE_PAIR_DISTANCE*ny/2.0)); 
212                 return end5;
213         }
214
215         public Point2D.Double getAbsEnd3()
216         {
217                 double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
218                 double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
219                 double nx = dy;
220                 double ny = -dx;
221                 Point2D.Double end3 = new Point2D.Double((getExtentX()+Helix.BASE_PAIR_DISTANCE*nx/2.0),(getExtentY()+Helix.BASE_PAIR_DISTANCE*ny/2.0));
222                 return end3;
223         }
224         
225         public Point2D.Double getStart5()
226         {
227                 if (_h.isFlipped())
228                         return getAbsStart3();
229                 else
230                         return getAbsStart5();
231                 
232         }
233
234         public Point2D.Double getStart3()
235         {
236                 if (_h.isFlipped())
237                         return getAbsStart5();
238                 else
239                         return getAbsStart3();
240         }
241
242         public Point2D.Double getEnd5()
243         {
244                 if (_h.isFlipped())
245                         return getAbsEnd3();
246                 else
247                         return getAbsEnd5();
248         }
249
250         public Point2D.Double getEnd3()
251         {
252                 if (_h.isFlipped())
253                         return getAbsEnd5();
254                 else
255                         return getAbsEnd3();
256         }
257
258         public Polygon getBoundingPolygon()
259         {
260                 double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
261                 double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
262                 double nx = dy;
263                 double ny = -dx;
264                 Point2D.Double start5 = new Point2D.Double((getPosX()+Helix.BASE_PAIR_DISTANCE*nx/2.0),(getPosY()+Helix.BASE_PAIR_DISTANCE*ny/2.0)); 
265                 Point2D.Double end5 = new Point2D.Double((getExtentX()+Helix.BASE_PAIR_DISTANCE*nx/2.0),(getExtentY()+Helix.BASE_PAIR_DISTANCE*ny/2.0)); 
266                 Point2D.Double start3 = new Point2D.Double((getPosX()-Helix.BASE_PAIR_DISTANCE*nx/2.0),(getPosY()-Helix.BASE_PAIR_DISTANCE*ny/2.0)); 
267                 Point2D.Double end3 = new Point2D.Double((getExtentX()-Helix.BASE_PAIR_DISTANCE*nx/2.0),(getExtentY()-Helix.BASE_PAIR_DISTANCE*ny/2.0));
268                 Polygon p = new Polygon();
269                 p.addPoint((int)start5.x, (int)start5.y);
270                 p.addPoint((int)end5.x, (int)end5.y);
271                 p.addPoint((int)end3.x, (int)end3.y);
272                 p.addPoint((int)start3.x, (int)start3.y);
273                 return p;
274         }
275
276         
277         public Point2D.Double getCenter()
278         {
279                 return new Point2D.Double((int)((_h.getStartPosition().x+_h.getEndPosition().x)/2.0),
280                                 (int)((_h.getStartPosition().y+_h.getEndPosition().y)/2.0));
281         }
282
283
284         public Point2D.Double getCenterEditStart()
285         {
286                 double dist = _h.getStartPosition().distance(_h.getEndPosition());
287                 double dx = (_h.getEndPosition().x-_h.getStartPosition().x)/(dist);
288                 double dy = (_h.getEndPosition().y-_h.getStartPosition().y)/(dist);
289                 return new Point2D.Double((int)(_h.getStartPosition().x+(dist-10.0)*dx),
290                                 (int)(_h.getStartPosition().y+(dist-10.0)*dy));
291         }       
292
293         public Point2D.Double getCenterEditEnd()
294         {
295                 double dist = _h.getStartPosition().distance(_h.getEndPosition());
296                 double dx = (_h.getEndPosition().x-_h.getStartPosition().x)/(dist);
297                 double dy = (_h.getEndPosition().y-_h.getStartPosition().y)/(dist);
298                 return new Point2D.Double((int)(_h.getStartPosition().x+(10.0)*dx),
299                                 (int)(_h.getStartPosition().y+(10.0)*dy));
300         }       
301
302         
303         public Shape getSelectionBox()
304         {
305                 double dx = (_h.getStartPosition().x-_h.getEndPosition().x)/(_h.getStartPosition().distance(_h.getEndPosition()));
306                 double dy = (_h.getStartPosition().y-_h.getEndPosition().y)/(_h.getStartPosition().distance(_h.getEndPosition()));
307                 double nx = dy;
308                 double ny = -dx;
309                 Polygon hbox = getBoundingPolygon();
310                 Polygon p = new Polygon();
311                 Point2D.Double start5 = new Point2D.Double(hbox.xpoints[0]+SELECTION_RADIUS*(dx+nx),hbox.ypoints[0]+SELECTION_RADIUS*(dy+ny)); 
312                 Point2D.Double end5 = new Point2D.Double(hbox.xpoints[1]+SELECTION_RADIUS*(-dx+nx),hbox.ypoints[1]+SELECTION_RADIUS*(-dy+ny)); 
313                 Point2D.Double end3  = new Point2D.Double(hbox.xpoints[2]+SELECTION_RADIUS*(-dx-nx),hbox.ypoints[2]+SELECTION_RADIUS*(-dy-ny));;
314                 Point2D.Double start3 = new Point2D.Double(hbox.xpoints[3]+SELECTION_RADIUS*(dx-nx),hbox.ypoints[3]+SELECTION_RADIUS*(dy-ny));; 
315                 p.addPoint((int)start5.x, (int)start5.y);
316                 p.addPoint((int)end5.x, (int)end5.y);
317                 p.addPoint((int)end3.x, (int)end3.y);
318                 p.addPoint((int)start3.x, (int)start3.y);
319                 return p;
320         }
321
322         public Shape getArea()
323         {
324                 return getSelectionBox();
325         }
326
327         
328         public static final double EDIT_RADIUS = 10.0;
329         public static final double MOVE_RADIUS = 13.0;
330         public static final double BASE_RADIUS = 8.0;
331         public static final double EDGE_BASE_RADIUS = 7.0;
332         
333         
334         public RelativePosition getRelativePosition(double x, double y)
335         {
336                 Point2D.Double current = new Point2D.Double(x,y);
337                 Shape p = getSelectionBox();
338                 if (p.contains(current))
339                 {
340                         if (getCenterEditStart().distance(current)<EDIT_RADIUS)
341                         {
342                                 return RelativePosition.RP_EDIT_START;
343                         }
344                         else if (getCenterEditEnd().distance(current)<EDIT_RADIUS)
345                         {
346                                 return RelativePosition.RP_EDIT_END;
347                         }
348                         else if (getCenter().distance(current)<MOVE_RADIUS)
349                         {
350                                 return RelativePosition.RP_INNER_MOVE;
351                         }
352                         else if (getEnd3().distance(current)<EDGE_BASE_RADIUS)
353                         {
354                                 return RelativePosition.RP_CONNECT_END3;
355                         }
356                         else if (getEnd5().distance(current)<EDGE_BASE_RADIUS)
357                         {
358                                 return RelativePosition.RP_CONNECT_END5;
359                         }
360                         else if (getStart3().distance(current)<EDGE_BASE_RADIUS)
361                         {
362                                 return RelativePosition.RP_CONNECT_START3;
363                         }
364                         else if (getStart5().distance(current)<EDGE_BASE_RADIUS)
365                         {
366                                 return RelativePosition.RP_CONNECT_START5;
367                         }
368                                 
369                         return RelativePosition.RP_INNER_GENERAL;
370                 }
371                 else 
372                         return RelativePosition.RP_OUTER;  
373         }
374
375         public RelativePosition getClosestEdge(double x, double y)
376         {
377                 RelativePosition result = RelativePosition.RP_OUTER;
378                 double dist = Double.MAX_VALUE;
379                 Point2D.Double current = new Point2D.Double(x,y);
380                 double dcand = getStart5().distance(current);
381             if (dcand<dist)
382             {
383                 dist = dcand;
384                 result = RelativePosition.RP_CONNECT_START5;
385             }
386                 dcand = getStart3().distance(current);
387             if (dcand<dist)
388             {
389                 dist = dcand;
390                 result = RelativePosition.RP_CONNECT_START3;
391             }
392                 dcand = getEnd5().distance(current);
393             if (dcand<dist)
394             {
395                 dist = dcand;
396                 result = RelativePosition.RP_CONNECT_END5;
397             }
398                 dcand = getEnd3().distance(current);
399             if (dcand<dist)
400             {
401                 dist = dcand;
402                 result = RelativePosition.RP_CONNECT_END3;
403             }
404                 return result;
405         }
406         
407         public Point2D.Double getEdgePosition(Helix.RelativePosition edge)
408         {
409                 switch (edge)
410                 {
411                         case RP_CONNECT_END3:
412                                 return getEnd3();
413                         case RP_CONNECT_END5:
414                                 return getEnd5();
415                         case RP_CONNECT_START5:
416                                 return getStart5();
417                         case RP_CONNECT_START3:
418                                 return getStart3();
419                         case RP_EDIT_START:
420                                 return getPos();
421                         case RP_EDIT_END:
422                                 return  getExtent();
423                         case RP_INNER_MOVE:
424                                 return  getCenter();
425                 }
426                 return getCenter();
427         }
428
429         public RelativePosition getConnectedEdge(RelativePosition edge)
430         {
431                 switch (edge)
432                 {
433                         case RP_CONNECT_END3:
434                                 return RelativePosition.RP_CONNECT_START3;
435                         case RP_CONNECT_END5:
436                                 return RelativePosition.RP_CONNECT_START5;
437                         case RP_CONNECT_START5:
438                                 return RelativePosition.RP_CONNECT_END5;
439                         case RP_CONNECT_START3:
440                                 return RelativePosition.RP_CONNECT_END3;
441                 }
442                 return RelativePosition.RP_OUTER;
443         }
444         
445         public boolean isAnchored5Start()
446         {
447                 return (_h.getIn1().getOtherElement()!=null);
448         }
449
450         public boolean isAnchored5End()
451         {
452                 return (_h.getOut1().getOtherElement()!=null);
453         }
454         
455         public boolean isAnchored3Start()
456         {
457                 return (_h.getOut2().getOtherElement()!=null);
458         }
459
460         public boolean isAnchored3End()
461         {
462                 return (_h.getIn2().getOtherElement()!=null);
463         }
464         
465         public int getNbBP()
466         {
467                 Point2D.Double pos = getPos();
468                 Point2D.Double extent = getExtent();
469                 double helLength =  pos.distance(extent);
470                 return Math.max((int)Math.round(helLength/Helix.LOOP_DISTANCE) + 1, 2);
471         }
472         
473         public void draw(Graphics2D g2d,boolean isSelected)
474         {
475                 g2d.setStroke(_solidStroke);
476                 Point2D.Double pos = getPos();
477                 Point2D.Double extent = getExtent();
478                 double dx = (pos.x-extent.x)/pos.distance(extent);
479                 double dy = (pos.y-extent.y)/pos.distance(extent);
480                 double nx = Helix.BASE_PAIR_DISTANCE*dy/2.0;
481                 double ny = -Helix.BASE_PAIR_DISTANCE*dx/2.0;
482                 Point2D.Double start5 = getStart5(); 
483                 Point2D.Double end5 = getEnd5(); 
484                 Point2D.Double start3 = getStart3(); 
485                 Point2D.Double end3 = getEnd3();
486                 
487                 for (RelativePosition e:this.getConnectedEdges())
488                 {
489                         g2d.setStroke(_solidStroke);
490                         g2d.setColor(BACKBONE_COLOR);
491                         Point2D.Double p1 = this.getEdgePosition(e);
492                         Point2D.Double p2 = this.getEdgePosition(getConnectedEdge(e));
493                         if (_mainColors.containsKey(e))
494                         { 
495                                 g2d.setColor(_mainColors.get(e));
496                                 g2d.setStroke(this._boldStroke);
497                         }
498                         g2d.drawLine((int)p1.x,(int)p1.y,(int)(p1.x+p2.x)/2,(int)(p1.y+p2.y)/2);
499                 }
500
501                 g2d.setColor(NUMBER_COLOR);
502                 double captionx = (_h.isFlipped()?-1.0:1.0)*1.5*nx+(start3.x+end3.x)/2.0;
503                 double captiony = (_h.isFlipped()?-1.0:1.0)*1.5*ny+(start3.y+end3.y)/2.0;
504                 drawStringCentered(g2d, getCaption(),captionx,captiony);
505
506                 int nbBasePairs = _h.getLength();
507
508                 g2d.setStroke(_solidStroke);
509
510                 for (int i=0;i<nbBasePairs;i++)
511                 {
512                         g2d.setColor(BASE_PAIR_COLOR);
513                         Point2D.Double p5 = new Point2D.Double(
514                                         (i*start5.x+(nbBasePairs-1-i)*end5.x)/(nbBasePairs-1),
515                                         (i*start5.y+(nbBasePairs-1-i)*end5.y)/(nbBasePairs-1));
516                         Point2D.Double p3 = new Point2D.Double(
517                                         (i*start3.x+(nbBasePairs-1-i)*end3.x)/(nbBasePairs-1),
518                                         (i*start3.y+(nbBasePairs-1-i)*end3.y)/(nbBasePairs-1));
519                         g2d.drawLine((int)p3.x,(int)p3.y,(int)p5.x,(int)p5.y);
520                         if (i==0)
521                         {
522                                 if (isAnchored5End())
523                                 { drawMagnet(g2d, p5); }
524                                 else
525                                 { drawAnchor3(g2d, p5); }
526                                 
527                                 if (isAnchored3End())
528                                 { drawMagnet(g2d, p3); }
529                                 else
530                                 { drawAnchor5(g2d, p3); }
531                         }
532                         else if (i==nbBasePairs-1)
533                         {
534                                 if (isAnchored5Start())
535                                 { drawMagnet(g2d, p5); }
536                                 else
537                                 { drawAnchor5(g2d, p5); }
538                                 
539                                 if (isAnchored3Start())
540                                 { drawMagnet(g2d, p3); }
541                                 else
542                                 { drawAnchor3(g2d, p3); }
543                         }
544                         else
545                         {
546                                 drawBase(g2d, p3);
547                                 drawBase(g2d, p5);
548                         }
549                 }
550
551                 if (isSelected)
552                 {
553                         nx = dy;
554                         ny = -dx;
555                         Shape p = getSelectionBox();
556                         g2d.setColor(BACKBONE_COLOR);
557                         g2d.setStroke(_dashedStroke);
558                         g2d.draw(p);
559                         Point2D.Double center = getCenter();
560                         g2d.setStroke(_solidStroke);
561                         drawMove(g2d,center);
562                         drawEditStart(g2d,this,-dx,-dy,nx,ny);                  
563                         drawEditEnd(g2d,this,-dx,-dy,nx,ny);                    
564                 }
565         }
566
567
568         public void translate(double x, double y) {
569                   Point2D.Double pos = getPos();
570                   Point2D.Double extent = getExtent();
571                   setPos(pos.x+x,pos.y+y);
572                   setExtent(extent.x+x,extent.y+y);
573         }
574
575         public RNATemplateHelix getHelix() {
576                 return _h;
577         }
578         
579
580         public EdgeEndPoint getEndPoint(RelativePosition r) {
581                 switch(r)
582                 {
583                         case RP_CONNECT_START5:
584                         return _h.getIn1();                             
585                         case RP_CONNECT_START3:
586                         return _h.getOut2();                            
587                         case RP_CONNECT_END3:
588                                 return _h.getIn2();
589                         case RP_CONNECT_END5:
590                                 return _h.getOut1();
591                 }
592                 return null;
593         }
594
595         public boolean isIn(RelativePosition r) {
596                 switch(r)
597                 {
598                 case RP_CONNECT_START5:
599                         return true;                            
600                 case RP_CONNECT_START3:
601                         return false;                           
602                 case RP_CONNECT_END3:
603                         return true;
604                 case RP_CONNECT_END5:
605                         return false;
606                 }
607                 return true;
608         }
609         
610         
611         public void attach(GraphicalTemplateElement e, RelativePosition edgeOrig, RelativePosition edgeDest) throws ExceptionInvalidRNATemplate
612         {
613                 super.attach(e,edgeOrig,edgeDest);
614                 EdgeEndPoint e1 = this.getEndPoint(edgeOrig);
615                 EdgeEndPoint e2 = e.getEndPoint(edgeDest);
616                 boolean parity1 = this.isIn(edgeOrig);
617                 boolean parity2 = e.isIn(edgeDest);
618                 if ((e1!=null)&&(e2!=null)&&(parity1!=parity2))
619                 {
620                    e1.disconnect();
621                    e2.disconnect();
622                    e1.connectTo(e2);
623                 }
624         }
625         
626
627
628         public void detach(RelativePosition edge)
629         {
630                 // If the underlying template element is still connected, disconnect it
631                 if (getEndPoint(edge).isConnected())
632                 {
633                         getEndPoint(edge).disconnect();
634                 }
635                 
636                 // Call the parent class detach function, which will also take care to disconnect this other endpoint of this edge
637                 super.detach(edge);
638         }
639
640         public void setEdgePosition(RelativePosition edge, java.awt.geom.Point2D.Double pos) {
641                 switch (edge)
642                 {
643                         case RP_EDIT_START:
644                                 setPos(pos);
645                                 break;
646                         case RP_EDIT_END:
647                                 setExtent(pos);
648                                 break;
649                         case RP_INNER_MOVE:
650                                 moveCenter(pos.x,pos.y);
651                                 break;
652                 }
653                 updateAttachedUnpairedRegions();
654         }
655
656         public ArrayList<RelativePosition> getConnectedEdges() {
657                 ArrayList<RelativePosition> result = new ArrayList<RelativePosition>();
658                 result.add(RelativePosition.RP_CONNECT_START5);
659                 result.add(RelativePosition.RP_CONNECT_START3);
660                 result.add(RelativePosition.RP_CONNECT_END5);
661                 result.add(RelativePosition.RP_CONNECT_END3);
662                 return result;
663         }
664         
665         public String toString()
666         {
667                 return "Helix " + getCaption();
668         }
669
670         public RelativePosition relativePositionFromEdgeEndPointPosition(
671                         EdgeEndPointPosition pos) {
672                 switch (pos) {
673                 case IN1:
674                         return RelativePosition.RP_CONNECT_START5;
675                 case OUT1:
676                         return RelativePosition.RP_CONNECT_END5;
677                 case IN2:
678                         return RelativePosition.RP_CONNECT_END3;
679                 case OUT2:
680                         return RelativePosition.RP_CONNECT_START3;
681                 default:
682                         return null;
683                 }
684         }
685
686 }
687