Add Global event for Rotary device.
Add Rotary Event functions for isolated evas object.
Add Tests for rotary events.
Change-Id: I56fc247daf0b25c93269a09310c22ddb257acc6e
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace ElmSharp.Wearable
+{
+ /// <summary>
+ /// RotaryEventManager serve functions for global Rotary event like Galaxy Gear.
+ /// </summary>
+ public static class RotaryEventManager
+ {
+ static Dictionary<RotaryEventHandler, Interop.Eext.Eext_Rotary_Handler_Cb> s_rotaryEventHandlers = new Dictionary<RotaryEventHandler, Interop.Eext.Eext_Rotary_Handler_Cb>();
+
+ /// <summary>
+ /// Rotated will triggered when rotatable device like Galaxy Gear Bezel is rotated.
+ /// </summary>
+ public static event RotaryEventHandler Rotated
+ {
+ add
+ {
+ if (s_rotaryEventHandlers.ContainsKey(value)) return;
+
+ Interop.Eext.Eext_Rotary_Handler_Cb cb = (data, infoPtr) =>
+ {
+ var info = Interop.Eext.FromIntPtr(infoPtr);
+ value.Invoke(new RotaryEventArgs
+ {
+ IsClockwise = info.Direction == Interop.Eext.Eext_Rotary_Event_Direction.Clockwise,
+ Timestamp = info.TimeStamp
+ });
+ return true;
+ };
+ Interop.Eext.eext_rotary_event_handler_add(cb, IntPtr.Zero);
+ s_rotaryEventHandlers[value] = cb;
+ }
+
+ remove
+ {
+ Interop.Eext.Eext_Rotary_Handler_Cb cb;
+ if (s_rotaryEventHandlers.TryGetValue(value, out cb))
+ {
+ Interop.Eext.eext_rotary_event_handler_del(cb);
+ s_rotaryEventHandlers.Remove(value);
+ }
+ }
+ }
+ }
+
+
+ /// <summary>
+ /// RotaryEventManager serve extension functions for Rotary event to EvasObject on device like Galaxy Gear.
+ /// </summary>
+ public static class EvasObjectExtensions
+ {
+ static Dictionary<EvasObject, RotaryEventHandler> s_rotaryObjectEventHandlers = new Dictionary<EvasObject, RotaryEventHandler>();
+ static Dictionary<EvasObject, Interop.Eext.Eext_Rotary_Event_Cb> s_rotaryObjectEventMap = new Dictionary<EvasObject, Interop.Eext.Eext_Rotary_Event_Cb>();
+
+ /// <summary>
+ /// Add a handler for Rotary event on specific EvasObject.
+ /// </summary>
+ /// <param name="obj">Target EvasObject</param>
+ /// <param name="handler">Event handler for Rotary event</param>
+ public static void AddRotaryEventHandler(this EvasObject obj, RotaryEventHandler handler)
+ {
+ EnableRotaryEventHandler(obj);
+
+ if (s_rotaryObjectEventHandlers.ContainsKey(obj))
+ {
+ s_rotaryObjectEventHandlers[obj] += handler;
+ }
+ else
+ {
+ s_rotaryObjectEventHandlers[obj] = handler;
+ }
+ }
+
+ /// <summary>
+ /// Remove a handler on specific EvasObject for Rotary event.
+ /// </summary>
+ /// <param name="obj">Target EvasObject</param>
+ /// <param name="handler">Event handler for Rotary event</param>
+ public static void RemoveRotaryEventHandler(this EvasObject obj, RotaryEventHandler handler)
+ {
+ if (s_rotaryObjectEventHandlers.ContainsKey(obj))
+ {
+ s_rotaryObjectEventHandlers[obj] -= handler;
+ if (s_rotaryObjectEventHandlers[obj] == null)
+ {
+ DisableRotaryEventHandler(obj, false);
+ s_rotaryObjectEventHandlers.Remove(obj);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Activate this object can take Rotary event.
+ /// </summary>
+ /// <param name="obj">Target object</param>
+ public static void Activate(this EvasObject obj)
+ {
+ Interop.Eext.eext_rotary_object_event_activated_set(obj, true);
+ }
+
+ /// <summary>
+ /// Deactivate this object is blocked from Rotary event.
+ /// </summary>
+ /// <param name="obj">Target object</param>
+ public static void Deactivate(this EvasObject obj)
+ {
+ Interop.Eext.eext_rotary_object_event_activated_set(obj, false);
+ }
+
+ static void EnableRotaryEventHandler(EvasObject obj)
+ {
+ if (!s_rotaryObjectEventMap.ContainsKey(obj))
+ {
+ Interop.Eext.Eext_Rotary_Event_Cb cb = (d, o, i) =>
+ {
+ RotaryEventHandler events;
+ if (s_rotaryObjectEventHandlers.TryGetValue(obj, out events))
+ {
+ var info = Interop.Eext.FromIntPtr(i);
+ events?.Invoke(new RotaryEventArgs
+ {
+ IsClockwise = info.Direction == Interop.Eext.Eext_Rotary_Event_Direction.Clockwise,
+ Timestamp = info.TimeStamp
+ });
+ }
+ return true;
+ };
+ Interop.Eext.eext_rotary_object_event_callback_add(obj, cb, IntPtr.Zero);
+ s_rotaryObjectEventMap[obj] = cb;
+ obj.Deleted += (s, e) => DisableRotaryEventHandler(obj, true);
+ }
+ }
+
+ static void DisableRotaryEventHandler(EvasObject obj, bool removeHandler)
+ {
+ Interop.Eext.Eext_Rotary_Event_Cb cb;
+ if (s_rotaryObjectEventMap.TryGetValue(obj, out cb))
+ {
+ Interop.Eext.eext_rotary_object_event_callback_del(obj, cb);
+ s_rotaryObjectEventMap.Remove(obj);
+ }
+ if (removeHandler && s_rotaryObjectEventHandlers.ContainsKey(obj))
+ {
+ s_rotaryObjectEventHandlers.Remove(obj);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Handler for Rotary event
+ /// </summary>
+ /// <param name="args">Rotary event information</param>
+ public delegate void RotaryEventHandler(RotaryEventArgs args);
+
+ /// <summary>
+ /// RotaryEventArgs serve information for triggered rotary event.
+ /// </summary>
+ public class RotaryEventArgs : EventArgs
+ {
+ /// <summary>
+ /// IsClockwise is true when Rotary device rotated clockwise direction or false on counter clockwise.
+ /// </summary>
+ public bool IsClockwise { get; set; }
+
+ /// <summary>
+ /// Timestamp of rotary event
+ /// </summary>
+ public uint Timestamp { get; set; }
+ }
+}
internal static partial class Interop
{
-
internal static partial class Eext
{
+ const short EEXT_CALLBACK_PRIORITY_AFTER = 100;
+ const short EEXT_CALLBACK_PRIORITY_BEFORE = -100;
+ const short EEXT_CALLBACK_PRIORITY_DEFAULT = 0;
+
+ internal delegate bool Eext_Rotary_Event_Cb(IntPtr data, IntPtr obj, IntPtr info);
+ internal delegate bool Eext_Rotary_Handler_Cb(IntPtr data, IntPtr info);
+
+ internal enum Eext_Rotary_Event_Direction
+ {
+ Clockwise,
+ CounterClockwise
+ }
+
+ internal struct Eext_Rotary_Event_Info
+ {
+ public Eext_Rotary_Event_Direction Direction;
+ public uint TimeStamp;
+ }
+
+ internal static Eext_Rotary_Event_Info FromIntPtr(IntPtr infoPtr)
+ {
+ var info = Marshal.PtrToStructure<Eext_Rotary_Event_Info>(infoPtr);
+ return info;
+ }
+
[DllImport(Libraries.Eext)]
internal static extern IntPtr eext_rotary_object_event_activated_set(IntPtr circleObject, bool activated);
+
+ [DllImport(Libraries.Eext)]
+ internal static extern bool eext_rotary_object_event_callback_add(IntPtr obj, Eext_Rotary_Event_Cb func, IntPtr data);
+
+ [DllImport(Libraries.Eext)]
+ internal static extern bool eext_rotary_object_event_callback_priority_add(IntPtr obj, short priority, Eext_Rotary_Event_Cb func, IntPtr data);
+
+ [DllImport(Libraries.Eext)]
+ internal static extern IntPtr eext_rotary_object_event_callback_del(IntPtr obj, Eext_Rotary_Event_Cb func);
+
+ [DllImport(Libraries.Eext)]
+ internal static extern bool eext_rotary_event_handler_add(Eext_Rotary_Handler_Cb func, IntPtr data);
+
+ [DllImport(Libraries.Eext)]
+ internal static extern IntPtr eext_rotary_event_handler_del(Eext_Rotary_Handler_Cb func);
}
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ElmSharp.Test
+{
+ public static class CircleTool
+ {
+ static Rect _inSquare;
+ public static Rect GetInnerSquare(this Window window)
+ {
+ Size screenSize = window.ScreenSize;
+ int min = Math.Min(screenSize.Height, screenSize.Width);
+ int width = (int)(min * Math.Cos(Math.PI / 4));
+ int x = screenSize.Width / 2 - width / 2;
+ int y = screenSize.Height / 2 - width / 2;
+
+ return _inSquare == default(Rect) ? (_inSquare = new Rect(x, y, width, width)) : _inSquare;
+ }
+ }
+}
--- /dev/null
+using ElmSharp.Wearable;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ElmSharp.Test.TC
+{
+ public class RotaryEvent1 : TestCaseBase
+ {
+ public override string TestName => "Rotary Event Test 1";
+
+ public override string TestDescription => "Wearable test for Rotary event";
+
+ public override void Run(Window window)
+ {
+ Log.Debug("window id is " + window.Handle.ToString());
+ Rect square = window.GetInnerSquare();
+
+ Log.Debug(square.ToString());
+
+ Rectangle redSquare = new Rectangle(window)
+ {
+ Color = Color.Red,
+ Geometry = square
+ };
+ redSquare.Show();
+
+ double degrees = 0;
+
+ RotaryEventHandler handler = (args) =>
+ {
+ if (args.IsClockwise) degrees += 10;
+ else degrees -= 10;
+
+ if (degrees < 0) degrees = 360;
+ else if (degrees > 360) degrees = 0;
+
+ Rect rect = redSquare.Geometry;
+ EvasMap map = new EvasMap(4);
+ map.PopulatePoints(redSquare, 0);
+ map.Rotate(degrees, rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
+ redSquare.EvasMap = map;
+ redSquare.IsMapEnabled = true;
+ };
+
+ RotaryEventManager.Rotated += handler;
+
+ window.BackButtonPressed += (s, e) =>
+ {
+ RotaryEventManager.Rotated -= handler;
+ Log.Debug("handler is Removed!!!!!!!");
+ };
+ }
+ }
+}
--- /dev/null
+using ElmSharp.Wearable;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ElmSharp.Test.TC
+{
+ public class RotaryEvent2 : TestCaseBase
+ {
+ public override string TestName => "Rotary Event Test 2";
+
+ public override string TestDescription => "Wearable test for Rotary object event";
+
+ Rectangle rect;
+
+ double degrees = 0;
+
+ void EventHandler(RotaryEventArgs args)
+ {
+ if (args.IsClockwise) degrees += 10;
+ else degrees -= 10;
+
+ if (degrees < 0) degrees = 360;
+ else if (degrees > 360) degrees = 0;
+
+ Rect r = rect.Geometry;
+ EvasMap map = new EvasMap(4);
+ map.PopulatePoints(rect, 0);
+ map.Rotate(degrees, r.X + r.Width / 2, r.Y + r.Height / 2);
+ rect.EvasMap = map;
+ rect.IsMapEnabled = true;
+ }
+
+ public override void Run(Window window)
+ {
+ Rect square = window.GetInnerSquare();
+
+ Log.Debug(square.ToString());
+
+ rect = new Rectangle(window)
+ {
+ Color = Color.Blue,
+ Geometry = square
+ };
+ rect.Show();
+
+ rect.AddRotaryEventHandler(EventHandler);
+ rect.Activate();
+
+ window.BackButtonPressed += (s, e) => rect.RemoveRotaryEventHandler(EventHandler);
+ }
+ }
+}
--- /dev/null
+using ElmSharp.Wearable;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ElmSharp.Test.TC
+{
+ public class RotaryEvent3 : TestCaseBase
+ {
+ public override string TestName => "Rotary Event Test 3";
+
+ public override string TestDescription => "Multiple wearable test for Rotary event";
+
+ public override void Run(Window window)
+ {
+ Log.Debug("window id is " + window.Handle.ToString());
+ Rect square = window.GetInnerSquare();
+
+ Log.Debug(square.ToString());
+
+ Rectangle redSquare = new Rectangle(window)
+ {
+ Color = Color.Red,
+ Geometry = square
+ };
+ redSquare.Show();
+
+ Rectangle blueSquare = new Rectangle(window)
+ {
+ Color = Color.Blue,
+ Geometry = new Rect(square.X + square.Width / 4, square.Y + square.Height / 4, square.Width / 2, square.Height / 2)
+ };
+ blueSquare.Show();
+
+ double degrees = 0;
+ double degrees2 = 0;
+
+ RotaryEventHandler handler1 = (args) =>
+ {
+ Log.Debug((args.IsClockwise ? "CW" : "CCW") + " : " + args.Timestamp);
+ if (args.IsClockwise) degrees2 += 10;
+ else degrees2 -= 10;
+
+ if (degrees2 < 0) degrees2 = 360;
+ else if (degrees2 > 360) degrees2 = 0;
+
+ Rect rect = blueSquare.Geometry;
+ EvasMap map = new EvasMap(4);
+ map.PopulatePoints(blueSquare, 0);
+ map.Rotate(degrees2, rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
+ blueSquare.EvasMap = map;
+ blueSquare.IsMapEnabled = true;
+ };
+
+ RotaryEventHandler handler2 = (args) =>
+ {
+ if (args.IsClockwise) degrees += 10;
+ else degrees -= 10;
+
+ if (degrees < 0) degrees = 360;
+ else if (degrees > 360) degrees = 0;
+
+ Rect rect = redSquare.Geometry;
+ EvasMap map = new EvasMap(4);
+ map.PopulatePoints(redSquare, 0);
+ map.Rotate(degrees, rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
+ redSquare.EvasMap = map;
+ redSquare.IsMapEnabled = true;
+ };
+
+ RotaryEventManager.Rotated += handler1;
+ RotaryEventManager.Rotated += handler2;
+
+ window.BackButtonPressed += (s, e) =>
+ {
+ RotaryEventManager.Rotated -= handler1;
+ RotaryEventManager.Rotated -= handler2;
+ Log.Debug("handler is Removed!!!!!!!");
+ };
+ }
+ }
+}