Skip to content

Commit

Permalink
8290016: IGV: Fix graph panning when mouse dragged outside of window
Browse files Browse the repository at this point in the history
Reviewed-by: kvn, thartmann
  • Loading branch information
tobiasholenstein committed Jul 21, 2022
1 parent 59e495e commit 604a115
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import com.sun.hotspot.igv.hierarchicallayout.HierarchicalLayoutManager;
import com.sun.hotspot.igv.layout.LayoutGraph;
import com.sun.hotspot.igv.layout.Link;
import com.sun.hotspot.igv.selectioncoordinator.*;
import com.sun.hotspot.igv.selectioncoordinator.SelectionCoordinator;
import com.sun.hotspot.igv.util.ColorIcon;
import com.sun.hotspot.igv.util.CustomSelectAction;
import com.sun.hotspot.igv.util.DoubleClickAction;
Expand Down Expand Up @@ -91,7 +91,6 @@ public class DiagramScene extends ObjectScene implements DiagramViewer {
private Widget bottomRight;
private DiagramViewModel model;
private DiagramViewModel modelCopy;
private WidgetAction zoomAction;
private boolean rebuilding;

/**
Expand Down Expand Up @@ -267,16 +266,6 @@ public void performSelection(Rectangle rectangle) {
}
};

private MouseWheelListener mouseWheelListener = new MouseWheelListener() {

@Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (e.isControlDown()) {
DiagramScene.this.relayoutWithoutLayout(null);
}
}
};

public Point getScrollPosition() {
return getScrollPane().getViewport().getViewPosition();
}
Expand Down Expand Up @@ -406,7 +395,7 @@ public DiagramScene(Action[] actions, Action[] actionsWithSelection, DiagramView
// This panAction handles the event only when the left mouse button is
// pressed without any modifier keys, otherwise it will not consume it
// and the selection action (below) will handle the event
panAction = new CustomizablePanAction(~0, MouseEvent.BUTTON1_DOWN_MASK);
panAction = new CustomizablePanAction(MouseEvent.BUTTON1_DOWN_MASK);
this.getActions().addAction(panAction);

selectAction = new CustomSelectAction(new SelectProvider() {
Expand Down Expand Up @@ -455,17 +444,10 @@ public void select(Widget widget, Point localLocation, boolean invertSelection)
bottomRight.setPreferredLocation(new Point(-BORDER_SIZE, -BORDER_SIZE));
this.addChild(bottomRight);

LayerWidget selectionLayer = new LayerWidget(this);
this.addChild(selectionLayer);

this.setLayout(LayoutFactory.createAbsoluteLayout());

this.getInputBindings().setZoomActionModifiers(Utilities.isMac() ? KeyEvent.META_MASK : KeyEvent.CTRL_MASK);
zoomAction = ActionFactory.createMouseCenteredZoomAction(1.2);
this.getActions().addAction(zoomAction);
this.getView().addMouseWheelListener(mouseWheelListener);
this.getActions().addAction(ActionFactory.createMouseCenteredZoomAction(1.1));
this.getActions().addAction(ActionFactory.createPopupMenuAction(popupMenuProvider));

this.getActions().addAction(ActionFactory.createWheelPanAction());

LayerWidget selectLayer = new LayerWidget(this);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2015, 2022, Oracle and/or its affiliates. All rights reserved.

This comment has been minimized.

Copy link
@RogerRiggs

RogerRiggs Jul 21, 2022

Contributor

There should only be 2 copyright dates here. Please fix.

*
* Oracle and Java are registered trademarks of Oracle and/or its affiliates.
* Other names may be trademarks of their respective owners.
Expand Down Expand Up @@ -50,6 +50,7 @@
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.JScrollBar;
import org.netbeans.api.visual.action.WidgetAction;
import org.netbeans.api.visual.action.WidgetAction.State;
import org.netbeans.api.visual.action.WidgetAction.WidgetMouseEvent;
Expand All @@ -62,16 +63,15 @@
*/
public class CustomizablePanAction extends WidgetAction.LockedAdapter {
private boolean enabled = true;
private boolean active = true;

private Scene scene;
private JScrollPane scrollPane;
private Point lastLocation;

private final int modifiersExMask;
private Rectangle rectangle;
private final int modifiersEx;

public CustomizablePanAction(int modifiersExMask, int modifiersEx) {
this.modifiersExMask = modifiersExMask;
public CustomizablePanAction(int modifiersEx) {
this.modifiersEx = modifiersEx;
}

Expand All @@ -80,72 +80,89 @@ protected boolean isLocked() {
return scrollPane != null;
}

private void lock() {
scrollPane = findScrollPane(scene.getView());
}

private void unlock() {
scrollPane = null;
}

public void setEnabled(boolean enabled) {
if (this.enabled != enabled) {
if (isLocked())
if (this.isLocked()) {
throw new IllegalStateException();

}
this.enabled = enabled;
}
}

@Override
public State mousePressed (Widget widget, WidgetMouseEvent event) {
public State mouseEntered(Widget widget, WidgetMouseEvent event) {
active = true;
return super.mouseEntered(widget, event);
}

@Override
public State mouseExited(Widget widget, WidgetMouseEvent event) {
active = false;
return super.mouseExited(widget, event);
}

@Override
public State mousePressed(Widget widget, WidgetMouseEvent event) {
EditorTopComponent editor = EditorTopComponent.getActive();
if (editor != null) {
editor.requestActive();
}
if (isLocked ())
return State.createLocked (widget, this);
if (enabled && (event.getModifiersEx() & modifiersExMask) == modifiersEx) {
scene = widget.getScene ();
scrollPane = findScrollPane (scene.getView ());
if (scrollPane != null) {
lastLocation = scene.convertSceneToView (widget.convertLocalToScene (event.getPoint ()));
SwingUtilities.convertPointToScreen (lastLocation, scene.getView ());
return State.createLocked (widget, this);
if (!this.isLocked() && active && enabled && (event.getModifiersEx() == modifiersEx)) {
scene = widget.getScene();
this.lock();
if (this.isLocked()) {
lastLocation = scene.convertSceneToView(widget.convertLocalToScene(event.getPoint()));
SwingUtilities.convertPointToScreen(lastLocation, scene.getView());
rectangle = scene.getView().getVisibleRect();
}
}
return State.REJECTED;
return super.mousePressed(widget, event);
}

private JScrollPane findScrollPane (JComponent component) {
private JScrollPane findScrollPane(JComponent component) {
for (;;) {
if (component == null)
if (component == null) {
return null;
if (component instanceof JScrollPane)
}
if (component instanceof JScrollPane) {
return ((JScrollPane) component);
Container parent = component.getParent ();
if (! (parent instanceof JComponent))
}
Container parent = component.getParent();
if (!(parent instanceof JComponent)) {
return null;
}
component = (JComponent) parent;
}
}

@Override
public State mouseReleased (Widget widget, WidgetMouseEvent event) {
boolean state = pan (widget, event.getPoint ());
if (state)
scrollPane = null;
return state ? State.createLocked (widget, this) : State.REJECTED;
public State mouseReleased(Widget widget, WidgetMouseEvent event) {
if (this.isLocked() && scene == widget.getScene()) {
this.unlock();
}
return super.mouseReleased(widget, event);
}

@Override
public State mouseDragged (Widget widget, WidgetMouseEvent event) {
return pan (widget, event.getPoint ()) ? State.createLocked (widget, this) : State.REJECTED;
}

private boolean pan (Widget widget, Point newLocation) {
if (scrollPane == null || scene != widget.getScene ())
return false;
newLocation = scene.convertSceneToView (widget.convertLocalToScene (newLocation));
SwingUtilities.convertPointToScreen (newLocation, scene.getView ());
JComponent view = scene.getView ();
Rectangle rectangle = view.getVisibleRect ();
rectangle.x += lastLocation.x - newLocation.x;
rectangle.y += lastLocation.y - newLocation.y;
view.scrollRectToVisible (rectangle);
lastLocation = newLocation;
return true;
public State mouseDragged(Widget widget, WidgetMouseEvent event) {
if (active && this.isLocked() && scene == widget.getScene()) {
Point newLocation = event.getPoint();
newLocation = scene.convertSceneToView(widget.convertLocalToScene(newLocation));
SwingUtilities.convertPointToScreen(newLocation, scene.getView());
rectangle.x += lastLocation.x - newLocation.x;
rectangle.y += lastLocation.y - newLocation.y;
scene.getView().scrollRectToVisible(rectangle);
lastLocation = newLocation;
return State.createLocked(widget, this);
}
return State.REJECTED;
}
}

1 comment on commit 604a115

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.