Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.scene.input;
027
028import com.sun.javafx.scene.input.InputEventUtils;
029import java.io.IOException;
030import java.io.Serializable;
031import javafx.event.EventTarget;
032import javafx.geometry.Point3D;
033import javafx.scene.Node;
034import javafx.scene.Scene;
035
036/**
037 * Touch point represents a single point of a multi-touch action, typically
038 * one finger touching a screen. It is contained in {@link TouchEvent}.
039 * <p>
040 * The touch point has its coordinates, state (see {@link State}) and ID. The
041 * ID is sequential number of this touch point unique in scope of a single
042 * multi-touch gesture.
043 * <p>
044 * Each touch point is by default delivered to a single node during its whole
045 * trajectory - to the node on which it was pressed. There is a grabbing API
046 * to modify this behavior. The above means that when touch point is pressed,
047 * it is automatically grabbed by the top-most node on the press coordinates.
048 * Any time during the gesture {@code grab()} and {@code ungrab()} methods
049 * can be used to alter the event delivery target. When grabbed by a different
050 * node, it will next time be targeted to it; when ungrabbed, it will be
051 * always targeted to the top-most node on the current location.
052 *
053 * @since 2.2
054 */
055public final class TouchPoint implements Serializable{
056
057    private transient EventTarget target;
058    private transient Object source;
059
060    /**
061     * Creates new instance of TouchPoint.
062     * @param id ID of the new touch point
063     * @param state state of the new touch point
064     * @param x The x with respect to the scene.
065     * @param y The y with respect to the scene.
066     * @param screenX The x coordinate relative to screen.
067     * @param screenY The y coordinate relative to screen.
068     * @param pickResult pick result. Can be null, in this case a 2D pick result
069     *                   without any further values is constructed
070     *                   based on the scene coordinates and target
071     */
072    public TouchPoint(int id, State state, double x, double y, double screenX,
073            double screenY, EventTarget target, PickResult pickResult) {
074        this.target = target;
075        this.id = id;
076        this.state = state;
077        this.x = x;
078        this.y = y;
079        this.sceneX = x;
080        this.sceneY = y;
081        this.screenX = screenX;
082        this.screenY = screenY;
083        this.pickResult = pickResult != null ? pickResult : new PickResult(target, x, y);
084        final Point3D p = InputEventUtils.recomputeCoordinates(this.pickResult, null);
085        this.x = p.getX();
086        this.y = p.getY();
087        this.z = p.getZ();
088    }
089
090    /**
091     * Recomputes this touch point (coordinates, relevancy) for the given event
092     * source object.
093     * @param oldSource Source object of the current values
094     * @param newSource Source object to compute values for
095     */
096    void recomputeToSource(Object oldSource, Object newSource) {
097
098        final Point3D newCoordinates = InputEventUtils.recomputeCoordinates(
099                pickResult, newSource);
100
101        x = newCoordinates.getX();
102        y = newCoordinates.getY();
103        z = newCoordinates.getZ();
104
105        source = newSource;
106    }
107
108    /**
109     * Distinguishes between touch points targeted to the given node or some
110     * of its children from touch points targeted somewhere else. This allows
111     * for testing all touch points carried by one touch event on their
112     * relevance for a given node.
113     * @param target Node or other event target to be tested
114     * @return true if this touch point is targeted to the given target or
115     * some of its children
116     */
117    public boolean belongsTo(EventTarget target) {
118
119        if (this.target instanceof Node) {
120            Node n = (Node) this.target;
121
122            if (target instanceof Scene) {
123                return n.getScene() == target;
124            }
125            while (n != null) {
126                if (n == target) {
127                    return true;
128                }
129                n = n.getParent();
130            }
131        }
132        
133        return target == this.target;
134    }
135
136    /**
137     * @treatAsPrivate implementation detail
138     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
139     */
140    @Deprecated
141    public void impl_reset() {
142        final Point3D p = InputEventUtils.recomputeCoordinates(pickResult, null);
143        x = p.getX();
144        y = p.getY();
145        z = p.getZ();
146    }
147
148    private EventTarget grabbed = null;
149
150    /**
151     * Gets event target which has grabbed this touch point.
152     * @return The current grabbed target, null if the touch point is ungrabbed
153     */
154    public EventTarget getGrabbed() {
155        return grabbed;
156    }
157
158    /**
159     * Grabs this touch point by current event source. Next event containing
160     * this touch point will be targeted to the same node whose event handler
161     * called this method.
162     */
163    public void grab() {
164        if (source instanceof EventTarget) {
165            grabbed = (EventTarget) source;
166        } else {
167            throw new IllegalStateException("Cannot grab touch point, "
168                    + "source is not an instance of EventTarget: " + source);
169        }
170    }
171
172    /**
173     * Grabs this touch point by the given target. Next event containing this
174     * touch point will be targeted to it.
175     * @param target Target by which to grab the touch point
176     */
177    public void grab(EventTarget target) {
178        grabbed = target;
179    }
180
181    /**
182     * Ungrabs this touch point from its target. Since the next event this
183     * touch point will be delivered to the top-most node picked on its
184     * respective location until it is grabbed again or released.
185     */
186    public void ungrab() {
187        grabbed = null;
188    }
189
190    private int id;
191
192    /**
193     * Gets identifier of this touch point. The number is sequential and unique
194     * in scope of one multi touch gesture. The first pressed touch point has id
195     * {@code 1}, each subsequently pressed touch points gets the next ordinal
196     * number until all touch points are released and the counter is reset.
197     *
198     * @return the identifier of this touch point.
199     */
200    public final int getId() {
201        return id;
202    }
203
204    private State state;
205
206    /**
207     * Gets state of this touch point
208     * @return state of this touch point
209     */
210    public final State getState() {
211        return state;
212    }
213
214
215    private transient double x;
216
217    /**
218     * Gets the horizontal position of the touch point relative to the
219     * origin of the TouchEvent's source.
220     *
221     * @return the horizontal position of the touch point relative to the
222     * origin of the TouchEvent's source.
223     */
224    public final double getX() {
225        return x;
226    }
227
228    private transient double y;
229
230    /**
231     * Gets the vertical position of the touch point relative to the
232     * origin of the TouchEvent's source.
233     *
234     * @return the vertical position of the touch point relative to the
235     * origin of the TouchEvent's source.
236     */
237    public final double getY() {
238        return y;
239    }
240
241    /**
242     * Depth z position of the event relative to the
243     * origin of the MouseEvent's node.
244     */
245    private transient double z;
246
247    /**
248     * Depth position of the event relative to the
249     * origin of the MouseEvent's source.
250     *
251     * @return depth position of the event relative to the
252     * origin of the MouseEvent's source.
253     */
254    public final double getZ() {
255        return z;
256    }
257
258    private double screenX;
259
260    /**
261     * Gets the absolute horizontal position of the touch point.
262     * @return the absolute horizontal position of the touch point
263     */
264    public final double getScreenX() {
265        return screenX;
266    }
267
268    private double screenY;
269
270    /**
271     * Gets the absolute vertical position of the touch point.
272     * @return the absolute vertical position of the touch point
273     */
274    public final double getScreenY() {
275        return screenY;
276    }
277
278    private double sceneX;
279
280    /**
281     * Gets the horizontal position of the touch point relative to the
282     * origin of the {@code Scene} that contains the TouchEvent's source.
283     * If the node is not in a {@code Scene}, then the value is relative to
284     * the boundsInParent of the root-most parent of the TouchEvent's node.
285     * Note that in 3D scene, this represents the flat coordinates after
286     * applying the projection transformations.
287     *
288     * @return the horizontal position of the touch point relative to the
289     * origin of the {@code Scene} that contains the TouchEvent's source
290     */
291    public final double getSceneX() {
292        return sceneX;
293    }
294
295    private double sceneY;
296
297    /**
298     * Gets the vertical position of the touch point relative to the
299     * origin of the {@code Scene} that contains the TouchEvent's source.
300     * If the node is not in a {@code Scene}, then the value is relative to
301     * the boundsInParent of the root-most parent of the TouchEvent's node.
302     * Note that in 3D scene, this represents the flat coordinates after
303     * applying the projection transformations.
304     *
305     * @return the vertical position of the touch point relative to the
306     * origin of the {@code Scene} that contains the TouchEvent's source
307     */
308    public final double getSceneY() {
309        return sceneY;
310    }
311
312    /**
313     * Information about the pick if the picked {@code Node} is a
314     * {@code Shape3D} node and its pickOnBounds is false.
315     */
316    private PickResult pickResult;
317
318    /**
319     * Returns information about the pick.
320     *
321     * @return new PickResult object that contains information about the pick
322     */
323    public final PickResult getPickResult() {
324        return pickResult;
325    }
326
327    /**
328     * Gets event target on which the touch event carrying this touch point
329     * is fired.
330     * @return Event target for this touch point
331     */
332    public EventTarget getTarget() {
333        return target;
334    }
335
336    /**
337     * Returns a string representation of this {@code TouchPoint} object.
338     * @return a string representation of this {@code TouchPoint} object.
339     */
340    @Override public String toString() {
341        final StringBuilder sb = new StringBuilder("TouchPoint [");
342
343        sb.append("state = ").append(getState());
344        sb.append(", id = ").append(getId());
345        sb.append(", target = ").append(getTarget());
346        sb.append(", x = ").append(getX()).append(", y = ").append(getY())
347                .append(", z = ").append(getZ());
348        sb.append(", pickResult = ").append(getPickResult());
349
350        return sb.append("]").toString();
351    }
352
353    private void readObject(java.io.ObjectInputStream in)
354            throws IOException, ClassNotFoundException {
355        in.defaultReadObject();
356        x = sceneX;
357        y = sceneY;
358    }
359
360    /**
361     * Represents current state of the touch point
362     *
363     * @since 2.2
364     */
365    public enum State {
366        /**
367         * The touch point has just been pressed (touched for the first time)
368         */
369        PRESSED,
370        /**
371         * The touch point has been moved
372         */
373        MOVED,
374        /**
375         * The touch point remains pressed and still (without moving)
376         */
377        STATIONARY,
378        /**
379         * The touch point has been released
380         */
381        RELEASED
382    }
383}