change ui event handling

This commit is contained in:
Eduardo Bart 2011-08-22 09:44:26 -03:00
parent 30de60c562
commit 8fb07afc10
19 changed files with 214 additions and 359 deletions

View File

@ -26,7 +26,7 @@ RectPanel
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: prev.right anchors.left: prev.right
anchors.right: parent.right anchors.right: parent.right
margin.left: 2 margin.left: 4
font: terminus-14px-bold font: terminus-14px-bold
onAction: | onAction: |
function(self) function(self)

View File

@ -165,7 +165,7 @@ void Platform::init(PlatformListener* platformListener, const char *appName)
x11.keyMap[XK_KP_Equal] = KC_NUMPADEQUALS; x11.keyMap[XK_KP_Equal] = KC_NUMPADEQUALS;
x11.keyMap[XK_KP_Divide] = KC_DIVIDE; x11.keyMap[XK_KP_Divide] = KC_DIVIDE;
x11.keyMap[XK_KP_Multiply] = KC_MULTIPLY; x11.keyMap[XK_KP_Multiply] = KC_MULTIPLY;
x11.keyMap[XK_KP_Enter] = KC_NUMPADENTER; x11.keyMap[XK_KP_Enter] = KC_RETURN;
// keypad with numlock off // keypad with numlock off
x11.keyMap[XK_KP_Home] = KC_NUMPAD7; x11.keyMap[XK_KP_Home] = KC_NUMPAD7;

View File

