1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package javafx.scene.input;
  27 
  28 import com.sun.javafx.collections.annotations.ReturnsUnmodifiableCollection;
  29 import java.util.Collections;
  30 import java.util.List;
  31 import javafx.beans.NamedArg;
  32 import javafx.event.Event;
  33 import javafx.event.EventTarget;
  34 import javafx.event.EventType;
  35 
  36 /**
  37  * Touch event indicates a touch screen action. It contains detailed information
  38  * about each particular touch point.
  39  * <p>
  40  * Touch point represents a single touched finger and has its location,
  41  * state (pressed/moved/released/stationary) and an ID unique in scope of a
  42  * single gesture. For detailed reference see {@link TouchPoint}.
  43  * <p>
  44  * For each multi-touch action a set of touch events is generated - for each
  45  * touch point one. The event has type corresponds to its touch point's state.
  46  * Each of the events also contain
  47  * list of all the touch points. This design allows for handling complicated
  48  * multi-touch actions from one place while keeping it possible to
  49  * filter/consume each touch point separately. To recognize
  50  * which events belong into a single set there is {@code getEventSetId()}
  51  * method.
  52  * <p>
  53  * Each touch point is - similarly to mouse dragging - delivered to a single
  54  * node on which it was pressed, regardless of where it moves then. It is
  55  * possible to change this behavior by using a grabbing mechanism described
  56  * in {@link TouchPoint} documentation.
  57  *
  58  * @since JavaFX 2.2
  59  */
  60 public final class TouchEvent extends InputEvent {
  61 
  62     private static final long serialVersionUID = 20121107L;
  63 
  64     /**
  65      * Common supertype for all touch event types.
  66      */
  67     public static final EventType<TouchEvent> ANY =
  68             new EventType<TouchEvent>(InputEvent.ANY, "TOUCH");
  69 
  70     /**
  71      * This event occurs when the touch point is pressed (touched for the
  72      * first time).
  73      */
  74     public static final EventType<TouchEvent> TOUCH_PRESSED =
  75             new EventType<TouchEvent>(ANY, "TOUCH_PRESSED");
  76 
  77     /**
  78      * This event occurs when the touch point is moved.
  79      */
  80     public static final EventType<TouchEvent> TOUCH_MOVED =
  81             new EventType<TouchEvent>(ANY, "TOUCH_MOVED");
  82 
  83     /**
  84      * This event occurs when the touch point is released.
  85      */
  86     public static final EventType<TouchEvent> TOUCH_RELEASED =
  87             new EventType<TouchEvent>(ANY, "TOUCH_RELEASED");
  88 
  89     /**
  90      * This event occurs when the touch point is pressed and still (doesn't
  91      * move).
  92      */
  93     public static final EventType<TouchEvent> TOUCH_STATIONARY =
  94             new EventType<TouchEvent>(ANY, "TOUCH_STATIONARY");
  95 
  96     /**
  97      * Constructs new TouchEvent event.
  98      * @param source the source of the event. Can be null.
  99      * @param target the target of the event. Can be null.
 100      * @param eventType The type of the event.
 101      * @param touchPoint the touch point of this event
 102      * @param touchPoints set of touch points for the multi-touch action
 103      * @param eventSetId set id of the multi-touch action
 104      * @param shiftDown true if shift modifier was pressed.
 105      * @param controlDown true if control modifier was pressed.
 106      * @param altDown true if alt modifier was pressed.
 107      * @param metaDown true if meta modifier was pressed.
 108      * @since JavaFX 8.0
 109      */
 110     public TouchEvent(@NamedArg("source") Object source, @NamedArg("target") EventTarget target, @NamedArg("eventType") EventType<TouchEvent> eventType,
 111             @NamedArg("touchPoint") TouchPoint touchPoint, @NamedArg("touchPoints") List<TouchPoint> touchPoints, @NamedArg("eventSetId") int eventSetId,
 112             @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown, @NamedArg("altDown") boolean altDown,
 113             @NamedArg("metaDown") boolean metaDown) {
 114         super(source, target, eventType);
 115         this.touchPoints = touchPoints != null ? Collections.unmodifiableList(touchPoints) : null;
 116         this.eventSetId = eventSetId;
 117         this.shiftDown = shiftDown;
 118         this.controlDown = controlDown;
 119         this.altDown = altDown;
 120         this.metaDown = metaDown;
 121         this.touchPoint = touchPoint;
 122     }
 123 
 124     /**
 125      * Constructs new TouchEvent event with null source and target.
 126      * @param eventType The type of the event.
 127      * @param touchPoint the touch point of this event
 128      * @param touchPoints set of touch points for the multi-touch action
 129      * @param eventSetId set id of the multi-touch action
 130      * @param shiftDown true if shift modifier was pressed.
 131      * @param controlDown true if control modifier was pressed.
 132      * @param altDown true if alt modifier was pressed.
 133      * @param metaDown true if meta modifier was pressed.
 134      * @since JavaFX 8.0
 135      */
 136     public TouchEvent(@NamedArg("eventType") EventType<TouchEvent> eventType,
 137             @NamedArg("touchPoint") TouchPoint touchPoint, @NamedArg("touchPoints") List<TouchPoint> touchPoints, @NamedArg("eventSetId") int eventSetId,
 138             @NamedArg("shiftDown") boolean shiftDown, @NamedArg("controlDown") boolean controlDown, @NamedArg("altDown") boolean altDown,
 139             @NamedArg("metaDown") boolean metaDown) {
 140         this(null, null, eventType, touchPoint, touchPoints, eventSetId,
 141                 shiftDown, controlDown, altDown, metaDown);
 142     }
 143 
 144     /**
 145      * Returns number of touch points represented by this touch event set.
 146      * The returned number matches the size of the {@code touchPoints} list.
 147      * @return The number of touch points represented by this touch event set.
 148      */
 149     public int getTouchCount() {
 150         return touchPoints.size();
 151     }
 152 
 153     /**
 154      * Recomputes touch event for the given event source object.
 155      * @param event Event to modify
 156      * @param oldSource Source object of the current values
 157      * @param newSource Source object to compute values for
 158      */
 159     private static void recomputeToSource(TouchEvent event, Object oldSource,
 160             Object newSource) {
 161 
 162         for (TouchPoint tp : event.touchPoints) {
 163             tp.recomputeToSource(oldSource, newSource);
 164         }
 165     }
 166 
 167 
 168     /**
 169      * @inheritDoc
 170      */
 171     @Override
 172     public TouchEvent copyFor(Object newSource, EventTarget newTarget) {
 173         TouchEvent e = (TouchEvent) super.copyFor(newSource, newTarget);
 174         recomputeToSource(e, getSource(), newSource);
 175         return e;
 176     }
 177 
 178     /**
 179      * Creates a copy of the given event with the given fields substituted.
 180      * @param newSource the new source of the copied event
 181      * @param newTarget the new target of the copied event
 182      * @param type the new eventType
 183      * @return the event copy with the fields substituted
 184      * @since JavaFX 8.0
 185      */
 186     public TouchEvent copyFor(Object newSource, EventTarget newTarget, EventType<TouchEvent> type) {
 187         TouchEvent e = copyFor(newSource, newTarget);
 188         e.eventType = type;
 189         return e;
 190     }
 191 
 192     @Override
 193     public EventType<TouchEvent> getEventType() {
 194         return (EventType<TouchEvent>) super.getEventType();
 195     }
 196 
 197     private final int eventSetId;
 198 
 199     /**
 200      * Gets sequential number of the set of touch events representing the same
 201      * multi-touch action. For a multi-touch user action, number of touch points
 202      * may exist; each of them produces a touch event, each of those touch
 203      * events carry the same list of touch points - and all of them return the
 204      * same number from this method. Then state of some of the touch points
 205      * changes and the new set of events has new id. The id is guaranteed
 206      * to be sequential and unique in scope of one gesture (is reset when
 207      * all touch points are released).
 208      *
 209      * @return Sequential id of event set unique in scope of a gesture
 210      */
 211     public final int getEventSetId() {
 212         return eventSetId;
 213     }
 214 
 215 
 216     /**
 217      * Whether or not the Shift modifier is down on this event.
 218      */
 219     private final boolean shiftDown;
 220 
 221     /**
 222      * Whether or not the Shift modifier is down on this event.
 223      * @return true if the Shift modifier is down on this event
 224      */
 225     public final boolean isShiftDown() {
 226         return shiftDown;
 227     }
 228 
 229     /**
 230      * Whether or not the Control modifier is down on this event.
 231      */
 232     private final boolean controlDown;
 233 
 234     /**
 235      * Whether or not the Control modifier is down on this event.
 236      * @return true if the Control modifier is down on this event
 237      */
 238     public final boolean isControlDown() {
 239         return controlDown;
 240     }
 241 
 242     /**
 243      * Whether or not the Alt modifier is down on this event.
 244      */
 245     private final boolean altDown;
 246 
 247     /**
 248      * Whether or not the Alt modifier is down on this event.
 249      * @return true if the Alt modifier is down on this event
 250      */
 251     public final boolean isAltDown() {
 252         return altDown;
 253     }
 254 
 255     /**
 256      * Whether or not the Meta modifier is down on this event.
 257      */
 258     private final boolean metaDown;
 259 
 260     /**
 261      * Whether or not the Meta modifier is down on this event.
 262      * @return true if the Meta modifier is down on this event
 263      */
 264     public final boolean isMetaDown() {
 265         return metaDown;
 266     }
 267 
 268     private final TouchPoint touchPoint;
 269 
 270     /**
 271      * Gets the touch point of this event.
 272      * @return Touch point of this event
 273      */
 274     public TouchPoint getTouchPoint() {
 275         return touchPoint;
 276     }
 277 
 278     private final List<TouchPoint> touchPoints;
 279 
 280     /**
 281      * Gets all the touch points represented by this set of touch events,
 282      * including the touch point of this event. The list is unmodifiable and
 283      * is sorted by their IDs, which means it is also sorted by the time
 284      * they were pressed. To distinguish between touch points belonging to
 285      * a node and unrelated touch points, TouchPoint's {@code belongsTo}
 286      * method can be used.
 287      * @return All current touch points in an unmodifiable list
 288      */
 289     @ReturnsUnmodifiableCollection
 290     public List<TouchPoint> getTouchPoints() {
 291         return touchPoints;
 292     }
 293 
 294     /**
 295      * Returns a string representation of this {@code TouchEvent} object.
 296      * @return a string representation of this {@code TouchEvent} object.
 297      */
 298     @Override public String toString() {
 299         final StringBuilder sb = new StringBuilder("TouchEvent [");
 300 
 301         sb.append("source = ").append(getSource());
 302         sb.append(", target = ").append(getTarget());
 303         sb.append(", eventType = ").append(getEventType());
 304         sb.append(", consumed = ").append(isConsumed());
 305         sb.append(", touchCount = ").append(getTouchCount());
 306         sb.append(", eventSetId = ").append(getEventSetId());
 307 
 308         sb.append(", touchPoint = ").append(getTouchPoint().toString());
 309 
 310         return sb.append("]").toString();
 311     }
 312 
 313 }