#include "stdafx.h" #include "overlay_edit_text.hpp" namespace rsx { namespace overlays { static usz get_line_start(const std::u32string& text, usz pos) { if (pos == 0) { return 0; } const usz line_start = text.rfind('\n', pos - 1); if (line_start == std::string::npos) { return 0; } return line_start + 1; } static usz get_line_end(const std::u32string& text, usz pos) { const usz line_end = text.find('\n', pos); if (line_end == std::string::npos) { return text.length(); } return line_end; } void edit_text::move_caret(direction dir) { m_reset_caret_pulse = true; switch (dir) { case direction::left: { if (caret_position) { caret_position--; refresh(); } break; } case direction::right: { if (caret_position < value.length()) { caret_position++; refresh(); } break; } case direction::up: { const usz current_line_start = get_line_start(value, caret_position); if (current_line_start == 0) { // This is the first line, so caret moves to the very beginning caret_position = 0; refresh(); break; } const usz caret_pos_in_line = caret_position - current_line_start; const usz prev_line_end = current_line_start - 1; const usz prev_line_start = get_line_start(value, prev_line_end); // TODO : Save caret position to some kind of buffer, so after switching back and forward, caret would be on initial position caret_position = std::min(prev_line_end, prev_line_start + caret_pos_in_line); refresh(); break; } case direction::down: { const usz current_line_end = get_line_end(value, caret_position); if (current_line_end == value.length()) { // This is the last line, so caret moves to the very end caret_position = current_line_end; refresh(); break; } const usz current_line_start = get_line_start(value, caret_position); const usz caret_pos_in_line = caret_position - current_line_start; const usz next_line_start = current_line_end + 1; const usz next_line_end = get_line_end(value, next_line_start); // TODO : Save caret position to some kind of buffer, so after switching back and forward, caret would be on initial position caret_position = std::min(next_line_end, next_line_start + caret_pos_in_line); refresh(); break; } } } void edit_text::set_text(const std::string& text) { set_unicode_text(utf8_to_u32string(text)); } void edit_text::set_unicode_text(const std::u32string& text) { value = text; if (value.empty()) { overlay_element::set_unicode_text(placeholder); } else if (password_mode) { overlay_element::set_unicode_text(std::u32string(value.size(), U"*"[0])); } else { overlay_element::set_unicode_text(value); } } void edit_text::set_placeholder(const std::u32string& placeholder_text) { placeholder = placeholder_text; } void edit_text::insert_text(const std::u32string& str) { if (caret_position == 0) { // Start value = str + text; } else if (caret_position == text.length()) { // End value += str; } else { // Middle value.insert(caret_position, str); } caret_position += str.length(); m_reset_caret_pulse = true; set_unicode_text(value); refresh(); } void edit_text::erase() { if (!caret_position) { return; } if (caret_position == 1) { value = value.length() > 1 ? value.substr(1) : U""; } else if (caret_position == text.length()) { value = value.substr(0, caret_position - 1); } else { value = value.substr(0, caret_position - 1) + value.substr(caret_position); } caret_position--; m_reset_caret_pulse = true; set_unicode_text(value); refresh(); } compiled_resource& edit_text::get_compiled() { if (!is_compiled) { auto& compiled = label::get_compiled(); overlay_element caret; auto renderer = get_font(); const auto caret_loc = renderer->get_char_offset(text.c_str(), caret_position, clip_text ? w : -1, wrap_text); caret.set_pos(static_cast(caret_loc.first) + padding_left + x, static_cast(caret_loc.second) + padding_top + y); caret.set_size(1, static_cast(renderer->get_size_px() + 2)); caret.fore_color = fore_color; caret.back_color = fore_color; caret.pulse_effect_enabled = true; if (m_reset_caret_pulse) { // Reset the pulse slightly below 1 rising on each user interaction caret.set_sinus_offset(1.6f); m_reset_caret_pulse = false; } compiled.add(caret.get_compiled()); for (auto& cmd : compiled.draw_commands) { // TODO: Scrolling by using scroll offset cmd.config.clip_region = true; cmd.config.clip_rect = {static_cast(x), static_cast(y), static_cast(x + w), static_cast(y + h)}; } is_compiled = true; } return compiled_resources; } } // namespace overlays } // namespace rsx