@ -3,15 +3,7 @@
// namespace ui { // namespace ui {
enum UIWidgetType { namespace UI {
UITypeWidget = 0,
UITypeLabel,
UITypeButton,
UITypeLineEdit,
UITypeWindow,
UITypeList,
UITypeConsole
};
enum FocusReason { enum FocusReason {
MouseFocusReason = 0, MouseFocusReason = 0,
@ -40,11 +32,7 @@ enum KeyboardModifier {
KeyboardShiftModifier = 4 KeyboardShiftModifier = 4
}; };
enum ButtonState { }
ButtonUp = 0,
ButtonDown,
ButtonHover
};
// } // }

View File

@ -3,6 +3,7 @@
#include <framework/global.h> #include <framework/global.h>
#include "const.h" #include "const.h"
#include <framework/platform/platformevent.h>
class UIManager; class UIManager;
class UIAnchor; class UIAnchor;

View File

@ -5,7 +5,7 @@
#include <framework/luascript/luainterface.h> #include <framework/luascript/luainterface.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
UIButton::UIButton(): UIWidget(UITypeButton) UIButton::UIButton()
{ {
m_state = ButtonUp; m_state = ButtonUp;
m_focusable = false; m_focusable = false;
@ -20,9 +20,9 @@ UIButtonPtr UIButton::create()
return button; return button;
} }
void UIButton::loadStyleFromOTML(const OTMLNodePtr& styleNode) void UIButton::onStyleApply(const OTMLNodePtr& styleNode)
{ {
UIWidget::loadStyleFromOTML(styleNode); UIWidget::onStyleApply(styleNode);
for(int i=0; i<3; ++i) { for(int i=0; i<3; ++i) {
m_statesStyle[i].image = m_image; m_statesStyle[i].image = m_image;
@ -73,28 +73,29 @@ void UIButton::render()
m_font->renderText(m_text, textRect, AlignCenter, currentStyle.foregroundColor); m_font->renderText(m_text, textRect, AlignCenter, currentStyle.foregroundColor);
} }
void UIButton::onHoverChange(UIHoverEvent& event) void UIButton::onHoverChange(bool hovered)
{ {
if(event.mouseEnter() && m_state == ButtonUp) if(hovered && m_state == ButtonUp)
m_state = ButtonHover; m_state = ButtonHover;
else if(m_state == ButtonHover) else if(m_state == ButtonHover)
m_state = ButtonUp; m_state = ButtonUp;
} }
void UIButton::onMousePress(UIMouseEvent& event) bool UIButton::onMousePress(const Point& mousePos, UI::MouseButton button)
{ {
if(event.button() == MouseLeftButton) { if(button == UI::MouseLeftButton) {
m_state = ButtonDown; m_state = ButtonDown;
} else }
event.ignore(); return true;
} }
void UIButton::onMouseRelease(UIMouseEvent& event) bool UIButton::onMouseRelease(const Point& mousePos, UI::MouseButton button)
{ {
if(m_state == ButtonDown) { if(m_state == ButtonDown) {
if(m_onClick && getRect().contains(event.pos())) if(m_onClick && getRect().contains(mousePos))
m_onClick(); m_onClick();
m_state = (isHovered() && isEnabled()) ? ButtonHover : ButtonUp; m_state = (isHovered() && isEnabled()) ? ButtonHover : ButtonUp;
} else return true;
event.ignore(); }
return false;
} }

View File

@ -12,12 +12,18 @@ class UIButton : public UIWidget
Color color; Color color;
}; };
enum ButtonState {
ButtonUp = 0,
ButtonDown,
ButtonHover
};
public: public:
UIButton(); UIButton();
static UIButtonPtr create(); static UIButtonPtr create();
virtual void loadStyleFromOTML(const OTMLNodePtr& styleNode); virtual void onStyleApply(const OTMLNodePtr& styleNode);
void loadStateStyle(ButtonStateStyle& stateStyle, const OTMLNodePtr& stateStyleNode); void loadStateStyle(ButtonStateStyle& stateStyle, const OTMLNodePtr& stateStyleNode);
virtual void render(); virtual void render();
@ -31,9 +37,9 @@ public:
UIButtonPtr asUIButton() { return std::static_pointer_cast<UIButton>(shared_from_this()); } UIButtonPtr asUIButton() { return std::static_pointer_cast<UIButton>(shared_from_this()); }
protected: protected:
virtual void onHoverChange(UIHoverEvent& event); virtual void onHoverChange(bool hovered);
virtual void onMousePress(UIMouseEvent& event); virtual bool onMousePress(const Point& mousePos, UI::MouseButton button);
virtual void onMouseRelease(UIMouseEvent& event); virtual bool onMouseRelease(const Point& mousePos, UI::MouseButton button);
ButtonState m_state; ButtonState m_state;
ButtonStateStyle m_statesStyle[3]; ButtonStateStyle m_statesStyle[3];

View File

@ -1,113 +0,0 @@
#ifndef UIEVENT_H
#define UIEVENT_H
#include <framework/platform/platformevent.h>
#include "declarations.h"
class UIEvent
{
public:
UIEvent() : m_accepted(true) { }
void setAccepted(bool accepted) { m_accepted = accepted; }
void accept() { m_accepted = true; }
void ignore() { m_accepted = false; }
bool isAccepted() { return m_accepted; }
private:
bool m_accepted;
};
class UIMouseEvent : public UIEvent
{
public:
UIMouseEvent(const Point& pos, MouseButton button)
: m_pos(pos), m_button(button), m_wheelDirection(MouseNoWheel) { }
UIMouseEvent(const Point& pos, MouseWheelDirection wheelDirection)
: m_pos(pos), m_button(MouseNoButton), m_wheelDirection(wheelDirection) { }
UIMouseEvent(const Point& pos, Point moved)
: m_pos(pos), m_moved(moved), m_button(MouseNoButton), m_wheelDirection(MouseNoWheel) { }
Point pos() const { return m_pos; }
Point oldPos() const { return m_pos - m_moved; }
Point moved() const { return m_moved; }
int x() const { return m_pos.x; }
int y() const { return m_pos.y; }
MouseButton button() const { return m_button; }
MouseWheelDirection wheelDirection() const { return m_wheelDirection; }
private:
Point m_pos;
Point m_moved;
MouseButton m_button;
MouseWheelDirection m_wheelDirection;
};
class UIKeyEvent : public UIEvent
{
public:
UIKeyEvent(uchar keyCode, char keyChar, int keyboardModifiers)
: m_keyCode(keyCode), m_keyChar(keyChar), m_keyboardModifiers(keyboardModifiers) { }
uchar keyCode() const { return m_keyCode; }
char keyChar() const { return m_keyChar; }
int keyboardModifiers() const { return m_keyboardModifiers; }
private:
uchar m_keyCode;
char m_keyChar;
int m_keyboardModifiers;
};
class UIFocusEvent : public UIEvent
{
public:
UIFocusEvent(FocusReason reason, bool gotFocus)
: m_reason(reason), m_gotFocus(gotFocus) { }
bool gotFocus() const { return m_gotFocus; }
bool lostFocus() const { return !m_gotFocus; }
bool reason() const { return m_reason; }
private:
FocusReason m_reason;
bool m_gotFocus;
};
class UIHoverEvent : public UIEvent
{
public:
UIHoverEvent(bool hovered) : m_hovered(hovered) { }
bool hovered() const { return m_hovered; }
bool mouseEnter() const { return m_hovered; }
bool mouseLeave() const { return !m_hovered; }
private:
bool m_hovered;
};
class UIRectUpdateEvent : public UIEvent
{
public:
UIRectUpdateEvent(const Rect& oldRect, const Rect& rect)
: m_oldRect(oldRect), m_rect(rect) { }
Point pos() const { return m_rect.topLeft(); }
Size size() const { return m_rect.size(); }
Rect rect() const { return m_rect; }
Point oldPos() const { return m_oldRect.topLeft(); }
Size oldSize() const { return m_oldRect.size(); }
Rect oldRect() const { return m_oldRect; }
Point moved() const { return m_rect.topLeft() - m_oldRect.topLeft(); }
Size resized() const { return m_rect.size() - m_oldRect.size(); }
bool hasMoved() const { return m_rect.topLeft() != m_oldRect.topLeft(); }
bool hasResized() const { return m_rect.size() != m_oldRect.size(); }
private:
Rect m_oldRect;
Rect m_rect;
};
#endif

View File

@ -2,7 +2,7 @@
#include <framework/graphics/font.h> #include <framework/graphics/font.h>
#include <framework/otml/otmlnode.h> #include <framework/otml/otmlnode.h>
UILabel::UILabel() : UIWidget(UITypeLabel) UILabel::UILabel()
{ {
m_align = AlignLeft; m_align = AlignLeft;
m_focusable = false; m_focusable = false;
@ -14,9 +14,9 @@ UILabelPtr UILabel::create()
return label; return label;
} }
void UILabel::loadStyleFromOTML(const OTMLNodePtr& styleNode) void UILabel::onStyleApply(const OTMLNodePtr& styleNode)
{ {
UIWidget::loadStyleFromOTML(styleNode); UIWidget::onStyleApply(styleNode);
m_text = styleNode->valueAt("text", m_text); m_text = styleNode->valueAt("text", m_text);

View File

@ -10,7 +10,7 @@ public:
static UILabelPtr create(); static UILabelPtr create();
virtual void loadStyleFromOTML(const OTMLNodePtr& styleNode); virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual void render(); virtual void render();
void resizeToText(); void resizeToText();

View File

@ -4,7 +4,7 @@
#include <framework/platform/platform.h> #include <framework/platform/platform.h>
#include <framework/otml/otmlnode.h> #include <framework/otml/otmlnode.h>
UILineEdit::UILineEdit() : UIWidget(UITypeLabel) UILineEdit::UILineEdit()
{ {
m_align = AlignLeftCenter; m_align = AlignLeftCenter;
m_cursorPos = 0; m_cursorPos = 0;
@ -21,18 +21,6 @@ UILineEditPtr UILineEdit::create()
return lineEdit; return lineEdit;
} }
void UILineEdit::loadStyleFromOTML(const OTMLNodePtr& styleNode)
{
UIWidget::loadStyleFromOTML(styleNode);
setText(styleNode->valueAt("text", getText()));
if(OTMLNodePtr node = styleNode->get("onAction")) {
g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]");
luaSetField(node->tag());
}
}
void UILineEdit::render() void UILineEdit::render()
{ {
UIWidget::render(); UIWidget::render();
@ -339,57 +327,69 @@ int UILineEdit::getTextPos(Point pos)
return candidatePos; return candidatePos;
} }
void UILineEdit::onRectUpdate(UIRectUpdateEvent& event) void UILineEdit::onStyleApply(const OTMLNodePtr& styleNode)
{
UIWidget::onStyleApply(styleNode);
setText(styleNode->valueAt("text", getText()));
if(OTMLNodePtr node = styleNode->get("onAction")) {
g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]");
luaSetField(node->tag());
}
}
void UILineEdit::onGeometryUpdate(const Rect& oldRect, const Rect& newRect)
{ {
update(); update();
} }
void UILineEdit::onFocusChange(UIFocusEvent& event) void UILineEdit::onFocusChange(bool focused, UI::FocusReason reason)
{ {
if(event.gotFocus()) { if(focused) {
if(event.reason() == TabFocusReason) if(reason == UI::TabFocusReason)
setCursorPos(0); setCursorPos(0);
else else
blinkCursor(); blinkCursor();
} }
} }
void UILineEdit::onKeyPress(UIKeyEvent& event) bool UILineEdit::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
{ {
if(event.keyCode() == KC_DELETE) // erase right character if(keyCode == KC_DELETE) // erase right character
removeCharacter(true); removeCharacter(true);
else if(event.keyCode() == KC_BACK) // erase left character { else if(keyCode == KC_BACK) // erase left character {
removeCharacter(false); removeCharacter(false);
else if(event.keyCode() == KC_RIGHT) // move cursor right else if(keyCode == KC_RIGHT) // move cursor right
moveCursor(true); moveCursor(true);
else if(event.keyCode() == KC_LEFT) // move cursor left else if(keyCode == KC_LEFT) // move cursor left
moveCursor(false); moveCursor(false);
else if(event.keyCode() == KC_HOME) // move cursor to first character else if(keyCode == KC_HOME) // move cursor to first character
setCursorPos(0); setCursorPos(0);
else if(event.keyCode() == KC_END) // move cursor to last character else if(keyCode == KC_END) // move cursor to last character
setCursorPos(m_text.length()); setCursorPos(m_text.length());
else if(event.keyCode() == KC_TAB) { else if(keyCode == KC_TAB) {
if(UIWidgetPtr parent = getParent()) if(UIWidgetPtr parent = getParent())
parent->focusNextChild(TabFocusReason); parent->focusNextChild(UI::TabFocusReason);
} else if(event.keyCode() == KC_RETURN) { } else if(keyCode == KC_RETURN) {
if(m_onAction) if(m_onAction)
m_onAction(); m_onAction();
} else if(event.keyChar() != 0) { } else if(keyCode != 0) {
appendCharacter(event.keyChar()); appendCharacter(keyChar);
} else } else
event.ignore(); return false;
if(!event.isAccepted()) return true;
UIWidget::onKeyPress(event);
} }
void UILineEdit::onMousePress(UIMouseEvent& event) bool UILineEdit::onMousePress(const Point& mousePos, UI::MouseButton button)
{ {
if(event.button() == MouseLeftButton) { if(button == UI::MouseLeftButton) {
int pos = getTextPos(event.pos()); int pos = getTextPos(mousePos);
if(pos >= 0) if(pos >= 0)
setCursorPos(pos); setCursorPos(pos);
} }
return true;
} }
void UILineEdit::blinkCursor() void UILineEdit::blinkCursor()

View File

@ -10,7 +10,6 @@ public:
static UILineEditPtr create(); static UILineEditPtr create();
virtual void loadStyleFromOTML(const OTMLNodePtr& styleNode);
virtual void render(); virtual void render();
void update(); void update();
@ -30,10 +29,11 @@ public:
int getTextPos(Point pos); int getTextPos(Point pos);
protected: protected:
virtual void onRectUpdate(UIRectUpdateEvent& event); virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual void onFocusChange(UIFocusEvent& event); virtual void onGeometryUpdate(const Rect& oldRect, const Rect& newRect);
virtual void onKeyPress(UIKeyEvent& event); virtual void onFocusChange(bool focused, UI::FocusReason reason);
virtual void onMousePress(UIMouseEvent& event); virtual bool onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers);
virtual bool onMousePress(const Point& mousePos, UI::MouseButton button);
private: private:
void blinkCursor(); void blinkCursor();

