/******************************************************************************* * 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 *******************************************************************************/ package org.simantics.g2d.participant; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Paint; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.AffineTransform; import java.awt.geom.Path2D; import java.util.Map; import org.simantics.g2d.canvas.SGDesignation; import org.simantics.g2d.canvas.impl.AbstractCanvasParticipant; import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency; import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup; import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit; import org.simantics.g2d.participant.MouseUtil.MouseInfo; import org.simantics.scenegraph.g2d.G2DParentNode; import org.simantics.scenegraph.g2d.events.MouseEvent; import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonReleasedEvent; import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; import org.simantics.scenegraph.g2d.nodes.InstancingShapeNode; import org.simantics.utils.datastructures.hints.IHintContext.Key; import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; /** * Paints mouse cursors in a multi-mouse setup. * * @author Toni Kalajainen * @author Tuukka Lehtonen */ public class PointerPainter extends AbstractCanvasParticipant { /** * Key for the hint that determines whether cursors are painter or not. */ public static final Key KEY_PAINT_POINTER = new KeyOf(Boolean.class); public static final int CURSOR_PAINT_Z_ORDER = 5000; private final static Stroke CURSOR_STROKE = new BasicStroke(1.0f); @Dependency MouseUtil monitor; InstancingShapeNode node; Shape pointer; public PointerPainter() { Path2D p = new Path2D.Double(); p.moveTo(-10, -10); p.lineTo(10, 10); p.moveTo(10, -10); p.lineTo(-10, 10); this.pointer = p; } @SGInit(designation = SGDesignation.CONTROL) public void init(G2DParentNode parent) { node = parent.addNode("pointers", InstancingShapeNode.class); node.setZIndex(CURSOR_PAINT_Z_ORDER); node.setShape(pointer); node.setStroke(CURSOR_STROKE); node.setFill(false); node.setScaleStroke(false); node.setScaleShape(false); } @SGCleanup public void cleanup() { node.remove(); node = null; } public boolean isCursorEnabled() { Boolean pp = getHint(KEY_PAINT_POINTER); return Boolean.TRUE.equals(pp); } @EventHandler(priority = Integer.MAX_VALUE) public boolean handleMouseEvent(MouseEvent e) { if (!isCursorEnabled()) return false; assertDependencies(); if (e instanceof MouseMovedEvent || e instanceof MouseButtonPressedEvent || e instanceof MouseButtonReleasedEvent) { updateNode(); setDirty(); } return false; } private void updateNode() { Map miceInfo = monitor.getMiceInfo(); AffineTransform[] transforms = new AffineTransform[miceInfo.size()]; Paint[] paints = new Paint[miceInfo.size()]; int i = 0; for (MouseInfo mi : miceInfo.values()) { int color = 0; if ((mi.buttons & 1) > 0) color |= 0xff; if ((mi.buttons & 2) > 0) color |= 0xff00; if ((mi.buttons & 4) > 0) color |= 0xff0000; transforms[i] = AffineTransform.getTranslateInstance(mi.controlPosition.getX(), mi.controlPosition.getY()); paints[i] = new Color(color); ++i; } node.setInstances(transforms, paints); } }