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.left: prev.right
anchors.right: parent.right
margin.left: 2
margin.left: 4
font: terminus-14px-bold
onAction: |
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_Divide] = KC_DIVIDE;
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
x11.keyMap[XK_KP_Home] = KC_NUMPAD7;

View File

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

View File

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

View File

@ -5,7 +5,7 @@
#include <framework/luascript/luainterface.h>
#include <framework/graphics/graphics.h>
UIButton::UIButton(): UIWidget(UITypeButton)
UIButton::UIButton()
{
m_state = ButtonUp;
m_focusable = false;
@ -20,9 +20,9 @@ UIButtonPtr UIButton::create()
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) {
m_statesStyle[i].image = m_image;
@ -73,28 +73,29 @@ void UIButton::render()
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;
else if(m_state == ButtonHover)
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;
} 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_onClick && getRect().contains(event.pos()))
if(m_onClick && getRect().contains(mousePos))
m_onClick();
m_state = (isHovered() && isEnabled()) ? ButtonHover : ButtonUp;
} else
event.ignore();
return true;
}
return false;
}

View File

@ -12,12 +12,18 @@ class UIButton : public UIWidget
Color color;
};
enum ButtonState {
ButtonUp = 0,
ButtonDown,
ButtonHover
};
public:
UIButton();
static UIButtonPtr create();
virtual void loadStyleFromOTML(const OTMLNodePtr& styleNode);
virtual void onStyleApply(const OTMLNodePtr& styleNode);
void loadStateStyle(ButtonStateStyle& stateStyle, const OTMLNodePtr& stateStyleNode);
virtual void render();
@ -31,9 +37,9 @@ public:
UIButtonPtr asUIButton() { return std::static_pointer_cast<UIButton>(shared_from_this()); }
protected:
virtual void onHoverChange(UIHoverEvent& event);
virtual void onMousePress(UIMouseEvent& event);
virtual void onMouseRelease(UIMouseEvent& event);
virtual void onHoverChange(bool hovered);
virtual bool onMousePress(const Point& mousePos, UI::MouseButton button);
virtual bool onMouseRelease(const Point& mousePos, UI::MouseButton button);
ButtonState m_state;
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/otml/otmlnode.h>
UILabel::UILabel() : UIWidget(UITypeLabel)
UILabel::UILabel()
{
m_align = AlignLeft;
m_focusable = false;
@ -14,9 +14,9 @@ UILabelPtr UILabel::create()
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);

View File

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

View File

