Merge remote-tracking branch
[jalview.git] / src / jalview / gui / OverviewPanel.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.gui;
22
23 import jalview.util.MessageManager;
24 import jalview.util.Platform;
25 import jalview.viewmodel.OverviewDimensions;
26 import jalview.viewmodel.OverviewDimensionsAllVisible;
27 import jalview.viewmodel.OverviewDimensionsWithHidden;
28
29 import java.awt.BorderLayout;
30 import java.awt.Dimension;
31 import java.awt.event.ActionEvent;
32 import java.awt.event.ActionListener;
33 import java.awt.event.ComponentAdapter;
34 import java.awt.event.ComponentEvent;
35 import java.awt.event.MouseAdapter;
36 import java.awt.event.MouseEvent;
37 import java.awt.event.MouseMotionAdapter;
38
39 import javax.swing.JMenuItem;
40 import javax.swing.JPanel;
41 import javax.swing.JPopupMenu;
42 import javax.swing.SwingUtilities;
43
44 /**
45  * Panel displaying an overview of the full alignment, with an interactive box
46  * representing the viewport onto the alignment.
47  * 
48  * @author $author$
49  * @version $Revision$
50  */
51 public class OverviewPanel extends JPanel implements Runnable
52 {
53   private OverviewDimensions od;
54
55   private OverviewCanvas oviewCanvas;
56
57   private AlignViewport av;
58
59   private AlignmentPanel ap;
60
61   private boolean showHidden = true;
62
63   /**
64    * Creates a new OverviewPanel object.
65    * 
66    * @param alPanel
67    *          The alignment panel which is shown in the overview panel
68    */
69   public OverviewPanel(AlignmentPanel alPanel)
70   {
71     this.av = alPanel.av;
72     this.ap = alPanel;
73
74     od = new OverviewDimensionsWithHidden(av.getRanges(),
75             (av.isShowAnnotation() && av
76                     .getAlignmentConservationAnnotation() != null));
77
78     oviewCanvas = new OverviewCanvas(od, av);
79     setLayout(new BorderLayout());
80     add(oviewCanvas, BorderLayout.CENTER);
81
82     addComponentListener(new ComponentAdapter()
83     {
84       @Override
85       public void componentResized(ComponentEvent evt)
86       {
87         if ((getWidth() != od.getWidth())
88                 || (getHeight() != (od.getHeight())))
89         {
90           updateOverviewImage();
91         }
92       }
93     });
94
95     addMouseMotionListener(new MouseMotionAdapter()
96     {
97       @Override
98       public void mouseDragged(MouseEvent evt)
99       {
100         if (!SwingUtilities.isRightMouseButton(evt)
101                 && !av.getWrapAlignment())
102         {
103           od.updateViewportFromMouse(evt.getX(), evt.getY(), av
104                   .getAlignment().getHiddenSequences(), av.getAlignment()
105                   .getHiddenColumns(), av.getRanges());
106           ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
107         }
108       }
109     });
110
111     addMouseListener(new MouseAdapter()
112     {
113       @Override
114       public void mousePressed(MouseEvent evt)
115       {
116         if (SwingUtilities.isRightMouseButton(evt))
117         {
118           if (!Platform.isAMac())
119           {
120             showPopupMenu(evt);
121           }
122         }
123         else if (!av.getWrapAlignment())
124         {
125           od.updateViewportFromMouse(evt.getX(), evt.getY(), av
126                   .getAlignment().getHiddenSequences(), av.getAlignment()
127                   .getHiddenColumns(), av.getRanges());
128           ap.setScrollValues(od.getScrollCol(), od.getScrollRow());
129         }
130       }
131
132       @Override
133       public void mouseClicked(MouseEvent evt)
134       {
135         if (SwingUtilities.isRightMouseButton(evt))
136         {
137           showPopupMenu(evt);
138         }
139       }
140     });
141
142
143     updateOverviewImage();
144   }
145
146   /*
147    * Displays the popup menu and acts on user input
148    */
149   private void showPopupMenu(MouseEvent e)
150   {
151     JPopupMenu popup = new JPopupMenu();
152     ActionListener menuListener = new ActionListener()
153     {
154       @Override
155       public void actionPerformed(ActionEvent event)
156       {
157         // switch on/off the hidden columns view
158         toggleHiddenColumns();
159       }
160     };
161     JMenuItem item = new JMenuItem(
162             MessageManager.getString("label.togglehidden"));
163     popup.add(item);
164     item.addActionListener(menuListener);
165     popup.show(this, e.getX(), e.getY());
166   }
167
168   /*
169    * Toggle overview display between showing hidden columns and hiding hidden columns
170    */
171   private void toggleHiddenColumns()
172   {
173     if (showHidden)
174     {
175       showHidden = false;
176       od = new OverviewDimensionsAllVisible(av.getRanges(),
177               (av.isShowAnnotation() && av
178                       .getAlignmentConservationAnnotation() != null));
179     }
180     else
181     {
182       showHidden = true;
183       od = new OverviewDimensionsWithHidden(av.getRanges(),
184               (av.isShowAnnotation() && av
185                       .getAlignmentConservationAnnotation() != null));
186     }
187     oviewCanvas.resetOviewDims(od);
188     updateOverviewImage();
189   }
190
191   /**
192    * Updates the overview image when the related alignment panel is updated
193    */
194   public void updateOverviewImage()
195   {
196     if ((getWidth() > 0) && (getHeight() > 0))
197     {
198       od.setWidth(getWidth());
199       od.setHeight(getHeight());
200     }
201
202     setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
203
204     if (oviewCanvas.restartDraw())
205     {
206       return;
207     }
208
209     Thread thread = new Thread(this);
210     thread.start();
211     repaint();
212
213   }
214
215   @Override
216   public void run()
217   {
218     oviewCanvas.draw(av.isShowSequenceFeatures(),
219             (av.isShowAnnotation() && av
220                     .getAlignmentConservationAnnotation() != null), ap
221                     .getSeqPanel().seqCanvas.getFeatureRenderer());
222     setBoxPosition();
223   }
224
225   /**
226    * Update the overview panel box when the associated alignment panel is
227    * changed
228    * 
229    */
230   public void setBoxPosition()
231   {
232     od.setBoxPosition(av.getAlignment()
233 .getHiddenSequences(), av
234             .getAlignment().getHiddenColumns(), av.getRanges());
235     repaint();
236   }
237 }