FIFE  2008.0
 All Classes Namespaces Functions Variables Enumerations Enumerator Pages
guimanager.cpp
1 /***************************************************************************
2  * Copyright (C) 2005-2008 by the FIFE team *
3  * http://www.fifengine.de *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <iostream>
24 
25 // 3rd party library includes
26 #include <boost/filesystem/convenience.hpp>
27 #include <guichan/sdl/sdlinput.hpp>
28 #include <guichan/key.hpp>
29 #include <guichan/focushandler.hpp>
30 #include <guichan.hpp>
31 
32 // FIFE includes
33 // These includes are split up in two parts, separated by one empty line
34 // First block: files included from the FIFE root src directory
35 // Second block: files included from the same folder
36 #include "util/base/exception.h"
37 #include "util/log/logger.h"
38 #include "video/renderbackend.h"
39 #include "gui/base/gui_imageloader.h"
40 #include "gui/base/gui_font.h"
41 #include "gui/console/console.h"
42 #include "video/fonts/fontbase.h"
43 #include "video/fonts/truetypefont.h"
44 #include "video/fonts/subimagefont.h"
45 #include "eventchannel/key/ec_key.h"
46 #include "eventchannel/key/ec_keyevent.h"
47 #include "eventchannel/mouse/ec_mouseevent.h"
48 
49 #include "guimanager.h"
50 
51 
52 namespace FIFE {
53  static Logger _log(LM_GUI);
54 
55  GUIManager::GUIManager(ImagePool& pool) :
56  m_gcn_gui(new gcn::Gui()),
57  m_focushandler(0),
58  m_gcn_topcontainer(new gcn::Container()),
59  m_imgloader(new GuiImageLoader(pool)) ,
60  m_input(new gcn::SDLInput()),
61  m_console(0),
62  m_fonts(),
63  m_pool(pool),
64  m_logic_executed(false) {
65 
66  m_gcn_gui->setInput(m_input);
67  gcn::Image::setImageLoader(m_imgloader);
68 
69  m_gcn_gui->setTop(m_gcn_topcontainer);
70  m_focushandler = m_gcn_topcontainer->_getFocusHandler();
71 
72  m_gcn_topcontainer->setOpaque(false);
73  m_gcn_topcontainer->setFocusable(false);
74  m_had_mouse = false;
75  }
76 
77  GUIManager::~GUIManager() {
78  delete m_console;
79  delete m_gcn_topcontainer;
80  delete m_imgloader;
81  delete m_input;
82  delete m_gcn_gui;
83  std::vector<GuiFont*>::iterator i = m_fonts.begin();
84  while (i != m_fonts.end()) {
85  delete *i;
86  ++i;
87  }
88  }
89 
90  bool GUIManager::onSdlEvent(SDL_Event& evt) {
91  if (!m_input) {
92  FL_WARN(_log, "GUIManager, GuichanGUI->getInput == 0 ... discarding events!");
93  return false;
94  }
95 
96  switch(evt.type) {
97  case SDL_MOUSEBUTTONDOWN:
98  case SDL_MOUSEBUTTONUP:
99  if( m_gcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) ) {
100  m_input->pushInput(evt);
101  return true;
102  }
103  m_focushandler->focusNone();
104  return false;
105 
106  case SDL_MOUSEMOTION:
107  if( m_gcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) ) {
108  m_had_mouse = true;
109  m_input->pushInput(evt);
110  return true;
111  }
112  if( m_had_mouse ) {
113  // We only keep the mouse if a widget/window has requested
114  // dragging.
115  m_had_mouse = bool(m_focushandler->getDraggedWidget());
116  m_input->pushInput(evt);
117  return true;
118  }
119  return false;
120 
121  case SDL_KEYDOWN:
122  case SDL_KEYUP:
123  if(m_focushandler->getFocused()) {
124  m_input->pushInput(evt);
125  return true;
126  }
127  return false;
128 
129  case SDL_ACTIVEEVENT:
130  // Actually Guichan doesn't care (it should!)
131  // so at least don't swallow mouse_focus events up.
132  return false;
133 
134  default:
135  return false;
136  }
137  }
138 
139  void GUIManager::resizeTopContainer(unsigned int x, unsigned int y, unsigned int width, unsigned int height) {
140  m_gcn_topcontainer->setDimension(gcn::Rectangle(x, y, width, height));
141  }
142 
143  gcn::Gui* GUIManager::getGuichanGUI() const {
144  return m_gcn_gui;
145  }
146 
147  void GUIManager::add(gcn::Widget* widget) {
148  if( !m_widgets.count(widget) ) {
149  m_gcn_topcontainer->add(widget);
150  m_widgets.insert(widget);
151  }
152  }
153 
154  void GUIManager::remove(gcn::Widget* widget) {
155  if( m_widgets.count(widget) ) {
156  m_widgets.erase(widget);
157  m_gcn_topcontainer->remove(widget);
158  }
159  }
160 
161  void GUIManager::init(gcn::Graphics* graphics, int screenWidth, int screenHeight) {
162  m_gcn_gui->setGraphics(graphics);
163  resizeTopContainer(0, 0, screenWidth, screenHeight);
164  m_console = new Console();
165  }
166 
167  GuiFont* GUIManager::createFont(const std::string& path, unsigned int size, const std::string& glyphs) {
168  std::string fontpath = path;
169  std::string fontglyphs = glyphs;
170  int fontsize = size;
171 
172  // Set default settings if necessary
173  if(fontpath == "") {
174  fontpath = m_fontpath;
175  }
176  if(fontsize == 0) {
177  fontsize = m_fontsize;
178  }
179  if(fontglyphs == "") {
180  fontglyphs = m_fontglyphs;
181  }
182 
183  AbstractFont* font = NULL;
184  GuiFont* guifont = NULL;
185  if( boost::filesystem::extension(fontpath) == ".ttf" ) {
186  font = new TrueTypeFont(fontpath, fontsize);
187  } else {
188  font = new SubImageFont(fontpath, fontglyphs, m_pool);
189  }
190  guifont = new GuiFont(font);
191 
192  m_fonts.push_back(guifont);
193  return guifont;
194  }
195 
196  void GUIManager::releaseFont(GuiFont* font) {
197  std::vector<GuiFont*>::iterator i = m_fonts.begin();
198  while (i != m_fonts.end()) {
199  if ((*i) == font) {
200  m_fonts.erase(i);
201  delete font;
202  return;
203  }
204  ++i;
205  }
206  }
207 
208  void GUIManager::invalidateFonts() {
209  std::vector<GuiFont*>::iterator it = m_fonts.begin();
210  while (it != m_fonts.end()) {
211  (*it)->invalidate();
212  ++it;
213  }
214  }
215 
216  GuiFont* GUIManager::setDefaultFont(const std::string& path, unsigned int size, const std::string& glyphs) {
217  m_fontpath = path;
218  m_fontsize = size;
219  m_fontglyphs = glyphs;
220 
221  GuiFont* defaultfont = createFont();
222  gcn::Widget::setGlobalFont(defaultfont);
223  if (m_console) {
224  m_console->reLayout();
225  }
226 
227  return defaultfont;
228  }
229 
230  void GUIManager::turn() {
231  if (!m_logic_executed)
232  m_gcn_gui->logic();
233  m_logic_executed = false;
234  m_gcn_gui->draw();
235  }
236 
237  KeyEvent GUIManager::translateKeyEvent(const gcn::KeyEvent& gcnevt) {
238  KeyEvent keyevt;
239  if(gcnevt.getType() == gcn::KeyEvent::PRESSED)
240  keyevt.setType(KeyEvent::PRESSED);
241  else if(gcnevt.getType() == gcn::KeyEvent::RELEASED)
242  keyevt.setType(KeyEvent::RELEASED);
243  else
244  throw EventException("Invalid event type in fillKeyEvent");
245  keyevt.setShiftPressed(gcnevt.isShiftPressed());
246  keyevt.setControlPressed(gcnevt.isControlPressed());
247  keyevt.setAltPressed(gcnevt.isAltPressed());
248  keyevt.setMetaPressed(gcnevt.isMetaPressed());
249  keyevt.setNumericPad(gcnevt.isNumericPad());
250 
251  // Convert from guichan keyval to FIFE keyval
252  int keyval = gcnevt.getKey().getValue();
253  keyval = convertGuichanKeyToFifeKey(keyval);
254 
255  keyevt.setKey(Key(static_cast<Key::KeyType>(keyval), keyval));
256 
257  return keyevt;
258  }
259 
260  MouseEvent GUIManager::translateMouseEvent(const gcn::MouseEvent& gcnevt) {
261  MouseEvent mouseevt;
262  mouseevt.setShiftPressed(gcnevt.isShiftPressed());
263  mouseevt.setControlPressed(gcnevt.isControlPressed());
264  mouseevt.setAltPressed(gcnevt.isAltPressed());
265  mouseevt.setMetaPressed(gcnevt.isMetaPressed());
266  mouseevt.setX(gcnevt.getX());
267  mouseevt.setY(gcnevt.getY());
268 
269  switch(gcnevt.getType()) {
270  case gcn::MouseEvent::PRESSED:
271  mouseevt.setType(MouseEvent::PRESSED);
272  break;
273  case gcn::MouseEvent::RELEASED:
274  mouseevt.setType(MouseEvent::RELEASED);
275  break;
276  case gcn::MouseEvent::MOVED:
277  mouseevt.setType(MouseEvent::MOVED);
278  break;
279  case gcn::MouseEvent::CLICKED:
280  mouseevt.setType(MouseEvent::CLICKED);
281  break;
282  case gcn::MouseEvent::ENTERED:
283  mouseevt.setType(MouseEvent::ENTERED);
284  break;
285  case gcn::MouseEvent::EXITED:
286  mouseevt.setType(MouseEvent::EXITED);
287  break;
288  case gcn::MouseEvent::DRAGGED:
289  mouseevt.setType(MouseEvent::DRAGGED);
290  break;
291  case gcn::MouseEvent::WHEEL_MOVED_DOWN:
292  mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN);
293  break;
294  case gcn::MouseEvent::WHEEL_MOVED_UP:
295  mouseevt.setType(MouseEvent::WHEEL_MOVED_UP);
296  break;
297  default:
298  mouseevt.setType(MouseEvent::UNKNOWN_EVENT);
299  }
300 
301  switch(gcnevt.getButton()) {
302  case gcn::MouseInput::LEFT:
303  mouseevt.setButton(MouseEvent::LEFT);
304  break;
305  case gcn::MouseInput::RIGHT:
306  mouseevt.setButton(MouseEvent::RIGHT);
307  break;
308  case gcn::MouseInput::MIDDLE:
309  mouseevt.setButton(MouseEvent::MIDDLE);
310  break;
311  default:
312  mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON);
313  break;
314  }
315  return mouseevt;
316  }
317 
318 
319  int GUIManager::convertGuichanKeyToFifeKey(int value) {
320 
321  switch (value) {
322  case gcn::Key::TAB:
323  value = Key::TAB;
324  break;
325  case gcn::Key::LEFT_ALT:
326  value = Key::LEFT_ALT;
327  break;
328  case gcn::Key::RIGHT_ALT:
329  value = Key::RIGHT_ALT;
330  break;
331  case gcn::Key::LEFT_SHIFT:
332  value = Key::LEFT_SHIFT;
333  break;
334  case gcn::Key::RIGHT_SHIFT:
335  value = Key::RIGHT_SHIFT;
336  break;
337  case gcn::Key::LEFT_CONTROL:
338  value = Key::LEFT_CONTROL;
339  break;
340  case gcn::Key::RIGHT_CONTROL:
341  value = Key::RIGHT_CONTROL;
342  break;
343  case gcn::Key::BACKSPACE:
344  value = Key::BACKSPACE;
345  break;
346  case gcn::Key::PAUSE:
347  value = Key::PAUSE;
348  break;
349  case gcn::Key::SPACE:
350  value = Key::SPACE;
351  break;
352  case gcn::Key::ESCAPE:
353  value = Key::ESCAPE;
354  break;
355  case gcn::Key::DELETE:
356  value = Key::DELETE;
357  break;
358  case gcn::Key::INSERT:
359  value = Key::INSERT;
360  break;
361  case gcn::Key::HOME:
362  value = Key::HOME;
363  break;
364  case gcn::Key::END:
365  value = Key::END;
366  break;
367  case gcn::Key::PAGE_UP:
368  value = Key::PAGE_UP;
369  break;
370  case gcn::Key::PRINT_SCREEN:
371  value = Key::PRINT_SCREEN;
372  break;
373  case gcn::Key::PAGE_DOWN:
374  value = Key::PAGE_DOWN;
375  break;
376  case gcn::Key::F1:
377  value = Key::F1;
378  break;
379  case gcn::Key::F2:
380  value = Key::F2;
381  break;
382  case gcn::Key::F3:
383  value = Key::F3;
384  break;
385  case gcn::Key::F4:
386  value = Key::F4;
387  break;
388  case gcn::Key::F5:
389  value = Key::F5;
390  break;
391  case gcn::Key::F6:
392  value = Key::F6;
393  break;
394  case gcn::Key::F7:
395  value = Key::F7;
396  break;
397  case gcn::Key::F8:
398  value = Key::F8;
399  break;
400  case gcn::Key::F9:
401  value = Key::F9;
402  break;
403  case gcn::Key::F10:
404  value = Key::F10;
405  break;
406  case gcn::Key::F11:
407  value = Key::F11;
408  break;
409  case gcn::Key::F12:
410  value = Key::F12;
411  break;
412  case gcn::Key::F13:
413  value = Key::F13;
414  break;
415  case gcn::Key::F14:
416  value = Key::F14;
417  break;
418  case gcn::Key::F15:
419  value = Key::F15;
420  break;
421  case gcn::Key::NUM_LOCK:
422  value = Key::NUM_LOCK;
423  break;
424  case gcn::Key::CAPS_LOCK:
425  value = Key::CAPS_LOCK;
426  break;
427  case gcn::Key::SCROLL_LOCK:
428  value = Key::SCROLL_LOCK;
429  break;
430  case gcn::Key::RIGHT_META:
431  value = Key::RIGHT_META;
432  break;
433  case gcn::Key::LEFT_META:
434  value = Key::LEFT_META;
435  break;
436  case gcn::Key::LEFT_SUPER:
437  value = Key::LEFT_SUPER;
438  break;
439  case gcn::Key::RIGHT_SUPER:
440  value = Key::RIGHT_SUPER;
441  break;
442  case gcn::Key::ALT_GR:
443  value = Key::ALT_GR;
444  break;
445  case gcn::Key::UP:
446  value = Key::UP;
447  break;
448  case gcn::Key::DOWN:
449  value = Key::DOWN;
450  break;
451  case gcn::Key::LEFT:
452  value = Key::LEFT;
453  break;
454  case gcn::Key::RIGHT:
455  value = Key::RIGHT;
456  break;
457  case gcn::Key::ENTER:
458  value = Key::ENTER;
459  break;
460 
461  default:
462  // Convert from unicode to lowercase letters
463  if (value >= 1 && value <= 26) {
464  // Control characters
465  value = value - 1 + 'a';
466  } else if (value >= 'A' && value <= 'Z') {
467  value = value - 'A' + 'a';
468  }
469 
470  // FIXME: Accented characters (รก) will not get converted properly.
471  break;
472  }
473 
474  return value;
475  }
476 }