1. Introduction
In the previous article, we implemented some of the basic functionalities of UITextEdit. In this part, we’ll continue by implementing features like IME (Input Method Editor) support, along with copy, paste, and cut functionality.
2. Functional Requirements Analysis
Core Features
- Copy, cut, and paste
- IME support (for Chinese, Japanese, and other languages)
Interaction Details
To handle button events, we’ll check for user input in the bool Handle(SDL_Event*e)
method. If a user presses Ctrl+C
, we’ll store the selected content in the system clipboard. A crucial detail to note here is that after handling a key combination event, we need to prevent the C
key from being processed as regular input. Other key combinations should be handled in a similar way.
For drawing the IME-related window, which is usually on top of other UI elements, we can’t handle it within the normal control drawing logic. Instead, it needs to be drawn at a lower level to ensure it’s rendered at the correct time. For this, we’ll choose to draw it within the SceneManager
.
3. Essential SDL Functions
SDL_StartTextInput
/SDL_StopTextInput
: Enable/disable text input.SDL_TEXTINPUT
: A character input event.SDL_TEXTEDITING
: An input method editing event.SDL_KEYDOWN
: Used to detect key combinations likeCtrl+C
,Ctrl+V
, andCtrl+X
.SDL_SetClipboardText
/SDL_GetClipboardText
: For clipboard operations.
4. Design Considerations
Paste, Copy, and Cut
- Copy: Use
SDL_SetClipboardText
to save the selected text to the clipboard. - Paste: Use
SDL_GetClipboardText
to retrieve text from the clipboard. - Cut: This is a combination of copying the selected text and then deleting it.
IME Support
- To input characters from Eurasian languages like Chinese or Japanese, you need the appropriate font support.
- The
SDL_TEXTEDITING
event provides the temporary input string and cursor position. - You must render this temporary input string at the cursor’s location.
- Use platform-specific APIs to get the list of available IMEs.
- Pay close attention to character encoding settings in different states.
5. Key Code Snippets
In the UITextEdit::Handle
method:
C++
SDL_Keymod modState = SDL_GetModState();
switch (e->key.keysym.sym)
{
case SDLK_c:
{
if (modState & KMOD_CTRL)
{
auto str = GetSelectionText();
SDL_SetClipboardText(str.c_str());
return true;
}
break;
}
case SDLK_v:
{
if (modState & KMOD_CTRL)
{
auto str = SDL_GetClipboardText();
replaceSelectionText(str);
return true;
}
break;
}
case SDLK_x:
{
if (modState & KMOD_CTRL)
{
auto str = GetSelectionText();
SDL_SetClipboardText(str.c_str());
removeSelectedText();
return true;
}
break;
}
For drawing the IME list:
C++
void UITextEdit::DrawImgList()
{
if (IsPassword()) return;
if (m_ims.size() <= 0) return;
SDL_Color bk{ 220,220,220,255 };
SDL_Color clr{ 0,0,0,255 };
SDL_Color csel{ 116,216,255,255 };
int imesize = (int)(IME_SIZE);
auto rc = calcCursorRect(cursor.position);
auto [cw, ch] = sRender->GetClientSize();
auto [w, h] = sRender->GetTextSize(wstring_to_utf8(m_ims[0]).c_str(), m_fontSize);
int x = rc.x;
int y = rc.y + rc.h;
if (y + h * 8 > ch)
{
auto rect = GetGlobalRect();
y = rect.y - (h + 4) * 8;
}
auto rcBK = SDL_Rect{ rc.x,y, 90, (h + 4) * imesize };
sRender->FillRect(rcBK, bk);
for (size_t i = 0; i < imesize; i++)
{
if (i == editing.index)
{
sRender->FillRect(SDL_Rect{ x,y,80, h + 4 }, csel);
}
SDL_Point pt{ x + 4,y + 2 };
char txt[64] = {};
//sprintf_s(txt, "%d. %s", (int)i + 1, wstring_to_utf8(m_ims[i]).c_str());
sRender->DrawString(txt, m_fontSize, pt, clr);
y += (h + 4);
}
}
6. Example Usage
We’ll continue to use the same use case from the previous section.
7. Conclusion
In this article, we’ve enhanced the UITextEdit control by adding copy, paste, cut, and IME-related functionalities. In the next part, we’ll move on to implementing a UICheckBox.
- This chapter’s example code: https://github.com/84378996/simple_sdl_gui_tutorials/tree/main/tutorials04
- This chapter’s demo: