/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_GUI #include "glgui_handler.h" #include "event_handler.h" #include "key_names.h" #include "glgui_mainwidget.h" #include "glgui_cursor.h" #include "class_list.h" #include #include "debug.h" #include /// TAKE THIS OUT OF HERE. #include "graphics_engine.h" namespace OrxGui { /** * standard constructor */ GLGuiHandler::GLGuiHandler () { this->setClassID(CL_GLGUI_HANDLER, "GLGuiHandler"); this->setName("GLGuiHandler"); EventHandler::getInstance()->withUNICODE(ES_MENU, true ); this->_cursor = NULL; for (unsigned int i = 0; i < EV_NUMBER; i++) { this->subscribeEvent(ES_ALL, i); } } /** * the singleton reference to this class */ GLGuiHandler* GLGuiHandler::singletonRef = NULL; /** @brief standard deconstructor */ GLGuiHandler::~GLGuiHandler () { GLGuiHandler::singletonRef = NULL; } void GLGuiHandler::activateCursor() { if (this->_cursor == NULL) this->_cursor = new GLGuiCursor(); this->_cursor->show(); this->_cursor->setMaxBorders(Vector2D(GraphicsEngine::getInstance()->getResolutionX(), GraphicsEngine::getInstance()->getResolutionY())); } void GLGuiHandler::deactivateCursor(bool deleteCursor) { if (this->_cursor) { if (deleteCursor) delete this->_cursor; this->_cursor = NULL; } } void GLGuiHandler::activate() { //EventHandler::getInstance()->pushState(ES_MENU); } void GLGuiHandler::deactivate() { //EventHandler::getInstance()->popState(); } void GLGuiHandler::selectNext() { // retrieve Objects. const std::list* objects = ClassList::getList(CL_GLGUI_WIDGET); if (objects) { std::list::const_iterator it ; std::list::const_iterator currentIt = objects->end(); if (GLGuiWidget::selected() != NULL) { it = std::find(objects->begin(), objects->end(), GLGuiWidget::selected()); if (it != objects->end()) { currentIt = it; it++; } } else { it = objects->begin(); } bool cycledOnce = false; for (; it != currentIt; ++it) { if (it == objects->end() && !cycledOnce) { it = objects->begin(); cycledOnce = true; } if (dynamic_cast(*it)->selectable() && dynamic_cast(*it)->isVisible()) { dynamic_cast(*it)->select(); return; } } } else { PRINTF(0)("NO GUI-ELEMENTS EXISTING\n"); } } void GLGuiHandler::selectPrevious() { // retrieve Objects. const std::list* objects = ClassList::getList(CL_GLGUI_WIDGET); if (objects) { std::list::const_iterator it ; std::list::const_iterator currentIt = objects->begin(); if (GLGuiWidget::selected() != NULL) { it = std::find(objects->begin(), objects->end(), GLGuiWidget::selected()); if (it != objects->end()) { currentIt = it; it--; } } else { it = objects->end(); } bool cycledOnce = false; for (; it != currentIt; --it) { if (it == objects->end() && !cycledOnce) { --it ; cycledOnce = true; } if (dynamic_cast(*it)->selectable() && dynamic_cast(*it)->isVisible()) { dynamic_cast(*it)->select(); return; } } } else { PRINTF(0)("NO GUI-ELEMENTS EXISTING\n"); } } void GLGuiHandler::process(const Event &event) { switch (event.type) { case EV_MOUSE_MOTION: this->checkFocus(); break; case EV_MOUSE_BUTTON_LEFT: if (GLGuiWidget::mouseFocused() != NULL && event.bPressed) { // if clickable select the Widget. if (GLGuiWidget::mouseFocused()->clickable()) { Vector2D cursorPos = (this->_cursor != NULL) ? this->_cursor->getAbsCoor2D() : Vector2D(event.x, event.y); GLGuiWidget::mouseFocused()->select(); GLGuiWidget::mouseFocused()->click(cursorPos - GLGuiWidget::mouseFocused()->getAbsCoor2D()); } } else if (GLGuiWidget::selected() != NULL && !event.bPressed) { if (GLGuiWidget::selected()->clickable()) { Vector2D cursorPos = (this->_cursor != NULL) ? this->_cursor->getAbsCoor2D() : Vector2D(event.x, event.y); GLGuiWidget::selected()->release(cursorPos - GLGuiWidget::selected()->getAbsCoor2D()); } } break; case EV_LEAVE_STATE: if (GLGuiWidget::selected() != NULL) GLGuiWidget::selected()->unselect(); if (GLGuiWidget::mouseFocused() != NULL) GLGuiWidget::mouseFocused()->breakMouseFocus(); break; case EV_VIDEO_RESIZE: if (this->_cursor != NULL) this->_cursor->setMaxBorders(Vector2D(event.resize.w, event.resize.h)); break; case SDLK_TAB: if (event.bPressed) { if (EventHandler::getInstance()->isPressed(SDLK_LSHIFT) || EventHandler::getInstance()->isPressed(SDLK_RSHIFT)) this->selectPrevious(); else this->selectNext(); } break; } // Send the Event to the Widget below. if (GLGuiWidget::selected() != NULL) { GLGuiWidget::selected()->processEvent(event); } } Vector2D GLGuiHandler::cursorPositionOverFocusedWidget() const { return (this->_cursor != NULL) ? this->_cursor->getAbsCoor2D() : Vector2D(0,0); } const Vector2D& GLGuiHandler::cursorPositionAbs() const { if (this->_cursor) return this->_cursor->getAbsCoor2D(); else return Vector2D::nullVector(); } Vector2D GLGuiHandler::cursorPositionRel(const GLGuiWidget* const widget) const { assert (widget != NULL); if (this->_cursor) return this->_cursor->getAbsCoor2D() - widget->getAbsCoor2D(); else return Vector2D::nullVector(); } void GLGuiHandler::checkFocus() { // CHECK THE COLLISIONS. const std::list* objects = ClassList::getList(CL_GLGUI_WIDGET); if (objects != NULL && this->_cursor != NULL) { for (std::list::const_iterator it = objects->begin(); it != objects->end(); it++) { GLGuiWidget* widget = dynamic_cast(*it); if (widget->isVisible() && widget->focusable() && widget->focusOverWidget(this->_cursor)) { // receiving Focus if (GLGuiWidget::mouseFocused() != widget) { widget->giveMouseFocus(); } return ; } } if (GLGuiWidget::mouseFocused() != NULL) GLGuiWidget::mouseFocused()->breakMouseFocus(); } } void GLGuiHandler::draw() { // GLGuiMainWidget::getInstance()->draw2D(E2D_LAYER_TOP); } void GLGuiHandler::tick(float dt) { // do not change if we already clicked into a Widget. // if (GLGuiWidget::selected() != NULL && GLGuiWidget::selected()->pushed()) // return ; this->checkFocus(); } }