Refactoring EvasObjectEvent/SmartEvent
authorSeungkeun Lee <sngn.lee@samsung.com>
Wed, 9 Nov 2016 04:38:48 +0000 (13:38 +0900)
committerSeungkeun Lee <sngn.lee@samsung.com>
Wed, 9 Nov 2016 22:32:54 +0000 (07:32 +0900)
 - Change to public
  - need to access from others packages
 - Fix already been freed error message
 - Introduce EventLifeTracker to release automatically
  - EFL event object life cycle is depend on target object, so we treat different with normal c# class

Change-Id: I667fb5c3673fb2d3fb5741098737edea64ec5ae5

34 files changed:
ElmSharp.Test/TestRunner.cs
ElmSharp/ElmSharp.Net45.csproj
ElmSharp/ElmSharp.csproj
ElmSharp/ElmSharp/Button.cs
ElmSharp/ElmSharp/Calendar.cs
ElmSharp/ElmSharp/Check.cs
ElmSharp/ElmSharp/ColorSelector.cs
ElmSharp/ElmSharp/ContextPopup.cs
ElmSharp/ElmSharp/DateTimeSelector.cs
ElmSharp/ElmSharp/Entry.cs
ElmSharp/ElmSharp/EvasObject.cs
ElmSharp/ElmSharp/EvasObjectEvent.cs [new file with mode: 0644]
ElmSharp/ElmSharp/GenGrid.cs
ElmSharp/ElmSharp/GenList.cs
ElmSharp/ElmSharp/Image.cs [changed mode: 0755->0644]
ElmSharp/ElmSharp/Index.cs
ElmSharp/ElmSharp/Label.cs
ElmSharp/ElmSharp/Layout.cs
ElmSharp/ElmSharp/List.cs
ElmSharp/ElmSharp/Naviframe.cs
ElmSharp/ElmSharp/Panel.cs
ElmSharp/ElmSharp/Panes.cs
ElmSharp/ElmSharp/Popup.cs
ElmSharp/ElmSharp/ProgressBar.cs
ElmSharp/ElmSharp/Radio.cs
ElmSharp/ElmSharp/Scroller.cs
ElmSharp/ElmSharp/Slider.cs
ElmSharp/ElmSharp/SmartEvent.cs [moved from ElmSharp/Interop/Interop.SmartEvent.cs with 64% similarity]
ElmSharp/ElmSharp/Spinner.cs
ElmSharp/ElmSharp/Toolbar.cs
ElmSharp/ElmSharp/Widget.cs
ElmSharp/ElmSharp/Window.cs
ElmSharp/Interop/Interop.EvasObjectEvent.cs [deleted file]
packaging/elm-sharp.spec

index 9bee255..0d7afa2 100644 (file)
@@ -106,6 +106,8 @@ namespace ElmSharp.Test
                     {
                         window.Hide();
                         window.Unrealize();
+                        GC.Collect();
+                        GC.WaitForPendingFinalizers();
                     }
                 };
             }
index 6bc1650..9d53b09 100644 (file)
@@ -73,6 +73,7 @@
     <Compile Include="ElmSharp\EvasKeyEventArgs.cs" />
     <Compile Include="ElmSharp\EvasMap.cs" />
     <Compile Include="ElmSharp\EvasObject.cs" />
+    <Compile Include="ElmSharp\EvasObjectEvent.cs" />
     <Compile Include="ElmSharp\GenGrid.cs" />
     <Compile Include="ElmSharp\GenGridItem.cs" />
     <Compile Include="ElmSharp\GenItem.cs" />
     <Compile Include="ElmSharp\Scroller.cs" />
     <Compile Include="ElmSharp\Size.cs" />
     <Compile Include="ElmSharp\Slider.cs" />
+    <Compile Include="ElmSharp\SmartEvent.cs" />
     <Compile Include="ElmSharp\Spinner.cs" />
     <Compile Include="ElmSharp\Table.cs" />
     <Compile Include="ElmSharp\Toolbar.cs" />
     <Compile Include="Interop\Interop.Eo.cs" />
     <Compile Include="Interop\Interop.Evas.cs" />
     <Compile Include="Interop\Interop.Evas.Image.cs" />
-    <Compile Include="Interop\Interop.EvasObjectEvent.cs" />
     <Compile Include="Interop\Interop.Libc.cs" />
     <Compile Include="Interop\Interop.Libraries.cs" />
-    <Compile Include="Interop\Interop.SmartEvent.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
   <ItemGroup>
   <Target Name="AfterBuild">
   </Target>
   -->
-</Project>
\ No newline at end of file
+</Project>
index df61891..f11e9a8 100644 (file)
@@ -70,6 +70,7 @@
     <Compile Include="ElmSharp\EvasKeyEventArgs.cs" />
     <Compile Include="ElmSharp\EvasMap.cs" />
     <Compile Include="ElmSharp\EvasObject.cs" />
+    <Compile Include="ElmSharp\EvasObjectEvent.cs" />
     <Compile Include="ElmSharp\GenGrid.cs" />
     <Compile Include="ElmSharp\GenGridItem.cs" />
     <Compile Include="ElmSharp\GenItem.cs" />
     <Compile Include="ElmSharp\Scroller.cs" />
     <Compile Include="ElmSharp\Size.cs" />
     <Compile Include="ElmSharp\Slider.cs" />
+    <Compile Include="ElmSharp\SmartEvent.cs" />
     <Compile Include="ElmSharp\Spinner.cs" />
     <Compile Include="ElmSharp\Table.cs" />
     <Compile Include="ElmSharp\Toolbar.cs" />
     <Compile Include="Interop\Interop.Elementary.Win.cs" />
     <Compile Include="Interop\Interop.Evas.cs" />
     <Compile Include="Interop\Interop.Evas.Image.cs" />
-    <Compile Include="Interop\Interop.EvasObjectEvent.cs" />
     <Compile Include="Interop\Interop.Libc.cs" />
     <Compile Include="Interop\Interop.Libraries.cs" />
-    <Compile Include="Interop\Interop.SmartEvent.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
   <ItemGroup>
