rework walk

This commit is contained in:
Eduardo Bart
2012-01-19 02:12:53 -02:00
parent 4491ee8bdd
commit 6ce92a1a64
22 changed files with 478 additions and 228 deletions

View File

@@ -26,6 +26,11 @@
#include <framework/global.h>
class Module;
class Event;
class ScheduledEvent;
typedef std::shared_ptr<Module> ModulePtr;
typedef std::shared_ptr<Event> EventPtr;
typedef std::shared_ptr<ScheduledEvent> ScheduledEventPtr;
#endif

View File

@@ -37,29 +37,34 @@ void EventDispatcher::flush()
void EventDispatcher::poll()
{
while(!m_scheduledEventList.empty()) {
if(g_clock.ticks() < m_scheduledEventList.top().ticks)
ScheduledEventPtr scheduledEvent = m_scheduledEventList.top();
if(scheduledEvent->reamaningTicks() > 0)
break;
SimpleCallback callback = std::move(m_scheduledEventList.top().callback);
m_scheduledEventList.pop();
callback();
scheduledEvent->execute();
}
while(!m_eventList.empty()) {
m_eventList.front()();
EventPtr event = m_eventList.front();
m_eventList.pop_front();
event->execute();
}
}
void EventDispatcher::scheduleEvent(const SimpleCallback& callback, int delay)
ScheduledEventPtr EventDispatcher::scheduleEvent(const SimpleCallback& callback, int delay)
{
assert(delay >= 0);
m_scheduledEventList.push(ScheduledEvent(g_clock.ticksFor(delay), callback));
ScheduledEventPtr scheduledEvent(new ScheduledEvent(callback, delay));
m_scheduledEventList.push(scheduledEvent);
return scheduledEvent;
}
void EventDispatcher::addEvent(const SimpleCallback& callback, bool pushFront)
EventPtr EventDispatcher::addEvent(const SimpleCallback& callback, bool pushFront)
{
EventPtr event(new Event(callback));
if(pushFront)
m_eventList.push_front(callback);
m_eventList.push_front(event);
else
m_eventList.push_back(callback);
m_eventList.push_back(event);
return event;
}

View File

@@ -24,12 +24,49 @@
#define EVENTDISPATCHER_H
#include "declarations.h"
#include "clock.h"
#include <framework/luascript/luaobject.h>
struct ScheduledEvent {
ScheduledEvent(ticks_t ticks, const SimpleCallback& callback) : ticks(ticks), callback(callback) { }
bool operator<(const ScheduledEvent& other) const { return ticks > other.ticks; }
ticks_t ticks;
SimpleCallback callback;
class Event : public LuaObject
{
public:
Event(const SimpleCallback& callback) : m_callback(callback), m_canceled(false), m_executed(false) { }
void execute() {
if(!m_canceled) {
m_callback();
m_executed = true;
}
}
void cancel() { m_canceled = true; }
bool isCanceled() { return m_canceled; }
bool isExecuted() { return m_executed; }
protected:
SimpleCallback m_callback;
bool m_canceled;
bool m_executed;
};
class ScheduledEvent : public Event
{
public:
ScheduledEvent(const SimpleCallback& callback, int delay) : Event(callback) {
m_ticks = g_clock.ticksFor(delay);
}
int ticks() const { return m_ticks; }
int reamaningTicks() const { return m_ticks - g_clock.ticks(); }
private:
ticks_t m_ticks;
};
struct lessScheduledEvent : std::binary_function<ScheduledEventPtr, ScheduledEventPtr&, bool> {
bool operator()(const ScheduledEventPtr& a, const ScheduledEventPtr& b) const {
return b->ticks() < a->ticks();
}
};
class EventDispatcher
@@ -38,12 +75,12 @@ public:
void flush();
void poll();
void addEvent(const SimpleCallback& callback, bool pushFront = false);
void scheduleEvent(const SimpleCallback& callback, int delay);
EventPtr addEvent(const SimpleCallback& callback, bool pushFront = false);
ScheduledEventPtr scheduleEvent(const SimpleCallback& callback, int delay);
private:
std::list<SimpleCallback> m_eventList;
std::priority_queue<ScheduledEvent> m_scheduledEventList;
std::list<EventPtr> m_eventList;
std::priority_queue<ScheduledEventPtr, std::vector<ScheduledEventPtr>, lessScheduledEvent> m_scheduledEventList;
};
extern EventDispatcher g_dispatcher;

