using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; namespace AV.UITK { public partial class FluentElement<T> { public delegate void Call<in TEvent>(TEvent evt, CallHandle c) where TEvent : EventBase<TEvent>, new(); static class EventStorage<TEvent> where TEvent : EventBase<TEvent>, new() { public static Dictionary<Call<TEvent>, CallHandle> Handlers = new Dictionary<Call<TEvent>, CallHandle>(); } /// <summary> Returns all callbacks registered to this element. </summary> public IEnumerable<FluentUITK.EventFunctor> GetCallbacks() { return FluentUITK.GetCallbacks(x); } // TODO: OnBind // TODO: OnAnyChange public FluentElement<T> OnChange<TValue>(Call<ChangeEvent<TValue>> evt) { Register(evt); return x; } public FluentElement<T> OnChange<TValue>(EventCallback<ChangeEvent<TValue>> evt) { Register(evt); return x; } public FluentElement<T> OnChange<TValue>(Action evt) { Register<ChangeEvent<TValue>>(_ => evt()); return x; } public FluentElement<T> OnAttach(Call<AttachToPanelEvent> evt) { Register(evt); return x; } public FluentElement<T> OnAttach(EventCallback<AttachToPanelEvent> evt) { Register(evt); return x; } public FluentElement<T> OnAttach(Action evt) { Register<AttachToPanelEvent>(_ => evt()); return x; } public FluentElement<T> OnLayoutUpdate(Call<GeometryChangedEvent> evt) { Register(evt); return x; } public FluentElement<T> OnLayoutUpdate(EventCallback<GeometryChangedEvent> evt) { Register(evt); return x; } public FluentElement<T> OnLayoutUpdate(Action evt) { Register<GeometryChangedEvent>(_ => evt()); return x; } public FluentElement<T> OnClick(Action up) { OnClick((_, __) => up()); return x; } public FluentElement<T> OnClick(Action up, MouseButton button) { OnClick((evt, c) => up(), (int)button); return x; } public FluentElement<T> OnClick(EventCallback<MouseUpEvent> up) { OnClick((evt, _) => up(evt)); return x; } public FluentElement<T> OnClick(EventCallback<MouseUpEvent> up, MouseButton button) { OnClick((evt, _) => up(evt), (int)button); return x; } public FluentElement<T> OnClick(Call<MouseUpEvent> up) { // LMB is used as default value OnClick(up, 0); return x; } public FluentElement<T> OnClick(Call<MouseUpEvent> up, MouseButton button) { OnClick(up, (int)button); return x; } FluentElement<T> OnClick(Call<MouseUpEvent> up, int button) { var isMouseOver = false; // TODO: Could be improved by avoiding extra enter leave events? Register<MouseEnterEvent>(evt => isMouseOver = true); Register<MouseLeaveEvent>(evt => isMouseOver = false); Register<MouseUpEvent>((evt, c) => { if (button != -1 && evt.button != button) return; if (isMouseOver) up.Invoke(evt, c); }); return x; } public FluentElement<T> Register<TEvent>(EventCallback<TEvent> evt, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEvent : EventBase<TEvent>, new() { x.RegisterCallback(evt, trickleDown); return x; } public FluentElement<T> Register<TEvent>(Call<TEvent> c, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEvent : EventBase<TEvent>, new() { var handler = new CallHandle { x = x, eventTypeId = EventBase<TEvent>.TypeId() }; var callback = (EventCallback<TEvent>)(evt => { handler.evt = evt; handler.totalCalls++; handler.trickle = trickleDown; c.Invoke(evt, handler); }); handler.callback = callback; x.RegisterCallback(callback, trickleDown); if (EventStorage<TEvent>.Handlers.ContainsKey(c)) EventStorage<TEvent>.Handlers[c] = handler; else EventStorage<TEvent>.Handlers.Add(c, handler); return x; } public FluentElement<T> Unregister<TEvent>(Call<TEvent> c) where TEvent : EventBase<TEvent>, new() { if (EventStorage<TEvent>.Handlers.TryGetValue(c, out var handler)) Unregister(handler); return x; } public FluentElement<T> Unregister<TEvent>(EventCallback<TEvent> callback) where TEvent : EventBase<TEvent>, new() { x.UnregisterCallback(callback); return x; } public FluentElement<T> Unregister(CallHandle handle) { FluentUITK.UnregisterCallback(x, handle.eventTypeId, handle.callback, handle.trickle); return x; } } }