Skip to content

Commit

Permalink
chore: Tweak mouse listener
Browse files Browse the repository at this point in the history
Don't create new rect on each mouse events.
Emit onStopHover on mouse exit when the pointer actually exit scrollPane
  • Loading branch information
bric3 committed Jun 19, 2023
1 parent 62b05bb commit 1b88223
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 13 deletions.
2 changes: 1 addition & 1 deletion fireplace-app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ java {
}

application {
mainClass.set("com.github.bric3.fireplace.FirePlaceMainKt")
mainClass.set("com.github.bric3.fireplace.FireplaceMain")
}

tasks.jar {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
@file:JvmName("FireplaceMain")
package io.github.bric3.fireplace

import io.github.bric3.fireplace.jfr.ProfileContentPanel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import java.awt.*;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Area;
Expand Down Expand Up @@ -172,14 +174,24 @@ public interface ZoomableComponent {
}

/**
* Represents a custom actions when zooming
* Listener for hovered frames.
*
* @param <T> The type of the node data.
*/
public interface HoverListener<T> {
/**
* @param previousHoveredFrame The previous frame that was hovered, or {@code null} if the mouse is exiting the component.
* @param prevHoveredFrameRectangle The rectangle of the previous hovered frame, or {@code null} if the mouse is exiting the component.
* @param e The mouse event
*/
default void onStopHover(FrameBox<T> previousHoveredFrame, Rectangle prevHoveredFrameRectangle, MouseEvent e) {
}

/**
* @param frame The frame that is hovered.
* @param hoveredFrameRectangle The rectangle of the hovered frame.
* @param e The mouse event
*/
void onFrameHover(FrameBox<T> frame, Rectangle hoveredFrameRectangle, MouseEvent e);

/**
Expand Down Expand Up @@ -275,7 +287,7 @@ protected LayoutManager createLayoutManager() {
private final Dimension oldViewPortSize = new Dimension(); // reusable
private final Dimension flamegraphSize = new Dimension(); // reusable
private final Point flamegraphLocation = new Point(); // reusable

@Override
public void layoutContainer(Container parent) {
// Custom layout code to handle container shrinking.
Expand Down Expand Up @@ -797,12 +809,13 @@ public void highlightFrames(Set<FrameBox<T>> framesToHighlight, String searched)
*
* @param <T>
*/
private static class FlamegraphScrollPaneMouseInputListener<T> implements MouseInputListener {
private static class FlamegraphScrollPaneMouseInputListener<T> implements MouseInputListener, FocusListener {
private Point pressedPoint;
private final FlamegraphCanvas<T> canvas;
private Rectangle hoveredFrameRectangle;
private HoverListener<T> hoverListener;
private FrameBox<T> hoveredFrame;
private final Rectangle tmpBounds = new Rectangle(); // reusable

public FlamegraphScrollPaneMouseInputListener(FlamegraphCanvas<T> canvas) {
this.canvas = canvas;
Expand Down Expand Up @@ -867,7 +880,7 @@ public void mouseClicked(MouseEvent e) {
// find zoom target then do an animated transition
canvas.getFlamegraphRenderEngine().flatMap(fgp -> fgp.calculateZoomTargetForFrameAt(
(Graphics2D) canvas.getGraphics(),
canvas.getBounds(),
canvas.getBounds(tmpBounds),
canvas.getVisibleRect(),
latestMouseLocation
)).ifPresent(zoomTarget -> zoom(canvas, zoomTarget));
Expand All @@ -877,7 +890,7 @@ public void mouseClicked(MouseEvent e) {
canvas.getFlamegraphRenderEngine()
.ifPresent(fgp -> fgp.toggleSelectedFrameAt(
(Graphics2D) viewPort.getView().getGraphics(),
canvas.getBounds(),
canvas.getBounds(tmpBounds),
latestMouseLocation,
(frame, r) -> canvas.repaint()
));
Expand All @@ -891,17 +904,23 @@ public void mouseEntered(MouseEvent e) {
@Override
public void mouseExited(MouseEvent e) {
if ((e.getSource() instanceof JScrollPane)) {
var source = (JScrollPane) e.getSource();
hoveredFrameRectangle = null;
hoveredFrame = null;
canvas.getFlamegraphRenderEngine()
.ifPresent(fgp -> fgp.stopHover(
(Graphics2D) canvas.getGraphics(),
canvas.getBounds(),
canvas.getBounds(tmpBounds),
canvas::repaint
));
canvas.repaint();
if (hoverListener != null) {
hoverListener.onStopHover(hoveredFrame, hoveredFrameRectangle, e);

// mouse exit is triggered when the pointer leaves the scroll pane and enters the canvas
// this part is only interested to pass event when the pointer leaves the scroll pane area
var latestMouseLocation = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(latestMouseLocation, source);
if (hoverListener != null && !source.getBounds(tmpBounds).contains(latestMouseLocation)) {
hoverListener.onStopHover(hoveredFrame, null, e);
}
}
}
Expand Down Expand Up @@ -931,23 +950,24 @@ public void mouseMoved(MouseEvent e) {
canvas.getFlamegraphRenderEngine()
.ifPresent(fgp -> {
var canvasGraphics = (Graphics2D) canvas.getGraphics();
var canvasBounds = canvas.getBounds(tmpBounds);
fgp.getFrameAt(
canvasGraphics,
canvas.getBounds(),
canvasBounds,
latestMouseLocation
)
.ifPresentOrElse(
frame -> {
fgp.hoverFrame(
frame,
canvasGraphics,
canvas.getBounds(),
canvasBounds,
canvas::repaint
);
canvas.setToolTipText(frame);
hoveredFrameRectangle = fgp.getFrameRectangle(
canvasGraphics,
canvas.getBounds(),
canvasBounds,
frame
);
hoveredFrame = frame;
Expand All @@ -958,7 +978,7 @@ public void mouseMoved(MouseEvent e) {
() -> {
fgp.stopHover(
canvasGraphics,
canvas.getBounds(),
canvasBounds,
canvas::repaint
);
var prevHoveredFrameRectangle = hoveredFrameRectangle;
Expand All @@ -977,9 +997,24 @@ public void setHoverListener(HoverListener<T> hoveringListener) {
this.hoverListener = hoveringListener;
}

@Override
public void focusGained(FocusEvent e) {
// no op
}

@Override
public void focusLost(FocusEvent e) {
// idea is to stop hover when focus is lost
// if (hoverListener != null) {
// System.out.println("stop hover because focus lost");
// hoverListener.onStopHover(hoveredFrame, hoveredFrameRectangle,e);
// }
}

public void install(JScrollPane sp) {
sp.addMouseListener(this);
sp.addMouseMotionListener(this);
sp.addFocusListener(this);
}
}

Expand Down

0 comments on commit 1b88223

Please sign in to comment.