From ddc9c73cecc33b0b464b5cdb4b8a3ec56ff47217 Mon Sep 17 00:00:00 2001 From: Seungkeun Lee Date: Wed, 9 Nov 2016 13:38:48 +0900 Subject: [PATCH] Refactoring EvasObjectEvent/SmartEvent - 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 --- ElmSharp.Test/TestRunner.cs | 2 + ElmSharp/ElmSharp.Net45.csproj | 6 +- ElmSharp/ElmSharp.csproj | 4 +- ElmSharp/ElmSharp/Button.cs | 16 +- ElmSharp/ElmSharp/Calendar.cs | 8 +- ElmSharp/ElmSharp/Check.cs | 4 +- ElmSharp/ElmSharp/ColorSelector.cs | 4 +- ElmSharp/ElmSharp/ContextPopup.cs | 4 +- ElmSharp/ElmSharp/DateTimeSelector.cs | 4 +- ElmSharp/ElmSharp/Entry.cs | 16 +- ElmSharp/ElmSharp/EvasObject.cs | 90 ++++---- ElmSharp/ElmSharp/EvasObjectEvent.cs | 242 +++++++++++++++++++++ ElmSharp/ElmSharp/GenGrid.cs | 37 ++-- ElmSharp/ElmSharp/GenList.cs | 52 ++--- ElmSharp/ElmSharp/Image.cs | 12 +- ElmSharp/ElmSharp/Index.cs | 4 +- ElmSharp/ElmSharp/Label.cs | 4 +- ElmSharp/ElmSharp/Layout.cs | 8 +- ElmSharp/ElmSharp/List.cs | 20 +- ElmSharp/ElmSharp/Naviframe.cs | 4 +- ElmSharp/ElmSharp/Panel.cs | 4 +- ElmSharp/ElmSharp/Panes.cs | 8 +- ElmSharp/ElmSharp/Popup.cs | 17 +- ElmSharp/ElmSharp/ProgressBar.cs | 4 +- ElmSharp/ElmSharp/Radio.cs | 4 +- ElmSharp/ElmSharp/Scroller.cs | 16 +- ElmSharp/ElmSharp/Slider.cs | 16 +- .../SmartEvent.cs} | 117 +++++----- ElmSharp/ElmSharp/Spinner.cs | 8 +- ElmSharp/ElmSharp/Toolbar.cs | 12 +- ElmSharp/ElmSharp/Widget.cs | 9 +- ElmSharp/ElmSharp/Window.cs | 8 +- ElmSharp/Interop/Interop.EvasObjectEvent.cs | 181 --------------- packaging/elm-sharp.spec | 2 +- 34 files changed, 521 insertions(+), 426 deletions(-) create mode 100644 ElmSharp/ElmSharp/EvasObjectEvent.cs mode change 100755 => 100644 ElmSharp/ElmSharp/Image.cs rename ElmSharp/{Interop/Interop.SmartEvent.cs => ElmSharp/SmartEvent.cs} (64%) delete mode 100644 ElmSharp/Interop/Interop.EvasObjectEvent.cs diff --git a/ElmSharp.Test/TestRunner.cs b/ElmSharp.Test/TestRunner.cs index 9bee255..0d7afa2 100644 --- a/ElmSharp.Test/TestRunner.cs +++ b/ElmSharp.Test/TestRunner.cs @@ -106,6 +106,8 @@ namespace ElmSharp.Test { window.Hide(); window.Unrealize(); + GC.Collect(); + GC.WaitForPendingFinalizers(); } }; } diff --git a/ElmSharp/ElmSharp.Net45.csproj b/ElmSharp/ElmSharp.Net45.csproj index 6bc1650..9d53b09 100644 --- a/ElmSharp/ElmSharp.Net45.csproj +++ b/ElmSharp/ElmSharp.Net45.csproj @@ -73,6 +73,7 @@ + @@ -105,6 +106,7 @@ + @@ -144,10 +146,8 @@ - - @@ -163,4 +163,4 @@ --> - \ No newline at end of file + diff --git a/ElmSharp/ElmSharp.csproj b/ElmSharp/ElmSharp.csproj index df61891..f11e9a8 100644 --- a/ElmSharp/ElmSharp.csproj +++ b/ElmSharp/ElmSharp.csproj @@ -70,6 +70,7 @@ + @@ -102,6 +103,7 @@ + @@ -141,10 +143,8 @@ - - diff --git a/ElmSharp/ElmSharp/Button.cs b/ElmSharp/ElmSharp/Button.cs index 70d2bc3..1d69347 100644 --- a/ElmSharp/ElmSharp/Button.cs +++ b/ElmSharp/ElmSharp/Button.cs @@ -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) => { diff --git a/ElmSharp/ElmSharp/Calendar.cs b/ElmSharp/ElmSharp/Calendar.cs index 0c6876c..cecb080 100644 --- a/ElmSharp/ElmSharp/Calendar.cs +++ b/ElmSharp/ElmSharp/Calendar.cs @@ -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; diff --git a/ElmSharp/ElmSharp/Check.cs b/ElmSharp/ElmSharp/Check.cs index 86ab105..8284503 100644 --- a/ElmSharp/ElmSharp/Check.cs +++ b/ElmSharp/ElmSharp/Check.cs @@ -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)); diff --git a/ElmSharp/ElmSharp/ColorSelector.cs b/ElmSharp/ElmSharp/ColorSelector.cs index 1872eda..1b0d251 100644 --- a/ElmSharp/ElmSharp/ColorSelector.cs +++ b/ElmSharp/ElmSharp/ColorSelector.cs @@ -31,12 +31,12 @@ namespace ElmSharp public class ColorSelector : Layout { - private readonly Interop.SmartEvent _changed; + private readonly SmartEvent _changed; private Color _currentColor; public ColorSelector(EvasObject parent) : base(parent) { - _changed = new Interop.SmartEvent(this, Handle, "changed", (data, obj, info) => + _changed = new SmartEvent(this, "changed", (data, obj, info) => { return new ColorChangedEventArgs(_currentColor, SelectedColor); }); diff --git a/ElmSharp/ElmSharp/ContextPopup.cs b/ElmSharp/ElmSharp/ContextPopup.cs index e3fdbd6..47a336c 100644 --- a/ElmSharp/ElmSharp/ContextPopup.cs +++ b/ElmSharp/ElmSharp/ContextPopup.cs @@ -31,12 +31,12 @@ namespace ElmSharp public class ContextPopup : Layout { HashSet _children = new HashSet(); - 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); diff --git a/ElmSharp/ElmSharp/DateTimeSelector.cs b/ElmSharp/ElmSharp/DateTimeSelector.cs index 6624e1d..fd3012d 100644 --- a/ElmSharp/ElmSharp/DateTimeSelector.cs +++ b/ElmSharp/ElmSharp/DateTimeSelector.cs @@ -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; diff --git a/ElmSharp/ElmSharp/Entry.cs b/ElmSharp/ElmSharp/Entry.cs index 0e4e5a5..a5ef7ca 100644 --- a/ElmSharp/ElmSharp/Entry.cs +++ b/ElmSharp/ElmSharp/Entry.cs @@ -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); } diff --git a/ElmSharp/ElmSharp/EvasObject.cs b/ElmSharp/ElmSharp/EvasObject.cs index d366a64..664afd4 100644 --- a/ElmSharp/ElmSharp/EvasObject.cs +++ b/ElmSharp/ElmSharp/EvasObject.cs @@ -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 _keyup; - Interop.EvasObjectEvent _keydown; - Interop.EvasObjectEvent _moved; - Interop.EvasObjectEvent _resized; - Interop.EvasObjectEvent _renderPost; + EvasObjectEvent _deleted; + EvasObjectEvent _keyup; + EvasObjectEvent _keydown; + EvasObjectEvent _moved; + EvasObjectEvent _resized; + EvasObjectEvent _renderPost; + + readonly HashSet _eventStore = new HashSet(); 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(this, Handle, Interop.Evas.ObjectCallbackType.KeyDown, EvasKeyEventArgs.Create); - _keyup = new Interop.EvasObjectEvent(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(this, EvasObjectCallbackType.KeyDown, EvasKeyEventArgs.Create); + _keyup = new EvasObjectEvent(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 index 0000000..23c0b53 --- /dev/null +++ b/ElmSharp/ElmSharp/EvasObjectEvent.cs @@ -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 : 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 _nativeCallbacks = new List(); + + 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 eventHandler; + } + + public event EventHandler On + { + add + { + if (_handle == IntPtr.Zero) + { + return; + } + EventHandler 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 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 _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(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(); + } + } +} diff --git a/ElmSharp/ElmSharp/GenGrid.cs b/ElmSharp/ElmSharp/GenGrid.cs index ce3334a..20566a4 100644 --- a/ElmSharp/ElmSharp/GenGrid.cs +++ b/ElmSharp/ElmSharp/GenGrid.cs @@ -42,15 +42,15 @@ namespace ElmSharp { HashSet _children = new HashSet(); - Interop.SmartEvent _selected; - Interop.SmartEvent _unselected; - Interop.SmartEvent _activated; - Interop.SmartEvent _pressed; - Interop.SmartEvent _released; - Interop.SmartEvent _doubleClicked; - Interop.SmartEvent _realized; - Interop.SmartEvent _unrealized; - Interop.SmartEvent _longpressed; + SmartEvent _selected; + SmartEvent _unselected; + SmartEvent _activated; + SmartEvent _pressed; + SmartEvent _released; + SmartEvent _doubleClicked; + SmartEvent _realized; + SmartEvent _unrealized; + SmartEvent _longpressed; public GenGrid(EvasObject parent) : base(parent) { @@ -239,15 +239,15 @@ namespace ElmSharp void InitializeSmartEvent() { - _selected = new Interop.SmartEvent(this, Handle, "selected", GenGridItemEventArgs.CreateFromSmartEvent); - _unselected = new Interop.SmartEvent(this, Handle, "unselected", GenGridItemEventArgs.CreateFromSmartEvent); - _activated = new Interop.SmartEvent(this, Handle, "activated", GenGridItemEventArgs.CreateFromSmartEvent); - _pressed = new Interop.SmartEvent(this, Handle, "pressed", GenGridItemEventArgs.CreateFromSmartEvent); - _released = new Interop.SmartEvent(this, Handle, "released", GenGridItemEventArgs.CreateFromSmartEvent); - _doubleClicked = new Interop.SmartEvent(this, Handle, "clicked,double", GenGridItemEventArgs.CreateFromSmartEvent); - _realized = new Interop.SmartEvent(this, Handle, "realized", GenGridItemEventArgs.CreateFromSmartEvent); - _unrealized = new Interop.SmartEvent(this, Handle, "unrealized", GenGridItemEventArgs.CreateFromSmartEvent); - _longpressed = new Interop.SmartEvent(this, Handle, "longpressed", GenGridItemEventArgs.CreateFromSmartEvent); + _selected = new SmartEvent(this, "selected", GenGridItemEventArgs.CreateFromSmartEvent); + _unselected = new SmartEvent(this, "unselected", GenGridItemEventArgs.CreateFromSmartEvent); + _activated = new SmartEvent(this,"activated", GenGridItemEventArgs.CreateFromSmartEvent); + _pressed = new SmartEvent(this, "pressed", GenGridItemEventArgs.CreateFromSmartEvent); + _released = new SmartEvent(this, "released", GenGridItemEventArgs.CreateFromSmartEvent); + _doubleClicked = new SmartEvent(this, "clicked,double", GenGridItemEventArgs.CreateFromSmartEvent); + _realized = new SmartEvent(this, "realized", GenGridItemEventArgs.CreateFromSmartEvent); + _unrealized = new SmartEvent(this, "unrealized", GenGridItemEventArgs.CreateFromSmartEvent); + _longpressed = new SmartEvent(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) diff --git a/ElmSharp/ElmSharp/GenList.cs b/ElmSharp/ElmSharp/GenList.cs index 91dec9a..9d542a2 100644 --- a/ElmSharp/ElmSharp/GenList.cs +++ b/ElmSharp/ElmSharp/GenList.cs @@ -58,19 +58,19 @@ namespace ElmSharp { HashSet _children = new HashSet(); - Interop.SmartEvent _selected; - Interop.SmartEvent _unselected; - Interop.SmartEvent _activated; - Interop.SmartEvent _pressed; - Interop.SmartEvent _released; - Interop.SmartEvent _doubleClicked; - Interop.SmartEvent _expanded; - Interop.SmartEvent _realized; - Interop.SmartEvent _unrealized; - Interop.SmartEvent _longpressed; - Interop.SmartEvent _scrollAnimationStarted; - Interop.SmartEvent _scrollAnimationStopped; - Interop.SmartEvent _changed; + SmartEvent _selected; + SmartEvent _unselected; + SmartEvent _activated; + SmartEvent _pressed; + SmartEvent _released; + SmartEvent _doubleClicked; + SmartEvent _expanded; + SmartEvent _realized; + SmartEvent _unrealized; + SmartEvent _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(this, Handle, "selected", GenListItemEventArgs.CreateFromSmartEvent); - _unselected = new Interop.SmartEvent(this, Handle, "unselected", GenListItemEventArgs.CreateFromSmartEvent); - _activated = new Interop.SmartEvent(this, Handle, "activated", GenListItemEventArgs.CreateFromSmartEvent); - _pressed = new Interop.SmartEvent(this, Handle, "pressed", GenListItemEventArgs.CreateFromSmartEvent); - _released = new Interop.SmartEvent(this, Handle, "released", GenListItemEventArgs.CreateFromSmartEvent); - _doubleClicked = new Interop.SmartEvent(this, Handle, "clicked,double", GenListItemEventArgs.CreateFromSmartEvent); - _expanded = new Interop.SmartEvent(this, Handle, "expanded", GenListItemEventArgs.CreateFromSmartEvent); - _realized = new Interop.SmartEvent(this, Handle, "realized", GenListItemEventArgs.CreateFromSmartEvent); - _unrealized = new Interop.SmartEvent(this, Handle, "unrealized", GenListItemEventArgs.CreateFromSmartEvent); - _longpressed = new Interop.SmartEvent(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(this, "selected", GenListItemEventArgs.CreateFromSmartEvent); + _unselected = new SmartEvent(this, "unselected", GenListItemEventArgs.CreateFromSmartEvent); + _activated = new SmartEvent(this, "activated", GenListItemEventArgs.CreateFromSmartEvent); + _pressed = new SmartEvent(this, "pressed", GenListItemEventArgs.CreateFromSmartEvent); + _released = new SmartEvent(this, "released", GenListItemEventArgs.CreateFromSmartEvent); + _doubleClicked = new SmartEvent(this, "clicked,double", GenListItemEventArgs.CreateFromSmartEvent); + _expanded = new SmartEvent(this, "expanded", GenListItemEventArgs.CreateFromSmartEvent); + _realized = new SmartEvent(this, "realized", GenListItemEventArgs.CreateFromSmartEvent); + _unrealized = new SmartEvent(this, "unrealized", GenListItemEventArgs.CreateFromSmartEvent); + _longpressed = new SmartEvent(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); }; diff --git a/ElmSharp/ElmSharp/Image.cs b/ElmSharp/ElmSharp/Image.cs old mode 100755 new mode 100644 index e9b59fd..9268c1b --- a/ElmSharp/ElmSharp/Image.cs +++ b/ElmSharp/ElmSharp/Image.cs @@ -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(); diff --git a/ElmSharp/ElmSharp/Index.cs b/ElmSharp/ElmSharp/Index.cs index 7316816..4ed1381 100644 --- a/ElmSharp/ElmSharp/Index.cs +++ b/ElmSharp/ElmSharp/Index.cs @@ -22,11 +22,11 @@ namespace ElmSharp public class Index : Layout { HashSet _children = new HashSet(); - 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; } diff --git a/ElmSharp/ElmSharp/Label.cs b/ElmSharp/ElmSharp/Label.cs index 0c62c96..e05eb24 100644 --- a/ElmSharp/ElmSharp/Label.cs +++ b/ElmSharp/ElmSharp/Label.cs @@ -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); diff --git a/ElmSharp/ElmSharp/Layout.cs b/ElmSharp/ElmSharp/Layout.cs index e794f51..c1678d9 100644 --- a/ElmSharp/ElmSharp/Layout.cs +++ b/ElmSharp/ElmSharp/Layout.cs @@ -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); diff --git a/ElmSharp/ElmSharp/List.cs b/ElmSharp/ElmSharp/List.cs index 70a7581..b79d589 100644 --- a/ElmSharp/ElmSharp/List.cs +++ b/ElmSharp/ElmSharp/List.cs @@ -40,19 +40,19 @@ namespace ElmSharp public class List : Layout { HashSet _children = new HashSet(); - Interop.SmartEvent _selected; - Interop.SmartEvent _unselected; - Interop.SmartEvent _doubleClicked; - Interop.SmartEvent _longpressed; - Interop.SmartEvent _activated; + SmartEvent _selected; + SmartEvent _unselected; + SmartEvent _doubleClicked; + SmartEvent _longpressed; + SmartEvent _activated; public List(EvasObject parent) : base(parent) { - _selected = new Interop.SmartEvent(this, Handle, "selected", ListItemEventArgs.CreateFromSmartEvent); - _unselected = new Interop.SmartEvent(this, Handle, "unselected", ListItemEventArgs.CreateFromSmartEvent); - _doubleClicked = new Interop.SmartEvent(this, Handle, "clicked,double", ListItemEventArgs.CreateFromSmartEvent); - _longpressed = new Interop.SmartEvent(this, Handle, "longpressed", ListItemEventArgs.CreateFromSmartEvent); - _activated = new Interop.SmartEvent(this, Handle, "activated", ListItemEventArgs.CreateFromSmartEvent); + _selected = new SmartEvent(this, "selected", ListItemEventArgs.CreateFromSmartEvent); + _unselected = new SmartEvent(this, "unselected", ListItemEventArgs.CreateFromSmartEvent); + _doubleClicked = new SmartEvent(this, "clicked,double", ListItemEventArgs.CreateFromSmartEvent); + _longpressed = new SmartEvent(this, "longpressed", ListItemEventArgs.CreateFromSmartEvent); + _activated = new SmartEvent(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); }; diff --git a/ElmSharp/ElmSharp/Naviframe.cs b/ElmSharp/ElmSharp/Naviframe.cs index f24f61e..c657ff0 100644 --- a/ElmSharp/ElmSharp/Naviframe.cs +++ b/ElmSharp/ElmSharp/Naviframe.cs @@ -25,11 +25,11 @@ namespace ElmSharp } public class Naviframe : Widget { - Interop.SmartEvent _transitionFinished; + SmartEvent _transitionFinished; readonly List _itemStack = new List(); 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); } diff --git a/ElmSharp/ElmSharp/Panel.cs b/ElmSharp/ElmSharp/Panel.cs index dcb720c..20fd61f 100644 --- a/ElmSharp/ElmSharp/Panel.cs +++ b/ElmSharp/ElmSharp/Panel.cs @@ -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); } diff --git a/ElmSharp/ElmSharp/Panes.cs b/ElmSharp/ElmSharp/Panes.cs index 981849c..6a80beb 100644 --- a/ElmSharp/ElmSharp/Panes.cs +++ b/ElmSharp/ElmSharp/Panes.cs @@ -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); diff --git a/ElmSharp/ElmSharp/Popup.cs b/ElmSharp/ElmSharp/Popup.cs index e8a2df8..f9c9305 100644 --- a/ElmSharp/ElmSharp/Popup.cs +++ b/ElmSharp/ElmSharp/Popup.cs @@ -35,37 +35,36 @@ namespace ElmSharp public class Popup : Layout { HashSet _children = new HashSet(); - 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; diff --git a/ElmSharp/ElmSharp/ProgressBar.cs b/ElmSharp/ElmSharp/ProgressBar.cs index 72e2e99..de66329 100644 --- a/ElmSharp/ElmSharp/ProgressBar.cs +++ b/ElmSharp/ElmSharp/ProgressBar.cs @@ -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); diff --git a/ElmSharp/ElmSharp/Radio.cs b/ElmSharp/ElmSharp/Radio.cs index 8e122f7..20c9100 100644 --- a/ElmSharp/ElmSharp/Radio.cs +++ b/ElmSharp/ElmSharp/Radio.cs @@ -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); } diff --git a/ElmSharp/ElmSharp/Scroller.cs b/ElmSharp/ElmSharp/Scroller.cs index ccc3fb4..f7404f8 100644 --- a/ElmSharp/ElmSharp/Scroller.cs +++ b/ElmSharp/ElmSharp/Scroller.cs @@ -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 diff --git a/ElmSharp/ElmSharp/Slider.cs b/ElmSharp/ElmSharp/Slider.cs index 9ba5df2..adf65b2 100644 --- a/ElmSharp/ElmSharp/Slider.cs +++ b/ElmSharp/ElmSharp/Slider.cs @@ -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); } diff --git a/ElmSharp/Interop/Interop.SmartEvent.cs b/ElmSharp/ElmSharp/SmartEvent.cs similarity index 64% rename from ElmSharp/Interop/Interop.SmartEvent.cs rename to ElmSharp/ElmSharp/SmartEvent.cs index dd0e110..2d06143 100644 --- a/ElmSharp/Interop/Interop.SmartEvent.cs +++ b/ElmSharp/ElmSharp/SmartEvent.cs @@ -18,26 +18,32 @@ using System; using System.Collections.Generic; using System.Linq; -internal static partial class Interop +namespace ElmSharp { - internal class SmartEvent : IDisposable where TEventArgs : EventArgs + public class SmartEvent : 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 _nativeCallbacks = new List(); - 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 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 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 _nativeCallbacks = new List(); + private SmartEvent _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(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(); + } + } } } diff --git a/ElmSharp/ElmSharp/Spinner.cs b/ElmSharp/ElmSharp/Spinner.cs index 8572311..e466e7a 100644 --- a/ElmSharp/ElmSharp/Spinner.cs +++ b/ElmSharp/ElmSharp/Spinner.cs @@ -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); } diff --git a/ElmSharp/ElmSharp/Toolbar.cs b/ElmSharp/ElmSharp/Toolbar.cs index 6c18c3a..7393328 100644 --- a/ElmSharp/ElmSharp/Toolbar.cs +++ b/ElmSharp/ElmSharp/Toolbar.cs @@ -48,12 +48,12 @@ namespace ElmSharp public class Toolbar : Widget { - Interop.SmartEvent _clicked; - Interop.SmartEvent _selected; - Interop.SmartEvent _longpressed; + SmartEvent _clicked; + SmartEvent _selected; + SmartEvent _longpressed; public Toolbar(EvasObject parent) : base(parent) { - _selected = new Interop.SmartEvent(this, Handle, "selected", ToolbarItemEventArgs.CreateFromSmartEvent); + _selected = new SmartEvent(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(this, Handle, "longpressed", ToolbarItemEventArgs.CreateFromSmartEvent); + _longpressed = new SmartEvent(this, "longpressed", ToolbarItemEventArgs.CreateFromSmartEvent); _longpressed.On += (s, e) => { e.Item?.SendLongPressed(); }; - _clicked = new Interop.SmartEvent(this, Handle, "clicked", ToolbarItemEventArgs.CreateFromSmartEvent); + _clicked = new SmartEvent(this, "clicked", ToolbarItemEventArgs.CreateFromSmartEvent); _clicked.On += (s, e) => { e.Item?.SendClicked(); diff --git a/ElmSharp/ElmSharp/Widget.cs b/ElmSharp/ElmSharp/Widget.cs index 2569615..fabf249 100644 --- a/ElmSharp/ElmSharp/Widget.cs +++ b/ElmSharp/ElmSharp/Widget.cs @@ -23,8 +23,8 @@ namespace ElmSharp { Dictionary _partContents = new Dictionary(); - 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; diff --git a/ElmSharp/ElmSharp/Window.cs b/ElmSharp/ElmSharp/Window.cs index ea704ea..1b4d54d 100644 --- a/ElmSharp/ElmSharp/Window.cs +++ b/ElmSharp/ElmSharp/Window.cs @@ -51,8 +51,8 @@ namespace ElmSharp public class Window : Widget { - Interop.SmartEvent _deleteRequest; - Interop.SmartEvent _rotationChanged; + SmartEvent _deleteRequest; + SmartEvent _rotationChanged; HashSet _referenceHolder = new HashSet(); 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 index e5a8408..0000000 --- a/ElmSharp/Interop/Interop.EvasObjectEvent.cs +++ /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 : 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 _nativeCallbacks = new List(); - - 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 eventHandler; - } - - public event EventHandler On - { - add - { - EventHandler 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 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 _nativeCallbacks = new List(); - - 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); - } - } -} diff --git a/packaging/elm-sharp.spec b/packaging/elm-sharp.spec index 4118192..7b5c7fe 100644 --- a/packaging/elm-sharp.spec +++ b/packaging/elm-sharp.spec @@ -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 -- 2.7.4