View File

@ -1,11 +1,11 @@
#include "uilist.h" #include "uilist.h"
UIList::UIList() : UIWidget(UITypeList) UIList::UIList()
{ {
} }
void UIList::loadStyleFromOTML(const OTMLNodePtr& styleNode) void UIList::onStyleApply(const OTMLNodePtr& styleNode)
{ {
} }
@ -15,18 +15,18 @@ void UIList::render()
} }
void UIList::onKeyPress(UIKeyEvent& event) bool UIList::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
{ {
return false;
} }
void UIList::onMousePress(UIMouseEvent& event) bool UIList::onMousePress(const Point& mousePos, UI::MouseButton button)
{ {
return false;
} }
void UIList::onMouseMove(UIMouseEvent& event) bool UIList::onMouseMove(const Point& mousePos, const Point& mouseMoved)
{ {
return false;
} }

View File

@ -8,13 +8,13 @@ class UIList : public UIWidget
public: public:
UIList(); UIList();
virtual void loadStyleFromOTML(const OTMLNodePtr& styleNode); virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual void render(); virtual void render();
protected: protected:
virtual void onKeyPress(UIKeyEvent& event); virtual bool onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers);
virtual void onMousePress(UIMouseEvent& event); virtual bool onMousePress(const Point& mousePos, UI::MouseButton button);
virtual void onMouseMove(UIMouseEvent& event); virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
private: private:
std::list<std::string> m_items; std::list<std::string> m_items;

