/** This function returns the last widget found in within_vector.
 *  \param within_vector The vector to look into
 *  \return The result of the search, or NULL if the object is not found */
Widget* AbstractTopLevelContainer::getLastWidget(
                                              PtrVector<Widget>* within_vector)
{
    if (m_last_widget != NULL) return m_last_widget;
    if (within_vector == NULL) within_vector = &m_widgets;

    for (int i = within_vector->size()-1; i >= 0; i--)
    {
        if (!within_vector->get(i)->m_focusable) continue;

        // if container, also checks children
        if (within_vector->get(i)->getChildren().size() > 0 &&
            within_vector->get(i)->getType() != WTYPE_RIBBON &&
            within_vector->get(i)->getType() != WTYPE_SPINNER)
        {
            Widget* w = getLastWidget(&within_vector->get(i)->m_children);
            if (w != NULL) return w;
        }

        Widget* item = within_vector->get(i);
        IGUIElement* elem = item->getIrrlichtElement();

        if (elem == NULL ||
            elem->getTabOrder() == -1 ||
            !Widget::isFocusableId(elem->getTabOrder()) ||
            !item->m_focusable)
        {
            continue;
        }

        return item;
    }  // for i in all widgets of within_vector
    return NULL;
}   // getLastWidget
Ejemplo n.º 2
0
void EventHandler::navigateDown(const int playerID, Input::InputType type, const bool pressedDown)
{
    //std::cout << "Naviagte down!\n";

    IGUIElement *el = NULL, *closest = NULL;

    if (type == Input::IT_STICKBUTTON && !pressedDown)
        return;

    Widget* w = GUIEngine::getFocusForPlayer(playerID);
    if (w != NULL)
    {
        el = w->getIrrlichtElement();
    }
    //std::cout << "!!! Player " << playerID << " navigating down of " << w->m_element->getID() << std::endl;

    // list widgets are a bit special, because up/down keys are also used
    // to navigate between various list items, not only to navigate between
    // components
    if (w != NULL && w->m_type == WTYPE_LIST)
    {
        ListWidget* list = (ListWidget*)w;

        const bool stay_within_list = list->getSelectionID() < list->getItemCount()-1;

        if (stay_within_list)
        {
            list->setSelectionID(list->getSelectionID()+1);
            return;
        }
        else
        {
            list->setSelectionID(-1);
        }
    }

    if (w != NULL && w->m_tab_down_root != -1)
    {
        Widget* down = GUIEngine::getWidget( w->m_tab_down_root );
        assert(down != NULL);
        el = down->getIrrlichtElement();

        if (el == NULL)
        {
            std::cerr << "WARNING : m_tab_down_root is set to an ID for which I can't find the widget\n";
            return;
        }
    }

    // don't allow navigating to any widget when a dialog is shown; only navigate to widgets in the dialog
    if (ModalDialog::isADialogActive() && !ModalDialog::getCurrent()->isMyIrrChild(el))
    {
        el = NULL;
    }

    bool found = false;

    if (el != NULL && el->getTabGroup() != NULL)
    {
        // if the current widget is e.g. 5, search for widget 6, 7, 8, 9, ..., 15 (up to 10 IDs may be missing)
        for (int n=1; n<10 && !found; n++)
        {
            closest = GUIEngine::getGUIEnv()->getRootGUIElement()->getElementFromId(el->getTabOrder() + n, true);

            if (closest != NULL && Widget::isFocusableId(closest->getID()))
            {

                Widget* closestWidget = GUIEngine::getWidget( closest->getID() );
                if (playerID != PLAYER_ID_GAME_MASTER && !closestWidget->m_supports_multiplayer) return;

                // if a dialog is shown, restrict to items in the dialog
                if (ModalDialog::isADialogActive() && !ModalDialog::getCurrent()->isMyChild(closestWidget))
                {
                    continue;
                }

                if (NAVIGATION_DEBUG)
                {
                    std::cout << "Navigating down to " << closestWidget->getID() << "\n";
                }

                assert( closestWidget != NULL );
                closestWidget->setFocusForPlayer(playerID);

                // another list exception : when entering a list, select the first item
                if (closestWidget->m_type == WTYPE_LIST)
                {
                    IGUIListBox* list = (IGUIListBox*)(closestWidget->m_element);
                    assert(list != NULL);

                    list->setSelected(0);
                }

                found = true;
            }
        } // end for
    }

    if (!found)
    {

        if (NAVIGATION_DEBUG) std::cout << "Navigating down : wrap around\n";

        // select the first widget
        Widget* firstWidget = NULL;

        if (ModalDialog::isADialogActive())
        {
            //std::cout <<  "w = ModalDialog::getCurrent()->getFirstWidget();\n";
            firstWidget = ModalDialog::getCurrent()->getFirstWidget();
        }
        else
        {
            Screen* screen = GUIEngine::getCurrentScreen();
            if (screen == NULL) return;
            firstWidget = screen->getFirstWidget();
        }

        if (firstWidget != NULL)  firstWidget->setFocusForPlayer(playerID);
    }
}
Ejemplo n.º 3
0
/**
 * Focus the next widget either downwards or upwards.
 *
 * \param reverse True means navigating up, false means down.
 */
