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