View File

@ -38,47 +38,43 @@ void UIManager::inputEvent(const PlatformEvent& event)
// translate input event to ui events // translate input event to ui events
if(m_rootWidget) { if(m_rootWidget) {
if(event.type & EventKeyboardAction) { if(event.type & EventKeyboardAction) {
int keyboardModifiers = KeyboardNoModifier; int keyboardModifiers = UI::KeyboardNoModifier;
if(event.ctrl) if(event.ctrl)
keyboardModifiers |= KeyboardCtrlModifier; keyboardModifiers |= UI::KeyboardCtrlModifier;
if(event.shift) if(event.shift)
keyboardModifiers |= KeyboardShiftModifier; keyboardModifiers |= UI::KeyboardShiftModifier;
if(event.alt) if(event.alt)
keyboardModifiers |= KeyboardAltModifier; keyboardModifiers |= UI::KeyboardAltModifier;
UIKeyEvent e(event.keycode, event.keychar, keyboardModifiers);
if(event.type == EventKeyDown) if(event.type == EventKeyDown)
m_rootWidget->onKeyPress(e); m_rootWidget->onKeyPress(event.keycode, event.keychar, keyboardModifiers);
else else
m_rootWidget->onKeyRelease(e); m_rootWidget->onKeyRelease(event.keycode, event.keychar, keyboardModifiers);
} else if(event.type & EventMouseAction) { } else if(event.type & EventMouseAction) {
if(event.type == EventMouseMove) { if(event.type == EventMouseMove) {
UIMouseEvent e(event.mousePos, event.mousePos); m_rootWidget->onMouseMove(event.mousePos, event.mouseMoved);
m_rootWidget->onMouseMove(e);
} }
else if(event.type & EventMouseWheel) { else if(event.type & EventMouseWheel) {
MouseWheelDirection dir; UI::MouseWheelDirection dir = UI::MouseNoWheel;
if(event.type & EventDown) if(event.type & EventDown)
dir = MouseWheelDown; dir = UI::MouseWheelDown;
else if(event.type & EventUp) else if(event.type & EventUp)
dir = MouseWheelUp; dir = UI::MouseWheelUp;
UIMouseEvent e(event.mousePos, dir); m_rootWidget->onMouseWheel(event.mousePos, dir);
m_rootWidget->onMouseWheel(e);
} else { } else {
MouseButton button; UI::MouseButton button = UI::MouseNoButton;
if(event.type & EventMouseLeftButton) if(event.type & EventMouseLeftButton)
button = MouseLeftButton; button = UI::MouseLeftButton;
else if(event.type & EventMouseMidButton) else if(event.type & EventMouseMidButton)
button = MouseMidButton; button = UI::MouseMidButton;
else if(event.type & EventMouseRightButton) else if(event.type & EventMouseRightButton)
button = MouseRightButton; button = UI::MouseRightButton;
UIMouseEvent e(event.mousePos, button);
if(event.type & EventDown) if(event.type & EventDown)
m_rootWidget->onMousePress(e); m_rootWidget->onMousePress(event.mousePos, button);
else if(event.type & EventUp) else if(event.type & EventUp)
m_rootWidget->onMouseRelease(e); m_rootWidget->onMouseRelease(event.mousePos, button);
} }
} }
} }
@ -182,7 +178,7 @@ UIWidgetPtr UIManager::loadWidgetFromOTML(const OTMLNodePtr& widgetNode)
else else
throw OTMLException(styleNode, "cannot determine widget type"); throw OTMLException(styleNode, "cannot determine widget type");
widget->loadStyleFromOTML(styleNode); widget->onStyleApply(styleNode);
widget->updateLayout(); widget->updateLayout();
for(const OTMLNodePtr& childNode : widgetNode->children()) { for(const OTMLNodePtr& childNode : widgetNode->children()) {

View File

@ -9,9 +9,8 @@
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include "uianchor.h" #include "uianchor.h"
UIWidget::UIWidget(UIWidgetType type) UIWidget::UIWidget()
{ {
m_type = type;
m_visible = true; m_visible = true;
m_enabled = true; m_enabled = true;
m_hovered = false; m_hovered = false;
@ -37,12 +36,6 @@ UIWidget::~UIWidget()
logWarning("widget '", m_id, "' was destructed without being explicit destroyed"); logWarning("widget '", m_id, "' was destructed without being explicit destroyed");
} }
UIWidgetPtr UIWidget::create()
{
UIWidgetPtr widget(new UIWidget);
return widget;
}
void UIWidget::destroy() void UIWidget::destroy()
{ {
//TODO: onDestroy event //TODO: onDestroy event
@ -86,7 +79,7 @@ void UIWidget::destroyCheck()
logWarning("destroyed widget with id '",m_id,"', but it still have ",realUseCount," references left"); logWarning("destroyed widget with id '",m_id,"', but it still have ",realUseCount," references left");
} }
void UIWidget::loadStyleFromOTML(const OTMLNodePtr& styleNode) void UIWidget::onStyleApply(const OTMLNodePtr& styleNode)
{ {
assert(!m_destroyed); assert(!m_destroyed);
@ -236,7 +229,7 @@ void UIWidget::setStyle(const std::string& styleName)
{ {
try { try {
OTMLNodePtr styleNode = g_ui.getStyle(styleName); OTMLNodePtr styleNode = g_ui.getStyle(styleName);
loadStyleFromOTML(styleNode); onStyleApply(styleNode);
// forces layout recalculation // forces layout recalculation
updateLayout(); updateLayout();
@ -260,10 +253,9 @@ void UIWidget::setRect(const Rect& rect)
UIWidgetPtr self = asUIWidget(); UIWidgetPtr self = asUIWidget();
g_dispatcher.addEvent([self, oldRect]() { g_dispatcher.addEvent([self, oldRect]() {
self->m_updateEventScheduled = false; self->m_updateEventScheduled = false;
UIRectUpdateEvent e(oldRect, self->getRect());
// this widget could be destroyed before the event happens // this widget could be destroyed before the event happens
if(!self->isDestroyed()) if(!self->isDestroyed())
self->onRectUpdate(e); self->onGeometryUpdate(oldRect, self->getRect());
}); });
m_updateEventScheduled = true; m_updateEventScheduled = true;
} }
@ -431,7 +423,7 @@ UIWidgetPtr UIWidget::backwardsGetWidgetById(const std::string& id)
return widget; return widget;
} }
void UIWidget::focusChild(const UIWidgetPtr& focusedChild, FocusReason reason) void UIWidget::focusChild(const UIWidgetPtr& focusedChild, UI::FocusReason reason)
{ {
assert(!m_destroyed); assert(!m_destroyed);
@ -439,14 +431,10 @@ void UIWidget::focusChild(const UIWidgetPtr& focusedChild, FocusReason reason)
UIWidgetPtr oldFocused = m_focusedChild; UIWidgetPtr oldFocused = m_focusedChild;
m_focusedChild = focusedChild; m_focusedChild = focusedChild;
if(oldFocused) { if(oldFocused)
UIFocusEvent e(reason, false); oldFocused->onFocusChange(false, reason);
oldFocused->onFocusChange(e); if(focusedChild)
} focusedChild->onFocusChange(focusedChild->hasFocus(), reason);
if(focusedChild) {
UIFocusEvent e(reason, focusedChild->hasFocus());
focusedChild->onFocusChange(e);
}
} }
} }
@ -469,7 +457,7 @@ void UIWidget::addChild(const UIWidgetPtr& childToAdd)
// always focus new children // always focus new children
if(childToAdd->isFocusable() && childToAdd->isExplicitlyVisible() && childToAdd->isExplicitlyEnabled()) if(childToAdd->isFocusable() && childToAdd->isExplicitlyVisible() && childToAdd->isExplicitlyEnabled())
focusChild(childToAdd, ActiveFocusReason); focusChild(childToAdd, UI::ActiveFocusReason);
} }
void UIWidget::insertChild(const UIWidgetPtr& childToInsert, int index) void UIWidget::insertChild(const UIWidgetPtr& childToInsert, int index)
@ -506,7 +494,7 @@ void UIWidget::removeChild(const UIWidgetPtr& childToRemove)
// defocus if needed // defocus if needed
if(m_focusedChild == childToRemove) if(m_focusedChild == childToRemove)
focusChild(nullptr, ActiveFocusReason); focusChild(nullptr, UI::ActiveFocusReason);
// try to unlock // try to unlock
unlockChild(childToRemove); unlockChild(childToRemove);
@ -521,14 +509,13 @@ void UIWidget::removeChild(const UIWidgetPtr& childToRemove)
childToRemove->setParent(nullptr); childToRemove->setParent(nullptr);
// recalculate anchors // recalculate anchors
UIWidgetPtr parent = getRootParent(); getRootParent()->recalculateAnchoredWidgets();
parent->recalculateAnchoredWidgets();
// may need to update children layout // may need to update children layout
updateChildrenLayout(); updateChildrenLayout();
} }
void UIWidget::focusNextChild(FocusReason reason) void UIWidget::focusNextChild(UI::FocusReason reason)
{ {
assert(!m_destroyed); assert(!m_destroyed);
@ -578,7 +565,7 @@ void UIWidget::lockChild(const UIWidgetPtr& childToLock)
// lock child focus // lock child focus
if(childToLock->isFocusable()) if(childToLock->isFocusable())
focusChild(childToLock, ActiveFocusReason); focusChild(childToLock, UI::ActiveFocusReason);
} }
void UIWidget::unlockChild(const UIWidgetPtr& childToUnlock) void UIWidget::unlockChild(const UIWidgetPtr& childToUnlock)
@ -827,18 +814,26 @@ void UIWidget::computeAnchoredWidgets()
child->computeAnchoredWidgets(); child->computeAnchoredWidgets();
} }
void UIWidget::onFocusChange(UIFocusEvent& event) void UIWidget::onGeometryUpdate(const Rect& oldRect, const Rect& newRect)
{
}
void UIWidget::onFocusChange(bool focused, UI::FocusReason reason)
{ {
if(m_focusedChild) if(m_focusedChild)
m_focusedChild->onFocusChange(event); m_focusedChild->onFocusChange(focused, reason);
} }
void UIWidget::onKeyPress(UIKeyEvent& event) void UIWidget::onHoverChange(bool hovered)
{
}
bool UIWidget::onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers)
{ {
assert(!m_destroyed); assert(!m_destroyed);
event.ignore();
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
@ -847,21 +842,18 @@ void UIWidget::onKeyPress(UIKeyEvent& event)
// key events go only to containers or focused child // key events go only to containers or focused child
if(child->hasChildren() || (child->isFocusable() && child->hasFocus())) { if(child->hasChildren() || (child->isFocusable() && child->hasFocus())) {
event.accept(); if(child->onKeyPress(keyCode, keyChar, keyboardModifiers))
child->onKeyPress(event); return true;
}
if(event.isAccepted())
break;
} }
} }
void UIWidget::onKeyRelease(UIKeyEvent& event) return false;
}
bool UIWidget::onKeyRelease(uchar keyCode, char keyChar, int keyboardModifiers)
{ {
assert(!m_destroyed); assert(!m_destroyed);
event.ignore();
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
@ -870,21 +862,18 @@ void UIWidget::onKeyRelease(UIKeyEvent& event)
// key events go only to containers or focused child // key events go only to containers or focused child
if(child->hasChildren() || (child->isFocusable() && child->hasFocus())) { if(child->hasChildren() || (child->isFocusable() && child->hasFocus())) {
event.accept(); if(child->onKeyRelease(keyCode, keyChar, keyboardModifiers))
child->onKeyRelease(event); return true;
}
if(event.isAccepted())
break;
} }
} }
void UIWidget::onMousePress(UIMouseEvent& event) return false;
}
bool UIWidget::onMousePress(const Point& mousePos, UI::MouseButton button)
{ {
assert(!m_destroyed); assert(!m_destroyed);
event.ignore();
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
@ -892,26 +881,23 @@ void UIWidget::onMousePress(UIMouseEvent& event)
continue; continue;
// mouse press events only go to children that contains the mouse position // mouse press events only go to children that contains the mouse position
if(child->getRect().contains(event.pos()) && child == getChildByPos(event.pos())) { if(child->getRect().contains(mousePos) && child == getChildByPos(mousePos)) {
// focus it // focus it
if(child->isFocusable()) if(child->isFocusable())
focusChild(child, MouseFocusReason); focusChild(child, UI::MouseFocusReason);
event.accept(); if(child->onMousePress(mousePos, button))
child->onMousePress(event); return true;
}
if(event.isAccepted())
break;
} }
} }
void UIWidget::onMouseRelease(UIMouseEvent& event) return false;
}
bool UIWidget::onMouseRelease(const Point& mousePos, UI::MouseButton button)
{ {
assert(!m_destroyed); assert(!m_destroyed);
event.ignore();
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
@ -919,52 +905,46 @@ void UIWidget::onMouseRelease(UIMouseEvent& event)
continue; continue;
// mouse release events go to all children // mouse release events go to all children
event.accept(); if(child->onMouseRelease(mousePos, button))
child->onMouseRelease(event); return true;
if(event.isAccepted())
break;
}
} }
void UIWidget::onMouseMove(UIMouseEvent& event) return false;
}
bool UIWidget::onMouseMove(const Point& mousePos, const Point& mouseMoved)
{ {
assert(!m_destroyed); assert(!m_destroyed);
event.ignore();
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible()) if(!child->isExplicitlyEnabled() || !child->isExplicitlyVisible())
continue; continue;
// check if the mouse is relally over this child // check if the mouse is really over this child
bool overChild = (isHovered() && bool overChild = (isHovered() &&
child->getRect().contains(event.pos()) && child->getRect().contains(mousePos) &&
child == getChildByPos(event.pos())); child == getChildByPos(mousePos));
// trigger hover events
if(overChild != child->isHovered()) { if(overChild != child->isHovered()) {
child->setHovered(overChild); child->setHovered(overChild);
child->onHoverChange(overChild);
UIHoverEvent e(overChild);
child->onHoverChange(e);
} }
// mouse move events go to all children // mouse move events go to all children
event.accept(); if(child->onMouseMove(mousePos, mouseMoved))
child->onMouseMove(event); return true;
if(event.isAccepted())
break;
}
} }
void UIWidget::onMouseWheel(UIMouseEvent& event) return false;
}
bool UIWidget::onMouseWheel(const Point& mousePos, UI::MouseWheelDirection direction)
{ {
assert(!m_destroyed); assert(!m_destroyed);
event.ignore();
// do a backup of children list, because it may change while looping it // do a backup of children list, because it may change while looping it
UIWidgetList children = m_children; UIWidgetList children = m_children;
for(const UIWidgetPtr& child : children) { for(const UIWidgetPtr& child : children) {
@ -972,12 +952,11 @@ void UIWidget::onMouseWheel(UIMouseEvent& event)
continue; continue;
// mouse wheel events only go to children that contains the mouse position // mouse wheel events only go to children that contains the mouse position
if(child->getRect().contains(event.pos()) && child == getChildByPos(event.pos())) { if(child->getRect().contains(mousePos) && child == getChildByPos(mousePos)) {
event.accept(); if(child->onMouseWheel(mousePos, direction))
child->onMouseWheel(event); return true;
}
} }
if(event.isAccepted()) return false;
break;
}
} }

