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