javauis/nokiauiapi_qt/javasrc_j2se/com/nokia/mid/ui/TactileFeedback.java
changeset 79 2f468c1958d0
--- /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.
+ * <p>
+ * The API supports both LCDUI and eSWT UI toolkits.
+ * <p>
+ * 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.
+ * <p>
+ * Tactile feedback can be generated in two ways:
+ * <ul>
+ * <li>By producing direct feedback from the application.</li>
+ * <li>By adding feedback areas to area registry, in which case the feedback
+ * will be produced by the tactile feedback system automatically when the
+ * defined screen area (with defined feedback) is touched.</li>
+ * </ul>
+ * <p>
+ * 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.
+ * <p>
+ * 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
+ * <code>controlMoved</code> and <code>controlResized</code> methods of
+ * <code>ControlListener</code> interface.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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.
+ * <p>
+ * 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: <code>javax.microedition.lcdui.Canvas</code>,
+ * <code>javax.microedition.lcdui.CustomItem</code>,
+ * <code>org.eclipse.swt.widgets.Control</code>. 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 <code>id</code> 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 <code>x</code>, <code>y</code>, <code>width</code>
+     * and <code>height</code> parameters may be located on the screen just
+     * partially.
+     *
+     * <p>
+     * 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
+     * <code>controlMoved</code> and <code>controlResized</code> methods of
+     * <code>ControlListener</code> interface. The update of an area may be
+     * implemented by calling registerFeedbackArea with the same area id but new
+     * coordinates and/or feedback style.
+     * <p>
+     * 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: <code>javax.microedition.lcdui.Canvas</code>
+     *            , <code>javax.microedition.lcdui.CustomItem</code>,
+     *            <code>org.eclipse.swt.widgets.Control</code>.
+     * @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 <code>FEEDBACK_STYLE_BASIC</code>,
+     *            <code>FEEDBACK_STYLE_SENSITIVE</code>. 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:
+     *            <code>javax.microedition.lcdui.Canvas</code>,
+     *            <code>javax.microedition.lcdui.CustomItem</code>,
+     *            <code>org.eclipse.swt.widgets.Control</code>.
+     * @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:
+     *            <code>javax.microedition.lcdui.Canvas</code>,
+     *            <code>javax.microedition.lcdui.CustomItem</code>,
+     *            <code>org.eclipse.swt.widgets.Control</code>.
+     * @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:
+     *            <code>javax.microedition.lcdui.Canvas</code>,
+     *            <code>javax.microedition.lcdui.CustomItem</code>,
+     *            <code>org.eclipse.swt.widgets.Control</code>.
+     * @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;
+    }
+
+}