1. Project Clover database Fri Dec 6 2024 13:47:14 GMT
  2. Package jalview.gui

File OverviewPanel.java

 

Coverage histogram

../../img/srcFileCovDistChart6.png
37% of files have more coverage

Code metrics

38
109
23
1
493
330
46
0.42
4.74
23
2

Classes

Class
Line #
Actions
OverviewPanel 59 109 46
0.5823529458.2%
 

Contributing tests

This file is covered by 12 tests. .

Source view

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 java.awt.BorderLayout;
24    import java.awt.Cursor;
25    import java.awt.Dimension;
26    import java.awt.Rectangle;
27    import java.awt.event.ActionEvent;
28    import java.awt.event.ActionListener;
29    import java.awt.event.ComponentAdapter;
30    import java.awt.event.ComponentEvent;
31    import java.awt.event.MouseAdapter;
32    import java.awt.event.MouseEvent;
33    import java.awt.event.MouseMotionAdapter;
34    import java.beans.PropertyChangeEvent;
35    import java.beans.PropertyVetoException;
36   
37    import javax.swing.JCheckBoxMenuItem;
38    import javax.swing.JInternalFrame;
39    import javax.swing.JPanel;
40    import javax.swing.JPopupMenu;
41    import javax.swing.SwingUtilities;
42   
43    import jalview.renderer.OverviewRenderer;
44    import jalview.util.MessageManager;
45    import jalview.util.Platform;
46    import jalview.viewmodel.OverviewDimensions;
47    import jalview.viewmodel.OverviewDimensionsHideHidden;
48    import jalview.viewmodel.OverviewDimensionsShowHidden;
49    import jalview.viewmodel.ViewportListenerI;
50   
51    /**
52    * Panel displaying an overview of the full alignment, with an interactive box
53    * representing the viewport onto the alignment.
54    *
55    * @author $author$
56    * @version $Revision$
57    */
58    @SuppressWarnings("serial")
 
