static void ForEachEventListenerBubbleUp <T>(T e, HitChain hitPointChain, EventListenerAction <T> listenerAction) where T : UIEventArgs { HitInfo hitInfo; for (int i = hitPointChain.Count - 1; i >= 0; --i) { hitInfo = hitPointChain.GetHitInfo(i); if (hitInfo.HitElemAsRenderElement.GetController() is IUIEventListener listener) { if (e.SourceHitElement == null) { e.SetSourceHitObject(listener); } Point p = hitInfo.point; e.SetLocation(p.X, p.Y); e.SetCurrentContextElement(listener); if (listenerAction(e, listener)) { return; } } } }
static void ForEachEventListenerBubbleUp(UIEventArgs e, HitChain hitPointChain, EventListenerAction listenerAction) { HitInfo hitInfo; for (int i = hitPointChain.Count - 1; i >= 0; --i) { hitInfo = hitPointChain.GetHitInfo(i); IUIEventListener listener = hitInfo.hitElement.GetController() as IUIEventListener; if (listener != null) { if (e.SourceHitElement == null) { e.SourceHitElement = listener; } var hitPoint = hitInfo.point; e.SetLocation(hitPoint.X, hitPoint.Y); e.CurrentContextElement = listener; if (listenerAction(listener)) { return; } } } }
static void SetEventOrigin(UIEventArgs e, HitChain hitChain) { int count = hitChain.Count; if (count > 0) { var hitInfo = hitChain.GetHitInfo(count - 1); e.ExactHitObject = hitInfo.hitElement; } }
static RenderElement HitTestOnPreviousChain(HitChain hitPointChain, HitChain previousChain, int x, int y) { #if DEBUG if (hitPointChain == previousChain) { throw new NotSupportedException(); } #endif if (previousChain.Count > 0) { previousChain.SetStartTestPoint(x, y); //test on prev chain top to bottom int j = previousChain.Count; for (int i = 0; i < j; ++i) { HitInfo hitInfo = previousChain.GetHitInfo(i); RenderElement elem = hitInfo.hitElement; if (elem != null && elem.VisibleAndHasParent) { if (elem.Contains(hitInfo.point)) { RenderElement found = elem.FindUnderlyingSiblingAtPoint(hitInfo.point); if (found == null) { Point leftTop = elem.Location; hitPointChain.OffsetTestPoint(leftTop.X, leftTop.Y); hitPointChain.AddHitObject(elem); //add to chain } else { break; } } } else { break; } } } //--------------------------------- if (hitPointChain.Count > 0) { var commonElement = hitPointChain.GetHitInfo(hitPointChain.Count - 1).hitElement; hitPointChain.RemoveCurrentHit(); return(commonElement); } else { return(null); } }
static void SetEventOrigin(UIEventArgs e, HitChain hitChain) { int count = hitChain.Count; if (count > 0) { e.SetExactHitObject(hitChain.GetHitInfo(count - 1).HitElemAsRenderElement); } else { e.SetExactHitObject(null); } }
static void ForEachOnlyEventPortalBubbleUp <T>(T e, HitChain hitPointChain, EventPortalAction <T> eventPortalAction) where T : UIEventArgs { for (int i = hitPointChain.Count - 1; i >= 0; --i) { HitInfo hitPoint = hitPointChain.GetHitInfo(i); object currentHitObj = hitPoint.HitElemAsRenderElement.GetController(); if (currentHitObj is IEventPortal eventPortal) { Point p = hitPoint.point; e.SetCurrentContextElement(currentHitObj as IUIEventListener); e.SetLocation(p.X, p.Y); if (eventPortalAction(e, eventPortal)) { return; } } } }
static void ForEachOnlyEventPortalBubbleUp(UIEventArgs e, HitChain hitPointChain, EventPortalAction eventPortalAction) { for (int i = hitPointChain.Count - 1; i >= 0; --i) { HitInfo hitPoint = hitPointChain.GetHitInfo(i); object currentHitElement = hitPoint.hitElement.GetController(); IEventPortal eventPortal = currentHitElement as IEventPortal; if (eventPortal != null) { var ppp = hitPoint.point; e.CurrentContextElement = currentHitElement as IUIEventListener; e.SetLocation(ppp.X, ppp.Y); if (eventPortalAction(eventPortal)) { return; } } } }
// static RenderElement HitTestOnPreviousChain(HitChain hitPointChain, HitChain previousChain, int x, int y) // { //#if DEBUG // if (hitPointChain == previousChain) // { // throw new NotSupportedException(); // } //#endif // if (previousChain.Count > 0) // { // previousChain.SetStartTestPoint(x, y); // //test on prev chain top to bottom // int j = previousChain.Count; // for (int i = 0; i < j; ++i) // { // HitInfo hitInfo = previousChain.GetHitInfo(i); // RenderElement elem = hitInfo.HitElemAsRenderElement; // if (elem != null && elem.VisibleAndHasParent) // { // if (elem.Contains(hitInfo.point)) // { // RenderElement found = elem.FindUnderlyingSiblingAtPoint(hitInfo.point); // if (found == null) // { // Point leftTop = elem.Location; // hitPointChain.OffsetTestPoint(leftTop.X, leftTop.Y); // hitPointChain.AddHitObject(elem); // //add to chain // } // else // { // break; // } // } // } // else // { // break; // } // } // } // //--------------------------------- // if (hitPointChain.Count > 0) // { // var commonElement = hitPointChain.GetHitInfo(hitPointChain.Count - 1).HitElemAsRenderElement; // hitPointChain.RemoveCurrentHit(); // return commonElement; // } // else // { // return null; // } // } void HitTestCoreWithPrevChainHint(HitChain hitChain, HitChain previousChain, int x, int y) { //--------------------------------- //test on previous chain first , find common element hitChain.Reset(); hitChain.SetStartTestPoint(x, y); #if DEBUG hitChain.dbugHitPhase = _dbugHitChainPhase; #endif //if (this.dbugId > 0 && isDragging && previousChain.Count > 1) //{ //} //RenderElement commonElement = HitTestOnPreviousChain(hitPointChain, previousChain, x, y); //temp fix //TODO: fix bug on HitTestOnPreviousChain() RenderElement commonElement = _topRenderElement; commonElement.HitTestCore(hitChain); //remove disable elements //if (hitPointChain.dbugHitPhase == dbugHitChainPhase.MouseDown) //{ int j = hitChain.Count; for (int i = 0; i < j; ++i) { HitInfo info = hitChain.GetHitInfo(i); RenderElement renderE = info.HitElemAsRenderElement; if (renderE != null && renderE.GetController() is IUIEventListener ui && !ui.Enabled) { HitChain.UnsafeClear(hitChain); break;//stop loop and exit } } //} }
void IEventPortal.PortalMouseDown(UIMouseDownEventArgs e) { #if DEBUG if (this.dbugRootGraphics != null && this.dbugRootGraphics.dbugEnableGraphicInvalidateTrace) { this.dbugRootGraphics.dbugGraphicInvalidateTracer.WriteInfo("================"); this.dbugRootGraphics.dbugGraphicInvalidateTracer.WriteInfo("MOUSEDOWN"); this.dbugRootGraphics.dbugGraphicInvalidateTracer.WriteInfo("================"); } dbugMsgChainVersion = 1; int local_msgVersion = 1; #endif HitChain hitPointChain = GetFreeHitChain(); #if DEBUG _dbugHitChainPhase = dbugHitChainPhase.MouseDown; #endif HitTestCoreWithPrevChainHint(hitPointChain, _previousChain, e.X, e.Y); if (hitPointChain.Count > 0) { //------------------------------ //1. origin object SetEventOrigin(e, hitPointChain); //------------------------------ _currentMouseDown = null; //portal ForEachOnlyEventPortalBubbleUp(e, hitPointChain, (e1, portal) => { //please ensure=> no local var/pararmeter capture inside lambda portal.PortalMouseDown(e1); //***** _currentMouseDown = e1.CurrentContextElement; return(true); }); //------------------------------ //use events if (!e.CancelBubbling) { _currentMouseDown = null; //clear e.SetCurrentContextElement(null); ForEachEventListenerBubbleUp(e, hitPointChain, (e1, listener) => { //please ensure=> no local var/pararmeter capture inside lambda if (listener.BypassAllMouseEvents) { return(false); } _currentMouseDown = listener; listener.ListenMouseDown(e1); //------------------------------------------------------- //auto begin monitor mouse press _mousePressMonitor.AddMousePressInformation(e1); _mousePressMonitor.SetMonitoredElement(listener); //------------------------------------------------------- bool cancelMouseBubbling = e1.CancelBubbling; if (_prevMouseDownElement != null && _prevMouseDownElement != listener) { _prevMouseDownElement.ListenLostMouseFocus(_mouseLostFocusArgs); _prevMouseDownElement = null;//clear } //------------------------------------------------------- //retrun true to stop this loop (no further bubble up) //return false to bubble this to upper control return(e1.CancelBubbling || !listener.BypassAllMouseEvents); }); if (_currentMouseDown == null) { _mousePressMonitor.Reset(); } } if (_prevMouseDownElement != _currentMouseDown && _prevMouseDownElement != null) { //TODO: review here, auto or manual _prevMouseDownElement.ListenLostMouseFocus(_mouseLostFocusArgs); _prevMouseDownElement = null; } } //--------------------------------------------------------------- #if DEBUG RootGraphic dbug_visualroot = this.dbugRootGraphics; if (dbug_visualroot != null && dbug_visualroot.dbug_RecordHitChain) { dbug_visualroot.dbug_rootHitChainMsg.Clear(); HitInfo hitInfo; for (int tt = hitPointChain.Count - 1; tt >= 0; --tt) { hitInfo = hitPointChain.GetHitInfo(tt); RenderElement ve = hitInfo.HitElemAsRenderElement; if (ve != null) { ve.dbug_WriteOwnerLayerInfo(dbug_visualroot, tt); ve.dbug_WriteOwnerLineInfo(dbug_visualroot, tt); string hit_info = new string('.', tt) + " [" + tt + "] " + "(" + hitInfo.point.X + "," + hitInfo.point.Y + ") " + ve.dbug_FullElementDescription(); dbug_visualroot.dbug_rootHitChainMsg.AddLast(new dbugLayoutMsg(ve, hit_info)); } } } #endif SwapHitChain(hitPointChain); e.StopPropagation(); //TODO: review this again #if DEBUG if (local_msgVersion != dbugMsgChainVersion) { return; } dbug_visualroot.dbugHitTracker.Write("stop-mousedown"); dbug_visualroot.dbugHitTracker.Play = false; #endif }
void IEventPortal.PortalMouseDown(UIMouseEventArgs e) { #if DEBUG if (this.dbugRootGraphics.dbugEnableGraphicInvalidateTrace) { this.dbugRootGraphics.dbugGraphicInvalidateTracer.WriteInfo("================"); this.dbugRootGraphics.dbugGraphicInvalidateTracer.WriteInfo("MOUSEDOWN"); this.dbugRootGraphics.dbugGraphicInvalidateTracer.WriteInfo("================"); } dbugMsgChainVersion = 1; int local_msgVersion = 1; #endif HitChain hitPointChain = GetFreeHitChain(); HitTestCoreWithPrevChainHint(hitPointChain, this._previousChain, e.X, e.Y); int hitCount = hitPointChain.Count; RenderElement hitElement = hitPointChain.TopMostElement; if (hitCount > 0) { //------------------------------ //1. origin object SetEventOrigin(e, hitPointChain); //------------------------------ var prevMouseDownElement = e.PreviousMouseDown; IUIEventListener currentMouseDown = null; //portal ForEachOnlyEventPortalBubbleUp(e, hitPointChain, (portal) => { portal.PortalMouseDown(e); //***** currentMouseDown = e.CurrentContextElement; return(true); }); //------------------------------ //use events if (!e.CancelBubbling) { e.CurrentContextElement = currentMouseDown = null; //clear ForEachEventListenerBubbleUp(e, hitPointChain, (listener) => { currentMouseDown = listener; listener.ListenMouseDown(e); //------------------------------------------------------- bool cancelMouseBubbling = e.CancelBubbling; if (prevMouseDownElement != null && prevMouseDownElement != listener) { prevMouseDownElement.ListenLostMouseFocus(e); prevMouseDownElement = null;//clear } //------------------------------------------------------- return(e.CancelBubbling || !listener.BypassAllMouseEvents); }); } if (prevMouseDownElement != currentMouseDown && prevMouseDownElement != null) { prevMouseDownElement.ListenLostMouseFocus(e); prevMouseDownElement = null; } } //--------------------------------------------------------------- #if DEBUG RootGraphic visualroot = this.dbugRootGraphics; if (visualroot.dbug_RecordHitChain) { visualroot.dbug_rootHitChainMsg.Clear(); HitInfo hitInfo; for (int tt = hitPointChain.Count - 1; tt >= 0; --tt) { hitInfo = hitPointChain.GetHitInfo(tt); RenderElement ve = hitInfo.hitElement; if (ve != null) { ve.dbug_WriteOwnerLayerInfo(visualroot, tt); ve.dbug_WriteOwnerLineInfo(visualroot, tt); string hit_info = new string('.', tt) + " [" + tt + "] " + "(" + hitInfo.point.X + "," + hitInfo.point.Y + ") " + ve.dbug_FullElementDescription(); visualroot.dbug_rootHitChainMsg.AddLast(new dbugLayoutMsg(ve, hit_info)); } } } #endif SwapHitChain(hitPointChain); e.StopPropagation(); #if DEBUG if (local_msgVersion != dbugMsgChainVersion) { return; } visualroot.dbugHitTracker.Write("stop-mousedown"); visualroot.dbugHitTracker.Play = false; #endif }