From 90600bbd69fc6ade3235805044c86db9b19048d8 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Mon, 2 Jan 2012 20:09:49 -0200 Subject: [PATCH] make menu work --- modules/core_styles/styles/popupmenus.otui | 8 ++-- modules/core_widgets/uipopupmenu.lua | 44 ++++++++++++++----- modules/game_inventory/inventory.lua | 10 +++-- modules/game_inventory/inventory.otui | 3 +- src/framework/luafunctions.cpp | 8 ++++ src/framework/ui/uimanager.cpp | 16 ++++--- src/framework/ui/uimanager.h | 12 +++-- src/framework/ui/uiwidget.cpp | 51 +++++++++++++++++++--- src/framework/ui/uiwidget.h | 8 ++++ src/framework/ui/uiwindow.cpp | 11 +---- 10 files changed, 126 insertions(+), 45 deletions(-) diff --git a/modules/core_styles/styles/popupmenus.otui b/modules/core_styles/styles/popupmenus.otui index 8bd47394..a8006386 100644 --- a/modules/core_styles/styles/popupmenus.otui +++ b/modules/core_styles/styles/popupmenus.otui @@ -17,11 +17,11 @@ PopupMenuButton < UIButton $disabled: color: #555555 -PopupMenuFirstButton < PopupMenuButton - margin-top: 3 + $first: + margin-top: 3 -PopupMenuLastButton < PopupMenuButton - margin-bottom: 3 + $last: + margin-bottom: 3 PopupMenuSeparator < UIWidget margin-left: 2 diff --git a/modules/core_widgets/uipopupmenu.lua b/modules/core_widgets/uipopupmenu.lua index 0605571d..ad49efd3 100644 --- a/modules/core_widgets/uipopupmenu.lua +++ b/modules/core_widgets/uipopupmenu.lua @@ -7,28 +7,50 @@ function UIPopupMenu.create() local layout = UIVerticalLayout.create(menu) layout:setFitParent(true) menu:setLayout(layout) + menu:setStyle('PopupMenu') return menu end -function UIPopupMenu.display(otui, pos) - local menu = UI.display(otui, {x = pos.x, y = pos.y}) +function UIPopupMenu.display(menu, pos) + UI.display(menu, {x = pos.x, y = pos.y}) + menu:bindRectToParent() + menu:grabMouse() + menu:grabKeyboard() return menu end --- hooked events -local function onWidgetStyleApply(widget, style) - if style and style.popupmenu then - widget.popupmenu = style.popupmenu +function UIPopupMenu.addOption(menu, optionName, optionCallback) + local optionWidget = UIButton.create() + local lastOptionWidget = menu:getLastChild() + optionWidget.onClick = function() + optionCallback() + menu:destroy() end + optionWidget:setText(optionName) + optionWidget:setStyle('PopupMenuButton') + menu:addChild(optionWidget) +end + +function UIPopupMenu.addSeparator(menu) + local separatorWidget = UIWidget.create() + separatorWidget:setStyle('PopupMenuSeparator') + menu:addChild(separator) end -local function onWidgetMousePress(widget, mousePos, mouseButton) - if widget.popupmenu and mouseButton == MouseRightButton then - UIPopupMenu.display(widget.popupmenu, mousePos) +-- hooked events +function UIPopupMenu.onMousePress(menu, mousePos, mouseButton) + -- clicks outside menu area destroys the menu + if not menu:containsPoint(mousePos) then + menu:destroy() return true end return false end -connect(UIWidget, { onStyleApply = onWidgetStyleApply, - onMousePress = onWidgetMousePress }) \ No newline at end of file +function UIPopupMenu.onKeyPress(menu, keyCode, keyText, keyboardModifiers) + if keyCode == KeyEscape then + menu:destroy() + return true + end + return false +end diff --git a/modules/game_inventory/inventory.lua b/modules/game_inventory/inventory.lua index d4a60dc6..f4bc070e 100644 --- a/modules/game_inventory/inventory.lua +++ b/modules/game_inventory/inventory.lua @@ -17,9 +17,6 @@ local InventorySlotAmmo = 10 -- public functions function Inventory.create() window = UI.display('inventory.otui', { parent = Game.gameRightPanel }) - - local itemWidget = window:getChildById('feet') - window:setHeight(itemWidget:getPosition().y + itemWidget:getHeight() - window:getPosition().y) end function Inventory.destroy() @@ -66,6 +63,13 @@ function Inventory.onSoulChange(soul) widget:setText("Soul:\n" .. soul) end +function Inventory.onInventoryItemMousePress(itemWidget, mousePos, mouseButton) + local menu = UIPopupMenu.create() + menu:addOption('Look', function() print('look') end) + menu:addOption('Use', function() print('use') end) + menu:display(mousePos) +end + connect(Game, { onLogin = Inventory.create, onLogout = Inventory.destroy, onInventoryChange = Inventory.onInventoryChange, diff --git a/modules/game_inventory/inventory.otui b/modules/game_inventory/inventory.otui index 33eae15e..cc544d11 100644 --- a/modules/game_inventory/inventory.otui +++ b/modules/game_inventory/inventory.otui @@ -1,8 +1,9 @@ InvetoryItem < Item - popupmenu: /game_inventory/itempopupmenu.otui + &onMousePress: Inventory.onInventoryItemMousePress UIWindow width: 192 + height: 148 margin-top: 10 margin-left: 6 margin-right: 6 diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index ffc1f421..d7f0ae90 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -63,6 +63,7 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("setMarginLeft", &UIWidget::setMarginLeft); g_lua.bindClassMemberFunction("setSizeFixed", &UIWidget::setSizeFixed); g_lua.bindClassMemberFunction("setLastFocusReason", &UIWidget::setLastFocusReason); + g_lua.bindClassMemberFunction("bindRectToParent", &UIWidget::bindRectToParent); g_lua.bindClassMemberFunction("resize", &UIWidget::resize); g_lua.bindClassMemberFunction("moveTo", &UIWidget::moveTo); g_lua.bindClassMemberFunction("hide", &UIWidget::hide); @@ -72,6 +73,10 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("lock", &UIWidget::lock); g_lua.bindClassMemberFunction("unlock", &UIWidget::unlock); g_lua.bindClassMemberFunction("focus", &UIWidget::focus); + g_lua.bindClassMemberFunction("grabMouse", &UIWidget::grabMouse); + g_lua.bindClassMemberFunction("ungrabMouse", &UIWidget::ungrabMouse); + g_lua.bindClassMemberFunction("grabKeyboard", &UIWidget::grabKeyboard); + g_lua.bindClassMemberFunction("ungrabKeyboard", &UIWidget::ungrabKeyboard); g_lua.bindClassMemberFunction("isActive", &UIWidget::isActive); g_lua.bindClassMemberFunction("isEnabled", &UIWidget::isEnabled); g_lua.bindClassMemberFunction("isDisabled", &UIWidget::isDisabled); @@ -85,6 +90,7 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("isFocusable", &UIWidget::isFocusable); g_lua.bindClassMemberFunction("isPhantom", &UIWidget::isPhantom); g_lua.bindClassMemberFunction("isSizeFixed", &UIWidget::isSizeFixed); + g_lua.bindClassMemberFunction("containsPoint", &UIWidget::containsPoint); g_lua.bindClassMemberFunction("hasChildren", &UIWidget::hasChildren); g_lua.bindClassMemberFunction("hasChild", &UIWidget::hasChild); g_lua.bindClassMemberFunction("getId", &UIWidget::getId); @@ -117,6 +123,8 @@ void Application::registerLuaFunctions() g_lua.bindClassMemberFunction("getChildById", &UIWidget::getChildById); g_lua.bindClassMemberFunction("getChildByPos", &UIWidget::getChildByPos); g_lua.bindClassMemberFunction("getChildByIndex", &UIWidget::getChildByIndex); + g_lua.bindClassMemberFunction("getFirstChild", &UIWidget::getFirstChild); + g_lua.bindClassMemberFunction("getLastChild", &UIWidget::getLastChild); g_lua.bindClassMemberFunction("recursiveGetChildById", &UIWidget::recursiveGetChildById); g_lua.bindClassMemberFunction("recursiveGetChildByPos", &UIWidget::recursiveGetChildByPos); g_lua.bindClassMemberFunction("backwardsGetWidgetById", &UIWidget::backwardsGetWidgetById); diff --git a/src/framework/ui/uimanager.cpp b/src/framework/ui/uimanager.cpp index edbefb48..79fd1265 100644 --- a/src/framework/ui/uimanager.cpp +++ b/src/framework/ui/uimanager.cpp @@ -35,6 +35,8 @@ void UIManager::init() m_rootWidget = UIWidget::create(); m_rootWidget->setId("root"); m_rootWidget->resize(g_window.getSize()); + m_mouseReceiver = m_rootWidget; + m_keyboardReceiver = m_rootWidget; } void UIManager::terminate() @@ -58,23 +60,23 @@ void UIManager::inputEvent(const InputEvent& event) { switch(event.type) { case Fw::KeyPressInputEvent: - m_rootWidget->onKeyPress(event.keyCode, event.keyText, event.keyboardModifiers); + m_keyboardReceiver->onKeyPress(event.keyCode, event.keyText, event.keyboardModifiers); break; case Fw::KeyReleaseInputEvent: - m_rootWidget->onKeyRelease(event.keyCode, event.keyText, event.keyboardModifiers); + m_keyboardReceiver->onKeyRelease(event.keyCode, event.keyText, event.keyboardModifiers); break; case Fw::MousePressInputEvent: - m_rootWidget->onMousePress(event.mousePos, event.mouseButton); + m_keyboardReceiver->onMousePress(event.mousePos, event.mouseButton); break; case Fw::MouseReleaseInputEvent: - m_rootWidget->onMouseRelease(event.mousePos, event.mouseButton); + m_mouseReceiver->onMouseRelease(event.mousePos, event.mouseButton); break; case Fw::MouseMoveInputEvent: - m_rootWidget->updateState(Fw::HoverState); - m_rootWidget->onMouseMove(event.mousePos, event.mouseMoved); + m_mouseReceiver->updateState(Fw::HoverState); + m_mouseReceiver->onMouseMove(event.mousePos, event.mouseMoved); break; case Fw::MouseWheelInputEvent: - m_rootWidget->onMouseWheel(event.mousePos, event.wheelDirection); + m_mouseReceiver->onMouseWheel(event.mousePos, event.wheelDirection); break; }; } diff --git a/src/framework/ui/uimanager.h b/src/framework/ui/uimanager.h index 817591b9..3051e98e 100644 --- a/src/framework/ui/uimanager.h +++ b/src/framework/ui/uimanager.h @@ -44,15 +44,19 @@ public: UIWidgetPtr loadUI(const std::string& file, const UIWidgetPtr& parent = nullptr); UIWidgetPtr loadWidgetFromOTML(const OTMLNodePtr& widgetNode, const UIWidgetPtr& parent); - //void setMouseGrabWidget(); - //void setKeyboardGrabWidget(); + void setMouseReceiver(const UIWidgetPtr& widget) { m_mouseReceiver = widget; } + void setKeyboardReceiver(const UIWidgetPtr& widget) { m_keyboardReceiver = widget; } + void resetMouseReceiver() { m_mouseReceiver = m_rootWidget; } + void resetKeyboardReceiver() { m_keyboardReceiver = m_rootWidget; } + UIWidgetPtr getMouseReceiver() { return m_mouseReceiver; } + UIWidgetPtr getKeyboardReceiver() { return m_keyboardReceiver; } UIWidgetPtr getRootWidget() { return m_rootWidget; } private: UIWidgetPtr m_rootWidget; - //UIWidgetPtr m_mouseGrabWidget; - //UIWidgetPtr m_keyboardGrabWidget; + UIWidgetPtr m_mouseReceiver; + UIWidgetPtr m_keyboardReceiver; std::map m_styles; }; diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index a39bb616..e5ff3190 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -52,6 +52,13 @@ void UIWidget::destroy() setVisible(false); setEnabled(false); + // release input grabs + if(g_ui.getKeyboardReceiver() == asUIWidget()) + g_ui.resetKeyboardReceiver(); + + if(g_ui.getMouseReceiver() == asUIWidget()) + g_ui.resetMouseReceiver(); + // remove itself from parent if(UIWidgetPtr parent = getParent()) { if(parent->hasChild(asUIWidget())) @@ -207,6 +214,18 @@ void UIWidget::setRect(const Rect& rect) m_updateEventScheduled = true; } +void UIWidget::bindRectToParent() +{ + Rect boundRect = m_rect; + UIWidgetPtr parent = getParent(); + if(parent) { + Rect parentRect = parent->getRect(); + boundRect.bound(parentRect); + } + + setRect(boundRect); +} + void UIWidget::lock() { if(UIWidgetPtr parent = getParent()) @@ -227,6 +246,28 @@ void UIWidget::focus() parent->focusChild(asUIWidget(), Fw::ActiveFocusReason); } +void UIWidget::grabMouse() +{ + g_ui.setMouseReceiver(asUIWidget()); +} + +void UIWidget::ungrabMouse() +{ + if(g_ui.getMouseReceiver() == asUIWidget()) + g_ui.resetMouseReceiver(); +} + +void UIWidget::grabKeyboard() +{ + g_ui.setKeyboardReceiver(asUIWidget()); +} + +void UIWidget::ungrabKeyboard() +{ + if(g_ui.getKeyboardReceiver() == asUIWidget()) + g_ui.resetKeyboardReceiver(); +} + bool UIWidget::isVisible() { if(!m_visible) @@ -282,7 +323,7 @@ UIWidgetPtr UIWidget::getChildByPos(const Point& childPos) { for(auto it = m_children.rbegin(); it != m_children.rend(); ++it) { const UIWidgetPtr& widget = (*it); - if(widget->isExplicitlyVisible() && widget->getRect().contains(childPos)) + if(widget->isExplicitlyVisible() && widget->containsPoint(childPos)) return widget; } @@ -313,7 +354,7 @@ UIWidgetPtr UIWidget::recursiveGetChildById(const std::string& id) UIWidgetPtr UIWidget::recursiveGetChildByPos(const Point& childPos) { for(const UIWidgetPtr& child : m_children) { - if(child->getRect().contains(childPos)) { + if(child->containsPoint(childPos)) { if(UIWidgetPtr subChild = child->recursiveGetChildByPos(childPos)) return subChild; return child; @@ -677,7 +718,7 @@ void UIWidget::updateState(Fw::WidgetState state) UIWidgetPtr parent; do { parent = widget->getParent(); - if(!widget->isExplicitlyEnabled() || !widget->isExplicitlyVisible() || !widget->getRect().contains(mousePos) || + if(!widget->isExplicitlyEnabled() || !widget->isExplicitlyVisible() || !widget->containsPoint(mousePos) || (parent && widget != parent->getChildByPos(mousePos))) { newStatus = false; break; @@ -1035,7 +1076,7 @@ bool UIWidget::onMousePress(const Point& mousePos, Fw::MouseButton button) continue; // mouse press events only go to children that contains the mouse position - if(child->getRect().contains(mousePos) && child == getChildByPos(mousePos)) + if(child->containsPoint(mousePos) && child == getChildByPos(mousePos)) children.push_back(child); } @@ -1119,7 +1160,7 @@ bool UIWidget::onMouseWheel(const Point& mousePos, Fw::MouseWheelDirection direc continue; // mouse wheel events only go to children that contains the mouse position - if(child->getRect().contains(mousePos) && child == getChildByPos(mousePos)) + if(child->containsPoint(mousePos) && child == getChildByPos(mousePos)) children.push_back(child); } diff --git a/src/framework/ui/uiwidget.h b/src/framework/ui/uiwidget.h index 5aaee097..d4cc395d 100644 --- a/src/framework/ui/uiwidget.h +++ b/src/framework/ui/uiwidget.h @@ -69,6 +69,7 @@ public: void setSizeFixed(bool fixed) { m_fixedSize = fixed; updateParentLayout(); } void setLastFocusReason(Fw::FocusReason reason) { m_lastFocusReason = reason; } + void bindRectToParent(); void resize(const Size& size) { setRect(Rect(getPosition(), size)); } void moveTo(const Point& pos) { setRect(Rect(pos, getSize())); } void hide() { setVisible(false); } @@ -78,6 +79,10 @@ public: void lock(); void unlock(); void focus(); + void grabMouse(); + void ungrabMouse(); + void grabKeyboard(); + void ungrabKeyboard(); bool isActive() { return hasState(Fw::ActiveState); } bool isEnabled() { return !hasState(Fw::DisabledState); } @@ -92,6 +97,7 @@ public: bool isFocusable() { return m_focusable; } bool isPhantom() { return m_phantom; } bool isSizeFixed() { return m_fixedSize; } + bool containsPoint(const Point& point) { return m_rect.contains(point); } bool hasChildren() { return m_children.size() > 0; } bool hasChild(const UIWidgetPtr& child); @@ -126,6 +132,8 @@ public: UIWidgetPtr getChildById(const std::string& childId); UIWidgetPtr getChildByPos(const Point& childPos); UIWidgetPtr getChildByIndex(int index); + UIWidgetPtr getFirstChild() { return getChildByIndex(1); } + UIWidgetPtr getLastChild() { return getChildByIndex(-1); } UIWidgetPtr recursiveGetChildById(const std::string& id); UIWidgetPtr recursiveGetChildByPos(const Point& childPos); UIWidgetPtr backwardsGetWidgetById(const std::string& id); diff --git a/src/framework/ui/uiwindow.cpp b/src/framework/ui/uiwindow.cpp index e15c3359..d637fecc 100644 --- a/src/framework/ui/uiwindow.cpp +++ b/src/framework/ui/uiwindow.cpp @@ -82,16 +82,7 @@ void UIWindow::onStyleApply(const OTMLNodePtr& styleNode) void UIWindow::onGeometryUpdate(const Rect& oldRect, const Rect& newRect) { - // bind window rect to parent rect - Rect boundRect = newRect; - UIWidgetPtr parent = getParent(); - if(parent) { - Rect parentRect = parent->getRect(); - boundRect.bound(parentRect); - } - - if(boundRect != newRect) - setRect(boundRect); + bindRectToParent(); } bool UIWindow::onMousePress(const Point& mousePos, Fw::MouseButton button)