void CATouchController::passingTouchesViews(float dt)
{
    CAView* view = dynamic_cast<CAView*>(CAApplication::getApplication()->getTouchDispatcher()->getFirstResponder());
    bool isContainsFirstPoint = view && view->convertRectToWorldSpace(view->getBounds()).containsPoint(m_tFirstPoint);
    if (!isContainsFirstPoint && view)
    {
        view->ccTouchBegan(m_pTouch, m_pEvent);
    }
    
    CC_RETURN_IF(m_vTouchesViews.empty());

    CAResponder* responder = m_vTouchesViews.front();
    while (responder->nextResponder())
    {
        m_vTouchesViews.pushBack(responder->nextResponder());
        responder = responder->nextResponder();
    }
    
    for (int i=0; i<m_vTouchesViews.size();)
    {
        if (!m_vTouchesViews.at(i)->ccTouchBegan(m_pTouch, m_pEvent))
        {
            m_vTouchesViews.erase(i);
        }
        else
        {
            i++;
        }
    }
}
void CATouchController::touchCancelled()
{
    CAScheduler::unschedule(schedule_selector(CATouchController::passingTouchesViews), this);
    
    CAView* view = dynamic_cast<CAView*>(CAApplication::getApplication()->getTouchDispatcher()->getFirstResponder());
    bool isContainsFirstPoint = view && view->convertRectToWorldSpace(view->getBounds()).containsPoint(m_tFirstPoint);
    if (!isContainsFirstPoint && view)
    {
        view->ccTouchCancelled(m_pTouch, m_pEvent);
    }
    
    CAVector<CAResponder*>::iterator itr;
    for (itr=m_vTouchesViews.begin(); itr!=m_vTouchesViews.end(); itr++)
    {
        (*itr)->ccTouchCancelled(m_pTouch, m_pEvent);
    }
}
void CATouchController::touchBegan()
{
    m_tFirstPoint = m_pTouch->getLocation();
    
    std::vector<CAResponder*> vector;
    
    CAView* view = dynamic_cast<CAView*>(CAApplication::getApplication()->getTouchDispatcher()->getFirstResponder());
    bool isContainsFirstPoint = view && view->convertRectToWorldSpace(view->getBounds()).containsPoint(m_tFirstPoint);
    if (isContainsFirstPoint)
    {
        vector = this->getEventListener(m_pTouch, view);
    }
    else
    {
        vector = this->getEventListener(m_pTouch, CAApplication::getApplication()->getRootWindow());
    }

    std::vector<CAResponder*>::iterator itr;
    for (itr=vector.begin(); itr!=vector.end(); itr++)
    {
        if ((*itr)->isTouchMovedStopSubviews())
        {
            m_vTouchMovedsViewCache.pushBack((*itr));
        }
    }
    m_vTouchesViews.pushBack(vector.back());
    
    if (!m_vTouchMovedsViewCache.empty())
    {
        CAScheduler::schedule(schedule_selector(CATouchController::passingTouchesViews), this, 0, 0, 0.05f);
    }
    else
    {
        this->passingTouchesViews();
    }
}
void CATouchController::touchMoved()
{
    CC_RETURN_IF(ccpDistance(m_tFirstPoint, m_pTouch->getLocation()) < _px(32));
    
    m_tFirstPoint = CCPointZero;
    
    if (!m_vTouchMovedsViewCache.empty())
    {
        bool isScheduledPassing = CAScheduler::isScheduled(schedule_selector(CATouchController::passingTouchesViews), this);
        
        CAScheduler::unschedule(schedule_selector(CATouchController::passingTouchesViews), this);
        
        while (!m_vTouchMovedsViewCache.empty())
        {
            CAResponder* responder = m_vTouchMovedsViewCache.back();
            CCPoint pointOffSet = CCPointZero;
            if (CAView* v = dynamic_cast<CAView*>(responder))
            {
                pointOffSet = ccpSub(v->convertToNodeSpace(m_pTouch->getLocation()),
                                     v->convertToNodeSpace(m_pTouch->getPreviousLocation()));
            }
            else if (CAViewController* c = dynamic_cast<CAViewController*>(responder))
            {
                pointOffSet = ccpSub(c->getView()->convertToNodeSpace(m_pTouch->getLocation()),
                                     c->getView()->convertToNodeSpace(m_pTouch->getPreviousLocation()));
            }
            else
            {
                pointOffSet = ccpSub(m_pTouch->getLocation(), m_pTouch->getPreviousLocation());
            }
            
            pointOffSet.x = fabsf(pointOffSet.x);
            pointOffSet.y = fabsf(pointOffSet.y);
            
            do
            {
                CC_BREAK_IF(!responder->isTouchMovedListenHorizontal() && pointOffSet.x >= pointOffSet.y);
                CC_BREAK_IF(!responder->isTouchMovedListenVertical() && pointOffSet.x < pointOffSet.y);
                m_vTouchMovedsView.pushBack(m_vTouchMovedsViewCache.back());
            }
            while (0);
            
            m_vTouchMovedsViewCache.popBack();
        }
        
        
        CAVector<CAResponder * > tTouchesViews = m_vTouchesViews;
        if (!m_vTouchMovedsView.empty())
        {
            if (!isScheduledPassing)
            {
                
                CAVector<CAResponder*>::iterator itr;
                //
                for (itr = m_vTouchMovedsView.begin(); itr != m_vTouchMovedsView.end(); itr++)
                {
                    m_vTouchesViews.eraseObject(*itr, true);
                }
                //
                
                for (itr=m_vTouchesViews.begin(); itr!=m_vTouchesViews.end(); itr++)
                {
                    (*itr)->ccTouchCancelled(m_pTouch, m_pEvent);
                }
            }
            
            {
                m_vTouchesViews.clear();
                
                for (int i=0; i<m_vTouchMovedsView.size(); i++)
                {
                    CAResponder* responder = m_vTouchMovedsView.at(i);
                    CCPoint pointOffSet = CCPointZero;
                    if (CAView* v = dynamic_cast<CAView*>(responder))
                    {
                        pointOffSet = ccpSub(v->convertToNodeSpace(m_pTouch->getLocation()),
                                             v->convertToNodeSpace(m_pTouch->getPreviousLocation()));
                    }
                    else if (CAViewController* c = dynamic_cast<CAViewController*>(responder))
                    {
                        pointOffSet = ccpSub(c->getView()->convertToNodeSpace(m_pTouch->getLocation()),
                                             c->getView()->convertToNodeSpace(m_pTouch->getPreviousLocation()));
                    }
                    else
                    {
                        pointOffSet = ccpSub(m_pTouch->getLocation(), m_pTouch->getPreviousLocation());
                    }
                    
                    if (responder->isTouchMovedListenHorizontal()
                        && fabsf(pointOffSet.x) >= fabsf(pointOffSet.y))
                    {
                        CC_CONTINUE_IF(responder->isSlidingMinX() && pointOffSet.x > 0);
                        CC_CONTINUE_IF(responder->isSlidingMaxX() && pointOffSet.x < 0);
                    }
                    
                    if (responder->isTouchMovedListenVertical()
                        && fabsf(pointOffSet.x) < fabsf(pointOffSet.y))
                    {
                        CC_CONTINUE_IF(responder->isSlidingMinY() && pointOffSet.y > 0);
                        CC_CONTINUE_IF(responder->isSlidingMaxY() && pointOffSet.y < 0);
                    }
                    
                    m_vTouchesViews.pushBack(responder);
                    
                    
                    if (tTouchesViews.contains(responder)==false)
                    {
                        responder->ccTouchBegan(m_pTouch, m_pEvent);
                    }
                    break;
                }
                
                if (m_vTouchesViews.empty())
                {
                    m_vTouchesViews.pushBack(m_vTouchMovedsView.front());
                    if (tTouchesViews.contains(m_vTouchesViews.back())==false)
                    {
                        m_vTouchesViews.back()->ccTouchBegan(m_pTouch, m_pEvent);//
                    }
                    
                }
            }
        }
        
    }
    
    CAView* view = dynamic_cast<CAView*>(CAApplication::getApplication()->getTouchDispatcher()->getFirstResponder());
    bool isContainsFirstPoint = view && view->convertRectToWorldSpace(view->getBounds()).containsPoint(m_tFirstPoint);
    if (!isContainsFirstPoint && view)
    {
        view->ccTouchMoved(m_pTouch, m_pEvent);
    }
    
    CAVector<CAResponder*>::iterator itr;
    for (itr=m_vTouchesViews.begin(); itr!=m_vTouchesViews.end(); itr++)
    {
        (*itr)->ccTouchMoved(m_pTouch, m_pEvent);
    }
    
}
void CATouchController::touchMoved()
{
    CC_RETURN_IF(ccpDistance(m_tFirstPoint, m_pTouch->getLocation()) < 16);
    
    m_tFirstPoint = DPointZero;

    if (!m_vTouchMovedsViewCache.empty())
    {
        bool isScheduledPassing = CAScheduler::isScheduled(schedule_selector(CATouchController::passingTouchesViews), this);
        
        bool isTouchEventScrollHandOverToSuperview = true;
        
        for (CAVector<CAResponder*>::iterator itr=m_vTouchesViews.begin();
             itr!=m_vTouchesViews.end(); itr++)
        {
            CC_CONTINUE_IF((*itr)->isTouchEventScrollHandOverToSuperview());
            isTouchEventScrollHandOverToSuperview = false;
            break;
        }
        
        
        if (isScheduledPassing || isTouchEventScrollHandOverToSuperview)
        {
            CAScheduler::unschedule(schedule_selector(CATouchController::passingTouchesViews), this);
            
            while (!m_vTouchMovedsViewCache.empty())
            {
                CAResponder* responder = m_vTouchMovedsViewCache.back();
                DPoint pointOffSet = DPointZero;
                if (CAView* v = dynamic_cast<CAView*>(responder))
                {
                    pointOffSet = ccpSub(v->convertToNodeSpace(m_pTouch->getLocation()),
                                         v->convertToNodeSpace(m_pTouch->getPreviousLocation()));
                }
                else if (CAViewController* c = dynamic_cast<CAViewController*>(responder))
                {
                    pointOffSet = ccpSub(c->getView()->convertToNodeSpace(m_pTouch->getLocation()),
                                         c->getView()->convertToNodeSpace(m_pTouch->getPreviousLocation()));
                }
                else
                {
                    pointOffSet = ccpSub(m_pTouch->getLocation(), m_pTouch->getPreviousLocation());
                }
                
                pointOffSet.x = fabsf(pointOffSet.x);
                pointOffSet.y = fabsf(pointOffSet.y);
                
                do
                {
                    CC_BREAK_IF(!responder->isHorizontalScrollEnabled() && pointOffSet.x >= pointOffSet.y);
                    CC_BREAK_IF(!responder->isVerticalScrollEnabled() && pointOffSet.x < pointOffSet.y);
                    m_vTouchMovedsView.pushBack(m_vTouchMovedsViewCache.back());
                }
                while (0);
                
                m_vTouchMovedsViewCache.popBack();
            }
            
            if (!m_vTouchMovedsView.empty())
            {
                bool isTouchCancelled = true;
                CAVector<CAResponder*>::iterator itr;
                for (itr=m_vTouchesViews.begin(); itr!=m_vTouchesViews.end(); itr++)
                {
                    CAResponder* responder = (*itr);
                    if (responder->isPriorityScroll())
                    {
                        DPoint pointOffSet = DPointZero;
                        if (CAView* v = dynamic_cast<CAView*>(responder))
                        {
                            pointOffSet = ccpSub(v->convertToNodeSpace(m_pTouch->getLocation()),
                                                 v->convertToNodeSpace(m_pTouch->getPreviousLocation()));
                        }
                        else if (CAViewController* c = dynamic_cast<CAViewController*>(responder))
                        {
                            pointOffSet = ccpSub(c->getView()->convertToNodeSpace(m_pTouch->getLocation()),
                                                 c->getView()->convertToNodeSpace(m_pTouch->getPreviousLocation()));
                        }
                        else
                        {
                            pointOffSet = ccpSub(m_pTouch->getLocation(), m_pTouch->getPreviousLocation());
                        }
                        
                        if (!responder->isReachBoundaryHandOverToSuperview())
                        {
                            isTouchCancelled = false;
                            break;
                        }
                        
                        if (responder->isHorizontalScrollEnabled()
                            && fabsf(pointOffSet.x) >= fabsf(pointOffSet.y))
                        {
                            if (!responder->isReachBoundaryLeft() && pointOffSet.x >= 0)
                            {
                                isTouchCancelled = false;
                                break;
                            }
                            if (!responder->isReachBoundaryRight() && pointOffSet.x <= 0)
                            {
                                isTouchCancelled = false;
                                break;
                            }
                            
                        }
                        
                        if (responder->isVerticalScrollEnabled()
                            && fabsf(pointOffSet.x) < fabsf(pointOffSet.y))
                        {
                            if (!responder->isReachBoundaryUp() && pointOffSet.y >= 0)
                            {
                                isTouchCancelled = false;
                                break;
                            }
                            if (!responder->isReachBoundaryDown() && pointOffSet.y <= 0)
                            {
                                isTouchCancelled = false;
                                break;
                            }
                        }
                    }
                }
                
                if (isTouchCancelled)
                {
                    if (!isScheduledPassing)
                    {
                        CAVector<CAResponder*>::iterator itr;
                        for (itr=m_vTouchesViews.begin(); itr!=m_vTouchesViews.end(); itr++)
                        {
                            this->touchCancelledWithResponder(*itr);
                        }
                    }
                    m_vTouchesViews.clear();
                }
                
                if (isScheduledPassing || m_vTouchesViews.empty())
                {
                    for (int i=0; i<m_vTouchMovedsView.size(); i++)
                    {
                        CAResponder* responder = m_vTouchMovedsView.at(i);
                        DPoint pointOffSet = DPointZero;
                        if (CAView* v = dynamic_cast<CAView*>(responder))
                        {
                            pointOffSet = ccpSub(v->convertToNodeSpace(m_pTouch->getLocation()),
                                                 v->convertToNodeSpace(m_pTouch->getPreviousLocation()));
                        }
                        else if (CAViewController* c = dynamic_cast<CAViewController*>(responder))
                        {
                            pointOffSet = ccpSub(c->getView()->convertToNodeSpace(m_pTouch->getLocation()),
                                                 c->getView()->convertToNodeSpace(m_pTouch->getPreviousLocation()));
                        }
                        else
                        {
                            pointOffSet = ccpSub(m_pTouch->getLocation(), m_pTouch->getPreviousLocation());
                        }
                        
                        if (responder->isReachBoundaryHandOverToSuperview())
                        {
                            if (responder->isHorizontalScrollEnabled()
                                && fabsf(pointOffSet.x) >= fabsf(pointOffSet.y))
                            {
                                CC_CONTINUE_IF(responder->isReachBoundaryLeft() && pointOffSet.x > 0);
                                CC_CONTINUE_IF(responder->isReachBoundaryRight() && pointOffSet.x < 0);
                            }
                            else if (responder->isVerticalScrollEnabled()
                                     && fabsf(pointOffSet.x) < fabsf(pointOffSet.y))
                            {
                                CC_CONTINUE_IF(responder->isReachBoundaryUp() && pointOffSet.y > 0);
                                CC_CONTINUE_IF(responder->isReachBoundaryDown() && pointOffSet.y < 0);
                            }
                        }

                        if (this->touchBeganWithResponder(responder))
                        {
                            m_vTouchesViews.pushBack(responder);
                        }
                        
                        break;
                    }
                    
                    if (m_vTouchesViews.empty())
                    {
                        m_vTouchesViews.pushBack(m_vTouchMovedsView.front());
                        
                        while (m_vTouchesViews.back())
                        {
                            if (this->touchBeganWithResponder(m_vTouchesViews.back()))
                            {
                                break;
                            }
                            m_vTouchesViews.popBack();
                        }
                        
                    }
                }
            }
        }

    }

    CAView* view = dynamic_cast<CAView*>(CAApplication::getApplication()->getTouchDispatcher()->getFirstResponder());
    bool isContainsFirstPoint = view && view->convertRectToWorldSpace(view->getBounds()).containsPoint(m_tFirstPoint);
    if (!isContainsFirstPoint && view && view->isScrollEnabled())
    {
        this->touchMovedWithResponder(view);
    }
    
    CAVector<CAResponder*>::iterator itr;
    for (itr=m_vTouchesViews.begin(); itr!=m_vTouchesViews.end(); itr++)
    {
        CC_CONTINUE_IF(!(*itr)->isScrollEnabled());
        this->touchMovedWithResponder(*itr);
    }
    
}