mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-29 22:45:36 +00:00
Make coordinate calculation more robust, implement Flex widget type
This commit is contained in:
parent
fbc84465c5
commit
788745e004
10 changed files with 181 additions and 25 deletions
|
@ -256,7 +256,7 @@ add_component_dir (fallback
|
|||
add_component_dir (lua_ui
|
||||
registerscriptsettings scriptsettings
|
||||
properties widget element util layers content alignment resources
|
||||
adapter text textedit window image container
|
||||
adapter text textedit window image container flex
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -9,9 +9,9 @@ namespace LuaUi
|
|||
align |= MyGUI::Align::Left;
|
||||
if (horizontal == Alignment::End)
|
||||
align |= MyGUI::Align::Right;
|
||||
if (horizontal == Alignment::Start)
|
||||
if (vertical == Alignment::Start)
|
||||
align |= MyGUI::Align::Top;
|
||||
if (horizontal == Alignment::End)
|
||||
if (vertical == Alignment::End)
|
||||
align |= MyGUI::Align::Bottom;
|
||||
return align;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace LuaUi
|
|||
size.width = std::max(size.width, coord.left + coord.width);
|
||||
size.height = std::max(size.height, coord.top + coord.height);
|
||||
}
|
||||
setForcedSize(size);
|
||||
forceSize(size);
|
||||
updateCoord();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,8 +136,8 @@ namespace LuaUi
|
|||
setTemplate(ext, layout.get<sol::object>(LayoutKeys::templateLayout));
|
||||
ext->setProperties(layout.get<sol::object>(LayoutKeys::props));
|
||||
setEventCallbacks(ext, layout.get<sol::object>(LayoutKeys::events));
|
||||
|
||||
ext->setChildren(updateContent(ext->children(), layout.get<sol::object>(LayoutKeys::content)));
|
||||
ext->updateCoord();
|
||||
}
|
||||
|
||||
std::string setLayer(WidgetExtension* ext, const sol::table& layout)
|
||||
|
|
106
components/lua_ui/flex.cpp
Normal file
106
components/lua_ui/flex.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
#include "flex.hpp"
|
||||
|
||||
namespace LuaUi
|
||||
{
|
||||
void LuaFlex::updateProperties()
|
||||
{
|
||||
mHorizontal = propertyValue("horizontal", false);
|
||||
mAutoSized = propertyValue("autoSize", true);
|
||||
mAlign = propertyValue("align", Alignment::Start);
|
||||
mArrange = propertyValue("arrange", Alignment::Start);
|
||||
WidgetExtension::updateProperties();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
MyGUI::IntPoint alignSize(const MyGUI::IntSize& container, const MyGUI::IntSize& content, Alignment alignment)
|
||||
{
|
||||
MyGUI::IntPoint alignedPosition;
|
||||
{
|
||||
MyGUI::IntSize alignSize = container;
|
||||
switch (alignment)
|
||||
{
|
||||
case Alignment::Start:
|
||||
alignedPosition = MyGUI::IntPoint(0, 0);
|
||||
break;
|
||||
case Alignment::Center:
|
||||
alignSize -= content;
|
||||
alignedPosition = { alignSize.width / 2, alignSize.height / 2 };
|
||||
break;
|
||||
case Alignment::End:
|
||||
alignSize -= content;
|
||||
alignedPosition = { alignSize.width, alignSize.height };
|
||||
break;
|
||||
}
|
||||
}
|
||||
return alignedPosition;
|
||||
}
|
||||
}
|
||||
|
||||
void LuaFlex::updateChildren()
|
||||
{
|
||||
float totalGrow = 0;
|
||||
MyGUI::IntSize childrenSize;
|
||||
for (auto* w: children())
|
||||
{
|
||||
w->clearForced();
|
||||
childrenSize += w->calculateSize();
|
||||
totalGrow += w->externalValue("grow", 0.0f);
|
||||
}
|
||||
mChildrenSize = childrenSize;
|
||||
|
||||
MyGUI::IntSize flexSize = calculateSize();
|
||||
MyGUI::IntSize growSize;
|
||||
MyGUI::FloatSize growFactor;
|
||||
if (totalGrow > 0)
|
||||
{
|
||||
growSize = flexSize - childrenSize;
|
||||
growFactor = { growSize.width / totalGrow, growSize.height / totalGrow };
|
||||
}
|
||||
if (mHorizontal)
|
||||
flexSize.width -= growSize.width;
|
||||
else
|
||||
flexSize.height-= growSize.height;
|
||||
|
||||
MyGUI::IntPoint alignedPosition = alignSize(flexSize, childrenSize, mAlign);
|
||||
MyGUI::IntPoint arrangedPosition = alignSize(flexSize, childrenSize, mArrange);
|
||||
MyGUI::IntPoint childPosition;
|
||||
if (mHorizontal)
|
||||
childPosition = { alignedPosition.left, arrangedPosition.top };
|
||||
else
|
||||
childPosition = { arrangedPosition.left, alignedPosition.top };
|
||||
for (auto* w : children())
|
||||
{
|
||||
w->forcePosition(childPosition);
|
||||
float grow = w->externalValue("grow", 0);
|
||||
MyGUI::IntSize growth(growFactor.width * grow, growFactor.height * grow);
|
||||
if (mHorizontal)
|
||||
{
|
||||
int width = w->widget()->getWidth();
|
||||
width += growth.width;
|
||||
w->forceSize({width, w->widget()->getHeight()});
|
||||
childPosition.left += width;
|
||||
}
|
||||
else
|
||||
{
|
||||
int height = w->widget()->getHeight();
|
||||
height += growth.height;
|
||||
w->forceSize({ w->widget()->getWidth(), height });
|
||||
childPosition.top += height;
|
||||
}
|
||||
}
|
||||
WidgetExtension::updateProperties();
|
||||
}
|
||||
|
||||
MyGUI::IntSize LuaFlex::calculateSize()
|
||||
{
|
||||
MyGUI::IntSize size = WidgetExtension::calculateSize();
|
||||
if (mAutoSized) {
|
||||
if (mHorizontal)
|
||||
size.width = mChildrenSize.width;
|
||||
else
|
||||
size.height = mChildrenSize.height;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
27
components/lua_ui/flex.hpp
Normal file
27
components/lua_ui/flex.hpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef OPENMW_LUAUI_FLEX
|
||||
#define OPENMW_LUAUI_FLEX
|
||||
|
||||
#include "widget.hpp"
|
||||
#include "alignment.hpp"
|
||||
|
||||
namespace LuaUi
|
||||
{
|
||||
class LuaFlex : public MyGUI::Widget, public WidgetExtension
|
||||
{
|
||||
MYGUI_RTTI_DERIVED(LuaFlex)
|
||||
|
||||
protected:
|
||||
MyGUI::IntSize calculateSize() override;
|
||||
void updateProperties() override;
|
||||
void updateChildren() override;
|
||||
|
||||
private:
|
||||
bool mHorizontal;
|
||||
bool mAutoSized;
|
||||
MyGUI::IntSize mChildrenSize;
|
||||
Alignment mAlign;
|
||||
Alignment mArrange;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // OPENMW_LUAUI_FLEX
|
|
@ -9,6 +9,7 @@
|
|||
#include "window.hpp"
|
||||
#include "image.hpp"
|
||||
#include "container.hpp"
|
||||
#include "flex.hpp"
|
||||
|
||||
#include "element.hpp"
|
||||
#include "registerscriptsettings.hpp"
|
||||
|
@ -24,8 +25,9 @@ namespace LuaUi
|
|||
MyGUI::FactoryManager::getInstance().registerFactory<LuaTextEdit>("Widget");
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<LuaWindow>("Widget");
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<LuaImage>("Widget");
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<LuaContainer>("Widget");
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<LuaTileRect>("BasisSkin");
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<LuaContainer>("Widget");
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<LuaFlex>("Widget");
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string, std::string>& widgetTypeToName()
|
||||
|
@ -36,6 +38,7 @@ namespace LuaUi
|
|||
{ "LuaTextEdit", "TextEdit" },
|
||||
{ "LuaWindow", "Window" },
|
||||
{ "LuaImage", "Image" },
|
||||
{ "LuaFlex", "Flex" },
|
||||
};
|
||||
return types;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,9 @@
|
|||
namespace LuaUi
|
||||
{
|
||||
WidgetExtension::WidgetExtension()
|
||||
: mPropagateEvents(true)
|
||||
: mForcePosition(false)
|
||||
, mForceSize(false)
|
||||
, mPropagateEvents(true)
|
||||
, mLua(nullptr)
|
||||
, mWidget(nullptr)
|
||||
, mSlot(this)
|
||||
|
@ -85,7 +87,6 @@ namespace LuaUi
|
|||
ext->mParent = this;
|
||||
ext->mTemplateChild = false;
|
||||
ext->widget()->attachToWidget(mSlot->widget());
|
||||
ext->updateCoord();
|
||||
}
|
||||
|
||||
void WidgetExtension::attachTemplate(WidgetExtension* ext)
|
||||
|
@ -93,7 +94,6 @@ namespace LuaUi
|
|||
ext->mParent = this;
|
||||
ext->mTemplateChild = true;
|
||||
ext->widget()->attachToWidget(widget());
|
||||
ext->updateCoord();
|
||||
}
|
||||
|
||||
WidgetExtension* WidgetExtension::findDeep(std::string_view flagName)
|
||||
|
@ -219,16 +219,30 @@ namespace LuaUi
|
|||
return mForcedCoord;
|
||||
}
|
||||
|
||||
void WidgetExtension::setForcedCoord(const MyGUI::IntCoord& offset)
|
||||
void WidgetExtension::forceCoord(const MyGUI::IntCoord& offset)
|
||||
{
|
||||
mForcePosition = true;
|
||||
mForceSize = true;
|
||||
mForcedCoord = offset;
|
||||
}
|
||||
|
||||
void WidgetExtension::setForcedSize(const MyGUI::IntSize& size)
|
||||
void WidgetExtension::forcePosition(const MyGUI::IntPoint& pos)
|
||||
{
|
||||
mForcePosition = true;
|
||||
mForcedCoord = pos;
|
||||
}
|
||||
|
||||
void WidgetExtension::forceSize(const MyGUI::IntSize& size)
|
||||
{
|
||||
mForceSize = true;
|
||||
mForcedCoord = size;
|
||||
}
|
||||
|
||||
void WidgetExtension::clearForced() {
|
||||
mForcePosition = false;
|
||||
mForceSize = false;
|
||||
}
|
||||
|
||||
void WidgetExtension::updateCoord()
|
||||
{
|
||||
MyGUI::IntCoord oldCoord = mWidget->getCoord();
|
||||
|
@ -246,7 +260,6 @@ namespace LuaUi
|
|||
{
|
||||
mProperties = props;
|
||||
updateProperties();
|
||||
updateCoord();
|
||||
}
|
||||
|
||||
void WidgetExtension::updateProperties()
|
||||
|
@ -281,9 +294,12 @@ namespace LuaUi
|
|||
|
||||
MyGUI::IntSize WidgetExtension::calculateSize()
|
||||
{
|
||||
if (mForceSize)
|
||||
return mForcedCoord.size();
|
||||
|
||||
MyGUI::IntSize pSize = parentSize();
|
||||
MyGUI::IntSize newSize;
|
||||
newSize = mAbsoluteCoord.size() + mForcedCoord.size();
|
||||
newSize = mAbsoluteCoord.size();
|
||||
newSize.width += mRelativeCoord.width * pSize.width;
|
||||
newSize.height += mRelativeCoord.height * pSize.height;
|
||||
return newSize;
|
||||
|
@ -291,9 +307,11 @@ namespace LuaUi
|
|||
|
||||
MyGUI::IntPoint WidgetExtension::calculatePosition(const MyGUI::IntSize& size)
|
||||
{
|
||||
if (mForcePosition)
|
||||
return mForcedCoord.point();
|
||||
MyGUI::IntSize pSize = parentSize();
|
||||
MyGUI::IntPoint newPosition;
|
||||
newPosition = mAbsoluteCoord.point() + mForcedCoord.point();
|
||||
newPosition = mAbsoluteCoord.point();
|
||||
newPosition.left += mRelativeCoord.left * pSize.width - mAnchor.width * size.width;
|
||||
newPosition.top += mRelativeCoord.top * pSize.height - mAnchor.height * size.height;
|
||||
return newPosition;
|
||||
|
|
|
@ -47,8 +47,11 @@ namespace LuaUi
|
|||
void setExternal(sol::object external) { mExternal = external; }
|
||||
|
||||
MyGUI::IntCoord forcedCoord();
|
||||
void setForcedCoord(const MyGUI::IntCoord& offset);
|
||||
void setForcedSize(const MyGUI::IntSize& size);
|
||||
void forceCoord(const MyGUI::IntCoord& offset);
|
||||
void forceSize(const MyGUI::IntSize& size);
|
||||
void forcePosition(const MyGUI::IntPoint& pos);
|
||||
void clearForced();
|
||||
|
||||
void updateCoord();
|
||||
|
||||
const sol::table& getLayout() { return mLayout; }
|
||||
|
@ -65,6 +68,9 @@ namespace LuaUi
|
|||
mOnCoordChange = callback;
|
||||
}
|
||||
|
||||
virtual MyGUI::IntSize calculateSize();
|
||||
virtual MyGUI::IntPoint calculatePosition(const MyGUI::IntSize& size);
|
||||
|
||||
protected:
|
||||
virtual void initialize();
|
||||
sol::table makeTable() const;
|
||||
|
@ -72,8 +78,6 @@ namespace LuaUi
|
|||
sol::object mouseEvent(int left, int top, MyGUI::MouseButton button) const;
|
||||
|
||||
MyGUI::IntSize parentSize();
|
||||
virtual MyGUI::IntSize calculateSize();
|
||||
virtual MyGUI::IntPoint calculatePosition(const MyGUI::IntSize& size);
|
||||
MyGUI::IntCoord calculateCoord();
|
||||
virtual MyGUI::IntSize childScalingSize();
|
||||
|
||||
|
@ -113,6 +117,8 @@ namespace LuaUi
|
|||
}
|
||||
}
|
||||
|
||||
bool mForcePosition;
|
||||
bool mForceSize;
|
||||
// offsets the position and size, used only in C++ widget code
|
||||
MyGUI::IntCoord mForcedCoord;
|
||||
// position and size in pixels
|
||||
|
|
|
@ -39,8 +39,7 @@ namespace LuaUi
|
|||
if (mCaption)
|
||||
mCaption->setCaption(propertyValue("caption", std::string()));
|
||||
mMoveResize = MyGUI::IntCoord();
|
||||
setForcedCoord(mMoveResize);
|
||||
|
||||
clearForced();
|
||||
WidgetExtension::updateProperties();
|
||||
}
|
||||
|
||||
|
@ -70,11 +69,8 @@ namespace LuaUi
|
|||
change.width *= (left - mPreviousMouse.left);
|
||||
change.height *= (top - mPreviousMouse.top);
|
||||
|
||||
mMoveResize = mMoveResize + change.size();
|
||||
setForcedCoord(mMoveResize);
|
||||
// position can change based on size changes
|
||||
mMoveResize = mMoveResize + change.point() + getPosition() - calculateCoord().point();
|
||||
setForcedCoord(mMoveResize);
|
||||
mMoveResize = mMoveResize + change;
|
||||
forceCoord(mMoveResize);
|
||||
updateCoord();
|
||||
|
||||
mPreviousMouse.left = left;
|
||||
|
|
Loading…
Reference in a new issue