/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ /* * * @author Toni Kalajainen */ package org.simantics.scenegraph.g2d.events.adapter; 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 org.simantics.scenegraph.g2d.events.EventDebugPolicy; import org.simantics.scenegraph.g2d.events.IEventHandler; import org.simantics.scenegraph.g2d.events.IEventQueue; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseEnterEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseExitEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent; /** * Adapts AWT mouse events into G2D events. * * Sends adapted events to IEventHandler */ public class AWTMouseEventAdapter extends AbstractEventAdapter implements MouseListener, MouseMotionListener, MouseWheelListener { private final boolean DEBUG = EventDebugPolicy.AWT_MOUSE_EVENT_ADAPTION; private final boolean IGNORE_CONSUMED_EVENTS = false; /** Mouse id of the default mouse */ public static final int MOUSE_ID = 0; private final long [] pressTime = new long[5]; int buttonStatus = 0; /** * create new adapter * @param sender the sender field in the events * @param delegator the target of the adapted events */ public AWTMouseEventAdapter(Object sender, IEventHandler delegator) { super(sender, delegator); } /** * create new adapter * @param sender the sender field in the events * @param queue */ public AWTMouseEventAdapter(Object sender, IEventQueue queue) { super(sender, queue); } public static Point2D getControlPosition(MouseEvent e) { return new Point2D.Double(e.getX(), e.getY()); } public static Point2D getScreenPosition(MouseEvent e) { return e.getLocationOnScreen(); } public static int getStateMask(MouseEvent e) { int modifiers = e.getModifiersEx(); int stateMask = 0; if((modifiers & InputEvent.CTRL_DOWN_MASK) != 0) stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.CTRL_MASK; if((modifiers & InputEvent.ALT_DOWN_MASK) != 0) stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.ALT_MASK; if((modifiers & InputEvent.ALT_GRAPH_DOWN_MASK) != 0) stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.ALT_GRAPH_MASK; if((modifiers & InputEvent.SHIFT_DOWN_MASK) != 0) stateMask |= org.simantics.scenegraph.g2d.events.MouseEvent.SHIFT_MASK; return stateMask; } public static int getMouseButton(MouseEvent e) { int awtMouseButton = e.getButton(); if (awtMouseButton == MouseEvent.BUTTON1) return org.simantics.scenegraph.g2d.events.MouseEvent.LEFT_BUTTON; if (awtMouseButton == MouseEvent.BUTTON2) return org.simantics.scenegraph.g2d.events.MouseEvent.MIDDLE_BUTTON; if (awtMouseButton == MouseEvent.BUTTON3) return org.simantics.scenegraph.g2d.events.MouseEvent.RIGHT_BUTTON; return awtMouseButton; } /** * Converts AWT {@link MouseEvent#getModifiersEx()} mouse button status to * G2D mouse button status. Only supports three buttons while AWT supports * plenty more. * * @param e * @return */ public static int getButtonStatus(MouseEvent e) { int modex = e.getModifiersEx(); int status = 0; status |= (modex & MouseEvent.BUTTON1_DOWN_MASK) != 0 ? org.simantics.scenegraph.g2d.events.MouseEvent.LEFT_MASK : 0; status |= (modex & MouseEvent.BUTTON2_DOWN_MASK) != 0 ? org.simantics.scenegraph.g2d.events.MouseEvent.MIDDLE_MASK : 0; status |= (modex & MouseEvent.BUTTON3_DOWN_MASK) != 0 ? org.simantics.scenegraph.g2d.events.MouseEvent.RIGHT_MASK : 0; return status; } @Override public void mouseEntered(MouseEvent e) { if (IGNORE_CONSUMED_EVENTS) { if (e.isConsumed()) { if (DEBUG) System.out.println("AWT mouse entered but already consumed: " + e); return; } } if (DEBUG) System.out.println("AWT mouse entered: " + e); buttonStatus = getButtonStatus(e); MouseEnterEvent me = new MouseEnterEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e)); handleEvent(me); } @Override public void mouseExited(MouseEvent e) { if (IGNORE_CONSUMED_EVENTS) { if (e.isConsumed()) { if (DEBUG) System.out.println("AWT mouse exited but already consumed: " + e); return; } } if (DEBUG) System.out.println("AWT mouse exited: " + e); MouseExitEvent me = new MouseExitEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e)); handleEvent(me); } @Override public void mousePressed(MouseEvent e) { if (IGNORE_CONSUMED_EVENTS) { if (e.isConsumed()) { if (DEBUG) System.out.println("AWT mouse pressed but already consumed: " + e); return; } } if (DEBUG) System.out.println("AWT mouse pressed: " + e); int mouseButton = getMouseButton(e); if (mouseButton == MouseEvent.NOBUTTON) { // This is strange, seems to happen on Linux constantly when pressing buttons rapidly. //System.out.println("NO BUTTON EVENT: " + e); return; } if (mouseButton<=pressTime.length) pressTime[mouseButton-1] = e.getWhen(); buttonStatus |= 1 << (mouseButton-1); handleEvent(new MouseButtonPressedEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), mouseButton, getControlPosition(e), getScreenPosition(e))); if (e.getClickCount() == 2) { handleEvent(new MouseDoubleClickedEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), mouseButton, getControlPosition(e), getScreenPosition(e))); } } @Override public void mouseReleased(MouseEvent e) { if (IGNORE_CONSUMED_EVENTS) { if (e.isConsumed()) { if (DEBUG) System.out.println("AWT mouse released but already consumed: " + e); return; } } if (DEBUG) System.out.println("AWT mouse released: " + e); int mouseButton = getMouseButton(e); if (mouseButton == MouseEvent.NOBUTTON) { // This is strange, seems to happen on Linux constantly when pressing buttons rapidly. //System.out.println("NO BUTTON EVENT: " + e); return; } long holdTime = Long.MAX_VALUE; if (mouseButton<=pressTime.length) holdTime = e.getWhen() - pressTime[mouseButton-1]; int stateMask = getStateMask(e); // This works around the problem of AWT putting the ALT_DOWN_MASK in the // mouse event extended modifiers when button 2 is pressed. if (mouseButton == org.simantics.scenegraph.g2d.events.MouseEvent.MIDDLE_BUTTON) { stateMask &= ~(org.simantics.scenegraph.g2d.events.MouseEvent.ALT_MASK); } buttonStatus &=~ (1<<(mouseButton-1)); MouseButtonReleasedEvent me = new MouseButtonReleasedEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, stateMask, mouseButton, holdTime, getControlPosition(e), getScreenPosition(e)); handleEvent(me); } @Override public void mouseDragged(MouseEvent e) { if (IGNORE_CONSUMED_EVENTS) { if (e.isConsumed()) { if (DEBUG) System.out.println("AWT mouse dragged but already consumed: " + e); return; } } if (DEBUG) System.out.println("AWT mouse dragged: " + e); MouseMovedEvent me = new MouseMovedEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e)); handleEvent(me); } @Override public void mouseMoved(MouseEvent e) { if (IGNORE_CONSUMED_EVENTS) { if (e.isConsumed()) { if (DEBUG) System.out.println("AWT mouse moved but already consumed: " + e); return; } } if (DEBUG) System.out.println("AWT mouse moved: " + e); MouseMovedEvent me = new MouseMovedEvent(sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e)); handleEvent(me); } @Override public void mouseWheelMoved(MouseWheelEvent e) { if (IGNORE_CONSUMED_EVENTS) { if (e.isConsumed()) { if (DEBUG) System.out.println("AWT mouse wheel moved but already consumed: " + e); return; } } if (DEBUG) System.out.println("AWT mouse wheel moved: " + e); int wheelRotation = 0; if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) { wheelRotation = -e.getUnitsToScroll(); } else { wheelRotation = -e.getWheelRotation(); } handleEvent(new MouseWheelMovedEvent( sender, e.getWhen(), MOUSE_ID, buttonStatus, getStateMask(e), getControlPosition(e), getScreenPosition(e), e.getScrollType(), e.getScrollAmount(), wheelRotation )); } @Override public void mouseClicked(MouseEvent e) { if (IGNORE_CONSUMED_EVENTS) { if (e.isConsumed()) { if (DEBUG) System.out.println("AWT mouse clicked but already consumed: " + e); return; } } if (DEBUG) System.out.println("AWT mouse clicked: " + e); } }