Mercurial > fife-parpg
comparison engine/core/gui/guimanager.cpp @ 697:ecaa4d98f05f tip
Abstracted the GUI code and refactored the GUIChan-specific code into its own module.
* Most of the GUIChan code has been refactored into its own gui/guichan module. However, references to the GuiFont class still persist in the Engine and GuiManager code and these will need further refactoring.
* GuiManager is now an abstract base class which specific implementations (e.g. GUIChan) should subclass.
* The GUIChan GUI code is now a concrete implementation of GuiManager, most of which is in the new GuiChanGuiManager class.
* The GUI code in the Console class has been refactored out of the Console and into the GUIChan module as its own GuiChanConsoleWidget class. The rest of the Console class related to executing commands was left largely unchanged.
* Existing client code may need to downcast the GuiManager pointer received from FIFE::Engine::getGuiManager() to GuiChanGuiManager, since not all functionality is represented in the GuiManager abstract base class. Python client code can use the new GuiChanGuiManager.castTo static method for this purpose.
author | M. George Hansen <technopolitica@gmail.com> |
---|---|
date | Sat, 18 Jun 2011 00:28:40 -1000 |
parents | 5d6b1820b953 |
children |
comparison
equal
deleted
inserted
replaced
696:e201abd8c807 | 697:ecaa4d98f05f |
---|---|
22 // Standard C++ library includes | 22 // Standard C++ library includes |
23 #include <iostream> | 23 #include <iostream> |
24 | 24 |
25 // 3rd party library includes | 25 // 3rd party library includes |
26 #include <boost/filesystem/convenience.hpp> | 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 | 27 |
32 // FIFE includes | 28 // FIFE includes |
33 // These includes are split up in two parts, separated by one empty line | 29 // These includes are split up in two parts, separated by one empty line |
34 // First block: files included from the FIFE root src directory | 30 // First block: files included from the FIFE root src directory |
35 // Second block: files included from the same folder | 31 // Second block: files included from the same folder |
36 #include "util/base/exception.h" | 32 #include "util/base/exception.h" |
37 #include "util/log/logger.h" | 33 #include "util/log/logger.h" |
38 #include "video/renderbackend.h" | 34 #include "video/renderbackend.h" |
39 #include "gui/base/gui_imageloader.h" | 35 #include "video/fonts/subimagefont.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" | 36 #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 | 37 |
38 #include "console.h" | |
39 // FIXME M. George Hansen 2011-06-17: There should be NO references to GuiChan | |
40 // here! | |
41 #include "guichan/gui_font.h" | |
42 #include "guichan/gui_imageloader.h" | |
49 #include "guimanager.h" | 43 #include "guimanager.h" |
50 | 44 |
51 | |
52 namespace FIFE { | 45 namespace FIFE { |
53 static Logger _log(LM_GUI); | 46 GuiManager::GuiManager(ImagePool& pool) : |
54 | 47 m_console_visible(false), |
55 GUIManager::GUIManager(ImagePool& pool) : | 48 m_image_pool(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), | 49 m_console(0), |
62 m_fonts(), | 50 m_fonts(), |
63 m_pool(pool), | 51 m_fontpath(), |
64 m_logic_executed(false) { | 52 m_fontglyphs(), |
65 | 53 m_fontsize() { |
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 } | 54 } |
76 | 55 |
77 GUIManager::~GUIManager() { | 56 GuiManager::~GuiManager() { |
78 delete m_console; | 57 delete m_console; |
79 delete m_gcn_topcontainer; | 58 } |
80 delete m_imgloader; | 59 |
81 delete m_input; | 60 void GuiManager::init(RenderBackend* render_backend, int screenWidth, |
82 delete m_gcn_gui; | 61 int screenHeight) { |
83 std::vector<GuiFont*>::iterator i = m_fonts.begin(); | 62 m_console = new Console(); |
84 while (i != m_fonts.end()) { | 63 } |
85 delete *i; | 64 |
86 ++i; | 65 void GuiManager::toggleConsole() { |
66 if (m_console_visible) { | |
67 hideConsole(); | |
68 } else { | |
69 showConsole(); | |
87 } | 70 } |
88 } | 71 } |
89 | 72 |
90 bool GUIManager::onSdlEvent(SDL_Event& evt) { | 73 GuiFont* GuiManager::createFont(const std::string& path, unsigned int size, |
91 if (!m_input) { | 74 const std::string& glyphs) { |
92 FL_WARN(_log, "GUIManager, GuichanGUI->getInput == 0 ... discarding events!"); | 75 std::string fontpath = path; |
93 return false; | 76 std::string fontglyphs = glyphs; |
77 int fontsize = size; | |
78 | |
79 // Set default settings if necessary | |
80 if (fontpath == "") { | |
81 fontpath = m_fontpath; | |
82 } | |
83 if (fontsize == 0) { | |
84 fontsize = m_fontsize; | |
85 } | |
86 if (fontglyphs == "") { | |
87 fontglyphs = m_fontglyphs; | |
88 } | |
89 | |
90 AbstractFont* font = NULL; | |
91 GuiFont* guifont = NULL; | |
92 if (boost::filesystem::extension(fontpath) == ".ttf") { | |
93 font = new TrueTypeFont(fontpath, fontsize); | |
94 } else { | |
95 font = new SubImageFont(fontpath, fontglyphs, m_image_pool); | |
96 } | |
97 guifont = new GuiFont(font); | |
98 | |
99 m_fonts.push_back(guifont); | |
100 return guifont; | |
94 } | 101 } |
95 | 102 |
96 switch(evt.type) { | 103 void GuiManager::releaseFont(GuiFont* font) { |
97 case SDL_MOUSEBUTTONDOWN: | 104 std::vector<GuiFont*>::iterator i = m_fonts.begin(); |
98 case SDL_MOUSEBUTTONUP: | 105 while (i != m_fonts.end()) { |
99 if( m_gcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) ) { | 106 if ((*i) == font) { |
100 m_input->pushInput(evt); | 107 m_fonts.erase(i); |
101 return true; | 108 delete font; |
109 return; | |
102 } | 110 } |
103 m_focushandler->focusNone(); | 111 ++i; |
104 return false; | 112 } |
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 } | 113 } |
182 | 114 |
183 AbstractFont* font = NULL; | 115 void GuiManager::invalidateFonts() { |
184 GuiFont* guifont = NULL; | 116 std::vector<GuiFont*>::iterator it = m_fonts.begin(); |
185 if( boost::filesystem::extension(fontpath) == ".ttf" ) { | 117 while (it != m_fonts.end()) { |
186 font = new TrueTypeFont(fontpath, fontsize); | 118 (*it)->invalidate(); |
187 } else { | 119 ++it; |
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 } | 120 } |
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 } | 121 } |
226 | 122 |
227 return defaultfont; | 123 GuiFont* GuiManager::setDefaultFont(const std::string& path, |
228 } | 124 unsigned int size, const std::string& glyphs) { |
125 m_fontpath = path; | |
126 m_fontsize = size; | |
127 m_fontglyphs = glyphs; | |
229 | 128 |
230 void GUIManager::turn() { | 129 GuiFont* defaultfont = createFont(); |
231 if (!m_logic_executed) | 130 return defaultfont; |
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 } | 131 } |
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 } | 132 } |