/******************************************************************************* * Copyright (c) 2016 Alex Shapiro - github.com/shpralex * This program and the accompanying materials * are made available under the terms of the The MIT License (MIT) * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. *******************************************************************************/ package com.sproutlife.panel.gamepanel.handler; import java.awt.Point; import java.awt.event.InputEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.geom.Point2D; import java.util.Vector; import com.sproutlife.panel.PanelController; import com.sproutlife.panel.gamepanel.handler.HandlerConsts.RequiredKey; public class InteractionHandler implements MouseListener, MouseMotionListener, MouseWheelListener { private enum MouseButton { Left, Right; } private PanelController gc; private MouseOverHandler mouseOverHandler; private boolean enableMouseOverOnDrag; private HandlerSet handlerSet; private RequiredKey dragRequiredKey; private RequiredKey clickRequiredKey; private Point mousePoint; private MouseButton mouseButtonPressed = null; public InteractionHandler(PanelController panelController) { this.gc = panelController; mouseOverHandler = new MouseOverHandler(panelController); dragRequiredKey = RequiredKey.None; } public HandlerSet getHandlerSet() { return handlerSet; } public void setHandlerSet(HandlerSet handlerSet) { this.handlerSet = handlerSet; } private <T extends Handler> Vector<T> getHandlers(Iterable<T> handlers, RequiredKey requiredKey) { Vector<T> handlersToReturn = new Vector<T>(); for ( T handler : handlers ) { if ( (handler.getRequiredKey() == requiredKey || handler.getRequiredKey() == RequiredKey.Any) ) { handlersToReturn.add(handler); } } return handlersToReturn; } public void updateMouseOver() { mouseOverHandler.updateMouseOver(gc.getScrollController().getDrawPositionFromMousePosition(mousePoint)); /* try { gc.getInteractionLock().writeLock().lock(); //if ( !handlerSet.popupVisible() ) { // mouseOverHandler.updateMouseOver(gc.getScrollController().getDrawPositionFromMousePosition(mousePoint)); //} } finally { gc.getInteractionLock().writeLock().unlock(); } */ } private static int getAllKeyModifiers() { return InputEvent.ALT_MASK + InputEvent.CTRL_MASK + InputEvent.SHIFT_MASK; } public static RequiredKey getRequiredKey(MouseEvent mouseEvent) { int modifiers = mouseEvent.getModifiers() & getAllKeyModifiers(); if ( modifiers == 0 ) { return RequiredKey.None; } else if ( modifiers == InputEvent.ALT_MASK ) { return RequiredKey.Alt; } else if ( modifiers == InputEvent.CTRL_MASK ) { return RequiredKey.Control; } else if ( modifiers == InputEvent.SHIFT_MASK ) { return RequiredKey.Shift; } return null; } public void mousePressed(MouseEvent mouseEvent) { if ( mouseButtonPressed != null ) { return; } mouseButtonPressed = getMouseButton(mouseEvent); if ( mouseButtonPressed == MouseButton.Right ) { } if ( mouseButtonPressed == MouseButton.Left ) { for ( BackgroundDragHandler backgroundDragHandler : getHandlers(handlerSet.getBackgroundDragHandlers(), dragRequiredKey) ) { backgroundDragHandler.mousePressed(mouseEvent); } for ( DragHandler dragHandler : getHandlers(handlerSet.getDragHandlers(), dragRequiredKey) ) { dragHandler.mousePressed(mouseEvent); } } } public void mouseReleased(MouseEvent mouseEvent) { if ( mouseButtonPressed == MouseButton.Right && getMouseButton(mouseEvent) == MouseButton.Right ) { Point2D.Double mouseLocation = gc.getScrollController().getDrawPositionFromMousePosition(mousePoint); mouseButtonPressed = null; } if ( mouseButtonPressed == MouseButton.Left && getMouseButton(mouseEvent) == MouseButton.Left ) { boolean mouseOverChanged = false; try { gc.getInteractionLock().readLock().lock(); mouseOverChanged = false; //update value } finally { gc.getInteractionLock().readLock().unlock(); } for ( BackgroundDragHandler backgroundDragHandler : getHandlers(handlerSet.getBackgroundDragHandlers(), dragRequiredKey) ) { backgroundDragHandler.mouseReleased(mouseEvent, mouseOverChanged); } for ( DragHandler dragHandler : getHandlers(handlerSet.getDragHandlers(), dragRequiredKey) ) { dragHandler.mouseReleased(mouseEvent); } mouseButtonPressed = null; } } public void setEnableMouseOverOnDrag(boolean enableMouseOverOnDrag) { //FIXME - should drag handlers that need this just call updateMouseOver? this.enableMouseOverOnDrag = enableMouseOverOnDrag; } public void mouseDragged(MouseEvent mouseEvent) { if ( mouseButtonPressed == MouseButton.Left ) { updateMousePosition(mouseEvent, enableMouseOverOnDrag); boolean mouseOverChanged = false; try { gc.getInteractionLock().readLock().lock(); mouseOverChanged = false; //update value } finally { gc.getInteractionLock().readLock().unlock(); } for ( BackgroundDragHandler backgroundDragHandler : getHandlers(handlerSet.getBackgroundDragHandlers(), dragRequiredKey) ) { backgroundDragHandler.mouseDragged(mouseEvent, mouseOverChanged); } for ( DragHandler dragHandler : getHandlers(handlerSet.getDragHandlers(), dragRequiredKey) ) { dragHandler.mouseDragged(mouseEvent); } } } public void mouseClicked(MouseEvent mouseEvent) { if ( getMouseButton(mouseEvent) == MouseButton.Left ) { if ( mouseEvent.getClickCount() == 1 ) { clickRequiredKey = getRequiredKey(mouseEvent); for ( BackgroundClickHandler backgroundClickHandler : getHandlers(handlerSet.getBackgroundClickHandlers(), clickRequiredKey) ) { backgroundClickHandler.mouseClicked(mouseEvent); } for ( ClickHandler clickHandler : getHandlers(handlerSet.getClickHandlers(), clickRequiredKey) ) { clickHandler.mouseClicked(mouseEvent); } } if ( mouseEvent.getClickCount() == 2 ) { boolean mouseOverChanged = false; for (BackgroundClickHandler backgroundClickHandler : getHandlers( handlerSet.getBackgroundClickHandlers(), clickRequiredKey)) { backgroundClickHandler.mouseDoubleClicked(mouseEvent, mouseOverChanged); } for (ClickHandler clickHandler : getHandlers( handlerSet.getClickHandlers(), clickRequiredKey)) { clickHandler.mouseDoubleClicked(mouseEvent); } } } } public void mouseMoved(MouseEvent mouseEvent) { updateMousePosition(mouseEvent); } public void mouseEntered(MouseEvent mouseEvent) { updateMousePosition(mouseEvent); } private void updateMousePosition(MouseEvent mouseEvent) { updateMousePosition(mouseEvent, true); } public void mouseWheelMoved(MouseWheelEvent mouseWheelEvent) { for ( MouseWheelHandler mouseWheelHandler : getHandlers(handlerSet.getMouseWheelHandlers(), getRequiredKey(mouseWheelEvent)) ) { mouseWheelHandler.mouseWheelMoved(mouseWheelEvent); } } private void updateMousePosition(MouseEvent mouseEvent, boolean updateMouseOver) { mousePoint = mouseEvent.getPoint(); if ( updateMouseOver ) { mouseOverHandler.mouseMoved(gc.getScrollController().getDrawPositionFromMousePosition(mousePoint)); } /* try { gc.getInteractionLock().writeLock().lock(); mousePoint = mouseEvent.getPoint(); if ( updateMouseOver ) { mouseOverHandler.mouseMoved(gc.getScrollController().getDrawPositionFromMousePosition(mousePoint)); } } finally { gc.getInteractionLock().writeLock().unlock(); } */ } public void mouseExited(MouseEvent mouseEvent) { mousePoint = null; mouseOverHandler.mouseExited(); } private static MouseButton getMouseButton(MouseEvent me) { if ( (me.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK ) { return MouseButton.Left; } if ( (me.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK ) { return MouseButton.Right; } return null; } private static boolean isMouseButtonDown(MouseEvent me, MouseButton mouseButton) { boolean leftButtonDown = (me.getModifiers() & InputEvent.BUTTON1_DOWN_MASK) == InputEvent.BUTTON1_DOWN_MASK; boolean rightButtonDown = (me.getModifiers() & InputEvent.BUTTON3_DOWN_MASK) == InputEvent.BUTTON3_DOWN_MASK; if ( mouseButton == MouseButton.Left ) { return leftButtonDown; } if ( mouseButton == MouseButton.Right ) { return rightButtonDown; } return !leftButtonDown && !rightButtonDown; // Can check for neither left or right } }