From a238111c0721618dc734775f8e53e6c5f6489f6b Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Sun, 15 Jan 2012 11:57:42 -0200 Subject: [PATCH] add horizontal box layout, enter keypress fix --- src/framework/CMakeLists.txt | 2 + src/framework/luafunctions.cpp | 26 +++++++- src/framework/platform/x11window.cpp | 5 +- src/framework/ui/declarations.h | 4 ++ src/framework/ui/ui.h | 1 + src/framework/ui/uiboxlayout.cpp | 42 ++++++++++++ src/framework/ui/uiboxlayout.h | 47 +++++++++++++ src/framework/ui/uihorizontallayout.cpp | 88 +++++++++++++++++++++++++ src/framework/ui/uihorizontallayout.h | 45 +++++++++++++ src/framework/ui/uilayout.h | 2 + src/framework/ui/uiverticallayout.cpp | 16 +---- src/framework/ui/uiverticallayout.h | 13 +--- src/framework/ui/uiwidgetbasestyle.cpp | 5 +- 13 files changed, 269 insertions(+), 27 deletions(-) create mode 100644 src/framework/ui/uiboxlayout.cpp create mode 100644 src/framework/ui/uiboxlayout.h create mode 100644 src/framework/ui/uihorizontallayout.cpp create mode 100644 src/framework/ui/uihorizontallayout.h diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 206af41f..09a86f1a 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -189,6 +189,8 @@ SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/ui/uiwidgettext.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/uiwidgetbasestyle.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/uilineedit.cpp + ${CMAKE_CURRENT_LIST_DIR}/ui/uiboxlayout.cpp + ${CMAKE_CURRENT_LIST_DIR}/ui/uihorizontallayout.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/uiverticallayout.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/uigridlayout.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/uianchorlayout.cpp diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index cd06237c..d1864bc6 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -270,16 +270,38 @@ void Application::registerLuaFunctions() // UILayout g_lua.registerClass(); - g_lua.bindClassMemberFunction("applyStyle", &UILayout::applyStyle); g_lua.bindClassMemberFunction("update", &UILayout::update); + g_lua.bindClassMemberFunction("updateLater", &UILayout::updateLater); + g_lua.bindClassMemberFunction("applyStyle", &UILayout::applyStyle); g_lua.bindClassMemberFunction("addWidget", &UILayout::addWidget); g_lua.bindClassMemberFunction("removeWidget", &UILayout::removeWidget); + g_lua.bindClassMemberFunction("disableUpdates", &UILayout::disableUpdates); + g_lua.bindClassMemberFunction("enableUpdates", &UILayout::enableUpdates); + g_lua.bindClassMemberFunction("setParent", &UILayout::setParent); g_lua.bindClassMemberFunction("getParentWidget", &UILayout::getParentWidget); + g_lua.bindClassMemberFunction("isUpdateDisabled", &UILayout::isUpdateDisabled); + g_lua.bindClassMemberFunction("isUpdating", &UILayout::isUpdating); + g_lua.bindClassMemberFunction("asUILayout", &UILayout::asUILayout); + g_lua.bindClassMemberFunction("asUIAnchorLayout", &UILayout::asUIAnchorLayout); + g_lua.bindClassMemberFunction("asUIBoxLayout", &UILayout::asUIBoxLayout); + g_lua.bindClassMemberFunction("asUIHorizontalLayout", &UILayout::asUIHorizontalLayout); + g_lua.bindClassMemberFunction("asUIVerticalLayout", &UILayout::asUIVerticalLayout); + g_lua.bindClassMemberFunction("asUIGridLayout", &UILayout::asUIGridLayout); + + // UIBoxLayout + g_lua.registerClass(); + g_lua.bindClassMemberFunction("setSpacing", &UIBoxLayout::setSpacing); + g_lua.bindClassMemberFunction("setFitChildren", &UIBoxLayout::setFitChildren); // UIVerticalLayout g_lua.registerClass(); g_lua.bindClassStaticFunction("create", [](UIWidgetPtr parent){ return UIVerticalLayoutPtr(new UIVerticalLayout(parent)); } ); - g_lua.bindClassMemberFunction("setFitParent", &UIVerticalLayout::setFitParent); + g_lua.bindClassMemberFunction("setAlignBottom", &UIVerticalLayout::setAlignBottom); + + // UIHorizontalLayout + g_lua.registerClass(); + g_lua.bindClassStaticFunction("create", [](UIWidgetPtr parent){ return UIHorizontalLayoutPtr(new UIHorizontalLayout(parent)); } ); + g_lua.bindClassMemberFunction("setAlignRight", &UIHorizontalLayout::setAlignRight); // UIGridLayout g_lua.registerClass(); diff --git a/src/framework/platform/x11window.cpp b/src/framework/platform/x11window.cpp index 9b72cbc7..b8af7bb6 100644 --- a/src/framework/platform/x11window.cpp +++ b/src/framework/platform/x11window.cpp @@ -647,7 +647,10 @@ void X11Window::poll() XKeyEvent xkey = event.xkey; xkey.state = xkey.state & ~(ShiftMask); len = XLookupString(&xkey, buf, sizeof(buf), &keysym, 0); - if(len > 0 && m_inputEvent.keyText.length() == 0) + if(len > 0 && m_inputEvent.keyText.length() == 0 && keysym != XK_BackSpace && + keysym != XK_Return && + keysym != XK_Delete && + keysym != XK_Escape) m_inputEvent.keyText = buf; if(m_keyMap.find(keysym) != m_keyMap.end()) diff --git a/src/framework/ui/declarations.h b/src/framework/ui/declarations.h index 4cde7dd8..94f8f997 100644 --- a/src/framework/ui/declarations.h +++ b/src/framework/ui/declarations.h @@ -30,6 +30,8 @@ class UIWidget; class UILineEdit; class UIFrameCounter; class UILayout; +class UIBoxLayout; +class UIHorizontalLayout; class UIVerticalLayout; class UIGridLayout; class UIAnchorLayout; @@ -40,6 +42,8 @@ typedef std::weak_ptr UIWidgetWeakPtr; typedef std::shared_ptr UILineEditPtr; typedef std::shared_ptr UIFrameCounterPtr; typedef std::shared_ptr UILayoutPtr; +typedef std::shared_ptr UIBoxLayoutPtr; +typedef std::shared_ptr UIHorizontalLayoutPtr; typedef std::shared_ptr UIVerticalLayoutPtr; typedef std::shared_ptr UIGridLayoutPtr; typedef std::shared_ptr UIAnchorLayoutPtr; diff --git a/src/framework/ui/ui.h b/src/framework/ui/ui.h index 1e157123..909e1c26 100644 --- a/src/framework/ui/ui.h +++ b/src/framework/ui/ui.h @@ -28,6 +28,7 @@ #include "uilineedit.h" #include "uiframecounter.h" #include "uilayout.h" +#include "uihorizontallayout.h" #include "uiverticallayout.h" #include "uigridlayout.h" #include "uianchorlayout.h" diff --git a/src/framework/ui/uiboxlayout.cpp b/src/framework/ui/uiboxlayout.cpp new file mode 100644 index 00000000..9a7ee339 --- /dev/null +++ b/src/framework/ui/uiboxlayout.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "uiboxlayout.h" +#include "uiwidget.h" + +UIBoxLayout::UIBoxLayout(UIWidgetPtr parentWidget) : UILayout(parentWidget) +{ + m_spacing = 0; +} + +void UIBoxLayout::applyStyle(const OTMLNodePtr& styleNode) +{ + UILayout::applyStyle(styleNode); + + for(const OTMLNodePtr& node : styleNode->children()) { + if(node->tag() == "spacing") + setSpacing(node->value()); + else if(node->tag() == "fit-children") + setFitChildren(node->value()); + } +} + diff --git a/src/framework/ui/uiboxlayout.h b/src/framework/ui/uiboxlayout.h new file mode 100644 index 00000000..1200db63 --- /dev/null +++ b/src/framework/ui/uiboxlayout.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef UIBOXLAYOUT_H +#define UIBOXLAYOUT_H + +#include "uilayout.h" + +class UIBoxLayout : public UILayout +{ +public: + UIBoxLayout(UIWidgetPtr parentWidget); + + void applyStyle(const OTMLNodePtr& styleNode); + void addWidget(const UIWidgetPtr& widget) { update(); } + void removeWidget(const UIWidgetPtr& widget) { update(); } + + void setSpacing(int spacing) { m_spacing = spacing; update(); } + void setFitChildren(bool fitParent) { m_fitChildren = fitParent; update(); } + + UIBoxLayoutPtr asUIBoxLayout() { return std::static_pointer_cast(shared_from_this()); } + +protected: + Boolean m_fitChildren; + int m_spacing; +}; + +#endif diff --git a/src/framework/ui/uihorizontallayout.cpp b/src/framework/ui/uihorizontallayout.cpp new file mode 100644 index 00000000..f0d026ef --- /dev/null +++ b/src/framework/ui/uihorizontallayout.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "uihorizontallayout.h" +#include "uiwidget.h" +#include + + +void UIHorizontalLayout::applyStyle(const OTMLNodePtr& styleNode) +{ + UIBoxLayout::applyStyle(styleNode); + + for(const OTMLNodePtr& node : styleNode->children()) { + if(node->tag() == "align-right") + setAlignRight(node->value()); + } +} + +void UIHorizontalLayout::internalUpdate() +{ + UIWidgetPtr parentWidget = getParentWidget(); + UIWidgetList widgets = parentWidget->getChildren(); + + if(m_alignRight) + std::reverse(widgets.begin(), widgets.end()); + + Rect childrenRect = parentWidget->getChildrenRect(); + Point pos = (m_alignRight) ? childrenRect.topRight() : childrenRect.topLeft(); + int prefferedWidth = 0; + int gap; + + for(const UIWidgetPtr& widget : widgets) { + if(!widget->isExplicitlyVisible()) + continue; + + Size size = widget->getSize(); + + gap = (m_alignRight) ? -(widget->getMarginRight()+widget->getWidth()) : widget->getMarginLeft(); + pos.x += gap; + prefferedWidth += gap; + + if(widget->isFixedSize()) { + // center it + pos.y = childrenRect.top() + (childrenRect.height() - (widget->getMarginTop() + widget->getHeight() + widget->getMarginBottom()))/2; + pos.y = std::max(pos.y, parentWidget->getY()); + } else { + // expand height + size.setHeight(childrenRect.height() - (widget->getMarginTop() + widget->getMarginBottom())); + pos.y = childrenRect.top() + (childrenRect.height() - size.height())/2; + } + + widget->setRect(Rect(pos, size)); + + gap = (m_alignRight) ? -widget->getMarginLeft() : (widget->getWidth() + widget->getMarginRight()); + gap += m_spacing; + pos.x += gap; + prefferedWidth += gap; + } + + prefferedWidth -= m_spacing; + prefferedWidth += parentWidget->getPaddingLeft() + parentWidget->getPaddingRight(); + + if(m_fitChildren && prefferedWidth != parentWidget->getWidth()) { + // must set the preffered width later + g_dispatcher.addEvent([=] { + parentWidget->setWidth(prefferedWidth); + }); + } +} diff --git a/src/framework/ui/uihorizontallayout.h b/src/framework/ui/uihorizontallayout.h new file mode 100644 index 00000000..f0826530 --- /dev/null +++ b/src/framework/ui/uihorizontallayout.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010-2012 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef UIHORIZONTALLAYOUT_H +#define UIHORIZONTALLAYOUT_H + +#include "uiboxlayout.h" + +class UIHorizontalLayout : public UIBoxLayout +{ +public: + UIHorizontalLayout(UIWidgetPtr parentWidget) : UIBoxLayout(parentWidget) { } + + void applyStyle(const OTMLNodePtr& styleNode); + + void setAlignRight(bool aliginRight) { m_alignRight = aliginRight; update(); } + + UIHorizontalLayoutPtr asUIHorizontalLayout() { return std::static_pointer_cast(shared_from_this()); } + +protected: + void internalUpdate(); + + Boolean m_alignRight; +}; + +#endif diff --git a/src/framework/ui/uilayout.h b/src/framework/ui/uilayout.h index dd1563e5..28baf1d8 100644 --- a/src/framework/ui/uilayout.h +++ b/src/framework/ui/uilayout.h @@ -49,6 +49,8 @@ public: UILayoutPtr asUILayout() { return std::static_pointer_cast(shared_from_this()); } virtual UIAnchorLayoutPtr asUIAnchorLayout() { return nullptr; } + virtual UIBoxLayoutPtr asUIBoxLayout() { return nullptr; } + virtual UIHorizontalLayoutPtr asUIHorizontalLayout() { return nullptr; } virtual UIVerticalLayoutPtr asUIVerticalLayout() { return nullptr; } virtual UIGridLayoutPtr asUIGridLayout() { return nullptr; } diff --git a/src/framework/ui/uiverticallayout.cpp b/src/framework/ui/uiverticallayout.cpp index 2eb72088..5e50f2b5 100644 --- a/src/framework/ui/uiverticallayout.cpp +++ b/src/framework/ui/uiverticallayout.cpp @@ -24,23 +24,13 @@ #include "uiwidget.h" #include -UIVerticalLayout::UIVerticalLayout(UIWidgetPtr parentWidget) - : UILayout(parentWidget) -{ - m_spacing = 0; -} - void UIVerticalLayout::applyStyle(const OTMLNodePtr& styleNode) { - UILayout::applyStyle(styleNode); + UIBoxLayout::applyStyle(styleNode); for(const OTMLNodePtr& node : styleNode->children()) { if(node->tag() == "align-bottom") setAlignBottom(node->value()); - else if(node->tag() == "spacing") - setSpacing(node->value()); - else if(node->tag() == "fit-parent") - setFitParent(node->value()); } } @@ -88,10 +78,10 @@ void UIVerticalLayout::internalUpdate() prefferedHeight -= m_spacing; prefferedHeight += parentWidget->getPaddingTop() + parentWidget->getPaddingBottom(); - if(m_fitParent && prefferedHeight != parentWidget->getHeight()) { + if(m_fitChildren && prefferedHeight != parentWidget->getHeight()) { // must set the preffered width later g_dispatcher.addEvent([=] { parentWidget->setHeight(prefferedHeight); }); } -} \ No newline at end of file +} diff --git a/src/framework/ui/uiverticallayout.h b/src/framework/ui/uiverticallayout.h index 78e63156..ceeb4e39 100644 --- a/src/framework/ui/uiverticallayout.h +++ b/src/framework/ui/uiverticallayout.h @@ -23,30 +23,23 @@ #ifndef UIVERTICALLAYOUT_H #define UIVERTICALLAYOUT_H -#include "uilayout.h" +#include "uiboxlayout.h" -class UIVerticalLayout : public UILayout +class UIVerticalLayout : public UIBoxLayout { public: - UIVerticalLayout(UIWidgetPtr parentWidget); + UIVerticalLayout(UIWidgetPtr parentWidget) : UIBoxLayout(parentWidget) { } void applyStyle(const OTMLNodePtr& styleNode); - void addWidget(const UIWidgetPtr& widget) { update(); } - void removeWidget(const UIWidgetPtr& widget) { update(); } void setAlignBottom(bool aliginBottom) { m_alignBottom = aliginBottom; update(); } - void setSpacing(int spacing) { m_spacing = spacing; update(); } - void setFitParent(bool fitParent) { m_fitParent = fitParent; update(); } UIVerticalLayoutPtr asUIVerticalLayout() { return std::static_pointer_cast(shared_from_this()); } protected: void internalUpdate(); -private: Boolean m_alignBottom; - Boolean m_fitParent; - int m_spacing; }; #endif diff --git a/src/framework/ui/uiwidgetbasestyle.cpp b/src/framework/ui/uiwidgetbasestyle.cpp index e28d7e90..d38b6dd8 100644 --- a/src/framework/ui/uiwidgetbasestyle.cpp +++ b/src/framework/ui/uiwidgetbasestyle.cpp @@ -21,6 +21,7 @@ */ #include "uiwidget.h" +#include "uihorizontallayout.h" #include "uiverticallayout.h" #include "uigridlayout.h" #include "uianchorlayout.h" @@ -232,7 +233,9 @@ void UIWidget::parseBaseStyle(const OTMLNodePtr& styleNode) if(!layoutType.empty()) { UILayoutPtr layout; - if(layoutType == "verticalBox") + if(layoutType == "horizontalBox") + layout = UIHorizontalLayoutPtr(new UIHorizontalLayout(asUIWidget())); + else if(layoutType == "verticalBox") layout = UIVerticalLayoutPtr(new UIVerticalLayout(asUIWidget())); else if(layoutType == "grid") layout = UIGridLayoutPtr(new UIGridLayout(asUIWidget()));