FIFE  2008.0
guichanmanager.cpp
1 /***************************************************************************
2  * Copyright (C) 2005-2011 by the FIFE team *
3  * http://www.fifengine.net *
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 
24 // 3rd party library includes
25 #include <guichan/sdl/sdlinput.hpp>
26 #include <guichan/key.hpp>
27 #include <guichan/focushandler.hpp>
28 #include <guichan.hpp>
29 
30 // FIFE includes
31 // These includes are split up in two parts, separated by one empty line
32 // First block: files included from the FIFE root src directory
33 // Second block: files included from the same folder
34 #ifdef HAVE_OPENGL
35 #include "gui/guichan/base/opengl/opengl_gui_graphics.h"
36 #include "gui/guichan/base/opengle/opengle_gui_graphics.h"
37 #endif
38 #include "gui/guichan/base/sdl/sdl_gui_graphics.h"
39 #include "util/base/exception.h"
40 #include "util/log/logger.h"
41 #include "video/renderbackend.h"
42 #include "gui/guichan/base/gui_imageloader.h"
43 #include "gui/guichan/base/gui_font.h"
44 #include "gui/guichan/console/console.h"
45 #include "video/fonts/fontbase.h"
46 #include "video/fonts/truetypefont.h"
47 #include "video/fonts/subimagefont.h"
48 #include "eventchannel/key/ec_key.h"
49 #include "eventchannel/key/ec_keyevent.h"
50 #include "eventchannel/mouse/ec_mouseevent.h"
51 #include "vfs/fife_boost_filesystem.h"
52 
53 #include "guichanmanager.h"
54 
55 namespace FIFE {
56  static Logger _log(LM_GUI);
57 
58  GUIChanManager::GUIChanManager() :
59  m_gcn_gui(new gcn::Gui()),
60  m_focushandler(0),
61  m_gcn_topcontainer(new gcn::Container()),
62  m_imgloader(new GuiImageLoader()) ,
63  m_input(new gcn::SDLInput()),
64  m_console(0),
65  m_defaultfont(0),
66  m_fonts(),
67  m_logic_executed(false) {
68 
69  m_gcn_gui->setInput(m_input);
70  gcn::Image::setImageLoader(m_imgloader);
71 
72  m_gcn_gui->setTop(m_gcn_topcontainer);
73  m_focushandler = m_gcn_topcontainer->_getFocusHandler();
74 
75  m_gcn_topcontainer->setOpaque(false);
76  m_gcn_topcontainer->setFocusable(false);
77  m_had_mouse = false;
78  m_had_widget = false;
79  }
80 
81  GUIChanManager::~GUIChanManager() {
82  delete m_console;
83  delete m_gcn_topcontainer;
84  delete m_imgloader;
85  delete m_input;
86  delete m_gcn_gui;
87  delete m_gui_graphics;
88  std::vector<GuiFont*>::iterator i = m_fonts.begin();
89  while (i != m_fonts.end()) {
90  delete *i;
91  ++i;
92  }
93  }
94 
95  bool GUIChanManager::onSdlEvent(SDL_Event& evt) {
96  if (!m_input) {
97  FL_WARN(_log, "GUIChanManager, GuichanGUI->getInput == 0 ... discarding events!");
98  return false;
99  }
100 
101  bool overWidget = m_gcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) != 0;
102 
103  switch(evt.type) {
104  case SDL_MOUSEBUTTONDOWN:
105  m_had_widget = overWidget;
106  case SDL_MOUSEBUTTONUP:
107  // Always send the button up/down events to guichan
108  m_input->pushInput(evt);
109 
110  // Button was pressed over a widget and still is over a widget
111  // so we mark the event as processed.
112  if( m_had_widget && overWidget ) {
113  return true;
114  }
115 
116  // Button wasn't pressed over a widget so we want to release focus
117  // no matter what.
118  if (!m_had_widget) {
119  m_focushandler->focusNone();
120  }
121 
122  // Button up was processed by guichan but there was no widget under
123  // the mouse at the time. Don't mark it as processed here so the
124  // other listeners have a chance to process the event.
125  return false;
126 
127  case SDL_MOUSEMOTION:
128  if( m_gcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) ) {
129  m_had_mouse = true;
130  m_input->pushInput(evt);
131  return true;
132  }
133  if( m_had_mouse ) {
134  // We only keep the mouse if a widget/window has requested
135  // dragging.
136  m_had_mouse = m_focushandler->getDraggedWidget() != 0;
137  m_input->pushInput(evt);
138  return true;
139  }
140  return false;
141 
142  case SDL_KEYDOWN:
143  case SDL_KEYUP:
144  if(m_focushandler->getFocused()) {
145  m_input->pushInput(evt);
146  return true;
147  }
148  return false;
149 
150  case SDL_ACTIVEEVENT:
151  // Actually Guichan doesn't care (it should!)
152  // so at least don't swallow mouse_focus events up.
153  return false;
154 
155  default:
156  return false;
157  }
158  }
159 
160  void GUIChanManager::resizeTopContainer(uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
161  m_gcn_topcontainer->setDimension(gcn::Rectangle(x, y, width, height));
162  this->invalidateFonts();
163  this->m_console->reLayout();
164  }
165 
166  gcn::Gui* GUIChanManager::getGuichanGUI() const {
167  return m_gcn_gui;
168  }
169 
170  void GUIChanManager::add(gcn::Widget* widget) {
171  if( !m_widgets.count(widget) ) {
172  m_gcn_topcontainer->add(widget);
173  m_widgets.insert(widget);
174  }
175  }
176 
177  void GUIChanManager::remove(gcn::Widget* widget) {
178  if( m_widgets.count(widget) ) {
179  m_widgets.erase(widget);
180  m_gcn_topcontainer->remove(widget);
181  }
182  }
183 
184  void GUIChanManager::init(const std::string& backend, int32_t screenWidth, int32_t screenHeight) {
185  if( backend == "SDL" ) {
186  m_gui_graphics = new SdlGuiGraphics();
187  }
188  else if (backend == "OpenGL") {
189  m_gui_graphics = new OpenGLGuiGraphics();
190  }
191  else if (backend == "OpenGLe") {
192  m_gui_graphics = new OpenGLeGuiGraphics();
193  } else {
194  //should never get here
195  assert(0);
196  }
197 
198  m_gcn_gui->setGraphics(m_gui_graphics);
199  m_console = new Console();
200 
201  resizeTopContainer(0, 0, screenWidth, screenHeight);
202  }
203 
204  GuiFont* GUIChanManager::createFont(const std::string& path, uint32_t size, const std::string& glyphs) {
205  std::string fontpath = path;
206  std::string fontglyphs = glyphs;
207  int32_t fontsize = size;
208 
209  // Set default settings if necessary
210  if(fontpath == "") {
211  fontpath = m_fontpath;
212  }
213  if(fontsize == 0) {
214  fontsize = m_fontsize;
215  }
216  if(fontglyphs == "") {
217  fontglyphs = m_fontglyphs;
218  }
219 
220  IFont* font = NULL;
221  GuiFont* guifont = NULL;
222  if( bfs::extension(fontpath) == ".ttf" || bfs::extension(fontpath) == ".ttc" ) {
223  font = new TrueTypeFont(fontpath, fontsize);
224  } else {
225  font = new SubImageFont(fontpath, fontglyphs);
226  }
227  guifont = new GuiFont(font);
228 
229  m_fonts.push_back(guifont);
230  return guifont;
231  }
232 
233  void GUIChanManager::releaseFont(GuiFont* font) {
234  std::vector<GuiFont*>::iterator i = m_fonts.begin();
235  while (i != m_fonts.end()) {
236  if ((*i) == font) {
237  m_fonts.erase(i);
238  delete font;
239  return;
240  }
241  ++i;
242  }
243  }
244 
245  void GUIChanManager::invalidateFonts() {
246  std::vector<GuiFont*>::iterator it = m_fonts.begin();
247  while (it != m_fonts.end()) {
248  (*it)->invalidate();
249  ++it;
250  }
251  }
252 
253  GuiFont* GUIChanManager::setDefaultFont(const std::string& path, uint32_t size, const std::string& glyphs) {
254  m_fontpath = path;
255  m_fontsize = size;
256  m_fontglyphs = glyphs;
257 
258  m_defaultfont = createFont();
259  gcn::Widget::setGlobalFont(m_defaultfont);
260  if (m_console) {
261  m_console->reLayout();
262  }
263 
264  return m_defaultfont;
265  }
266 
267  void GUIChanManager::turn() {
268  if (!m_logic_executed)
269  m_gcn_gui->logic();
270  m_logic_executed = false;
271  m_gcn_gui->draw();
272  }
273 
274  KeyEvent GUIChanManager::translateKeyEvent(const gcn::KeyEvent& gcnevt) {
275  KeyEvent keyevt;
276  if(gcnevt.getType() == gcn::KeyEvent::PRESSED)
277  keyevt.setType(KeyEvent::PRESSED);
278  else if(gcnevt.getType() == gcn::KeyEvent::RELEASED)
279  keyevt.setType(KeyEvent::RELEASED);
280  else {
281  FL_WARN(_log, LMsg("GUIChanManager::translateKeyEvent() - ") << "Unknown event type: " << gcnevt.getType());
282  keyevt.setType(KeyEvent::UNKNOWN);
283  }
284  keyevt.setShiftPressed(gcnevt.isShiftPressed());
285  keyevt.setControlPressed(gcnevt.isControlPressed());
286  keyevt.setAltPressed(gcnevt.isAltPressed());
287  keyevt.setMetaPressed(gcnevt.isMetaPressed());
288  keyevt.setNumericPad(gcnevt.isNumericPad());
289 
290  // Convert from guichan keyval to FIFE keyval
291  int32_t keyval = gcnevt.getKey().getValue();
292  keyval = convertGuichanKeyToFifeKey(keyval);
293 
294  keyevt.setKey(Key(static_cast<Key::KeyType>(keyval), keyval));
295 
296  return keyevt;
297  }
298 
299  MouseEvent GUIChanManager::translateMouseEvent(const gcn::MouseEvent& gcnevt) {
300  MouseEvent mouseevt;
301  mouseevt.setShiftPressed(gcnevt.isShiftPressed());
302  mouseevt.setControlPressed(gcnevt.isControlPressed());
303  mouseevt.setAltPressed(gcnevt.isAltPressed());
304  mouseevt.setMetaPressed(gcnevt.isMetaPressed());
305  mouseevt.setX(gcnevt.getX());
306  mouseevt.setY(gcnevt.getY());
307 
308  switch(gcnevt.getType()) {
309  case gcn::MouseEvent::PRESSED:
310  mouseevt.setType(MouseEvent::PRESSED);
311  break;
312  case gcn::MouseEvent::RELEASED:
313  mouseevt.setType(MouseEvent::RELEASED);
314  break;
315  case gcn::MouseEvent::MOVED:
316  mouseevt.setType(MouseEvent::MOVED);
317  break;
318  case gcn::MouseEvent::CLICKED:
319  mouseevt.setType(MouseEvent::CLICKED);
320  break;
321  case gcn::MouseEvent::ENTERED:
322  mouseevt.setType(MouseEvent::ENTERED);
323  break;
324  case gcn::MouseEvent::EXITED:
325  mouseevt.setType(MouseEvent::EXITED);
326  break;
327  case gcn::MouseEvent::DRAGGED:
328  mouseevt.setType(MouseEvent::DRAGGED);
329  break;
330  case gcn::MouseEvent::WHEEL_MOVED_DOWN:
331  mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN);
332  break;
333  case gcn::MouseEvent::WHEEL_MOVED_UP:
334  mouseevt.setType(MouseEvent::WHEEL_MOVED_UP);
335  break;
336  default:
337  mouseevt.setType(MouseEvent::UNKNOWN_EVENT);
338  }
339 
340  switch(gcnevt.getButton()) {
341  case gcn::MouseInput::LEFT:
342  mouseevt.setButton(MouseEvent::LEFT);
343  break;
344  case gcn::MouseInput::RIGHT:
345  mouseevt.setButton(MouseEvent::RIGHT);
346  break;
347  case gcn::MouseInput::MIDDLE:
348  mouseevt.setButton(MouseEvent::MIDDLE);
349  break;
350  default:
351  mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON);
352  break;
353  }
354  return mouseevt;
355  }
356 
357 
358  int32_t GUIChanManager::convertGuichanKeyToFifeKey(int32_t value) {
359 
360  switch (value) {
361  case gcn::Key::TAB:
362  value = Key::TAB;
363  break;
364  case gcn::Key::LEFT_ALT:
365  value = Key::LEFT_ALT;
366  break;
367  case gcn::Key::RIGHT_ALT:
368  value = Key::RIGHT_ALT;
369  break;
370  case gcn::Key::LEFT_SHIFT:
371  value = Key::LEFT_SHIFT;
372  break;
373  case gcn::Key::RIGHT_SHIFT:
374  value = Key::RIGHT_SHIFT;
375  break;
376  case gcn::Key::LEFT_CONTROL:
377  value = Key::LEFT_CONTROL;
378  break;
379  case gcn::Key::RIGHT_CONTROL:
380  value = Key::RIGHT_CONTROL;
381  break;
382  case gcn::Key::BACKSPACE:
383  value = Key::BACKSPACE;
384  break;
385  case gcn::Key::PAUSE:
386  value = Key::PAUSE;
387  break;
388  case gcn::Key::SPACE:
389  value = Key::SPACE;
390  break;
391  case gcn::Key::ESCAPE:
392  value = Key::ESCAPE;
393  break;
394  case gcn::Key::DELETE:
395  value = Key::DELETE;
396  break;
397  case gcn::Key::INSERT:
398  value = Key::INSERT;
399  break;
400  case gcn::Key::HOME:
401  value = Key::HOME;
402  break;
403  case gcn::Key::END:
404  value = Key::END;
405  break;
406  case gcn::Key::PAGE_UP:
407  value = Key::PAGE_UP;
408  break;
409  case gcn::Key::PRINT_SCREEN:
410  value = Key::PRINT_SCREEN;
411  break;
412  case gcn::Key::PAGE_DOWN:
413  value = Key::PAGE_DOWN;
414  break;
415  case gcn::Key::F1:
416  value = Key::F1;
417  break;
418  case gcn::Key::F2:
419  value = Key::F2;
420  break;
421  case gcn::Key::F3:
422  value = Key::F3;
423  break;
424  case gcn::Key::F4:
425  value = Key::F4;
426  break;
427  case gcn::Key::F5:
428  value = Key::F5;
429  break;
430  case gcn::Key::F6:
431  value = Key::F6;
432  break;
433  case gcn::Key::F7:
434  value = Key::F7;
435  break;
436  case gcn::Key::F8:
437  value = Key::F8;
438  break;
439  case gcn::Key::F9:
440  value = Key::F9;
441  break;
442  case gcn::Key::F10:
443  value = Key::F10;
444  break;
445  case gcn::Key::F11:
446  value = Key::F11;
447  break;
448  case gcn::Key::F12:
449  value = Key::F12;
450  break;
451  case gcn::Key::F13:
452  value = Key::F13;
453  break;
454  case gcn::Key::F14:
455  value = Key::F14;
456  break;
457  case gcn::Key::F15:
458  value = Key::F15;
459  break;
460  case gcn::Key::NUM_LOCK:
461  value = Key::NUM_LOCK;
462  break;
463  case gcn::Key::CAPS_LOCK:
464  value = Key::CAPS_LOCK;
465  break;
466  case gcn::Key::SCROLL_LOCK:
467  value = Key::SCROLL_LOCK;
468  break;
469  case gcn::Key::RIGHT_META:
470  value = Key::RIGHT_META;
471  break;
472  case gcn::Key::LEFT_META:
473  value = Key::LEFT_META;
474  break;
475  case gcn::Key::LEFT_SUPER:
476  value = Key::LEFT_SUPER;
477  break;
478  case gcn::Key::RIGHT_SUPER:
479  value = Key::RIGHT_SUPER;
480  break;
481  case gcn::Key::ALT_GR:
482  value = Key::ALT_GR;
483  break;
484  case gcn::Key::UP:
485  value = Key::UP;
486  break;
487  case gcn::Key::DOWN:
488  value = Key::DOWN;
489  break;
490  case gcn::Key::LEFT:
491  value = Key::LEFT;
492  break;
493  case gcn::Key::RIGHT:
494  value = Key::RIGHT;
495  break;
496  case gcn::Key::ENTER:
497  value = Key::ENTER;
498  break;
499 
500  default:
501  // Convert from unicode to lowercase letters
502  if (value >= 1 && value <= 26) {
503  // Control characters
504  value = value - 1 + 'a';
505  } else if (value >= 'A' && value <= 'Z') {
506  value = value - 'A' + 'a';
507  }
508 
509  // FIXME: Accented characters (รก) will not get converted properly.
510  break;
511  }
512 
513  return value;
514  }
515 }
credit to phoku for his NodeDisplay example which the visitor code is adapted from ( he coded the qua...
Definition: soundclip.cpp:39