59    public class OverviewPanel extends JPanel
60    implements Runnable, ViewportListenerI
61    {
62    protected OverviewDimensions od;
63   
64    private OverviewCanvas oviewCanvas;
65   
66    protected AlignViewport av;
67   
68    private AlignmentPanel ap;
69   
70    private JInternalFrame internalFrame;
71   
72    protected JCheckBoxMenuItem displayToggle;
73   
74    protected boolean showHidden = true;
75   
76    protected boolean draggingBox = false;
77   
78    protected ProgressPanel progressPanel;
79   
80    /**
81    * Creates a new OverviewPanel object.
82    *
83    * @param alPanel
84    * The alignment panel which is shown in the overview panel
85    * @param frame
86    * @param isShowHidden
87    * TODO
88    */
 
89  43 toggle public OverviewPanel(AlignmentPanel alPanel, JInternalFrame frame,
90    boolean isShowHidden)
91    {
92  43 this.av = alPanel.av;
93  43 this.ap = alPanel;
94  43 this.internalFrame = frame;
95   
96  43 showHidden = isShowHidden;
97  43 if (showHidden)
98    {
99  6 od = new OverviewDimensionsShowHidden(av.getRanges(),
100    (av.isShowAnnotation()
101    && av.getAlignmentConservationAnnotation() != null));
102    }
103    else
104    {
105  37 od = new OverviewDimensionsHideHidden(av.getRanges(),
106    (av.isShowAnnotation()
107    && av.getAlignmentConservationAnnotation() != null));
108    }
109   
110  43 setLayout(new BorderLayout());
111  43 progressPanel = new ProgressPanel(OverviewRenderer.UPDATE,
112    MessageManager.getString("label.oview_calc"), getWidth());
113  43 this.add(progressPanel, BorderLayout.SOUTH);
114  43 oviewCanvas = new OverviewCanvas(od, av, progressPanel);
115   
116  43 add(oviewCanvas, BorderLayout.CENTER);
117   
118  43 av.getRanges().addPropertyChangeListener(this);
119   
120    // without this the overview window does not size to fit the overview canvas
121  43 setPreferredSize(new Dimension(od.getWidth(), od.getHeight()));
122   
123  43 addComponentListener(new ComponentAdapter()
124    {
 
125  98 toggle @Override
126    public void componentResized(ComponentEvent evt)
127    {
128    // Resize is called on the initial display of the overview.
129    // This code adjusts sizes to account for the progress bar if it has not
130    // already been accounted for, which triggers another resize call for
131    // the correct sizing, at which point the overview image is updated.
132    // (This avoids a double recalculation of the image.)
133  98 if (getWidth() == od.getWidth() && getHeight() == od.getHeight()
134    + progressPanel.getHeight())
135    {
136  65 updateOverviewImage();
137    }
138    else
139    {
140  33 if ((getWidth() > 0) && (getHeight() > 0))
141    {
142  22 od.setWidth(getWidth());
143  22 od.setHeight(getHeight() - progressPanel.getHeight());
144    }
145   
146  33 setPreferredSize(new Dimension(od.getWidth(),
147    od.getHeight() + progressPanel.getHeight()));
148    }
149    }
150   
151    });
152   
153  43 addMouseMotionListener(new MouseMotionAdapter()
154    {
 
155  0 toggle @Override
156    public void mouseDragged(MouseEvent evt)
157    {
158  0 if (!SwingUtilities.isRightMouseButton(evt))
159    {
160  0 if (draggingBox)
161    {
162    // set the mouse position as a fixed point in the box
163    // and drag relative to that position
164  0 od.adjustViewportFromMouse(evt.getX(), evt.getY(),
165    av.getAlignment().getHiddenSequences(),
166    av.getAlignment().getHiddenColumns());
167    }
168    else
169    {
170  0 od.updateViewportFromMouse(evt.getX(), evt.getY(),
171    av.getAlignment().getHiddenSequences(),
172    av.getAlignment().getHiddenColumns());
173    }
174    }
175    }
176   
 
177  0 toggle @Override
178    public void mouseMoved(MouseEvent evt)
179    {
180  0 if (od.isPositionInBox(evt.getX(), evt.getY()))
181    {
182    /*
183    * using HAND_CURSOR rather than DRAG_CURSOR
184    * as the latter is not supported on Mac
185    */
186  0 getParent().setCursor(
187    Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
188    }
189    else
190    {
191    // reset cursor
192  0 getParent().setCursor(
193    Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
194    }
195    }
196   
197    });
198   
199  43 addMouseListener(new MouseAdapter()
200    {
 
201  0 toggle @Override
202    public void mousePressed(MouseEvent evt)
203    {
204   
205  0 if (Platform.isWinRightButton(evt))
206    {
207  0 showPopupMenu(evt);
208  0 return;
209    }
210  0 if (SwingUtilities.isRightMouseButton(evt))
211    {
212  0 return;
213    }
214    // don't do anything if the mouse press is in the overview's box
215    // (wait to see if it's a drag instead)
216    // otherwise update the viewport
217  0 if (!od.isPositionInBox(evt.getX(), evt.getY()))
218    {
219  0 draggingBox = false;
220   
221    // display drag cursor at mouse position
222  0 setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
223   
224  0 od.updateViewportFromMouse(evt.getX(), evt.getY(),
225    av.getAlignment().getHiddenSequences(),
226    av.getAlignment().getHiddenColumns());
227  0 getParent().setCursor(
228    Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
229    }
230    else
231    {
232  0 draggingBox = true;
233  0 od.setDragPoint(evt.getX(), evt.getY(),
234    av.getAlignment().getHiddenSequences(),
235    av.getAlignment().getHiddenColumns());
236    }
237    }
238   
 
239  0 toggle @Override
240    public void mouseClicked(MouseEvent evt)
241    {
242  0 if (SwingUtilities.isRightMouseButton(evt))
243    {
244  0 showPopupMenu(evt);
245    }
246    }
247   
 
248  0 toggle @Override
249    public void mouseReleased(MouseEvent evt)
250    {
251  0 draggingBox = false;
252    }
253   
254    });
255   
256    /*
257    * Javascript does not call componentResized on initial display,
258    * so do the update here
259    */
260  43 if (Platform.isJS())
261    {
262  0 updateOverviewImage();
263    }
264    }
265   
266    /*
267    * Displays the popup menu and acts on user input
268    */
 
269  0 toggle protected void showPopupMenu(MouseEvent e)
270    {
271  0 JPopupMenu popup = new JPopupMenu();
272  0 ActionListener menuListener = new ActionListener()
273    {
 
274  0 toggle @Override
275    public void actionPerformed(ActionEvent event)
276    {
277    // switch on/off the hidden columns view
278  0 toggleHiddenColumns();
279  0 displayToggle.setSelected(showHidden);
280    }
281    };
282  0 displayToggle = new JCheckBoxMenuItem(
283    MessageManager.getString("label.togglehidden"));
284  0 displayToggle.setEnabled(true);
285  0 displayToggle.setSelected(showHidden);
286  0 popup.add(displayToggle);
287  0 displayToggle.addActionListener(menuListener);
288  0 popup.show(this, e.getX(), e.getY());
289    }
290   
291    /*
292    * Toggle overview display between showing hidden columns and hiding hidden columns
293    */
 
294  0 toggle protected void toggleHiddenColumns()
295    {
296  0 if (showHidden)
297    {
298  0 showHidden = false;
299  0 od = new OverviewDimensionsHideHidden(av.getRanges(),
300    (av.isShowAnnotation()
301    && av.getAlignmentConservationAnnotation() != null));
302    }
303    else
304    {
305  0 showHidden = true;
306  0 od = new OverviewDimensionsShowHidden(av.getRanges(),
307    (av.isShowAnnotation()
308    && av.getAlignmentConservationAnnotation() != null));
309    }
310  0 oviewCanvas.resetOviewDims(od);
311  0 updateOverviewImage();
312  0 setBoxPosition();
313    }
314   
315    /**
316    * Updates the overview image when the related alignment panel is updated
317    */
 
318  558 toggle public void updateOverviewImage()
319    {
320  558 if (oviewCanvas == null)
321    {
322    /*
323    * panel has been disposed
324    */
325  0 return;
326    }
327   
328  558 if ((getWidth() > 0) && (getHeight() > 0))
329    {
330  557 od.setWidth(getWidth());
331  557 od.setHeight(getHeight() - progressPanel.getHeight());
332    }
333   
334  558 setPreferredSize(new Dimension(od.getWidth(),
335    od.getHeight() + progressPanel.getHeight()));
336   
337  558 if (oviewCanvas.restartDraw())
338    {
339  421 return;
340    }
341   
342  137 Thread thread = new Thread(this);
343  137 thread.start();
344  137 repaint();
345   
346    }
347   
 
348  137 toggle @Override
349    public void run()
350    {
351  137 if (oviewCanvas != null)
352    {
353  134 oviewCanvas.draw(av.isShowSequenceFeatures(),
354    (av.isShowAnnotation()
355    && av.getAlignmentConservationAnnotation() != null),
356    ap.getSeqPanel().seqCanvas.getFeatureRenderer());
357  121 setBoxPosition();
358    }
359    }
360   
361    /**
362    * Update the overview panel box when the associated alignment panel is
363    * changed
364    *
365    */
 
366  118 toggle private void setBoxPositionOnly()
367    {
368  118 if (od != null)
369    {
370  118 int oldX = od.getBoxX();
371  118 int oldY = od.getBoxY();
372  118 int oldWidth = od.getBoxWidth();
373  118 int oldHeight = od.getBoxHeight();
374  118 od.setBoxPosition(av.getAlignment().getHiddenSequences(),
375    av.getAlignment().getHiddenColumns());
376  118 repaint(oldX - 1, oldY - 1, oldWidth + 2, oldHeight + 2);
377  118 repaint(od.getBoxX(), od.getBoxY(), od.getBoxWidth(),
378    od.getBoxHeight());
379    }
380    }
381   
 
382  121 toggle private void setBoxPosition()
383    {
384  121 if (od != null)
385    {
386  121 od.setBoxPosition(av.getAlignment().getHiddenSequences(),
387    av.getAlignment().getHiddenColumns());
388  121 repaint();
389    }
390    }
391   
 
392  118 toggle @Override
393    public void propertyChange(PropertyChangeEvent evt)
394    {
395  118 setBoxPositionOnly();
396    }
397   
398    /**
399    * Removes this object as a property change listener, and nulls references
400    */
 
401  40 toggle protected void dispose()
402    {
403  40 try
404    {
405  40 if (av != null)
406    {
407  40 av.getRanges().removePropertyChangeListener(this);
408    }
409   
410  40 oviewCanvas.dispose();
411   
412    /*
413    * close the parent frame (which also removes it from the
414    * Desktop Windows menu)
415    */
416  40 ((JInternalFrame) SwingUtilities
417    .getAncestorOfClass(JInternalFrame.class, (this)))
418    .setClosed(true);
419    } catch (PropertyVetoException e)
420    {
421    // ignore
422    } finally
423    {
424  40 progressPanel = null;
425  40 av = null;
426  40 oviewCanvas = null;
427  40 ap = null;
428  40 od = null;
429  40 internalFrame = null;
430    }
431    }
432   
 
433  17 toggle public boolean isShowHiddenRegions()
434    {
435  17 return showHidden;
436    }
437   
 
438  59 toggle public OverviewCanvas getCanvas()
439    {
440  59 return oviewCanvas;
441    }
442   
443    /**
444    * Sets the title of the enclosing frame
445    *
446    * @param title
447    */
 
448  113 toggle public void setTitle(String title)
449    {
450  113 internalFrame.setTitle(title);
451    }
452   
453    /**
454    * Returns the title of the enclosing frame
455    *
456    * @return title
457    */
 
458  68 toggle public String getTitle()
459    {
460  68 return internalFrame.getTitle();
461    }
462   
463    /**
464    * Sets the bounds of the frame holding the Overview panel
465    *
466    * @param xpos
467    * @param ypos
468    * @param width
469    * @param height
470    */
 
471  13 toggle public void setFrameBounds(int xpos, int ypos, int width, int height)
472    {
473  13 internalFrame.setBounds(xpos, ypos, width, height);
474    }
475   
476    /**
477    * Returns the bounds of the enclosing frame
478    *
479    * @return
480    */
 
481  16 toggle public Rectangle getFrameBounds()
482    {
483  16 return internalFrame.getBounds();
484    }
485   
486    /**
487    * Closes the frame containing the overview panel
488    */
 
489  12 toggle public void close()
490    {
491  12 internalFrame.dispose();
492    }
493    }