import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
-import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
/**
* The panel containing the sequence ruler (when not in wrapped mode), and
* supports a range of mouse operations to select, hide or reveal columns.
*/
+@SuppressWarnings("serial")
public class ScalePanel extends JPanel
implements MouseMotionListener, MouseListener, ViewportListenerI
{
{
x = av.getAlignment().getHiddenColumns().visibleToAbsoluteColumn(x);
}
-
- if (x >= av.getAlignment().getWidth())
- {
- res = av.getAlignment().getWidth() - 1;
- }
- else
- {
- res = x;
- }
+ res = Math.min(x, av.getAlignment().getWidth() - 1);
min = res;
max = res;
if (evt.isPopupTrigger()) // Mac: mousePressed
{
rightMouseButtonPressed(evt, res);
+ return;
}
- else if (SwingUtilities.isRightMouseButton(evt) && !Platform.isAMac())
+ if (Platform.isWinRightButton(evt))
{
/*
* defer right-mouse click handling to mouse up on Windows
*/
return;
}
- else
- {
- leftMouseButtonPressed(evt, res);
- }
+ leftMouseButtonPressed(evt, res);
}
/**
*/
protected void rightMouseButtonPressed(MouseEvent evt, final int res)
{
+ JPopupMenu pop = buildPopupMenu(res);
+ if (pop.getSubElements().length > 0)
+ {
+ pop.show(this, evt.getX(), evt.getY());
+ }
+ }
+
+ /**
+ * Builds a popup menu with 'Hide' or 'Reveal' options, or both, or neither
+ *
+ * @param res
+ * column number (0..)
+ * @return
+ */
+ protected JPopupMenu buildPopupMenu(final int res)
+ {
JPopupMenu pop = new JPopupMenu();
/*
- * grab the hidden range in case mouseMoved nulls it
+ * logic here depends on 'reveal', set in mouseMoved;
+ * grab the hidden range in case mouseMoved nulls it later
*/
final int[] hiddenRange = reveal;
if (hiddenRange != null)
});
pop.add(item);
- if (av.getAlignment().getHiddenColumns().hasMultiHiddenColumnRegions())
+ if (av.getAlignment().getHiddenColumns()
+ .hasMultiHiddenColumnRegions())
{
item = new JMenuItem(MessageManager.getString("action.reveal_all"));
item.addActionListener(new ActionListener()
});
pop.add(item);
}
- pop.show(this, evt.getX(), evt.getY());
}
- else if (av.getColumnSelection().contains(res))
+
+ if (av.getColumnSelection().contains(res))
{
JMenuItem item = new JMenuItem(
MessageManager.getString("label.hide_columns"));
}
});
pop.add(item);
- pop.show(this, evt.getX(), evt.getY());
}
+ return pop;
}
/**
mouseDragging = false;
ap.getSeqPanel().stopScrolling();
+ // todo res calculation should be a method on AlignViewport
int xCords = Math.max(0, evt.getX()); // prevent negative X coordinates
- int res = (xCords / av.getCharWidth())
- + av.getRanges().getStartRes();
+ ViewportRanges ranges = av.getRanges();
+ int res = (xCords / av.getCharWidth()) + ranges.getStartRes();
+ res = Math.min(res, ranges.getEndRes());
if (av.hasHiddenColumns())
{
res = av.getAlignment().getHiddenColumns()
.visibleToAbsoluteColumn(res);
}
- res = Math.min(res, av.getRanges().getEndRes());
res = Math.max(0, res);
if (!stretchingGroup)
{
if (mouseDragging)
{
+ mouseDragging = false;
ap.getSeqPanel().stopScrolling();
}
}
@Override
public void paintComponent(Graphics g)
{
- super.paintComponent(g);
-
/*
* shouldn't get called in wrapped mode as the scale above is
* drawn instead by SeqCanvas.drawNorthScale
}
}
- // scalewidth will normally be screenwidth,
public void drawScale(Graphics g, int startx, int endx, int width,
int height)
{
gg.fillPolygon(
new int[]
- { -1 + res * avCharWidth - avCharHeight / 4,
- -1 + res * avCharWidth + avCharHeight / 4,
- -1 + res * avCharWidth }, new int[]
- { y, y, y + 2 * yOf }, 3);
+ { -1 + res * avCharWidth - avCharHeight / 4,
+ -1 + res * avCharWidth + avCharHeight / 4,
+ -1 + res * avCharWidth },
+ new int[]
+ { y, y, y + 2 * yOf }, 3);
}
}
}
@Override
public void propertyChange(PropertyChangeEvent evt)
{
- // Respond to viewport change events (e.g. alignment panel was scrolled)
- // Both scrolling and resizing change viewport ranges: scrolling changes
- // both start and end points, but resize only changes end values.
- // Here we only want to fastpaint on a scroll, with resize using a normal
- // paint, so scroll events are identified as changes to the horizontal or
- // vertical start value.
- if (evt.getPropertyName().equals(ViewportRanges.STARTRES)
- || evt.getPropertyName().equals(ViewportRanges.STARTRESANDSEQ)
- || evt.getPropertyName().equals(ViewportRanges.MOVE_VIEWPORT))
+ switch (evt.getPropertyName())
{
+ case ViewportRanges.STARTRES:
+ case ViewportRanges.STARTRESANDSEQ:
+ case ViewportRanges.MOVE_VIEWPORT:
// scroll event, repaint panel
-
- // Call repaint on alignment panel so that repaints from other alignment
- // panel components can be aggregated. Otherwise performance of the overview
- // window and others may be adversely affected.
- av.getAlignPanel().repaint();
+ // original comment:
+ // Call repaint on alignment panel so that repaints from other alignment
+ // panel components can be aggregated. Otherwise performance of the
+ // overview
+ // window and others may be adversely affected.
+
+ // TODO: check this?
+ // BH: This is actually quite strange. AlignmentPanel is taking care of
+ // all of this with fast paint, so why indirectly trigger a repaint from
+ // the ScalePanel? Where do we see this behavior necessary?
+ // I have set this to check for a trigger from some other ViewportRanges,
+ // but I don't actually think that is possible.
+
+ if (evt.getSource() != av.getRanges())
+ {
+ av.getAlignPanel().repaint();
+ }
+ break;
}
}
+ boolean isMouseDragging()
+ {
+ return mouseDragging;
+ }
+
}