@ -4,7 +4,7 @@
#include <framework/platform/platform.h>
#include <framework/otml/otmlnode.h>
UILineEdit::UILineEdit() : UIWidget(UITypeLabel)
UILineEdit::UILineEdit()
{
m_align = AlignLeftCenter;
m_cursorPos = 0;
@ -21,18 +21,6 @@ UILineEditPtr UILineEdit::create()
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()
{
UIWidget::render();
@ -339,57 +327,69 @@ int UILineEdit::getTextPos(Point pos)
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();
}
void UILineEdit::onFocusChange(UIFocusEvent& event)
void UILineEdit::onFocusChange(bool focused, UI::FocusReason reason)
{
if(event.gotFocus()) {
if(event.reason() == TabFocusReason)
if(focused) {
if(reason == UI::TabFocusReason)
setCursorPos(0);
else
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);
else if(event.keyCode() == KC_BACK) // erase left character {
else if(keyCode == KC_BACK) // erase left character {
removeCharacter(false);
else if(event.keyCode() == KC_RIGHT) // move cursor right
else if(keyCode == KC_RIGHT) // move cursor right
moveCursor(true);
else if(event.keyCode() == KC_LEFT) // move cursor left
else if(keyCode == KC_LEFT) // move cursor left
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);
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());
else if(event.keyCode() == KC_TAB) {
else if(keyCode == KC_TAB) {
if(UIWidgetPtr parent = getParent())
parent->focusNextChild(TabFocusReason);
} else if(event.keyCode() == KC_RETURN) {
parent->focusNextChild(UI::TabFocusReason);
} else if(keyCode == KC_RETURN) {
if(m_onAction)
m_onAction();
} else if(event.keyChar() != 0) {
appendCharacter(event.keyChar());
} else if(keyCode != 0) {
appendCharacter(keyChar);
} else
event.ignore();
return false;
if(!event.isAccepted())
UIWidget::onKeyPress(event);
return true;
}
void UILineEdit::onMousePress(UIMouseEvent& event)
bool UILineEdit::onMousePress(const Point& mousePos, UI::MouseButton button)
{
if(event.button() == MouseLeftButton) {
int pos = getTextPos(event.pos());
if(button == UI::MouseLeftButton) {
int pos = getTextPos(mousePos);
if(pos >= 0)
setCursorPos(pos);
}
return true;
}
void UILineEdit::blinkCursor()

View File

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

View File

@ -1,11 +1,11 @@
#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:
UIList();
virtual void loadStyleFromOTML(const OTMLNodePtr& styleNode);
virtual void onStyleApply(const OTMLNodePtr& styleNode);
virtual void render();
protected:
virtual void onKeyPress(UIKeyEvent& event);
virtual void onMousePress(UIMouseEvent& event);
virtual void onMouseMove(UIMouseEvent& event);
virtual bool onKeyPress(uchar keyCode, char keyChar, int keyboardModifiers);
virtual bool onMousePress(const Point& mousePos, UI::MouseButton button);
virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
private:
std::list<std::string> m_items;

View File

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

View File

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

View File

@ -2,7 +2,6 @@
#define UIWIDGET_H
#include "declarations.h"
#include "uievent.h"
#include <framework/luascript/luaobject.h>
#include <framework/graphics/declarations.h>
#include <framework/otml/declarations.h>
@ -10,10 +9,10 @@
class UIWidget : public LuaObject
{
public:
UIWidget(UIWidgetType type = UITypeWidget);
UIWidget();
virtual ~UIWidget();
static UIWidgetPtr create();
static UIWidgetPtr create() { return UIWidgetPtr(new UIWidget); }
/// Must be called just after the widget creation
virtual void setup() { }
@ -21,9 +20,6 @@ public:
/// Remove this widget from parent then destroy it and its children
virtual void destroy();
/// Load style from otml node
virtual void loadStyleFromOTML(const OTMLNodePtr& styleNode);
/// Draw widget on screen
virtual void render();
@ -67,7 +63,6 @@ public:
bool hasFocus();
bool hasChild(const UIWidgetPtr& child);
UIWidgetType getWidgetType() const { return m_type; }
std::string getId() const { return m_id; }
int getChildCount() const { return m_children.size(); }
UIWidgetPtr getParent() const { return m_parent.lock(); }
@ -104,8 +99,8 @@ public:
void addChild(const UIWidgetPtr& childToAdd);
void insertChild(const UIWidgetPtr& childToInsert, int index);
void removeChild(const UIWidgetPtr& childToRemove);
void focusChild(const UIWidgetPtr& childToFocus, FocusReason reason);
void focusNextChild(FocusReason reason);
void focusChild(const UIWidgetPtr& childToFocus, UI::FocusReason reason);
void focusNextChild(UI::FocusReason reason);
void moveChildToTop(const UIWidgetPtr& childToMove);
void lockChild(const UIWidgetPtr& childToLock);
void unlockChild(const UIWidgetPtr& childToUnlock);
@ -135,26 +130,26 @@ private:
bool m_childrenLayoutUpdateScheduled;
protected:
/// Triggered when widget style is changed
virtual void onStyleApply(const OTMLNodePtr& styleNode);
/// Triggered when widget is moved or resized
virtual void onRectUpdate(UIRectUpdateEvent& event) { }
// Triggered when widget change visibility/enabled/style/children/parent/layout/...
//virtual void onChange(const UIEvent& event);
virtual void onGeometryUpdate(const Rect& oldRect, const Rect& newRect);
/// 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
virtual void onHoverChange(UIHoverEvent& event) { }
virtual void onHoverChange(bool hovered);
/// 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
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
virtual void onMousePress(UIMouseEvent& event);
virtual bool onMousePress(const Point& mousePos, UI::MouseButton button);
/// 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)
virtual void onMouseMove(UIMouseEvent& event);
virtual bool onMouseMove(const Point& mousePos, const Point& mouseMoved);
/// 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;
@ -162,7 +157,6 @@ private:
void destroyCheck();
protected:
UIWidgetType m_type;
bool m_enabled;
bool m_visible;
bool m_hovered;

View File

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

View File

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

View File

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