index 70d2bc3..1d69347 100644 (file)
@@ -20,17 +20,17 @@ namespace ElmSharp
 {
     public class Button : Layout
     {
-        private Interop.SmartEvent _clicked;
-        private Interop.SmartEvent _repeated;
-        private Interop.SmartEvent _pressed;
-        private Interop.SmartEvent _released;
+        private SmartEvent _clicked;
+        private SmartEvent _repeated;
+        private SmartEvent _pressed;
+        private SmartEvent _released;
 
         public Button(EvasObject parent) : base(parent)
         {
-            _clicked = new Interop.SmartEvent(this, Handle, "clicked");
-            _repeated = new Interop.SmartEvent(this, Handle, "repeated");
-            _pressed = new Interop.SmartEvent(this, Handle, "pressed");
-            _released = new Interop.SmartEvent(this, Handle, "unpressed");
+            _clicked = new SmartEvent(this, "clicked");
+            _repeated = new SmartEvent(this, "repeated");
+            _pressed = new SmartEvent(this, "pressed");
+            _released = new SmartEvent(this, "unpressed");
 
             _clicked.On += (sender, e) =>
             {
index 0c6876c..cecb080 100644 (file)
@@ -23,14 +23,14 @@ namespace ElmSharp
 {
     public class Calendar : Layout
     {
-        private Interop.SmartEvent _changed;
+        private SmartEvent _changed;
         private DateTime _cacheSelectedDate;
-        private Interop.SmartEvent _displayedMonthChanged;
+        private SmartEvent _displayedMonthChanged;
         private int _cacheDisplayedMonth;
 
         public Calendar(EvasObject parent) : base(parent)
         {
-            _changed = new Interop.SmartEvent(this, Handle, "changed");
+            _changed = new SmartEvent(this, "changed");
             _changed.On += (sender, e) =>
             {
                 DateTime selectedDate = SelectedDate;
@@ -38,7 +38,7 @@ namespace ElmSharp
                 _cacheSelectedDate = selectedDate;
             };
 
-            _displayedMonthChanged = new Interop.SmartEvent(this, Handle, "display,changed");
+            _displayedMonthChanged = new SmartEvent(this, "display,changed");
             _displayedMonthChanged.On += (sender, e) =>
             {
                 int currentDisplayedMonth = SelectedDate.Month;
index 86ab105..8284503 100644 (file)
@@ -20,12 +20,12 @@ namespace ElmSharp
 {
     public class Check : Layout
     {
-        private Interop.SmartEvent _changed;
+        private SmartEvent _changed;
         private bool _currentState;
 
         public Check(EvasObject parent) : base(parent)
         {
-            _changed = new Interop.SmartEvent(this, Handle, "changed");
+            _changed = new SmartEvent(this, "changed");
             _changed.On += (sender, e) =>
             {
                 StateChanged?.Invoke(this, new CheckStateChangedEventArgs(_currentState, IsChecked));
index 1872eda..1b0d251 100644 (file)
@@ -31,12 +31,12 @@ namespace ElmSharp
 
     public class ColorSelector : Layout
     {
-        private readonly Interop.SmartEvent<ColorChangedEventArgs> _changed;
+        private readonly SmartEvent<ColorChangedEventArgs> _changed;
         private Color _currentColor;
 
         public ColorSelector(EvasObject parent) : base(parent)
         {
-            _changed = new Interop.SmartEvent<ColorChangedEventArgs>(this, Handle, "changed", (data, obj, info) =>
+            _changed = new SmartEvent<ColorChangedEventArgs>(this, "changed", (data, obj, info) =>
             {
                 return new ColorChangedEventArgs(_currentColor, SelectedColor);
             });
index e3fdbd6..47a336c 100644 (file)
@@ -31,12 +31,12 @@ namespace ElmSharp
     public class ContextPopup : Layout
     {
         HashSet<ContextPopupItem> _children = new HashSet<ContextPopupItem>();
-        Interop.SmartEvent _dismissed;
+        SmartEvent _dismissed;
         Interop.Evas.SmartCallback _onSelected;
 
         public ContextPopup(EvasObject parent) : base(parent)
         {
-            _dismissed = new Interop.SmartEvent(this, Handle, "dismissed");
+            _dismissed = new SmartEvent(this, "dismissed");
             _dismissed.On += (sender, e) =>
             {
                 Dismissed?.Invoke(this, EventArgs.Empty);
index 6624e1d..fd3012d 100644 (file)
@@ -30,12 +30,12 @@ namespace ElmSharp
 
     public class DateTimeSelector : Layout
     {
-        Interop.SmartEvent _changed;
+        SmartEvent _changed;
         DateTime _cacheDateTime;
 
         public DateTimeSelector(EvasObject parent) : base(parent)
         {
-            _changed = new Interop.SmartEvent(this, Handle, "changed");
+            _changed = new SmartEvent(this, "changed");
             _changed.On += (s, e) =>
             {
                 DateTime newDateTime = DateTime;
index 0e4e5a5..a5ef7ca 100644 (file)
@@ -106,23 +106,23 @@ namespace ElmSharp
 
     public class Entry : Layout
     {
-        Interop.SmartEvent _clicked;
-        Interop.SmartEvent _changedByUser;
-        Interop.SmartEvent _cursorChanged;
-        Interop.SmartEvent _activated;
+        SmartEvent _clicked;
+        SmartEvent _changedByUser;
+        SmartEvent _cursorChanged;
+        SmartEvent _activated;
 
         public Entry(EvasObject parent) : base(parent)
         {
-            _clicked = new Interop.SmartEvent(this, Handle, "clicked");
+            _clicked = new SmartEvent(this, "clicked");
             _clicked.On += (s, e) => Clicked?.Invoke(this, EventArgs.Empty);
 
-            _changedByUser = new Interop.SmartEvent(this, Handle, "changed,user");
+            _changedByUser = new SmartEvent(this, "changed,user");
             _changedByUser.On += (s, e) => ChangedByUser?.Invoke(this, EventArgs.Empty);
 
-            _cursorChanged = new Interop.SmartEvent(this, Handle, "cursor,changed");
+            _cursorChanged = new SmartEvent(this, "cursor,changed");
             _cursorChanged.On += (s, e) => CursorChanged?.Invoke(this, EventArgs.Empty);
 
-            _activated = new Interop.SmartEvent(this, Handle, "activated");
+            _activated = new SmartEvent(this, "activated");
             _activated.On += (s, e) => Activated?.Invoke(this, EventArgs.Empty);
         }
 
index d366a64..664afd4 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 using System;
+using System.Collections.Generic;
 using System.Diagnostics;
 
 namespace ElmSharp
@@ -24,12 +25,14 @@ namespace ElmSharp
         internal IntPtr Handle { get; set; }
         internal EvasObject Parent { get; set; }
 
-        Interop.EvasObjectEvent _deleted;
-        Interop.EvasObjectEvent<EvasKeyEventArgs> _keyup;
-        Interop.EvasObjectEvent<EvasKeyEventArgs> _keydown;
-        Interop.EvasObjectEvent _moved;
-        Interop.EvasObjectEvent _resized;
-        Interop.EvasObjectEvent _renderPost;
+        EvasObjectEvent _deleted;
+        EvasObjectEvent<EvasKeyEventArgs> _keyup;
+        EvasObjectEvent<EvasKeyEventArgs> _keydown;
+        EvasObjectEvent _moved;
+        EvasObjectEvent _resized;
+        EvasObjectEvent _renderPost;
+
+        readonly HashSet<IInvalidatable> _eventStore = new HashSet<IInvalidatable>();
 
         protected EvasObject(EvasObject parent) : this()
         {
@@ -70,7 +73,6 @@ namespace ElmSharp
             remove { _renderPost.On -= value; }
         }
 
-
         public bool IsRealized { get { return Handle != IntPtr.Zero; } }
 
         public string ClassName
@@ -261,17 +263,6 @@ namespace ElmSharp
             Interop.Evas.evas_object_lower(Handle);
         }
 
-        public void MakeInvalidate()
-        {
-            Deleted?.Invoke(this, EventArgs.Empty);
-            OnInvalidate();
-            Handle = IntPtr.Zero;
-
-            (Parent as Window)?.RemoveChild(this);
-            Parent = null;
-            _deleted = null;
-        }
-
         public static implicit operator IntPtr(EvasObject obj)
         {
             if (obj == null)
@@ -323,17 +314,16 @@ namespace ElmSharp
                 (parent as Window)?.AddChild(this);
 
                 OnRealized();
-                _deleted = new Interop.EvasObjectEvent(this, Handle, Interop.Evas.ObjectCallbackType.Del);
-                _keydown = new Interop.EvasObjectEvent<EvasKeyEventArgs>(this, Handle, Interop.Evas.ObjectCallbackType.KeyDown, EvasKeyEventArgs.Create);
-                _keyup = new Interop.EvasObjectEvent<EvasKeyEventArgs>(this, Handle, Interop.Evas.ObjectCallbackType.KeyUp, EvasKeyEventArgs.Create);
-                _moved = new Interop.EvasObjectEvent(this, Handle, Interop.Evas.ObjectCallbackType.Move);
-                _resized = new Interop.EvasObjectEvent(this, Handle, Interop.Evas.ObjectCallbackType.Resize);
-                _renderPost = new Interop.EvasObjectEvent(this, Interop.Evas.evas_object_evas_get(Handle), Interop.Evas.ObjectCallbackType.RenderPost);
+                _deleted = new EvasObjectEvent(this, EvasObjectCallbackType.Del);
+                _keydown = new EvasObjectEvent<EvasKeyEventArgs>(this, EvasObjectCallbackType.KeyDown, EvasKeyEventArgs.Create);
+                _keyup = new EvasObjectEvent<EvasKeyEventArgs>(this, EvasObjectCallbackType.KeyUp, EvasKeyEventArgs.Create);
+                _moved = new EvasObjectEvent(this, EvasObjectCallbackType.Move);
+                _resized = new EvasObjectEvent(this, EvasObjectCallbackType.Resize);
+                _renderPost = new EvasObjectEvent(this, Interop.Evas.evas_object_evas_get(Handle), EvasObjectCallbackType.RenderPost);
 
                 _deleted.On += (s, e) => MakeInvalidate();
                 _keydown.On += (s, e) => KeyDown?.Invoke(this, e);
                 _keyup.On += (s, e) => KeyUp?.Invoke(this, e);
-
             }
         }
 
@@ -344,18 +334,8 @@ namespace ElmSharp
                 OnUnrealize();
                 IntPtr toBeDeleted = Handle;
                 Handle = IntPtr.Zero;
-                _deleted?.Dispose();
-                _deleted = null;
-                _keydown?.Dispose();
-                _keydown = null;
-                _keyup?.Dispose();
-                _keyup = null;
-                _moved?.Dispose();
-                _moved = null;
-                _resized?.Dispose();
-                _resized = null;
-                _renderPost?.Dispose();
-                _renderPost = null;
+
+                DisposeEvent();
 
                 (Parent as Window)?.RemoveChild(this);
 
@@ -363,5 +343,41 @@ namespace ElmSharp
                 Parent = null;
             }
         }
+
+        private void MakeInvalidate()
+        {
+            Deleted?.Invoke(this, EventArgs.Empty);
+            OnInvalidate();
+            Handle = IntPtr.Zero;
+
+            MakeInvalidateEvent();
+
+            (Parent as Window)?.RemoveChild(this);
+            Parent = null;
+            _deleted = null;
+        }
+
+        private void DisposeEvent()
+        {
+            foreach (var evt in _eventStore)
+            {
+                evt.Dispose();
+            }
+            _eventStore.Clear();
+        }
+        private void MakeInvalidateEvent()
+        {
+            foreach (var evt in _eventStore)
+            {
+                evt.MakeInvalidate();
+            }
+            _eventStore.Clear();
+        }
+
+        internal void AddToEventLifeTracker(IInvalidatable item)
+        {
+            _eventStore.Add(item);
+        }
+
     }
 }
diff --git a/ElmSharp/ElmSharp/EvasObjectEvent.cs b/ElmSharp/ElmSharp/EvasObjectEvent.cs
new file mode 100644 (file)
index 0000000..23c0b53
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * 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.Linq;
+
+namespace ElmSharp
+{
+    public interface IInvalidatable : IDisposable
+    {
+        void MakeInvalidate();
+    }
+    public enum EvasObjectCallbackType
+    {
+        MouseIn,
+        MouseOut,
+        MouseDown,
+        MouseUp,
+        MouseMove,
+        MouseWheel,
+        MultiDown,
+        MultiUp,
+        MultiMove,
+        Free,
+        KeyDown,
+        KeyUp,
+        FocusIn,
+        FocusOut,
+        Show,
+        Hide,
+        Move,
+        Resize,
+        Restack,
+        Del,
+        Hold,
+        ChangedSizeHints,
+        ImagePreloaded,
+        CanvasFocusIn,
+        CanvasFocusOut,
+        RenderFlushPre,
+        RenderFlushPost,
+        CanvasObjectFocusIn,
+        CanvasObjectFocusOut,
+        ImageUnloaded,
+        RenderPre,
+        RenderPost,
+        ImageResize,
+        DeviceChanged,
+        AxisUpdate,
+        CanvasViewportResize
+    }
+
+    public class EvasObjectEvent<TEventArgs> : IInvalidatable where TEventArgs : EventArgs
+    {
+        public delegate TEventArgs SmartEventInfoParser(IntPtr data, IntPtr obj, IntPtr info);
+
+        private bool _disposed = false;
+        private EvasObject _sender;
+        private IntPtr _handle;
+        private readonly EvasObjectCallbackType _type;
+        private readonly SmartEventInfoParser _parser;
+        private readonly List<NativeCallback> _nativeCallbacks = new List<NativeCallback>();
+
+        public EvasObjectEvent(EvasObject sender, EvasObjectCallbackType type, SmartEventInfoParser parser) : this(sender, sender.Handle, type, parser)
+        {
+        }
+
+        internal EvasObjectEvent(EvasObject sender, IntPtr handle, EvasObjectCallbackType type, SmartEventInfoParser parser)
+        {
+            _sender = sender;
+            _handle = handle;
+            _type = type;
+            _parser = parser;
+            sender.AddToEventLifeTracker(this);
+        }
+
+        public EvasObjectEvent(EvasObject sender, EvasObjectCallbackType type) : this(sender, type, null)
+        {
+        }
+
+        ~EvasObjectEvent()
+        {
+            Dispose(false);
+        }
+
+        private struct NativeCallback
+        {
+            public Interop.Evas.EventCallback callback;
+            public EventHandler<TEventArgs> eventHandler;
+        }
+
+        public event EventHandler<TEventArgs> On
+        {
+            add
+            {
+                if (_handle == IntPtr.Zero)
+                {
+                    return;
+                }
+                EventHandler<TEventArgs> handler = value;
+                var cb = new Interop.Evas.EventCallback((data, evas, obj, info) =>
+                {
+                    TEventArgs ea = _parser == null ? (TEventArgs)EventArgs.Empty : _parser(data, obj, info);
+                    handler(_sender, ea);
+                });
+                _nativeCallbacks.Add(new NativeCallback { callback = cb, eventHandler = handler });
+                int i = _nativeCallbacks.Count - 1;
+                Interop.Evas.evas_object_event_callback_add(_handle, (Interop.Evas.ObjectCallbackType)_type, _nativeCallbacks[i].callback, IntPtr.Zero);
+            }
+
+            remove
+            {
+                if (_handle == IntPtr.Zero)
+                {
+                    return;
+                }
+                EventHandler<TEventArgs> handler = value;
+                var callbacks = _nativeCallbacks.Where(cb => cb.eventHandler == handler);
+                foreach (var cb in callbacks)
+                {
+                    Interop.Evas.evas_object_event_callback_del(_handle, (Interop.Evas.ObjectCallbackType)_type, cb.callback);
+                }
+            }
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!_disposed)
+            {
+                if (disposing)
+                {
+                    // Place holder to dispose managed state (managed objects).
+                }
+                if (_handle != IntPtr.Zero)
+                {
+                    foreach (var cb in _nativeCallbacks)
+                    {
+                        Interop.Evas.evas_object_event_callback_del(_handle, (Interop.Evas.ObjectCallbackType)_type, cb.callback);
+                    }
+                }
+                _nativeCallbacks.Clear();
+                _disposed = true;
+            }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        public void MakeInvalidate()
+        {
+            _sender = null;
+            _handle = IntPtr.Zero;
+        }
+    }
+
+    public class EvasObjectEvent : IInvalidatable
+    {
+        private EvasObjectEvent<EventArgs> _evasObjectEvent;
+        private event EventHandler _handlers;
+        private bool _disposed = false;
+
+        public EvasObjectEvent(EvasObject sender, EvasObjectCallbackType type) : this(sender, sender.Handle, type)
+        {
+        }
+
+        internal EvasObjectEvent(EvasObject sender, IntPtr handle, EvasObjectCallbackType type)
+        {
+            _evasObjectEvent = new EvasObjectEvent<EventArgs>(sender, handle, type, null);
+        }
+
+        ~EvasObjectEvent()
+        {
+            Dispose(false);
+        }
+
+        public event EventHandler On
+        {
+            add
+            {
+                if (_handlers == null)
+                {
+                    _evasObjectEvent.On += SendEvent;
+                }
+                _handlers += value;
+            }
+
+            remove
+            {
+                _handlers -= value;
+                if (_handlers == null)
+                {
+                    _evasObjectEvent.On -= SendEvent;
+                }
+            }
+        }
+
+        private void SendEvent(object sender, EventArgs e)
+        {
+            _handlers?.Invoke(sender, e);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!_disposed)
+            {
+                if (disposing)
+                {
+                    _evasObjectEvent.Dispose();
+                }
+                _disposed = true;
+            }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        public void MakeInvalidate()
+        {
+            _evasObjectEvent.MakeInvalidate();
+        }
+    }
+}
index ce3334a..20566a4 100644 (file)
@@ -42,15 +42,15 @@ namespace ElmSharp
     {
         HashSet<GenGridItem> _children = new HashSet<GenGridItem>();
 
-        Interop.SmartEvent<GenGridItemEventArgs> _selected;
-        Interop.SmartEvent<GenGridItemEventArgs> _unselected;
-        Interop.SmartEvent<GenGridItemEventArgs> _activated;
-        Interop.SmartEvent<GenGridItemEventArgs> _pressed;
-        Interop.SmartEvent<GenGridItemEventArgs> _released;
-        Interop.SmartEvent<GenGridItemEventArgs> _doubleClicked;
-        Interop.SmartEvent<GenGridItemEventArgs> _realized;
-        Interop.SmartEvent<GenGridItemEventArgs> _unrealized;
-        Interop.SmartEvent<GenGridItemEventArgs> _longpressed;
+        SmartEvent<GenGridItemEventArgs> _selected;
+        SmartEvent<GenGridItemEventArgs> _unselected;
+        SmartEvent<GenGridItemEventArgs> _activated;
+        SmartEvent<GenGridItemEventArgs> _pressed;
+        SmartEvent<GenGridItemEventArgs> _released;
+        SmartEvent<GenGridItemEventArgs> _doubleClicked;
+        SmartEvent<GenGridItemEventArgs> _realized;
+        SmartEvent<GenGridItemEventArgs> _unrealized;
+        SmartEvent<GenGridItemEventArgs> _longpressed;
 
         public GenGrid(EvasObject parent) : base(parent)
         {
@@ -239,15 +239,15 @@ namespace ElmSharp
 
         void InitializeSmartEvent()
         {
-            _selected = new Interop.SmartEvent<GenGridItemEventArgs>(this, Handle, "selected", GenGridItemEventArgs.CreateFromSmartEvent);
-            _unselected = new Interop.SmartEvent<GenGridItemEventArgs>(this, Handle, "unselected", GenGridItemEventArgs.CreateFromSmartEvent);
-            _activated = new Interop.SmartEvent<GenGridItemEventArgs>(this, Handle, "activated", GenGridItemEventArgs.CreateFromSmartEvent);
-            _pressed = new Interop.SmartEvent<GenGridItemEventArgs>(this, Handle, "pressed", GenGridItemEventArgs.CreateFromSmartEvent);
-            _released = new Interop.SmartEvent<GenGridItemEventArgs>(this, Handle, "released", GenGridItemEventArgs.CreateFromSmartEvent);
-            _doubleClicked = new Interop.SmartEvent<GenGridItemEventArgs>(this, Handle, "clicked,double", GenGridItemEventArgs.CreateFromSmartEvent);
-            _realized = new Interop.SmartEvent<GenGridItemEventArgs>(this, Handle, "realized", GenGridItemEventArgs.CreateFromSmartEvent);
-            _unrealized = new Interop.SmartEvent<GenGridItemEventArgs>(this, Handle, "unrealized", GenGridItemEventArgs.CreateFromSmartEvent);
-            _longpressed = new Interop.SmartEvent<GenGridItemEventArgs>(this, Handle, "longpressed", GenGridItemEventArgs.CreateFromSmartEvent);
+            _selected = new SmartEvent<GenGridItemEventArgs>(this, "selected", GenGridItemEventArgs.CreateFromSmartEvent);
+            _unselected = new SmartEvent<GenGridItemEventArgs>(this, "unselected", GenGridItemEventArgs.CreateFromSmartEvent);
+            _activated = new SmartEvent<GenGridItemEventArgs>(this,"activated", GenGridItemEventArgs.CreateFromSmartEvent);
+            _pressed = new SmartEvent<GenGridItemEventArgs>(this, "pressed", GenGridItemEventArgs.CreateFromSmartEvent);
+            _released = new SmartEvent<GenGridItemEventArgs>(this, "released", GenGridItemEventArgs.CreateFromSmartEvent);
+            _doubleClicked = new SmartEvent<GenGridItemEventArgs>(this, "clicked,double", GenGridItemEventArgs.CreateFromSmartEvent);
+            _realized = new SmartEvent<GenGridItemEventArgs>(this, "realized", GenGridItemEventArgs.CreateFromSmartEvent);
+            _unrealized = new SmartEvent<GenGridItemEventArgs>(this, "unrealized", GenGridItemEventArgs.CreateFromSmartEvent);
+            _longpressed = new SmartEvent<GenGridItemEventArgs>(this, "longpressed", GenGridItemEventArgs.CreateFromSmartEvent);
 
             _selected.On += (s, e) => { if (e.Item != null) ItemSelected?.Invoke(this, e); };
             _unselected.On += (s, e) => { if (e.Item != null) ItemUnselected?.Invoke(this, e); };
@@ -258,7 +258,6 @@ namespace ElmSharp
             _realized.On += (s, e) => { if (e.Item != null) ItemRealized?.Invoke(this, e); };
             _unrealized.On += (s, e) => { if (e.Item != null) ItemUnrealized?.Invoke(this, e); };
             _longpressed.On += (s, e) => { if (e.Item != null) ItemLongPressed?.Invoke(this, e); };
-
         }
 
         void AddInternal(GenGridItem item)
index 91dec9a..9d542a2 100644 (file)
@@ -58,19 +58,19 @@ namespace ElmSharp
     {
         HashSet<GenListItem> _children = new HashSet<GenListItem>();
 
-        Interop.SmartEvent<GenListItemEventArgs> _selected;
-        Interop.SmartEvent<GenListItemEventArgs> _unselected;
-        Interop.SmartEvent<GenListItemEventArgs> _activated;
-        Interop.SmartEvent<GenListItemEventArgs> _pressed;
-        Interop.SmartEvent<GenListItemEventArgs> _released;
-        Interop.SmartEvent<GenListItemEventArgs> _doubleClicked;
-        Interop.SmartEvent<GenListItemEventArgs> _expanded;
-        Interop.SmartEvent<GenListItemEventArgs> _realized;
-        Interop.SmartEvent<GenListItemEventArgs> _unrealized;
-        Interop.SmartEvent<GenListItemEventArgs> _longpressed;
-        Interop.SmartEvent _scrollAnimationStarted;
-        Interop.SmartEvent _scrollAnimationStopped;
-        Interop.SmartEvent _changed;
+        SmartEvent<GenListItemEventArgs> _selected;
+        SmartEvent<GenListItemEventArgs> _unselected;
+        SmartEvent<GenListItemEventArgs> _activated;
+        SmartEvent<GenListItemEventArgs> _pressed;
+        SmartEvent<GenListItemEventArgs> _released;
+        SmartEvent<GenListItemEventArgs> _doubleClicked;
+        SmartEvent<GenListItemEventArgs> _expanded;
+        SmartEvent<GenListItemEventArgs> _realized;
+        SmartEvent<GenListItemEventArgs> _unrealized;
+        SmartEvent<GenListItemEventArgs> _longpressed;
+        SmartEvent _scrollAnimationStarted;
+        SmartEvent _scrollAnimationStopped;
+        SmartEvent _changed;
 
         public GenList(EvasObject parent) : base(parent)
         {
@@ -241,19 +241,19 @@ namespace ElmSharp
 
         void InitializeSmartEvent()
         {
-            _selected = new Interop.SmartEvent<GenListItemEventArgs>(this, Handle, "selected", GenListItemEventArgs.CreateFromSmartEvent);
-            _unselected = new Interop.SmartEvent<GenListItemEventArgs>(this, Handle, "unselected", GenListItemEventArgs.CreateFromSmartEvent);
-            _activated = new Interop.SmartEvent<GenListItemEventArgs>(this, Handle, "activated", GenListItemEventArgs.CreateFromSmartEvent);
-            _pressed = new Interop.SmartEvent<GenListItemEventArgs>(this, Handle, "pressed", GenListItemEventArgs.CreateFromSmartEvent);
-            _released = new Interop.SmartEvent<GenListItemEventArgs>(this, Handle, "released", GenListItemEventArgs.CreateFromSmartEvent);
-            _doubleClicked = new Interop.SmartEvent<GenListItemEventArgs>(this, Handle, "clicked,double", GenListItemEventArgs.CreateFromSmartEvent);
-            _expanded = new Interop.SmartEvent<GenListItemEventArgs>(this, Handle, "expanded", GenListItemEventArgs.CreateFromSmartEvent);
-            _realized = new Interop.SmartEvent<GenListItemEventArgs>(this, Handle, "realized", GenListItemEventArgs.CreateFromSmartEvent);
-            _unrealized = new Interop.SmartEvent<GenListItemEventArgs>(this, Handle, "unrealized", GenListItemEventArgs.CreateFromSmartEvent);
-            _longpressed = new Interop.SmartEvent<GenListItemEventArgs>(this, Handle, "longpressed", GenListItemEventArgs.CreateFromSmartEvent);
-            _scrollAnimationStarted = new Interop.SmartEvent(this, Handle, "scroll,anim,start");
-            _scrollAnimationStopped = new Interop.SmartEvent(this, Handle, "scroll,anim,stop");
-            _changed = new Interop.SmartEvent(this, Handle, "changed");
+            _selected = new SmartEvent<GenListItemEventArgs>(this, "selected", GenListItemEventArgs.CreateFromSmartEvent);
+            _unselected = new SmartEvent<GenListItemEventArgs>(this, "unselected", GenListItemEventArgs.CreateFromSmartEvent);
+            _activated = new SmartEvent<GenListItemEventArgs>(this, "activated", GenListItemEventArgs.CreateFromSmartEvent);
+            _pressed = new SmartEvent<GenListItemEventArgs>(this, "pressed", GenListItemEventArgs.CreateFromSmartEvent);
+            _released = new SmartEvent<GenListItemEventArgs>(this, "released", GenListItemEventArgs.CreateFromSmartEvent);
+            _doubleClicked = new SmartEvent<GenListItemEventArgs>(this, "clicked,double", GenListItemEventArgs.CreateFromSmartEvent);
+            _expanded = new SmartEvent<GenListItemEventArgs>(this, "expanded", GenListItemEventArgs.CreateFromSmartEvent);
+            _realized = new SmartEvent<GenListItemEventArgs>(this, "realized", GenListItemEventArgs.CreateFromSmartEvent);
+            _unrealized = new SmartEvent<GenListItemEventArgs>(this, "unrealized", GenListItemEventArgs.CreateFromSmartEvent);
+            _longpressed = new SmartEvent<GenListItemEventArgs>(this, "longpressed", GenListItemEventArgs.CreateFromSmartEvent);
+            _scrollAnimationStarted = new SmartEvent(this, "scroll,anim,start");
+            _scrollAnimationStopped = new SmartEvent(this, "scroll,anim,stop");
+            _changed = new SmartEvent(this, "changed");
 
             _selected.On += (s, e) => { if (e.Item != null) ItemSelected?.Invoke(this, e); };
             _unselected.On += (s, e) => { if (e.Item != null) ItemUnselected?.Invoke(this, e); };
old mode 100755 (executable)
new mode 100644 (file)
index e9b59fd..9268c1b
@@ -25,11 +25,11 @@ namespace ElmSharp
     {
         bool _canScaleUp = true;
         bool _canScaleDown = true;
-        Interop.SmartEvent _clicked;
+        SmartEvent _clicked;
 
         public Image(EvasObject parent) : base(parent)
         {
-            _clicked = new Interop.SmartEvent(this, Handle, "clicked");
+            _clicked = new SmartEvent(this, "clicked");
             _clicked.On += (s, e) => Clicked?.Invoke(this, EventArgs.Empty);
         }
 
@@ -307,7 +307,7 @@ namespace ElmSharp
                 }
             });
 
-            Interop.SmartEvent loadReady = new Interop.SmartEvent(this, Handle, "load,ready");
+            SmartEvent loadReady = new SmartEvent(this, Handle, "load,ready");
             loadReady.On += (s, e) =>
             {
                 loadReady.Dispose();
@@ -318,7 +318,7 @@ namespace ElmSharp
                 }
             };
 
-            Interop.SmartEvent loadError = new Interop.SmartEvent(this, Handle, "load,error");
+            SmartEvent loadError = new SmartEvent(this, Handle, "load,error");
             loadError.On += (s, e) =>
             {
                 loadError.Dispose();
@@ -364,7 +364,7 @@ namespace ElmSharp
                 }
             });
 
-            Interop.SmartEvent loadReady = new Interop.SmartEvent(this, Handle, "load,ready");
+            SmartEvent loadReady = new SmartEvent(this, Handle, "load,ready");
             loadReady.On += (s, e) =>
             {
                 loadReady.Dispose();
@@ -375,7 +375,7 @@ namespace ElmSharp
                 }
             };
 
-            Interop.SmartEvent loadError = new Interop.SmartEvent(this, Handle, "load,error");
+            SmartEvent loadError = new SmartEvent(this, Handle, "load,error");
             loadError.On += (s, e) =>
             {
                 loadError.Dispose();
index 7316816..4ed1381 100644 (file)
@@ -22,11 +22,11 @@ namespace ElmSharp
     public class Index : Layout
     {
         HashSet<IndexItem> _children = new HashSet<IndexItem>();
-        Interop.SmartEvent _delayedChanged;
+        SmartEvent _delayedChanged;
 
         public Index(EvasObject parent) : base(parent)
         {
-            _delayedChanged = new Interop.SmartEvent(this, Handle, "delay,changed");
+            _delayedChanged = new SmartEvent(this, "delay,changed");
             _delayedChanged.On += _delayedChanged_On;
         }
 
index 0c62c96..e05eb24 100644 (file)
@@ -20,11 +20,11 @@ namespace ElmSharp
 {
     public class Label : Layout
     {
-        Interop.SmartEvent _slideCompleted;
+        SmartEvent _slideCompleted;
 
         public Label(EvasObject parent) : base(parent)
         {
-            _slideCompleted = new Interop.SmartEvent(this, Handle, "slide,end");
+            _slideCompleted = new SmartEvent(this, "slide,end");
             _slideCompleted.On += (s, e) =>
             {
                 SlideCompleted?.Invoke(this, EventArgs.Empty);
index e794f51..c1678d9 100644 (file)
@@ -20,19 +20,19 @@ namespace ElmSharp
 {
     public class Layout : Widget
     {
-        Interop.SmartEvent _languageChanged;
-        Interop.SmartEvent _themeChanged;
+        SmartEvent _languageChanged;
+        SmartEvent _themeChanged;
 
         IntPtr _edjeHandle;
 
         public Layout(EvasObject parent) : base(parent)
         {
-            _languageChanged = new Interop.SmartEvent(this, Handle, "language,changed");
+            _languageChanged = new SmartEvent(this, "language,changed");
             _languageChanged.On += (s, e) => {
                 LanguageChanged?.Invoke(this, EventArgs.Empty);
             };
 
-            _themeChanged = new Interop.SmartEvent(this, Handle, "theme,changed");
+            _themeChanged = new SmartEvent(this, "theme,changed");
             _themeChanged.On += (s, e) =>
             {
                 ThemeChanged?.Invoke(this, EventArgs.Empty);
index 70a7581..b79d589 100644 (file)
@@ -40,19 +40,19 @@ namespace ElmSharp
     public class List : Layout
     {
         HashSet<ListItem> _children = new HashSet<ListItem>();
-        Interop.SmartEvent<ListItemEventArgs> _selected;
-        Interop.SmartEvent<ListItemEventArgs> _unselected;
-        Interop.SmartEvent<ListItemEventArgs> _doubleClicked;
-        Interop.SmartEvent<ListItemEventArgs> _longpressed;
-        Interop.SmartEvent<ListItemEventArgs> _activated;
+        SmartEvent<ListItemEventArgs> _selected;
+        SmartEvent<ListItemEventArgs> _unselected;
+        SmartEvent<ListItemEventArgs> _doubleClicked;
+        SmartEvent<ListItemEventArgs> _longpressed;
+        SmartEvent<ListItemEventArgs> _activated;
 
         public List(EvasObject parent) : base(parent)
         {
-            _selected = new Interop.SmartEvent<ListItemEventArgs>(this, Handle, "selected", ListItemEventArgs.CreateFromSmartEvent);
-            _unselected = new Interop.SmartEvent<ListItemEventArgs>(this, Handle, "unselected", ListItemEventArgs.CreateFromSmartEvent);
-            _doubleClicked = new Interop.SmartEvent<ListItemEventArgs>(this, Handle, "clicked,double", ListItemEventArgs.CreateFromSmartEvent);
-            _longpressed = new Interop.SmartEvent<ListItemEventArgs>(this, Handle, "longpressed", ListItemEventArgs.CreateFromSmartEvent);
-            _activated = new Interop.SmartEvent<ListItemEventArgs>(this, Handle, "activated", ListItemEventArgs.CreateFromSmartEvent);
+            _selected = new SmartEvent<ListItemEventArgs>(this, "selected", ListItemEventArgs.CreateFromSmartEvent);
+            _unselected = new SmartEvent<ListItemEventArgs>(this, "unselected", ListItemEventArgs.CreateFromSmartEvent);
+            _doubleClicked = new SmartEvent<ListItemEventArgs>(this, "clicked,double", ListItemEventArgs.CreateFromSmartEvent);
+            _longpressed = new SmartEvent<ListItemEventArgs>(this, "longpressed", ListItemEventArgs.CreateFromSmartEvent);
+            _activated = new SmartEvent<ListItemEventArgs>(this, "activated", ListItemEventArgs.CreateFromSmartEvent);
             _selected.On += (s, e) => { ItemSelected?.Invoke(this, e); };
             _unselected.On += (s, e) => { ItemUnselected?.Invoke(this, e); };
             _doubleClicked.On += (s, e) => { ItemDoubleClicked?.Invoke(this, e); };
index f24f61e..c657ff0 100644 (file)
@@ -25,11 +25,11 @@ namespace ElmSharp
     }
     public class Naviframe : Widget
     {
-        Interop.SmartEvent _transitionFinished;
+        SmartEvent _transitionFinished;
         readonly List<NaviItem> _itemStack = new List<NaviItem>();
         public Naviframe(EvasObject parent) : base(parent)
         {
-            _transitionFinished = new Interop.SmartEvent(this, Handle, "transition,finished");
+            _transitionFinished = new SmartEvent(this, "transition,finished");
             _transitionFinished.On += (s, e) => AnimationFinished?.Invoke(this, EventArgs.Empty);
         }
 
index dcb720c..20fd61f 100644 (file)
@@ -40,10 +40,10 @@ namespace ElmSharp
 
     public class Panel : Layout
     {
-        Interop.SmartEvent _toggled;
+        SmartEvent _toggled;
         public Panel(EvasObject parent) : base(parent)
         {
-            _toggled = new Interop.SmartEvent(this, Handle, "toggled");
+            _toggled = new SmartEvent(this, "toggled");
             _toggled.On += (s, e) => Toggled?.Invoke(this, EventArgs.Empty);
         }
 
index 981849c..6a80beb 100644 (file)
@@ -20,12 +20,12 @@ namespace ElmSharp
 {
     public class Panes : Layout
     {
-        Interop.SmartEvent _press;
-        Interop.SmartEvent _unpressed;
+        SmartEvent _press;
+        SmartEvent _unpressed;
         public Panes(EvasObject parent) : base(parent)
         {
-            _press = new Interop.SmartEvent(this, Handle, "press");
-            _unpressed = new Interop.SmartEvent(this, Handle, "unpressed");
+            _press = new SmartEvent(this, "press");
+            _unpressed = new SmartEvent(this, "unpressed");
 
             _press.On += (s, e) => Pressed?.Invoke(this, e);
             _unpressed.On += (s, e) => Unpressed?.Invoke(this, e);
index e8a2df8..f9c9305 100644 (file)
@@ -35,37 +35,36 @@ namespace ElmSharp
     public class Popup : Layout
     {
         HashSet<PopupItem> _children = new HashSet<PopupItem>();
-        Interop.SmartEvent _dismissed;
-        Interop.SmartEvent _blockClicked;
-        Interop.SmartEvent _timeout;
-        Interop.SmartEvent _showFinished;
+        SmartEvent _dismissed;
+        SmartEvent _blockClicked;
+        SmartEvent _timeout;
+        SmartEvent _showFinished;
 
         public Popup(EvasObject parent) : base(parent)
         {
-            _dismissed = new Interop.SmartEvent(this, Handle, "dismissed");
+            _dismissed = new SmartEvent(this, "dismissed");
             _dismissed.On += (sender, e) =>
             {
                 Dismissed?.Invoke(this, EventArgs.Empty);
             };
 
-            _blockClicked = new Interop.SmartEvent(this, Handle, "block,clicked");
+            _blockClicked = new SmartEvent(this, "block,clicked");
             _blockClicked.On += (sender, e) =>
             {
                 OutsideClicked?.Invoke(this, EventArgs.Empty);
             };
 
-            _timeout = new Interop.SmartEvent(this, Handle, "timeout");
+            _timeout = new SmartEvent(this, "timeout");
             _timeout.On += (sender, e) =>
             {
                 TimedOut?.Invoke(this, EventArgs.Empty);
             };
 
-            _showFinished = new Interop.SmartEvent(this, Handle, "show,finished");
+            _showFinished = new SmartEvent(this, "show,finished");
             _showFinished.On += (sender, e) =>
             {
                 ShowAnimationFinished?.Invoke(this, EventArgs.Empty);
             };
-
         }
 
         public event EventHandler Dismissed;
index 72e2e99..de66329 100644 (file)
@@ -20,11 +20,11 @@ namespace ElmSharp
 {
     public class ProgressBar : Layout
     {
-        Interop.SmartEvent _changed;
+        SmartEvent _changed;
 
         public ProgressBar(EvasObject parent) : base(parent)
         {
-            _changed = new Interop.SmartEvent(this, Handle, "changed");
+            _changed = new SmartEvent(this, "changed");
             _changed.On += (s, e) =>
             {
                 ValueChanged?.Invoke(this, EventArgs.Empty);
index 8e122f7..20c9100 100644 (file)
@@ -20,11 +20,11 @@ namespace ElmSharp
 {
     public class Radio : Layout
     {
-        Interop.SmartEvent _changed;
+        SmartEvent _changed;
 
         public Radio(EvasObject parent) : base(parent)
         {
-            _changed = new Interop.SmartEvent(this, Handle, "changed");
+            _changed = new SmartEvent(this, "changed");
             _changed.On += (s, e) => ValueChanged?.Invoke(this, EventArgs.Empty);
         }
 
index ccc3fb4..f7404f8 100644 (file)
@@ -34,17 +34,17 @@ namespace ElmSharp
 
     public class Scroller : Layout
     {
-        Interop.SmartEvent _scroll;
-        Interop.SmartEvent _dragStart;
-        Interop.SmartEvent _dragStop;
-        Interop.SmartEvent _scrollpage;
+        SmartEvent _scroll;
+        SmartEvent _dragStart;
+        SmartEvent _dragStop;
+        SmartEvent _scrollpage;
 
         public Scroller(EvasObject parent) : base(parent)
         {
-            _scroll = new Interop.SmartEvent(this, Handle, "scroll");
-            _dragStart = new Interop.SmartEvent(this, Handle, "scroll,drag,start");
-            _dragStop = new Interop.SmartEvent(this, Handle, "scroll,drag,stop");
-            _scrollpage = new Interop.SmartEvent(this, Handle, "scroll,page,changed");
+            _scroll = new SmartEvent(this, "scroll");
+            _dragStart = new SmartEvent(this, "scroll,drag,start");
+            _dragStop = new SmartEvent(this, "scroll,drag,stop");
+            _scrollpage = new SmartEvent(this, "scroll,page,changed");
         }
 
         public event EventHandler Scrolled
index 9ba5df2..adf65b2 100644 (file)
@@ -23,23 +23,23 @@ namespace ElmSharp
         double _minimum = 0.0;
         double _maximum = 1.0;
 
-        Interop.SmartEvent _changed;
-        Interop.SmartEvent _delayedChanged;
-        Interop.SmartEvent _dragStarted;
-        Interop.SmartEvent _dragStopped;
+        SmartEvent _changed;
+        SmartEvent _delayedChanged;
+        SmartEvent _dragStarted;
+        SmartEvent _dragStopped;
 
         public Slider(EvasObject parent) : base(parent)
         {
-            _changed = new Interop.SmartEvent(this, Handle, "changed");
+            _changed = new SmartEvent(this, "changed");
             _changed.On += (s, e) => ValueChanged?.Invoke(this, EventArgs.Empty);
 
-            _delayedChanged = new Interop.SmartEvent(this, Handle, "delay,changed");
+            _delayedChanged = new SmartEvent(this, "delay,changed");
             _delayedChanged.On += (s, e) => DelayedValueChanged?.Invoke(this, EventArgs.Empty);
 
-            _dragStarted = new Interop.SmartEvent(this, Handle, "slider,drag,start");
+            _dragStarted = new SmartEvent(this, "slider,drag,start");
             _dragStarted.On += (s, e) => DragStarted?.Invoke(this, EventArgs.Empty);
 
-            _dragStopped = new Interop.SmartEvent(this, Handle, "slider,drag,stop");
+            _dragStopped = new SmartEvent(this, "slider,drag,stop");
             _dragStopped.On += (s, e) => DragStopped?.Invoke(this, EventArgs.Empty);
         }
 
similarity index 64%
rename from ElmSharp/Interop/Interop.SmartEvent.cs
rename to ElmSharp/ElmSharp/SmartEvent.cs
index dd0e110..2d06143 100644 (file)
@@ -18,26 +18,32 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 
-internal static partial class Interop
+namespace ElmSharp
 {
-    internal class SmartEvent<TEventArgs> : IDisposable where TEventArgs : EventArgs
+    public class SmartEvent<TEventArgs> : IInvalidatable where TEventArgs : EventArgs
     {
         public delegate TEventArgs SmartEventInfoParser(IntPtr data, IntPtr obj, IntPtr info);
 
-        private readonly object _sender;
+        private EvasObject _sender;
         private readonly string _eventName;
-        private readonly IntPtr _handle;
+        private IntPtr _handle;
         private readonly SmartEventInfoParser _parser;
         private readonly List<NativeCallback> _nativeCallbacks = new List<NativeCallback>();
 
-        public SmartEvent(object sender, IntPtr handle, string eventName, SmartEventInfoParser parser)
+        public SmartEvent(EvasObject sender, string eventName, SmartEventInfoParser parser) : this(sender, sender.Handle, eventName, parser)
+        {
+        }
+
+        internal SmartEvent(EvasObject sender, IntPtr handle, string eventName, SmartEventInfoParser parser)
         {
             _sender = sender;
             _eventName = eventName;
             _handle = handle;
             _parser = parser;
+            sender.AddToEventLifeTracker(this);
         }
-        public SmartEvent(object sender, IntPtr handle, string eventName) : this(sender, handle, eventName, null)
+
+        public SmartEvent(EvasObject sender, string eventName) : this(sender, eventName, null)
         {
         }
 
@@ -56,6 +62,10 @@ internal static partial class Interop
         {
             add
             {
+                if (_handle == IntPtr.Zero)
+                {
+                    return;
+                }
                 EventHandler<TEventArgs> handler = value;
                 var cb = new Interop.Evas.SmartCallback((d, o, e) =>
                 {
@@ -69,6 +79,10 @@ internal static partial class Interop
 
             remove
             {
+                if (_handle == IntPtr.Zero)
+                {
+                    return;
+                }
                 EventHandler<TEventArgs> handler = value;
                 var callbacks = _nativeCallbacks.Where(cb => cb.eventHandler == handler);
                 foreach (var cb in callbacks)
@@ -78,87 +92,78 @@ internal static partial class Interop
             }
         }
 
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        public void MakeInvalidate()
+        {
+            _sender = null;
+            _handle = IntPtr.Zero;
+        }
+
         protected virtual void Dispose(bool disposing)
         {
             if (disposing)
             {
                 // Place holder to dispose managed state (managed objects).
             }
-            foreach (var cb in _nativeCallbacks)
+            if (_handle != IntPtr.Zero)
             {
-                Evas.evas_object_smart_callback_del(_handle, _eventName, cb.callback);
+                foreach (var cb in _nativeCallbacks)
+                {
+                    Interop.Evas.evas_object_smart_callback_del(_handle, _eventName, cb.callback);
+                }
             }
             _nativeCallbacks.Clear();
         }
-
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
     }
 
-    internal class SmartEvent : IDisposable
+    public class SmartEvent : IInvalidatable
     {
-        private readonly object _sender;
-        private readonly string _eventName;
-        private readonly IntPtr _handle;
-        private readonly List<NativeCallback> _nativeCallbacks = new List<NativeCallback>();
+        private SmartEvent<EventArgs> _smartEvent;
+        private event EventHandler _handlers;
 
-        public SmartEvent(object sender, IntPtr handle, string eventName)
+        public SmartEvent(EvasObject sender, string eventName) : this(sender, sender.Handle, eventName)
         {
-            _sender = sender;
-            _eventName = eventName;
-            _handle = handle;
         }
 
-        ~SmartEvent()
+        internal SmartEvent(EvasObject sender, IntPtr handle, string eventName)
         {
-            Dispose(false);
+            _smartEvent = new SmartEvent<EventArgs>(sender, handle, eventName, null);
         }
 
-        private struct NativeCallback
+        ~SmartEvent()
         {
-            public Interop.Evas.SmartCallback callback;
-            public EventHandler eventHandler;
+            Dispose(false);
         }
 
         public event EventHandler On
         {
             add
             {
-                EventHandler handler = value;
-                var cb = new Interop.Evas.SmartCallback((d, o, e) =>
+                if (_handlers == null)
                 {
-                    handler(_sender, EventArgs.Empty);
-                });
-                _nativeCallbacks.Add(new NativeCallback { callback = cb, eventHandler = handler });
-                int i = _nativeCallbacks.Count - 1;
-                Interop.Evas.evas_object_smart_callback_add(_handle, _eventName, _nativeCallbacks[i].callback, IntPtr.Zero);
+                    _smartEvent.On += SendEvent;
+                }
+                _handlers += value;
             }
 
             remove
             {
-                EventHandler handler = value;
-                var callbacks = _nativeCallbacks.Where(cb => cb.eventHandler == handler);
-                foreach (var cb in callbacks)
+                _handlers -= value;
+                if (_handlers == null)
                 {
-                    Interop.Evas.evas_object_smart_callback_del(_handle, _eventName, cb.callback);
+                    _smartEvent.On -= SendEvent;
                 }
             }
         }
 
-        protected virtual void Dispose(bool disposing)
+        private void SendEvent(object sender, EventArgs e)
         {
-            if (disposing)
-            {
-                // Place holder to dispose managed state (managed objects).
-            }
-            foreach (var cb in _nativeCallbacks)
-            {
-                Evas.evas_object_smart_callback_del(_handle, _eventName, cb.callback);
-            }
-            _nativeCallbacks.Clear();
+            _handlers?.Invoke(sender, e);
         }
 
         public void Dispose()
@@ -166,5 +171,19 @@ internal static partial class Interop
             Dispose(true);
             GC.SuppressFinalize(this);
         }
+
+        public void MakeInvalidate()
+        {
+            _smartEvent.MakeInvalidate();
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                // Place holder to dispose managed state (managed objects).
+                _smartEvent.Dispose();
+            }
+        }
     }
 }
index 8572311..e466e7a 100644 (file)
@@ -23,15 +23,15 @@ namespace ElmSharp
         double _minimum = 0.0;
         double _maximum = 100.0;
 
-        Interop.SmartEvent _changed;
-        Interop.SmartEvent _delayedChanged;
+        SmartEvent _changed;
+        SmartEvent _delayedChanged;
 
         public Spinner(EvasObject parent) : base(parent)
         {
-            _changed = new Interop.SmartEvent(this, Handle, "changed");
+            _changed = new SmartEvent(this, "changed");
             _changed.On += (s, e) => ValueChanged?.Invoke(this, EventArgs.Empty);
 
-            _delayedChanged = new Interop.SmartEvent(this, Handle, "delay,changed");
+            _delayedChanged = new SmartEvent(this, "delay,changed");
             _delayedChanged.On += (s, e) => DelayedValueChanged?.Invoke(this, EventArgs.Empty);
         }
 
index 6c18c3a..7393328 100644 (file)
@@ -48,12 +48,12 @@ namespace ElmSharp
 
     public class Toolbar : Widget
     {
-        Interop.SmartEvent<ToolbarItemEventArgs> _clicked;
-        Interop.SmartEvent<ToolbarItemEventArgs> _selected;
-        Interop.SmartEvent<ToolbarItemEventArgs> _longpressed;
+        SmartEvent<ToolbarItemEventArgs> _clicked;
+        SmartEvent<ToolbarItemEventArgs> _selected;
+        SmartEvent<ToolbarItemEventArgs> _longpressed;
         public Toolbar(EvasObject parent) : base(parent)
         {
-            _selected = new Interop.SmartEvent<ToolbarItemEventArgs>(this, Handle, "selected", ToolbarItemEventArgs.CreateFromSmartEvent);
+            _selected = new SmartEvent<ToolbarItemEventArgs>(this, "selected", ToolbarItemEventArgs.CreateFromSmartEvent);
             _selected.On += (s, e) =>
             {
                 if (e.Item != null)
@@ -62,12 +62,12 @@ namespace ElmSharp
                     e.Item.SendSelected();
                 }
             };
-            _longpressed = new Interop.SmartEvent<ToolbarItemEventArgs>(this, Handle, "longpressed", ToolbarItemEventArgs.CreateFromSmartEvent);
+            _longpressed = new SmartEvent<ToolbarItemEventArgs>(this, "longpressed", ToolbarItemEventArgs.CreateFromSmartEvent);
             _longpressed.On += (s, e) =>
             {
                 e.Item?.SendLongPressed();
             };
-            _clicked = new Interop.SmartEvent<ToolbarItemEventArgs>(this, Handle, "clicked", ToolbarItemEventArgs.CreateFromSmartEvent);
+            _clicked = new SmartEvent<ToolbarItemEventArgs>(this, "clicked", ToolbarItemEventArgs.CreateFromSmartEvent);
             _clicked.On += (s, e) =>
             {
                 e.Item?.SendClicked();
index 2569615..fabf249 100644 (file)
@@ -23,8 +23,8 @@ namespace ElmSharp
     {
         Dictionary<string, EvasObject> _partContents = new Dictionary<string, EvasObject>();
 
-        Interop.SmartEvent _focused;
-        Interop.SmartEvent _unfocused;
+        SmartEvent _focused;
+        SmartEvent _unfocused;
 
         protected Widget()
         {
@@ -32,12 +32,11 @@ namespace ElmSharp
 
         protected Widget(EvasObject parent) : base(parent)
         {
-            _focused = new Interop.SmartEvent(this, Handle, "focused");
+            _focused = new SmartEvent(this, "focused");
             _focused.On += (s, e) => Focused?.Invoke(this, EventArgs.Empty);
 
-            _unfocused = new Interop.SmartEvent(this, Handle, "unfocused");
+            _unfocused = new SmartEvent(this, "unfocused");
             _unfocused.On += (s, e) => Unfocused?.Invoke(this, EventArgs.Empty);
-
         }
 
         public event EventHandler Focused;
index ea704ea..1b4d54d 100644 (file)
@@ -51,8 +51,8 @@ namespace ElmSharp
 
     public class Window : Widget
     {
-        Interop.SmartEvent _deleteRequest;
-        Interop.SmartEvent _rotationChanged;
+        SmartEvent _deleteRequest;
+        SmartEvent _rotationChanged;
         HashSet<EvasObject> _referenceHolder = new HashSet<EvasObject>();
 
         public Window(string name) : this(null, name)
@@ -65,8 +65,8 @@ namespace ElmSharp
             Realize(parent);
             Interop.Elementary.elm_win_indicator_mode_set(Handle, 2 /* ELM_WIN_INDICATOR_SHOW */);
 
-            _deleteRequest = new Interop.SmartEvent(this, Handle, "delete,request");
-            _rotationChanged = new Interop.SmartEvent(this, Handle, "wm,rotation,changed");
+            _deleteRequest = new SmartEvent(this, "delete,request");
+            _rotationChanged = new SmartEvent(this, "wm,rotation,changed");
             _deleteRequest.On += (s, e) => CloseRequested?.Invoke(this, EventArgs.Empty);
             _rotationChanged.On += (s, e) => RotationChanged?.Invoke(this, EventArgs.Empty);
         }
diff --git a/ElmSharp/Interop/Interop.EvasObjectEvent.cs b/ElmSharp/Interop/Interop.EvasObjectEvent.cs
deleted file mode 100644 (file)
index e5a8408..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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.Linq;
-
-internal static partial class Interop
-{
-    internal class EvasObjectEvent<TEventArgs> : IDisposable where TEventArgs : EventArgs
-    {
-        public delegate TEventArgs SmartEventInfoParser(IntPtr data, IntPtr obj, IntPtr info);
-
-        private bool _disposed = false;
-        private readonly object _sender;
-        private readonly IntPtr _handle;
-        private readonly Evas.ObjectCallbackType _type;
-        private readonly SmartEventInfoParser _parser;
-        private readonly List<NativeCallback> _nativeCallbacks = new List<NativeCallback>();
-
-        public EvasObjectEvent(object sender, IntPtr handle, Evas.ObjectCallbackType type, SmartEventInfoParser parser)
-        {
-            _sender = sender;
-            _handle = handle;
-            _type = type;
-            _parser = parser;
-        }
-
-        public EvasObjectEvent(object sender, IntPtr handle, Evas.ObjectCallbackType type) : this(sender, handle, type, null)
-        {
-        }
-
-        ~EvasObjectEvent()
-        {
-            Dispose(false);
-        }
-
-        private struct NativeCallback
-        {
-            public Evas.EventCallback callback;
-            public EventHandler<TEventArgs> eventHandler;
-        }
-
-        public event EventHandler<TEventArgs> On
-        {
-            add
-            {
-                EventHandler<TEventArgs> handler = value;
-                var cb = new Evas.EventCallback((data, evas, obj, info) =>
-                {
-                    TEventArgs ea = _parser == null ? (TEventArgs)EventArgs.Empty : _parser(data, obj, info);
-                    handler(_sender, ea);
-                });
-                _nativeCallbacks.Add(new NativeCallback { callback = cb, eventHandler = handler });
-                int i = _nativeCallbacks.Count - 1;
-                Evas.evas_object_event_callback_add(_handle, _type, _nativeCallbacks[i].callback, IntPtr.Zero);
-            }
-
-            remove
-            {
-                EventHandler<TEventArgs> handler = value;
-                var callbacks = _nativeCallbacks.Where(cb => cb.eventHandler == handler);
-                foreach (var cb in callbacks)
-                {
-                    Evas.evas_object_event_callback_del(_handle, _type, cb.callback);
-                }
-            }
-        }
-
-        protected virtual void Dispose(bool disposing)
-        {
-            if (!_disposed)
-            {
-                if (disposing)
-                {
-                    // Place holder to dispose managed state (managed objects).
-                }
-                foreach (var cb in _nativeCallbacks)
-                {
-                    Evas.evas_object_event_callback_del(_handle, _type, cb.callback);
-                }
-                _nativeCallbacks.Clear();
-                _disposed = true;
-            }
-        }
-
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-    }
-
-    internal class EvasObjectEvent : IDisposable
-    {
-        private bool _disposed = false;
-        private readonly object _sender;
-        private readonly IntPtr _handle;
-        private readonly Evas.ObjectCallbackType _type;
-        private readonly List<NativeCallback> _nativeCallbacks = new List<NativeCallback>();
-
-        public EvasObjectEvent(object sender, IntPtr handle, Evas.ObjectCallbackType type)
-        {
-            _sender = sender;
-            _handle = handle;
-            _type = type;
-        }
-
-        ~EvasObjectEvent()
-        {
-            Dispose(false);
-        }
-
-        private struct NativeCallback
-        {
-            public Evas.EventCallback callback;
-            public EventHandler eventHandler;
-        }
-
-        public event EventHandler On
-        {
-            add
-            {
-                EventHandler handler = value;
-                var cb = new Evas.EventCallback((data, evas, obj, info) =>
-                {
-                    handler(_sender, EventArgs.Empty);
-                });
-                _nativeCallbacks.Add(new NativeCallback { callback = cb, eventHandler = handler });
-                int i = _nativeCallbacks.Count - 1;
-                Evas.evas_object_event_callback_add(_handle, _type, _nativeCallbacks[i].callback, IntPtr.Zero);
-            }
-
-            remove
-            {
-                EventHandler handler = value;
-                var callbacks = _nativeCallbacks.Where(cb => cb.eventHandler == handler);
-                foreach (var cb in callbacks)
-                {
-                    Evas.evas_object_event_callback_del(_handle, _type, cb.callback);
-                }
-            }
-        }
-
-        protected virtual void Dispose(bool disposing)
-        {
-            if (!_disposed)
-            {
-                if (disposing)
-                {
-                    // Place holder to dispose managed state (managed objects).
-                }
-                foreach (var cb in _nativeCallbacks)
-                {
-                    Evas.evas_object_event_callback_del(_handle, _type, cb.callback);
-                }
-                _nativeCallbacks.Clear();
-                _disposed = true;
-            }
-        }
-
-        public void Dispose()
-        {
-            Dispose(true);
-            GC.SuppressFinalize(this);
-        }
-    }
-}
index 4118192..7b5c7fe 100644 (file)
@@ -8,7 +8,7 @@
 
 Name:       elm-sharp
 Summary:    C# Binding for Elementary
-Version:    1.0.12
+Version:    1.0.13
 Release:    1
 Group:      Development/Libraries
 License:    Apache-2.0