aboutsummaryrefslogtreecommitdiff
path: root/demos/InputMethod
diff options
context:
space:
mode:
Diffstat (limited to 'demos/InputMethod')
-rw-r--r--demos/InputMethod/main.cpp122
1 files changed, 49 insertions, 73 deletions
diff --git a/demos/InputMethod/main.cpp b/demos/InputMethod/main.cpp
index 430075f4..6c0fba3c 100644
--- a/demos/InputMethod/main.cpp
+++ b/demos/InputMethod/main.cpp
@@ -1,5 +1,6 @@
#include "cru/platform/Color.h"
#include "cru/platform/GraphicsBase.h"
+#include "cru/platform/Matrix.h"
#include "cru/platform/bootstrap/Bootstrap.h"
#include "cru/platform/graphics/Factory.h"
#include "cru/platform/graphics/Font.h"
@@ -8,19 +9,11 @@
#include "cru/platform/gui/UiApplication.h"
#include "cru/platform/gui/Window.h"
-#include <optional>
-
using namespace cru;
using namespace cru::platform;
using namespace cru::platform::graphics;
using namespace cru::platform::gui;
-struct InputMethodState {
- CompositionText composition_text;
- Rect cursor_rect;
- TextRange colored_text_range;
-};
-
int main() {
IUiApplication* application = bootstrap::CreateUiApplication();
application->SetQuitOnAllWindowClosed(true);
@@ -49,61 +42,51 @@ int main() {
u"Ctrl+2: Disable IME\n"
u"Ctrl+3: Complete composition.\n"
u"Ctrl+4: Cancel composition.");
- float anchor_y;
-
String committed_text;
auto text_layout = graphics_factory->CreateTextLayout(font, u"");
- std::optional<InputMethodState> state;
+ CompositionText composition_text;
- auto update_text_layout_width = [&prompt_text_layout, &anchor_y,
- &text_layout](float width) {
- prompt_text_layout->SetMaxWidth(width);
- text_layout->SetMaxWidth(width);
- anchor_y = prompt_text_layout->GetTextBounds().height;
+ auto update_text_layout_width = [&prompt_text_layout,
+ &text_layout](const Size& size) {
+ prompt_text_layout->SetMaxWidth(size.width);
+ text_layout->SetMaxWidth(size.width);
};
- update_text_layout_width(window->GetClientSize().width);
-
- window->ResizeEvent()->AddHandler(
- [&update_text_layout_width](const Size& size) {
- update_text_layout_width(size.width);
- });
+ update_text_layout_width(window->GetClientSize());
+ window->ResizeEvent()->AddHandler(update_text_layout_width);
- window->PaintEvent()->AddHandler([&](auto) {
+ window->PaintEvent()->AddSpyOnlyHandler([&]() {
auto painter = window->BeginPaint();
painter->Clear(colors::white);
painter->DrawText(Point{}, prompt_text_layout.get(), brush.get());
-
- if (state) {
- const auto& composition_text = state->composition_text;
-
- for (int i = 0; i < static_cast<int>(composition_text.clauses.size());
- i++) {
- const auto& clause = composition_text.clauses[i];
- auto rects = text_layout->TextRangeRect(TextRange::FromTwoSides(
- clause.start, clause.end, committed_text.size()));
- const auto& b = clause.target
- ? target_clause_brush
- : (i % 2 ? odd_clause_brush : even_clause_brush);
- for (auto& rect : rects) {
- rect.top += anchor_y;
- painter->FillRectangle(rect, b.get());
- }
+ painter->PushState();
+ painter->ConcatTransform(
+ Matrix::Translation(0, prompt_text_layout->GetTextBounds().height));
+
+ for (int i = 0; i < static_cast<int>(composition_text.clauses.size());
+ i++) {
+ const auto& clause = composition_text.clauses[i];
+ auto rects = text_layout->TextRangeRect(TextRange::FromTwoSides(
+ clause.start, clause.end, committed_text.size()));
+ const auto& b = clause.target
+ ? target_clause_brush
+ : (i % 2 ? odd_clause_brush : even_clause_brush);
+ for (auto& rect : rects) {
+ painter->FillRectangle(rect, b.get());
}
}
- painter->DrawText(Point{0, anchor_y}, text_layout.get(), brush.get());
-
- if (state) {
- const auto& composition_text = state->composition_text;
- const auto& cursor_rect = state->cursor_rect;
+ painter->DrawText(Point{}, text_layout.get(), brush.get());
- painter->FillRectangle(Rect{cursor_rect.left, cursor_rect.top + anchor_y,
- 3, cursor_rect.height},
- brush.get());
- }
+ const auto cursor_pos = composition_text.selection.position +
+ static_cast<int>(committed_text.size());
+ auto cursor_rect = text_layout->TextSinglePoint(cursor_pos, false);
+ painter->FillRectangle(
+ Rect{cursor_rect.left, cursor_rect.top, 3, cursor_rect.height},
+ brush.get());
+ painter->PopState();
painter->EndDraw();
});
@@ -129,38 +112,31 @@ int main() {
}
});
- input_method_context->TextEvent()->AddHandler(
- [window, &committed_text](const StringView& c) {
- committed_text += c;
- window->RequestRepaint();
- });
-
- input_method_context->CompositionEvent()->AddHandler([window,
- &input_method_context,
- &committed_text,
- &anchor_y, &state,
- &text_layout](auto) {
- const auto composition_text = input_method_context->GetCompositionText();
- state.emplace();
- state->composition_text = input_method_context->GetCompositionText();
-
+ auto update_state = [&] {
text_layout->SetText(committed_text + composition_text.text);
-
+ auto y = prompt_text_layout->GetTextBounds().height;
const auto cursor_pos = composition_text.selection.position +
static_cast<int>(committed_text.size());
- state->cursor_rect = text_layout->TextSinglePoint(cursor_pos, false);
-
+ auto cursor_rect = text_layout->TextSinglePoint(cursor_pos, false);
input_method_context->SetCandidateWindowPosition(
- {state->cursor_rect.left, anchor_y + state->cursor_rect.GetBottom()});
-
+ {cursor_rect.left, cursor_rect.GetBottom()});
window->RequestRepaint();
+ };
+
+ input_method_context->TextEvent()->AddHandler([&](const StringView& c) {
+ committed_text += c;
+ update_state();
});
- input_method_context->CompositionEndEvent()->AddHandler(
- [window, &state](auto) {
- state = std::nullopt;
- window->RequestRepaint();
- });
+ input_method_context->CompositionEvent()->AddHandler([&](auto) {
+ composition_text = input_method_context->GetCompositionText();
+ update_state();
+ });
+
+ input_method_context->CompositionEndEvent()->AddHandler([&](auto) {
+ composition_text = {};
+ update_state();
+ });
window->SetVisibility(WindowVisibilityType::Show);