FIFE  2008.0
guimanager.cpp
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2008 by the FIFE team                              *
00003  *   http://www.fifengine.de                                               *
00004  *   This file is part of FIFE.                                            *
00005  *                                                                         *
00006  *   FIFE is free software; you can redistribute it and/or                 *
00007  *   modify it under the terms of the GNU Lesser General Public            *
00008  *   License as published by the Free Software Foundation; either          *
00009  *   version 2.1 of the License, or (at your option) any later version.    *
00010  *                                                                         *
00011  *   This library is distributed in the hope that it will be useful,       *
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00014  *   Lesser General Public License for more details.                       *
00015  *                                                                         *
00016  *   You should have received a copy of the GNU Lesser General Public      *
00017  *   License along with this library; if not, write to the                 *
00018  *   Free Software Foundation, Inc.,                                       *
00019  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
00020  ***************************************************************************/
00021 
00022 // Standard C++ library includes
00023 #include <iostream>
00024 
00025 // 3rd party library includes
00026 #include <boost/filesystem/convenience.hpp>
00027 #include <guichan/sdl/sdlinput.hpp>
00028 #include <guichan/key.hpp>
00029 #include <guichan/focushandler.hpp>
00030 #include <guichan.hpp>
00031 
00032 // FIFE includes
00033 // These includes are split up in two parts, separated by one empty line
00034 // First block: files included from the FIFE root src directory
00035 // Second block: files included from the same folder
00036 #include "util/base/exception.h"
00037 #include "util/log/logger.h"
00038 #include "video/renderbackend.h"
00039 #include "gui/base/gui_imageloader.h"
00040 #include "gui/base/gui_font.h"
00041 #include "gui/console/console.h"
00042 #include "video/fonts/fontbase.h"
00043 #include "video/fonts/truetypefont.h"
00044 #include "video/fonts/subimagefont.h"
00045 #include "eventchannel/key/ec_key.h"
00046 #include "eventchannel/key/ec_keyevent.h"
00047 #include "eventchannel/mouse/ec_mouseevent.h"
00048 
00049 #include "guimanager.h"
00050 
00051 
00052 namespace FIFE {
00053     static Logger _log(LM_GUI);
00054 
00055     GUIManager::GUIManager(ImagePool& pool) :
00056         m_gcn_gui(new gcn::Gui()),
00057         m_focushandler(0),
00058         m_gcn_topcontainer(new gcn::Container()),
00059         m_imgloader(new GuiImageLoader(pool)) ,
00060         m_input(new gcn::SDLInput()),
00061         m_console(0),
00062         m_fonts(),
00063         m_pool(pool),
00064         m_logic_executed(false) {
00065 
00066         m_gcn_gui->setInput(m_input);
00067         gcn::Image::setImageLoader(m_imgloader);
00068 
00069         m_gcn_gui->setTop(m_gcn_topcontainer);
00070         m_focushandler = m_gcn_topcontainer->_getFocusHandler();
00071 
00072         m_gcn_topcontainer->setOpaque(false);
00073         m_gcn_topcontainer->setFocusable(false);
00074         m_had_mouse = false;
00075     }
00076 
00077     GUIManager::~GUIManager() {
00078         delete m_console;
00079         delete m_gcn_topcontainer;
00080         delete m_imgloader;
00081         delete m_input;
00082         delete m_gcn_gui;
00083         std::vector<GuiFont*>::iterator i = m_fonts.begin();
00084         while (i != m_fonts.end()) {
00085             delete *i;
00086             ++i;
00087         }
00088     }
00089 
00090     bool GUIManager::onSdlEvent(SDL_Event& evt) {
00091         if (!m_input) {
00092             FL_WARN(_log, "GUIManager, GuichanGUI->getInput == 0 ... discarding events!");
00093             return false;
00094         }
00095 
00096         switch(evt.type) {
00097             case SDL_MOUSEBUTTONDOWN:
00098             case SDL_MOUSEBUTTONUP:
00099                 if( m_gcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) ) {
00100                     m_input->pushInput(evt);
00101                     return true;
00102                 }
00103                 m_focushandler->focusNone();
00104                 return false;
00105 
00106             case SDL_MOUSEMOTION:
00107                 if( m_gcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) ) {
00108                     m_had_mouse = true;
00109                     m_input->pushInput(evt);
00110                     return true;
00111                 }
00112                 if( m_had_mouse ) {
00113                     // We only keep the mouse if a widget/window has requested
00114                     // dragging.
00115                     m_had_mouse = bool(m_focushandler->getDraggedWidget());
00116                     m_input->pushInput(evt);
00117                     return true;
00118                 }
00119                 return false;
00120 
00121             case SDL_KEYDOWN:
00122             case SDL_KEYUP:
00123                 if(m_focushandler->getFocused()) {
00124                     m_input->pushInput(evt);
00125                     return true;
00126                 }
00127                 return false;
00128 
00129             case SDL_ACTIVEEVENT:
00130                 // Actually Guichan doesn't care (it should!)
00131                 // so at least don't swallow mouse_focus events up.
00132                 return false;
00133 
00134             default:
00135                 return false;
00136         }
00137     }
00138 
00139     void GUIManager::resizeTopContainer(unsigned int x, unsigned int y, unsigned int width, unsigned int height) {
00140         m_gcn_topcontainer->setDimension(gcn::Rectangle(x, y, width, height));
00141     }
00142 
00143     gcn::Gui* GUIManager::getGuichanGUI() const {
00144         return m_gcn_gui;
00145     }
00146 
00147     void GUIManager::add(gcn::Widget* widget) {
00148         if( !m_widgets.count(widget) ) {
00149             m_gcn_topcontainer->add(widget);
00150             m_widgets.insert(widget);
00151         }
00152     }
00153 
00154     void GUIManager::remove(gcn::Widget* widget) {
00155         if( m_widgets.count(widget) ) {
00156             m_widgets.erase(widget);
00157             m_gcn_topcontainer->remove(widget);
00158         }
00159     }
00160 
00161     void GUIManager::init(gcn::Graphics* graphics, int screenWidth, int screenHeight) {
00162         m_gcn_gui->setGraphics(graphics);
00163         resizeTopContainer(0, 0, screenWidth, screenHeight);
00164         m_console = new Console();
00165     }
00166 
00167     GuiFont* GUIManager::createFont(const std::string& path, unsigned int size, const std::string& glyphs) {
00168         std::string fontpath = path;
00169         std::string fontglyphs = glyphs;
00170         int fontsize = size;
00171 
00172         // Set default settings if necessary
00173         if(fontpath == "") {
00174             fontpath = m_fontpath;
00175         }
00176         if(fontsize == 0) {
00177             fontsize = m_fontsize;
00178         }
00179         if(fontglyphs == "") {
00180             fontglyphs = m_fontglyphs;
00181         }
00182 
00183         AbstractFont* font = NULL;
00184         GuiFont* guifont = NULL;
00185         if( boost::filesystem::extension(fontpath) == ".ttf" ) {
00186             font = new TrueTypeFont(fontpath, fontsize);
00187         } else {
00188             font = new SubImageFont(fontpath, fontglyphs, m_pool);
00189         }
00190         guifont = new GuiFont(font);
00191 
00192         m_fonts.push_back(guifont);
00193         return guifont;
00194     }
00195 
00196     void GUIManager::releaseFont(GuiFont* font) {
00197         std::vector<GuiFont*>::iterator i = m_fonts.begin();
00198         while (i != m_fonts.end()) {
00199             if ((*i) == font) {
00200                 m_fonts.erase(i);
00201                 delete font;
00202                 return;
00203             }
00204             ++i;
00205         }
00206     }
00207 
00208     void GUIManager::invalidateFonts() {
00209         std::vector<GuiFont*>::iterator it = m_fonts.begin();
00210         while (it != m_fonts.end()) {
00211             (*it)->invalidate();
00212             ++it;
00213         }
00214     }
00215 
00216     GuiFont* GUIManager::setDefaultFont(const std::string& path, unsigned int size, const std::string& glyphs) {
00217         m_fontpath = path;
00218         m_fontsize = size;
00219         m_fontglyphs = glyphs;
00220 
00221         GuiFont* defaultfont = createFont();
00222         gcn::Widget::setGlobalFont(defaultfont);
00223         if (m_console) {
00224             m_console->reLayout();
00225         }
00226 
00227         return defaultfont;
00228     }
00229 
00230     void GUIManager::turn() {
00231         if (!m_logic_executed)
00232             m_gcn_gui->logic();
00233         m_logic_executed = false;
00234         m_gcn_gui->draw();
00235     }
00236 
00237     KeyEvent GUIManager::translateKeyEvent(const gcn::KeyEvent& gcnevt) {
00238         KeyEvent keyevt;
00239         if(gcnevt.getType() == gcn::KeyEvent::PRESSED)
00240             keyevt.setType(KeyEvent::PRESSED);
00241         else if(gcnevt.getType() == gcn::KeyEvent::RELEASED)
00242             keyevt.setType(KeyEvent::RELEASED);
00243         else
00244             throw EventException("Invalid event type in fillKeyEvent");
00245         keyevt.setShiftPressed(gcnevt.isShiftPressed());
00246         keyevt.setControlPressed(gcnevt.isControlPressed());
00247         keyevt.setAltPressed(gcnevt.isAltPressed());
00248         keyevt.setMetaPressed(gcnevt.isMetaPressed());
00249         keyevt.setNumericPad(gcnevt.isNumericPad());
00250 
00251         // Convert from guichan keyval to FIFE keyval
00252         int keyval = gcnevt.getKey().getValue();
00253         keyval = convertGuichanKeyToFifeKey(keyval);
00254 
00255         keyevt.setKey(Key(static_cast<Key::KeyType>(keyval), keyval));
00256 
00257         return keyevt;
00258     }
00259 
00260     MouseEvent GUIManager::translateMouseEvent(const gcn::MouseEvent& gcnevt) {
00261         MouseEvent mouseevt;
00262         mouseevt.setShiftPressed(gcnevt.isShiftPressed());
00263         mouseevt.setControlPressed(gcnevt.isControlPressed());
00264         mouseevt.setAltPressed(gcnevt.isAltPressed());
00265         mouseevt.setMetaPressed(gcnevt.isMetaPressed());
00266         mouseevt.setX(gcnevt.getX());
00267         mouseevt.setY(gcnevt.getY());
00268 
00269         switch(gcnevt.getType()) {
00270             case gcn::MouseEvent::PRESSED:
00271                 mouseevt.setType(MouseEvent::PRESSED);
00272                 break;
00273             case gcn::MouseEvent::RELEASED:
00274                 mouseevt.setType(MouseEvent::RELEASED);
00275                 break;
00276             case gcn::MouseEvent::MOVED:
00277                 mouseevt.setType(MouseEvent::MOVED);
00278                 break;
00279             case gcn::MouseEvent::CLICKED:
00280                 mouseevt.setType(MouseEvent::CLICKED);
00281                 break;
00282             case gcn::MouseEvent::ENTERED:
00283                 mouseevt.setType(MouseEvent::ENTERED);
00284                 break;
00285             case gcn::MouseEvent::EXITED:
00286                 mouseevt.setType(MouseEvent::EXITED);
00287                 break;
00288             case gcn::MouseEvent::DRAGGED:
00289                 mouseevt.setType(MouseEvent::DRAGGED);
00290                 break;
00291             case gcn::MouseEvent::WHEEL_MOVED_DOWN:
00292                 mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN);
00293                 break;
00294             case gcn::MouseEvent::WHEEL_MOVED_UP:
00295                 mouseevt.setType(MouseEvent::WHEEL_MOVED_UP);
00296                 break;
00297             default:
00298                 mouseevt.setType(MouseEvent::UNKNOWN_EVENT);
00299         }
00300 
00301         switch(gcnevt.getButton()) {
00302             case gcn::MouseInput::LEFT:
00303                 mouseevt.setButton(MouseEvent::LEFT);
00304                 break;
00305             case gcn::MouseInput::RIGHT:
00306                 mouseevt.setButton(MouseEvent::RIGHT);
00307                 break;
00308             case gcn::MouseInput::MIDDLE:
00309                 mouseevt.setButton(MouseEvent::MIDDLE);
00310                 break;
00311             default:
00312                 mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON);
00313                 break;
00314         }
00315         return mouseevt;
00316     }
00317 
00318 
00319     int GUIManager::convertGuichanKeyToFifeKey(int value) {
00320 
00321         switch (value) {
00322             case gcn::Key::TAB:
00323                 value = Key::TAB;
00324                 break;
00325             case gcn::Key::LEFT_ALT:
00326                 value = Key::LEFT_ALT;
00327                 break;
00328             case gcn::Key::RIGHT_ALT:
00329                 value = Key::RIGHT_ALT;
00330                 break;
00331             case gcn::Key::LEFT_SHIFT:
00332                 value = Key::LEFT_SHIFT;
00333                 break;
00334             case gcn::Key::RIGHT_SHIFT:
00335                 value = Key::RIGHT_SHIFT;
00336                 break;
00337             case gcn::Key::LEFT_CONTROL:
00338                 value = Key::LEFT_CONTROL;
00339                 break;
00340             case gcn::Key::RIGHT_CONTROL:
00341                 value = Key::RIGHT_CONTROL;
00342                 break;
00343             case gcn::Key::BACKSPACE:
00344                 value = Key::BACKSPACE;
00345                 break;
00346             case gcn::Key::PAUSE:
00347                 value = Key::PAUSE;
00348                 break;
00349             case gcn::Key::SPACE:
00350                 value = Key::SPACE;
00351                 break;
00352             case gcn::Key::ESCAPE:
00353                 value = Key::ESCAPE;
00354                 break;
00355             case gcn::Key::DELETE:
00356                 value = Key::DELETE;
00357                 break;
00358             case gcn::Key::INSERT:
00359                 value = Key::INSERT;
00360                 break;
00361             case gcn::Key::HOME:
00362                 value = Key::HOME;
00363                 break;
00364             case gcn::Key::END:
00365                 value = Key::END;
00366                 break;
00367             case gcn::Key::PAGE_UP:
00368                 value = Key::PAGE_UP;
00369                 break;
00370             case gcn::Key::PRINT_SCREEN:
00371                 value = Key::PRINT_SCREEN;
00372                 break;
00373             case gcn::Key::PAGE_DOWN:
00374                 value = Key::PAGE_DOWN;
00375                 break;
00376             case gcn::Key::F1:
00377                 value = Key::F1;
00378                 break;
00379             case gcn::Key::F2:
00380                 value = Key::F2;
00381                 break;
00382             case gcn::Key::F3:
00383                 value = Key::F3;
00384                 break;
00385             case gcn::Key::F4:
00386                 value = Key::F4;
00387                 break;
00388             case gcn::Key::F5:
00389                 value = Key::F5;
00390                 break;
00391             case gcn::Key::F6:
00392                 value = Key::F6;
00393                 break;
00394             case gcn::Key::F7:
00395                 value = Key::F7;
00396                 break;
00397             case gcn::Key::F8:
00398                 value = Key::F8;
00399                 break;
00400             case gcn::Key::F9:
00401                 value = Key::F9;
00402                 break;
00403             case gcn::Key::F10:
00404                 value = Key::F10;
00405                 break;
00406             case gcn::Key::F11:
00407                 value = Key::F11;
00408                 break;
00409             case gcn::Key::F12:
00410                 value = Key::F12;
00411                 break;
00412             case gcn::Key::F13:
00413                 value = Key::F13;
00414                 break;
00415             case gcn::Key::F14:
00416                 value = Key::F14;
00417                 break;
00418             case gcn::Key::F15:
00419                 value = Key::F15;
00420                 break;
00421             case gcn::Key::NUM_LOCK:
00422                 value = Key::NUM_LOCK;
00423                 break;
00424             case gcn::Key::CAPS_LOCK:
00425                 value = Key::CAPS_LOCK;
00426                 break;
00427             case gcn::Key::SCROLL_LOCK:
00428                 value = Key::SCROLL_LOCK;
00429                 break;
00430             case gcn::Key::RIGHT_META:
00431                 value = Key::RIGHT_META;
00432                 break;
00433             case gcn::Key::LEFT_META:
00434                 value = Key::LEFT_META;
00435                 break;
00436             case gcn::Key::LEFT_SUPER:
00437                 value = Key::LEFT_SUPER;
00438                 break;
00439             case gcn::Key::RIGHT_SUPER:
00440                 value = Key::RIGHT_SUPER;
00441                 break;
00442             case gcn::Key::ALT_GR:
00443                 value = Key::ALT_GR;
00444                 break;
00445             case gcn::Key::UP:
00446                 value = Key::UP;
00447                 break;
00448             case gcn::Key::DOWN:
00449                 value = Key::DOWN;
00450                 break;
00451             case gcn::Key::LEFT:
00452                 value = Key::LEFT;
00453                 break;
00454             case gcn::Key::RIGHT:
00455                 value = Key::RIGHT;
00456                 break;
00457             case gcn::Key::ENTER:
00458                 value = Key::ENTER;
00459                 break;
00460 
00461             default:
00462                 // Convert from unicode to lowercase letters
00463                 if (value >= 1 && value <= 26) {
00464                     // Control characters
00465                     value = value - 1 + 'a';
00466                 } else if (value >= 'A' && value <= 'Z') {
00467                     value = value - 'A' + 'a';
00468                 }
00469 
00470                 // FIXME: Accented characters (รก) will not get converted properly.
00471                 break;
00472         }
00473 
00474         return value;
00475     }
00476 }