Merge branch 'Jalview-JS/jim/JAL-3253-JAL-3418' into Jalview-JS/JAL-3253-applet
[jalview.git] / srcjar / fr / orsay / lri / varna / controlers / ControleurClicMovement.java
1 /*
2  VARNA is a tool for the automated drawing, visualization and annotation of the secondary structure of RNA, designed as a companion software for web servers and databases.
3  Copyright (C) 2008  Kevin Darty, Alain Denise and Yann Ponty.
4  electronic mail : Yann.Ponty@lri.fr
5  paper mail : LRI, bat 490 Université Paris-Sud 91405 Orsay Cedex France
6
7  This file is part of VARNA version 3.1.
8  VARNA version 3.1 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
9  as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
10
11  VARNA version 3.1 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  See the GNU General Public License for more details.
14
15  You should have received a copy of the GNU General Public License along with VARNA version 3.1.
16  If not, see http://www.gnu.org/licenses.
17  */
18 package fr.orsay.lri.varna.controlers;
19
20 import java.awt.Component;
21 import java.awt.Point;
22 import java.awt.Rectangle;
23 import java.awt.event.MouseEvent;
24 import java.awt.event.MouseListener;
25 import java.awt.event.MouseMotionListener;
26 import java.awt.geom.Point2D;
27 import java.util.ArrayList;
28 import java.util.Collection;
29 import java.util.Vector;
30
31 import javax.swing.JMenu;
32 import javax.swing.JMenuItem;
33 import javax.swing.event.PopupMenuEvent;
34 import javax.swing.event.PopupMenuListener;
35
36 import fr.orsay.lri.varna.VARNAPanel;
37 import fr.orsay.lri.varna.exceptions.ExceptionNAViewAlgorithm;
38 import fr.orsay.lri.varna.models.annotations.TextAnnotation;
39 import fr.orsay.lri.varna.models.rna.ModeleBase;
40 import fr.orsay.lri.varna.models.rna.ModeleBaseNucleotide;
41 import fr.orsay.lri.varna.models.rna.ModeleBasesComparison;
42 import fr.orsay.lri.varna.models.rna.ModeleBP;
43 import fr.orsay.lri.varna.models.rna.RNA;
44
45
46 /**
47  * Controller of the mouse click
48  * 
49  * @author darty
50  * 
51  */
52 public class ControleurClicMovement implements MouseListener,
53                 MouseMotionListener, PopupMenuListener {
54         private VARNAPanel _vp;
55         private boolean _presenceMenuSelection;
56         private JMenu _submenuSelection;
57         public Point _spawnPoint;       
58         public Point _initialPoint;
59         public Point _prevPoint;
60         public Point _currentPoint;
61
62         public static final double MIN_SELECTION_DISTANCE = 40.0;
63         public static final double HYSTERESIS_DISTANCE = 10.0;
64         
65         private ModeleBase _selectedBase = null;
66         
67         
68         public enum MouseStates {
69                 NONE,
70                 MOVE_ELEMENT,
71                 MOVE_OR_SELECT_ELEMENT,
72                 SELECT_ELEMENT,
73                 SELECT_REGION_OR_UNSELECT,
74                 SELECT_REGION,
75                 CREATE_BP,
76                 POPUP_MENU,
77                 MOVE_ANNOTATION,
78         };
79         private MouseStates _currentState = MouseStates.NONE;
80         
81
82
83         public ControleurClicMovement(VARNAPanel _vuep) {
84                 _vp = _vuep;
85                 _vp.getPopup().addPopupMenuListener(this);
86                 _presenceMenuSelection = false;
87         }
88
89         public void mouseClicked(MouseEvent arg0) {
90         }
91
92         public void mouseEntered(MouseEvent arg0) {
93         }
94
95         public void mouseExited(MouseEvent arg0) {
96         }
97
98         public void mousePressed(MouseEvent arg0) 
99         {
100                 _vp.requestFocus();
101                 boolean button1 = (arg0.getButton() == MouseEvent.BUTTON1);
102                 boolean button2 = (arg0.getButton() == MouseEvent.BUTTON2);
103                 boolean button3 = (arg0.getButton() == MouseEvent.BUTTON3);
104                 boolean shift = arg0.isShiftDown();
105                 boolean ctrl = arg0.isControlDown();
106                 boolean alt = arg0.isAltDown();
107                 _vp.removeSelectedAnnotation();
108                 if (button1 && !ctrl && !alt && !shift)
109                 {
110                         if (_vp.isModifiable()) 
111                         {
112                                 _currentState = MouseStates.MOVE_OR_SELECT_ELEMENT;
113                                 if (_vp.getRealCoords() != null
114                                                 && _vp.getRealCoords().length != 0
115                                                 && _vp.getRNA().get_listeBases().size() != 0) 
116                                 {
117                                         _selectedBase = _vp.getNearestBase(arg0.getX(),arg0.getY(),false,false);
118                                         TextAnnotation selectedAnnotation = _vp.getNearestAnnotation(arg0.getX(), arg0.getY());
119                                         _initialPoint = new Point(arg0.getX(),arg0.getY());
120                                         _currentPoint = new Point(_initialPoint);
121                                         _prevPoint = new Point(_initialPoint);
122                                         if (_selectedBase != null)
123                                         { 
124                                                 if (_vp.getRNA().get_drawMode() == RNA.DRAW_MODE_RADIATE) 
125                                                 {
126                                                         _vp.highlightSelectedBase(_selectedBase);
127                                                 } else {
128                                                         if (!_vp.getSelectionIndices().contains(_selectedBase.getIndex()))
129                                                         {
130                                                                 _vp.highlightSelectedBase(_selectedBase);
131                                                         }
132                                                         else
133                                                         {
134                                                           // Otherwise, keep current selection as it is and move it
135                                                         }
136                                                 }
137                                         }
138                                         else
139                                         {
140                                                 if (selectedAnnotation != null)
141                                                 {
142                                                         _currentState = MouseStates.MOVE_ANNOTATION;
143                                                         _vp.set_selectedAnnotation(selectedAnnotation);
144                                                         _vp.highlightSelectedAnnotation();
145                                                 }
146                                                 else
147                                                 {
148                                                         _vp.clearSelection();
149                                                         _selectedBase = null;
150                                                         _currentState = MouseStates.SELECT_REGION_OR_UNSELECT;
151                                                         _initialPoint = new Point(arg0.getX(),arg0.getY());
152                                                         _prevPoint = new Point(_initialPoint);
153                                                         _currentPoint = new Point(_initialPoint);
154                                                 }
155                                         }
156                                 }
157                         }
158                 }
159                 else if (button1 && ctrl && !alt && !shift)
160                 {
161                         _selectedBase = _vp.getNearestBase(arg0.getX(),arg0.getY(),false,false);
162                         if (_selectedBase != null)
163                         { 
164                                 _vp.clearSelection();
165                                 _currentState = MouseStates.CREATE_BP;
166                                 _vp.highlightSelectedBase(_selectedBase);
167                                 _vp.setOriginLink(_vp.logicToPanel(_selectedBase.getCoords()));
168                                 _initialPoint = new Point(arg0.getX(),arg0.getY());
169                                 _currentPoint = new Point(_initialPoint);
170                         }
171                 }
172                 else if (button1 && !ctrl && !alt && shift)
173                 {
174                         _currentState = MouseStates.SELECT_ELEMENT;
175                         _initialPoint = new Point(arg0.getX(),arg0.getY());
176                         _currentPoint = new Point(_initialPoint);
177                 }
178                 else if (button3) 
179                 {
180                         _currentState = MouseStates.POPUP_MENU;
181                         if (_presenceMenuSelection) {
182                                 _vp.getPopupMenu().removeSelectionMenu();
183                         }
184                         if ((_vp.getRealCoords() != null) && _vp.getRNA().get_listeBases().size() != 0) {
185                                 updateNearestBase(arg0);
186                                 // on insere dans le menu les nouvelles options
187                                 addMenu(arg0);
188                                 if (_vp.get_selectedAnnotation() != null)
189                                         _vp.highlightSelectedAnnotation();
190                         }
191                         // affichage du popup menu
192                         if (_vp.getRNA().get_drawMode() == RNA.DRAW_MODE_LINEAR) {
193                                 _vp.getPopup().get_rotation().setEnabled(false);
194                         } else {
195                                 _vp.getPopup().get_rotation().setEnabled(true);
196                         }
197                         _vp.getPopup().updateDialog();
198                         _vp.getPopup().show(_vp, arg0.getX(), arg0.getY());
199                 }
200                 _vp.repaint();
201         }
202
203         public void mouseDragged(MouseEvent me) {
204                 if ((_currentState == MouseStates.MOVE_OR_SELECT_ELEMENT)||(_currentState == MouseStates.MOVE_ELEMENT))
205                 {
206                         _vp.lockScrolling();
207
208                         _currentState = MouseStates.MOVE_ELEMENT;
209                                 // si on deplace la souris et qu'une base est selectionnée
210                                 if (_selectedBase != null) {
211                                         if (_vp.getRNA().get_drawMode() == RNA.DRAW_MODE_RADIATE) {
212                                                 _vp.highlightSelectedStem(_selectedBase);
213                                                 // dans le cas radiale on deplace une helice
214                                                 _vp.getVARNAUI().UIMoveHelixAtom(_selectedBase.getIndex(), _vp.panelToLogicPoint(new Point2D.Double(me.getX(), me.getY())));
215                                         } else {
216                                                 // dans le cas circulaire naview ou line on deplace une base
217                                                 _currentPoint = new Point(me.getX(), me.getY());
218                                                 moveSelection(_prevPoint,_currentPoint);
219                                                 _prevPoint = new Point(_currentPoint);
220                                         }
221                                         _vp.repaint();
222                                 }
223                 }
224                 else if (_currentState == MouseStates.MOVE_ANNOTATION)
225                 {
226                         if (_vp.get_selectedAnnotation()!=null)
227                         {
228                                 Point2D.Double p = _vp.panelToLogicPoint(new Point2D.Double(me.getX(), me.getY()));
229                                 _vp.get_selectedAnnotation().setAncrage(p.x,p.y);
230                                 _vp.repaint();
231                         }                       
232                 }
233                 else if ((_currentState == MouseStates.SELECT_ELEMENT)||(_currentState == MouseStates.SELECT_REGION_OR_UNSELECT))
234                 {
235                         if (_initialPoint.distance(me.getX(),me.getY())>HYSTERESIS_DISTANCE)
236                                 _currentState = MouseStates.SELECT_REGION;
237                 }
238                 else if (_currentState == MouseStates.SELECT_REGION)
239                 {
240                         _currentPoint = new Point(me.getX(),me.getY());
241                         int minx = Math.min(_currentPoint.x, _initialPoint.x);
242                         int miny = Math.min(_currentPoint.y, _initialPoint.y);
243                         int maxx = Math.max(_currentPoint.x, _initialPoint.x);
244                         int maxy = Math.max(_currentPoint.y, _initialPoint.y);
245                         _vp.setSelectionRectangle(new Rectangle(minx,miny,maxx-minx,maxy-miny));
246                 }
247                 else if (_currentState == MouseStates.CREATE_BP)
248                 {
249                         if (_initialPoint.distance(me.getX(),me.getY())>HYSTERESIS_DISTANCE)
250                         {
251                                 ModeleBase newSelectedBase = _vp.getNearestBase(me.getX(),me.getY(),false,false);
252                                 _vp.setHoverBase(newSelectedBase);
253                                 if (newSelectedBase==null)
254                                 {
255                                         _vp.setDestinationLink(new Point2D.Double(me.getX(),me.getY()));
256                                         _vp.clearSelection();
257                                         _vp.addToSelection(_selectedBase.getIndex());
258                                 }
259                                 else
260                                 {
261                                         ModeleBase mborig = _selectedBase;
262                                         _vp.clearSelection();
263                                         _vp.addToSelection(newSelectedBase.getIndex());
264                                         _vp.addToSelection(mborig.getIndex());
265                                         _vp.setDestinationLink(_vp.logicToPanel(newSelectedBase.getCoords()));
266                                 }
267                                 _vp.repaint();
268                         }
269                         
270                 }
271         }
272
273
274         public void mouseReleased(MouseEvent arg0) {
275                 if (arg0.getButton() == MouseEvent.BUTTON1)
276                 {
277                         _vp.fireBaseClicked(_selectedBase, arg0);       
278                         //System.out.println(""+_currentState);
279                         
280                         if (_currentState == MouseStates.MOVE_ELEMENT)
281                         {
282                                 _vp.clearSelection();
283                                 _selectedBase = null;
284                                 _vp.unlockScrolling();
285                                 _vp.removeSelectedAnnotation();
286                         }
287                         else if (_currentState == MouseStates.SELECT_REGION_OR_UNSELECT)
288                         {
289                                 _vp.clearSelection();
290                                 _selectedBase = null;
291                                 _vp.removeSelectedAnnotation();
292                         }
293                         else if (_currentState == MouseStates.SELECT_ELEMENT)
294                         {
295                                 if (_vp.getRealCoords() != null
296                                                 && _vp.getRealCoords().length != 0
297                                                 && _vp.getRNA().get_listeBases().size() != 0) 
298                                         {
299                                                 int selectedIndex = _vp.getNearestBaseIndex(arg0.getX(),arg0.getY(),false,false);
300                                                 if (selectedIndex !=-1)
301                                                 { 
302                                                         _vp.toggleSelection(selectedIndex);
303                                                 }
304                                         }
305                                 _selectedBase = null;
306                         }
307                         else if (_currentState == MouseStates.SELECT_REGION)
308                         {
309                           _vp.removeSelectionRectangle();
310                         }
311                         else if (_currentState == MouseStates.CREATE_BP)
312                         {
313                                 if (_initialPoint.distance(arg0.getX(),arg0.getY())>HYSTERESIS_DISTANCE)
314                                 {
315                                         int selectedIndex = _vp.getNearestBaseIndex(arg0.getX(),arg0.getY(),false,false);
316                                         if (selectedIndex>=0)
317                                         {
318                                                 ModeleBase mb = _vp.getNearestBase(arg0.getX(),arg0.getY(),false,false);
319                                                 ModeleBase mborig = _selectedBase;
320                                                 ModeleBP msbp = new ModeleBP(mb,mborig); 
321                                                 if (mb!=mborig)
322                                                 {
323                                                   _vp.getVARNAUI().UIAddBP(mb.getIndex(),mborig.getIndex(),msbp);
324                                                 }
325                                         }
326                                 }
327                                 _vp.removeLink();
328                                 _vp.clearSelection();
329                                 _vp.repaint();
330                         }
331                         else
332                         {
333                                 _vp.clearSelection();
334                         }
335
336                 }
337                 _currentState = MouseStates.NONE;
338                 _vp.repaint();          
339         }
340
341
342         private void addMenu(MouseEvent arg0) {
343                 // creation du menu
344                 _submenuSelection = new JMenu("Selection");
345                 addCurrent();
346                 // ajout des option sur base
347                 addMenuBase();
348                 // ajout des option sur paire de base
349                 if (_vp.getRNA().get_listeBases().get(_vp.getNearestBase())
350                                 .getElementStructure() != -1) {
351                         addMenuBasePair();
352                 }
353
354                 // detection renflement
355                 detectBulge();
356                 // detection 3'
357                 detect3Prime();
358                 // detection 5'
359                 detect5Prime();
360                 // detection boucle
361                 detectLoop();
362                 // detection d'helice
363                 detectHelix();
364                 // detection tige
365                 detectStem();
366                 // Ajout de toutes bases
367                 addAllBase();
368                 // detection d'annotation
369                 detectAnnotation(arg0);
370
371                 _vp.getPopup().addSelectionMenu(_submenuSelection);
372                 _presenceMenuSelection = true;
373         }
374
375         private void detectAnnotation(MouseEvent arg0) {
376                 if (_vp.getListeAnnotations().size() != 0) {
377                         double dist = Double.MAX_VALUE;
378                         double d2;
379                         Point2D.Double position;
380                         for (TextAnnotation textAnnot : _vp.getListeAnnotations()) {
381                                 // calcul de la distance
382                                 position = textAnnot.getCenterPosition();
383                                 position = _vp.transformCoord(position);
384                                 d2 = Math.sqrt(Math.pow((position.x - arg0.getX()), 2)
385                                                 + Math.pow((position.y - arg0.getY()), 2));
386                                 // si la valeur est inferieur au minimum actuel
387                                 if (dist > d2) {
388                                         _vp.set_selectedAnnotation(textAnnot);
389                                         dist = d2;
390                                 }
391                         }
392                         _submenuSelection.addSeparator();
393                         _vp.getPopup().addAnnotationMenu(_submenuSelection,true);
394                 }
395         }
396
397         private void detectBulge() {
398                 int indiceB = _vp.getNearestBase();
399                 ArrayList<Integer> indices = _vp.getRNA().findBulge(indiceB);
400                 if ((indices.size() > 0)
401                                 && (_vp.getRNA().getHelixCountOnLoop(_vp.getNearestBase()) == 2)) {
402                         JMenu submenuBulge = new JMenu("Bulge");
403                         submenuBulge.addChangeListener(new ControleurSelectionHighlight(
404                                         new Vector<Integer>(indices), _vp, submenuBulge));
405                         submenuBulge.setActionCommand("bulge");
406                         if (!_vp.isModifiable())
407                                 submenuBulge.setEnabled(false);
408                         _vp.getPopupMenu().addColorOptions(submenuBulge);
409                         _submenuSelection.add(submenuBulge);
410                 }
411         }
412
413         private void detectHelix() {
414                 int indiceH = _vp.getNearestBase();
415                 ArrayList<Integer> indices = _vp.getRNA().findHelix(indiceH);
416                 if (indices.size() != 0) {
417                         // ajout menu helice
418                         JMenu submenuHelix = new JMenu("Helix");
419                         submenuHelix.addChangeListener(new ControleurSelectionHighlight(
420                                         new Vector<Integer>(indices), _vp, submenuHelix));
421                         submenuHelix.setActionCommand("helix");
422                         if (!_vp.isModifiable())
423                                 submenuHelix.setEnabled(false);
424                         _vp.getPopupMenu().addColorOptions(submenuHelix);
425                         submenuHelix.addSeparator();
426                         _vp.getPopupMenu().addAnnotationMenu(submenuHelix);
427                         _submenuSelection.add(submenuHelix);
428                 }
429         }
430
431         private void detectStem() {
432                 int indiceS = _vp.getNearestBase();
433                 ArrayList<Integer> indices = _vp.getRNA().findStem(indiceS);
434                 if (indices.size() > 0) {
435                         JMenu submenuStem = new JMenu("Stem");
436                         submenuStem.addChangeListener(new ControleurSelectionHighlight(
437                                         new Vector<Integer>(indices), _vp, submenuStem));
438                         submenuStem.setActionCommand("stem");
439                         if (!_vp.isModifiable())
440                                 submenuStem.setEnabled(false);
441                         _vp.getPopupMenu().addColorOptions(submenuStem);
442                         _submenuSelection.add(submenuStem);
443                 }
444         }
445
446         private void detect3Prime() {
447                 // detection 3'
448                 int indice3 = _vp.getNearestBase();
449                 ArrayList<Integer> indices = _vp.getRNA().find3Prime(indice3);
450                 if (indices.size() != 0) {
451                         JMenu submenu3Prime = new JMenu("3'");
452                         submenu3Prime.addChangeListener(new ControleurSelectionHighlight(
453                                         new Vector<Integer>(indices), _vp, submenu3Prime));
454                         submenu3Prime.setActionCommand("3'");
455                         if (!_vp.isModifiable())
456                                 submenu3Prime.setEnabled(false);
457                         _vp.getPopupMenu().addColorOptions(submenu3Prime);
458                         _submenuSelection.add(submenu3Prime);
459                 }
460         }
461
462         private void detect5Prime() {
463                 int indice5 = _vp.getNearestBase();
464                 ArrayList<Integer> indices = _vp.getRNA().find5Prime(indice5);
465                 if (indices.size() != 0) {
466                         JMenu submenu5Prime = new JMenu("5'");
467                         submenu5Prime.addChangeListener(new ControleurSelectionHighlight(
468                                         new Vector<Integer>(indices), _vp, submenu5Prime));
469                         submenu5Prime.setActionCommand("5'");
470                         if (!_vp.isModifiable())
471                                 submenu5Prime.setEnabled(false);
472                         _vp.getPopupMenu().addColorOptions(submenu5Prime);
473                         _submenuSelection.add(submenu5Prime);
474                 }
475         }
476
477         private void detectLoop() {
478                 int indexL = _vp.getNearestBase();
479                 if (_vp.getRNA().get_listeBases().get(indexL).getElementStructure() == -1) {
480                         ArrayList<Integer> listLoop = _vp.getRNA().findLoop(indexL);
481                         JMenu submenuLoop = new JMenu("Loop");
482                         submenuLoop.addChangeListener(new ControleurSelectionHighlight(
483                                         listLoop, _vp, submenuLoop));
484                         submenuLoop.setActionCommand("loop1");
485                         if (!_vp.isModifiable())
486                                 submenuLoop.setEnabled(false);
487                         _vp.getPopupMenu().addColorOptions(submenuLoop);
488                         submenuLoop.addSeparator();
489                         _vp.getPopupMenu().addAnnotationMenu(submenuLoop);
490                         _submenuSelection.add(submenuLoop);
491                 } else {
492                         ArrayList<Integer> listLoop1 = _vp.getRNA().findLoopForward(indexL);
493                         if (listLoop1.size() > 0) {
494                                 JMenu submenuLoop1 = new JMenu("Forward loop");
495                                 submenuLoop1
496                                                 .addChangeListener(new ControleurSelectionHighlight(
497                                                                 listLoop1, _vp, submenuLoop1));
498                                 submenuLoop1.setActionCommand("loop1");
499                                 if (!_vp.isModifiable())
500                                         submenuLoop1.setEnabled(false);
501                                 _vp.getPopupMenu().addColorOptions(submenuLoop1);
502                                 submenuLoop1.addSeparator();
503                                 _vp.getPopupMenu().addAnnotationMenu(submenuLoop1);
504                                 _submenuSelection.add(submenuLoop1);
505                         }
506                         ArrayList<Integer> listLoop2 = _vp.getRNA()
507                                         .findLoopBackward(indexL);
508                         if (listLoop2.size() > 0) {
509                                 JMenu submenuLoop2 = new JMenu("Backward loop");
510                                 submenuLoop2
511                                                 .addChangeListener(new ControleurSelectionHighlight(
512                                                                 listLoop2, _vp, submenuLoop2));
513                                 submenuLoop2.setActionCommand("loop2");
514                                 if (!_vp.isModifiable())
515                                         submenuLoop2.setEnabled(false);
516                                 _vp.getPopupMenu().addColorOptions(submenuLoop2);
517                                 submenuLoop2.addSeparator();
518                                 _vp.getPopupMenu().addAnnotationMenu(submenuLoop2);
519                                 _submenuSelection.add(submenuLoop2);
520                         }
521                 }
522         }
523
524         private void addCurrent() {
525                 Collection<? extends ModeleBase> mbs = _vp.getSelection().getBases();
526                 if (mbs.size()>0)
527                 {
528                 JMenu submenuAll = new JMenu("Current");
529                 submenuAll.addChangeListener(new ControleurSelectionHighlight(
530                                 mbs, _vp, submenuAll));
531                 submenuAll.setActionCommand("current");
532                 if (!_vp.isModifiable())
533                         submenuAll.setEnabled(false);
534                 _vp.getPopupMenu().addColorOptions(submenuAll);
535                 _submenuSelection.add(submenuAll);
536                 }
537         }
538         
539         
540         private void addMenuBase() {
541                 JMenu submenuBase = new JMenu();
542                 ModeleBase mb = _vp.getRNA().get_listeBases().get(_vp.getNearestBase());
543                 if (mb instanceof ModeleBasesComparison) {
544                         submenuBase.setText("Base #" + (mb.getBaseNumber()) + ":"
545                                         + ((ModeleBasesComparison) mb).getBases());
546                 } else {
547                         submenuBase.setText("Base #" + (mb.getBaseNumber()) + ":"
548                                         + ((ModeleBaseNucleotide) mb).getBase());
549                 }
550                 submenuBase.addChangeListener(new ControleurSelectionHighlight(mb
551                                 .getIndex(), _vp, submenuBase));
552                 submenuBase.setActionCommand("base");
553                 // option disponible seulement en mode modifiable
554                 if (!_vp.isModifiable())
555                         submenuBase.setEnabled(false);
556
557                 JMenuItem baseChar = new JMenuItem("Edit base");
558                 baseChar.setActionCommand("baseChar");
559                 baseChar.addActionListener(_vp.getPopupMenu().get_controleurMenu());
560                 submenuBase.add(baseChar);
561                 _vp.getPopupMenu().addColorOptions(submenuBase);
562                 submenuBase.addSeparator();
563                 _vp.getPopupMenu().addAnnotationMenu(submenuBase);
564                 _submenuSelection.add(submenuBase);
565         }
566
567         private void addAllBase() {
568                 ArrayList<Integer> indices = _vp.getRNA().findAll();
569                 JMenu submenuAll = new JMenu("All");
570                 submenuAll.addChangeListener(new ControleurSelectionHighlight(
571                                 new Vector<Integer>(indices), _vp, submenuAll));
572                 submenuAll.setActionCommand("all");
573                 if (!_vp.isModifiable())
574                         submenuAll.setEnabled(false);
575                 _vp.getPopupMenu().addColorOptions(submenuAll);
576                 _submenuSelection.add(submenuAll);
577         }
578
579         private void addMenuBasePair() {
580                         int indiceBP = _vp.getNearestBase();
581                         ArrayList<Integer> indices = _vp.getRNA().findPair(indiceBP);
582                         ModeleBase base = _vp.getRNA()
583                                         .get_listeBases().get(_vp.getNearestBase());
584                         if (base.getElementStructure() != -1) {
585                                 JMenu submenuBasePair = new JMenu();
586                                 ModeleBase partner = _vp
587                                                 .getRNA().get_listeBases().get(
588                                                                 base.getElementStructure());
589                                 submenuBasePair
590                                                 .addChangeListener(new ControleurSelectionHighlight(
591                                                                 indices, _vp, submenuBasePair));
592                                 submenuBasePair.setText("Base pair #("
593                                                 + (Math.min(base.getBaseNumber(), partner
594                                                                 .getBaseNumber()))
595                                                 + ","
596                                                 + (Math.max(base.getBaseNumber(), partner
597                                                                 .getBaseNumber())) + ")");
598                                 submenuBasePair.setActionCommand("bp");
599                                 // option disponible seulement en mode modifiable
600                                 if (!_vp.isModifiable())
601                                         submenuBasePair.setEnabled(false);
602
603                                 JMenuItem basepair = new JMenuItem("Edit BP");
604                                 basepair.setActionCommand("basepair");
605                                 basepair.addActionListener(_vp.getPopupMenu()
606                                                 .get_controleurMenu());
607
608                                 _vp.getPopupMenu().addColorOptions(submenuBasePair);
609                                 Component[] comps = submenuBasePair.getMenuComponents();
610                                 int offset = -1;
611                                 for (int i = 0; i < comps.length; i++) {
612                                         Component c = comps[i];
613                                         if (c instanceof JMenuItem) {
614                                                 JMenuItem jmi = (JMenuItem) c;
615                                                 if (jmi.getActionCommand().contains(",BPColor")) {
616                                                         offset = i;
617                                                 }
618                                         }
619                                 }
620                                 if (offset != -1) {
621                                         submenuBasePair.insert(basepair, offset);
622                                 } else {
623                                         submenuBasePair.add(basepair);
624                                 }
625                                 _submenuSelection.add(submenuBasePair);
626                         }
627                 }
628
629         private void updateNearestBase(MouseEvent arg0) {
630                 int i = _vp.getNearestBaseIndex(arg0.getX(),arg0.getY(),true,false);
631                 if (i!=-1)
632                         _vp.setNearestBase(i);
633         }
634
635
636
637         
638         public void mouseMoved(MouseEvent arg0) {
639                 _selectedBase = _vp.getNearestBase(arg0.getX(),arg0.getY());
640                 TextAnnotation selectedAnnotation = _vp.getNearestAnnotation(arg0.getX(),arg0.getY());
641                 _vp.setHoverBase(_selectedBase);
642                 if (_selectedBase != null)
643                 {
644                 }
645                 else if (selectedAnnotation!=null)
646                 {
647                         _vp.set_selectedAnnotation(selectedAnnotation);
648                         _vp.highlightSelectedAnnotation();
649                         _vp.repaint();
650                 }
651                 _vp.setLastSelectedPosition(new Point2D.Double(arg0.getX(),arg0.getY()));
652         }
653
654         
655         
656         private void moveSelection(Point prev, Point cur) 
657         {
658                 Point2D.Double p1 =  _vp.panelToLogicPoint(new Point2D.Double(prev.x,prev.y));
659                 Point2D.Double p2 =  _vp.panelToLogicPoint(new Point2D.Double(cur.x,cur.y));
660                 double dx = (p2.x - p1.x);
661                 double dy = (p2.y - p1.y);
662                 
663                 if (_vp.isModifiable())
664                 {  
665                         double ndx = dx;
666                         double ndy = dy;
667                         if (_vp.getRNA().get_drawMode() == RNA.DRAW_MODE_LINEAR) 
668                         {
669                                 ndy=0.0;
670                         }
671                         _vp.getVARNAUI().UIShiftBaseCoord(_vp.getSelectionIndices(), ndx, ndy);
672                         _vp.fireLayoutChanged();
673                         
674                 }
675         }
676
677
678         public void popupMenuCanceled(PopupMenuEvent arg0) {
679         }
680
681         public void popupMenuWillBecomeInvisible(PopupMenuEvent arg0) {
682                 _vp.resetAnnotationHighlight();
683                 _selectedBase = null;
684         }
685
686         public void popupMenuWillBecomeVisible(PopupMenuEvent arg0) {
687         }
688 }