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         gcn::SDLInput *input = dynamic_cast<gcn::SDLInput*>(m_gcn_gui->getInput());
00092         if (!input) {
00093             FL_WARN(_log, "GUIManager, GuichanGUI->getInput == 0 ... discarding events!");
00094             return false;
00095         }
00096 
00097         switch(evt.type) {
00098             case SDL_MOUSEBUTTONDOWN:
00099             case SDL_MOUSEBUTTONUP:
00100                 if( m_gcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) ) {
00101                     input->pushInput(evt);
00102                     return true;
00103                 }
00104                 m_focushandler->focusNone();
00105                 return false;
00106 
00107             case SDL_MOUSEMOTION:
00108                 if( m_gcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) ) {
00109                     m_had_mouse = true;
00110                     input->pushInput(evt);
00111                     return true;
00112                 }
00113                 if( m_had_mouse ) {
00114                     // We only keep the mouse if a widget/window has requested
00115                     // dragging.
00116                     m_had_mouse = bool(m_focushandler->getDraggedWidget());
00117                     input->pushInput(evt);
00118                     return true;
00119                 }
00120                 return false;
00121 
00122             case SDL_KEYDOWN:
00123             case SDL_KEYUP:
00124                 if(m_focushandler->getFocused()) {
00125                     input->pushInput(evt);
00126                     return true;
00127                 }
00128                 return false;
00129 
00130             case SDL_ACTIVEEVENT:
00131                 // Actually Guichan doesn't care (it should!)
00132                 // so at least don't swallow mouse_focus events up.
00133                 return false;
00134 
00135             default:
00136                 return false;
00137         }
00138     }
00139 
00140     void GUIManager::resizeTopContainer(unsigned int x, unsigned int y, unsigned int width, unsigned int height) {
00141         m_gcn_topcontainer->setDimension(gcn::Rectangle(x, y, width, height));
00142     }
00143 
00144     gcn::Gui* GUIManager::getGuichanGUI() const {
00145         return m_gcn_gui;
00146     }
00147 
00148     void GUIManager::add(gcn::Widget* widget) {
00149         if( !m_widgets.count(widget) ) {
00150             m_gcn_topcontainer->add(widget);
00151             m_widgets.insert(widget);
00152         }
00153     }
00154 
00155     void GUIManager::remove(gcn::Widget* widget) {
00156         if( m_widgets.count(widget) ) {
00157             m_widgets.erase(widget);
00158             m_gcn_topcontainer->remove(widget);
00159         }
00160     }
00161 
00162     void GUIManager::init(gcn::Graphics* graphics, int screenWidth, int screenHeight) {
00163         m_gcn_gui->setGraphics(graphics);
00164         resizeTopContainer(0, 0, screenWidth, screenHeight);
00165         m_console = new Console();
00166     }
00167 
00168     GuiFont* GUIManager::createFont(const std::string& path, unsigned int size, const std::string& glyphs) {
00169         std::string fontpath = path;
00170         std::string fontglyphs = glyphs;
00171         int fontsize = size;
00172 
00173         // Set default settings if necessary
00174         if(fontpath == "") {
00175             fontpath = m_fontpath;
00176         }
00177         if(fontsize == 0) {
00178             fontsize = m_fontsize;
00179         }
00180         if(fontglyphs == "") {
00181             fontglyphs = m_fontglyphs;
00182         }
00183 
00184         AbstractFont* font = NULL;
00185         GuiFont* guifont = NULL;
00186         if( boost::filesystem::extension(fontpath) == ".ttf" ) {
00187             font = new TrueTypeFont(fontpath, fontsize);
00188         } else {
00189             font = new SubImageFont(fontpath, fontglyphs, m_pool);
00190         }
00191         guifont = new GuiFont(font);
00192         
00193         m_fonts.push_back(guifont);
00194         return guifont;
00195     }
00196 
00197     void GUIManager::releaseFont(GuiFont* font) {
00198         std::vector<GuiFont*>::iterator i = m_fonts.begin();
00199         while (i != m_fonts.end()) {
00200             if ((*i) == font) {
00201                 m_fonts.erase(i);
00202                 delete font;
00203                 return;
00204             }
00205             ++i;
00206         }   
00207     }
00208 
00209     GuiFont* GUIManager::setDefaultFont(const std::string& path, unsigned int size, const std::string& glyphs) {
00210         m_fontpath = path;
00211         m_fontsize = size;
00212         m_fontglyphs = glyphs;
00213 
00214         GuiFont* defaultfont = createFont();
00215         gcn::Widget::setGlobalFont(defaultfont);
00216         if (m_console) {
00217             m_console->reLayout();
00218         }
00219 
00220         return defaultfont;
00221     }
00222 
00223     void GUIManager::turn() {
00224         if (!m_logic_executed)
00225             m_gcn_gui->logic();
00226         m_logic_executed = false;
00227         m_gcn_gui->draw();
00228     }
00229 
00230     KeyEvent GUIManager::translateKeyEvent(const gcn::KeyEvent& gcnevt) {
00231         KeyEvent keyevt;
00232         if(gcnevt.getType() == gcn::KeyEvent::PRESSED)
00233             keyevt.setType(KeyEvent::PRESSED);
00234         else if(gcnevt.getType() == gcn::KeyEvent::RELEASED)
00235             keyevt.setType(KeyEvent::RELEASED);
00236         else
00237             throw EventException("Invalid event type in fillKeyEvent");
00238         keyevt.setShiftPressed(gcnevt.isShiftPressed());
00239         keyevt.setControlPressed(gcnevt.isControlPressed());
00240         keyevt.setAltPressed(gcnevt.isAltPressed());
00241         keyevt.setMetaPressed(gcnevt.isMetaPressed());
00242         keyevt.setNumericPad(gcnevt.isNumericPad());
00243 
00244         // Convert from guichan keyval to FIFE keyval
00245         int keyval = gcnevt.getKey().getValue();
00246         keyval = convertGuichanKeyToFifeKey(keyval);
00247         
00248         keyevt.setKey(Key(static_cast<Key::KeyType>(keyval), keyval));
00249 
00250         return keyevt;
00251     }
00252 
00253     MouseEvent GUIManager::translateMouseEvent(const gcn::MouseEvent& gcnevt) {
00254         MouseEvent mouseevt;
00255         mouseevt.setShiftPressed(gcnevt.isShiftPressed());
00256         mouseevt.setControlPressed(gcnevt.isControlPressed());
00257         mouseevt.setAltPressed(gcnevt.isAltPressed());
00258         mouseevt.setMetaPressed(gcnevt.isMetaPressed());
00259         mouseevt.setX(gcnevt.getX());
00260         mouseevt.setY(gcnevt.getY());
00261 
00262         switch(gcnevt.getType()) {
00263             case gcn::MouseEvent::PRESSED:
00264                 mouseevt.setType(MouseEvent::PRESSED);
00265                 break;
00266             case gcn::MouseEvent::RELEASED:
00267                 mouseevt.setType(MouseEvent::RELEASED);
00268                 break;
00269             case gcn::MouseEvent::MOVED:
00270                 mouseevt.setType(MouseEvent::MOVED);
00271                 break;
00272             case gcn::MouseEvent::CLICKED:
00273                 mouseevt.setType(MouseEvent::CLICKED);
00274                 break;
00275             case gcn::MouseEvent::ENTERED:
00276                 mouseevt.setType(MouseEvent::ENTERED);
00277                 break;
00278             case gcn::MouseEvent::EXITED:
00279                 mouseevt.setType(MouseEvent::EXITED);
00280                 break;
00281             case gcn::MouseEvent::DRAGGED:
00282                 mouseevt.setType(MouseEvent::DRAGGED);
00283                 break;
00284             case gcn::MouseEvent::WHEEL_MOVED_DOWN:
00285                 mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN);
00286                 break;
00287             case gcn::MouseEvent::WHEEL_MOVED_UP:
00288                 mouseevt.setType(MouseEvent::WHEEL_MOVED_UP);
00289                 break;
00290             default:
00291                 mouseevt.setType(MouseEvent::UNKNOWN_EVENT);
00292         }
00293 
00294         switch(gcnevt.getButton()) {
00295             case gcn::MouseInput::LEFT:
00296                 mouseevt.setButton(MouseEvent::LEFT);
00297                 break;
00298             case gcn::MouseInput::RIGHT:
00299                 mouseevt.setButton(MouseEvent::RIGHT);
00300                 break;
00301             case gcn::MouseInput::MIDDLE:
00302                 mouseevt.setButton(MouseEvent::MIDDLE);
00303                 break;
00304             default:
00305                 mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON);
00306                 break;
00307         }
00308         return mouseevt;
00309     }
00310 
00311 
00312     int GUIManager::convertGuichanKeyToFifeKey(int value) {
00313 
00314         switch (value) {
00315             case gcn::Key::TAB:
00316                 value = Key::TAB;
00317                 break;
00318             case gcn::Key::LEFT_ALT:
00319                 value = Key::LEFT_ALT;
00320                 break;
00321             case gcn::Key::RIGHT_ALT:
00322                 value = Key::RIGHT_ALT;
00323                 break;
00324             case gcn::Key::LEFT_SHIFT:
00325                 value = Key::LEFT_SHIFT;
00326                 break;
00327             case gcn::Key::RIGHT_SHIFT:
00328                 value = Key::RIGHT_SHIFT;
00329                 break;
00330             case gcn::Key::LEFT_CONTROL:
00331                 value = Key::LEFT_CONTROL;
00332                 break;
00333             case gcn::Key::RIGHT_CONTROL:
00334                 value = Key::RIGHT_CONTROL;
00335                 break;
00336             case gcn::Key::BACKSPACE:
00337                 value = Key::BACKSPACE;
00338                 break;
00339             case gcn::Key::PAUSE:
00340                 value = Key::PAUSE;
00341                 break;
00342             case gcn::Key::SPACE:
00343                 value = Key::SPACE;
00344                 break;
00345             case gcn::Key::ESCAPE:
00346                 value = Key::ESCAPE;
00347                 break;
00348             case gcn::Key::DELETE:
00349                 value = Key::DELETE;
00350                 break;
00351             case gcn::Key::INSERT:
00352                 value = Key::INSERT;
00353                 break;
00354             case gcn::Key::HOME:
00355                 value = Key::HOME;
00356                 break;
00357             case gcn::Key::END:
00358                 value = Key::END;
00359                 break;
00360             case gcn::Key::PAGE_UP:
00361                 value = Key::PAGE_UP;
00362                 break;
00363             case gcn::Key::PRINT_SCREEN:
00364                 value = Key::PRINT_SCREEN;
00365                 break;
00366             case gcn::Key::PAGE_DOWN:
00367                 value = Key::PAGE_DOWN;
00368                 break;
00369             case gcn::Key::F1:
00370                 value = Key::F1;
00371                 break;
00372             case gcn::Key::F2:
00373                 value = Key::F2;
00374                 break;
00375             case gcn::Key::F3:
00376                 value = Key::F3;
00377                 break;
00378             case gcn::Key::F4:
00379                 value = Key::F4;
00380                 break;
00381             case gcn::Key::F5:
00382                 value = Key::F5;
00383                 break;
00384             case gcn::Key::F6:
00385                 value = Key::F6;
00386                 break;
00387             case gcn::Key::F7:
00388                 value = Key::F7;
00389                 break;
00390             case gcn::Key::F8:
00391                 value = Key::F8;
00392                 break;
00393             case gcn::Key::F9:
00394                 value = Key::F9;
00395                 break;
00396             case gcn::Key::F10:
00397                 value = Key::F10;
00398                 break;
00399             case gcn::Key::F11:
00400                 value = Key::F11;
00401                 break;
00402             case gcn::Key::F12:
00403                 value = Key::F12;
00404                 break;
00405             case gcn::Key::F13:
00406                 value = Key::F13;
00407                 break;
00408             case gcn::Key::F14:
00409                 value = Key::F14;
00410                 break;
00411             case gcn::Key::F15:
00412                 value = Key::F15;
00413                 break;
00414             case gcn::Key::NUM_LOCK:
00415                 value = Key::NUM_LOCK;
00416                 break;
00417             case gcn::Key::CAPS_LOCK:
00418                 value = Key::CAPS_LOCK;
00419                 break;
00420             case gcn::Key::SCROLL_LOCK:
00421                 value = Key::SCROLL_LOCK;
00422                 break;
00423             case gcn::Key::RIGHT_META:
00424                 value = Key::RIGHT_META;
00425                 break;
00426             case gcn::Key::LEFT_META:
00427                 value = Key::LEFT_META;
00428                 break;
00429             case gcn::Key::LEFT_SUPER:
00430                 value = Key::LEFT_SUPER;
00431                 break;
00432             case gcn::Key::RIGHT_SUPER:
00433                 value = Key::RIGHT_SUPER;
00434                 break;
00435             case gcn::Key::ALT_GR:
00436                 value = Key::ALT_GR;
00437                 break;
00438             case gcn::Key::UP:
00439                 value = Key::UP;
00440                 break;
00441             case gcn::Key::DOWN:
00442                 value = Key::DOWN;
00443                 break;
00444             case gcn::Key::LEFT:
00445                 value = Key::LEFT;
00446                 break;
00447             case gcn::Key::RIGHT:
00448                 value = Key::RIGHT;
00449                 break;
00450             case gcn::Key::ENTER:
00451                 value = Key::ENTER;
00452                 break;
00453 
00454             default:
00455                 // Convert from unicode to lowercase letters
00456                 if (value >= 1 && value <= 26) {
00457                     // Control characters
00458                     value = value - 1 + 'a';
00459                 } else if (value >= 'A' && value <= 'Z') {
00460                     value = value - 'A' + 'a';
00461                 }
00462 
00463                 // FIXME: Accented characters (á) will not get converted properly.
00464                 break;
00465         }
00466 
00467         return value;
00468     }
00469 }
Generated by  doxygen 1.6.2-20100208