Move getCluster code to a dedicated function for later usage
This commit is contained in:
parent
fe5b49e63a
commit
4deeac7dc8
@ -9,6 +9,7 @@
|
||||
#include "SColor.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace irr
|
||||
@ -125,6 +126,7 @@ namespace gui
|
||||
virtual void setUseGlyphLayoutsOnly(bool gls_only) = 0;
|
||||
virtual bool useGlyphLayoutsOnly() const = 0;
|
||||
virtual void setMouseCallback(std::function<bool(IGUIStaticText* text, SEvent::SMouseInput)> cb) {}
|
||||
virtual s32 getCluster(int x, int y, std::shared_ptr<std::u32string>* out_orig_str) { return -1; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -393,6 +393,89 @@ bool CGUIStaticText::OnEvent(const SEvent& event)
|
||||
return IGUIElement::OnEvent(event);
|
||||
}
|
||||
|
||||
|
||||
s32 CGUIStaticText::getCluster(int x, int y, std::shared_ptr<std::u32string>* out_orig_str)
|
||||
{
|
||||
core::position2di p;
|
||||
p.X = x;
|
||||
p.Y = y;
|
||||
if (p.X < 0 || p.Y < 0)
|
||||
return -1;
|
||||
|
||||
if (m_glyph_layouts.empty())
|
||||
return -1;
|
||||
|
||||
IGUIFont* font = getActiveFont();
|
||||
std::vector<f32> width_per_line = gui::getGlyphLayoutsWidthPerLine(
|
||||
m_glyph_layouts, font->getInverseShaping(), font->getScale());
|
||||
if (width_per_line.empty())
|
||||
return -1;
|
||||
|
||||
// Check if the line is RTL
|
||||
core::rect<s32> position = getAbsolutePosition();
|
||||
bool rtl = (m_glyph_layouts[0].flags & gui::GLF_RTL_LINE) != 0;
|
||||
int offset = 0;
|
||||
int cur_line = 0;
|
||||
if (rtl)
|
||||
offset = (s32)(position.getWidth() - width_per_line[cur_line]);
|
||||
|
||||
float next_line_height = font->getHeightPerLine();
|
||||
if (width_per_line.size() > 1 &&
|
||||
width_per_line.size() * next_line_height > position.getHeight())
|
||||
{
|
||||
next_line_height = (float)position.getHeight() /
|
||||
(float)width_per_line.size();
|
||||
}
|
||||
|
||||
int idx = -1;
|
||||
core::recti r;
|
||||
r.UpperLeftCorner.X = r.LowerRightCorner.X = offset;
|
||||
r.LowerRightCorner.Y = (int)next_line_height;
|
||||
bool line_changed = false;
|
||||
for (unsigned i = 0; i < m_glyph_layouts.size(); i++)
|
||||
{
|
||||
const GlyphLayout& glyph_layout = m_glyph_layouts[i];
|
||||
if ((glyph_layout.flags & GLF_NEWLINE) != 0)
|
||||
{
|
||||
r.UpperLeftCorner.Y += (int)next_line_height;
|
||||
r.LowerRightCorner.Y += (int)next_line_height;
|
||||
cur_line++;
|
||||
line_changed = true;
|
||||
continue;
|
||||
}
|
||||
if (line_changed)
|
||||
{
|
||||
line_changed = false;
|
||||
rtl = (glyph_layout.flags & gui::GLF_RTL_LINE) != 0;
|
||||
offset = 0;
|
||||
if (rtl)
|
||||
{
|
||||
offset = (s32)
|
||||
(position.getWidth() - width_per_line[cur_line]);
|
||||
}
|
||||
r.UpperLeftCorner.X = r.LowerRightCorner.X = offset;
|
||||
}
|
||||
r.LowerRightCorner.X += int(
|
||||
(float)glyph_layout.x_advance * font->getInverseShaping() *
|
||||
font->getScale());
|
||||
if (r.isPointInside(p))
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == -1)
|
||||
return -1;
|
||||
|
||||
std::shared_ptr<std::u32string> s = m_glyph_layouts[idx].orig_string;
|
||||
unsigned cluster = m_glyph_layouts[idx].cluster.front();
|
||||
if (cluster > s->size())
|
||||
return -1;
|
||||
*out_orig_str = s;
|
||||
return cluster;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace gui
|
||||
} // end namespace irr
|
||||
|
||||
|
@ -113,6 +113,7 @@ namespace gui
|
||||
//! called if an event happened.
|
||||
virtual bool OnEvent(const SEvent& event);
|
||||
virtual void setMouseCallback(std::function<bool(IGUIStaticText* text, SEvent::SMouseInput)> cb) { m_callback = cb; }
|
||||
virtual s32 getCluster(int x, int y, std::shared_ptr<std::u32string>* out_orig_str);
|
||||
private:
|
||||
|
||||
//! Breaks the single text line.
|
||||
|
@ -264,81 +264,11 @@ void NetworkingLobby::init()
|
||||
{
|
||||
if (mouse.Event == EMIE_LMOUSE_PRESSED_DOWN)
|
||||
{
|
||||
core::position2di p;
|
||||
p.X = mouse.X - text->getAbsolutePosition().UpperLeftCorner.X;
|
||||
p.Y = mouse.Y - text->getAbsolutePosition().UpperLeftCorner.Y;
|
||||
if (p.X < 0 || p.Y < 0)
|
||||
return false;
|
||||
|
||||
const std::vector<GlyphLayout>& gls = text->getGlyphLayouts();
|
||||
if (gls.empty())
|
||||
return false;
|
||||
|
||||
gui::IGUIFont* font = GUIEngine::getFont();
|
||||
auto width_per_line = gui::getGlyphLayoutsWidthPerLine(gls,
|
||||
font->getInverseShaping(), font->getScale());
|
||||
if (width_per_line.empty())
|
||||
return false;
|
||||
|
||||
// Check if the line is RTL
|
||||
auto position = text->getAbsolutePosition();
|
||||
bool rtl = (gls[0].flags & gui::GLF_RTL_LINE) != 0;
|
||||
int offset = 0;
|
||||
int cur_line = 0;
|
||||
if (rtl)
|
||||
offset = (s32)(position.getWidth() - width_per_line[cur_line]);
|
||||
|
||||
float next_line_height = font->getHeightPerLine();
|
||||
if (width_per_line.size() > 1 &&
|
||||
width_per_line.size() * next_line_height > position.getHeight())
|
||||
{
|
||||
next_line_height = (float)position.getHeight() /
|
||||
(float)width_per_line.size();
|
||||
}
|
||||
|
||||
int idx = -1;
|
||||
core::recti r;
|
||||
r.UpperLeftCorner.X = r.LowerRightCorner.X = offset;
|
||||
r.LowerRightCorner.Y = (int)next_line_height;
|
||||
bool line_changed = false;
|
||||
for (unsigned i = 0; i < gls.size(); i++)
|
||||
{
|
||||
const GlyphLayout& glyph_layout = gls[i];
|
||||
if ((glyph_layout.flags & GLF_NEWLINE) != 0)
|
||||
{
|
||||
r.UpperLeftCorner.Y += (int)next_line_height;
|
||||
r.LowerRightCorner.Y += (int)next_line_height;
|
||||
cur_line++;
|
||||
line_changed = true;
|
||||
continue;
|
||||
}
|
||||
if (line_changed)
|
||||
{
|
||||
line_changed = false;
|
||||
rtl = (glyph_layout.flags & gui::GLF_RTL_LINE) != 0;
|
||||
offset = 0;
|
||||
if (rtl)
|
||||
{
|
||||
offset = (s32)
|
||||
(position.getWidth() - width_per_line[cur_line]);
|
||||
}
|
||||
r.UpperLeftCorner.X = r.LowerRightCorner.X = offset;
|
||||
}
|
||||
r.LowerRightCorner.X += int(
|
||||
(float)glyph_layout.x_advance * font->getInverseShaping() *
|
||||
font->getScale());
|
||||
if (r.isPointInside(p))
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == -1)
|
||||
return false;
|
||||
|
||||
auto s = gls[idx].orig_string;
|
||||
unsigned cluster = gls[idx].cluster.front();
|
||||
if (cluster > s->size())
|
||||
std::shared_ptr<std::u32string> s;
|
||||
int cluster = text->getCluster(
|
||||
mouse.X - text->getAbsolutePosition().UpperLeftCorner.X,
|
||||
mouse.Y - text->getAbsolutePosition().UpperLeftCorner.Y, &s);
|
||||
if (cluster == -1 || (unsigned)cluster > s->size())
|
||||
return false;
|
||||
|
||||
size_t start = s->substr(0, cluster).rfind(U'\n');
|
||||
@ -351,10 +281,9 @@ void NetworkingLobby::init()
|
||||
end = s->size();
|
||||
else
|
||||
end += cluster - start;
|
||||
if (idx == -1)
|
||||
return false;
|
||||
|
||||
std::u32string substr = s->substr(start, end);
|
||||
int local_pos = (int)cluster - (int)start;
|
||||
int local_pos = cluster - (int)start;
|
||||
if ((size_t)local_pos > substr.size())
|
||||
return false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user