From 27218a9a515b676aaa59091c01d71b59d3a05dce Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 2 Jan 2025 07:56:52 -0500 Subject: [PATCH 1/3] Added methods and member variables to ToolTip to permit manual sizing of tool tips. --- libControls/ToolTip.cpp | 19 +++++++++++++++++++ libControls/ToolTip.h | 10 ++++++++++ 2 files changed, 29 insertions(+) diff --git a/libControls/ToolTip.cpp b/libControls/ToolTip.cpp index 3f91915fd..f290ba5cc 100644 --- a/libControls/ToolTip.cpp +++ b/libControls/ToolTip.cpp @@ -138,3 +138,22 @@ void ToolTip::draw() const }); } } + + +void ToolTip::commandSize(int width, int height) +{ + mCommandedWidth = width; + mCommandedHeight = height; +} + + +void ToolTip::commandWidth(int width) +{ + mCommandedWidth = width; +} + + +void ToolTip::commandHeight(int height) +{ + mCommandedHeight = height; +} diff --git a/libControls/ToolTip.h b/libControls/ToolTip.h index e3618d3ab..8006d91c7 100644 --- a/libControls/ToolTip.h +++ b/libControls/ToolTip.h @@ -9,6 +9,7 @@ #include #include +#include class ToolTip : public Control @@ -22,6 +23,10 @@ class ToolTip : public Control void update() override; void draw() const override; + void commandSize(int width, int height); + void commandWidth(int width); + void commandHeight(int height); + private: void onMouseMove(NAS2D::Point position, NAS2D::Vector relative); @@ -34,4 +39,9 @@ class ToolTip : public Control std::pair* mFocusedControl{nullptr}; std::vector> mControls; + + std::optional mCommandedHeight{std::nullopt}; + std::optional mCommandedWidth{std::nullopt}; + + bool mTruncated{false}; }; From 7877185e36d7bfe06270e05100b7ec0baa0f5e65 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 3 Jan 2025 10:27:35 -0500 Subject: [PATCH 2/3] Added wrapIndexesBreakOnSpace wrapIndexesBreakOnSpace that can be used to create wrapped text from a given string. --- libControls/ToolTip.cpp | 91 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/libControls/ToolTip.cpp b/libControls/ToolTip.cpp index f290ba5cc..e48fa1b11 100644 --- a/libControls/ToolTip.cpp +++ b/libControls/ToolTip.cpp @@ -32,6 +32,93 @@ namespace }); return maxWidthStringSize; } + + + // Returns a vector of pairs and . + // Wraps occur at the last available space before the text width is exceeded. + std::vector> wrapIndexesBreakOnSpace (const std::string& text, const NAS2D::Font& font, int textWidth) + { + std::vector> wrapIndexes; + size_t wrapIndexOffset = 0; + size_t lastSpaceIndex = 0; + const int truncationSize = font.size("...").x; + + for (size_t index = 0; index < text.size(); ++index) + { + if (text[index] == '\n') + { + wrapIndexOffset = index + 1; + } + + if (text[index] == ' ') + { + lastSpaceIndex = index; + } + + if (font.size(text.substr(wrapIndexOffset, index - wrapIndexOffset + 1)).x + truncationSize > textWidth && lastSpaceIndex <= wrapIndexOffset) + { + wrapIndexes.push_back({index - 1, true}); + + // Fast forward the index to the next space + while (index < text.size() && text[index] != ' ') + { + ++index; + } + + if (index < text.size()) + { + wrapIndexOffset = index + 1; + lastSpaceIndex = index; + } + } + + if (font.size(text.substr(wrapIndexOffset, index - wrapIndexOffset + 1)).x > textWidth && lastSpaceIndex > wrapIndexOffset) + { + // Rewind index to the last space + index = lastSpaceIndex; + wrapIndexOffset = index + 1; + wrapIndexes.push_back({lastSpaceIndex, false}); + } + } + + return wrapIndexes; + }; + + + // Returns a constructed string with line breaks at the last available space before the text width is exceeded. + // Lines truncated will attempt to fit and end in "..." but may spill beyond the designated width + std::string wrapTextBreakOnSpace(const std::string& text, const NAS2D::Font& font, int textWidth) + { + auto wrapIndexes = wrapIndexesBreakOnSpace(text, font, textWidth); + std::string wrappedText; + size_t wrapIndexOffset = 0; + for (const auto& [wrapIndex, truncated] : wrapIndexes) + { + wrappedText += text.substr(wrapIndexOffset, wrapIndex - wrapIndexOffset); + if (truncated) + { + wrappedText += "..."; + wrapIndexOffset = wrapIndex; + while (wrapIndexOffset < text.size() && text[wrapIndexOffset] != ' ') + { + ++wrapIndexOffset; + } + + if (wrapIndexOffset < text.size()) + { + wrappedText += '\n'; + wrapIndexOffset++; + } + } + else + { + wrappedText += '\n'; + wrapIndexOffset = wrapIndex + 1; + } + } + wrappedText += text.substr(wrapIndexOffset); + return wrappedText; + }; } @@ -133,8 +220,8 @@ void ToolTip::draw() const auto linePosition = position() + PaddingSize; forEachLine(mFocusedControl->second, [this, &renderer, &linePosition](const std::string& lineStr) { - renderer.drawText(mFont, lineStr, linePosition); - linePosition.y += mFont.height(); + renderer.drawText(mFont, lineStr, linePosition); + linePosition.y += mFont.height(); }); } } From 85f73d190c0b23ff19fb72e5b97b437c0d3bffc8 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 3 Jan 2025 10:29:25 -0500 Subject: [PATCH 3/3] Added unordered_map mWrappedText to cache the string representing the wrapped text --- libControls/ToolTip.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libControls/ToolTip.h b/libControls/ToolTip.h index 8006d91c7..507ece33a 100644 --- a/libControls/ToolTip.h +++ b/libControls/ToolTip.h @@ -10,6 +10,7 @@ #include #include #include +#include class ToolTip : public Control @@ -40,6 +41,8 @@ class ToolTip : public Control std::vector> mControls; + std::unordered_map mWrappedText; + std::optional mCommandedHeight{std::nullopt}; std::optional mCommandedWidth{std::nullopt};