void EventHandler::navigate(const int playerID, Input::InputType type, const bool pressedDown, const bool reverse)
{
    IGUIElement *el = NULL, *closest = NULL;

    if (type == Input::IT_STICKBUTTON && !pressedDown)
        return;

    Widget* w = GUIEngine::getFocusForPlayer(playerID);
    if (w != NULL)
    {
        el = w->getIrrlichtElement();
    }

    // list widgets are a bit special, because up/down keys are also used
    // to navigate between various list items, not only to navigate between
    // components
    if (w != NULL && w->m_type == WTYPE_LIST)
    {
        ListWidget* list = (ListWidget*) w;

        const bool stay_within_list = reverse ? list->getSelectionID() > 0 :
            list->getSelectionID() < list->getItemCount() - 1;

        if (stay_within_list)
        {
            if (reverse)
                list->setSelectionID(list->getSelectionID() - 1);
            else
                list->setSelectionID(list->getSelectionID() + 1);
            return;
        }
        else
        {
            list->setSelectionID(-1);
        }
    }

    if (w != NULL && ((reverse && w->m_tab_up_root != -1) || (!reverse && w->m_tab_down_root != -1)))
    {
        Widget* next = GUIEngine::getWidget(reverse ? w->m_tab_up_root : w->m_tab_down_root);
        assert(next != NULL);
        el = next->getIrrlichtElement();

        if (el == NULL)
        {
            std::cerr << "WARNING : m_tab_down/up_root is set to an ID for which I can't find the widget\n";
            return;
        }
    }

    // don't allow navigating to any widget when a dialog is shown; only navigate to widgets in the dialog
    if (ModalDialog::isADialogActive() && !ModalDialog::getCurrent()->isMyIrrChild(el))
    {
        el = NULL;
    }

    bool found = false;

    // find closest widget
    if (el != NULL && el->getTabGroup() != NULL)
    {
        // Up: if the current widget is e.g. 15, search for widget 14, 13, 12, ... (up to 10 IDs may be missing)
        // Down: if the current widget is e.g. 5, search for widget 6, 7, 8, 9, ..., 15 (up to 10 IDs may be missing)
        for (int n = 1; n < 10 && !found; n++)
        {
            closest = GUIEngine::getGUIEnv()->getRootGUIElement()->getElementFromId(el->getTabOrder() + (reverse ? -n : n), true);

            if (closest != NULL && Widget::isFocusableId(closest->getID()))
            {
                Widget* closestWidget = GUIEngine::getWidget( closest->getID() );

                if (playerID != PLAYER_ID_GAME_MASTER && !closestWidget->m_supports_multiplayer) return;

                // if a dialog is shown, restrict to items in the dialog
                if (ModalDialog::isADialogActive() && !ModalDialog::getCurrent()->isMyChild(closestWidget))
                    continue;

                if (NAVIGATION_DEBUG)
                {
                    std::cout << "Navigating " << (reverse ? "up" : "down") << " to " << closest->getID() << std::endl;
                }

                assert(closestWidget != NULL);

                if (!closestWidget->isVisible() || !closestWidget->isActivated())
                    continue;

                closestWidget->setFocusForPlayer(playerID);

                // another list exception : when entering a list by going down, select the first item
                // when focusing a list by going up, select the last item of the list
                if (closestWidget->m_type == WTYPE_LIST)
                {
                    ListWidget* list = (ListWidget*) closestWidget;
                    assert(list != NULL);
                    list->setSelectionID(reverse ? list->getItemCount() - 1 : 0);
                }
                found = true;
            }
        } // end for
    }

    if (!found)
    {
        if (NAVIGATION_DEBUG)
            std::cout << "EventHandler::navigat : wrap around\n";

        // select the last/first widget
        Widget* wrapWidget = NULL;

        if (ModalDialog::isADialogActive())
        {
            wrapWidget = reverse ? ModalDialog::getCurrent()->getLastWidget() :
                ModalDialog::getCurrent()->getFirstWidget();
        }
        else
        {
            Screen* screen = GUIEngine::getCurrentScreen();
            if (screen == NULL) return;
            wrapWidget = reverse ? screen->getLastWidget() :
                screen->getFirstWidget();
        }

        if (wrapWidget != NULL)  wrapWidget->setFocusForPlayer(playerID);
    }
}