Update stk edit box to be more i18n friendly
This commit is contained in:
parent
acb9054dcb
commit
89e3bcd11b
@ -294,6 +294,7 @@ when the border that intersect at this corner are enabled.
|
||||
<color type="text_field" state="background" a="255" r="35" g="35" b="35" />
|
||||
<color type="text_field" state="background_focused" a="255" r="15" g="15" b="15" />
|
||||
<color type="text_field" state="background_deactivated" a="255" r="90" g="90" b="90" />
|
||||
<color type="text_field" state="background_marked" a="128" r="220" g="220" b="220" />
|
||||
<color type="text_field" state="neutral" a="255" r="35" g="35" b="35" />
|
||||
<color type="text_field" state="focused" a="255" r="15" g="15" b="15" />
|
||||
<color type="text_field" state="deactivated" a="255" r="90" g="90" b="90" />
|
||||
|
@ -294,6 +294,7 @@ when the border that intersect at this corner are enabled.
|
||||
<color type="text_field" state="background" a="255" r="200" g="200" b="200" />
|
||||
<color type="text_field" state="background_focused" a="255" r="223" g="250" b="245" />
|
||||
<color type="text_field" state="background_deactivated" a="255" r="200" g="200" b="200" />
|
||||
<color type="text_field" state="background_marked" a="128" r="30" g="80" b="40" />
|
||||
<color type="text_field" state="neutral" a="255" r="138" g="138" b="138" />
|
||||
<color type="text_field" state="focused" a="255" r="80" g="240" b="80" />
|
||||
<color type="text_field" state="deactivated" a="255" r="138" g="138" b="138" />
|
||||
|
@ -293,6 +293,7 @@ when the border that intersect at this corner are enabled.
|
||||
<color type="text_field" state="background" a="255" r="200" g="200" b="200" />
|
||||
<color type="text_field" state="background_focused" a="255" r="223" g="238" b="248" />
|
||||
<color type="text_field" state="background_deactivated" a="255" r="200" g="200" b="200" />
|
||||
<color type="text_field" state="background_marked" a="128" r="40" g="80" b="100" />
|
||||
<color type="text_field" state="neutral" a="255" r="138" g="138" b="138" />
|
||||
<color type="text_field" state="focused" a="255" r="42" g="169" b="211" />
|
||||
<color type="text_field" state="deactivated" a="255" r="138" g="138" b="138" />
|
||||
|
@ -291,6 +291,7 @@ when the border that intersect at this corner are enabled.
|
||||
<color type="text_field" state="background" a="255" r="200" g="200" b="200" />
|
||||
<color type="text_field" state="background_focused" a="255" r="236" g="226" b="201" />
|
||||
<color type="text_field" state="background_deactivated" a="255" r="200" g="200" b="200" />
|
||||
<color type="text_field" state="background_marked" a="128" r="90" g="55" b="25" />
|
||||
<color type="text_field" state="neutral" a="255" r="138" g="138" b="138" />
|
||||
<color type="text_field" state="focused" a="255" r="243" g="164" b="80" />
|
||||
<color type="text_field" state="deactivated" a="255" r="138" g="138" b="138" />
|
||||
|
@ -292,6 +292,7 @@ when the border that intersect at this corner are enabled.
|
||||
<color type="text_field" state="background" a="255" r="200" g="200" b="200" />
|
||||
<color type="text_field" state="background_focused" a="255" r="245" g="220" b="235" />
|
||||
<color type="text_field" state="background_deactivated" a="255" r="200" g="200" b="200" />
|
||||
<color type="text_field" state="background_marked" a="128" r="80" g="40" b="40" />
|
||||
<color type="text_field" state="neutral" a="255" r="138" g="138" b="138" />
|
||||
<color type="text_field" state="focused" a="255" r="240" g="80" b="110" />
|
||||
<color type="text_field" state="deactivated" a="255" r="138" g="138" b="138" />
|
||||
|
@ -26,6 +26,13 @@ GLF_QUICK_DRAW = 8, /* This glyph is not created by libraqm, which get x_advance
|
||||
GLF_NEWLINE = 16 /* This glyph will start a newline. */
|
||||
};
|
||||
|
||||
enum GlyphLayoutDraw
|
||||
{
|
||||
GLD_NONE = 0, /* Default flag. */
|
||||
GLD_MARKED = 1, /* This glyph will be drawn with background marked for marked text. */
|
||||
GLD_COMPOSING = 2 /* This glyph will be drawn with underline (for example composing text). */
|
||||
};
|
||||
|
||||
//! GlyphLayout copied from libraqm.
|
||||
struct GlyphLayout
|
||||
{
|
||||
@ -37,6 +44,7 @@ s32 y_offset;
|
||||
/* Above variable is same for raqm_glyph_t */
|
||||
// If some characters share the same glyph
|
||||
std::vector<s32> cluster;
|
||||
std::vector<u8> draw_flags;
|
||||
//! used to sorting back the visual order after line breaking
|
||||
u32 original_index;
|
||||
u16 flags;
|
||||
|
@ -437,6 +437,8 @@ void FontManager::shape(const std::u32string& text,
|
||||
extra_cluster <= next_cluster - 1; extra_cluster++)
|
||||
cur_line[l].cluster.push_back(extra_cluster);
|
||||
}
|
||||
cur_line[l].draw_flags.resize(cur_line[l].cluster.size(),
|
||||
gui::GLD_NONE);
|
||||
}
|
||||
// Sort glyphs in visual order
|
||||
std::sort(cur_line.begin(), cur_line.end(), []
|
||||
|
@ -574,6 +574,8 @@ void FontWithFace::render(const std::vector<gui::GlyphLayout>& gl,
|
||||
core::array<s32> indices(text_size);
|
||||
core::array<core::position2d<float>> offsets(text_size);
|
||||
std::vector<bool> fallback(text_size);
|
||||
core::array<core::position2d<float>> gld_offsets;
|
||||
gui::GlyphLayoutDraw df_used = gui::GLD_NONE;
|
||||
|
||||
// Check if the line is RTL
|
||||
bool rtl = (gl[0].flags & gui::GLF_RTL_LINE) != 0;
|
||||
@ -596,7 +598,7 @@ void FontWithFace::render(const std::vector<gui::GlyphLayout>& gl,
|
||||
if (line_changed)
|
||||
{
|
||||
line_changed = false;
|
||||
rtl = (gl[i].flags & gui::GLF_RTL_LINE) != 0;
|
||||
rtl = (glyph_layout.flags & gui::GLF_RTL_LINE) != 0;
|
||||
offset.X = float(position.UpperLeftCorner.X);
|
||||
if (hcenter)
|
||||
{
|
||||
@ -680,8 +682,32 @@ void FontWithFace::render(const std::vector<gui::GlyphLayout>& gl,
|
||||
}
|
||||
else
|
||||
{
|
||||
offset.X +=
|
||||
(int)(glyph_layout.x_advance * m_inverse_shaping) * scale;
|
||||
int width = (int)(glyph_layout.x_advance * m_inverse_shaping);
|
||||
if (char_collector == NULL)
|
||||
{
|
||||
float each_size = width * scale /
|
||||
(float)glyph_layout.cluster.size();
|
||||
float start = offset.X;
|
||||
for (unsigned df = 0; df < glyph_layout.draw_flags.size();
|
||||
df++)
|
||||
{
|
||||
if (glyph_layout.draw_flags[df] != gui::GLD_NONE)
|
||||
{
|
||||
if (df_used == gui::GLD_NONE)
|
||||
{
|
||||
if (glyph_layout.draw_flags[df] & gui::GLD_MARKED)
|
||||
df_used = gui::GLD_MARKED;
|
||||
else if (glyph_layout.draw_flags[df] &
|
||||
gui::GLD_COMPOSING)
|
||||
df_used = gui::GLD_COMPOSING;
|
||||
}
|
||||
gld_offsets.push_back({start, offset.Y});
|
||||
gld_offsets.push_back({start + each_size, offset.Y});
|
||||
}
|
||||
start += each_size;
|
||||
}
|
||||
}
|
||||
offset.X += width * scale;
|
||||
}
|
||||
} // for i < text_size
|
||||
|
||||
@ -825,6 +851,27 @@ void FontWithFace::render(const std::vector<gui::GlyphLayout>& gl,
|
||||
}
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < gld_offsets.size(); i += 2)
|
||||
{
|
||||
if (df_used == gui::GLD_MARKED)
|
||||
{
|
||||
core::rect<s32> gld((s32)gld_offsets[i].X, (s32)gld_offsets[i].Y,
|
||||
(s32)gld_offsets[i + 1].X,
|
||||
(s32)(gld_offsets[i + 1].Y + m_font_max_height * scale));
|
||||
GL32_draw2DRectangle(GUIEngine::getSkin()->getColor(
|
||||
"text_field::background_marked"), gld, clip);
|
||||
}
|
||||
else if (df_used == gui::GLD_COMPOSING)
|
||||
{
|
||||
float line1 = m_font_max_height * scale * 0.88f;
|
||||
float line2 = m_font_max_height * scale * 0.92f;
|
||||
core::rect<s32> gld((s32)gld_offsets[i].X, (s32)gld_offsets[i].Y + line1,
|
||||
(s32)gld_offsets[i + 1].X,
|
||||
(s32)(gld_offsets[i + 1].Y + line2));
|
||||
GL32_draw2DRectangle(GUIEngine::getSkin()->getColor(
|
||||
"text::neutral"), gld, clip);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // render
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -11,10 +11,14 @@
|
||||
#include "IOSOperator.h"
|
||||
#include "utils/leak_check.hpp"
|
||||
|
||||
#include "utils/time.hpp"
|
||||
#include "GlyphLayout.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace irr;
|
||||
using namespace gui;
|
||||
|
||||
namespace GUIEngine
|
||||
{
|
||||
enum TextBoxType: int;
|
||||
@ -28,7 +32,7 @@ namespace GUIEngine
|
||||
|
||||
//! constructor
|
||||
CGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment,
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle, bool is_rtl);
|
||||
IGUIElement* parent, s32 id, const core::rect<s32>& rectangle);
|
||||
|
||||
//! destructor
|
||||
virtual ~CGUIEditBox();
|
||||
@ -54,20 +58,20 @@ namespace GUIEngine
|
||||
virtual void setDrawBorder(bool border);
|
||||
|
||||
//! Enables or disables word wrap for using the edit box as multiline text editor.
|
||||
virtual void setWordWrap(bool enable);
|
||||
virtual void setWordWrap(bool enable) {}
|
||||
|
||||
//! Checks if word wrap is enabled
|
||||
//! \return true if word wrap is enabled, false otherwise
|
||||
virtual bool isWordWrapEnabled() const;
|
||||
virtual bool isWordWrapEnabled() const { return false; }
|
||||
|
||||
//! Enables or disables newlines.
|
||||
/** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired,
|
||||
instead a newline character will be inserted. */
|
||||
virtual void setMultiLine(bool enable);
|
||||
virtual void setMultiLine(bool enable) {}
|
||||
|
||||
//! Checks if multi line editing is enabled
|
||||
//! \return true if mult-line is enabled, false otherwise
|
||||
virtual bool isMultiLineEnabled() const;
|
||||
virtual bool isMultiLineEnabled() const { return false; }
|
||||
|
||||
//! Enables or disables automatic scrolling with cursor position
|
||||
//! \param enable: If set to true, the text will move around with the cursor position
|
||||
@ -123,19 +127,15 @@ namespace GUIEngine
|
||||
virtual irr::gui::IGUIFont* getActiveFont() const { return NULL; }
|
||||
virtual void setDrawBackground(bool) { }
|
||||
|
||||
void fromAndroidEditText(const core::stringw& text, int start, int end,
|
||||
void fromAndroidEditText(const std::u32string& text, int start, int end,
|
||||
int composing_start, int composing_end);
|
||||
void openScreenKeyboard();
|
||||
s32 getCursorPosInBox() const { return CursorPos; }
|
||||
s32 getTextCount() const { return (s32)Text.size(); }
|
||||
s32 getCursorPosInBox() const { return m_cursor_pos; }
|
||||
s32 getTextCount() const { return (s32)m_edit_text.size(); }
|
||||
void setTextBoxType(GUIEngine::TextBoxType t) { m_type = t; }
|
||||
protected:
|
||||
//! Breaks the single text line.
|
||||
void breakText();
|
||||
//! sets the area of the given line
|
||||
void setTextRect(s32 line);
|
||||
//! returns the line number that the cursor is on
|
||||
s32 getLineFromPos(s32 pos);
|
||||
//! adds a letter to the edit box
|
||||
void inputChar(wchar_t c);
|
||||
//! calculates the current scroll position
|
||||
@ -144,7 +144,7 @@ namespace GUIEngine
|
||||
void sendGuiEvent(EGUI_EVENT_TYPE type);
|
||||
//! set text markers
|
||||
void setTextMarkers(s32 begin, s32 end);
|
||||
|
||||
void updateCursorDistance();
|
||||
bool processKey(const SEvent& event);
|
||||
bool processMouse(const SEvent& event);
|
||||
#if defined(_IRR_COMPILE_WITH_WINDOWS_DEVICE_)
|
||||
@ -155,12 +155,13 @@ namespace GUIEngine
|
||||
core::position2di calculateICPos();
|
||||
#endif
|
||||
s32 getCursorPos(s32 x, s32 y);
|
||||
void updateGlyphLayouts();
|
||||
|
||||
bool MouseMarking;
|
||||
bool Border;
|
||||
bool OverrideColorEnabled;
|
||||
s32 MarkBegin;
|
||||
s32 MarkEnd;
|
||||
s32 m_mark_begin;
|
||||
s32 m_mark_end;
|
||||
|
||||
GUIEngine::TextBoxType m_type;
|
||||
|
||||
@ -168,20 +169,16 @@ namespace GUIEngine
|
||||
gui::IGUIFont *OverrideFont, *LastBreakFont;
|
||||
IOSOperator* Operator;
|
||||
|
||||
StkTime::TimeType BlinkStartTime;
|
||||
s32 CursorPos;
|
||||
s32 HScrollPos, VScrollPos; // scroll position in characters
|
||||
u32 Max;
|
||||
uint64_t m_force_show_cursor_time;
|
||||
s32 m_cursor_pos;
|
||||
s32 m_scroll_pos;
|
||||
s32 m_cursor_distance;
|
||||
u32 m_max_chars;
|
||||
|
||||
bool m_rtl;
|
||||
|
||||
bool WordWrap, MultiLine, AutoScroll, PasswordBox;
|
||||
wchar_t PasswordChar;
|
||||
bool AutoScroll, PasswordBox;
|
||||
char32_t PasswordChar;
|
||||
EGUI_ALIGNMENT HAlign, VAlign;
|
||||
|
||||
core::array< core::stringw > BrokenText;
|
||||
core::array< s32 > BrokenTextPositions;
|
||||
|
||||
core::rect<s32> CurrentTextRect, FrameRect; // temporary values
|
||||
|
||||
s32 m_composing_start;
|
||||
@ -190,6 +187,12 @@ namespace GUIEngine
|
||||
/* If true, this editbox will copy text and selection only from
|
||||
* android edittext, and process only mouse event. */
|
||||
bool m_from_android_edittext;
|
||||
|
||||
/* UTF32 string for shaping and editing to avoid wchar_t issue in
|
||||
* windows */
|
||||
std::u32string m_edit_text;
|
||||
std::vector<GlyphLayout> m_glyph_layouts;
|
||||
void correctCursor(s32& cursor_pos, bool left);
|
||||
};
|
||||
|
||||
|
||||
|
@ -22,7 +22,6 @@
|
||||
#include "guiengine/widgets/CGUIEditBox.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
#include "utils/utf8/unchecked.h"
|
||||
|
||||
#include <IGUIElement.h>
|
||||
#include <IGUIEnvironment.h>
|
||||
@ -39,9 +38,8 @@ public:
|
||||
|
||||
MyCGUIEditBox(const wchar_t* text, bool border, gui::IGUIEnvironment* environment,
|
||||
gui:: IGUIElement* parent, s32 id, const core::rect<s32>& rectangle) :
|
||||
CGUIEditBox(text, border, environment, parent, id, rectangle, translations->isRTLLanguage())
|
||||
CGUIEditBox(text, border, environment, parent, id, rectangle)
|
||||
{
|
||||
if (translations->isRTLLanguage()) setTextAlignment(irr::gui::EGUIA_LOWERRIGHT, irr::gui::EGUIA_CENTER);
|
||||
}
|
||||
|
||||
void addListener(GUIEngine::ITextBoxWidgetListener* listener)
|
||||
@ -68,8 +66,7 @@ public:
|
||||
if (m_listeners[n].onEnterPressed(Text))
|
||||
{
|
||||
handled = true;
|
||||
Text = L"";
|
||||
CursorPos = MarkBegin = MarkEnd = 0;
|
||||
setText(L"");
|
||||
}
|
||||
}
|
||||
return handled;
|
||||
@ -271,14 +268,8 @@ ANDROID_EDITTEXT_CALLBACK(ANDROID_PACKAGE_CALLBACK_NAME)
|
||||
if (utf8_text == NULL)
|
||||
return;
|
||||
|
||||
// Use utf32 for emoji later
|
||||
static_assert(sizeof(wchar_t) == sizeof(uint32_t), "Invalid wchar size");
|
||||
std::vector<wchar_t> utf32line;
|
||||
utf8::unchecked::utf8to32(utf8_text, utf8_text + strlen(utf8_text),
|
||||
back_inserter(utf32line));
|
||||
utf32line.push_back(0);
|
||||
|
||||
core::stringw to_editbox(&utf32line[0]);
|
||||
// Android use 32bit wchar_t
|
||||
std::u32string to_editbox = StringUtils::utf8ToUtf32(utf8_text);
|
||||
env->ReleaseStringUTFChars(text, utf8_text);
|
||||
|
||||
GUIEngine::addGUIFunctionBeforeRendering([widget_id, to_editbox, start,
|
||||
|
Loading…
Reference in New Issue
Block a user