View File

@ -2,7 +2,6 @@
#define UIWIDGET_H #define UIWIDGET_H
#include "declarations.h" #include "declarations.h"
#include "uievent.h"
#include <framework/luascript/luaobject.h> #include <framework/luascript/luaobject.h>
#include <framework/graphics/declarations.h> #include <framework/graphics/declarations.h>
#include <framework/otml/declarations.h> #include <framework/otml/declarations.h>
@ -10,10 +9,10 @@
class UIWidget : public LuaObject class UIWidget : public LuaObject
{ {
public: public:
UIWidget(UIWidgetType type = UITypeWidget); UIWidget();
virtual ~UIWidget(); virtual ~UIWidget();
static UIWidgetPtr create(); static UIWidgetPtr create() { return UIWidgetPtr(new UIWidget); }
/// Must be called just after the widget creation /// Must be called just after the widget creation
virtual void setup() { } virtual void setup() { }
@ -21,9 +20,6 @@ public:
/// Remove this widget from parent then destroy it and its children /// Remove this widget from parent then destroy it and its children
virtual void destroy(); virtual void destroy();
/// Load style from otml node
virtual void loadStyleFromOTML(const OTMLNodePtr& styleNode);
/// Draw widget on screen /// Draw widget on screen
virtual void render(); virtual void render();
@ -67,7 +63,6 @@ public:
bool hasFocus(); bool hasFocus();
bool hasChild(const UIWidgetPtr& child); bool hasChild(const UIWidgetPtr& child);
UIWidgetType getWidgetType() const { return m_type; }
std::string getId() const { return m_id; } std::string getId() const { return m_id; }
int getChildCount() const { return m_children.size(); } int getChildCount() const { return m_children.size(); }
UIWidgetPtr getParent() const { return m_parent.lock(); } UIWidgetPtr getParent() const { return m_parent.lock(); }
@ -104,8 +99,8 @@ public:
void addChild(const UIWidgetPtr& childToAdd); void addChild(const UIWidgetPtr& childToAdd);
void insertChild(const UIWidgetPtr& childToInsert, int index); void insertChild(const UIWidgetPtr& childToInsert, int index);
void removeChild(const UIWidgetPtr& childToRemove); void removeChild(const UIWidgetPtr& childToRemove);
void focusChild(const UIWidgetPtr& childToFocus, FocusReason reason); void focusChild(const UIWidgetPtr& childToFocus, UI::FocusReason reason);
void focusNextChild(FocusReason reason); void focusNextChild(UI::FocusReason reason);
void moveChildToTop(const UIWidgetPtr& childToMove); void moveChildToTop(const UIWidgetPtr& childToMove);
void lockChild(const UIWidgetPtr& childToLock); void lockChild(const UIWidgetPtr& childToLock);
void unlockChild(const UIWidgetPtr& childToUnlock); void unlockChild(const UIWidgetPtr& childToUnlock);
@ -135,26 +130,26 @@ private:
bool m_childrenLayoutUpdateScheduled; bool m_childrenLayoutUpdateScheduled;
protected: protected:
/// Triggered when widget style is changed
virtual void onStyleApply(const OTMLNodePtr& styleNode);
/// Triggered when widget is moved or resized /// Triggered when widget is moved or resized
virtual void onRectUpdate(UIRectUpdateEvent& event) { } virtual void onGeometryUpdate(const Rect& oldRect, const Rect& newRect);
// Triggered when widget change visibility/enabled/style/children/parent/layout/...
//virtual void onChange(const UIEvent& event);
/// Triggered when widget gets or loses focus /// Triggered when widget gets or loses focus
virtual void onFocusChange(UIFocusEvent& event); virtual void onFocusChange(bool focused, UI::FocusReason reason);
/// Triggered when the mouse enters or leaves widget area /// Triggered when the mouse enters or leaves widget area
virtual void onHoverChange(UIHoverEvent& event) { } virtual void onHoverChange(bool hovered);
/// Triggered when user presses key while widget has focus /// Triggered when user presses key while widget has focus
virtual void onKeyPress(UIKeyEvent& event); virtual bool onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers);
/// Triggered when user releases key while widget has focus /// Triggered when user releases key while widget has focus
virtual void onKeyRelease(UIKeyEvent& event); virtual bool onKeyRelease(uchar keyCode, char keyChar, int keyboardModifiers);
/// Triggered when a mouse button is pressed down while mouse pointer is inside widget area /// Triggered when a mouse button is pressed down while mouse pointer is inside widget area
virtual void onMousePress(UIMouseEvent& event); virtual bool onMousePress(const Point& mousePos, UI::MouseButton button);
/// Triggered when a mouse button is released /// Triggered when a mouse button is released
virtual void onMouseRelease(UIMouseEvent& event); virtual bool onMouseRelease(const Point& mousePos, UI::MouseButton button);
/// Triggered when mouse moves (even when the mouse is outside widget area) /// Triggered when mouse moves (even when the mouse is outside widget area)
virtual void onMouseMove(UIMouseEvent& event); virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
/// Triggered when mouse middle button wheels inside widget area /// Triggered when mouse middle button wheels inside widget area
virtual void onMouseWheel(UIMouseEvent& event); virtual bool onMouseWheel(const Point& mousePos, UI::MouseWheelDirection direction);
friend class UIManager; friend class UIManager;
@ -162,7 +157,6 @@ private:
void destroyCheck(); void destroyCheck();
protected: protected:
UIWidgetType m_type;
bool m_enabled; bool m_enabled;
bool m_visible; bool m_visible;
bool m_hovered; bool m_hovered;

View File

@ -3,7 +3,7 @@
#include <framework/graphics/font.h> #include <framework/graphics/font.h>
#include <framework/otml/otml.h> #include <framework/otml/otml.h>
UIWindow::UIWindow(): UIWidget(UITypeWindow) UIWindow::UIWindow()
{ {
m_moving = false; m_moving = false;
} }
@ -14,9 +14,9 @@ UIWindowPtr UIWindow::create()
return window; return window;
} }
void UIWindow::loadStyleFromOTML(const OTMLNodePtr& styleNode) void UIWindow::onStyleApply(const OTMLNodePtr& styleNode)
{ {
UIWidget::loadStyleFromOTML(styleNode); UIWidget::onStyleApply(styleNode);
if(OTMLNodePtr headNode = styleNode->get("head")) { if(OTMLNodePtr headNode = styleNode->get("head")) {
if(OTMLNodePtr node = headNode->get("border-image")) if(OTMLNodePtr node = headNode->get("border-image"))
@ -66,10 +66,10 @@ void UIWindow::render()
UIWidget::render(); UIWidget::render();
} }
void UIWindow::onRectUpdate(UIRectUpdateEvent& event) void UIWindow::onGeometryUpdate(const Rect& oldRect, const Rect& newRect)
{ {
// bind window rect to parent rect // bind window rect to parent rect
Rect boundRect = event.rect(); Rect boundRect = newRect;
UIWidgetPtr parent = getParent(); UIWidgetPtr parent = getParent();
if(parent) { if(parent) {
Rect parentRect = parent->getRect(); Rect parentRect = parent->getRect();
@ -83,40 +83,43 @@ void UIWindow::onRectUpdate(UIRectUpdateEvent& event)
boundRect.moveRight(parentRect.right()); boundRect.moveRight(parentRect.right());
} }
if(boundRect != event.rect()) if(boundRect != newRect)
setRect(boundRect); setRect(boundRect);
} }
void UIWindow::onFocusChange(UIFocusEvent& event) void UIWindow::onFocusChange(bool focused, UI::FocusReason reason)
{ {
// when a window is focused it goes to the top // when a window is focused it goes to the top
if(UIWidgetPtr parent = getParent()) if(UIWidgetPtr parent = getParent())
parent->moveChildToTop(asUIWidget()); parent->moveChildToTop(asUIWidget());
} }
void UIWindow::onMousePress(UIMouseEvent& event) bool UIWindow::onMousePress(const Point& mousePos, UI::MouseButton button)
{ {
Rect headRect = getRect(); Rect headRect = getRect();
headRect.setHeight(m_headHeight); headRect.setHeight(m_headHeight);
if(headRect.contains(event.pos())) { if(headRect.contains(mousePos)) {
m_moving = true; m_moving = true;
m_movingReference = event.pos() - getRect().topLeft(); m_movingReference = mousePos - getRect().topLeft();
} else return true;
UIWidget::onMousePress(event); }
return UIWidget::onMousePress(mousePos, button);
} }
void UIWindow::onMouseRelease(UIMouseEvent& event) bool UIWindow::onMouseRelease(const Point& mousePos, UI::MouseButton button)
{ {
if(m_moving) if(m_moving) {
m_moving = false; m_moving = false;
else return true;
UIWidget::onMouseRelease(event); }
return UIWidget::onMouseRelease(mousePos, button);
} }
void UIWindow::onMouseMove(UIMouseEvent& event) bool UIWindow::onMouseMove(const Point& mousePos, const Point& mouseMoved)
{ {
if(m_moving) if(m_moving) {
move(event.pos() - m_movingReference); move(mousePos - m_movingReference);
else return true;
UIWidget::onMouseMove(event); }
return UIWidget::onMouseMove(mousePos, mouseMoved);
} }

View File

@ -10,18 +10,18 @@ public:
static UIWindowPtr create(); static UIWindowPtr create();
virtual void loadStyleFromOTML(const OTMLNodePtr& styleNode); virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual void render(); virtual void render();
void setTitle(const std::string& title) { m_title = title; } void setTitle(const std::string& title) { m_title = title; }
std::string getTitle() const { return m_title; } std::string getTitle() const { return m_title; }
protected: protected:
virtual void onRectUpdate(UIRectUpdateEvent& event); virtual void onGeometryUpdate(const Rect& oldRect, const Rect& newRect);
virtual void onFocusChange(UIFocusEvent& event); virtual void onFocusChange(bool focused, UI::FocusReason reason);
virtual void onMousePress(UIMouseEvent& event); virtual bool onMousePress(const Point& mousePos, UI::MouseButton button);
virtual void onMouseRelease(UIMouseEvent& event); virtual bool onMouseRelease(const Point& mousePos, UI::MouseButton button);
virtual void onMouseMove(UIMouseEvent& event); virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
private: private:
std::string m_title; std::string m_title;

View File

@ -296,7 +296,7 @@ void OTClient::onPlatformEvent(const PlatformEvent& event)
// TODO: move these events to lua // TODO: move these events to lua
UIWidgetPtr console = g_ui.getRootWidget()->getChildById("consolePanel"); UIWidgetPtr console = g_ui.getRootWidget()->getChildById("consolePanel");
if(!console->isExplicitlyVisible()) { if(!console->isExplicitlyVisible()) {
g_ui.getRootWidget()->focusChild(console, ActiveFocusReason); g_ui.getRootWidget()->focusChild(console, UI::ActiveFocusReason);
g_ui.getRootWidget()->moveChildToTop(console); g_ui.getRootWidget()->moveChildToTop(console);
console->setVisible(true); console->setVisible(true);
} else { } else {