Improved code readability. Components now aware of what mouse button was clicked.
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Fri, 24 Feb 2023 21:57:39 +0000 (23:57 +0200)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Fri, 24 Feb 2023 21:57:39 +0000 (23:57 +0200)
src/main/java/eu/svjatoslav/sixth/e3d/gui/GuiComponent.java
src/main/java/eu/svjatoslav/sixth/e3d/gui/RenderingContext.java
src/main/java/eu/svjatoslav/sixth/e3d/gui/ViewPanel.java
src/main/java/eu/svjatoslav/sixth/e3d/gui/humaninput/HIDInputTracker.java
src/main/java/eu/svjatoslav/sixth/e3d/gui/humaninput/MouseEvent.java
src/main/java/eu/svjatoslav/sixth/e3d/gui/humaninput/MouseInteractionController.java
src/main/java/eu/svjatoslav/sixth/e3d/renderer/raster/shapes/basic/solidpolygon/SolidPolygon.java
src/main/java/eu/svjatoslav/sixth/e3d/renderer/raster/shapes/basic/texturedpolygon/TexturedPolygon.java

index 0fc1f11..e72de54 100644 (file)
@@ -94,7 +94,7 @@ public class GuiComponent extends AbstractCompositeShape implements
     }
 
     @Override
-    public boolean mouseClicked() {
+    public boolean mouseClicked(int button) {
         return viewPanel.getKeyboardFocusStack().pushFocusOwner(this);
     }
 
index 3641bc9..b6417e5 100644 (file)
@@ -28,11 +28,11 @@ public class RenderingContext {
     /**
      * UI component that mouse is currently hovering over.
      */
-    private MouseInteractionController currentMouseOverComponent;
+    private MouseInteractionController objectPreviouslyUnderMouseCursor;
 
     public void prepareForNewFrameRendering(){
         mouseEvent = null;
-        objectUnderMouse = null;
+        currentObjectUnderMouseCursor = null;
     }
 
     /**
@@ -51,15 +51,15 @@ public class RenderingContext {
     /**
      * Item that user clicked on.
      */
-    private MouseInteractionController objectUnderMouse;
+    private MouseInteractionController currentObjectUnderMouseCursor;
 
     /**
      * Called when given object was detected under mouse cursor, while processing {@link #mouseEvent}.
      * Because objects are rendered back to front. The last method caller will set the top-most object, if
      * there are multiple objects under mouse cursor.
      */
-    public void setObjectUnderMouse(MouseInteractionController objectUnderMouse) {
-        this.objectUnderMouse = objectUnderMouse;
+    public void setCurrentObjectUnderMouseCursor(MouseInteractionController currentObjectUnderMouseCursor) {
+        this.currentObjectUnderMouseCursor = currentObjectUnderMouseCursor;
     }
 
     public RenderingContext(final int width, final int height) {
@@ -85,28 +85,24 @@ public class RenderingContext {
     /**
      * @return <code>true</code> if view repaint is needed.
      */
-    public boolean handleDetectedComponentMouseEvents() {
-        if (objectUnderMouse != null) {
-            if (mouseEvent.button == 0) {
-                // mouse over
-                if (currentMouseOverComponent == null) {
-                    currentMouseOverComponent = objectUnderMouse;
-                    return currentMouseOverComponent.mouseEntered();
-                } else if (currentMouseOverComponent != objectUnderMouse) {
-                    boolean viewRepaintNeeded = currentMouseOverComponent.mouseExited();
-                    currentMouseOverComponent = objectUnderMouse;
-                    return viewRepaintNeeded | currentMouseOverComponent.mouseEntered();
-                }
-            } else {
-                // mouse click
-                return objectUnderMouse.mouseClicked();
-            }
-        } else if (currentMouseOverComponent != null) {
-            boolean viewRepaintNeeded = currentMouseOverComponent.mouseExited();
-            currentMouseOverComponent = null;
-            return viewRepaintNeeded;
+    public boolean handlePossibleComponentMouseEvent() {
+        if (mouseEvent == null) return false;
+
+        boolean viewRepaintNeeded = false;
+
+        if (objectPreviouslyUnderMouseCursor != currentObjectUnderMouseCursor) {
+            // Mouse cursor has just entered or left component.
+            viewRepaintNeeded = objectPreviouslyUnderMouseCursor != null && objectPreviouslyUnderMouseCursor.mouseExited();
+            viewRepaintNeeded |= currentObjectUnderMouseCursor != null && currentObjectUnderMouseCursor.mouseEntered();
+            objectPreviouslyUnderMouseCursor = currentObjectUnderMouseCursor;
         }
-        return false;
+
+        if (mouseEvent.button != 0 && currentObjectUnderMouseCursor != null) {
+            // Mouse button was clicked on some component.
+            viewRepaintNeeded |= currentObjectUnderMouseCursor.mouseClicked(mouseEvent.button);
+        }
+
+        return viewRepaintNeeded;
     }
 
 }
index 7f9b7eb..088d98a 100755 (executable)
@@ -206,7 +206,7 @@ public class ViewPanel extends JPanel implements ComponentListener {
         // abort rendering if window size is invalid
         if ((getWidth() > 0) && (getHeight() > 0) && renderFrame) {
             renderFrame();
-            viewRepaintNeeded = renderingContext.handleDetectedComponentMouseEvents();
+            viewRepaintNeeded = renderingContext.handlePossibleComponentMouseEvent();
         }
 
     }
index af0ae31..a63c33b 100755 (executable)
@@ -17,29 +17,25 @@ import java.util.List;
 import java.util.Map;
 
 /**
- * Human input device input tracker.
- * <p>
- * Idea is to capture all keyboard and mouse inputs from underlying operating system in this class
- * and forward those as needed to subsequent virtual components.
+ * This class is responsible for tracking human input devices (keyboard, mouse, etc.) and
+ * forwarding those inputs to subsequent virtual components.
  */
 public class HIDInputTracker implements
         MouseMotionListener, KeyListener, MouseListener, MouseWheelListener, ViewRenderListener {
 
     /**
-     * <pre>
-     * Key is keyboard key code.
-     * Value is system milliseconds when key was pressed.
-     *
-     * So by reading the map one can determine currently pressed keys as well as duration.
-     * </pre>
+     * <p>  Map of pressed keys. </p>
+     * <p>  Key is mouse button code. </p>
+     * <p>  Value is system milliseconds when button was pressed. </p>
+     * <p>  So by reading the map one can determine currently pressed buttons as well as duration. </p>
      */
     private final Map<Integer, Long> pressedKeysToPressedTimeMap = new HashMap<>();
     private final List<MouseEvent> detectedMouseEvents = new ArrayList<>();
     private final List<KeyEvent> detectedKeyEvents = new ArrayList<>();
     private int wheelMovedDirection = 0;
-    private Point2D mouseDraggedDirection = new Point2D();
+    private final Point2D mouseDraggedDirection = new Point2D();
     private Point2D oldMouseCoordinatesWhenDragging;
-    private ViewPanel viewPanel;
+    private final ViewPanel viewPanel;
     private Point2D currentMouseLocation;
     private boolean mouseMoved;
     private boolean mouseWithinWindow = false;
index 8582cc0..b487d15 100644 (file)
@@ -6,13 +6,24 @@ package eu.svjatoslav.sixth.e3d.gui.humaninput;
 
 import eu.svjatoslav.sixth.e3d.geometry.Point2D;
 
+/**
+ * Represents mouse event.
+ */
 public class MouseEvent {
 
+    /**
+     * Mouse coordinate in screen space (pixels) relative to top left corner of the screen
+     * when mouse button was clicked.
+     */
     public Point2D coordinate;
 
     /**
-     * Indicates pressed mouse button. Except 0 that simply means mouse over
-     * given region.
+     * <pre>
+     * 0 - mouse over (no button pressed)
+     * 1 - left mouse button
+     * 2 - middle mouse button
+     * 3 - right mouse button
+     * </pre>
      */
     public int button;
 
index 9ae1f43..e29f978 100644 (file)
@@ -10,7 +10,7 @@ public interface MouseInteractionController {
      * Called when mouse is clicked on component.
      * @return <code>true</code> if view update is needed as a consequence of this mouse click.
      */
-    boolean mouseClicked();
+    boolean mouseClicked(int button);
 
     /**
      * Called when mouse gets over given component.
index bc10857..87143b5 100644 (file)
@@ -102,7 +102,7 @@ public class SolidPolygon extends AbstractCoordinateShape {
             if (context.getMouseEvent() != null)
                 if (pointWithinPolygon(context.getMouseEvent().coordinate,
                         onScreenPoint1, onScreenPoint2, onScreenPoint3))
-                    context.setObjectUnderMouse(mouseInteractionController);
+                    context.setCurrentObjectUnderMouseCursor(mouseInteractionController);
 
         if (color.isTransparent())
             return;
index 889acda..7a6f2bf 100644 (file)
@@ -26,7 +26,12 @@ public class TexturedPolygon extends AbstractCoordinateShape {
      * Polygon texture coordinates.
      */
     public Point2D texturePoint1, texturePoint2, texturePoint3;
-    private boolean showBorders = false;
+
+    /**
+     * If <code>true</code> then polygon borders will be drawn.
+     * It is used for debugging purposes.
+     */
+    public boolean showBorders = false;
     private double totalTextureDistance = -1;
 
     public TexturedPolygon(final Point3D p1, final Point3D p2,
@@ -140,7 +145,7 @@ public class TexturedPolygon extends AbstractCoordinateShape {
                 if (pointWithinPolygon(
                         renderBuffer.getMouseEvent().coordinate, projectedPoint1,
                         projectedPoint2, projectedPoint3))
-                    renderBuffer.setObjectUnderMouse(mouseInteractionController);
+                    renderBuffer.setCurrentObjectUnderMouseCursor(mouseInteractionController);
 
         // Show polygon boundaries (for debugging)
         if (showBorders)