JAL-2587 Adjusting height for progress bar
[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.renderer.OverviewRenderer;
24 import jalview.util.MessageManager;
25 import jalview.util.Platform;
26 import jalview.viewmodel.OverviewDimensions;
27 import jalview.viewmodel.OverviewDimensionsHideHidden;
28 import jalview.viewmodel.OverviewDimensionsShowHidden;
29 import jalview.viewmodel.ViewportListenerI;
30
31 import java.awt.BorderLayout;
32 import java.awt.Cursor;
33 import java.awt.Dimension;
34 import java.awt.event.ActionEvent;
35 import java.awt.event.ActionListener;
36 import java.awt.event.ComponentAdapter;
37 import java.awt.event.ComponentEvent;
38 import java.awt.event.MouseAdapter;
39 import java.awt.event.MouseEvent;
40 import java.awt.event.MouseMotionAdapter;
41 import java.beans.PropertyChangeEvent;
42
43 import javax.swing.JCheckBoxMenuItem;
44 import javax.swing.JPanel;
45 import javax.swing.JPopupMenu;
46 import javax.swing.SwingUtilities;
47
48 /**
49  * Panel displaying an overview of the full alignment, with an interactive box
50  * representing the viewport onto the alignment.
51  * 
52  * @author $author$
53  * @version $Revision$
54  */
55 public class OverviewPanel extends JPanel implements Runnable,
56         ViewportListenerI
57 {
58   private OverviewDimensions od;
59
60   private OverviewCanvas oviewCanvas;
61
62   private AlignViewport av;
63
64   private AlignmentPanel ap;
65
66   private JCheckBoxMenuItem displayToggle;
67
68   private boolean showHidden = true;
69
70   private boolean draggingBox = false;
71
72   private ProgressPanel progressPanel;
73
74   /**
75    * Creates a new OverviewPanel object.
76    * 
77    * @param alPanel
78    *          The alignment panel which is shown in the overview panel
79    */
80   public OverviewPanel(AlignmentPanel alPanel)
81   {
82     this.av = alPanel.av;
83     this.ap = alPanel;
84
85     od = new OverviewDimensionsShowHidden(av.getRanges(),
86             (av.isShowAnnotation() && av
87                     .getAlignmentConservationAnnotation() != null));
88
89     // setSize(od.getWidth(), od.getHeight() + 20);
90
91     setLayout(new BorderLayout());
92     progressPanel = new ProgressPanel(OverviewRenderer.UPDATE,
93             MessageManager.getString("label.oview_calc"));
94     this.add(progressPanel, BorderLayout.SOUTH);
95     oviewCanvas = new OverviewCanvas(od, av, progressPanel);
96
97     add(oviewCanvas, BorderLayout.CENTER);
98
99     av.getRanges().addPropertyChangeListener(this);
100
101     addComponentListener(new ComponentAdapter()
102     {
103       @Override
104       public void componentResized(ComponentEvent evt)
105       {
106         updateOverviewImage();
107       }
108
109     });
110
111     addMouseMotionListener(new MouseMotionAdapter()
112     {
113       @Override
114       public void mouseDragged(MouseEvent evt)
115       {
116         if (!SwingUtilities.isRightMouseButton(evt))
117         {
118           if (draggingBox)
119           {
120             // set the mouse position as a fixed point in the box
121             // and drag relative to that position
122             od.adjustViewportFromMouse(evt.getX(),
123                     evt.getY(), av.getAlignment().getHiddenSequences(),
124                     av.getAlignment().getHiddenColumns());
125           }
126           else
127           {
128             od.updateViewportFromMouse(evt.getX(), evt.getY(), av
129                   .getAlignment().getHiddenSequences(), av.getAlignment()
130                   .getHiddenColumns());
131           }
132         }
133       }
134
135       @Override
136       public void mouseMoved(MouseEvent evt)
137       {
138         if (od.isPositionInBox(evt.getX(), evt.getY()))
139         {
140           // display drag cursor at mouse position
141           setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
142         }
143         else
144         {
145           // reset cursor
146           setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
147         }
148       }
149     });
150
151     addMouseListener(new MouseAdapter()
152     {
153       @Override
154       public void mousePressed(MouseEvent evt)
155       {
156         if (SwingUtilities.isRightMouseButton(evt))
157         {
158           if (!Platform.isAMac())
159           {
160             showPopupMenu(evt);
161           }
162         }
163         else
164         {
165           if (!od.isPositionInBox(evt.getX(), evt.getY()))
166           {
167             // don't do anything if the mouse press is in the overview's box
168             // (wait to see if it's a drag instead)
169             // otherwise update the viewport
170             od.updateViewportFromMouse(evt.getX(), evt.getY(),
171                     av.getAlignment().getHiddenSequences(),
172                     av.getAlignment().getHiddenColumns());
173           }
174           else
175           {
176             draggingBox = true;
177             od.setDragPoint(evt.getX(), evt.getY(),
178                     av.getAlignment().getHiddenSequences(),
179                     av.getAlignment().getHiddenColumns());
180           }
181         }
182       }
183
184       @Override
185       public void mouseReleased(MouseEvent evt)
186       {
187         if (draggingBox)
188         {
189           draggingBox = false;
190         }
191       }
192
193       @Override
194       public void mouseClicked(MouseEvent evt)
195       {
196         if (SwingUtilities.isRightMouseButton(evt))
197         {
198           showPopupMenu(evt);
199         }
200       }
201     });
202
203     setPreferredSize(new Dimension(od.getWidth(),
204             od.getHeight()));
205   }
206
207   /*
208    * Displays the popup menu and acts on user input
209    */
210   private void showPopupMenu(MouseEvent e)
211   {
212     JPopupMenu popup = new JPopupMenu();
213     ActionListener menuListener = new ActionListener()
214     {
215       @Override
216       public void actionPerformed(ActionEvent event)
217       {
218         // switch on/off the hidden columns view
219         toggleHiddenColumns();
220         displayToggle.setSelected(showHidden);
221       }
222     };
223     displayToggle = new JCheckBoxMenuItem(
224             MessageManager.getString("label.togglehidden"));
225     displayToggle.setEnabled(true);
226     displayToggle.setSelected(showHidden);
227     popup.add(displayToggle);
228     displayToggle.addActionListener(menuListener);
229     popup.show(this, e.getX(), e.getY());
230   }
231
232   /*
233    * Toggle overview display between showing hidden columns and hiding hidden columns
234    */
235   private void toggleHiddenColumns()
236   {
237     if (showHidden)
238     {
239       showHidden = false;
240       od = new OverviewDimensionsHideHidden(av.getRanges(),
241               (av.isShowAnnotation() && av
242                       .getAlignmentConservationAnnotation() != null));
243     }
244     else
245     {
246       showHidden = true;
247       od = new OverviewDimensionsShowHidden(av.getRanges(),
248               (av.isShowAnnotation() && av
249                       .getAlignmentConservationAnnotation() != null));
250     }
251     oviewCanvas.resetOviewDims(od);
252     updateOverviewImage();
253     setBoxPosition();
254   }
255
256   /**
257    * Updates the overview image when the related alignment panel is updated
258    */
259   public void updateOverviewImage()
260   {
261     if (oviewCanvas == null)
262     {
263       /*
264        * panel has been disposed
265        */
266       return;
267     }
268
269     if ((getWidth() > 0) && (getHeight() > 0))
270     {
271       od.setWidth(getWidth());
272       od.setHeight(getHeight() - progressPanel.getHeight());
273     }
274     
275     setPreferredSize(new Dimension(od.getWidth(),
276             od.getHeight() + progressPanel.getHeight()));
277
278     if (oviewCanvas.restartDraw())
279     {
280       return;
281     }
282
283     Thread thread = new Thread(this);
284     thread.start();
285     repaint();
286
287     
288   }
289
290   @Override
291   public void run()
292   {
293     oviewCanvas.draw(av.isShowSequenceFeatures(),
294             (av.isShowAnnotation() && av
295                     .getAlignmentConservationAnnotation() != null), ap
296                     .getSeqPanel().seqCanvas.getFeatureRenderer());
297     setBoxPosition();
298   }
299
300   /**
301    * Update the overview panel box when the associated alignment panel is
302    * changed
303    * 
304    */
305   private void setBoxPosition()
306   {
307     od.setBoxPosition(av.getAlignment().getHiddenSequences(), av
308             .getAlignment().getHiddenColumns());
309     repaint();
310   }
311
312   @Override
313   public void propertyChange(PropertyChangeEvent evt)
314   {
315     setBoxPosition();
316   }
317
318   /**
319    * Removes this object as a property change listener, and nulls references
320    */
321   protected void dispose()
322   {
323     try
324     {
325       av.getRanges().removePropertyChangeListener(this);
326     } finally
327     {
328       progressPanel = null;
329       av = null;
330       oviewCanvas = null;
331       ap = null;
332       od = null;
333     }
334   }
335 }