Mercurial > fife-parpg
changeset 157:bb9902910067
input_rework merged!
Bad features:
* Broken DND for zero-projekt.
* Design short-comings.
line wrap: on
line diff
--- a/clients/editor/listener.py Sun Oct 12 20:30:09 2008 +0000 +++ b/clients/editor/listener.py Tue Oct 14 07:41:48 2008 +0000 @@ -3,21 +3,14 @@ import fife class EditorListener(fife.IKeyListener, fife.ICommandListener, fife.IMouseListener, - fife.ConsoleExecuter, fife.IWidgetListener): + fife.ConsoleExecuter): def __init__(self, app): self.app = app engine = app.engine eventmanager = engine.getEventManager() - eventmanager.setNonConsumableKeys([ - fife.Key.ESCAPE, - fife.Key.F10, - fife.Key.F9, - fife.Key.F8, - fife.Key.TAB, - fife.Key.LEFT, - fife.Key.RIGHT, - fife.Key.UP, - fife.Key.DOWN]) + #eventmanager.setNonConsumableKeys([ + #fife.Key.ESCAPE, + #fife.Key.TAB,]) fife.IKeyListener.__init__(self) eventmanager.addKeyListener(self) @@ -27,8 +20,6 @@ eventmanager.addMouseListener(self) fife.ConsoleExecuter.__init__(self) engine.getGuiManager().getConsole().setConsoleExecuter(self) - fife.IWidgetListener.__init__(self) - eventmanager.addWidgetListener(self) self.engine = engine self.showTileOutline = True
--- a/clients/editor/plugins/mapeditor.py Sun Oct 12 20:30:09 2008 +0000 +++ b/clients/editor/plugins/mapeditor.py Tue Oct 14 07:41:48 2008 +0000 @@ -124,11 +124,11 @@ def __init__(self, engine): self._engine = engine eventmanager = self._engine.getEventManager() - eventmanager.setNonConsumableKeys([ - fife.Key.LEFT, - fife.Key.RIGHT, - fife.Key.UP, - fife.Key.DOWN]) + #eventmanager.setNonConsumableKeys([ + #fife.Key.LEFT, + #fife.Key.RIGHT, + #fife.Key.UP, + #fife.Key.DOWN]) fife.IMouseListener.__init__(self) eventmanager.addMouseListener(self) fife.IKeyListener.__init__(self)
--- a/clients/pychan_demo/dynamic.py Sun Oct 12 20:30:09 2008 +0000 +++ b/clients/pychan_demo/dynamic.py Tue Oct 14 07:41:48 2008 +0000 @@ -19,15 +19,35 @@ from pychan_test import PyChanExample +class Test(object): + def __init__(self,button,text1,text2): + super(Test,self).__init__() + self.button = button + self.text1 = text1 + self.text2 = text2 + self.button.text = text1 + + def mouseEntered(self, event): + print event + self.button.text = self.text2 + + def mouseExited(self, event): + print event + self.button.text = self.text1 + + class DynamicExample(PyChanExample): def __init__(self): super(DynamicExample,self).__init__('gui/dynamic.xml') def start(self): self.widget = pychan.loadXML(self.xmlFile) + self.l = Test(self.widget.findChild(name="okButton"),"Ok?","Ok!") self.widget.mapEvents({ 'okButton' :self.stop, 'addButton' :self.addLabel, + 'okButton/mouseEntered' : self.l.mouseEntered, + 'okButton/mouseExited' : self.l.mouseExited }) self.labelBox = self.widget.findChild(name="labelBox") self.widget.show()
--- a/clients/pychan_demo/pychan_test.py Sun Oct 12 20:30:09 2008 +0000 +++ b/clients/pychan_demo/pychan_test.py Tue Oct 14 07:41:48 2008 +0000 @@ -52,6 +52,9 @@ 'slider': self.test_slider } self.gui.mapEvents(eventMap) + credits = self.gui.findChild(name="creditsLink") + credits.setEnterCallback(lambda w : credits._setText("CREDITS")) + credits.capture(lambda : credits._setText("Credits"), event_name="mouseExited") from dynamic import DynamicExample from styling import StylingExample @@ -82,7 +85,6 @@ def showCredits(self): print pychan.loadXML('gui/credits.xml').execute({ 'okButton' : "Yay!" }) - def test_slider(self): self.slider_value._setText( str(self.slider.getValue()) )
--- a/clients/rio_de_hola/run.py Sun Oct 12 20:30:09 2008 +0000 +++ b/clients/rio_de_hola/run.py Tue Oct 14 07:41:48 2008 +0000 @@ -15,6 +15,7 @@ if not os.path.exists('settings.xml'): shutil.copyfile('settings-dist.xml', 'settings.xml') +import fife_compat import fife, fifelog from scripts import world from scripts.common import eventlistenerbase @@ -31,12 +32,7 @@ self.engine = engine self.world = world engine.getEventManager().setNonConsumableKeys([ - fife.Key.ESCAPE, - fife.Key.F10, - fife.Key.LEFT, - fife.Key.RIGHT, - fife.Key.UP, - fife.Key.DOWN]) + fife.Key.ESCAPE,]) self.quit = False self.aboutWindow = None @@ -50,6 +46,7 @@ self.rootpanel.show() def keyPressed(self, evt): + print evt keyval = evt.getKey().getValue() keystr = evt.getKey().getAsString().lower() consumed = False
--- a/clients/rio_de_hola/scripts/common/eventlistenerbase.py Sun Oct 12 20:30:09 2008 +0000 +++ b/clients/rio_de_hola/scripts/common/eventlistenerbase.py Tue Oct 14 07:41:48 2008 +0000 @@ -1,6 +1,6 @@ import fife -class EventListenerBase(fife.IKeyListener, fife.ICommandListener, fife.IMouseListener, fife.ConsoleExecuter, fife.IWidgetListener): +class EventListenerBase(fife.IKeyListener, fife.ICommandListener, fife.IMouseListener, fife.ConsoleExecuter): def __init__(self, engine, regKeys=False, regCmd=False, regMouse=False, regConsole=False, regWidget=False): self.eventmanager = engine.getEventManager() @@ -16,9 +16,6 @@ fife.ConsoleExecuter.__init__(self) if regConsole: engine.getGuiManager().getConsole().setConsoleExecuter(self) - fife.IWidgetListener.__init__(self) - if regWidget: - self.eventmanager.addWidgetListener(self) def mousePressed(self, evt):
--- a/doc/dependencies/dirdeps.dot Sun Oct 12 20:30:09 2008 +0000 +++ b/doc/dependencies/dirdeps.dot Tue Oct 14 07:41:48 2008 +0000 @@ -30,7 +30,7 @@ style=filled; color=lightgrey; node [style=filled,color=white]; - "eventchannel"; "eventchannel/base"; "eventchannel/command"; "eventchannel/key"; "eventchannel/mouse"; "eventchannel/sdl"; "eventchannel/source"; "eventchannel/trigger"; "eventchannel/widget" + "eventchannel"; "eventchannel/base"; "eventchannel/command"; "eventchannel/key"; "eventchannel/mouse"; "eventchannel/sdl"; "eventchannel/source"; "eventchannel/trigger" label = "eventchannel"; } subgraph cluster_4 { @@ -124,18 +124,15 @@ "eventchannel" -> "eventchannel/mouse" "eventchannel" -> "eventchannel/sdl" "eventchannel" -> "eventchannel/trigger" - "eventchannel" -> "eventchannel/widget" "eventchannel" -> "util/base" "eventchannel/base" -> "eventchannel/source" "eventchannel/command" -> "eventchannel/base" "eventchannel/key" -> "eventchannel/base" "eventchannel/key" -> "eventchannel/source" "eventchannel/mouse" -> "eventchannel/base" - "eventchannel/widget" -> "eventchannel/base" "gui" -> "eventchannel/key" "gui" -> "eventchannel/mouse" "gui" -> "eventchannel/sdl" - "gui" -> "eventchannel/widget" "gui" -> "gui/base" "gui" -> "gui/console" "gui" -> "util/base"
--- a/doc/dependencies/filedeps.dot Sun Oct 12 20:30:09 2008 +0000 +++ b/doc/dependencies/filedeps.dot Tue Oct 14 07:41:48 2008 +0000 @@ -82,11 +82,11 @@ "engine/core/eventchannel/command/ec_command.h" -> "eventchannel/base/ec_event.h" "engine/core/eventchannel/command/ec_icommandcontroller.h" -> "ec_icommandlistener.h" "engine/core/eventchannel/eventmanager.cpp" -> "eventchannel/command/ec_command.h" + "engine/core/eventchannel/eventmanager.cpp" -> "eventchannel/key/ec_ikeyfilter.h" "engine/core/eventchannel/eventmanager.cpp" -> "eventchannel/key/ec_key.h" "engine/core/eventchannel/eventmanager.cpp" -> "eventchannel/key/ec_keyevent.h" "engine/core/eventchannel/eventmanager.cpp" -> "eventchannel/mouse/ec_mouseevent.h" "engine/core/eventchannel/eventmanager.cpp" -> "eventchannel/trigger/ec_trigger.h" - "engine/core/eventchannel/eventmanager.cpp" -> "eventchannel/widget/ec_widgetevent.h" "engine/core/eventchannel/eventmanager.cpp" -> "eventmanager.h" "engine/core/eventchannel/eventmanager.cpp" -> "util/base/exception.h" "engine/core/eventchannel/eventmanager.h" -> "eventchannel/command/ec_command.h" @@ -102,9 +102,7 @@ "engine/core/eventchannel/eventmanager.h" -> "eventchannel/sdl/ec_isdleventcontroller.h" "engine/core/eventchannel/eventmanager.h" -> "eventchannel/sdl/ec_isdleventlistener.h" "engine/core/eventchannel/eventmanager.h" -> "eventchannel/trigger/ec_itriggercontroller.h" - "engine/core/eventchannel/eventmanager.h" -> "eventchannel/widget/ec_iwidgetcontroller.h" - "engine/core/eventchannel/eventmanager.h" -> "eventchannel/widget/ec_iwidgetlistener.h" - "engine/core/eventchannel/eventmanager.h" -> "eventchannel/widget/ec_widgetevent.h" + "engine/core/eventchannel/key/ec_ikeyfilter.h" -> "ec_keyevent.h" "engine/core/eventchannel/key/ec_keyevent.h" -> "ec_key.h" "engine/core/eventchannel/key/ec_keyevent.h" -> "eventchannel/base/ec_inputevent.h" "engine/core/eventchannel/key/ec_keyevent.h" -> "eventchannel/source/ec_ieventsource.h" @@ -112,8 +110,6 @@ "engine/core/eventchannel/source/ec_ieventsource.h" -> "ec_eventsourcetypes.h" "engine/core/eventchannel/trigger/ec_trigger.h" -> "ec_itriggercontroller.h" "engine/core/eventchannel/trigger/ec_trigger.h" -> "ec_itriggerlistener.h" - "engine/core/eventchannel/widget/ec_iwidgetcontroller.h" -> "ec_iwidgetlistener.h" - "engine/core/eventchannel/widget/ec_widgetevent.h" -> "eventchannel/base/ec_event.h" "engine/core/gui/base/gui_font.cpp" -> "gui_font.h" "engine/core/gui/base/gui_font.cpp" -> "util/structures/rect.h" "engine/core/gui/base/gui_font.cpp" -> "video/image.h" @@ -149,22 +145,20 @@ "engine/core/gui/console/console.cpp" -> "util/time/timemanager.h" "engine/core/gui/console/console.cpp" -> "video/renderbackend.h" "engine/core/gui/console/console.h" -> "util/time/timer.h" + "engine/core/gui/guilistener.cpp" -> "guilistener.h" "engine/core/gui/guimanager.cpp" -> "eventchannel/key/ec_keyevent.h" "engine/core/gui/guimanager.cpp" -> "eventchannel/mouse/ec_mouseevent.h" - "engine/core/gui/guimanager.cpp" -> "eventchannel/widget/ec_widgetevent.h" "engine/core/gui/guimanager.cpp" -> "gui/base/gui_font.h" "engine/core/gui/guimanager.cpp" -> "gui/base/gui_imageloader.h" "engine/core/gui/guimanager.cpp" -> "gui/console/console.h" "engine/core/gui/guimanager.cpp" -> "guimanager.h" + "engine/core/gui/guimanager.cpp" -> "util/base/exception.h" "engine/core/gui/guimanager.cpp" -> "util/log/logger.h" "engine/core/gui/guimanager.cpp" -> "video/fonts/fontbase.h" "engine/core/gui/guimanager.cpp" -> "video/fonts/subimagefont.h" "engine/core/gui/guimanager.cpp" -> "video/fonts/truetypefont.h" "engine/core/gui/guimanager.cpp" -> "video/renderbackend.h" - "engine/core/gui/guimanager.h" -> "eventchannel/key/ec_ikeylistener.h" - "engine/core/gui/guimanager.h" -> "eventchannel/mouse/ec_imouselistener.h" "engine/core/gui/guimanager.h" -> "eventchannel/sdl/ec_isdleventlistener.h" - "engine/core/gui/guimanager.h" -> "eventchannel/widget/ec_iwidgetlistener.h" "engine/core/gui/guimanager.h" -> "util/base/singleton.h" "engine/core/gui/widgets/clicklabel.cpp" -> "clicklabel.h" "engine/core/gui/widgets/clicklabel.cpp" -> "gui/base/gui_font.h"
--- a/engine/core/controller/engine.cpp Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/controller/engine.cpp Tue Oct 14 07:41:48 2008 +0000 @@ -207,13 +207,9 @@ m_gui_graphics = new SdlGuiGraphics(*m_imagepool); } FL_LOG(_log, "Constructing GUI manager"); - m_guimanager = new GUIManager(m_eventmanager, *m_imagepool); + m_guimanager = new GUIManager(*m_imagepool); + FL_LOG(_log, "Events bind to GUI manager"); m_eventmanager->addSdlEventListener(m_guimanager); - // keep guimanager as the first key listener so that it can evaluate guichan hits - m_eventmanager->addKeyListener(m_guimanager); - // keep guimanager as the first mouse listener so that it can evaluate guichan hits - m_eventmanager->addMouseListener(m_guimanager); - FL_LOG(_log, "Events bind to GUI manager"); FL_LOG(_log, "Creating default font"); m_defaultfont = m_guimanager->setDefaultFont(
--- a/engine/core/eventchannel/eventchannel.i Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/eventchannel/eventchannel.i Tue Oct 14 07:41:48 2008 +0000 @@ -29,12 +29,11 @@ #include "eventchannel/key/ec_key.h" #include "eventchannel/key/ec_keyevent.h" #include "eventchannel/key/ec_ikeylistener.h" +#include "eventchannel/key/ec_ikeyfilter.h" #include "eventchannel/source/ec_eventsourcetypes.h" #include "eventchannel/source/ec_ieventsource.h" #include "eventchannel/mouse/ec_mouseevent.h" #include "eventchannel/mouse/ec_imouselistener.h" -#include "eventchannel/widget/ec_widgetevent.h" -#include "eventchannel/widget/ec_iwidgetlistener.h" #include "eventchannel/eventmanager.h" %} @@ -168,19 +167,11 @@ virtual ~IMouseListener(); }; - class WidgetEvent: public Event { + %feature("director") IKeyFilter; + class IKeyFilter { public: - virtual const std::string& getId(); - virtual ~WidgetEvent(); - private: - WidgetEvent(); - }; - - %feature("director") IWidgetListener; - class IWidgetListener { - public: - virtual void onWidgetAction(WidgetEvent& evt) = 0; - virtual ~IWidgetListener(); + virtual bool isFiltered(const KeyEvent& evt) = 0; + virtual ~IKeyFilter(); }; class EventManager { @@ -193,11 +184,8 @@ void removeKeyListener(IKeyListener* listener); void addMouseListener(IMouseListener* listener); void removeMouseListener(IMouseListener* listener); - void addWidgetListener(IWidgetListener* listener); - void removeWidgetListener(IWidgetListener* listener); EventSourceType getEventSourceType(); void dispatchCommand(Command& command); - void setNonConsumableKeys(const std::vector<int>& keys); - std::vector<int> getNonConsumableKeys(); + void setKeyFilter(IKeyFilter* keyFilter); }; };
--- a/engine/core/eventchannel/eventmanager.cpp Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/eventchannel/eventmanager.cpp Tue Oct 14 07:41:48 2008 +0000 @@ -31,8 +31,8 @@ #include "util/base/exception.h" #include "eventchannel/key/ec_key.h" #include "eventchannel/key/ec_keyevent.h" +#include "eventchannel/key/ec_ikeyfilter.h" #include "eventchannel/mouse/ec_mouseevent.h" -#include "eventchannel/widget/ec_widgetevent.h" #include "eventchannel/command/ec_command.h" #include "eventchannel/trigger/ec_trigger.h" @@ -45,10 +45,8 @@ m_keylisteners(), m_mouselisteners(), m_sdleventlisteners(), - m_widgetlisteners(), - m_pending_widgetlisteners(), - m_nonconsumablekeys(), m_keystatemap(), + m_keyfilter(0), m_mousestate(0), m_mostrecentbtn(MouseEvent::EMPTY) { @@ -57,71 +55,6 @@ EventManager::~EventManager() { } - void EventManager::fillMouseEvent(const SDL_Event& sdlevt, MouseEvent& mouseevt) { - mouseevt.setX(sdlevt.button.x); - mouseevt.setY(sdlevt.button.y); - mouseevt.setButton(MouseEvent::EMPTY); - mouseevt.setType(MouseEvent::MOVED); - if ((sdlevt.type == SDL_MOUSEBUTTONUP) || (sdlevt.type == SDL_MOUSEBUTTONDOWN)) { - switch (sdlevt.button.button) { - case SDL_BUTTON_LEFT: - mouseevt.setButton(MouseEvent::LEFT); - break; - case SDL_BUTTON_RIGHT: - mouseevt.setButton(MouseEvent::RIGHT); - break; - case SDL_BUTTON_MIDDLE: - mouseevt.setButton(MouseEvent::MIDDLE); - break; - default: - mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON); - break; - } - - - if (sdlevt.type == SDL_MOUSEBUTTONUP ) { - - mouseevt.setType(MouseEvent::RELEASED); - - } else { - mouseevt.setType(MouseEvent::PRESSED); - } - - switch (sdlevt.button.button) { - case SDL_BUTTON_WHEELDOWN: - mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN); - break; - case SDL_BUTTON_WHEELUP: - mouseevt.setType(MouseEvent::WHEEL_MOVED_UP); - break; - default: - break; - } - } - if ((mouseevt.getType() == MouseEvent::MOVED) && m_mousestate) { - mouseevt.setType(MouseEvent::DRAGGED); - mouseevt.setButton(m_mostrecentbtn); - } - } - - void EventManager::fillKeyEvent(const SDL_Event& sdlevt, KeyEvent& keyevt) { - if (sdlevt.type == SDL_KEYDOWN) { - keyevt.setType(KeyEvent::PRESSED); - } else if (sdlevt.type == SDL_KEYUP) { - keyevt.setType(KeyEvent::RELEASED); - } else { - throw EventException("Invalid event type in fillKeyEvent"); - } - SDL_keysym keysym = sdlevt.key.keysym; - - keyevt.setShiftPressed(keysym.mod & KMOD_SHIFT); - keyevt.setControlPressed(keysym.mod & KMOD_CTRL); - keyevt.setAltPressed(keysym.mod & KMOD_ALT); - keyevt.setMetaPressed(keysym.mod & KMOD_META); - keyevt.setNumericPad(keysym.sym >= SDLK_KP0 && keysym.sym <= SDLK_KP_EQUALS); - keyevt.setKey(Key(static_cast<Key::KeyType>(keysym.sym), keysym.unicode)); - } - template<typename T> void removeListener(std::vector<T>& vec, T& listener) { vec.push_back(listener); @@ -164,14 +97,6 @@ removeListener<ISdlEventListener*>(m_pending_sdldeletions, listener); } - void EventManager::addWidgetListener(IWidgetListener* listener) { - addListener<IWidgetListener*>(m_pending_widgetlisteners, listener); - } - - void EventManager::removeWidgetListener(IWidgetListener* listener) { - removeListener<IWidgetListener*>(m_pending_wldeletions, listener); - } - void EventManager::dispatchCommand(Command& command) { if(!m_pending_commandlisteners.empty()) { std::vector<ICommandListener*>::iterator i = m_pending_commandlisteners.begin(); @@ -209,15 +134,6 @@ } void EventManager::dispatchKeyEvent(KeyEvent& evt) { - bool nonconsumablekey = false; - for (std::vector<int>::iterator it = m_nonconsumablekeys.begin(); - it != m_nonconsumablekeys.end(); ++it) { - if (*it == evt.getKey().getValue()) { - nonconsumablekey = true; - break; - } - } - if(!m_pending_keylisteners.empty()) { std::vector<IKeyListener*>::iterator i = m_pending_keylisteners.begin(); while (i != m_pending_keylisteners.end()) { @@ -255,25 +171,10 @@ default: break; } - if ((!nonconsumablekey) && (evt.isConsumed())) { - break; - } ++i; } } - void EventManager::fillModifiers(InputEvent& evt) { - evt.setAltPressed(m_keystatemap[Key::ALT_GR] | - m_keystatemap[Key::LEFT_ALT] | - m_keystatemap[Key::RIGHT_ALT]); - evt.setControlPressed(m_keystatemap[Key::LEFT_CONTROL] | - m_keystatemap[Key::RIGHT_CONTROL]); - evt.setMetaPressed(m_keystatemap[Key::LEFT_META] | - m_keystatemap[Key::RIGHT_META]); - evt.setShiftPressed(m_keystatemap[Key::LEFT_SHIFT] | - m_keystatemap[Key::RIGHT_SHIFT]); - } - void EventManager::dispatchMouseEvent(MouseEvent& evt) { if(!m_pending_mouselisteners.empty()) { std::vector<IMouseListener*>::iterator i = m_pending_mouselisteners.begin(); @@ -340,7 +241,8 @@ } } - void EventManager::dispatchSdlEvent(SDL_Event& evt) { + bool EventManager::dispatchSdlEvent(SDL_Event& evt) { + bool ret = false; if (!m_pending_sdleventlisteners.empty()) { std::vector<ISdlEventListener*>::iterator i = m_pending_sdleventlisteners.begin(); while(i != m_pending_sdleventlisteners.end()) { @@ -368,49 +270,10 @@ std::vector<ISdlEventListener*>::iterator i = m_sdleventlisteners.begin(); while (i != m_sdleventlisteners.end()) { - (*i)->onSdlEvent(evt); + ret = ret || (*i)->onSdlEvent(evt); ++i; } - } - - void EventManager::dispatchWidgetEvent(WidgetEvent& evt) { - if(!m_pending_widgetlisteners.empty()) { - std::vector<IWidgetListener*>::iterator i = m_pending_widgetlisteners.begin(); - while (i != m_pending_widgetlisteners.end()) { - m_widgetlisteners.push_back(*i); - ++i; - } - m_pending_widgetlisteners.clear(); - } - - if (!m_pending_wldeletions.empty()) { - std::vector<IWidgetListener*>::iterator i = m_pending_wldeletions.begin(); - while (i != m_pending_wldeletions.end()) { - std::vector<IWidgetListener*>::iterator j = m_widgetlisteners.begin(); - while (j != m_widgetlisteners.end()) { - if(*j == *i) { - m_widgetlisteners.erase(j); - break; - } - ++j; - } - ++i; - } - m_pending_wldeletions.clear(); - } - - std::vector<IWidgetListener*>::iterator i = m_widgetlisteners.begin(); - while (i != m_widgetlisteners.end()) { - (*i)->onWidgetAction(evt); - if (evt.isConsumed()) { - break; - } - ++i; - } - } - - void EventManager::onWidgetAction(WidgetEvent& evt) { - dispatchWidgetEvent(evt); + return ret; } bool EventManager::combineEvents(SDL_Event& event1, const SDL_Event& event2) { @@ -430,14 +293,16 @@ return false; } - void EventManager::processEvents(){ - SDL_Event event, newevent; - bool has_event = SDL_PollEvent(&event); - while (has_event) { - has_event = SDL_PollEvent(&newevent); - if(has_event && combineEvents(event, newevent)) + void EventManager::processEvents() { + // The double SDL_PollEvent calls don't throw away events, + // but try to combine (mouse motion) events. + SDL_Event event, next_event; + bool has_next_event = SDL_PollEvent(&event); + while (has_next_event) { + has_next_event = SDL_PollEvent(&next_event); + if(has_next_event && combineEvents(event, next_event)) continue; - dispatchSdlEvent(event); + switch (event.type) { case SDL_QUIT: { Command cmd; @@ -446,85 +311,180 @@ dispatchCommand(cmd); } break; - case SDL_ACTIVEEVENT: { - Command cmd; - cmd.setSource(this); - SDL_ActiveEvent actevt = event.active; - if (actevt.state == SDL_APPMOUSEFOCUS) - { - if (actevt.gain) - cmd.setCommandType(CMD_MOUSE_FOCUS_GAINED); - else - cmd.setCommandType(CMD_MOUSE_FOCUS_LOST); - } - else if (actevt.state == SDL_APPINPUTFOCUS) - { - if (actevt.gain) - cmd.setCommandType(CMD_INPUT_FOCUS_GAINED); - else - cmd.setCommandType(CMD_INPUT_FOCUS_LOST); - } - else if (actevt.state == SDL_APPACTIVE) - { - if (actevt.gain) - cmd.setCommandType(CMD_APP_RESTORED); - else - cmd.setCommandType(CMD_APP_ICONIFIED); - } - dispatchCommand(cmd); - } + + case SDL_ACTIVEEVENT: + processActiveEvent(event); break; + case SDL_KEYDOWN: - case SDL_KEYUP: { - KeyEvent keyevt; - keyevt.setSource(this); - fillKeyEvent(event, keyevt); - m_keystatemap[keyevt.getKey().getValue()] = (keyevt.getType() == KeyEvent::PRESSED); - dispatchKeyEvent(keyevt); - } + case SDL_KEYUP: + processKeyEvent(event); break; + case SDL_MOUSEBUTTONUP: case SDL_MOUSEMOTION: - case SDL_MOUSEBUTTONDOWN: { - MouseEvent mouseevt; - mouseevt.setSource(this); - fillMouseEvent(event, mouseevt); - fillModifiers(mouseevt); - if (event.type == SDL_MOUSEBUTTONDOWN) { - m_mousestate |= static_cast<int>(mouseevt.getButton()); - m_mostrecentbtn = mouseevt.getButton(); - } else if (event.type == SDL_MOUSEBUTTONUP) { - m_mousestate &= ~static_cast<int>(mouseevt.getButton()); - } - // fire scrollwheel events only once - if (event.button.button == SDL_BUTTON_WHEELDOWN || event.button.button == SDL_BUTTON_WHEELUP) { - if (event.type == SDL_MOUSEBUTTONUP) { - break; - } - } - dispatchMouseEvent(mouseevt); - } + case SDL_MOUSEBUTTONDOWN: + processMouseEvent(event); break; } - if(has_event) - event = newevent; + if(has_next_event) + event = next_event; + } + pollTriggers(); + } + + void EventManager::processActiveEvent(SDL_Event event) { + if(dispatchSdlEvent(event)) + return; + + Command cmd; + cmd.setSource(this); + SDL_ActiveEvent actevt = event.active; + if (actevt.state == SDL_APPMOUSEFOCUS) + { + if (actevt.gain) + cmd.setCommandType(CMD_MOUSE_FOCUS_GAINED); + else + cmd.setCommandType(CMD_MOUSE_FOCUS_LOST); + } + else if (actevt.state == SDL_APPINPUTFOCUS) + { + if (actevt.gain) + cmd.setCommandType(CMD_INPUT_FOCUS_GAINED); + else + cmd.setCommandType(CMD_INPUT_FOCUS_LOST); + } + else if (actevt.state == SDL_APPACTIVE) + { + if (actevt.gain) + cmd.setCommandType(CMD_APP_RESTORED); + else + cmd.setCommandType(CMD_APP_ICONIFIED); + } + dispatchCommand(cmd); + } + + void EventManager::processKeyEvent(SDL_Event event) { + KeyEvent keyevt; + keyevt.setSource(this); + fillKeyEvent(event, keyevt); + m_keystatemap[keyevt.getKey().getValue()] = (keyevt.getType() == KeyEvent::PRESSED); + + bool dispatchAsSdl = !keyevt.getKey().isFunctionKey(); + if( dispatchAsSdl && m_keyfilter ) { + dispatchAsSdl = !m_keyfilter->isFiltered(keyevt); + } + + if( dispatchAsSdl ) { + if( dispatchSdlEvent(event) ) + return; } - pollTriggers(); + dispatchKeyEvent(keyevt); + } + + void EventManager::processMouseEvent(SDL_Event event) { + if(dispatchSdlEvent(event)) + return; + + MouseEvent mouseevt; + mouseevt.setSource(this); + fillMouseEvent(event, mouseevt); + fillModifiers(mouseevt); + if (event.type == SDL_MOUSEBUTTONDOWN) { + m_mousestate |= static_cast<int>(mouseevt.getButton()); + m_mostrecentbtn = mouseevt.getButton(); + } else if (event.type == SDL_MOUSEBUTTONUP) { + m_mousestate &= ~static_cast<int>(mouseevt.getButton()); + } + // fire scrollwheel events only once + if (event.button.button == SDL_BUTTON_WHEELDOWN || event.button.button == SDL_BUTTON_WHEELUP) { + if (event.type == SDL_MOUSEBUTTONUP) { + return; + } + } + dispatchMouseEvent(mouseevt); + } + + + void EventManager::fillMouseEvent(const SDL_Event& sdlevt, MouseEvent& mouseevt) { + mouseevt.setX(sdlevt.button.x); + mouseevt.setY(sdlevt.button.y); + mouseevt.setButton(MouseEvent::EMPTY); + mouseevt.setType(MouseEvent::MOVED); + if ((sdlevt.type == SDL_MOUSEBUTTONUP) || (sdlevt.type == SDL_MOUSEBUTTONDOWN)) { + switch (sdlevt.button.button) { + case SDL_BUTTON_LEFT: + mouseevt.setButton(MouseEvent::LEFT); + break; + case SDL_BUTTON_RIGHT: + mouseevt.setButton(MouseEvent::RIGHT); + break; + case SDL_BUTTON_MIDDLE: + mouseevt.setButton(MouseEvent::MIDDLE); + break; + default: + mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON); + break; + } + + if (sdlevt.type == SDL_MOUSEBUTTONUP ) { + mouseevt.setType(MouseEvent::RELEASED); + } else { + mouseevt.setType(MouseEvent::PRESSED); + } + + switch (sdlevt.button.button) { + case SDL_BUTTON_WHEELDOWN: + mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN); + break; + case SDL_BUTTON_WHEELUP: + mouseevt.setType(MouseEvent::WHEEL_MOVED_UP); + break; + default: + break; + } + } + if ((mouseevt.getType() == MouseEvent::MOVED) && m_mousestate) { + mouseevt.setType(MouseEvent::DRAGGED); + mouseevt.setButton(m_mostrecentbtn); + } + } + + void EventManager::fillKeyEvent(const SDL_Event& sdlevt, KeyEvent& keyevt) { + if (sdlevt.type == SDL_KEYDOWN) { + keyevt.setType(KeyEvent::PRESSED); + } else if (sdlevt.type == SDL_KEYUP) { + keyevt.setType(KeyEvent::RELEASED); + } else { + throw EventException("Invalid event type in fillKeyEvent"); + } + SDL_keysym keysym = sdlevt.key.keysym; + + keyevt.setShiftPressed(keysym.mod & KMOD_SHIFT); + keyevt.setControlPressed(keysym.mod & KMOD_CTRL); + keyevt.setAltPressed(keysym.mod & KMOD_ALT); + keyevt.setMetaPressed(keysym.mod & KMOD_META); + keyevt.setNumericPad(keysym.sym >= SDLK_KP0 && keysym.sym <= SDLK_KP_EQUALS); + keyevt.setKey(Key(static_cast<Key::KeyType>(keysym.sym), keysym.unicode)); + } + + void EventManager::fillModifiers(InputEvent& evt) { + evt.setAltPressed(m_keystatemap[Key::ALT_GR] | + m_keystatemap[Key::LEFT_ALT] | + m_keystatemap[Key::RIGHT_ALT]); + evt.setControlPressed(m_keystatemap[Key::LEFT_CONTROL] | + m_keystatemap[Key::RIGHT_CONTROL]); + evt.setMetaPressed(m_keystatemap[Key::LEFT_META] | + m_keystatemap[Key::RIGHT_META]); + evt.setShiftPressed(m_keystatemap[Key::LEFT_SHIFT] | + m_keystatemap[Key::RIGHT_SHIFT]); } EventSourceType EventManager::getEventSourceType() { return ES_ENGINE; } - void EventManager::setNonConsumableKeys(const std::vector<int>& keys) { - m_nonconsumablekeys = keys; - } - - std::vector<int> EventManager::getNonConsumableKeys() { - return m_nonconsumablekeys; - } - void EventManager::registerTrigger(Trigger& trigger){ m_triggers.push_back(&trigger); } @@ -538,4 +498,8 @@ (*it)->pollTrigger(); } } + + void EventManager::setKeyFilter(IKeyFilter* keyFilter) { + m_keyfilter = keyFilter; + } }
--- a/engine/core/eventchannel/eventmanager.h Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/eventchannel/eventmanager.h Tue Oct 14 07:41:48 2008 +0000 @@ -52,10 +52,6 @@ #include "eventchannel/sdl/ec_isdleventcontroller.h" #include "eventchannel/sdl/ec_isdleventlistener.h" -#include "eventchannel/widget/ec_iwidgetcontroller.h" -#include "eventchannel/widget/ec_iwidgetlistener.h" -#include "eventchannel/widget/ec_widgetevent.h" - #include "eventchannel/trigger/ec_itriggercontroller.h" namespace FIFE { @@ -64,6 +60,7 @@ class InputEvent; class MouseEvent; class KeyEvent; + class IKeyFilter; /** Event Manager manages all events related to FIFE */ @@ -72,9 +69,7 @@ public IKeyController, public IMouseController, public ISdlEventController, - public IWidgetController, public IEventSource, - public IWidgetListener, public ITriggerController { public: /** Constructor. @@ -94,13 +89,7 @@ void removeMouseListener(IMouseListener* listener); void addSdlEventListener(ISdlEventListener* listener); void removeSdlEventListener(ISdlEventListener* listener); - void addWidgetListener(IWidgetListener* listener); - void removeWidgetListener(IWidgetListener* listener); EventSourceType getEventSourceType(); - void setNonConsumableKeys(const std::vector<int>& keys); - std::vector<int> getNonConsumableKeys(); - - void onWidgetAction(WidgetEvent& evt); void registerTrigger(Trigger& trigger); void unregisterTrigger(Trigger& trigger); @@ -111,15 +100,25 @@ */ void processEvents(); + void setKeyFilter(IKeyFilter* keyFilter); + private: + // Helpers for processEvents + void processActiveEvent(SDL_Event event); + void processKeyEvent(SDL_Event event); + void processMouseEvent(SDL_Event event); bool combineEvents(SDL_Event& event1, const SDL_Event& event2); + + // Events dispatchers - only dispatchSdlevent may reject the event. + bool dispatchSdlEvent(SDL_Event& evt); void dispatchKeyEvent(KeyEvent& evt); void dispatchMouseEvent(MouseEvent& evt); - void dispatchSdlEvent(SDL_Event& evt); - void dispatchWidgetEvent(WidgetEvent& evt); + + // Translate events void fillModifiers(InputEvent& evt); void fillKeyEvent(const SDL_Event& sdlevt, KeyEvent& keyevt); void fillMouseEvent(const SDL_Event& sdlevt, MouseEvent& mouseevt); + void pollTriggers(); std::vector<ICommandListener*> m_commandlisteners; @@ -138,12 +137,8 @@ std::vector<ISdlEventListener*> m_pending_sdleventlisteners; std::vector<ISdlEventListener*> m_pending_sdldeletions; - std::vector<IWidgetListener*> m_widgetlisteners; - std::vector<IWidgetListener*> m_pending_widgetlisteners; - std::vector<IWidgetListener*> m_pending_wldeletions; - - std::vector<int> m_nonconsumablekeys; std::map<int, bool> m_keystatemap; + IKeyFilter* m_keyfilter; int m_mousestate; MouseEvent::MouseButtonType m_mostrecentbtn;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/eventchannel/key/ec_ikeyfilter.h Tue Oct 14 07:41:48 2008 +0000 @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_EVENTCHANNEL_IKEYFILTER_H +#define FIFE_EVENTCHANNEL_IKEYFILTER_H + +// Standard C++ library includes +// + +// 3rd party library includes +// + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder +// +#include "ec_keyevent.h" + +namespace FIFE { + /** Controller provides a way to receive events from the system + * Using this interface, clients can subscribe themselves to receive events + */ + class IKeyFilter { + public: + + /** Check whether a keyevent should be filtered out. + * @param event They key event. + */ + virtual bool isFiltered(const KeyEvent& event) = 0; + + virtual ~IKeyFilter() {} + }; + +} //FIFE + +#endif
--- a/engine/core/eventchannel/key/ec_key.h Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/eventchannel/key/ec_key.h Tue Oct 14 07:41:48 2008 +0000 @@ -296,6 +296,9 @@ return m_unicode != 0; } + bool isFunctionKey() const { + return m_key >= F1 && m_key <= F15; + } /** Gets the value of the key. */
--- a/engine/core/eventchannel/sdl/ec_isdleventlistener.h Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/eventchannel/sdl/ec_isdleventlistener.h Tue Oct 14 07:41:48 2008 +0000 @@ -46,7 +46,7 @@ /** Called when an SDL event is received from SDL * @param evt SDL event */ - virtual void onSdlEvent(SDL_Event& evt) = 0; + virtual bool onSdlEvent(SDL_Event& evt) = 0; virtual ~ISdlEventListener() {} };
--- a/engine/core/eventchannel/widget/ec_iwidgetcontroller.h Sun Oct 12 20:30:09 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005-2008 by the FIFE team * - * http://www.fifengine.de * - * This file is part of FIFE. * - * * - * FIFE is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with this library; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - ***************************************************************************/ - -#ifndef FIFE_EVENTCHANNEL_IWIDGET_CONTROLLER_H -#define FIFE_EVENTCHANNEL_IWIDGET_CONTROLLER_H - -// Standard C++ library includes -// - -// 3rd party library includes -// - -// FIFE includes -// These includes are split up in two parts, separated by one empty line -// First block: files included from the FIFE root src directory -// Second block: files included from the same folder -// -#include "ec_iwidgetlistener.h" - -namespace FIFE { - - /** Controller provides a way to receive events from the system - * Using this interface, clients can subscribe themselves to receive events - */ - class IWidgetController { - public: - - /** Adds a listener to the controller - * Listener will be notified via the corresponding events - * @param listener listener to add - */ - virtual void addWidgetListener(IWidgetListener* listener) = 0; - - /** Removes an added listener from the controller. - * Listener will not be notified anymore via the corresponding events - * @param listener listener to remove - */ - virtual void removeWidgetListener(IWidgetListener* listener) = 0; - - virtual ~IWidgetController() {} - }; - -} //FIFE - -#endif
--- a/engine/core/eventchannel/widget/ec_iwidgetlistener.h Sun Oct 12 20:30:09 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005-2008 by the FIFE team * - * http://www.fifengine.de * - * This file is part of FIFE. * - * * - * FIFE is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with this library; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - ***************************************************************************/ - -#ifndef FIFE_EVENTCHANNEL_IWIDGETLISTENER_H -#define FIFE_EVENTCHANNEL_IWIDGETLISTENER_H - -// Standard C++ library includes -// - -// 3rd party library includes -// - -// FIFE includes -// These includes are split up in two parts, separated by one empty line -// First block: files included from the FIFE root src directory -// Second block: files included from the same folder -// - -namespace FIFE { - class WidgetEvent; - - /** Listener of widget events. - * To be able to listen for widget events you must make a class which inherits - * from this class and implements its functions. - */ - class IWidgetListener { - public: - /** - * Called when an action is recieved from a Widget. It is used - * to be able to recieve a notification that an action has - * occured. - * @param evy the event of the action. - */ - virtual void onWidgetAction(WidgetEvent& evt) = 0; - - virtual ~IWidgetListener() {} - }; -} //FIFE - -#endif
--- a/engine/core/eventchannel/widget/ec_widgetevent.h Sun Oct 12 20:30:09 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,81 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2005-2008 by the FIFE team * - * http://www.fifengine.de * - * This file is part of FIFE. * - * * - * FIFE is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with this library; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - ***************************************************************************/ - -#ifndef FIFE_EVENTCHANNEL_WIDGETEVENT_H -#define FIFE_EVENTCHANNEL_WIDGETEVENT_H - -// Standard C++ library includes -// - -// 3rd party library includes -// - -// FIFE includes -// These includes are split up in two parts, separated by one empty line -// First block: files included from the FIFE root src directory -// Second block: files included from the same folder -// -#include "eventchannel/base/ec_event.h" - -namespace FIFE { - /** Interface for widget events - * Events are sent by different UI widgets - */ - class WidgetEvent: public Event { - public: - /** Constructor. - */ - WidgetEvent(): - Event(), - m_id("") {} - - /** Destructor. - */ - ~WidgetEvent() {} - - /** - * Gets the id of the event. - * @return the id of the event. - */ - const std::string& getId() const { return m_id; } - void setId(const std::string& id) { m_id = id; } - - virtual void consume() { Event::consume(); } - virtual bool isConsumed() const { return Event::isConsumed(); } - virtual IEventSource* getSource() { return Event::getSource(); } - virtual void setSource(IEventSource* source) { Event::setSource(source); } - virtual gcn::Widget* getSourceWidget() { return Event::getSourceWidget(); } - virtual void setSourceWidget(gcn::Widget* widget) { Event::setSourceWidget(widget); } - virtual int getTimeStamp() const { return Event::getTimeStamp(); } - virtual void setTimeStamp(int timestamp ) { Event::setTimeStamp(timestamp); } - virtual const std::string& getName() const { - const static std::string eventName("WidgetEvent"); - return eventName; - } - virtual std::string getDebugString() const { return Event::getDebugString(); } - - private: - std::string m_id; - }; - -} //FIFE - -#endif
--- a/engine/core/gui/console/console.cpp Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/gui/console/console.cpp Tue Oct 14 07:41:48 2008 +0000 @@ -78,6 +78,8 @@ m_animationTimer.setCallback( boost::bind(&Console::updateAnimation, this) ); m_toolsbutton->addActionListener(this); + m_toolsbutton->setFocusable(false); + m_input->addFocusListener(this); GuiFont* font = GUIManager::instance()->createFont(); font->setColor(255,255,255); @@ -299,5 +301,9 @@ m_input->setFont(font); m_output->setFont(font); } + + void Console::focusLost(const gcn::Event& ) { + hide(); + } } /* vim: set noexpandtab: set shiftwidth=2: set tabstop=2: */
--- a/engine/core/gui/console/console.h Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/gui/console/console.h Tue Oct 14 07:41:48 2008 +0000 @@ -61,7 +61,7 @@ /** Ingame Console */ - class Console : public gcn::Container, public gcn::ActionListener { + class Console : public gcn::Container, public gcn::ActionListener, public gcn::FocusListener { public: /** Constructor */ @@ -138,6 +138,9 @@ */ void setIOFont(GuiFont* font); + /** Hide if we loose focus + */ + void focusLost(const gcn::Event& event); private: bool m_isAttached;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/gui/guilistener.cpp Tue Oct 14 07:41:48 2008 +0000 @@ -0,0 +1,43 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +// Standard C++ library includes +#include <iostream> + +// 3rd party library includes + + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder + +#include "guilistener.h" + + +namespace FIFE { + + GUIEventListener::GUIEventListener() { + } + + GUIEventListener::~GUIEventListener() { + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/gui/guilistener.h Tue Oct 14 07:41:48 2008 +0000 @@ -0,0 +1,48 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef FIFE_VIDEO_GUI_GUILISTENER_H +#define FIFE_VIDEO_GUI_GUILISTENER_H + +// Standard C++ library includes +#include <set> + +// 3rd party library includes +#include <guichan.hpp> + +// FIFE includes +// These includes are split up in two parts, separated by one empty line +// First block: files included from the FIFE root src directory +// Second block: files included from the same folder + +namespace FIFE { + + class GUIEventListener + : public gcn::MouseListener, public gcn::KeyListener, public gcn::ActionListener { + public: + GUIEventListener(); + virtual ~GUIEventListener(); + virtual void action(const gcn::ActionEvent& actionEvent) {}; + }; + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/core/gui/guilistener.i Tue Oct 14 07:41:48 2008 +0000 @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2005-2008 by the FIFE team * + * http://www.fifengine.de * + * This file is part of FIFE. * + * * + * FIFE is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +%module fife +%{ +#include <guichan.hpp> +#include "gui/guilistener.h" +%} + +namespace gcn { + + %nodefaultctor; + class MouseListener { + public: + }; + + class KeyListener { + public: + }; + + class ActionListener { + public: + }; + %clearnodefaultctor; +} + +namespace FIFE { + + %feature("director") GUIEventListener; + class GUIEventListener : + public gcn::MouseListener, public gcn::KeyListener, public gcn::ActionListener { + public: + GUIEventListener(); + virtual ~GUIEventListener(); + + /* Mouse events */ + virtual void mouseEntered(gcn::MouseEvent& mouseEvent); + virtual void mouseExited(gcn::MouseEvent& mouseEvent); + virtual void mousePressed(gcn::MouseEvent& mouseEvent); + virtual void mouseReleased(gcn::MouseEvent& mouseEvent); + virtual void mouseClicked(gcn::MouseEvent& mouseEvent); + virtual void mouseWheelMovedUp(gcn::MouseEvent& mouseEvent); + virtual void mouseWheelMovedDown(gcn::MouseEvent& mouseEvent); + virtual void mouseMoved(gcn::MouseEvent& mouseEvent); + virtual void mouseDragged(gcn::MouseEvent& mouseEvent); + + virtual void action(const gcn::ActionEvent& actionEvent); + + }; + +}
--- a/engine/core/gui/guimanager.cpp Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/gui/guimanager.cpp Tue Oct 14 07:41:48 2008 +0000 @@ -32,6 +32,7 @@ // These includes are split up in two parts, separated by one empty line // First block: files included from the FIFE root src directory // Second block: files included from the same folder +#include "util/base/exception.h" #include "util/log/logger.h" #include "video/renderbackend.h" #include "gui/base/gui_imageloader.h" @@ -40,7 +41,6 @@ #include "video/fonts/fontbase.h" #include "video/fonts/truetypefont.h" #include "video/fonts/subimagefont.h" -#include "eventchannel/widget/ec_widgetevent.h" #include "eventchannel/key/ec_keyevent.h" #include "eventchannel/mouse/ec_mouseevent.h" @@ -50,24 +50,26 @@ namespace FIFE { static Logger _log(LM_GUI); - GUIManager::GUIManager(IWidgetListener* widgetlistener, ImagePool& pool) : + GUIManager::GUIManager(ImagePool& pool) : m_gcn_gui(new gcn::Gui()), m_focushandler(0), - m_gcn_topcontainer(new gcn::Container()), - m_imgloader(new GuiImageLoader(pool)) , - m_input(new gcn::SDLInput()), - m_console(0), - m_fonts(), - m_widgetlistener(widgetlistener), + m_gcn_topcontainer(new gcn::Container()), + m_imgloader(new GuiImageLoader(pool)) , + m_input(new gcn::SDLInput()), + m_console(0), + m_fonts(), m_pool(pool), m_logic_executed(false) { - - m_gcn_gui->setTop(m_gcn_topcontainer); - m_gcn_topcontainer->setOpaque(false); + m_gcn_gui->setInput(m_input); + gcn::Image::setImageLoader(m_imgloader); - gcn::Image::setImageLoader(m_imgloader); + m_gcn_gui->setTop(m_gcn_topcontainer); m_focushandler = m_gcn_topcontainer->_getFocusHandler(); + + m_gcn_topcontainer->setOpaque(false); + m_gcn_topcontainer->setFocusable(false); + m_had_mouse = false; } GUIManager::~GUIManager() { @@ -83,13 +85,54 @@ } } - void GUIManager::onSdlEvent(SDL_Event& evt) { + bool GUIManager::onSdlEvent(SDL_Event& evt) { gcn::SDLInput *input = dynamic_cast<gcn::SDLInput*>(m_gcn_gui->getInput()); if (!input) { FL_WARN(_log, "GUIManager, GuichanGUI->getInput == 0 ... discarding events!"); - return; + return false; } - input->pushInput(evt); + + switch(evt.type) { + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + if( m_gcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) ) { + input->pushInput(evt); + return true; + } + m_focushandler->focusNone(); + return false; + + case SDL_MOUSEMOTION: + if( m_gcn_topcontainer->getWidgetAt(evt.button.x,evt.button.y) ) { + m_had_mouse = true; + input->pushInput(evt); + return true; + } + if( m_had_mouse ) { + m_had_mouse = false; + input->pushInput(evt); + return true; + } + return false; + + case SDL_KEYDOWN: + case SDL_KEYUP: + if(m_focushandler->getFocused()) { + input->pushInput(evt); + return true; + } + return false; + + case SDL_ACTIVEEVENT: + if( evt.active.state & SDL_APPMOUSEFOCUS ) { + input->pushInput(evt); + return true; + } + return false; + + default: + return false; + } } void GUIManager::resizeTopContainer(unsigned int x, unsigned int y, unsigned int width, unsigned int height) { @@ -176,56 +219,85 @@ } void GUIManager::turn() { - if (!m_logic_executed) { - // Due to a BUG in Guichan we need to catch GCN exceptions - // This is a potentially dangerous workaround put in place - // until we upgrade to Guichan 0.8.0 - // See here: http://code.google.com/p/guichan/issues/detail?id=24 - try { - m_gcn_gui->logic(); - } catch( const gcn::Exception& e) { - FL_WARN(_log, LMsg("GUIManager, discarding gcn::Exception: ") << e.getMessage()); - } - } + if (!m_logic_executed) + m_gcn_gui->logic(); + m_logic_executed = false; m_gcn_gui->draw(); - m_logic_executed = false; } - void GUIManager::action(const gcn::ActionEvent & event) { - WidgetEvent wevt; - wevt.setId(event.getId()); - wevt.setSourceWidget(event.getSource()); - m_widgetlistener->onWidgetAction(wevt); + KeyEvent GUIManager::translateKeyEvent(const gcn::KeyEvent& gcnevt) { + KeyEvent keyevt; + if(gcnevt.getType() == gcn::KeyEvent::PRESSED) + keyevt.setType(KeyEvent::PRESSED); + else if(gcnevt.getType() == gcn::KeyEvent::RELEASED) + keyevt.setType(KeyEvent::RELEASED); + else + throw EventException("Invalid event type in fillKeyEvent"); + keyevt.setShiftPressed(gcnevt.isShiftPressed()); + keyevt.setControlPressed(gcnevt.isControlPressed()); + keyevt.setAltPressed(gcnevt.isAltPressed()); + keyevt.setMetaPressed(gcnevt.isMetaPressed()); + keyevt.setNumericPad(gcnevt.isNumericPad()); + keyevt.setKey(Key(static_cast<Key::KeyType>(gcnevt.getKey().getValue()), gcnevt.getKey().getValue())); + return keyevt; } - void GUIManager::evaluateKeyEventConsumption(KeyEvent& evt) { - gcn::Widget* w = m_focushandler->getFocused(); - if (w) { - evt.consumedByWidgets(); + MouseEvent GUIManager::translateMouseEvent(const gcn::MouseEvent& gcnevt) { + MouseEvent mouseevt; + mouseevt.setShiftPressed(gcnevt.isShiftPressed()); + mouseevt.setControlPressed(gcnevt.isControlPressed()); + mouseevt.setAltPressed(gcnevt.isAltPressed()); + mouseevt.setMetaPressed(gcnevt.isMetaPressed()); + mouseevt.setX(gcnevt.getX()); + mouseevt.setY(gcnevt.getY()); + + switch(gcnevt.getType()) { + case gcn::MouseEvent::PRESSED: + mouseevt.setType(MouseEvent::PRESSED); + break; + case gcn::MouseEvent::RELEASED: + mouseevt.setType(MouseEvent::RELEASED); + break; + case gcn::MouseEvent::MOVED: + mouseevt.setType(MouseEvent::MOVED); + break; + case gcn::MouseEvent::CLICKED: + mouseevt.setType(MouseEvent::CLICKED); + break; + case gcn::MouseEvent::ENTERED: + mouseevt.setType(MouseEvent::ENTERED); + break; + case gcn::MouseEvent::EXITED: + mouseevt.setType(MouseEvent::EXITED); + break; + case gcn::MouseEvent::DRAGGED: + mouseevt.setType(MouseEvent::DRAGGED); + break; + case gcn::MouseEvent::WHEEL_MOVED_DOWN: + mouseevt.setType(MouseEvent::WHEEL_MOVED_DOWN); + break; + case gcn::MouseEvent::WHEEL_MOVED_UP: + mouseevt.setType(MouseEvent::WHEEL_MOVED_UP); + break; + default: + mouseevt.setType(MouseEvent::UNKNOWN_EVENT); } - } - void GUIManager::evaluateMouseEventConsumption(MouseEvent& evt) { - gcn::Widget* w = m_gcn_topcontainer->getWidgetAt(evt.getX(), evt.getY()); - if (w && w->isVisible()) { - evt.consumedByWidgets(); + switch(gcnevt.getButton()) { + case gcn::MouseInput::LEFT: + mouseevt.setButton(MouseEvent::LEFT); + break; + case gcn::MouseInput::RIGHT: + mouseevt.setButton(MouseEvent::RIGHT); + break; + case gcn::MouseInput::MIDDLE: + mouseevt.setButton(MouseEvent::MIDDLE); + break; + default: + mouseevt.setButton(MouseEvent::UNKNOWN_BUTTON); + break; } + return mouseevt; } - void GUIManager::mousePressed(MouseEvent& evt) { - evaluateMouseEventConsumption(evt); - if (!evt.isConsumedByWidgets()) { - m_focushandler->focusNone(); - } - } - - void GUIManager::mouseDragged(MouseEvent& evt) { - try { - m_gcn_gui->logic(); - m_logic_executed = true; - } catch( const gcn::Exception& e) { - FL_WARN(_log, LMsg("GUIManager, discarding gcn::Exception: ") << e.getMessage()); - } - evaluateMouseEventConsumption(evt); - } }
--- a/engine/core/gui/guimanager.h Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/gui/guimanager.h Tue Oct 14 07:41:48 2008 +0000 @@ -34,9 +34,8 @@ // Second block: files included from the same folder #include "util/base/singleton.h" #include "eventchannel/sdl/ec_isdleventlistener.h" -#include "eventchannel/mouse/ec_imouselistener.h" -#include "eventchannel/key/ec_ikeylistener.h" -#include "eventchannel/widget/ec_iwidgetlistener.h" +// #include "eventchannel/mouse/ec_imouselistener.h" +// #include "eventchannel/key/ec_ikeylistener.h" namespace gcn { @@ -65,15 +64,12 @@ */ class GUIManager : public DynamicSingleton<GUIManager>, - public ISdlEventListener, - public IKeyListener, - public IMouseListener, - public gcn::ActionListener + public ISdlEventListener { public: /** Constructor. */ - GUIManager(IWidgetListener* widgetListener, ImagePool& pool); + GUIManager(ImagePool& pool); /** Destructor. */ virtual ~GUIManager(); @@ -140,27 +136,12 @@ */ void releaseFont(GuiFont* font); - /** Callback from guichan - */ - void action(const gcn::ActionEvent & event); + bool onSdlEvent(SDL_Event& evt); - void onSdlEvent(SDL_Event& evt); - void keyPressed(KeyEvent& evt) { evaluateKeyEventConsumption(evt); } - void keyReleased(KeyEvent& evt) { evaluateKeyEventConsumption(evt); } - void mouseEntered(MouseEvent& evt) { evaluateMouseEventConsumption(evt); } - void mouseExited(MouseEvent& evt) { evaluateMouseEventConsumption(evt); } - void mousePressed(MouseEvent& evt); - void mouseReleased(MouseEvent& evt) { evaluateMouseEventConsumption(evt); } - void mouseClicked(MouseEvent& evt) { evaluateMouseEventConsumption(evt); } - void mouseWheelMovedUp(MouseEvent& evt) { evaluateMouseEventConsumption(evt); } - void mouseWheelMovedDown(MouseEvent& evt) { evaluateMouseEventConsumption(evt); } - void mouseMoved(MouseEvent& evt) { evaluateMouseEventConsumption(evt); } - void mouseDragged(MouseEvent& evt); + KeyEvent translateKeyEvent(const gcn::KeyEvent& evt); + MouseEvent translateMouseEvent(const gcn::MouseEvent& evt); private: - void evaluateKeyEventConsumption(KeyEvent& evt); - void evaluateMouseEventConsumption(MouseEvent& evt); - // The Guichan GUI. gcn::Gui* m_gcn_gui; // Focus handler for input management @@ -178,8 +159,9 @@ // Added widgets std::set<gcn::Widget*> m_widgets; - // instance whom to deliver widget events coming from guichan - IWidgetListener* m_widgetlistener; + // Used to accept mouse motion events that leave widget space + bool m_had_mouse; + // pool used for images ImagePool& m_pool;
--- a/engine/core/gui/guimanager.i Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/gui/guimanager.i Tue Oct 14 07:41:48 2008 +0000 @@ -27,25 +27,23 @@ namespace gcn { class Widget; - class ActionEvent; - class ActionListener { - public: - virtual void action(const ActionEvent& actionEvent) = 0; - }; } namespace FIFE { class Console; %feature("notabstract") GUIManager; - class GUIManager: public gcn::ActionListener { + class GUIManager { public: Console* getConsole(); void add(gcn::Widget* widget); void remove(gcn::Widget* widget); GuiFont* createFont(const std::string& path, unsigned int size, const std::string& glyphs); void releaseFont(GuiFont* font); + + KeyEvent translateKeyEvent(const gcn::KeyEvent& evt); + MouseEvent translateMouseEvent(const gcn::MouseEvent& evt); private: - GUIManager(IWidgetListener* widgetListener); + GUIManager(); }; }
--- a/engine/core/gui/widgets/clicklabel.cpp Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/gui/widgets/clicklabel.cpp Tue Oct 14 07:41:48 2008 +0000 @@ -40,7 +40,6 @@ // setAlignment(Graphics::LEFT); setTextWrapping(false); setFrameSize(0); - m_listener = NULL; addMouseListener(this); addKeyListener(this); addFocusListener(this); @@ -53,7 +52,6 @@ setTextWrapping(false); setCaption(caption); setFrameSize(0); - m_listener = NULL; addMouseListener(this); addKeyListener(this); addFocusListener(this); @@ -141,19 +139,11 @@ void ClickLabel::mouseExited(MouseEvent& mouseEvent) { - // taken from TwoButton.cpp - if (m_listener) { - m_listener->mouseExited(*this); - } mHasMouse = false; } void ClickLabel::mouseEntered(MouseEvent& mouseEvent) { - // taken from TwoButton.cpp - if (m_listener) { - m_listener->mouseEntered(*this); - } mHasMouse = true; }
--- a/engine/core/gui/widgets/clicklabel.h Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/gui/widgets/clicklabel.h Tue Oct 14 07:41:48 2008 +0000 @@ -39,18 +39,6 @@ namespace gcn { - // taken from TwoButton.cpp - // FIXME: the listener code for Twobutton and Clicklabel is - // a kind of a hack and shouldn't be necessary later. So if - // eventmanager changes some day, this should be modified, too - class ClickLabel; - class ClickLabelListener { - public: - virtual ~ClickLabelListener() {} - virtual void mouseEntered(ClickLabel& btn) = 0; - virtual void mouseExited(ClickLabel& btn) = 0; - }; - class ClickLabel : public Widget, public MouseListener, public KeyListener, public FocusListener { public: ClickLabel(); @@ -92,11 +80,6 @@ virtual void keyReleased(KeyEvent& keyEvent); - - // taken from TwoButton.cpp - void setListener(ClickLabelListener* listener) { m_listener = listener; } - ClickLabelListener* getListener() { return m_listener; } - protected: void wrapText(); @@ -104,7 +87,6 @@ bool mTextWrapping; std::string mCaption; std::string mWrappedText; - ClickLabelListener* m_listener; bool mHasMouse; bool mKeyPressed;
--- a/engine/core/gui/widgets/twobutton.cpp Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/gui/widgets/twobutton.cpp Tue Oct 14 07:41:48 2008 +0000 @@ -39,7 +39,6 @@ m_hoverImage(hover_file), x_downoffset(0), y_downoffset(0), - m_listener(NULL), m_helptext("") { m_hoverImage = hover_file; setFrameSize(0); @@ -139,19 +138,6 @@ adjustSize(); } - void TwoButton::mouseEntered(MouseEvent& mouseEvent) { - if (m_listener) { - m_listener->mouseEntered(*this); - } - Button::mouseEntered(mouseEvent); - } - - void TwoButton::mouseExited(MouseEvent& mouseEvent) { - if (m_listener) { - m_listener->mouseExited(*this); - } - Button::mouseExited(mouseEvent); - } } /* vim: set noexpandtab: set shiftwidth=2: set tabstop=2: */
--- a/engine/core/gui/widgets/twobutton.h Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/gui/widgets/twobutton.h Tue Oct 14 07:41:48 2008 +0000 @@ -36,13 +36,7 @@ namespace gcn { class TwoButton; - class TwoButtonListener { - public: - virtual ~TwoButtonListener() {} - virtual void mouseEntered(TwoButton& btn) = 0; - virtual void mouseExited(TwoButton& btn) = 0; - }; - + class TwoButton : public Button { public: TwoButton(Image *up_image = 0, Image *down_image = 0, Image *hover_file = 0, const std::string& caption = ""); @@ -58,12 +52,6 @@ int getDownXOffset() { return x_downoffset; } int getDownYOffset() { return y_downoffset; } - void mouseEntered(MouseEvent& mouseEvent); - void mouseExited(MouseEvent& mouseEvent); - - void setListener(TwoButtonListener* listener) { m_listener = listener; } - TwoButtonListener* getListener() { return m_listener; } - void setHelpText(const std::string& txt) { m_helptext = txt; } const std::string& getHelpText() { return m_helptext; } @@ -73,7 +61,6 @@ Image *m_hoverImage; int x_downoffset; int y_downoffset; - TwoButtonListener* m_listener; std::string m_helptext; };
--- a/engine/core/gui/widgets/widgets.i Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/core/gui/widgets/widgets.i Tue Oct 14 07:41:48 2008 +0000 @@ -31,6 +31,8 @@ class Font; class Image; class ActionListener; + class MouseListener; + class KeyListener; %nodefaultctor; class Graphics { @@ -117,6 +119,10 @@ virtual void focusPrevious() { }; virtual void addActionListener(ActionListener* actionListener); virtual void removeActionListener(ActionListener* actionListener); + virtual void addMouseListener(MouseListener* actionListener); + virtual void removeMouseListener(MouseListener* actionListener); + virtual void addKeyListener(KeyListener* actionListener); + virtual void removeKeyListener(KeyListener* actionListener); /* protected: */ virtual void draw(Graphics* graphics) = 0; }; @@ -171,16 +177,6 @@ virtual void adjustSize(); /*virtual bool isPressed() const;*/ }; - - - class TwoButton; - %feature("director") TwoButtonListener; - class TwoButtonListener { - public: - virtual ~TwoButtonListener(); - virtual void mouseEntered(TwoButton& btn) = 0; - virtual void mouseExited(TwoButton& btn) = 0; - }; %feature("notabstract") TwoButton; class TwoButton: public Widget { @@ -197,8 +193,6 @@ void setDownOffset(int x, int y); int getDownXOffset(); int getDownYOffset(); - void setListener(TwoButtonListener* listener); - TwoButtonListener* getListener(); void setHelpText(const std::string& txt); const std::string& getHelpText(); @@ -379,15 +373,6 @@ virtual void resizeToContent(); }; - class ClickLabel; - %feature("director") ClickLabelListener; - class ClickLabelListener { - public: - virtual ~ClickLabelListener(); - virtual void mouseEntered(ClickLabel& btn) = 0; - virtual void mouseExited(ClickLabel& btn) = 0; - }; - %feature("notabstract") ClickLabel; %rename(Label) ClickLabel; class ClickLabel: public Widget { @@ -401,9 +386,6 @@ void setTextWrapping(bool); virtual void setWidth(int width); virtual void adjustSize(); - - void setListener(ClickLabelListener* listener); - ClickLabelListener* getListener(); }; %feature("notabstract") Icon2;
--- a/engine/extensions/basicapplication.py Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/extensions/basicapplication.py Tue Oct 14 07:41:48 2008 +0000 @@ -20,7 +20,7 @@ self.app = app self.engine = app.engine eventmanager = self.engine.getEventManager() - eventmanager.setNonConsumableKeys([fife.Key.ESCAPE]) + #eventmanager.setNonConsumableKeys([fife.Key.ESCAPE]) fife.IKeyListener.__init__(self) eventmanager.addKeyListener(self) self.quitRequested = False
--- a/engine/extensions/fife_compat.py Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/extensions/fife_compat.py Tue Oct 14 07:41:48 2008 +0000 @@ -11,6 +11,7 @@ - Animation.addFrame now expects a fife.ResourcePtr instead of an fife.Image - Pool.getIndex is just an alias for Pool.addResourceFromFile. + - EventManager.setNonConsumableKeys is superseeded by EventManager.setKeyFilter """ @@ -47,3 +48,28 @@ revision = 2617, message = "Use addResourceFromFile instead of getIndex" ) + +def _compat_NonConsumableKeys(): + class CompatKeyFilter(fife.IKeyFilter): + def __init__(self, keys): + fife.IKeyFilter.__init__(self) + self.keys = keys + + def isFiltered(self, event): + return event.getKey().getValue() in self.keys + + def _setNonConsumableKeys(self,keys): + deprecated(2636, "Write an IKeyFilter instead of using EventManager.setNonConsumableKeys.\n" + + "You probably don't need it anyway") + self.compat_keyfilter = CompatKeyFilter(keys) + self.compat_keyfilter.__disown__() + self.setKeyFilter(self.compat_keyfilter) + + def _getNonConsumableKeys(self,keys): + deprecated(2636, "Write an IKeyFilter instead of using EventManager.getNonConsumableKeys.") + return self.compat_keyfilter.keys + + fife.EventManager.setNonConsumableKeys = _setNonConsumableKeys + fife.EventManager.getNonConsumableKeys = _getNonConsumableKeys + +_compat_NonConsumableKeys()
--- a/engine/extensions/pychan/__init__.py Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/extensions/pychan/__init__.py Tue Oct 14 07:41:48 2008 +0000 @@ -20,11 +20,8 @@ ---- - Make setting parent attribute imply containment relation. - Finalize Widget.execute - - ClickLabel/Label rework. (In progress) - Documentation ( Allways not enough :-( ) - - Completion of above features - - Wrap missing widgets: Slider - Handle Image Fonts - Move Font config files to XML, too ... - Add support for fixed size 'Spacers'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine/extensions/pychan/events.py Tue Oct 14 07:41:48 2008 +0000 @@ -0,0 +1,204 @@ +#coding: utf-8 + +""" +PyChan event handling +===================== + +Users shouldn't need to use this module directly. +L{widgets.Widget.capture} and L{widgets.Widget.mapEvents} provide +a convenient API to capture events. + +Nevertheless to understand how its supposed to work +take a look at L{EventMapper} and L{EventListener} + +Available Events +---------------- + +""" + +import fife +import exceptions +import manager +import tools + +EVENTS = [ + "mouseEntered", + "mouseExited", + "mousePressed", + "mouseReleased", + "mouseClicked", + "mouseMoved", + "mouseDragged", + "action", + "keyPressed", + "keyReleased", +] + +# Add the EVENTS to the docs. +__doc__ += "".join([" - %s\n" % event for event in EVENTS]) + +MOUSE_EVENT, KEY_EVENT, ACTION_EVENT = range(3) +def getEventType(name): + if "mouse" in name: + return MOUSE_EVENT + if "key" in name: + return MOUSE_EVENT + return ACTION_EVENT + + +CALLBACK_NONE_MESSAGE = """\ +You passed None as parameter to %s.capture, which would normally remove a mapped event. +But there was no event mapped. Did you accidently call a function instead of passing it? +""" + +class EventListener(fife.GUIEventListener): + """ + Redirector for event callbacks. + Use *only* from L{EventMapper}. + + This class uses the SWIG director feature - overriden + virtual methods are called from C++ to - listen to + Guichan events. + + When the module is first loaded the event handler + methods are auto-generated from the list L{EVENTS}. + This is effectively the same code as:: + def mouseEntered(self,event): + self._redirectEvent("mouseEntered",event) + + This way L{EVENTS} and the actually receivable events + are forced to be in sync. + """ + def __init__(self,debug=True): + super(EventListener,self).__init__() + self.events = {} + self.indent = 0 + self.debug = debug + self.guimanager = manager.Manager.manager.guimanager + + def _redirectEvent(self,name,event): + self.indent += 4 + event = self.translateEvent(getEventType(name), event) + if name in self.events: + if self.debug: print "-"*self.indent, name + self.events[name]( event ) + self.indent -= 4 + + def translateEvent(self,event_type,event): + if event_type == MOUSE_EVENT: + return self.guimanager.translateMouseEvent(event) + if event_type == KEY_EVENT: + return self.guimanager.translateKeyEvent(event) + return event + +def _redirect(name): + def redirectorFunc(self,event): + self._redirectEvent(name,event) + return redirectorFunc + +for event_name in EVENTS: + setattr(EventListener,event_name,_redirect(event_name)) + +class EventMapper(object): + """ + Handles events and callbacks for L{widgets.Widget} + and derived classes. + + Every PyChan widget has an L{EventMapper} instance + as attribute *event_mapper*. + + This instance handles all necessary house-keeping. + Such an event mapper can be either *attached* or + *detached*. In its attached state an L{EventListener} + is added to the Guichan widget and will redirect + the events to the callbacks. + + In its detached state no events are received from the + real Guichan widget. + + The event mapper starts in the detached state. + When a new event is captured the mapper attaches itself + automatically. The widget doesn't need to handle that. + """ + def __init__(self,widget): + super(EventMapper,self).__init__() + self.widget = widget + self.listener = EventListener() + self.is_attached = False + self.debug = manager.Manager.manager.debug + + def __del__(self): + self.detach() + def __repr__(self): + return "EventMapper(%s)" % repr(self.widget) + + def attach(self): + """ + Start receiving events. + No need to call this manually. + """ + + if self.is_attached: + return + if not self.listener.events: + return + if self.debug: print "Attach:",self + self.widget.real_widget.addMouseListener( self.listener ) + self.widget.real_widget.addActionListener( self.listener ) + self.is_attached = True + + def detach(self): + """ + Stop receiving events. + No need to call this manually. + """ + + if not self.is_attached: + return + if self.debug: print "Detach:",self + self.widget.real_widget.removeMouseListener( self.listener ) + self.widget.real_widget.removeActionListener( self.listener ) + self.is_attached = False + + def capture(self,event_name,callback): + if event_name not in EVENTS: + raise exceptions.RuntimeError("Unknown eventname: " + event_name) + + if callback is None and not self.isCaptured(event_name): + if self.debug: + print CALLBACK_NONE_MESSAGE % str(self.widget) + return + + if callback is None: + del self.listener.events[event_name] + if not self.listener.events: + self.detach() + return + + if not callable(callback): + raise RuntimeError("An event callback must be either a callable or None - not %s" % repr(callback)) + + def captured_f(event): + tools.applyOnlySuitable(callback,event=event,widget=self.widget) + + self.listener.events[event_name] = captured_f + self.attach() + + def isCaptured(self,event_name): + return event_name in self.listener.events + + def getCapturedEvents(self): + return self.listener.events.keys() + + +def splitEventDescriptor(name): + """ Utility function to split "widgetName/eventName" descriptions into tuples. """ + L = name.split("/") + if len(L) == 1: + L = L[0],"action" + if len(L) != 2: + raise exceptions.RuntimeError("Invalid widgetname / eventname combination: " + name) + if L[1] not in EVENTS: + raise exceptions.RuntimeError("Unknown event name: " + name) + return L +
--- a/engine/extensions/pychan/manager.py Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/extensions/pychan/manager.py Tue Oct 14 07:41:48 2008 +0000 @@ -4,8 +4,9 @@ import widgets import fonts from exceptions import * +from traceback import print_exc -class Manager(fife.IWidgetListener): +class Manager(object): manager = None def __init__(self, engine, debug = False): @@ -26,13 +27,12 @@ self.styles = {} self.addStyle('default',DEFAULT_STYLE) - self.widgetEvents = {} - self.engine.getEventManager().addWidgetListener(self) Manager.manager = self + # Setup synchronous dialogs self.mainLoop = None self.breakFromMainLoop = None - self.can_execute = True + self.can_execute = False def setupModalExecution(self,mainLoop,breakFromMainLoop): """ @@ -128,15 +128,6 @@ index = self.engine.imagePool.addResourceFromFile(filename) return fife.GuiImage(index,self.engine.imagePool) - def defaultWidgetAction(self,event): - if self.debug: - print "Event(%s) received." % event.getId() - - def onWidgetAction(self, event): - #print event.getId(),self.widgetEvents - handler = self.widgetEvents.get( event.getId(), self.defaultWidgetAction ) - handler( event ) - # Default Widget style. DEFAULT_STYLE = {
--- a/engine/extensions/pychan/widgets.py Sun Oct 12 20:30:09 2008 +0000 +++ b/engine/extensions/pychan/widgets.py Tue Oct 14 07:41:48 2008 +0000 @@ -9,6 +9,7 @@ import fife, pythonize import tools +import events from exceptions import * from attrs import Attr,PointAttr,ColorAttr,BoolAttr,IntAttr,FloatAttr @@ -95,14 +96,14 @@ style = None, **kwargs): assert( hasattr(self,'real_widget') ) - self._has_listener = False + self.event_mapper = events.EventMapper(self) self._visible = False # Data distribution & retrieval settings self.accepts_data = False self.accepts_initial_data = False - self._parent = parent + self.parent = parent # This will also set the _event_id and call real_widget.setActionEventId self.name = name @@ -162,7 +163,7 @@ return False return True - def capture(self, callback): + def capture(self, callback, event_name="action"): """ Add a callback to be executed when the widget event occurs on this widget. @@ -172,37 +173,18 @@ wether this widgets events are currently captured. It might be useful to check out L{tools.callbackWithArguments}. - + + @param callback: Event callback - may accept keyword arguments event and widget. + @paran event_name: The event to capture - may be one of L{events.EVENTS} and defaults to "action" """ - if callback is None: - if not get_manager().widgetEvents.has_key(self._event_id): - if get_manager().debug: - print "You passed None as parameter to %s.capture, which would normally remove a mapped event." % str(self) - print "But there was no event mapped. Did you accidently call a function instead of passing it?" - else: - del get_manager().widgetEvents[self._event_id] - if self._has_listener: - self.real_widget.removeActionListener(get_manager().guimanager) - self._has_listener = None - return - - if not callable(callback): - raise RuntimeError("An event callback must be either a callable or None - not %s" % repr(callback)) - - def captured_f(event): - tools.applyOnlySuitable(callback,event=event,widget=self) - - get_manager().widgetEvents[self._event_id] = captured_f - if not self._has_listener: - self.real_widget.addActionListener(get_manager().guimanager) - self._has_listener = True + self.event_mapper.capture( event_name, callback ) def isCaptured(self): """ Check whether this widgets events are captured (a callback is installed) or not. """ - return self._has_listener + return bool(self.event_mapper.getCapturedEvents()) def show(self): """ @@ -223,7 +205,9 @@ if self._parent: raise RuntimeError(Widget.HIDE_SHOW_ERROR) if not self._visible: return + get_manager().hide(self) + self.afterHide() self._visible = False @@ -318,14 +302,27 @@ You can also pass C{None} instead of a callback, which will disable the event completely. - @param eventMap: A dictionary with widget names as keys and callbacks as values. + @param eventMap: A dictionary with widget/event names as keys and callbacks as values. @param ignoreMissing: Normally this method raises an RuntimeError, when a widget can not be found - this behaviour can be overriden by passing True here. + + The keys in the dictionary are parsed as "widgetName/eventName" with the slash + separating the two. If no slash is found the eventName is assumed to be "action". + + Example:: + guiElement.mapEvents({ + "button" : guiElement.hide, + "button/mouseEntered" : toggleButtonColorGreen, + "button/mouseExited" : toggleButtonColorBlue, + }) + """ - for name,func in eventMap.items(): + for descr,func in eventMap.items(): + name, event_name = events.splitEventDescriptor(descr) + print name, event_name widget = self.findChild(name=name) if widget: - widget.capture( func ) + widget.capture( func, event_name = event_name ) elif not ignoreMissing: raise RuntimeError("No widget with the name: %s" % name) @@ -594,25 +591,21 @@ self.real_widget.setSelectionColor(color) selection_color = property(_getSelectionColor,_setSelectionColor) - def _getName(self): return self._name - def _setName(self,name): - from pychan import manager - self._name = name - # Do not change the event id while we are captured. - if not self.isCaptured(): - self._event_id = "%s(name=%s,id=%d)" % (str(self.__class__),name,id(self)) - else: - # Print some notfication, so obscure behaviour might get debugged. - print "%s already captured, but changing the name attribute. Just a notification :-)" % str(self) - self.real_widget.setActionEventId(self._event_id) - name = property(_getName,_setName) - def _getStyle(self): return self._style def _setStyle(self,style): self._style = style get_manager().stylize(self,style) style = property(_getStyle,_setStyle) + def _getParent(self): return self._parent + def _setParent(self,parent): + self._parent = parent + parent = property(_getParent,_setParent) + + def _setName(self,name): self._name = name + def _getName(self): return self._name + name = property(_getName,_setName) + x = property(_getX,_setX) y = property(_getY,_setY) width = property(_getWidth,_setWidth) @@ -622,6 +615,32 @@ font = property(_getFont,_setFont) border_size = property(_getBorderSize,_setBorderSize) + def setEnterCallback(self, cb): + """ + *DEPRECATED* + + Callback is called when mouse enters the area of Widget + callback should have form of function(button) + """ + def callback(widget=None): + return cb(widget) + print "PyChan: You are using the DEPRECATED functionality: setEnterCallback." + self.capture(callback, event_name = "mouseEntered" ) + + def setExitCallback(self, cb): + """ + *DEPRECATED* + + Callback is called when mouse exits the area of Widget + callback should have form of function(button) + """ + def callback(widget=None): + return cb(widget) + print "PyChan: You are using the DEPRECATED functionality: setExitCallback." + self.capture(callback, event_name = "mouseExited" ) + + + ### Containers + Layout code ### class Container(Widget): @@ -654,7 +673,7 @@ super(Container,self).__init__(**kwargs) def addChild(self, widget): - widget._parent = self + widget.parent = self self.children.append(widget) self.real_widget.add(widget.real_widget) @@ -663,7 +682,7 @@ raise RuntimeError("%s does not have %s as direct child widget." % (str(self),str(widget))) self.children.remove(widget) self.real_widget.remove(widget.real_widget) - widget._parent = None + widget.parent = None def add(self,*widgets): print "PyChan: Deprecation warning: Please use 'addChild' or 'addChildren' instead." @@ -1028,26 +1047,6 @@ return self._image image = property(_getImage,_setImage) -class LabelListener(fife.ClickLabelListener): - """ the listener class for label onMouse events - - @type btn: object - @param btn: the label widget - """ - def __init__(self, lbl): - fife.ClickLabelListener.__init__(self) - self.lbl = lbl - self.entercb = None - self.exitcb = None - - def mouseEntered(self, lbl): - if self.entercb: - self.entercb(self.lbl) - - def mouseExited(self, lbl): - if self.exitcb: - self.exitcb(self.lbl) - class Label(BasicTextWidget): """ A basic label - displaying a string. @@ -1070,8 +1069,6 @@ self.real_widget = fife.Label("") self.wrap_text = wrap_text super(Label,self).__init__(**kwargs) - self.listener = LabelListener(self) - self.real_widget.setListener(self.listener) def resizeToContent(self): self.real_widget.setWidth( self.max_size[0] ) @@ -1084,20 +1081,6 @@ def _getTextWrapping(self): self.real_widget.isTextWrapping() wrap_text = property(_getTextWrapping,_setTextWrapping) - def setEnterCallback(self, cb): - """ - Callback is called when mouse enters the area of Label - callback should have form of function(button) - """ - self.listener.entercb = cb - - def setExitCallback(self, cb): - """ - Callback is called when mouse enters the area of Label - callback should have form of function(button) - """ - self.listener.exitcb = cb - class ClickLabel(Label): """ Deprecated - use L{Label} instead. @@ -1113,21 +1096,6 @@ self.real_widget = fife.Button("") super(Button,self).__init__(**kwargs) -class ImageButtonListener(fife.TwoButtonListener): - def __init__(self, btn): - fife.TwoButtonListener.__init__(self) - self.btn = btn - self.entercb = None - self.exitcb = None - - def mouseEntered(self, btn): - if self.entercb: - self.entercb(self.btn) - - def mouseExited(self, btn): - if self.exitcb: - self.exitcb(self.btn) - class ImageButton(BasicTextWidget): """ A basic push button with three different images for the up, down and hover state. @@ -1147,8 +1115,6 @@ def __init__(self,up_image="",down_image="",hover_image="",offset=(0,0),**kwargs): self.real_widget = fife.TwoButton() super(ImageButton,self).__init__(**kwargs) - self.listener = ImageButtonListener(self) - self.real_widget.setListener(self.listener) self.up_image = up_image self.down_image = down_image @@ -1201,21 +1167,6 @@ self.height = max(self._upimage.getHeight(),self._downimage.getHeight(),self._hoverimage.getHeight()) + self.margins[1]*2 self.width = max(self._upimage.getWidth(),self._downimage.getWidth(),self._hoverimage.getWidth()) + self.margins[1]*2 - def setEnterCallback(self, cb): - """ - Callback is called when mouse enters the area of ImageButton - callback should have form of function(button) - """ - self.listener.entercb = cb - - def setExitCallback(self, cb): - """ - Callback is called when mouse enters the area of ImageButton - callback should have form of function(button) - """ - self.listener.exitcb = cb - - class CheckBox(BasicTextWidget): """ @@ -1548,11 +1499,13 @@ def addChild(self,widget): self.content = widget + widget.parent = self def removeChild(self,widget): if self._content != widget: raise RuntimeError("%s does not have %s as direct child widget." % (str(self),str(widget))) self.content = None + widget.parent = None def _setContent(self,content): self.real_widget.setContent(content.real_widget)