From 148285ad01ca5b83476a6433d10bf5db6308093c Mon Sep 17 00:00:00 2001 From: VDm Date: Thu, 7 Aug 2025 19:28:25 +0400 Subject: [PATCH] feat(ui): add CSimpleHyperlinkButton class --- src/ui/CSimpleHyperlinkButton.cpp | 49 +++++++++++++++++++++++++ src/ui/CSimpleHyperlinkButton.hpp | 24 +++++++++++++ src/ui/CSimpleHyperlinkedFrame.cpp | 54 ++++++++++++++++++++++++++++ src/ui/CSimpleHyperlinkedFrame.hpp | 10 ++++++ src/ui/CSimpleMessageScrollFrame.cpp | 4 +++ src/ui/CSimpleMessageScrollFrame.hpp | 12 +++++++ src/ui/FrameXML.cpp | 4 ++- src/ui/Types.hpp | 8 +++++ 8 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 src/ui/CSimpleHyperlinkButton.cpp create mode 100644 src/ui/CSimpleHyperlinkButton.hpp create mode 100644 src/ui/CSimpleMessageScrollFrame.cpp create mode 100644 src/ui/CSimpleMessageScrollFrame.hpp diff --git a/src/ui/CSimpleHyperlinkButton.cpp b/src/ui/CSimpleHyperlinkButton.cpp new file mode 100644 index 0000000..a4b9fc0 --- /dev/null +++ b/src/ui/CSimpleHyperlinkButton.cpp @@ -0,0 +1,49 @@ +#include "ui/CSimpleHyperlinkButton.hpp" +#include "ui/CSimpleHyperlinkedFrame.hpp" +#include "ui/CSimpleFontString.hpp" +#include "gx/Coordinate.hpp" +#include + + +CSimpleHyperlinkButton::CSimpleHyperlinkButton(CSimpleHyperlinkedFrame* parent) + : CSimpleButton(parent) { +} + +void CSimpleHyperlinkButton::SetHyperlink(CSimpleFontString* string, const GXUFONTHYPERLINKINFO* hyperlink) { + if (!string || !hyperlink) { + this->Hide(); + return; + } + + this->m_hyperlink = static_cast(SMemReAlloc(this->m_hyperlink, hyperlink->linkLength + 1, __FILE__, __LINE__, 0)); + SStrCopy(this->m_hyperlink, hyperlink->link, hyperlink->linkLength + 1); + + CRect extent; + NDCToDDC(hyperlink->extent.minX, hyperlink->extent.minY, &extent.minX, &extent.minY); + NDCToDDC(hyperlink->extent.maxX, hyperlink->extent.maxY, &extent.maxX, &extent.maxY); + + // TODO: switch() + + this->ClearAllPoints(); + this->SetPoint( + FRAMEPOINT_TOPLEFT, + string, + FRAMEPOINT_TOPLEFT, + extent.minX / this->m_layoutScale, + extent.minY / this->m_layoutScale, + 1); + + float width = (extent.maxX - extent.minX) / this->m_layoutScale; + float height = (extent.maxY - extent.minY) / this->m_layoutScale; + this->SetSize(width, height); + this->Show(); +} + +void CSimpleHyperlinkButton::OnLayerCursorEnter(int32_t a2) { +} + +void CSimpleHyperlinkButton::OnLayerCursorExit(int32_t a2, int32_t a3) { +} + +void CSimpleHyperlinkButton::OnClick(const char* btn, int32_t a3) { +} diff --git a/src/ui/CSimpleHyperlinkButton.hpp b/src/ui/CSimpleHyperlinkButton.hpp new file mode 100644 index 0000000..590d24a --- /dev/null +++ b/src/ui/CSimpleHyperlinkButton.hpp @@ -0,0 +1,24 @@ +#ifndef UI_C_SIMPLE_HYPERLINK_BUTTON_HPP +#define UI_C_SIMPLE_HYPERLINK_BUTTON_HPP + +#include "ui/CSimpleButton.hpp" + +class CSimpleHyperlinkedFrame; + +class CSimpleHyperlinkButton : public CSimpleButton { + public: + // Member functions + CSimpleHyperlinkButton(CSimpleHyperlinkedFrame* parent); + void SetHyperlink(CSimpleFontString* string, const GXUFONTHYPERLINKINFO* hyperlink); + + virtual void OnLayerCursorEnter(int32_t a2); + virtual void OnLayerCursorExit(int32_t a2, int32_t a3); + virtual void OnClick(const char* btn, int32_t a3); + + + // Member variables + char* m_hyperlink = nullptr; + TSLink m_link; +}; + +#endif diff --git a/src/ui/CSimpleHyperlinkedFrame.cpp b/src/ui/CSimpleHyperlinkedFrame.cpp index ffc398f..50773b3 100644 --- a/src/ui/CSimpleHyperlinkedFrame.cpp +++ b/src/ui/CSimpleHyperlinkedFrame.cpp @@ -1,5 +1,59 @@ #include "ui/CSimpleHyperlinkedFrame.hpp" +#include "util/Lua.hpp" CSimpleHyperlinkedFrame::CSimpleHyperlinkedFrame(CSimpleFrame* parent) : CSimpleFrame(parent) { // TODO } + +FrameScript_Object::ScriptIx* CSimpleHyperlinkedFrame::GetScriptByName(const char* name, ScriptData& data) { + auto result = this->CSimpleFrame::GetScriptByName(name, data); + if (result) + return result; + + if (!SStrCmpI(name, "OnHyperlinkEnter", STORM_MAX_STR)) { + data.wrapper = "return function(self,link,text) %s end"; + return &this->m_onHyperlinkEnter; + } + + if (!SStrCmpI(name, "OnHyperlinkLeave", STORM_MAX_STR)) { + data.wrapper = "return function(self,link,text) %s end"; + return &this->m_onHyperlinkLeave; + } + + if (!SStrCmpI(name, "OnHyperlinkClick", STORM_MAX_STR)) { + data.wrapper = "return function(self,link,text,button) %s end"; + return &this->m_onHyperlinkClick; + } + + return nullptr; +} + +void CSimpleHyperlinkedFrame::OnHyperlinkClick(const char* a2, const char* a3, const char* a4) { + if (this->m_onHyperlinkClick.luaRef) { + auto L = FrameScript_GetContext(); + lua_pushstring(L, a2); + lua_pushstring(L, a3); + + this->RunScript(this->m_onHyperlinkClick, 2, 0); + } +} + +void CSimpleHyperlinkedFrame::OnHyperlinkLeave(const char* a2, const char* a3) { + if (this->m_onHyperlinkLeave.luaRef) { + auto L = FrameScript_GetContext(); + lua_pushstring(L, a2); + lua_pushstring(L, a3); + + this->RunScript(this->m_onHyperlinkLeave, 2, 0); + } +} + +void CSimpleHyperlinkedFrame::OnHyperlinkEnter(const char* a2, const char* a3) { + if (this->m_onHyperlinkEnter.luaRef) { + auto L = FrameScript_GetContext(); + lua_pushstring(L, a2); + lua_pushstring(L, a3); + + this->RunScript(this->m_onHyperlinkEnter, 2, 0); + } +} diff --git a/src/ui/CSimpleHyperlinkedFrame.hpp b/src/ui/CSimpleHyperlinkedFrame.hpp index 0c8aa10..a1ec502 100644 --- a/src/ui/CSimpleHyperlinkedFrame.hpp +++ b/src/ui/CSimpleHyperlinkedFrame.hpp @@ -7,6 +7,16 @@ class CSimpleHyperlinkedFrame : public CSimpleFrame { public: // Member functions CSimpleHyperlinkedFrame(CSimpleFrame* parent); + virtual ScriptIx* GetScriptByName(const char* name, ScriptData& data); + + void OnHyperlinkClick(const char* a2, const char* a3, const char* a4); + void OnHyperlinkLeave(const char* a2, const char* a3); + void OnHyperlinkEnter(const char* a2, const char* a3); + + // Member variables + ScriptIx m_onHyperlinkEnter; + ScriptIx m_onHyperlinkLeave; + ScriptIx m_onHyperlinkClick; }; #endif diff --git a/src/ui/CSimpleMessageScrollFrame.cpp b/src/ui/CSimpleMessageScrollFrame.cpp new file mode 100644 index 0000000..c8fd290 --- /dev/null +++ b/src/ui/CSimpleMessageScrollFrame.cpp @@ -0,0 +1,4 @@ +#include "ui/CSimpleMessageScrollFrame.hpp" + +CSimpleMessageScrollFrame::CSimpleMessageScrollFrame(CSimpleFrame* parent) : CSimpleHyperlinkedFrame(parent) { +} diff --git a/src/ui/CSimpleMessageScrollFrame.hpp b/src/ui/CSimpleMessageScrollFrame.hpp new file mode 100644 index 0000000..5063fd5 --- /dev/null +++ b/src/ui/CSimpleMessageScrollFrame.hpp @@ -0,0 +1,12 @@ +#ifndef UI_C_SIMPLE_MESSAGE_SCROLL_FRAME_HPP +#define UI_C_SIMPLE_MESSAGE_SCROLL_FRAME_HPP + +#include "ui/CSimpleHyperlinkedFrame.hpp" + +class CSimpleMessageScrollFrame : public CSimpleHyperlinkedFrame { + public: + // Member functions + CSimpleMessageScrollFrame(CSimpleFrame* parent); +}; + +#endif diff --git a/src/ui/FrameXML.cpp b/src/ui/FrameXML.cpp index 668b22c..30b6d54 100644 --- a/src/ui/FrameXML.cpp +++ b/src/ui/FrameXML.cpp @@ -8,6 +8,7 @@ #include "ui/CSimpleModel.hpp" #include "ui/CSimpleMovieFrame.hpp" #include "ui/CSimpleScrollFrame.hpp" +#include "ui/CSimpleMessageScrollFrame.hpp" #include "ui/CSimpleSlider.hpp" #include "util/CStatus.hpp" #include "util/SFile.hpp" @@ -77,7 +78,8 @@ CSimpleFrame* Create_SimpleScrollFrame(CSimpleFrame* parent) { CSimpleFrame* Create_SimpleScrollingMessageFrame(CSimpleFrame* parent) { // TODO - return nullptr; + auto m = SMemAlloc(sizeof(CSimpleMessageScrollFrame), __FILE__, __LINE__, 0x0); + return new (m) CSimpleMessageScrollFrame(parent); } CSimpleFrame* Create_SimpleSlider(CSimpleFrame* parent) { diff --git a/src/ui/Types.hpp b/src/ui/Types.hpp index fe0274e..5b3b3c2 100644 --- a/src/ui/Types.hpp +++ b/src/ui/Types.hpp @@ -2,6 +2,7 @@ #define UI_TYPES_HPP #include +#include struct lua_State; class CSimpleFrame; @@ -103,4 +104,11 @@ struct FrameScript_Method { int32_t (*method)(lua_State*); }; +struct GXUFONTHYPERLINKINFO { + CRect extent; + const char* link; + uint32_t linkLength; +}; + + #endif