diff options
Diffstat (limited to 'scene/gui/line_edit.cpp')
-rw-r--r-- | scene/gui/line_edit.cpp | 175 |
1 files changed, 127 insertions, 48 deletions
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 4a2bb3dad1..4a763844f8 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "line_edit.h" + #include "core/message_queue.h" #include "core/os/keyboard.h" #include "core/os/os.h" @@ -43,7 +44,7 @@ static bool _is_text_char(CharType c) { - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; + return !is_symbol(c); } void LineEdit::_gui_input(Ref<InputEvent> p_event) { @@ -55,8 +56,10 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT && context_menu_enabled) { menu->set_position(get_global_transform().xform(get_local_mouse_position())); menu->set_size(Vector2(1, 1)); + menu->set_scale(get_global_transform().get_scale()); menu->popup(); grab_focus(); + accept_event(); return; } @@ -66,6 +69,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { _reset_caret_blink_timer(); if (b->is_pressed()) { + accept_event(); //don't pass event further when clicked on text field if (!text.empty() && is_editable() && _is_over_clear_button(b->get_position())) { clear_button_status.press_attempt = true; clear_button_status.pressing_inside = true; @@ -157,6 +161,38 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { if (!k->is_pressed()) return; + +#ifdef APPLE_STYLE_KEYS + if (k->get_control() && !k->get_shift() && !k->get_alt() && !k->get_command()) { + uint32_t remap_key = KEY_UNKNOWN; + switch (k->get_scancode()) { + case KEY_F: { + remap_key = KEY_RIGHT; + } break; + case KEY_B: { + remap_key = KEY_LEFT; + } break; + case KEY_P: { + remap_key = KEY_UP; + } break; + case KEY_N: { + remap_key = KEY_DOWN; + } break; + case KEY_D: { + remap_key = KEY_DELETE; + } break; + case KEY_H: { + remap_key = KEY_BACKSPACE; + } break; + } + + if (remap_key != KEY_UNKNOWN) { + k->set_scancode(remap_key); + k->set_control(false); + } + } +#endif + unsigned int code = k->get_scancode(); if (k->get_command()) { @@ -320,7 +356,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { handled = false; break; } - // numlock disabled. fallthrough to key_left + FALLTHROUGH; } case KEY_LEFT: { @@ -367,7 +403,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { handled = false; break; } - // numlock disabled. fallthrough to key_right + FALLTHROUGH; } case KEY_RIGHT: { @@ -474,7 +510,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { handled = false; break; } - // numlock disabled. fallthrough to key_home + FALLTHROUGH; } case KEY_HOME: { @@ -487,7 +523,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { handled = false; break; } - // numlock disabled. fallthrough to key_end + FALLTHROUGH; } case KEY_END: { @@ -504,7 +540,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { if (handled) { accept_event(); - } else if (!k->get_alt() && !k->get_command()) { + } else if (!k->get_command()) { if (k->get_unicode() >= 32 && k->get_scancode() != KEY_DELETE) { if (editable) { @@ -588,10 +624,7 @@ bool LineEdit::_is_over_clear_button(const Point2 &p_pos) const { } Ref<Texture> icon = Control::get_icon("clear"); int x_ofs = get_stylebox("normal")->get_offset().x; - if (p_pos.x > get_size().width - icon->get_width() - x_ofs) { - return true; - } - return false; + return p_pos.x > get_size().width - icon->get_width() - x_ofs; } void LineEdit::_notification(int p_what) { @@ -611,12 +644,15 @@ void LineEdit::_notification(int p_what) { #endif case NOTIFICATION_RESIZED: { - if (expand_to_text_length) { - window_pos = 0; //force scroll back since it's expanding to text length - } + window_pos = 0; set_cursor_position(get_cursor_position()); } break; + case NOTIFICATION_TRANSLATION_CHANGED: { + placeholder_translated = tr(placeholder); + update_placeholder_width(); + update(); + } break; case MainLoop::NOTIFICATION_WM_FOCUS_IN: { window_has_focus = true; draw_caret = true; @@ -642,10 +678,8 @@ void LineEdit::_notification(int p_what) { RID ci = get_canvas_item(); Ref<StyleBox> style = get_stylebox("normal"); - float disabled_alpha = 1.0; // used to set the disabled input text color if (!is_editable()) { style = get_stylebox("read_only"); - disabled_alpha = .5; draw_caret = false; } @@ -691,20 +725,19 @@ void LineEdit::_notification(int p_what) { int font_ascent = font->get_ascent(); Color selection_color = get_color("selection_color"); - Color font_color = get_color("font_color"); + Color font_color = is_editable() ? get_color("font_color") : get_color("font_color_uneditable"); Color font_color_selected = get_color("font_color_selected"); Color cursor_color = get_color("cursor_color"); - const String &t = using_placeholder ? placeholder : text; + const String &t = using_placeholder ? placeholder_translated : text; // draw placeholder color if (using_placeholder) font_color.a *= placeholder_alpha; - font_color.a *= disabled_alpha; bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled; if (right_icon.is_valid() || display_clear_icon) { Ref<Texture> r_icon = display_clear_icon ? Control::get_icon("clear") : right_icon; - Color color_icon(1, 1, 1, disabled_alpha * .9); + Color color_icon(1, 1, 1, !is_editable() ? .5 * .9 : .9); if (display_clear_icon) { if (clear_button_status.press_attempt && clear_button_status.pressing_inside) { color_icon = get_color("clear_button_color_pressed"); @@ -721,6 +754,8 @@ void LineEdit::_notification(int p_what) { } else { x_ofs = MAX(style->get_margin(MARGIN_LEFT), x_ofs - r_icon->get_width() - style->get_margin(MARGIN_RIGHT)); } + + ofs_max -= r_icon->get_width(); } int caret_height = font->get_height() > y_area ? y_area : font->get_height(); @@ -888,7 +923,8 @@ void LineEdit::cut_text() { void LineEdit::paste_text() { - String paste_buffer = OS::get_singleton()->get_clipboard(); + // Strip escape characters like \n and \t as they can't be displayed on LineEdit. + String paste_buffer = OS::get_singleton()->get_clipboard().strip_escapes(); if (paste_buffer != "") { @@ -917,6 +953,10 @@ void LineEdit::undo() { TextOperation op = undo_stack_pos->get(); text = op.text; set_cursor_position(op.cursor_pos); + + if (expand_to_text_length) + minimum_size_changed(); + _emit_text_change(); } @@ -931,6 +971,10 @@ void LineEdit::redo() { TextOperation op = undo_stack_pos->get(); text = op.text; set_cursor_position(op.cursor_pos); + + if (expand_to_text_length) + minimum_size_changed(); + _emit_text_change(); } @@ -956,6 +1000,8 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) { Ref<StyleBox> style = get_stylebox("normal"); int pixel_ofs = 0; Size2 size = get_size(); + bool display_clear_icon = !text.empty() && is_editable() && clear_button_enabled; + int r_icon_width = Control::get_icon("clear")->get_width(); switch (align) { @@ -970,10 +1016,16 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) { pixel_ofs = int(style->get_offset().x); else pixel_ofs = int(size.width - (cached_width)) / 2; + + if (display_clear_icon) + pixel_ofs -= int(r_icon_width / 2 + style->get_margin(MARGIN_RIGHT)); } break; case ALIGN_RIGHT: { pixel_ofs = int(size.width - style->get_margin(MARGIN_RIGHT) - (cached_width)); + + if (display_clear_icon) + pixel_ofs -= int(r_icon_width + style->get_margin(MARGIN_RIGHT)); } break; } @@ -1104,16 +1156,9 @@ String LineEdit::get_text() const { void LineEdit::set_placeholder(String p_text) { - placeholder = tr(p_text); - if ((max_length <= 0) || (placeholder.length() <= max_length)) { - Ref<Font> font = get_font("font"); - cached_placeholder_width = 0; - if (font != NULL) { - for (int i = 0; i < placeholder.length(); i++) { - cached_placeholder_width += font->get_char_size(placeholder[i]).width; - } - } - } + placeholder = p_text; + placeholder_translated = tr(placeholder); + update_placeholder_width(); update(); } @@ -1154,14 +1199,14 @@ void LineEdit::set_cursor_position(int p_pos) { if (cursor_pos <= window_pos) { /* Adjust window if cursor goes too much to the left */ - if (window_pos > 0) - set_window_pos(window_pos - 1); - - } else if (cursor_pos > window_pos) { + set_window_pos(MAX(0, cursor_pos - 1)); + } else { /* Adjust window if cursor goes too much to the right */ int window_width = get_size().width - style->get_minimum_size().width; - if (right_icon.is_valid()) { - window_width -= right_icon->get_width(); + bool display_clear_icon = !text.empty() && is_editable() && clear_button_enabled; + if (right_icon.is_valid() || display_clear_icon) { + Ref<Texture> r_icon = display_clear_icon ? Control::get_icon("clear") : right_icon; + window_width -= r_icon->get_width(); } if (window_width < 0) @@ -1225,6 +1270,7 @@ void LineEdit::append_at_cursor(String p_text) { void LineEdit::clear_internal() { + deselect(); _clear_undo_stack(); cached_width = 0; cursor_pos = 0; @@ -1315,7 +1361,37 @@ void LineEdit::select_all() { void LineEdit::set_editable(bool p_editable) { + if (editable == p_editable) + return; + editable = p_editable; + + // Reorganize context menu. + menu->clear(); + + if (editable) { + menu->add_item(RTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z); + menu->add_item(RTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z); + } + + if (editable) { + menu->add_separator(); + menu->add_item(RTR("Cut"), MENU_CUT, KEY_MASK_CMD | KEY_X); + } + + menu->add_item(RTR("Copy"), MENU_COPY, KEY_MASK_CMD | KEY_C); + + if (editable) { + menu->add_item(RTR("Paste"), MENU_PASTE, KEY_MASK_CMD | KEY_V); + } + + menu->add_separator(); + menu->add_item(RTR("Select All"), MENU_SELECT_ALL, KEY_MASK_CMD | KEY_A); + + if (editable) { + menu->add_item(RTR("Clear"), MENU_CLEAR); + } + update(); } @@ -1339,8 +1415,7 @@ void LineEdit::set_secret_character(const String &p_string) { // An empty string as the secret character would crash the engine // It also wouldn't make sense to use multiple characters as the secret character - ERR_EXPLAIN("Secret character must be exactly one character long (" + itos(p_string.length()) + " characters given)"); - ERR_FAIL_COND(p_string.length() != 1); + ERR_FAIL_COND_MSG(p_string.length() != 1, "Secret character must be exactly one character long (" + itos(p_string.length()) + " characters given)."); secret_character = p_string; update(); @@ -1481,6 +1556,18 @@ void LineEdit::_emit_text_change() { text_changed_dirty = false; } +void LineEdit::update_placeholder_width() { + if ((max_length <= 0) || (placeholder_translated.length() <= max_length)) { + Ref<Font> font = get_font("font"); + cached_placeholder_width = 0; + if (font != NULL) { + for (int i = 0; i < placeholder_translated.length(); i++) { + cached_placeholder_width += font->get_char_size(placeholder_translated[i]).width; + } + } + } +} + void LineEdit::_clear_redo() { _create_undo_state(); if (undo_stack_pos == NULL) { @@ -1611,7 +1698,6 @@ LineEdit::LineEdit() { deselect(); set_focus_mode(FOCUS_ALL); - editable = true; set_default_cursor_shape(CURSOR_IBEAM); set_mouse_filter(MOUSE_FILTER_STOP); @@ -1626,15 +1712,8 @@ LineEdit::LineEdit() { context_menu_enabled = true; menu = memnew(PopupMenu); add_child(menu); - menu->add_item(RTR("Cut"), MENU_CUT, KEY_MASK_CMD | KEY_X); - menu->add_item(RTR("Copy"), MENU_COPY, KEY_MASK_CMD | KEY_C); - menu->add_item(RTR("Paste"), MENU_PASTE, KEY_MASK_CMD | KEY_V); - menu->add_separator(); - menu->add_item(RTR("Select All"), MENU_SELECT_ALL, KEY_MASK_CMD | KEY_A); - menu->add_item(RTR("Clear"), MENU_CLEAR); - menu->add_separator(); - menu->add_item(RTR("Undo"), MENU_UNDO, KEY_MASK_CMD | KEY_Z); - menu->add_item(RTR("Redo"), MENU_REDO, KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_Z); + editable = false; // initialise to opposite first, so we get past the early-out in set_editable + set_editable(true); menu->connect("id_pressed", this, "menu_option"); expand_to_text_length = false; } |