/******************************************************************************* * Copyright (c) 2015 * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. *******************************************************************************/ package go.graphics.swing.event.swingInterpreter; import java.awt.Component; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; import java.awt.Window; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.HierarchyEvent; import java.awt.event.HierarchyListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; 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.lang.reflect.Field; import go.graphics.UIPoint; import go.graphics.event.GOEventHandlerProvider; import go.graphics.event.interpreter.AbstractEventConverter; /** * This class listens to swing events, converts them to a go events and sends them to handlers. * * @author michael */ public class GOSwingEventConverter extends AbstractEventConverter implements MouseListener, MouseMotionListener, KeyListener, MouseWheelListener, ComponentListener, HierarchyListener { private static final int MOUSE_MOVE_TRESHOLD = 10; private static final double MOUSE_TIME_TRSHOLD = 5; /** * Are we currently panning with button 3? */ private boolean panWithButton3; private int scaleFactor = 1; /** * Creates a new event converter, that converts swing events to go events. * * @param component * The component. * @param provider * THe provider to which to send the events. */ public GOSwingEventConverter(Component component, GOEventHandlerProvider provider) { super(provider); component.addKeyListener(this); component.addMouseListener(this); component.addMouseMotionListener(this); component.addMouseWheelListener(this); component.addHierarchyListener(this); addReplaceRule(new EventReplacementRule(ReplacableEvent.DRAW, Replacement.COMMAND_SELECT, MOUSE_TIME_TRSHOLD, MOUSE_MOVE_TRESHOLD)); addReplaceRule(new EventReplacementRule(ReplacableEvent.PAN, Replacement.COMMAND_ACTION, MOUSE_TIME_TRSHOLD, MOUSE_MOVE_TRESHOLD)); } private UIPoint convertToLocal(MouseEvent e) { return new UIPoint(e.getX() * scaleFactor, (e.getComponent().getHeight() - e.getY()) * scaleFactor); } private void updateScaleFactor(Component component) { GraphicsConfiguration config = component.getGraphicsConfiguration(); if (config == null) { return; } GraphicsDevice myScreen = config.getDevice(); try { Field field = myScreen.getClass().getDeclaredField("scale"); if (field == null) { return; } field.setAccessible(true); Object scaleOfField = field.get(myScreen); if (scaleOfField instanceof Integer) { scaleFactor = ((Integer) scaleOfField).intValue(); } } catch (NoSuchFieldException exception) { // if there is no Field scale then we have a scale factor of 1 // this is expected for Oracle JRE < 1.7.0_u40 } catch (Exception exception) { exception.printStackTrace(); } } @Override public void mouseEntered(MouseEvent e) { startHover(convertToLocal(e)); } @Override public void mouseMoved(MouseEvent e) { updateHoverPosition(convertToLocal(e)); } @Override public void mouseExited(MouseEvent e) { endHover(convertToLocal(e)); } @Override public void mouseClicked(MouseEvent e) { } @Override public void mousePressed(MouseEvent e) { int mouseButton = e.getButton(); UIPoint local = convertToLocal(e); if (mouseButton == MouseEvent.BUTTON1) { startDraw(local); } else { boolean isPanClick = mouseButton == MouseEvent.BUTTON2 || mouseButton == MouseEvent.BUTTON3; if (isPanClick) { startPan(local); panWithButton3 = mouseButton == MouseEvent.BUTTON3; } } } @Override public void mouseDragged(MouseEvent e) { UIPoint local = convertToLocal(e); updateDrawPosition(local); updatePanPosition(local); updateHoverPosition(local); } @Override public void mouseReleased(MouseEvent e) { UIPoint local = convertToLocal(e); if (e.getButton() == MouseEvent.BUTTON1) { endDraw(local); } else if (panWithButton3 && e.getButton() == MouseEvent.BUTTON3) { endPan(local); } else if (!panWithButton3 && e.getButton() == MouseEvent.BUTTON2) { endPan(local); } } @Override public void keyPressed(KeyEvent e) { String text = getKeyName(e); startKeyEvent(text); /* * if (ongoingKeyEvent == null) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { ongoingKeyEvent.setHandler(getCancelHandler()); } else if * (e.getKeyCode() == KeyEvent.VK_UP) { ongoingKeyEvent.setHandler(getPanHandler(0, -KEYPAN)); } else if (e.getKeyCode() == KeyEvent.VK_DOWN) * { ongoingKeyEvent.setHandler(getPanHandler(0, KEYPAN)); } else if (e.getKeyCode() == KeyEvent.VK_LEFT) { * ongoingKeyEvent.setHandler(getPanHandler(KEYPAN, 0)); } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { * ongoingKeyEvent.setHandler(getPanHandler(-KEYPAN, 0)); } * * provider.handleEvent(ongoingKeyEvent); * * ongoingKeyEvent.started(); } */ } private String getKeyName(KeyEvent e) { String text = KeyEvent.getKeyText(e.getKeyCode()); if (text == null || text.length() != 1) { switch (e.getKeyCode()) { case KeyEvent.VK_LEFT: text = "LEFT"; break; case KeyEvent.VK_RIGHT: text = "RIGHT"; break; case KeyEvent.VK_DOWN: text = "DOWN"; break; case KeyEvent.VK_UP: text = "UP"; break; case KeyEvent.VK_PAUSE: text = "PAUSE"; break; case KeyEvent.VK_F1: text = "F1"; break; case KeyEvent.VK_F2: text = "F2"; break; case KeyEvent.VK_F3: text = "F3"; break; case KeyEvent.VK_F4: text = "F4"; break; case KeyEvent.VK_F5: text = "F5"; break; case KeyEvent.VK_F6: text = "F6"; break; case KeyEvent.VK_F7: text = "F7"; break; case KeyEvent.VK_F8: text = "F8"; break; case KeyEvent.VK_F9: text = "F9"; break; case KeyEvent.VK_F10: text = "F10"; break; case KeyEvent.VK_F11: text = "F11"; break; case KeyEvent.VK_F12: text = "F12"; break; case KeyEvent.VK_PLUS: text = "+"; break; case KeyEvent.VK_MINUS: text = "-"; break; case KeyEvent.VK_DELETE: text = "DELETE"; break; case KeyEvent.VK_SPACE: text = " "; break; case KeyEvent.VK_ESCAPE: text = "ESCAPE"; break; case KeyEvent.VK_BACK_SPACE: text = "BACK_SPACE"; break; default: text = "" + e.getKeyChar(); } } return text; } @Override public void keyReleased(KeyEvent e) { endKeyEvent(getKeyName(e)); } @Override public void keyTyped(KeyEvent e) { } @Override public void mouseWheelMoved(MouseWheelEvent e) { float factor = (float) Math.exp(-e.getUnitsToScroll() / 20.0); startZoom(); endZoomEvent(factor, convertToLocal(e)); } @Override public void componentResized(ComponentEvent e) { } @Override public void componentMoved(ComponentEvent componentEvent) { updateScaleFactor(componentEvent.getComponent()); } @Override public void componentShown(ComponentEvent componentEvent) { updateScaleFactor(componentEvent.getComponent()); } @Override public void componentHidden(ComponentEvent e) { } @Override public void hierarchyChanged(HierarchyEvent hierarchyEvent) { Component component = hierarchyEvent.getComponent(); privateRegisterComponentListenerToParentWindowOf(component, component); } void privateRegisterComponentListenerToParentWindowOf(Component component, Component childComponent) { if (component == null) { return; } else if (component instanceof Window) { updateScaleFactor(component); component.addComponentListener(this); childComponent.removeComponentListener(this); } else { privateRegisterComponentListenerToParentWindowOf(component.getParent(), childComponent); } } }