JAL-3026 srcjar files for VARNA and log4j
[jalview.git] / srcjar / fr / orsay / lri / varna / controlers / ControleurClicMovement.java
diff --git a/srcjar/fr/orsay/lri/varna/controlers/ControleurClicMovement.java b/srcjar/fr/orsay/lri/varna/controlers/ControleurClicMovement.java
new file mode 100644 (file)
index 0000000..4212106
--- /dev/null
@@ -0,0 +1,688 @@
+/*
+ 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.
+ Copyright (C) 2008  Kevin Darty, Alain Denise and Yann Ponty.
+ electronic mail : Yann.Ponty@lri.fr
+ paper mail : LRI, bat 490 Université Paris-Sud 91405 Orsay Cedex France
+
+ This file is part of VARNA version 3.1.
+ VARNA version 3.1 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
+
+ VARNA version 3.1 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with VARNA version 3.1.
+ If not, see http://www.gnu.org/licenses.
+ */
+package fr.orsay.lri.varna.controlers;
+
+import java.awt.Component;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Vector;
+
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.event.PopupMenuEvent;
+import javax.swing.event.PopupMenuListener;
+
+import fr.orsay.lri.varna.VARNAPanel;
+import fr.orsay.lri.varna.exceptions.ExceptionNAViewAlgorithm;
+import fr.orsay.lri.varna.models.annotations.TextAnnotation;
+import fr.orsay.lri.varna.models.rna.ModeleBase;
+import fr.orsay.lri.varna.models.rna.ModeleBaseNucleotide;
+import fr.orsay.lri.varna.models.rna.ModeleBasesComparison;
+import fr.orsay.lri.varna.models.rna.ModeleBP;
+import fr.orsay.lri.varna.models.rna.RNA;
+
+
+/**
+ * Controller of the mouse click
+ * 
+ * @author darty
+ * 
+ */
+public class ControleurClicMovement implements MouseListener,
+               MouseMotionListener, PopupMenuListener {
+       private VARNAPanel _vp;
+       private boolean _presenceMenuSelection;
+       private JMenu _submenuSelection;
+       public Point _spawnPoint;       
+       public Point _initialPoint;
+       public Point _prevPoint;
+       public Point _currentPoint;
+
+       public static final double MIN_SELECTION_DISTANCE = 40.0;
+       public static final double HYSTERESIS_DISTANCE = 10.0;
+       
+       private ModeleBase _selectedBase = null;
+       
+       
+       public enum MouseStates {
+               NONE,
+               MOVE_ELEMENT,
+               MOVE_OR_SELECT_ELEMENT,
+               SELECT_ELEMENT,
+               SELECT_REGION_OR_UNSELECT,
+               SELECT_REGION,
+               CREATE_BP,
+               POPUP_MENU,
+               MOVE_ANNOTATION,
+       };
+       private MouseStates _currentState = MouseStates.NONE;
+       
+
+
+       public ControleurClicMovement(VARNAPanel _vuep) {
+               _vp = _vuep;
+               _vp.getPopup().addPopupMenuListener(this);
+               _presenceMenuSelection = false;
+       }
+
+       public void mouseClicked(MouseEvent arg0) {
+       }
+
+       public void mouseEntered(MouseEvent arg0) {
+       }
+
+       public void mouseExited(MouseEvent arg0) {
+       }
+
+       public void mousePressed(MouseEvent arg0) 
+       {
+               _vp.requestFocus();
+               boolean button1 = (arg0.getButton() == MouseEvent.BUTTON1);
+               boolean button2 = (arg0.getButton() == MouseEvent.BUTTON2);
+               boolean button3 = (arg0.getButton() == MouseEvent.BUTTON3);
+               boolean shift = arg0.isShiftDown();
+               boolean ctrl = arg0.isControlDown();
+               boolean alt = arg0.isAltDown();
+               _vp.removeSelectedAnnotation();
+               if (button1 && !ctrl && !alt && !shift)
+               {
+                       if (_vp.isModifiable()) 
+                       {
+                               _currentState = MouseStates.MOVE_OR_SELECT_ELEMENT;
+                               if (_vp.getRealCoords() != null
+                                               && _vp.getRealCoords().length != 0
+                                               && _vp.getRNA().get_listeBases().size() != 0) 
+                               {
+                                       _selectedBase = _vp.getNearestBase(arg0.getX(),arg0.getY(),false,false);
+                                       TextAnnotation selectedAnnotation = _vp.getNearestAnnotation(arg0.getX(), arg0.getY());
+                                       _initialPoint = new Point(arg0.getX(),arg0.getY());
+                                       _currentPoint = new Point(_initialPoint);
+                                       _prevPoint = new Point(_initialPoint);
+                                       if (_selectedBase != null)
+                                       { 
+                                               if (_vp.getRNA().get_drawMode() == RNA.DRAW_MODE_RADIATE) 
+                                               {
+                                                       _vp.highlightSelectedBase(_selectedBase);
+                                               } else {
+                                                       if (!_vp.getSelectionIndices().contains(_selectedBase.getIndex()))
+                                                       {
+                                                               _vp.highlightSelectedBase(_selectedBase);
+                                                       }
+                                                       else
+                                                       {
+                                                         // Otherwise, keep current selection as it is and move it
+                                                       }
+                                               }
+                                       }
+                                       else
+                                       {
+                                               if (selectedAnnotation != null)
+                                               {
+                                                       _currentState = MouseStates.MOVE_ANNOTATION;
+                                                       _vp.set_selectedAnnotation(selectedAnnotation);
+                                                       _vp.highlightSelectedAnnotation();
+                                               }
+                                               else
+                                               {
+                                                       _vp.clearSelection();
+                                                       _selectedBase = null;
+                                                       _currentState = MouseStates.SELECT_REGION_OR_UNSELECT;
+                                                       _initialPoint = new Point(arg0.getX(),arg0.getY());
+                                                       _prevPoint = new Point(_initialPoint);
+                                                       _currentPoint = new Point(_initialPoint);
+                                               }
+                                       }
+                               }
+                       }
+               }
+               else if (button1 && ctrl && !alt && !shift)
+               {
+                       _selectedBase = _vp.getNearestBase(arg0.getX(),arg0.getY(),false,false);
+                       if (_selectedBase != null)
+                       { 
+                               _vp.clearSelection();
+                               _currentState = MouseStates.CREATE_BP;
+                               _vp.highlightSelectedBase(_selectedBase);
+                               _vp.setOriginLink(_vp.logicToPanel(_selectedBase.getCoords()));
+                               _initialPoint = new Point(arg0.getX(),arg0.getY());
+                               _currentPoint = new Point(_initialPoint);
+                       }
+               }
+               else if (button1 && !ctrl && !alt && shift)
+               {
+                       _currentState = MouseStates.SELECT_ELEMENT;
+                       _initialPoint = new Point(arg0.getX(),arg0.getY());
+                       _currentPoint = new Point(_initialPoint);
+               }
+               else if (button3) 
+               {
+                       _currentState = MouseStates.POPUP_MENU;
+                       if (_presenceMenuSelection) {
+                               _vp.getPopupMenu().removeSelectionMenu();
+                       }
+                       if ((_vp.getRealCoords() != null) && _vp.getRNA().get_listeBases().size() != 0) {
+                               updateNearestBase(arg0);
+                               // on insere dans le menu les nouvelles options
+                               addMenu(arg0);
+                               if (_vp.get_selectedAnnotation() != null)
+                                       _vp.highlightSelectedAnnotation();
+                       }
+                       // affichage du popup menu
+                       if (_vp.getRNA().get_drawMode() == RNA.DRAW_MODE_LINEAR) {
+                               _vp.getPopup().get_rotation().setEnabled(false);
+                       } else {
+                               _vp.getPopup().get_rotation().setEnabled(true);
+                       }
+                       _vp.getPopup().updateDialog();
+                       _vp.getPopup().show(_vp, arg0.getX(), arg0.getY());
+               }
+               _vp.repaint();
+       }
+
+       public void mouseDragged(MouseEvent me) {
+               if ((_currentState == MouseStates.MOVE_OR_SELECT_ELEMENT)||(_currentState == MouseStates.MOVE_ELEMENT))
+               {
+                       _vp.lockScrolling();
+
+                       _currentState = MouseStates.MOVE_ELEMENT;
+                               // si on deplace la souris et qu'une base est selectionnée
+                               if (_selectedBase != null) {
+                                       if (_vp.getRNA().get_drawMode() == RNA.DRAW_MODE_RADIATE) {
+                                               _vp.highlightSelectedStem(_selectedBase);
+                                               // dans le cas radiale on deplace une helice
+                                               _vp.getVARNAUI().UIMoveHelixAtom(_selectedBase.getIndex(), _vp.panelToLogicPoint(new Point2D.Double(me.getX(), me.getY())));
+                                       } else {
+                                               // dans le cas circulaire naview ou line on deplace une base
+                                               _currentPoint = new Point(me.getX(), me.getY());
+                                               moveSelection(_prevPoint,_currentPoint);
+                                               _prevPoint = new Point(_currentPoint);
+                                       }
+                                       _vp.repaint();
+                               }
+               }
+               else if (_currentState == MouseStates.MOVE_ANNOTATION)
+               {
+                       if (_vp.get_selectedAnnotation()!=null)
+                       {
+                               Point2D.Double p = _vp.panelToLogicPoint(new Point2D.Double(me.getX(), me.getY()));
+                               _vp.get_selectedAnnotation().setAncrage(p.x,p.y);
+                               _vp.repaint();
+                       }                       
+               }
+               else if ((_currentState == MouseStates.SELECT_ELEMENT)||(_currentState == MouseStates.SELECT_REGION_OR_UNSELECT))
+               {
+                       if (_initialPoint.distance(me.getX(),me.getY())>HYSTERESIS_DISTANCE)
+                               _currentState = MouseStates.SELECT_REGION;
+               }
+               else if (_currentState == MouseStates.SELECT_REGION)
+               {
+                       _currentPoint = new Point(me.getX(),me.getY());
+                       int minx = Math.min(_currentPoint.x, _initialPoint.x);
+                       int miny = Math.min(_currentPoint.y, _initialPoint.y);
+                       int maxx = Math.max(_currentPoint.x, _initialPoint.x);
+                       int maxy = Math.max(_currentPoint.y, _initialPoint.y);
+                       _vp.setSelectionRectangle(new Rectangle(minx,miny,maxx-minx,maxy-miny));
+               }
+               else if (_currentState == MouseStates.CREATE_BP)
+               {
+                       if (_initialPoint.distance(me.getX(),me.getY())>HYSTERESIS_DISTANCE)
+                       {
+                               ModeleBase newSelectedBase = _vp.getNearestBase(me.getX(),me.getY(),false,false);
+                               _vp.setHoverBase(newSelectedBase);
+                               if (newSelectedBase==null)
+                               {
+                                       _vp.setDestinationLink(new Point2D.Double(me.getX(),me.getY()));
+                                       _vp.clearSelection();
+                                       _vp.addToSelection(_selectedBase.getIndex());
+                               }
+                               else
+                               {
+                                       ModeleBase mborig = _selectedBase;
+                                       _vp.clearSelection();
+                                       _vp.addToSelection(newSelectedBase.getIndex());
+                                       _vp.addToSelection(mborig.getIndex());
+                                       _vp.setDestinationLink(_vp.logicToPanel(newSelectedBase.getCoords()));
+                               }
+                               _vp.repaint();
+                       }
+                       
+               }
+       }
+
+
+       public void mouseReleased(MouseEvent arg0) {
+               if (arg0.getButton() == MouseEvent.BUTTON1)
+               {
+                       _vp.fireBaseClicked(_selectedBase, arg0);       
+                       //System.out.println(""+_currentState);
+                       
+                       if (_currentState == MouseStates.MOVE_ELEMENT)
+                       {
+                               _vp.clearSelection();
+                               _selectedBase = null;
+                               _vp.unlockScrolling();
+                               _vp.removeSelectedAnnotation();
+                       }
+                       else if (_currentState == MouseStates.SELECT_REGION_OR_UNSELECT)
+                       {
+                               _vp.clearSelection();
+                               _selectedBase = null;
+                               _vp.removeSelectedAnnotation();
+                       }
+                       else if (_currentState == MouseStates.SELECT_ELEMENT)
+                       {
+                               if (_vp.getRealCoords() != null
+                                               && _vp.getRealCoords().length != 0
+                                               && _vp.getRNA().get_listeBases().size() != 0) 
+                                       {
+                                               int selectedIndex = _vp.getNearestBaseIndex(arg0.getX(),arg0.getY(),false,false);
+                                               if (selectedIndex !=-1)
+                                               { 
+                                                       _vp.toggleSelection(selectedIndex);
+                                               }
+                                       }
+                               _selectedBase = null;
+                       }
+                       else if (_currentState == MouseStates.SELECT_REGION)
+                       {
+                         _vp.removeSelectionRectangle();
+                       }
+                       else if (_currentState == MouseStates.CREATE_BP)
+                       {
+                               if (_initialPoint.distance(arg0.getX(),arg0.getY())>HYSTERESIS_DISTANCE)
+                               {
+                                       int selectedIndex = _vp.getNearestBaseIndex(arg0.getX(),arg0.getY(),false,false);
+                                       if (selectedIndex>=0)
+                                       {
+                                               ModeleBase mb = _vp.getNearestBase(arg0.getX(),arg0.getY(),false,false);
+                                               ModeleBase mborig = _selectedBase;
+                                               ModeleBP msbp = new ModeleBP(mb,mborig); 
+                                               if (mb!=mborig)
+                                               {
+                                                 _vp.getVARNAUI().UIAddBP(mb.getIndex(),mborig.getIndex(),msbp);
+                                               }
+                                       }
+                               }
+                               _vp.removeLink();
+                               _vp.clearSelection();
+                               _vp.repaint();
+                       }
+                       else
+                       {
+                               _vp.clearSelection();
+                       }
+
+               }
+               _currentState = MouseStates.NONE;
+               _vp.repaint();          
+       }
+
+
+       private void addMenu(MouseEvent arg0) {
+               // creation du menu
+               _submenuSelection = new JMenu("Selection");
+               addCurrent();
+               // ajout des option sur base
+               addMenuBase();
+               // ajout des option sur paire de base
+               if (_vp.getRNA().get_listeBases().get(_vp.getNearestBase())
+                               .getElementStructure() != -1) {
+                       addMenuBasePair();
+               }
+
+               // detection renflement
+               detectBulge();
+               // detection 3'
+               detect3Prime();
+               // detection 5'
+               detect5Prime();
+               // detection boucle
+               detectLoop();
+               // detection d'helice
+               detectHelix();
+               // detection tige
+               detectStem();
+               // Ajout de toutes bases
+               addAllBase();
+               // detection d'annotation
+               detectAnnotation(arg0);
+
+               _vp.getPopup().addSelectionMenu(_submenuSelection);
+               _presenceMenuSelection = true;
+       }
+
+       private void detectAnnotation(MouseEvent arg0) {
+               if (_vp.getListeAnnotations().size() != 0) {
+                       double dist = Double.MAX_VALUE;
+                       double d2;
+                       Point2D.Double position;
+                       for (TextAnnotation textAnnot : _vp.getListeAnnotations()) {
+                               // calcul de la distance
+                               position = textAnnot.getCenterPosition();
+                               position = _vp.transformCoord(position);
+                               d2 = Math.sqrt(Math.pow((position.x - arg0.getX()), 2)
+                                               + Math.pow((position.y - arg0.getY()), 2));
+                               // si la valeur est inferieur au minimum actuel
+                               if (dist > d2) {
+                                       _vp.set_selectedAnnotation(textAnnot);
+                                       dist = d2;
+                               }
+                       }
+                       _submenuSelection.addSeparator();
+                       _vp.getPopup().addAnnotationMenu(_submenuSelection,true);
+               }
+       }
+
+       private void detectBulge() {
+               int indiceB = _vp.getNearestBase();
+               ArrayList<Integer> indices = _vp.getRNA().findBulge(indiceB);
+               if ((indices.size() > 0)
+                               && (_vp.getRNA().getHelixCountOnLoop(_vp.getNearestBase()) == 2)) {
+                       JMenu submenuBulge = new JMenu("Bulge");
+                       submenuBulge.addChangeListener(new ControleurSelectionHighlight(
+                                       new Vector<Integer>(indices), _vp, submenuBulge));
+                       submenuBulge.setActionCommand("bulge");
+                       if (!_vp.isModifiable())
+                               submenuBulge.setEnabled(false);
+                       _vp.getPopupMenu().addColorOptions(submenuBulge);
+                       _submenuSelection.add(submenuBulge);
+               }
+       }
+
+       private void detectHelix() {
+               int indiceH = _vp.getNearestBase();
+               ArrayList<Integer> indices = _vp.getRNA().findHelix(indiceH);
+               if (indices.size() != 0) {
+                       // ajout menu helice
+                       JMenu submenuHelix = new JMenu("Helix");
+                       submenuHelix.addChangeListener(new ControleurSelectionHighlight(
+                                       new Vector<Integer>(indices), _vp, submenuHelix));
+                       submenuHelix.setActionCommand("helix");
+                       if (!_vp.isModifiable())
+                               submenuHelix.setEnabled(false);
+                       _vp.getPopupMenu().addColorOptions(submenuHelix);
+                       submenuHelix.addSeparator();
+                       _vp.getPopupMenu().addAnnotationMenu(submenuHelix);
+                       _submenuSelection.add(submenuHelix);
+               }
+       }
+
+       private void detectStem() {
+               int indiceS = _vp.getNearestBase();
+               ArrayList<Integer> indices = _vp.getRNA().findStem(indiceS);
+               if (indices.size() > 0) {
+                       JMenu submenuStem = new JMenu("Stem");
+                       submenuStem.addChangeListener(new ControleurSelectionHighlight(
+                                       new Vector<Integer>(indices), _vp, submenuStem));
+                       submenuStem.setActionCommand("stem");
+                       if (!_vp.isModifiable())
+                               submenuStem.setEnabled(false);
+                       _vp.getPopupMenu().addColorOptions(submenuStem);
+                       _submenuSelection.add(submenuStem);
+               }
+       }
+
+       private void detect3Prime() {
+               // detection 3'
+               int indice3 = _vp.getNearestBase();
+               ArrayList<Integer> indices = _vp.getRNA().find3Prime(indice3);
+               if (indices.size() != 0) {
+                       JMenu submenu3Prime = new JMenu("3'");
+                       submenu3Prime.addChangeListener(new ControleurSelectionHighlight(
+                                       new Vector<Integer>(indices), _vp, submenu3Prime));
+                       submenu3Prime.setActionCommand("3'");
+                       if (!_vp.isModifiable())
+                               submenu3Prime.setEnabled(false);
+                       _vp.getPopupMenu().addColorOptions(submenu3Prime);
+                       _submenuSelection.add(submenu3Prime);
+               }
+       }
+
+       private void detect5Prime() {
+               int indice5 = _vp.getNearestBase();
+               ArrayList<Integer> indices = _vp.getRNA().find5Prime(indice5);
+               if (indices.size() != 0) {
+                       JMenu submenu5Prime = new JMenu("5'");
+                       submenu5Prime.addChangeListener(new ControleurSelectionHighlight(
+                                       new Vector<Integer>(indices), _vp, submenu5Prime));
+                       submenu5Prime.setActionCommand("5'");
+                       if (!_vp.isModifiable())
+                               submenu5Prime.setEnabled(false);
+                       _vp.getPopupMenu().addColorOptions(submenu5Prime);
+                       _submenuSelection.add(submenu5Prime);
+               }
+       }
+
+       private void detectLoop() {
+               int indexL = _vp.getNearestBase();
+               if (_vp.getRNA().get_listeBases().get(indexL).getElementStructure() == -1) {
+                       ArrayList<Integer> listLoop = _vp.getRNA().findLoop(indexL);
+                       JMenu submenuLoop = new JMenu("Loop");
+                       submenuLoop.addChangeListener(new ControleurSelectionHighlight(
+                                       listLoop, _vp, submenuLoop));
+                       submenuLoop.setActionCommand("loop1");
+                       if (!_vp.isModifiable())
+                               submenuLoop.setEnabled(false);
+                       _vp.getPopupMenu().addColorOptions(submenuLoop);
+                       submenuLoop.addSeparator();
+                       _vp.getPopupMenu().addAnnotationMenu(submenuLoop);
+                       _submenuSelection.add(submenuLoop);
+               } else {
+                       ArrayList<Integer> listLoop1 = _vp.getRNA().findLoopForward(indexL);
+                       if (listLoop1.size() > 0) {
+                               JMenu submenuLoop1 = new JMenu("Forward loop");
+                               submenuLoop1
+                                               .addChangeListener(new ControleurSelectionHighlight(
+                                                               listLoop1, _vp, submenuLoop1));
+                               submenuLoop1.setActionCommand("loop1");
+                               if (!_vp.isModifiable())
+                                       submenuLoop1.setEnabled(false);
+                               _vp.getPopupMenu().addColorOptions(submenuLoop1);
+                               submenuLoop1.addSeparator();
+                               _vp.getPopupMenu().addAnnotationMenu(submenuLoop1);
+                               _submenuSelection.add(submenuLoop1);
+                       }
+                       ArrayList<Integer> listLoop2 = _vp.getRNA()
+                                       .findLoopBackward(indexL);
+                       if (listLoop2.size() > 0) {
+                               JMenu submenuLoop2 = new JMenu("Backward loop");
+                               submenuLoop2
+                                               .addChangeListener(new ControleurSelectionHighlight(
+                                                               listLoop2, _vp, submenuLoop2));
+                               submenuLoop2.setActionCommand("loop2");
+                               if (!_vp.isModifiable())
+                                       submenuLoop2.setEnabled(false);
+                               _vp.getPopupMenu().addColorOptions(submenuLoop2);
+                               submenuLoop2.addSeparator();
+                               _vp.getPopupMenu().addAnnotationMenu(submenuLoop2);
+                               _submenuSelection.add(submenuLoop2);
+                       }
+               }
+       }
+
+       private void addCurrent() {
+               Collection<? extends ModeleBase> mbs = _vp.getSelection().getBases();
+               if (mbs.size()>0)
+               {
+               JMenu submenuAll = new JMenu("Current");
+               submenuAll.addChangeListener(new ControleurSelectionHighlight(
+                               mbs, _vp, submenuAll));
+               submenuAll.setActionCommand("current");
+               if (!_vp.isModifiable())
+                       submenuAll.setEnabled(false);
+               _vp.getPopupMenu().addColorOptions(submenuAll);
+               _submenuSelection.add(submenuAll);
+               }
+       }
+       
+       
+       private void addMenuBase() {
+               JMenu submenuBase = new JMenu();
+               ModeleBase mb = _vp.getRNA().get_listeBases().get(_vp.getNearestBase());
+               if (mb instanceof ModeleBasesComparison) {
+                       submenuBase.setText("Base #" + (mb.getBaseNumber()) + ":"
+                                       + ((ModeleBasesComparison) mb).getBases());
+               } else {
+                       submenuBase.setText("Base #" + (mb.getBaseNumber()) + ":"
+                                       + ((ModeleBaseNucleotide) mb).getBase());
+               }
+               submenuBase.addChangeListener(new ControleurSelectionHighlight(mb
+                               .getIndex(), _vp, submenuBase));
+               submenuBase.setActionCommand("base");
+               // option disponible seulement en mode modifiable
+               if (!_vp.isModifiable())
+                       submenuBase.setEnabled(false);
+
+               JMenuItem baseChar = new JMenuItem("Edit base");
+               baseChar.setActionCommand("baseChar");
+               baseChar.addActionListener(_vp.getPopupMenu().get_controleurMenu());
+               submenuBase.add(baseChar);
+               _vp.getPopupMenu().addColorOptions(submenuBase);
+               submenuBase.addSeparator();
+               _vp.getPopupMenu().addAnnotationMenu(submenuBase);
+               _submenuSelection.add(submenuBase);
+       }
+
+       private void addAllBase() {
+               ArrayList<Integer> indices = _vp.getRNA().findAll();
+               JMenu submenuAll = new JMenu("All");
+               submenuAll.addChangeListener(new ControleurSelectionHighlight(
+                               new Vector<Integer>(indices), _vp, submenuAll));
+               submenuAll.setActionCommand("all");
+               if (!_vp.isModifiable())
+                       submenuAll.setEnabled(false);
+               _vp.getPopupMenu().addColorOptions(submenuAll);
+               _submenuSelection.add(submenuAll);
+       }
+
+       private void addMenuBasePair() {
+                       int indiceBP = _vp.getNearestBase();
+                       ArrayList<Integer> indices = _vp.getRNA().findPair(indiceBP);
+                       ModeleBase base = _vp.getRNA()
+                                       .get_listeBases().get(_vp.getNearestBase());
+                       if (base.getElementStructure() != -1) {
+                               JMenu submenuBasePair = new JMenu();
+                               ModeleBase partner = _vp
+                                               .getRNA().get_listeBases().get(
+                                                               base.getElementStructure());
+                               submenuBasePair
+                                               .addChangeListener(new ControleurSelectionHighlight(
+                                                               indices, _vp, submenuBasePair));
+                               submenuBasePair.setText("Base pair #("
+                                               + (Math.min(base.getBaseNumber(), partner
+                                                               .getBaseNumber()))
+                                               + ","
+                                               + (Math.max(base.getBaseNumber(), partner
+                                                               .getBaseNumber())) + ")");
+                               submenuBasePair.setActionCommand("bp");
+                               // option disponible seulement en mode modifiable
+                               if (!_vp.isModifiable())
+                                       submenuBasePair.setEnabled(false);
+
+                               JMenuItem basepair = new JMenuItem("Edit BP");
+                               basepair.setActionCommand("basepair");
+                               basepair.addActionListener(_vp.getPopupMenu()
+                                               .get_controleurMenu());
+
+                               _vp.getPopupMenu().addColorOptions(submenuBasePair);
+                               Component[] comps = submenuBasePair.getMenuComponents();
+                               int offset = -1;
+                               for (int i = 0; i < comps.length; i++) {
+                                       Component c = comps[i];
+                                       if (c instanceof JMenuItem) {
+                                               JMenuItem jmi = (JMenuItem) c;
+                                               if (jmi.getActionCommand().contains(",BPColor")) {
+                                                       offset = i;
+                                               }
+                                       }
+                               }
+                               if (offset != -1) {
+                                       submenuBasePair.insert(basepair, offset);
+                               } else {
+                                       submenuBasePair.add(basepair);
+                               }
+                               _submenuSelection.add(submenuBasePair);
+                       }
+               }
+
+       private void updateNearestBase(MouseEvent arg0) {
+               int i = _vp.getNearestBaseIndex(arg0.getX(),arg0.getY(),true,false);
+               if (i!=-1)
+                       _vp.setNearestBase(i);
+       }
+
+
+
+       
+       public void mouseMoved(MouseEvent arg0) {
+               _selectedBase = _vp.getNearestBase(arg0.getX(),arg0.getY());
+               TextAnnotation selectedAnnotation = _vp.getNearestAnnotation(arg0.getX(),arg0.getY());
+               _vp.setHoverBase(_selectedBase);
+               if (_selectedBase != null)
+               {
+               }
+               else if (selectedAnnotation!=null)
+               {
+                       _vp.set_selectedAnnotation(selectedAnnotation);
+                       _vp.highlightSelectedAnnotation();
+                       _vp.repaint();
+               }
+               _vp.setLastSelectedPosition(new Point2D.Double(arg0.getX(),arg0.getY()));
+       }
+
+       
+       
+       private void moveSelection(Point prev, Point cur) 
+       {
+               Point2D.Double p1 =  _vp.panelToLogicPoint(new Point2D.Double(prev.x,prev.y));
+               Point2D.Double p2 =  _vp.panelToLogicPoint(new Point2D.Double(cur.x,cur.y));
+               double dx = (p2.x - p1.x);
+               double dy = (p2.y - p1.y);
+               
+               if (_vp.isModifiable())
+               {  
+                       double ndx = dx;
+                       double ndy = dy;
+                       if (_vp.getRNA().get_drawMode() == RNA.DRAW_MODE_LINEAR) 
+                       {
+                               ndy=0.0;
+                       }
+                       _vp.getVARNAUI().UIShiftBaseCoord(_vp.getSelectionIndices(), ndx, ndy);
+                       _vp.fireLayoutChanged();
+                       
+               }
+       }
+
+
+       public void popupMenuCanceled(PopupMenuEvent arg0) {
+       }
+
+       public void popupMenuWillBecomeInvisible(PopupMenuEvent arg0) {
+               _vp.resetAnnotationHighlight();
+               _selectedBase = null;
+       }
+
+       public void popupMenuWillBecomeVisible(PopupMenuEvent arg0) {
+       }
+}
\ No newline at end of file