mirror of https://github.com/OpenMW/openmw.git
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
204 lines
7.1 KiB
C++
204 lines
7.1 KiB
C++
#ifndef OPENMW_LUAUI_WIDGET
|
|
#define OPENMW_LUAUI_WIDGET
|
|
|
|
#include <functional>
|
|
#include <map>
|
|
|
|
#include <MyGUI_Widget.h>
|
|
#include <sol/sol.hpp>
|
|
|
|
#include <components/lua/asyncpackage.hpp>
|
|
|
|
#include "properties.hpp"
|
|
|
|
namespace LuaUi
|
|
{
|
|
/*
|
|
* extends MyGUI::Widget and its child classes
|
|
* memory ownership is controlled by MyGUI
|
|
* it is important not to call any WidgetExtension methods after destroying the MyGUI::Widget
|
|
*/
|
|
class WidgetExtension
|
|
{
|
|
public:
|
|
WidgetExtension();
|
|
|
|
virtual ~WidgetExtension() = default;
|
|
|
|
// must be called after creating the underlying MyGUI::Widget
|
|
void initialize(lua_State* lua, MyGUI::Widget* self, bool isRoot);
|
|
// must be called after before destroying the underlying MyGUI::Widget
|
|
virtual void deinitialize();
|
|
|
|
MyGUI::Widget* widget() const { return mWidget; }
|
|
|
|
bool isRoot() const { return mElementRoot; }
|
|
WidgetExtension* getParent() const { return mParent; }
|
|
void detachFromParent();
|
|
|
|
void detachChildrenIf(auto&& predicate) { detachChildrenIf(predicate, mChildren); }
|
|
void detachTemplateChildrenIf(auto&& predicate) { detachChildrenIf(predicate, mTemplateChildren); }
|
|
|
|
void reset();
|
|
|
|
const std::vector<WidgetExtension*>& children() { return mChildren; }
|
|
void setChildren(const std::vector<WidgetExtension*>&);
|
|
|
|
const std::vector<WidgetExtension*>& templateChildren() { return mTemplateChildren; }
|
|
void setTemplateChildren(const std::vector<WidgetExtension*>&);
|
|
|
|
void setCallback(const std::string&, const LuaUtil::Callback&);
|
|
void clearCallbacks();
|
|
|
|
void setProperties(const sol::object& props);
|
|
void setTemplateProperties(const sol::object& props) { mTemplateProperties = props; }
|
|
|
|
void setExternal(const sol::object& external) { mExternal = external; }
|
|
|
|
MyGUI::IntCoord forcedCoord();
|
|
void forceCoord(const MyGUI::IntCoord& offset);
|
|
void forceSize(const MyGUI::IntSize& size);
|
|
void forcePosition(const MyGUI::IntPoint& pos);
|
|
void clearForced();
|
|
|
|
virtual void updateCoord();
|
|
|
|
const sol::table& getLayout() { return mLayout; }
|
|
void setLayout(const sol::table& layout) { mLayout = layout; }
|
|
|
|
template <typename T>
|
|
T externalValue(std::string_view name, const T& defaultValue) const
|
|
{
|
|
return parseExternal(mExternal, name, defaultValue);
|
|
}
|
|
|
|
virtual MyGUI::IntSize calculateSize() const;
|
|
virtual MyGUI::IntPoint calculatePosition(const MyGUI::IntSize& size) const;
|
|
MyGUI::IntCoord calculateCoord() const;
|
|
|
|
virtual bool isTextInput() { return false; }
|
|
|
|
protected:
|
|
virtual void initialize();
|
|
void registerEvents(MyGUI::Widget* w);
|
|
void clearEvents(MyGUI::Widget* w);
|
|
|
|
sol::table makeTable() const;
|
|
sol::object keyEvent(MyGUI::KeyCode) const;
|
|
sol::object mouseEvent(int left, int top, MyGUI::MouseButton button) const;
|
|
|
|
MyGUI::IntSize parentSize() const;
|
|
virtual MyGUI::IntSize childScalingSize() const;
|
|
virtual MyGUI::IntSize templateScalingSize() const;
|
|
|
|
template <typename T>
|
|
T propertyValue(std::string_view name, const T& defaultValue)
|
|
{
|
|
return parseProperty(mProperties, mTemplateProperties, name, defaultValue);
|
|
}
|
|
|
|
WidgetExtension* findDeepInTemplates(std::string_view flagName);
|
|
std::vector<WidgetExtension*> findAllInTemplates(std::string_view flagName);
|
|
|
|
virtual void updateTemplate();
|
|
virtual void updateProperties();
|
|
virtual void updateChildren() {}
|
|
|
|
lua_State* lua() const { return mLua; }
|
|
|
|
void triggerEvent(std::string_view name, sol::object argument) const;
|
|
template <class ArgFactory>
|
|
void propagateEvent(std::string_view name, const ArgFactory& argumentFactory) const
|
|
{
|
|
const WidgetExtension* w = this;
|
|
while (w)
|
|
{
|
|
bool shouldPropagate = true;
|
|
auto it = w->mCallbacks.find(name);
|
|
if (it != w->mCallbacks.end())
|
|
{
|
|
sol::object res = it->second.call(argumentFactory(w), w->mLayout);
|
|
shouldPropagate = res.is<bool>() && res.as<bool>();
|
|
}
|
|
if (w->mParent && w->mPropagateEvents && shouldPropagate)
|
|
w = w->mParent;
|
|
else
|
|
w = nullptr;
|
|
}
|
|
}
|
|
|
|
bool mForcePosition;
|
|
bool mForceSize;
|
|
// offsets the position and size, used only in C++ widget code
|
|
MyGUI::IntCoord mForcedCoord;
|
|
// position and size in pixels
|
|
MyGUI::IntCoord mAbsoluteCoord;
|
|
// position and size as a ratio of parent size
|
|
MyGUI::FloatCoord mRelativeCoord;
|
|
// negative position offset as a ratio of this widget's size
|
|
// used in combination with relative coord to align the widget, e. g. center it
|
|
MyGUI::FloatSize mAnchor;
|
|
|
|
bool mPropagateEvents;
|
|
bool mVisible; // used to implement updateVisible
|
|
|
|
private:
|
|
// use lua_State* instead of sol::state_view because MyGUI requires a default constructor
|
|
lua_State* mLua;
|
|
MyGUI::Widget* mWidget;
|
|
std::vector<WidgetExtension*> mChildren;
|
|
std::vector<WidgetExtension*> mTemplateChildren;
|
|
WidgetExtension* mSlot;
|
|
std::map<std::string, LuaUtil::Callback, std::less<>> mCallbacks;
|
|
sol::table mLayout;
|
|
sol::object mProperties;
|
|
sol::object mTemplateProperties;
|
|
sol::object mExternal;
|
|
WidgetExtension* mParent;
|
|
bool mTemplateChild;
|
|
bool mElementRoot;
|
|
|
|
void attach(WidgetExtension* ext);
|
|
void attachTemplate(WidgetExtension* ext);
|
|
|
|
WidgetExtension* findDeep(std::string_view name);
|
|
void findAll(std::string_view flagName, std::vector<WidgetExtension*>& result);
|
|
|
|
void updateChildrenCoord();
|
|
|
|
void keyPress(MyGUI::Widget*, MyGUI::KeyCode, MyGUI::Char);
|
|
void keyRelease(MyGUI::Widget*, MyGUI::KeyCode);
|
|
void mouseMove(MyGUI::Widget*, int, int);
|
|
void mouseDrag(MyGUI::Widget*, int, int, MyGUI::MouseButton);
|
|
void mouseClick(MyGUI::Widget*);
|
|
void mouseDoubleClick(MyGUI::Widget*);
|
|
void mousePress(MyGUI::Widget*, int, int, MyGUI::MouseButton);
|
|
void mouseRelease(MyGUI::Widget*, int, int, MyGUI::MouseButton);
|
|
void focusGain(MyGUI::Widget*, MyGUI::Widget*);
|
|
void focusLoss(MyGUI::Widget*, MyGUI::Widget*);
|
|
|
|
void updateVisible();
|
|
|
|
void detachChildrenIf(auto&& predicate, std::vector<WidgetExtension*> children)
|
|
{
|
|
for (auto it = children.begin(); it != children.end();)
|
|
{
|
|
if (predicate(*it))
|
|
{
|
|
(*it)->detachFromParent();
|
|
it = children.erase(it);
|
|
}
|
|
else
|
|
++it;
|
|
}
|
|
}
|
|
};
|
|
|
|
class LuaWidget : public MyGUI::Widget, public WidgetExtension
|
|
{
|
|
MYGUI_RTTI_DERIVED(LuaWidget)
|
|
};
|
|
}
|
|
|
|
#endif // !OPENMW_LUAUI_WIDGET
|