View File

@@ -43,6 +43,14 @@ void Application::registerLuaFunctions()
g_lua.bindGlobalFunction("colortostring", [](const Color& v) { return Fw::tostring(v); });
g_lua.bindGlobalFunction("sizetostring", [](const Size& v) { return Fw::tostring(v); });
// Event
g_lua.registerClass<Event>();
g_lua.bindClassMemberFunction<Event>("isCanceled", &Event::isCanceled);
g_lua.bindClassMemberFunction<Event>("isExecuted", &Event::isExecuted);
// ScheduledEvent
g_lua.registerClass<ScheduledEvent, Event>();
// UIWidget
g_lua.registerClass<UIWidget>();
g_lua.bindClassStaticFunction<UIWidget>("create", []{ return UIWidgetPtr(new UIWidget); });

View File

@@ -119,4 +119,4 @@ T LuaObject::getLuaField(const std::string& key) {
return g_lua.polymorphicPop<T>();
}
#endif
#endif

View File

@@ -351,16 +351,12 @@ void *WIN32Window::getExtensionProcAddress(const char *ext)
void WIN32Window::move(const Point& pos)
{
RECT windowRect = {pos.x, pos.y, m_pos.x + m_size.width(), m_pos.y + m_size.height()};
AdjustWindowRectEx(&windowRect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
MoveWindow(m_window, windowRect.left, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, TRUE);
MoveWindow(m_window, pos.x, pos.y, m_size.width(), m_size.height(), TRUE);
}
void WIN32Window::resize(const Size& size)
{
RECT windowRect = {m_pos.x, m_pos.y, m_pos.x + size.width(), m_pos.y + size.height()};
AdjustWindowRectEx(&windowRect, WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW | WS_EX_WINDOWEDGE);
MoveWindow(m_window, windowRect.left, windowRect.top, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, TRUE);
MoveWindow(m_window, m_pos.x, m_pos.y, size.width(), size.height(), TRUE);
}
void WIN32Window::show()
@@ -400,7 +396,6 @@ void WIN32Window::poll()
LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
m_inputEvent.reset();
switch(uMsg)
{
case WM_ACTIVATE: {
@@ -411,6 +406,8 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
if(wParam >= 32 && wParam <= 255) {
m_inputEvent.reset(Fw::KeyTextInputEvent);
m_inputEvent.keyText = wParam;
if(m_onInputEvent)
m_onInputEvent(m_inputEvent);
}
break;
}
@@ -429,31 +426,43 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
case WM_LBUTTONDOWN: {
m_inputEvent.reset(Fw::MousePressInputEvent);
m_inputEvent.mouseButton = Fw::MouseLeftButton;
if(m_onInputEvent)
m_onInputEvent(m_inputEvent);
break;
}
case WM_LBUTTONUP: {
m_inputEvent.reset(Fw::MouseReleaseInputEvent);
m_inputEvent.mouseButton = Fw::MouseLeftButton;
if(m_onInputEvent)
m_onInputEvent(m_inputEvent);
break;
}
case WM_MBUTTONDOWN: {
m_inputEvent.reset(Fw::MousePressInputEvent);
m_inputEvent.mouseButton = Fw::MouseMidButton;
if(m_onInputEvent)
m_onInputEvent(m_inputEvent);
break;
}
case WM_MBUTTONUP: {
m_inputEvent.reset(Fw::MouseReleaseInputEvent);
m_inputEvent.mouseButton = Fw::MouseMidButton;
if(m_onInputEvent)
m_onInputEvent(m_inputEvent);
break;
}
case WM_RBUTTONDOWN: {
m_inputEvent.reset(Fw::MousePressInputEvent);
m_inputEvent.mouseButton = Fw::MouseRightButton;
if(m_onInputEvent)
m_onInputEvent(m_inputEvent);
break;
}
case WM_RBUTTONUP: {
m_inputEvent.reset(Fw::MouseReleaseInputEvent);
m_inputEvent.mouseButton = Fw::MouseRightButton;
if(m_onInputEvent)
m_onInputEvent(m_inputEvent);
break;
}
case WM_MOUSEMOVE: {
@@ -461,11 +470,15 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
Point newMousePos(LOWORD(lParam), HIWORD(lParam));
m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos;
m_inputEvent.mousePos = newMousePos;
if(m_onInputEvent)
m_onInputEvent(m_inputEvent);
break;
}
case WM_MOUSEWHEEL: {
m_inputEvent.mouseButton = Fw::MouseMidButton;
m_inputEvent.wheelDirection = HIWORD(wParam) > 0 ? Fw::MouseWheelUp : Fw::MouseWheelDown;
if(m_onInputEvent)
m_onInputEvent(m_inputEvent);
break;
}
case WM_MOVE: {
@@ -494,8 +507,6 @@ LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
if(m_onInputEvent && m_inputEvent.type != Fw::NoInputEvent)
m_onInputEvent(m_inputEvent);
return 0;
}

View File

@@ -193,26 +193,27 @@ void UIWidget::removeChild(const UIWidgetPtr& child)
void UIWidget::focusChild(const UIWidgetPtr& child, Fw::FocusReason reason)
{
if(child == m_focusedChild)
return;
if(child && !hasChild(child)) {
logError("Attempt to focus an unknown child in a UIWidget");
logError("attempt to focus an unknown child in a UIWidget");
return;
}
if(child != m_focusedChild) {
UIWidgetPtr oldFocused = m_focusedChild;
m_focusedChild = child;
UIWidgetPtr oldFocused = m_focusedChild;
m_focusedChild = child;
if(child) {
child->setLastFocusReason(reason);
child->updateState(Fw::FocusState);
child->updateState(Fw::ActiveState);
}
if(child) {
child->setLastFocusReason(reason);
child->updateState(Fw::FocusState);
child->updateState(Fw::ActiveState);
}
if(oldFocused) {
oldFocused->setLastFocusReason(reason);
oldFocused->updateState(Fw::FocusState);
oldFocused->updateState(Fw::ActiveState);
}
if(oldFocused) {
oldFocused->setLastFocusReason(reason);
oldFocused->updateState(Fw::FocusState);
oldFocused->updateState(Fw::ActiveState);
}
}
@@ -389,6 +390,8 @@ void UIWidget::addAnchor(Fw::AnchorEdge anchoredEdge, const std::string& hookedW
{
if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout())
anchorLayout->addAnchor(asUIWidget(), anchoredEdge, hookedWidgetId, hookedEdge);
else
logError("cannot add anchors to widget ", m_id, ": the parent doesn't use anchors layout");
}
void UIWidget::centerIn(const std::string& hookedWidgetId)
@@ -396,7 +399,8 @@ void UIWidget::centerIn(const std::string& hookedWidgetId)
if(UIAnchorLayoutPtr anchorLayout = getAnchoredLayout()) {
anchorLayout->addAnchor(asUIWidget(), Fw::AnchorHorizontalCenter, hookedWidgetId, Fw::AnchorHorizontalCenter);
anchorLayout->addAnchor(asUIWidget(), Fw::AnchorVerticalCenter, hookedWidgetId, Fw::AnchorVerticalCenter);
}
} else
logError("cannot add anchors to widget ", m_id, ": the parent doesn't use anchors layout");
}
void UIWidget::fill(const std::string& hookedWidgetId)
@@ -406,7 +410,8 @@ void UIWidget::fill(const std::string& hookedWidgetId)
anchorLayout->addAnchor(asUIWidget(), Fw::AnchorRight, hookedWidgetId, Fw::AnchorRight);
anchorLayout->addAnchor(asUIWidget(), Fw::AnchorTop, hookedWidgetId, Fw::AnchorTop);
anchorLayout->addAnchor(asUIWidget(), Fw::AnchorBottom, hookedWidgetId, Fw::AnchorBottom);
}
} else
logError("cannot add anchors to widget ", m_id, ": the parent doesn't use anchors layout");
}
void UIWidget::breakAnchors()
@@ -732,17 +737,10 @@ Rect UIWidget::getChildrenRect()
UIAnchorLayoutPtr UIWidget::getAnchoredLayout()
{
UIWidgetPtr parent = getParent();
if(!parent) {
logError("cannot add anchors to widget ", m_id, ": there is no parent");
if(!parent)
return nullptr;
}
UIAnchorLayoutPtr anchorLayout = parent->getLayout()->asUIAnchorLayout();
if(!anchorLayout) {
logError("cannot add anchors to widget ", m_id, ": the parent doesn't use anchors layout");
return nullptr;
}
return anchorLayout;
return parent->getLayout()->asUIAnchorLayout();
}
UIWidgetPtr UIWidget::getRootParent()
@@ -1190,38 +1188,38 @@ bool UIWidget::propagateOnKeyUp(uchar keyCode, int keyboardModifiers)
bool UIWidget::propagateOnMousePress(const Point& mousePos, Fw::MouseButton button)
{
// do a backup of children list, because it may change while looping it
UIWidgetList children;
UIWidgetPtr clickedChild;
for(const UIWidgetPtr& child : m_children) {
// events on hidden or disabled widgets are discarded
if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible())
continue;
// mouse press events only go to children that contains the mouse position
if(child->containsPoint(mousePos) && child == getChildByPos(mousePos))
children.push_back(child);
if(child->containsPoint(mousePos) && child == getChildByPos(mousePos)) {
clickedChild = child;
break;
}
}
for(const UIWidgetPtr& child : children) {
// when a focusable item is focused it must gain focus
if(child->isFocusable())
focusChild(child, Fw::MouseFocusReason);
if(clickedChild) {
// focusable child gains focus when clicked
if(clickedChild->isFocusable())
focusChild(clickedChild, Fw::MouseFocusReason);
bool mustEnd = child->propagateOnMousePress(mousePos, button);
if(button == Fw::MouseLeftButton && !child->isPressed()) {
UIWidgetPtr clickedChild = child->getChildByPos(mousePos);
if(!clickedChild || clickedChild->isPhantom())
child->setPressed(true);
}
if(mustEnd)
// stop propagating if the child accept the event
if(clickedChild->propagateOnMousePress(mousePos, button))
return true;
}
if(!isPhantom())
return onMousePress(mousePos, button);
else
return false;
// only non phatom widgets receives mouse press events
if(!isPhantom()) {
onMousePress(mousePos, button);
if(button == Fw::MouseLeftButton && !isPressed())
setPressed(true);
return true;
}
return false;
}
void UIWidget::propagateOnMouseRelease(const Point& mousePos, Fw::MouseButton button)
@@ -1239,12 +1237,12 @@ void UIWidget::propagateOnMouseRelease(const Point& mousePos, Fw::MouseButton bu
for(const UIWidgetPtr& child : children) {
child->propagateOnMouseRelease(mousePos, button);
if(child->isPressed() && button == Fw::MouseLeftButton)
child->setPressed(false);
}
onMouseRelease(mousePos, button);
if(isPressed() && button == Fw::MouseLeftButton)
setPressed(false);
}
bool UIWidget::propagateOnMouseMove(const Point& mousePos, const Point& mouseMoved)