package org.itsnat.droid.impl.browser.serveritsnat; import android.view.View; import android.view.ViewParent; import org.itsnat.droid.HttpRequestResult; import org.itsnat.droid.ItsNatDroidException; import org.itsnat.droid.ItsNatDroidServerResponseException; import org.itsnat.droid.OnEventErrorListener; import org.itsnat.droid.impl.browser.DroidEventDispatcher; import org.itsnat.droid.impl.browser.ItsNatViewImpl; import org.itsnat.droid.impl.browser.PageImpl; import org.itsnat.droid.impl.browser.serveritsnat.event.DroidEventImpl; import org.itsnat.droid.impl.browser.serveritsnat.event.DroidInputEventImpl; import org.itsnat.droid.impl.browser.serveritsnat.evtlistener.DroidEventListener; import java.util.LinkedList; import java.util.List; /** * Created by jmarranz on 24/12/2015. */ public class DroidEventDispatcherItsNat extends DroidEventDispatcher { public DroidEventDispatcherItsNat(ItsNatDocItsNatImpl itsNatDoc) { super(itsNatDoc); } public void dispatch(ItsNatViewImpl viewDataCurrentTarget,String type,Object nativeEvt) { super.dispatch(viewDataCurrentTarget,type,nativeEvt); View viewTarget = viewDataCurrentTarget.getView(); // En "unload" y "load" viewDataCurrentTarget es ItsNatViewNullImpl por lo que getView() es nulo dispatch(viewDataCurrentTarget,type,nativeEvt,true, DroidEventImpl.AT_TARGET,viewTarget); } private void dispatch(ItsNatViewImpl viewDataCurrentTarget,String type,Object nativeEvt,boolean checkUseCapture,int eventPhase,View viewTarget) { List<DroidEventListener> list = viewDataCurrentTarget.getEventListeners(type); if (list == null) return; View viewCurrentTarget = viewDataCurrentTarget.getView(); for (DroidEventListener listener : list) { if (checkUseCapture && listener.isUseCapture()) { dispatchCapture(viewCurrentTarget,type,nativeEvt,viewTarget); } DroidEventImpl evtWrapper = (DroidEventImpl)listener.createNormalEvent(nativeEvt); try { evtWrapper.setEventPhase(eventPhase); evtWrapper.setTarget(viewTarget); listener.dispatchEvent(evtWrapper); } catch(Exception ex) { // Desde aquí capturamos todos los fallos del proceso de eventos, el código anterior a dispatchEvent(String,InputEvent) nunca debería // fallar, o bien porque es muy simple o porque hay llamadas al código del usuario que él mismo puede controlar sus fallos PageImpl page = itsNatDoc.getPageImpl(); OnEventErrorListener errorListener = page.getOnEventErrorListener(); if (errorListener != null) { HttpRequestResult result = (ex instanceof ItsNatDroidServerResponseException) ? ((ItsNatDroidServerResponseException)ex).getHttpRequestResult() : null; errorListener.onError(page, evtWrapper, ex, result); } else { if (ex instanceof ItsNatDroidException) throw (ItsNatDroidException) ex; else throw new ItsNatDroidException(ex); } } } } private void dispatchCapture(View view,String type,Object nativeEvt,View viewTarget) { List<ViewParent> tree = getViewTreeParent(view); for (ViewParent viewParent : tree) { ItsNatViewImpl viewParentData = itsNatDoc.getItsNatViewImpl((View) viewParent); dispatch(viewParentData, type, nativeEvt, false, DroidInputEventImpl.CAPTURING_PHASE, viewTarget); } } private static List<ViewParent> getViewTreeParent(View view) { List<ViewParent> tree = new LinkedList<ViewParent>(); ViewParent parent = view.getParent(); // Asegura que en la lista no está el View inicial getViewTree(parent,tree); return tree; } private static void getViewTree(ViewParent view,List<ViewParent> tree) { if (view == null || !(view instanceof View)) return; tree.add(0, view); getViewTree(view.getParent(),tree); } }