JAL-2446 merged to spike branch
[jalview.git] / src / jalview / appletgui / 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.appletgui;
22
23 import jalview.util.MessageManager;
24 import jalview.util.Platform;
25 import jalview.viewmodel.OverviewDimensions;
26 import jalview.viewmodel.OverviewDimensionsHideHidden;
27 import jalview.viewmodel.OverviewDimensionsShowHidden;
28 import jalview.viewmodel.ViewportListenerI;
29
30 import java.awt.BorderLayout;
31 import java.awt.CheckboxMenuItem;
32 import java.awt.Dimension;
33 import java.awt.Panel;
34 import java.awt.PopupMenu;
35 import java.awt.event.ComponentAdapter;
36 import java.awt.event.ComponentEvent;
37 import java.awt.event.InputEvent;
38 import java.awt.event.ItemEvent;
39 import java.awt.event.ItemListener;
40 import java.awt.event.MouseEvent;
41 import java.awt.event.MouseListener;
42 import java.awt.event.MouseMotionListener;
43 import java.beans.PropertyChangeEvent;
44
45 public class OverviewPanel extends Panel implements Runnable,
46         MouseMotionListener, MouseListener, ViewportListenerI
47 {
48   private OverviewDimensions od;
49
50   private OverviewCanvas oviewCanvas;
51
52   private AlignViewport av;
53
54   private AlignmentPanel ap;
55
56   private boolean showHidden = true;
57
58   private boolean updateRunning = false;
59
60   public OverviewPanel(AlignmentPanel alPanel)
61   {
62     this.av = alPanel.av;
63     this.ap = alPanel;
64     setLayout(null);
65
66     od = new OverviewDimensionsShowHidden(av.getRanges(),
67             (av.isShowAnnotation() && av.getSequenceConsensusHash() != null));
68
69     oviewCanvas = new OverviewCanvas(od, av);
70     setLayout(new BorderLayout());
71     add(oviewCanvas, BorderLayout.CENTER);
72
73     setSize(new Dimension(od.getWidth(), od.getHeight()));
74
75     av.getRanges().addPropertyChangeListener(this);
76
77     addComponentListener(new ComponentAdapter()
78     {
79
80       @Override
81       public void componentResized(ComponentEvent evt)
82       {
83         if ((getWidth() != od.getWidth())
84                 || (getHeight() != (od.getHeight())))
85         {
86           updateOverviewImage();
87         }
88       }
89     });
90
91     addMouseMotionListener(this);
92
93     addMouseListener(this);
94
95     updateOverviewImage();
96
97   }
98
99   @Override
100   public void mouseEntered(MouseEvent evt)
101   {
102   }
103
104   @Override
105   public void mouseExited(MouseEvent evt)
106   {
107   }
108
109   @Override
110   public void mouseClicked(MouseEvent evt)
111   {
112     if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
113     {
114       showPopupMenu(evt);
115     }
116   }
117
118   @Override
119   public void mouseMoved(MouseEvent evt)
120   {
121   }
122
123   @Override
124   public void mousePressed(MouseEvent evt)
125   {
126     mouseAction(evt);
127   }
128
129   @Override
130   public void mouseReleased(MouseEvent evt)
131   {
132     mouseAction(evt);
133   }
134
135   @Override
136   public void mouseDragged(MouseEvent evt)
137   {
138     mouseAction(evt);
139   }
140
141   private void mouseAction(MouseEvent evt)
142   {
143     if ((evt.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)
144     {
145       if (!Platform.isAMac())
146       {
147         showPopupMenu(evt);
148       }
149     }
150     else
151     {
152       od.updateViewportFromMouse(evt.getX(), evt.getY(), av.getAlignment()
153               .getHiddenSequences(), av.getAlignment().getHiddenColumns());
154       ap.paintAlignment(false);
155     }
156   }
157
158   /**
159    * Updates the overview image when the related alignment panel is updated
160    */
161   public void updateOverviewImage()
162   {
163     if ((getSize().width > 0) && (getSize().height > 0))
164     {
165       od.setWidth(getSize().width);
166       od.setHeight(getSize().height);
167     }
168     setSize(new Dimension(od.getWidth(), od.getHeight()));
169
170     synchronized (this)
171     {
172       if (updateRunning)
173       {
174         oviewCanvas.restartDraw();
175         return;
176       }
177
178       updateRunning = true;
179     }
180     Thread thread = new Thread(this);
181     thread.start();
182     repaint();
183     updateRunning = false;
184   }
185
186   @Override
187   public void run()
188   {
189     oviewCanvas.draw(av.isShowSequenceFeatures(),
190             (av.isShowAnnotation() && av
191                     .getAlignmentConservationAnnotation() != null),
192             ap.seqPanel.seqCanvas.getFeatureRenderer());
193     setBoxPosition();
194   }
195
196   /**
197    * Update the overview panel box when the associated alignment panel is
198    * changed
199    * 
200    */
201   private void setBoxPosition()
202   {
203     od.setBoxPosition(av.getAlignment()
204 .getHiddenSequences(), av
205             .getAlignment().getHiddenColumns());
206     repaint();
207   }
208
209   /*
210    * Displays the popup menu and acts on user input
211    */
212   private void showPopupMenu(MouseEvent e)
213   {
214     PopupMenu popup = new PopupMenu();
215     ItemListener menuListener = new ItemListener()
216     {
217       @Override
218       public void itemStateChanged(ItemEvent e)
219       {
220         toggleHiddenColumns();
221       }
222     };
223     CheckboxMenuItem item = new CheckboxMenuItem(
224             MessageManager.getString("label.togglehidden"));
225     item.setState(showHidden);
226     popup.add(item);
227     item.addItemListener(menuListener);
228     this.add(popup);
229     popup.show(this, e.getX(), e.getY());
230   }
231
232   @Override
233   public void propertyChange(PropertyChangeEvent evt)
234   {
235     setBoxPosition();
236   }
237
238   /*
239    * Toggle overview display between showing hidden columns and hiding hidden columns
240    */
241   private void toggleHiddenColumns()
242   {
243     if (showHidden)
244     {
245       showHidden = false;
246       od = new OverviewDimensionsHideHidden(av.getRanges(),
247               (av.isShowAnnotation() && av
248                       .getAlignmentConservationAnnotation() != null));
249     }
250     else
251     {
252       showHidden = true;
253       od = new OverviewDimensionsShowHidden(av.getRanges(),
254               (av.isShowAnnotation() && av
255                       .getAlignmentConservationAnnotation() != null));
256     }
257     oviewCanvas.resetOviewDims(od);
258     updateOverviewImage();
259   }
260 }