1 18 package org.apache.batik.bridge; 19 20 import java.awt.Point ; 21 import java.awt.event.KeyEvent ; 22 import java.awt.geom.NoninvertibleTransformException ; 23 import java.awt.geom.Point2D ; 24 import java.awt.geom.Rectangle2D ; 25 import java.text.AttributedCharacterIterator ; 26 import java.util.List ; 27 28 import org.apache.batik.dom.events.DOMKeyEvent; 29 import org.apache.batik.gvt.GraphicsNode; 30 import org.apache.batik.gvt.TextNode; 31 import org.apache.batik.gvt.event.EventDispatcher; 32 import org.apache.batik.gvt.event.GraphicsNodeKeyEvent; 33 import org.apache.batik.gvt.event.GraphicsNodeKeyListener; 34 import org.apache.batik.gvt.event.GraphicsNodeMouseEvent; 35 import org.apache.batik.gvt.event.GraphicsNodeMouseListener; 36 import org.apache.batik.gvt.renderer.StrokingTextPainter; 37 import org.apache.batik.gvt.text.GVTAttributedCharacterIterator; 38 import org.apache.batik.gvt.text.TextHit; 39 import org.apache.batik.gvt.text.TextSpanLayout; 40 import org.apache.batik.util.SVGConstants; 41 import org.w3c.dom.Document ; 42 import org.w3c.dom.Element ; 43 import org.w3c.dom.events.DocumentEvent ; 44 import org.w3c.dom.events.Event ; 45 import org.w3c.dom.events.EventListener ; 46 import org.w3c.dom.events.EventTarget ; 47 import org.w3c.dom.events.MouseEvent ; 48 49 56 public class BridgeEventSupport implements SVGConstants { 57 58 private BridgeEventSupport() {} 59 60 64 public static void addGVTListener(BridgeContext ctx, Document doc) { 65 UserAgent ua = ctx.getUserAgent(); 66 if (ua != null) { 67 EventDispatcher dispatcher = ua.getEventDispatcher(); 68 if (dispatcher != null) { 69 final Listener listener = new Listener(ctx, ua); 70 dispatcher.addGraphicsNodeMouseListener(listener); 71 dispatcher.addGraphicsNodeKeyListener(listener); 72 EventListener l = new GVTUnloadListener(dispatcher, listener); 75 EventTarget target = (EventTarget )doc; 76 target.addEventListener("SVGUnload", l, false); 77 ctx.storeEventListener(target, "SVGUnload", l, false); 78 } 79 } 80 } 81 82 protected static class GVTUnloadListener implements EventListener { 83 84 protected EventDispatcher dispatcher; 85 protected Listener listener; 86 87 public GVTUnloadListener(EventDispatcher dispatcher, 88 Listener listener) { 89 this.dispatcher = dispatcher; 90 this.listener = listener; 91 } 92 93 public void handleEvent(Event evt) { 94 dispatcher.removeGraphicsNodeMouseListener(listener); 95 dispatcher.removeGraphicsNodeKeyListener(listener); 96 evt.getTarget().removeEventListener 97 (SVGConstants.SVG_SVGUNLOAD_EVENT_TYPE, this, false); 98 } 99 } 100 101 104 protected static class Listener 105 implements GraphicsNodeMouseListener, GraphicsNodeKeyListener { 106 107 protected BridgeContext context; 108 protected UserAgent ua; 109 protected Element lastTargetElement; 110 protected boolean isDown; 111 112 public Listener(BridgeContext ctx, UserAgent u) { 113 context = ctx; 114 ua = u; 115 } 116 117 119 123 public void keyPressed(GraphicsNodeKeyEvent evt) { 124 if (!isDown) { 125 isDown = true; 126 dispatchKeyEvent("keydown", evt); 127 } 128 if (evt.getKeyChar() == KeyEvent.CHAR_UNDEFINED) { 129 dispatchKeyEvent("keypress", evt); 132 } 133 } 134 135 139 public void keyReleased(GraphicsNodeKeyEvent evt) { 140 dispatchKeyEvent("keyup", evt); 141 isDown = false; 142 } 143 144 148 public void keyTyped(GraphicsNodeKeyEvent evt) { 149 dispatchKeyEvent("keypress", evt); 150 } 151 152 protected void dispatchKeyEvent(String eventType, 153 GraphicsNodeKeyEvent evt) { 154 FocusManager fmgr = context.getFocusManager(); 155 if (fmgr == null) return; 156 157 Element targetElement = (Element )fmgr.getCurrentEventTarget(); 158 if (targetElement == null) { 159 return; 160 } 161 DocumentEvent d = (DocumentEvent )targetElement.getOwnerDocument(); 162 DOMKeyEvent keyEvt = (DOMKeyEvent)d.createEvent("KeyEvents"); 163 keyEvt.initKeyEvent(eventType, 164 true, 165 true, 166 evt.isControlDown(), 167 evt.isAltDown(), 168 evt.isShiftDown(), 169 evt.isMetaDown(), 170 mapKeyCode(evt.getKeyCode()), 171 evt.getKeyChar(), 172 null); 173 174 try { 175 ((EventTarget )targetElement).dispatchEvent(keyEvt); 176 } catch (RuntimeException e) { 177 ua.displayError(e); 178 } 179 } 180 181 187 protected final int mapKeyCode(int keyCode) { 188 switch (keyCode) { 189 case KeyEvent.VK_ENTER: 190 return DOMKeyEvent.DOM_VK_ENTER; 191 case KeyEvent.VK_KANA_LOCK: 192 return DOMKeyEvent.DOM_VK_UNDEFINED; 193 case KeyEvent.VK_INPUT_METHOD_ON_OFF: 194 return DOMKeyEvent.DOM_VK_UNDEFINED; 195 default: 196 return keyCode; 197 } 198 } 199 200 202 public void mouseClicked(GraphicsNodeMouseEvent evt) { 203 dispatchMouseEvent("click", evt, true); 204 } 205 206 public void mousePressed(GraphicsNodeMouseEvent evt) { 207 dispatchMouseEvent("mousedown", evt, true); 208 } 209 210 public void mouseReleased(GraphicsNodeMouseEvent evt) { 211 dispatchMouseEvent("mouseup", evt, true); 212 } 213 214 public void mouseEntered(GraphicsNodeMouseEvent evt) { 215 dispatchMouseEvent("mouseover", evt, true); 216 } 217 218 public void mouseExited(GraphicsNodeMouseEvent evt) { 219 Point clientXY = evt.getClientPoint(); 220 GraphicsNode node = evt.getRelatedNode(); 222 Element targetElement = getEventTarget(node, clientXY); 223 if (lastTargetElement != null) { 224 dispatchMouseEvent("mouseout", 225 lastTargetElement, targetElement, clientXY, 228 evt, 229 true); 230 } 231 } 232 233 public void mouseDragged(GraphicsNodeMouseEvent evt) { 234 dispatchMouseEvent("mousemove", evt, false); 235 } 236 237 public void mouseMoved(GraphicsNodeMouseEvent evt) { 238 Point clientXY = evt.getClientPoint(); 239 GraphicsNode node = evt.getGraphicsNode(); 240 Element targetElement = getEventTarget(node, clientXY); 241 Element holdLTE = lastTargetElement; 242 if (holdLTE != targetElement) { 243 if (holdLTE != null) { 244 dispatchMouseEvent("mouseout", 245 holdLTE, targetElement, clientXY, 248 evt, 249 true); 250 } 251 if (targetElement != null) { 252 dispatchMouseEvent("mouseover", 253 targetElement, holdLTE, clientXY, 256 evt, 257 true); 258 } 259 } 260 dispatchMouseEvent("mousemove", 261 targetElement, null, clientXY, 264 evt, 265 false); 266 } 267 268 276 protected void dispatchMouseEvent(String eventType, 277 GraphicsNodeMouseEvent evt, 278 boolean cancelable) { 279 Point clientXY = evt.getClientPoint(); 280 GraphicsNode node = evt.getGraphicsNode(); 281 Element targetElement = getEventTarget 282 (node, new Point2D.Float (evt.getX(), evt.getY())); 283 Element relatedElement = getRelatedElement(evt); 284 dispatchMouseEvent(eventType, 285 targetElement, 286 relatedElement, 287 clientXY, 288 evt, 289 cancelable); 290 } 291 292 303 protected void dispatchMouseEvent(String eventType, 304 Element targetElement, 305 Element relatedElement, 306 Point clientXY, 307 GraphicsNodeMouseEvent evt, 308 boolean cancelable) { 309 if (targetElement == null) { 310 return; 311 } 312 325 short button = getButton(evt); 326 Point screenXY = evt.getScreenPoint(); 327 DocumentEvent d = (DocumentEvent )targetElement.getOwnerDocument(); 329 MouseEvent mouseEvt = (MouseEvent)d.createEvent("MouseEvents"); 330 mouseEvt.initMouseEvent(eventType, 331 true, 332 cancelable, 333 null, 334 evt.getClickCount(), 335 screenXY.x, 336 screenXY.y, 337 clientXY.x, 338 clientXY.y, 339 evt.isControlDown(), 340 evt.isAltDown(), 341 evt.isShiftDown(), 342 evt.isMetaDown(), 343 button, 344 (EventTarget )relatedElement); 345 346 try { 347 ((EventTarget )targetElement).dispatchEvent(mouseEvt); 348 } catch (RuntimeException e) { 349 ua.displayError(e); 350 } finally { 351 lastTargetElement = targetElement; 352 } 353 } 354 355 360 protected Element getRelatedElement(GraphicsNodeMouseEvent evt) { 361 GraphicsNode relatedNode = evt.getRelatedNode(); 362 Element relatedElement = null; 363 if (relatedNode != null) { 364 relatedElement = context.getElement(relatedNode); 365 } 366 return relatedElement; 367 } 368 369 374 protected short getButton(GraphicsNodeMouseEvent evt) { 375 short button = 1; 376 if ((GraphicsNodeMouseEvent.BUTTON1_MASK & evt.getModifiers()) != 0) { 377 button = 0; 378 } else if ((GraphicsNodeMouseEvent.BUTTON3_MASK & evt.getModifiers()) != 0) { 379 button = 2; 380 } 381 return button; 382 } 383 384 391 protected Element getEventTarget(GraphicsNode node, Point2D coords) { 392 Element target = context.getElement(node); 393 396 if (target != null && node instanceof TextNode) { 397 TextNode textNode = (TextNode)node; 398 List list = textNode.getTextRuns(); 399 Point2D pt = (Point2D )coords.clone(); 400 try { 402 node.getGlobalTransform().createInverse().transform(pt, pt); 403 } catch (NoninvertibleTransformException ex) { 404 } 405 if (list != null){ 406 for (int i = 0 ; i < list.size(); i++) { 407 StrokingTextPainter.TextRun run = 408 (StrokingTextPainter.TextRun)list.get(i); 409 AttributedCharacterIterator aci = run.getACI(); 410 TextSpanLayout layout = run.getLayout(); 411 float x = (float)pt.getX(); 412 float y = (float)pt.getY(); 413 TextHit textHit = layout.hitTestChar(x, y); 414 Rectangle2D bounds = layout.getBounds2D(); 415 if ((textHit != null) && 416 (bounds != null) && bounds.contains(x, y)) { 417 Object delimiter = aci.getAttribute 418 (GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER); 419 if (delimiter instanceof Element ) { 420 return (Element )delimiter; 421 } 422 } 423 } 424 } 425 } 426 return target; 427 } 428 } 429 } 430 | Popular Tags |