/** 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
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); } }
/** * 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); } }