Index: source/gui/CGUISetting.h =================================================================== --- source/gui/CGUISetting.h +++ source/gui/CGUISetting.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -21,6 +21,7 @@ #include "ps/CStr.h" #include "scriptinterface/ScriptForward.h" +#include class IGUIObject; @@ -33,6 +34,7 @@ { public: NONCOPYABLE(IGUISetting); + IGUISetting(const CStr& name, IGUIObject* owner); /** @@ -51,7 +53,8 @@ virtual void ToJSVal(const ScriptRequest& rq, JS::MutableHandleValue value) = 0; protected: - IGUISetting(IGUISetting&& o); + IGUISetting(IGUISetting&& other); + virtual ~IGUISetting() = default; virtual bool DoFromString(const CStrW& value) = 0; @@ -67,12 +70,18 @@ /** * Return the name of the setting, from JS. */ - virtual CStr GetName() const = 0; + const CStr& GetName() const + { + return m_Name; + } /** * The object that stores this setting. */ - IGUIObject& m_pObject; + std::reference_wrapper m_Object; + +private: + CStr m_Name; }; /** @@ -85,11 +94,11 @@ { public: template - CGUISimpleSetting(IGUIObject* pObject, const CStr& Name, Args&&... args) - : IGUISetting(Name, pObject), m_Name(Name), m_Setting(args...) + CGUISimpleSetting(IGUIObject* pObject, const CStr& name, Args&&... args) + : IGUISetting(name, pObject), m_Setting(args...) {} NONCOPYABLE(CGUISimpleSetting); - MOVABLE(CGUISimpleSetting); + CGUISimpleSetting(CGUISimpleSetting&&) = default; operator const T&() const { return m_Setting; } const T& operator*() const { return m_Setting; } @@ -106,20 +115,14 @@ void Set(T value, bool sendMessage) { m_Setting = std::move(value); - OnSettingChange(m_Name, sendMessage); + OnSettingChange(GetName(), sendMessage); } protected: - CStr GetName() const override - { - return m_Name; - } - bool DoFromString(const CStrW& value) override; bool DoFromJSVal(const ScriptRequest& rq, JS::HandleValue value) override; void ToJSVal(const ScriptRequest& rq, JS::MutableHandleValue value) override; - const CStr m_Name; T m_Setting; }; Index: source/gui/CGUISetting.cpp =================================================================== --- source/gui/CGUISetting.cpp +++ source/gui/CGUISetting.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -20,18 +20,25 @@ #include "CGUISetting.h" #include "gui/CGUI.h" +#include "gui/CGUISprite.h" #include "gui/ObjectBases/IGUIObject.h" +#include "gui/SettingTypes/CGUIList.h" +#include "gui/SettingTypes/CGUISeries.h" +#include "gui/SettingTypes/CGUISize.h" +#include "gui/SettingTypes/CGUIString.h" +#include "gui/SettingTypes/EAlign.h" #include "ps/CLogger.h" +#include "ps/CStr.h" #include "scriptinterface/ScriptConversions.h" -IGUISetting::IGUISetting(const CStr& name, IGUIObject* owner) : m_pObject(*owner) +IGUISetting::IGUISetting(const CStr& name, IGUIObject* owner) : m_Object(*owner), m_Name(name) { - m_pObject.RegisterSetting(name, this); + m_Object.get().RegisterSetting(m_Name, this); } -IGUISetting::IGUISetting(IGUISetting&& o) : m_pObject(o.m_pObject) +IGUISetting::IGUISetting(IGUISetting&& other) : m_Object(other.m_Object), m_Name(other.m_Name) { - m_pObject.ReregisterSetting(o.GetName(), this); + m_Object.get().ReregisterSetting(m_Name, this); } bool IGUISetting::FromString(const CStrW& value, const bool sendMessage) @@ -57,13 +64,13 @@ void IGUISetting::OnSettingChange(const CStr& setting, bool sendMessage) { - m_pObject.SettingChanged(setting, sendMessage); + m_Object.get().SettingChanged(setting, sendMessage); } template bool CGUISimpleSetting::DoFromString(const CStrW& value) { - return CGUI::ParseString(&m_pObject.GetGUI(), value, m_Setting); + return CGUI::ParseString(&m_Object.get().GetGUI(), value, m_Setting); }; template<> @@ -75,7 +82,7 @@ if (!Script::FromJSVal(rq, value, name)) return false; - if (!m_Setting.ParseString(m_pObject.GetGUI(), name)) + if (!m_Setting.ParseString(m_Object.get().GetGUI(), name)) { LOGERROR("Invalid color '%s'", name.c_str()); return false; @@ -108,23 +115,16 @@ TYPE(u32) TYPE(float) TYPE(CVector2D) -#include "ps/CStr.h" TYPE(CStr) TYPE(CStrW) // TODO: make these inherit from CGUISimpleSetting directly. -#include "gui/SettingTypes/CGUISize.h" TYPE(CGUISize) TYPE(CGUIColor) -#include "gui/CGUISprite.h" TYPE(CGUISpriteInstance) -#include "gui/SettingTypes/CGUIString.h" TYPE(CGUIString) -#include "gui/SettingTypes/EAlign.h" TYPE(EAlign) TYPE(EVAlign) -#include "gui/SettingTypes/CGUIList.h" TYPE(CGUIList) -#include "gui/SettingTypes/CGUISeries.h" TYPE(CGUISeries) #undef TYPE Index: source/gui/ObjectTypes/CDropDown.cpp =================================================================== --- source/gui/ObjectTypes/CDropDown.cpp +++ source/gui/ObjectTypes/CDropDown.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -51,8 +51,8 @@ m_Sprite2Disabled(this, "sprite2_disabled"), m_TextColorDisabled(this, "textcolor_disabled") // Add these in CList! And implement TODO - //RegisterSetting("textcolor_over"); - //RegisterSetting("textcolor_pressed"); + //m_TextColorOver("textcolor_over"); + //m_TextColorPressed("textcolor_pressed"); { m_ScrollBar.Set(true, true); } Index: source/gui/ObjectTypes/COList.h =================================================================== --- source/gui/ObjectTypes/COList.h +++ source/gui/ObjectTypes/COList.h @@ -34,7 +34,8 @@ {} // Avoid copying the strings. NONCOPYABLE(COListColumn); - MOVABLE(COListColumn); + COListColumn(COListColumn&&) = default; + CGUIColor m_TextColor; CStr m_Id; float m_Width; Index: source/gui/SettingTypes/CGUIHotkey.h =================================================================== --- source/gui/SettingTypes/CGUIHotkey.h +++ source/gui/SettingTypes/CGUIHotkey.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -34,7 +34,7 @@ CGUIHotkey(IGUIObject* pObject, const CStr& Name) : CGUISimpleSetting(pObject, Name) {} NONCOPYABLE(CGUIHotkey); - MOVABLE(CGUIHotkey); + CGUIHotkey(CGUIHotkey&&) = default; bool DoFromString(const CStrW& value) override; bool DoFromJSVal(const ScriptRequest& rq, JS::HandleValue value) override; Index: source/gui/SettingTypes/CGUIHotkey.cpp =================================================================== --- source/gui/SettingTypes/CGUIHotkey.cpp +++ source/gui/SettingTypes/CGUIHotkey.cpp @@ -25,18 +25,18 @@ bool CGUIHotkey::DoFromString(const CStrW& value) { - m_pObject.GetGUI().UnsetObjectHotkey(&m_pObject, m_Setting); + m_Object.get().GetGUI().UnsetObjectHotkey(&m_Object.get(), m_Setting); m_Setting = value.ToUTF8(); - m_pObject.GetGUI().SetObjectHotkey(&m_pObject, m_Setting); + m_Object.get().GetGUI().SetObjectHotkey(&m_Object.get(), m_Setting); return true; } bool CGUIHotkey::DoFromJSVal(const ScriptRequest& rq, JS::HandleValue value) { - m_pObject.GetGUI().UnsetObjectHotkey(&m_pObject, m_Setting); + m_Object.get().GetGUI().UnsetObjectHotkey(&m_Object.get(), m_Setting); if (!Script::FromJSVal(rq, value, m_Setting)) return false; - m_pObject.GetGUI().SetObjectHotkey(&m_pObject, m_Setting); + m_Object.get().GetGUI().SetObjectHotkey(&m_Object.get(), m_Setting); return true; } Index: source/gui/SettingTypes/MouseEventMask.h =================================================================== --- source/gui/SettingTypes/MouseEventMask.h +++ source/gui/SettingTypes/MouseEventMask.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -42,6 +42,7 @@ { public: CGUIMouseEventMask(IGUIObject* owner); + CGUIMouseEventMask(CGUIMouseEventMask&&) = default; ~CGUIMouseEventMask(); /** @@ -60,7 +61,6 @@ protected: bool DoFromString(const CStrW& value) override; bool DoFromJSVal(const ScriptRequest& rq, JS::HandleValue value) override; - CStr GetName() const override; std::string m_Spec; std::unique_ptr m_Impl; Index: source/gui/SettingTypes/MouseEventMask.cpp =================================================================== --- source/gui/SettingTypes/MouseEventMask.cpp +++ source/gui/SettingTypes/MouseEventMask.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -36,7 +36,7 @@ namespace { - const std::string MOUSE_EVENT_MASK = "mouse_event_mask"; + const CStr MOUSE_EVENT_MASK = "mouse_event_mask"; } class CGUIMouseEventMask::Impl @@ -65,11 +65,6 @@ if (!Script::FromJSVal(rq, value, spec)) return false; return DoFromString(spec); -} - -CStr CGUIMouseEventMask::GetName() const -{ - return MOUSE_EVENT_MASK; } bool CGUIMouseEventMask::IsMouseOver(const CVector2D& mousePos, const CRect& objectSize) const Index: source/gui/tests/test_GUISetting.h =================================================================== --- source/gui/tests/test_GUISetting.h +++ source/gui/tests/test_GUISetting.h @@ -0,0 +1,102 @@ +/* Copyright (C) 2023 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "lib/self_test.h" + +#include "graphics/FontManager.h" +#include "graphics/FontMetrics.h" +#include "gui/CGUI.h" +#include "gui/CGUISetting.h" +#include "gui/CGUIText.h" +#include "gui/ObjectBases/IGUIObject.h" +#include "gui/SettingTypes/CGUIString.h" +#include "ps/CLogger.h" +#include "ps/ConfigDB.h" +#include "ps/Filesystem.h" +#include "ps/ProfileViewer.h" +#include "ps/VideoMode.h" +#include "renderer/Renderer.h" +#include "scriptinterface/ScriptInterface.h" + +#include + +class TestGUISetting : public CxxTest::TestSuite +{ + CProfileViewer* m_Viewer = nullptr; + CRenderer* m_Renderer = nullptr; + +public: + class TestGUIObject : public IGUIObject + { + public: + TestGUIObject(CGUI& gui) : IGUIObject(gui) {} + + void Draw(CCanvas2D&) {} + }; + + void setUp() + { + g_VFS = CreateVfs(); + TS_ASSERT_OK(g_VFS->Mount(L"", DataDir() / "mods" / "_test.minimal" / "", VFS_MOUNT_MUST_EXIST)); + TS_ASSERT_OK(g_VFS->Mount(L"cache", DataDir() / "_testcache" / "", 0, VFS_MAX_PRIORITY)); + + CXeromyces::Startup(); + + // The renderer spews messages. + TestLogger logger; + + // We need to initialise the renderer to initialise the font manager. + // TODO: decouple this. + CConfigDB::Initialise(); + CConfigDB::Instance()->SetValueString(CFG_SYSTEM, "rendererbackend", "dummy"); + g_VideoMode.InitNonSDL(); + g_VideoMode.CreateBackendDevice(false); + m_Viewer = new CProfileViewer; + m_Renderer = new CRenderer(g_VideoMode.GetBackendDevice()); + } + + void tearDown() + { + delete m_Renderer; + delete m_Viewer; + g_VideoMode.Shutdown(); + CConfigDB::Shutdown(); + CXeromyces::Terminate(); + g_VFS.reset(); + DeleteDirectory(DataDir() / "_testcache"); + } + + void test_movability() + { + CGUI gui(g_ScriptContext); + TestGUIObject object(gui); + + static_assert(std::is_move_constructible_v>); + static_assert(!std::is_move_assignable_v>); + + CGUISimpleSetting settingA(&object, "A"); + TS_ASSERT(settingA->empty()); + TS_ASSERT(object.SettingExists("A")); + object.SetSettingFromString("A", L"ValueA", false); + TS_ASSERT_EQUALS(*settingA, "ValueA"); + + CGUISimpleSetting settingB(std::move(settingA)); + TS_ASSERT(object.SettingExists("A")); + object.SetSettingFromString("A", L"ValueB", false); + TS_ASSERT_EQUALS(*settingB, "ValueB"); + } +};