001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021package org.biojava.nbio.structure.align.gui.aligpanel;
022
023import org.biojava.nbio.structure.gui.events.AlignmentPositionListener;
024import org.biojava.nbio.structure.gui.util.AlignedPosition;
025
026import java.awt.event.MouseEvent;
027import java.awt.event.MouseListener;
028import java.awt.event.MouseMotionListener;
029import java.util.ArrayList;
030import java.util.List;
031
032/**
033 * Mouse Motion Listener for the {@link MultipleAligPanel},
034 * which provides methods to obtain positions of the mouse
035 * and connect them to the sequence alignment positions using
036 * the information in {@link MultipleAlignmentCoordManager}.
037 *
038 * @author Aleix Lafita
039 *
040 */
041public class MultipleAligPanelMouseMotionListener
042implements MouseMotionListener, MouseListener {
043
044        private MultipleAligPanel parent;
045        private List<AlignmentPositionListener> aligPosListeners;
046        private int prevPos;
047
048        private boolean isDragging ;
049        private AlignedPosition selectionStart;
050        private AlignedPosition selectionEnd;
051        private boolean selectionLocked;
052
053        public MultipleAligPanelMouseMotionListener(MultipleAligPanel parent){
054                this.parent = parent;
055                aligPosListeners = new ArrayList<AlignmentPositionListener>();
056                prevPos = -1;
057                isDragging = false;
058                selectionStart = null;
059                selectionEnd = null;
060                selectionLocked = false;
061        }
062
063        public void addAligPosListener(AlignmentPositionListener li){
064                aligPosListeners.add(li);
065        }
066
067        @Override
068        public void mouseDragged(MouseEvent e) {
069
070                AlignedPosition pos = getCurrentAlignedPosition(e);
071
072                if (pos == null) return;
073                if (prevPos == pos.getPos1() && isDragging) return;
074
075                if (!isDragging) {
076                        isDragging = true;
077                        setSelectionLock(true);
078                }
079
080                if (selectionStart == null)     selectionStart = pos;
081                if (selectionEnd == null) selectionEnd = pos;
082
083                if (pos.getPos1() <= selectionStart.getPos1()) selectionStart = pos;
084                else selectionEnd = pos;
085
086                if (!keyPressed(e)) {
087                        triggerRangeSelected(selectionStart, selectionEnd);
088                } else triggerRangeSelected(selectionStart, selectionEnd);
089
090                prevPos = pos.getPos1();
091        }
092
093        private boolean keyPressed(MouseEvent e) {
094                if (e.isShiftDown() || e.isControlDown() || e.isAltDown())
095                        return true;
096                return false;
097        }
098
099        private void triggerRangeSelected(
100                        AlignedPosition start, AlignedPosition end) {
101                for (AlignmentPositionListener li : aligPosListeners){
102                        li.rangeSelected(start, end);
103                }
104        }
105
106        public void triggerSelectionLocked(boolean b) {
107                selectionLocked = b;
108                for (AlignmentPositionListener li : aligPosListeners){
109                        if (b) li.selectionLocked();
110                        else li.selectionUnlocked();
111                }
112        }
113
114        @Override
115        public void mouseMoved(MouseEvent e) {
116                if ( selectionLocked) return;
117                AlignedPosition pos = getCurrentAlignedPosition(e);
118                if ( pos == null) return;
119
120                triggerMouseOverPosition(pos);
121        }
122
123        private void triggerMouseOverPosition(AlignedPosition pos) {
124                for (AlignmentPositionListener li : aligPosListeners)
125                        li.mouseOverPosition(pos);
126        }
127
128        private AlignedPosition getCurrentAlignedPosition(MouseEvent e) {
129
130                MultipleAlignmentCoordManager coordManager = parent.getCoordManager();
131                int aligSeq = coordManager.getAligSeq(e.getPoint());
132
133                //We are not over a position in the sequences
134                if (aligSeq == -1) return null;
135
136                //Get sequence positions
137                int seqPos = coordManager.getSeqPos(aligSeq, e.getPoint());
138                if (seqPos < 0) return null;
139                if (seqPos >= parent.length) return null;
140
141                AlignedPosition pos = new AlignedPosition();
142                pos.setPos1(seqPos);
143
144                if (parent.getMapSeqToStruct().get(seqPos)!=-1)
145                        pos.setEquivalent(AlignedPosition.EQUIVALENT);
146
147                return pos;
148        }
149
150        public void destroy() {
151                aligPosListeners.clear();
152                parent = null;
153        }
154
155        @Override
156        public void mouseClicked(MouseEvent e) {}
157
158        private void triggerToggleSelection(AlignedPosition pos) {
159                for (AlignmentPositionListener li : aligPosListeners)
160                        li.toggleSelection(pos);
161        }
162
163        @Override
164        public void mouseEntered(MouseEvent e) {}
165
166        @Override
167        public void mouseExited(MouseEvent e) {}
168
169        @Override
170        public void mousePressed(MouseEvent e) {
171
172                selectionStart = null;
173                selectionEnd = null;
174
175                if (!keyPressed(e)) {
176
177                        setSelectionLock(false);
178                        triggerSelectionLocked(false);
179
180                        AlignedPosition pos = getCurrentAlignedPosition(e);
181                        if (pos != null) prevPos = pos.getPos1();
182                }
183        }
184
185        private void setSelectionLock(boolean flag){
186                selectionLocked = flag;
187                triggerSelectionLocked(flag);
188        }
189
190        @Override
191        public void mouseReleased(MouseEvent e) {
192
193                isDragging = false;
194
195                if (keyPressed(e)) {
196                        boolean keepOn = false;
197                        if (!selectionLocked) keepOn = true;
198                        setSelectionLock(true);
199
200                        // add to selection
201                        AlignedPosition pos = getCurrentAlignedPosition(e);
202                        if (pos == null) return;
203
204                        if (keepOn) triggerMouseOverPosition(pos);
205                        else triggerToggleSelection(pos);
206                        prevPos = pos.getPos1();
207                }
208        }
209}