diff -r 4ad59aaee882 -r 2f468c1958d0 javauis/nokiauiapi_qt/javasrc_j2se/com/nokia/mid/ui/TactileFeedback.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/nokiauiapi_qt/javasrc_j2se/com/nokia/mid/ui/TactileFeedback.java Mon Oct 04 00:10:53 2010 +0300 @@ -0,0 +1,462 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +package com.nokia.mid.ui; + +import org.eclipse.swt.widgets.Internal_PackageSupport; +import com.nokia.mid.ui.internal.OS; + +; + +/** + * This class is a Java extension to support tactile feedback (audio, vibra, + * piezo, etc.) on touch-enabled devices. Tactile feedback is meant to give user + * more clear feeling of touch events, like tapping and dragging. The actual + * physical tactile feedback depends on the device tactile feedback + * implementation, hardware and device settings. A device may implement the + * feedback with different hardware methods, for example, vibra, audio or piezo + * hardware. + *

+ * The API supports both LCDUI and eSWT UI toolkits. + *

+ * Using this class is safe when a device does not support tactile feedback. In + * this case methods of this class can be called but this has no effect. + *

+ * Tactile feedback can be generated in two ways: + *

+ *

+ * Direct feedback is given instantly with {@link #directFeedback + * directFeedback} specifying the feedback type. Direct feedback can be used + * when the user action is not just a tap in a certain area. For example if the + * user drags from one menu item to the other the application may give direct + * feedback to emphasize focus traverse. + *

+ * In case of area registry for eSWT Control, the registry needs to be updated + * every time when the size or position of a UI component changes, or when e.g. + * a state of a UI component changes in such way that feedback type also + * changes. Typically the area update may be implemented in + * controlMoved and controlResized methods of + * ControlListener interface. + *

+ * In case of area registry for LCDUI Canvas or CustomItem no further actions + * are required to update tactile feedback areas when a CustomItem is moved in a + * Form or when a Canvas is changed due to e.g. orientation switch. + *

+ * There are quite tight latency requirements for tactile feedback, and in most + * cases feedback should be triggered in less than 30ms from the time when user + * touched the screen. For the area registry the feedback system is responsible + * of fulfilling this requirement, but in case of direct feedback it is the + * responsibility of the user of this API. + *

+ * The tactile feedback has 2 different styles: Basic and Sensitive. Each type + * is defined in the device settings, not by this API. Each style of feedback is + * used in different cases. Typically Basic style is used to emphasize the tap + * event, while Sensitive style is used mostly at dragging operations, to + * emphasize focus traverse, text selection, etc. Choosing a specific style for + * each use case in up to developer, however it is good to follow the behavior + * of native applications. + *

+ * The goal of the API is to enable user-created UI components to have tactile + * feedback. The UI component types supported by the API are limited to + * user-defined components only: javax.microedition.lcdui.Canvas, + * javax.microedition.lcdui.CustomItem, + * org.eclipse.swt.widgets.Control. Other UI components (i.e. List, + * TextBox, etc.) get default tactile feedback automatically from the platform. + * + * @version 0.001 + * @since 1.2 + */ + +public class TactileFeedback +{ + + /** + * Constant for specifying basic tactile feedback style. Actual style + * behaviour is set through device settings. + */ + public static final int FEEDBACK_STYLE_BASIC = 1; + + /** + * Constant for specifying sensitive tactile feedback style. Actual style + * behaviour is set through device settings. + */ + public static final int FEEDBACK_STYLE_SENSITIVE = 2; + + private final String invalidFeedbackStyleMsg = "Invalid feedback style specified"; + private final String invalidControlTypeMsg = "Invalid object provided for tactile feedback registration"; + + private static final int TYPE_INVALID = 0; + private static final int TYPE_ESWT = 1; + private static final int TYPE_LCDUI = 2; + private static boolean feedbackEnabled; + + /** + * Constructs tactile feedback engine object. The object may be used in both + * LCDUI and eSWT java UI toolkits. TactileFeedback object must be + * constructed before using any tactile feedback methods. + */ + public TactileFeedback() + { + } + + /** + * Triggers direct tactile feedback of the specified style. + * + * @param style + * The style of the direct feedback. Use predefined values + * FEEDBACK_STYLE_BASIC, FEEDBACK_STYLE_SENSITIVE. Actual style + * behavior is set through device settings. + * @throws IllegalArgumentException + * if the style parameter has invalid type. + */ + public void directFeedback(int style) throws IllegalArgumentException + { + if ((style != FEEDBACK_STYLE_BASIC) + && (style != FEEDBACK_STYLE_SENSITIVE)) + throw new IllegalArgumentException(invalidFeedbackStyleMsg); + if (org.eclipse.swt.widgets.Display.getCurrent() == null) + { + final int fStyle = style; + com.nokia.mj.impl.nokialcdui.LCDUIInvoker + .eSWTUIThreadRunnerSyncExec(new Runnable() + { + public void run() + { + // OS.MTouchFeedback_InstantFeedback(fStyle); + } + }); + + } + else + { + //OS.MTouchFeedback_InstantFeedback(style); + } + } + + /** + * Queries the device if it supports tactile feedback. It is safe to use + * this class even if the device does not support tactile feedback. Methods + * of this class can be called but this has no effect. + * + * @return true if the device supports tactile feedback, false otherwise. + */ + public boolean isTouchFeedbackSupported() + { + if (org.eclipse.swt.widgets.Display.getCurrent() == null) + { + com.nokia.mj.impl.nokialcdui.LCDUIInvoker + .eSWTUIThreadRunnerSyncExec(new Runnable() + { + + public void run() + { + // feedbackEnabled = OS + // .MTouchFeedback_TouchFeedbackSupported(); + } + }); + } + else + { + // feedbackEnabled = OS.MTouchFeedback_TouchFeedbackSupported(); + } + return feedbackEnabled; + } + + /** + * Registers area within a UI component for tactile feedback. If areas + * overlap then the feedback is given from the last registered area. + * {@link #moveFeedbackAreaToFirstPriority moveFeedbackAreaToFirstPriority} + * can be used to bring a certain area covered by another area into action. + * If an area with specified id is already registered it is + * updated. When updating an existing area there is no need to unregister it + * before re-registering again with new coordinates and/or feedback style. + * The area specified by x, y, width + * and height parameters may be located on the screen just + * partially. + * + *

+ * In case of area registry for eSWT Control, the registry needs to be + * updated every time when the size or position of a UI component changes, + * or when e.g. a state of a UI component changes in such way that feedback + * type also changes. Typically the area update may be implemented in + * controlMoved and controlResized methods of + * ControlListener interface. The update of an area may be + * implemented by calling registerFeedbackArea with the same area id but new + * coordinates and/or feedback style. + *

+ * In case of area registry for LCDUI Canvas or CustomItem no further + * actions are required to update tactile feedback areas when a CustomItem + * is moved in a Form or when a Canvas is changed due to e.g. orientation + * switch. + * + * @param uiObject + * The UI component for tactile feedback registration. Valid + * object types are: javax.microedition.lcdui.Canvas + * , javax.microedition.lcdui.CustomItem, + * org.eclipse.swt.widgets.Control. + * @param id + * Id of the new tactile feedback area to be registered. Id's are + * used to identify particular tactile feedback area within one + * UI component. Id's do not need to be consecutive numbers. + * @param x + * x-coordinate of the top-left corner of tactile feedback + * rectangle to register. + * @param y + * y-coordinate of the top-left corner of tactile feedback + * rectangle to register. + * @param width + * Width of tactile feedback rectangle to register. + * @param height + * Height of tactile feedback rectangle to register. + * @param style + * The style of the feedback for specified area. Use predefined + * values FEEDBACK_STYLE_BASIC, + * FEEDBACK_STYLE_SENSITIVE. Actual style behaviour + * is defined through device settings. + * @throws IllegalArgumentException + * if the uiObject parameter has invalid type. + * @throws IllegalArgumentException + * if the style parameter has invalid type. + */ + public void registerFeedbackArea(Object uiObject, int id, int x, int y, + int width, int height, int style) throws IllegalArgumentException + { + int type = controlType(uiObject); + if (type == TYPE_INVALID) + throw new IllegalArgumentException(invalidControlTypeMsg); + + if ((style != FEEDBACK_STYLE_BASIC) + && (style != FEEDBACK_STYLE_SENSITIVE)) + throw new IllegalArgumentException(invalidFeedbackStyleMsg); + + int controlHandle = getControlHandle(uiObject); + if (type == TYPE_LCDUI) + { + final int fControlHandle = controlHandle; + final int fId = id; + final int fX = x; + final int fY = y; + final int fWidth = width; + final int fHeight = height; + final int fStyle = style; + com.nokia.mj.impl.nokialcdui.LCDUIInvoker + .eSWTUIThreadRunnerSyncExec(new Runnable() + { + + public void run() + { + // OS.MTouchFeedback_SetFeedbackArea(fControlHandle, + // fId, fX, fY, fWidth, fHeight, fStyle); + } + }); + } + else + { + //OS.MTouchFeedback_SetFeedbackArea(controlHandle, id, x, y, width, + // height, style); + } + } + + /** + * Unregisters tactile feedback area within a UI component. + * + * @param uiObject + * The UI component for tactile feedback area de-registration. + * Valid object types are: + * javax.microedition.lcdui.Canvas, + * javax.microedition.lcdui.CustomItem, + * org.eclipse.swt.widgets.Control. + * @param id + * Id of the tactile feedback area to be unregistered. Id's are + * used to identify particular tactile feedback area within one + * UI component. If given id was not registered by + * {@link #registerFeedbackArea registerFeedbackArea} then the + * call has no effect. + * @throws IllegalArgumentException + * if the uiObject parameter has invalid type. + */ + public void unregisterFeedbackArea(Object uiObject, int id) + throws IllegalArgumentException + { + + int type = controlType(uiObject); + if (type == TYPE_INVALID) + throw new IllegalArgumentException(invalidControlTypeMsg); + + int controlHandle = getControlHandle(uiObject); + if (type == TYPE_LCDUI) + { + final int fControlHandle = controlHandle; + final int fId = id; + com.nokia.mj.impl.nokialcdui.LCDUIInvoker + .eSWTUIThreadRunnerSyncExec(new Runnable() + { + + public void run() + { + // OS.MTouchFeedback_RemoveFeedbackArea( + // fControlHandle, fId); + } + }); + } + else + { + //OS.MTouchFeedback_RemoveFeedbackArea(controlHandle, id); + } + + } + + /** + * Removes all tactile feedback for a UI component. + * + * @param uiObject + * The UI component for tactile feedback area de-registration. + * Valid object types are: + * javax.microedition.lcdui.Canvas, + * javax.microedition.lcdui.CustomItem, + * org.eclipse.swt.widgets.Control. + * @throws IllegalArgumentException + * if the uiObject parameter has invalid type. + */ + public void removeFeedbackForComponent(Object uiObject) + { + if (isTouchFeedbackSupported() == false) + return; + + int type = controlType(uiObject); + if (type == TYPE_INVALID) + throw new IllegalArgumentException(invalidControlTypeMsg); + + int controlHandle = getControlHandle(uiObject); + + if (type == TYPE_LCDUI) + { + final int fControlHandle = controlHandle; + com.nokia.mj.impl.nokialcdui.LCDUIInvoker + .eSWTUIThreadRunnerSyncExec(new Runnable() + { + + public void run() + { + // OS.MTouchFeedback_RemoveFeedbackForControl(fControlHandle); + } + }); + } + else + { + //OS.MTouchFeedback_RemoveFeedbackForControl(controlHandle); + } + + } + + /** + * Moves the specified tactile feedback area to first priority. Priority is + * significant in case of overlapping tactile feedback areas. If the tactile + * feedback styles of registered areas are different, the feedback from + * first-priority area will be given. + * + * @param uiObject + * The UI component for tactile feedback area de-registration. + * Valid object types are: + * javax.microedition.lcdui.Canvas, + * javax.microedition.lcdui.CustomItem, + * org.eclipse.swt.widgets.Control. + * @param id + * Id of the tactile feedback area to be unregistered. Id's are + * used to identify particular tactile feedback area within one + * UI component. If given id was not registered by + * {@link #registerFeedbackArea registerFeedbackArea} then the + * call has no effect. + * @throws IllegalArgumentException + * if the uiObject parameter has invalid type. + */ + public void moveFeedbackAreaToFirstPriority(Object uiObject, int id) + { + if (isTouchFeedbackSupported() == false) + return; + + int type = controlType(uiObject); + if (type == TYPE_INVALID) + throw new IllegalArgumentException(invalidControlTypeMsg); + + int controlHandle = getControlHandle(uiObject); + if (type == TYPE_LCDUI) + { + final int fControlHandle = controlHandle; + final int fId = id; + com.nokia.mj.impl.nokialcdui.LCDUIInvoker + .eSWTUIThreadRunnerSyncExec(new Runnable() + { + + public void run() + { + // OS.MTouchFeedback_MoveFeedbackAreaToFirstPriority( + // fControlHandle, fId); + } + }); + } + else + { + // OS.MTouchFeedback_MoveFeedbackAreaToFirstPriority( + // controlHandle, id); + } + + } + + + private int controlType(Object obj) + { + if ((obj instanceof javax.microedition.lcdui.Canvas) + || (obj instanceof javax.microedition.lcdui.CustomItem)) + { + return TYPE_LCDUI; + } + else if ((obj instanceof org.eclipse.swt.widgets.Control)) + { + return TYPE_ESWT; + } + return TYPE_INVALID; + } + + private int getControlHandle(Object uiObject) + { + int controlHandle = 0; + org.eclipse.swt.widgets.Control eSwtControl = null; + if (uiObject instanceof javax.microedition.lcdui.Canvas + || uiObject instanceof javax.microedition.lcdui.CustomItem) + { + eSwtControl = com.nokia.mj.impl.nokialcdui.LCDUIInvoker + .getEswtControl(uiObject); + } + else if (uiObject instanceof org.eclipse.swt.widgets.Control) + { + eSwtControl = (org.eclipse.swt.widgets.Control) uiObject; + } + + if (eSwtControl != null) + { + controlHandle = Internal_PackageSupport.topHandle(eSwtControl); + } + return controlHandle; + } + +}