diff options
Diffstat (limited to 'scene/gui/text_edit.cpp')
| -rw-r--r-- | scene/gui/text_edit.cpp | 769 |
1 files changed, 545 insertions, 224 deletions
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index ceb40925ec..8efff21fc9 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -5,7 +5,7 @@ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -34,6 +34,7 @@ #include "globals.h" #include "message_queue.h" +#include "scene/main/viewport.h" #define TAB_PIXELS @@ -346,7 +347,7 @@ void TextEdit::_update_scrollbars() { v_scroll->show(); v_scroll->set_max(total_rows); v_scroll->set_page(visible_rows); - v_scroll->set_val(cursor.line_ofs); + v_scroll->set_value(cursor.line_ofs); } else { cursor.line_ofs = 0; @@ -358,7 +359,7 @@ void TextEdit::_update_scrollbars() { h_scroll->show(); h_scroll->set_max(total_width); h_scroll->set_page(visible_width); - h_scroll->set_val(cursor.x_ofs); + h_scroll->set_value(cursor.x_ofs); } else { @@ -417,9 +418,24 @@ void TextEdit::_notification(int p_what) { _update_caches(); } break; + case MainLoop::NOTIFICATION_WM_FOCUS_IN: { + window_has_focus = true; + draw_caret = true; + update(); + } break; + case MainLoop::NOTIFICATION_WM_FOCUS_OUT: { + window_has_focus = false; + draw_caret = false; + update(); + } break; case NOTIFICATION_DRAW: { + if ((!has_focus() && !menu->has_focus()) || !window_has_focus) { + draw_caret = false; + } + if (draw_breakpoint_gutter) { + breakpoint_gutter_width = (get_row_height() * 55) / 100; cache.breakpoint_gutter_width = breakpoint_gutter_width; } else { cache.breakpoint_gutter_width = 0; @@ -466,12 +482,20 @@ void TextEdit::_notification(int p_what) { Color color = cache.font_color; int in_region=-1; + if (line_length_guideline) { + int x=xmargin_beg+cache.font->get_char_size('0').width*line_length_guideline_col-cursor.x_ofs; + if (x>xmargin_beg && x<xmargin_end) { + Color guideline_color(color.r,color.g,color.b,color.a*0.25f); + VisualServer::get_singleton()->canvas_item_add_line(ci,Point2(x,0),Point2(x,cache.size.height),guideline_color); + } + } + if (syntax_coloring) { - if (custom_bg_color.a>0.01) { + if (cache.background_color.a>0.01) { Point2i ofs = Point2i(cache.style_normal->get_offset())/2.0; - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(ofs, get_size()-cache.style_normal->get_minimum_size()+ofs),custom_bg_color); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(ofs, get_size()-cache.style_normal->get_minimum_size()+ofs),cache.background_color); } //compute actual region to start (may be inside say, a comment). //slow in very large documments :( but ok for source! @@ -669,6 +693,8 @@ void TextEdit::_notification(int p_what) { // get the highlighted words String highlighted_text = get_selection_text(); + String line_num_padding = line_numbers_zero_padded ? "0" : " "; + for (int i=0;i<visible_rows;i++) { int line=i+cursor.line_ofs; @@ -684,6 +710,7 @@ void TextEdit::_notification(int p_what) { bool prev_is_char=false; bool prev_is_number = false; bool in_keyword=false; + bool underlined=false; bool in_word = false; bool in_function_name = false; bool in_member_variable = false; @@ -700,15 +727,6 @@ void TextEdit::_notification(int p_what) { if (highlighted_text.length() != 0 && highlighted_text != search_text) highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE|SEARCH_WHOLE_WORDS, 0); - if (cache.line_number_w) { - String fc = String::num(line+1); - while (fc.length() < line_number_char_count) { - fc="0"+fc; - } - - cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT)+cache.breakpoint_gutter_width,ofs_y+cache.font->get_ascent()),fc,cache.line_number_color); - } - const Map<int,Text::ColorRegionInfo>& cri_map=text.get_color_region_info(line); @@ -720,21 +738,32 @@ void TextEdit::_notification(int p_what) { if (text.is_breakpoint(line)) { VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.breakpoint_color); + } - // draw breakpoint marker + if (line==cursor.line) { + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(0, ofs_y,xmargin_end,get_row_height()),cache.current_line_color); + } + + // draw breakpoint marker + if (text.is_breakpoint(line)) { if (draw_breakpoint_gutter) { - int vertical_gap = cache.breakpoint_gutter_width / 2; - int marker_size = cache.breakpoint_gutter_width - vertical_gap; + int vertical_gap = (get_row_height() * 40) / 100; + int horizontal_gap = (cache.breakpoint_gutter_width * 30) / 100; + int marker_height = get_row_height() - (vertical_gap * 2); + int marker_width = cache.breakpoint_gutter_width - (horizontal_gap * 2); // no transparency on marker - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + 1, ofs_y + vertical_gap ,marker_size, marker_size),Color(cache.breakpoint_color.r, cache.breakpoint_color.g, cache.breakpoint_color.b)); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + horizontal_gap - 2, ofs_y + vertical_gap ,marker_width, marker_height),Color(cache.breakpoint_color.r, cache.breakpoint_color.g, cache.breakpoint_color.b)); } } - if (line==cursor.line) { - - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.current_line_color); + if (cache.line_number_w) { + String fc = String::num(line+1); + while (fc.length() < line_number_char_count) { + fc=line_num_padding+fc; + } + cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT)+cache.breakpoint_gutter_width,ofs_y+cache.font->get_ascent()),fc,cache.line_number_color); } for (int j=0;j<str.length();j++) { @@ -807,8 +836,10 @@ void TextEdit::_notification(int p_what) { } } - if (!is_char) + if (!is_char) { in_keyword=false; + underlined=false; + } if (in_region==-1 && !in_keyword && is_char && !prev_is_char) { @@ -826,6 +857,12 @@ void TextEdit::_notification(int p_what) { in_keyword=true; keyword_color=*col; } + + if (select_identifiers_enabled && hilighted_word!=String()) { + if (hilighted_word==range) { + underlined=true; + } + } } if (!in_function_name && in_word && !in_keyword) { @@ -835,6 +872,11 @@ void TextEdit::_notification(int p_what) { k++; } + // check for space between name and bracket + while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) { + k++; + } + if (str[k] == '(') { in_function_name = true; } @@ -865,7 +907,7 @@ void TextEdit::_notification(int p_what) { else if (in_function_name) color=cache.function_color; else if (is_symbol) - color=symbol_color; + color=cache.symbol_color; else if (is_number) color=cache.number_color; @@ -943,6 +985,12 @@ void TextEdit::_notification(int p_what) { } bool in_highlighted_word = (j >= highlighted_text_col && j < highlighted_text_col+highlighted_text.length()); + + /* if this is the original highlighted text we don't want to highlight it again */ + if (cursor.line==line && (cursor.column >= highlighted_text_col && cursor.column <= highlighted_text_col+highlighted_text.length())) { + in_highlighted_word = false; + } + if (in_highlighted_word) { VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w, get_row_height())),cache.word_highlighted_color); } @@ -971,34 +1019,43 @@ void TextEdit::_notification(int p_what) { } } - - if (str[j]>=32) - cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); - - else if (draw_tabs && str[j]=='\t') { - int yofs= (get_row_height() - cache.tab_icon->get_height())/2; - cache.tab_icon->draw(ci, Point2(char_ofs+char_margin,ofs_y+yofs),in_selection?cache.font_selected_color:color); - } - - if (cursor.column==j && cursor.line==line) { cursor_pos = Point2i( char_ofs+char_margin, ofs_y ); if (insert_mode) { - cursor_pos.y += get_row_height(); + cursor_pos.y += (get_row_height() - 3); } + int caret_w = (str[j]=='\t') ? cache.font->get_char_size(' ').width : char_w; if (draw_caret) { if (insert_mode) { - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color); + int caret_h = (block_caret) ? 4 : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(caret_w,caret_h)),cache.caret_color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color); + caret_w = (block_caret) ? caret_w : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(caret_w,get_row_height())),cache.caret_color); } } } - char_ofs+=char_w; + if (cursor.column==j && cursor.line==line && block_caret && draw_caret && !insert_mode) { + color = cache.caret_background_color; + } + + if (str[j]>=32) { + int w = cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); + if (underlined) { + draw_rect(Rect2( char_ofs+char_margin, ofs_y+ascent+2,w,1),in_selection?cache.font_selected_color:color); + } + } + + else if (draw_tabs && str[j]=='\t') { + int yofs= (get_row_height() - cache.tab_icon->get_height())/2; + cache.tab_icon->draw(ci, Point2(char_ofs+char_margin,ofs_y+yofs),in_selection?cache.font_selected_color:color); + } + + char_ofs+=char_w; } if (cursor.column==str.length() && cursor.line==line && (char_ofs+char_margin)>=xmargin_beg) { @@ -1006,15 +1063,18 @@ void TextEdit::_notification(int p_what) { cursor_pos=Point2i( char_ofs+char_margin, ofs_y ); if (insert_mode) { - cursor_pos.y += get_row_height(); + cursor_pos.y += (get_row_height() - 3); } if (draw_caret) { if (insert_mode) { int char_w = cache.font->get_char_size(' ').width; - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,1)),cache.caret_color); + int caret_h = (block_caret) ? 4 : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(char_w,caret_h)),cache.caret_color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.caret_color); + int char_w = cache.font->get_char_size(' ').width; + int caret_w = (block_caret) ? char_w : 1; + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(caret_w,get_row_height())),cache.caret_color); } } } @@ -1024,11 +1084,8 @@ void TextEdit::_notification(int p_what) { if (completion_active) { // code completion box Ref<StyleBox> csb = get_stylebox("completion"); - Ref<StyleBox> csel = get_stylebox("completion_selected"); int maxlines = get_constant("completion_lines"); int cmax_width = get_constant("completion_max_width")*cache.font->get_char_size('x').x; - Color existing = get_color("completion_existing"); - existing.a=0.2; int scrollw = get_constant("completion_scroll_width"); Color scrollc = get_color("completion_scroll_color"); @@ -1072,11 +1129,12 @@ void TextEdit::_notification(int p_what) { draw_style_box(csb,Rect2(completion_rect.pos-csb->get_offset(),completion_rect.size+csb->get_minimum_size()+Size2(scrollw,0))); - + if (cache.completion_background_color.a>0.01) { + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(completion_rect.pos,completion_rect.size+Size2(scrollw,0)),cache.completion_background_color); + } int line_from = CLAMP(completion_index - lines/2, 0, completion_options.size() - lines); - draw_style_box(csel,Rect2(Point2(completion_rect.pos.x,completion_rect.pos.y+(completion_index-line_from)*get_row_height()),Size2(completion_rect.size.width,get_row_height()))); - - draw_rect(Rect2(completion_rect.pos,Size2(nofs,completion_rect.size.height)),existing); + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2(completion_rect.pos.x,completion_rect.pos.y+(completion_index-line_from)*get_row_height()),Size2(completion_rect.size.width,get_row_height())),cache.completion_selected_color); + draw_rect(Rect2(completion_rect.pos,Size2(nofs,completion_rect.size.height)),cache.completion_existing_color); @@ -1085,7 +1143,7 @@ void TextEdit::_notification(int p_what) { int l = line_from + i; ERR_CONTINUE( l < 0 || l>= completion_options.size()); - Color text_color = cache.font_color; + Color text_color = cache.completion_font_color; for(int j=0;j<color_regions.size();j++) { if (completion_options[l].begins_with(color_regions[j].begin_key)) { text_color=color_regions[j].color; @@ -1192,17 +1250,24 @@ void TextEdit::_notification(int p_what) { } break; case NOTIFICATION_FOCUS_ENTER: { + if (!caret_blink_enabled) { + draw_caret = true; + } if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect()); + if (raised_from_completion) { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + } } break; case NOTIFICATION_FOCUS_EXIT: { if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->hide_virtual_keyboard(); - + if (raised_from_completion) { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + } } break; - } } @@ -1403,13 +1468,13 @@ void TextEdit::_get_mouse_pos(const Point2i& p_mouse, int &r_row, int &r_col) co r_col=col; } -void TextEdit::_input_event(const InputEvent& p_input_event) { +void TextEdit::_gui_input(const InputEvent& p_gui_input) { - switch(p_input_event.type) { + switch(p_gui_input.type) { case InputEvent::MOUSE_BUTTON: { - const InputEventMouseButton &mb=p_input_event.mouse_button; + const InputEventMouseButton &mb=p_gui_input.mouse_button; if (completion_active && completion_rect.has_point(Point2(mb.x,mb.y))) { @@ -1449,30 +1514,39 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } if (mb.pressed) { - if (mb.button_index==BUTTON_WHEEL_UP) { - v_scroll->set_val( v_scroll->get_val() -3 ); + if (mb.button_index==BUTTON_WHEEL_UP && !mb.mod.command) { + v_scroll->set_value( v_scroll->get_value() -3 ); } - if (mb.button_index==BUTTON_WHEEL_DOWN) { - v_scroll->set_val( v_scroll->get_val() +3 ); + if (mb.button_index==BUTTON_WHEEL_DOWN && !mb.mod.command) { + v_scroll->set_value( v_scroll->get_value() +3 ); } if (mb.button_index==BUTTON_WHEEL_LEFT) { - h_scroll->set_val( h_scroll->get_val() -3 ); + h_scroll->set_value( h_scroll->get_value() -3 ); } if (mb.button_index==BUTTON_WHEEL_RIGHT) { - h_scroll->set_val( h_scroll->get_val() +3 ); + h_scroll->set_value( h_scroll->get_value() +3 ); } if (mb.button_index==BUTTON_LEFT) { + _reset_caret_blink_timer(); int row,col; _get_mouse_pos(Point2i(mb.x,mb.y), row,col); + if (mb.mod.command && hilighted_word!=String()) { + + emit_signal("symbol_lookup",hilighted_word,row,col); + return; + } + + // toggle breakpoint on gutter click if (draw_breakpoint_gutter) { int gutter=cache.style_normal->get_margin(MARGIN_LEFT); if (mb.x > gutter && mb.x <= gutter + cache.breakpoint_gutter_width + 3) { set_line_as_breakpoint(row, !is_line_set_as_breakpoint(row)); + emit_signal("breakpoint_toggled", row); return; } } @@ -1591,7 +1665,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { update(); } - if (mb.button_index==BUTTON_RIGHT) { + if (mb.button_index==BUTTON_RIGHT && context_menu_enabled) { menu->set_pos(get_global_transform().xform(get_local_mouse_pos())); menu->set_size(Vector2(1,1)); @@ -1611,9 +1685,25 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } break; case InputEvent::MOUSE_MOTION: { - const InputEventMouseMotion &mm=p_input_event.mouse_motion; + const InputEventMouseMotion &mm=p_gui_input.mouse_motion; + + if (select_identifiers_enabled) { + if (mm.mod.command && mm.button_mask==0) { + + String new_word = get_word_at_pos(Vector2(mm.x,mm.y)); + if (new_word!=hilighted_word) { + hilighted_word=new_word; + update(); + } + } else { + if (hilighted_word!=String()) { + hilighted_word=String(); + update(); + } + } + } - if (mm.button_mask&BUTTON_MASK_LEFT) { + if (mm.button_mask&BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data()==Variant()) { //ignore if dragging if (selection.selecting_mode!=Selection::MODE_NONE) { @@ -1638,7 +1728,28 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { case InputEvent::KEY: { - InputEventKey k=p_input_event.key; + InputEventKey k=p_gui_input.key; + + +#ifdef OSX_ENABLED + if (k.scancode==KEY_META) { +#else + if (k.scancode==KEY_CONTROL) { + +#endif + if (select_identifiers_enabled) { + + if (k.pressed) { + + hilighted_word = get_word_at_pos(get_local_mouse_pos()); + update(); + + } else { + hilighted_word=String(); + update(); + } + } + } if (!k.pressed) return; @@ -1730,7 +1841,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { return; } - if (k.scancode==KEY_RETURN || k.scancode==KEY_TAB) { + if (k.scancode==KEY_ENTER || k.scancode==KEY_RETURN || k.scancode==KEY_TAB) { _confirm_completion(); accept_event(); @@ -1807,6 +1918,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (!k.mod.command) { _reset_caret_blink_timer(); } + + // save here for insert mode, just in case it is cleared in the following section bool had_selection = selection.active; @@ -1955,6 +2068,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } } break; case KEY_TAB: { + if (k.mod.command) break; // avoid tab when command if (readonly) break; @@ -2047,6 +2161,12 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (k.mod.shift) _pre_shift_selection(); +#ifdef APPLE_STYLE_KEYS + else +#else + else if (!k.mod.alt) +#endif + deselect(); #ifdef APPLE_STYLE_KEYS if (k.mod.command) { @@ -2100,6 +2220,12 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (k.mod.shift) _pre_shift_selection(); +#ifdef APPLE_STYLE_KEYS + else +#else + else if (!k.mod.alt) +#endif + deselect(); #ifdef APPLE_STYLE_KEYS if (k.mod.command) { @@ -2430,7 +2556,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } break; case KEY_X: { - + if (readonly) { + break; + } if (!k.mod.command || k.mod.shift || k.mod.alt) { scancode_handled=false; break; @@ -2462,7 +2590,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { undo(); } break; case KEY_V: { - + if (readonly) { + break; + } if (!k.mod.command || k.mod.shift || k.mod.alt) { scancode_handled=false; break; @@ -2507,7 +2637,7 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { } update(); } - break;} + } break; default: { @@ -2889,7 +3019,7 @@ int TextEdit::get_char_count() { return totalsize; // omit last \n } -Size2 TextEdit::get_minimum_size() { +Size2 TextEdit::get_minimum_size() const { return cache.style_normal->get_minimum_size(); } @@ -2906,7 +3036,7 @@ void TextEdit::adjust_viewport_to_cursor() { cursor.line_ofs=cursor.line; int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w-cache.breakpoint_gutter_width; - if (v_scroll->is_visible()) + if (v_scroll->is_visible_in_tree()) visible_width-=v_scroll->get_combined_minimum_size().width; visible_width-=20; // give it a little more space @@ -2914,7 +3044,7 @@ void TextEdit::adjust_viewport_to_cursor() { //printf("rowofs %i, visrows %i, cursor.line %i\n",cursor.line_ofs,get_visible_rows(),cursor.line); int visible_rows = get_visible_rows(); - if (h_scroll->is_visible()) + if (h_scroll->is_visible_in_tree()) visible_rows-=((h_scroll->get_combined_minimum_size().height-1)/get_row_height()); if (cursor.line>=(cursor.line_ofs+visible_rows)) @@ -2942,6 +3072,34 @@ void TextEdit::adjust_viewport_to_cursor() { } +void TextEdit::center_viewport_to_cursor() { + + if (cursor.line_ofs>cursor.line) + cursor.line_ofs=cursor.line; + + int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w-cache.breakpoint_gutter_width; + if (v_scroll->is_visible_in_tree()) + visible_width-=v_scroll->get_combined_minimum_size().width; + visible_width-=20; // give it a little more space + + int visible_rows = get_visible_rows(); + if (h_scroll->is_visible_in_tree()) + visible_rows-=((h_scroll->get_combined_minimum_size().height-1)/get_row_height()); + + int max_ofs = text.size()-(scroll_past_end_of_file_enabled?1:visible_rows); + cursor.line_ofs=CLAMP(cursor.line-(visible_rows/2),0,max_ofs); + + int cursor_x = get_column_x_offset( cursor.column, text[cursor.line] ); + + if (cursor_x>(cursor.x_ofs+visible_width)) + cursor.x_ofs=cursor_x-visible_width+1; + + if (cursor_x < cursor.x_ofs) + cursor.x_ofs=cursor_x; + + update(); +} + void TextEdit::cursor_set_column(int p_col, bool p_adjust_viewport) { if (p_col<0) @@ -3032,16 +3190,25 @@ void TextEdit::cursor_set_blink_speed(const float p_speed) { caret_blink_timer->set_wait_time(p_speed); } +void TextEdit::cursor_set_block_mode(const bool p_enable){ + block_caret = p_enable; + update(); +} + +bool TextEdit::cursor_is_block_mode() const { + return block_caret; +} + void TextEdit::_scroll_moved(double p_to_val) { if (updating_scrolls) return; - if (h_scroll->is_visible()) - cursor.x_ofs=h_scroll->get_val(); - if (v_scroll->is_visible()) - cursor.line_ofs=v_scroll->get_val(); + if (h_scroll->is_visible_in_tree()) + cursor.x_ofs=h_scroll->get_value(); + if (v_scroll->is_visible_in_tree()) + cursor.line_ofs=v_scroll->get_value(); update(); } @@ -3134,6 +3301,9 @@ void TextEdit::insert_text_at_cursor(const String& p_text) { } Control::CursorShape TextEdit::get_cursor_shape(const Point2& p_pos) const { + if (hilighted_word!=String()) + return CURSOR_POINTING_HAND; + int gutter=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w+cache.breakpoint_gutter_width; if((completion_active && completion_rect.has_point(p_pos)) || p_pos.x < gutter) { return CURSOR_ARROW; @@ -3157,7 +3327,7 @@ void TextEdit::set_text(String p_text){ cursor_set_column(0); update(); setting_text=false; - + _text_changed_emit(); //get_range()->set(0); }; @@ -3176,6 +3346,36 @@ String TextEdit::get_text() { }; + +String TextEdit::get_text_for_lookup_completion() { + + + int row,col; + _get_mouse_pos(get_local_mouse_pos(), row,col); + + + String longthing; + int len = text.size(); + for (int i=0;i<len;i++) { + + if (i==row) { + longthing+=text[i].substr(0,col); + longthing+=String::chr(0xFFFF); //not unicode, represents the cursor + longthing+=text[i].substr(col,text[i].size()); + } else { + + longthing+=text[i]; + } + + + if (i!=len-1) + longthing+="\n"; + } + + return longthing; + +} + String TextEdit::get_text_for_completion() { String longthing; @@ -3258,15 +3458,22 @@ void TextEdit::_reset_caret_blink_timer() { void TextEdit::_toggle_draw_caret() { draw_caret = !draw_caret; - update(); + if (is_visible_in_tree() && has_focus() && window_has_focus) { + update(); + } } void TextEdit::_update_caches() { cache.style_normal=get_stylebox("normal"); cache.style_focus=get_stylebox("focus"); + cache.completion_background_color=get_color("completion_background_color"); + cache.completion_selected_color=get_color("completion_selected_color"); + cache.completion_existing_color=get_color("completion_existing_color"); + cache.completion_font_color=get_color("completion_font_color"); cache.font=get_font("font"); cache.caret_color=get_color("caret_color"); + cache.caret_background_color=get_color("caret_background_color"); cache.line_number_color=get_color("line_number_color"); cache.font_color=get_color("font_color"); cache.font_selected_color=get_color("font_selected_color"); @@ -3282,6 +3489,8 @@ void TextEdit::_update_caches() { cache.word_highlighted_color=get_color("word_highlighted_color"); cache.search_result_color=get_color("search_result_color"); cache.search_result_border_color=get_color("search_result_border_color"); + cache.symbol_color=get_color("symbol_color"); + cache.background_color=get_color("background_color"); cache.line_spacing=get_constant("line_spacing"); cache.row_height = cache.font->get_height() + cache.line_spacing; cache.tab_icon=get_icon("tab"); @@ -3293,15 +3502,8 @@ void TextEdit::_update_caches() { void TextEdit::clear_colors() { keywords.clear(); - color_regions.clear();; + color_regions.clear(); text.clear_caches(); - custom_bg_color=Color(0,0,0,0); -} - -void TextEdit::set_custom_bg_color(const Color& p_color) { - - custom_bg_color=p_color; - update(); } void TextEdit::add_keyword_color(const String& p_keyword,const Color& p_color) { @@ -3319,12 +3521,6 @@ void TextEdit::add_color_region(const String& p_begin_key,const String& p_end_ke } -void TextEdit::set_symbol_color(const Color& p_color) { - - symbol_color=p_color; - update(); -} - void TextEdit::set_syntax_coloring(bool p_enabled) { syntax_coloring=p_enabled; @@ -3554,6 +3750,7 @@ void TextEdit::set_search_flags(uint32_t p_flags) { void TextEdit::set_current_search_result(int line, int col) { search_result_line = line; search_result_col = col; + update(); } void TextEdit::set_highlight_all_occurrences(const bool p_enabled) { @@ -3561,6 +3758,10 @@ void TextEdit::set_highlight_all_occurrences(const bool p_enabled) { update(); } +bool TextEdit::is_highlight_all_occurrences_enabled() const { + return highlight_all_occurrences; +} + int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column) { int col = -1; @@ -3582,7 +3783,7 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc if (col > 0 && _is_text_char(p_search[col-1])) { col = -1; - } else if (_is_text_char(p_search[col+p_key.length()])) { + } else if ((col + p_key.length()) < p_search.length() && _is_text_char(p_search[col+p_key.length()])) { col = -1; } } @@ -3593,11 +3794,11 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc return col; } -DVector<int> TextEdit::_search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const { +PoolVector<int> TextEdit::_search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const { int col,line; if (search(p_key,p_search_flags,p_from_line,p_from_column,col,line)) { - DVector<int> result; + PoolVector<int> result; result.resize(2); result.set(0,line); result.set(1,col); @@ -3605,7 +3806,7 @@ DVector<int> TextEdit::_search_bind(const String &p_key,uint32_t p_search_flags, } else { - return DVector<int>(); + return PoolVector<int>(); } } @@ -3819,16 +4020,26 @@ void TextEdit::undo() { _do_text_op(op, true); current_op.version=op.prev_version; if(undo_stack_pos->get().chain_backward) { - do { + while(true) { + ERR_BREAK(!undo_stack_pos->prev()); undo_stack_pos = undo_stack_pos->prev(); op = undo_stack_pos->get(); _do_text_op(op, true); current_op.version = op.prev_version; - } while(!undo_stack_pos->get().chain_forward); + if (undo_stack_pos->get().chain_forward) { + break; + } + } } - cursor_set_line(undo_stack_pos->get().from_line); - cursor_set_column(undo_stack_pos->get().from_column); + if (undo_stack_pos->get().type == TextOperation::TYPE_REMOVE) { + cursor_set_line(undo_stack_pos->get().to_line); + cursor_set_column(undo_stack_pos->get().to_column); + _cancel_code_hint(); + } else { + cursor_set_line(undo_stack_pos->get().from_line); + cursor_set_column(undo_stack_pos->get().from_column); + } update(); } @@ -3843,12 +4054,16 @@ void TextEdit::redo() { _do_text_op(op, false); current_op.version = op.version; if(undo_stack_pos->get().chain_forward) { - do { + + while(true) { + ERR_BREAK(!undo_stack_pos->next()); undo_stack_pos=undo_stack_pos->next(); op = undo_stack_pos->get(); _do_text_op(op, false); current_op.version = op.version; - } while(!undo_stack_pos->get().chain_backward); + if (undo_stack_pos->get().chain_backward) + break; + } } cursor_set_line(undo_stack_pos->get().to_line); cursor_set_column(undo_stack_pos->get().to_column); @@ -3940,21 +4155,21 @@ void TextEdit::tag_saved_version() { int TextEdit::get_v_scroll() const { - return v_scroll->get_val(); + return v_scroll->get_value(); } void TextEdit::set_v_scroll(int p_scroll) { - v_scroll->set_val(p_scroll); + v_scroll->set_value(p_scroll); cursor.line_ofs=p_scroll; } int TextEdit::get_h_scroll() const { - return h_scroll->get_val(); + return h_scroll->get_value(); } void TextEdit::set_h_scroll(int p_scroll) { - h_scroll->set_val(p_scroll); + h_scroll->set_value(p_scroll); } void TextEdit::set_completion(bool p_enabled,const Vector<String>& p_prefixes) { @@ -3967,39 +4182,35 @@ void TextEdit::set_completion(bool p_enabled,const Vector<String>& p_prefixes) { void TextEdit::_confirm_completion() { - String remaining=completion_current.substr(completion_base.length(),completion_current.length()-completion_base.length()); - String l = text[cursor.line]; - bool same=true; - //if what is going to be inserted is the same as what it is, don't change it - for(int i=0;i<remaining.length();i++) { - int c=i+cursor.column; - if (c>=l.length() || l[c]!=remaining[i]) { - same=false; - break; - } - } + begin_complex_operation(); - if (same) - cursor_set_column(cursor.column+remaining.length()); - else { - insert_text_at_cursor(remaining); - if (remaining.ends_with("(") && auto_brace_completion_enabled) { - insert_text_at_cursor(")"); - cursor.column--; - } + _remove_text(cursor.line, cursor.column - completion_base.length(), cursor.line, cursor.column); + cursor_set_column(cursor.column - completion_base.length(), false); + insert_text_at_cursor(completion_current); + + if (completion_current.ends_with("(") && auto_brace_completion_enabled) { + insert_text_at_cursor(")"); + cursor.column--; } + end_complex_operation(); + _cancel_completion(); } void TextEdit::_cancel_code_hint() { + + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + raised_from_completion = false; completion_hint=""; update(); } void TextEdit::_cancel_completion() { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 0); + raised_from_completion = false; if (!completion_active) return; @@ -4019,7 +4230,6 @@ void TextEdit::_update_completion_candidates() { String l = text[cursor.line]; int cofs = CLAMP(cursor.column,0,l.length()); - String s; //look for keywords first @@ -4068,14 +4278,14 @@ void TextEdit::_update_completion_candidates() { while(cofs>0 && l[cofs-1]>32 && _is_completable(l[cofs-1])) { s=String::chr(l[cofs-1])+s; - if (l[cofs-1]=='\'' || l[cofs-1]=='"') + if (l[cofs-1]=='\'' || l[cofs-1]=='"' || l[cofs-1]=='$') break; cofs--; } } - if (l[cursor.column - 1] == '(' && !pre_keyword && !completion_strings[0].begins_with("\"")) { + if (cursor.column > 0 && l[cursor.column - 1] == '(' && !pre_keyword && !completion_strings[0].begins_with("\"")) { cancel = true; } @@ -4090,31 +4300,43 @@ void TextEdit::_update_completion_candidates() { completion_options.clear(); completion_index=0; completion_base=s; - int ci_match=0; + Vector<float> sim_cache; for(int i=0;i<completion_strings.size();i++) { - if (completion_strings[i].begins_with(s)) { - // don't remove duplicates if no input is provided - if (completion_options.find(completion_strings[i]) != -1 && s != "") { - continue; - } - completion_options.push_back(completion_strings[i]); - int m=0; - int max=MIN(completion_current.length(),completion_strings[i].length()); - if (max<ci_match) - continue; - for(int j=0;j<max;j++) { + if (s == completion_strings[i]) { + // A perfect match, stop completion + _cancel_completion(); + return; + } - if (j>=completion_strings[i].length()) - break; - if (completion_current[j]!=completion_strings[i][j]) - break; - m++; + if (s.is_subsequence_ofi(completion_strings[i])) { + // don't remove duplicates if no input is provided + if (s != "" && completion_options.find(completion_strings[i]) != -1) { + continue; } - if (m>ci_match) { - ci_match=m; - completion_index=completion_options.size()-1; + // Calculate the similarity to keep completions in good order + float similarity; + if (completion_strings[i].to_lower().begins_with(s.to_lower())) { + // Substrings are the best candidates + similarity = 1.1; + } else { + // Otherwise compute the similarity + similarity = s.to_lower().similarity(completion_strings[i].to_lower()); } + int comp_size = completion_options.size(); + if (comp_size == 0) { + completion_options.push_back(completion_strings[i]); + sim_cache.push_back(similarity); + } else { + float comp_sim; + int pos = 0; + do { + comp_sim = sim_cache[pos++]; + } while(pos < comp_size && similarity < comp_sim); + pos = similarity > comp_sim ? pos - 1 : pos; // Pos will be off by one + completion_options.insert(pos, completion_strings[i]); + sim_cache.insert(pos, similarity); + } } } @@ -4123,24 +4345,24 @@ void TextEdit::_update_completion_candidates() { if (completion_options.size()==0) { //no options to complete, cancel _cancel_completion(); + return; } - completion_current=completion_options[completion_index]; + // The top of the list is the best match + completion_current=completion_options[0]; #if 0 // even there's only one option, user still get the chance to choose using it or not if (completion_options.size()==1) { //one option to complete, just complete it automagically _confirm_completion(); - // insert_text_at_cursor(completion_options[0].substr(s.length(),completion_options[0].length()-s.length())); + //insert_text_at_cursor(completion_options[0].substr(s.length(),completion_options[0].length()-s.length())); _cancel_completion(); return; } #endif - if (completion_options.size()==1 && s==completion_options[0]) - _cancel_completion(); completion_enabled=true; } @@ -4169,6 +4391,8 @@ void TextEdit::query_code_comple() { void TextEdit::set_code_hint(const String& p_hint) { + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + raised_from_completion = true; completion_hint=p_hint; completion_hint_offset=-0xFFFF; update(); @@ -4176,7 +4400,8 @@ void TextEdit::set_code_hint(const String& p_hint) { void TextEdit::code_complete(const Vector<String> &p_strings) { - + VisualServer::get_singleton()->canvas_item_set_z(get_canvas_item(), 1); + raised_from_completion = true; completion_strings=p_strings; completion_active=true; completion_current=""; @@ -4186,6 +4411,38 @@ void TextEdit::code_complete(const Vector<String> &p_strings) { } +String TextEdit::get_word_at_pos(const Vector2& p_pos) const { + + int row,col; + _get_mouse_pos(p_pos, row, col); + + String s = text[row]; + if (s.length()==0) + return ""; + int beg=CLAMP(col,0,s.length()); + int end=beg; + + + if (s[beg]>32 || beg==s.length()) { + + bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this + + while(beg>0 && s[beg-1]>32 && (symbol==_is_symbol(s[beg-1]))) { + beg--; + } + while(end<s.length() && s[end+1]>32 && (symbol==_is_symbol(s[end+1]))) { + end++; + } + + if (end<s.length()) + end+=1; + + return s.substr(beg,end-beg); + } + + return String(); +} + String TextEdit::get_tooltip(const Point2& p_pos) const { if (!tooltip_obj) @@ -4255,6 +4512,26 @@ void TextEdit::set_show_line_numbers(bool p_show) { update(); } +void TextEdit::set_line_numbers_zero_padded(bool p_zero_padded) { + + line_numbers_zero_padded=p_zero_padded; + update(); +} + +bool TextEdit::is_show_line_numbers_enabled() const { + return line_numbers; +} + +void TextEdit::set_show_line_length_guideline(bool p_show) { + line_length_guideline=p_show; + update(); +} + +void TextEdit::set_line_length_guideline_column(int p_column) { + line_length_guideline_col=p_column; + update(); +} + void TextEdit::set_draw_breakpoint_gutter(bool p_draw) { draw_breakpoint_gutter = p_draw; update(); @@ -4282,18 +4559,22 @@ void TextEdit::menu_option(int p_option) { switch( p_option ) { case MENU_CUT: { - - cut(); + if (!readonly) { + cut(); + } } break; case MENU_COPY: { copy(); } break; case MENU_PASTE: { - - paste(); + if (!readonly) { + paste(); + } } break; case MENU_CLEAR: { - clear(); + if (!readonly) { + clear(); + } } break; case MENU_SELECT_ALL: { select_all(); @@ -4305,6 +4586,21 @@ void TextEdit::menu_option(int p_option) { }; } + +void TextEdit::set_select_identifiers_on_hover(bool p_enable) { + + select_identifiers_enabled=p_enable; +} + +bool TextEdit::is_selecting_identifiers_on_hover_enabled() const { + + return select_identifiers_enabled; +} + +void TextEdit::set_context_menu_enabled(bool p_enable) { + context_menu_enabled = p_enable; +} + PopupMenu *TextEdit::get_menu() const { return menu; } @@ -4312,81 +4608,96 @@ PopupMenu *TextEdit::get_menu() const { void TextEdit::_bind_methods() { - ObjectTypeDB::bind_method(_MD("_input_event"),&TextEdit::_input_event); - ObjectTypeDB::bind_method(_MD("_scroll_moved"),&TextEdit::_scroll_moved); - ObjectTypeDB::bind_method(_MD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit); - ObjectTypeDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit); - ObjectTypeDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op); - ObjectTypeDB::bind_method(_MD("_click_selection_held"),&TextEdit::_click_selection_held); - ObjectTypeDB::bind_method(_MD("_toggle_draw_caret"),&TextEdit::_toggle_draw_caret); + ClassDB::bind_method(_MD("_gui_input"),&TextEdit::_gui_input); + ClassDB::bind_method(_MD("_scroll_moved"),&TextEdit::_scroll_moved); + ClassDB::bind_method(_MD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit); + ClassDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit); + ClassDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op); + ClassDB::bind_method(_MD("_click_selection_held"),&TextEdit::_click_selection_held); + ClassDB::bind_method(_MD("_toggle_draw_caret"),&TextEdit::_toggle_draw_caret); BIND_CONSTANT( SEARCH_MATCH_CASE ); BIND_CONSTANT( SEARCH_WHOLE_WORDS ); BIND_CONSTANT( SEARCH_BACKWARDS ); /* - ObjectTypeDB::bind_method(_MD("delete_char"),&TextEdit::delete_char); - ObjectTypeDB::bind_method(_MD("delete_line"),&TextEdit::delete_line); + ClassDB::bind_method(_MD("delete_char"),&TextEdit::delete_char); + ClassDB::bind_method(_MD("delete_line"),&TextEdit::delete_line); */ - ObjectTypeDB::bind_method(_MD("set_text","text"),&TextEdit::set_text); - ObjectTypeDB::bind_method(_MD("insert_text_at_cursor","text"),&TextEdit::insert_text_at_cursor); - - ObjectTypeDB::bind_method(_MD("get_line_count"),&TextEdit::get_line_count); - ObjectTypeDB::bind_method(_MD("get_text"),&TextEdit::get_text); - ObjectTypeDB::bind_method(_MD("get_line","line"),&TextEdit::get_line); - - ObjectTypeDB::bind_method(_MD("cursor_set_column","column","adjust_viewport"),&TextEdit::cursor_set_column,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("cursor_set_line","line","adjust_viewport"),&TextEdit::cursor_set_line,DEFVAL(false)); - - ObjectTypeDB::bind_method(_MD("cursor_get_column"),&TextEdit::cursor_get_column); - ObjectTypeDB::bind_method(_MD("cursor_get_line"),&TextEdit::cursor_get_line); - ObjectTypeDB::bind_method(_MD("cursor_set_blink_enabled", "enable"),&TextEdit::cursor_set_blink_enabled); - ObjectTypeDB::bind_method(_MD("cursor_get_blink_enabled"),&TextEdit::cursor_get_blink_enabled); - ObjectTypeDB::bind_method(_MD("cursor_set_blink_speed", "blink_speed"),&TextEdit::cursor_set_blink_speed); - ObjectTypeDB::bind_method(_MD("cursor_get_blink_speed"),&TextEdit::cursor_get_blink_speed); - - ObjectTypeDB::bind_method(_MD("set_readonly","enable"),&TextEdit::set_readonly); - ObjectTypeDB::bind_method(_MD("set_wrap","enable"),&TextEdit::set_wrap); - ObjectTypeDB::bind_method(_MD("set_max_chars","amount"),&TextEdit::set_max_chars); - - ObjectTypeDB::bind_method(_MD("cut"),&TextEdit::cut); - ObjectTypeDB::bind_method(_MD("copy"),&TextEdit::copy); - ObjectTypeDB::bind_method(_MD("paste"),&TextEdit::paste); - ObjectTypeDB::bind_method(_MD("select_all"),&TextEdit::select_all); - ObjectTypeDB::bind_method(_MD("select","from_line","from_column","to_line","to_column"),&TextEdit::select); - - ObjectTypeDB::bind_method(_MD("is_selection_active"),&TextEdit::is_selection_active); - ObjectTypeDB::bind_method(_MD("get_selection_from_line"),&TextEdit::get_selection_from_line); - ObjectTypeDB::bind_method(_MD("get_selection_from_column"),&TextEdit::get_selection_from_column); - ObjectTypeDB::bind_method(_MD("get_selection_to_line"),&TextEdit::get_selection_to_line); - ObjectTypeDB::bind_method(_MD("get_selection_to_column"),&TextEdit::get_selection_to_column); - ObjectTypeDB::bind_method(_MD("get_selection_text"),&TextEdit::get_selection_text); - ObjectTypeDB::bind_method(_MD("get_word_under_cursor"),&TextEdit::get_word_under_cursor); - ObjectTypeDB::bind_method(_MD("search","flags","from_line","from_column","to_line","to_column"),&TextEdit::_search_bind); - - ObjectTypeDB::bind_method(_MD("undo"),&TextEdit::undo); - ObjectTypeDB::bind_method(_MD("redo"),&TextEdit::redo); - ObjectTypeDB::bind_method(_MD("clear_undo_history"),&TextEdit::clear_undo_history); - - ObjectTypeDB::bind_method(_MD("set_syntax_coloring","enable"),&TextEdit::set_syntax_coloring); - ObjectTypeDB::bind_method(_MD("is_syntax_coloring_enabled"),&TextEdit::is_syntax_coloring_enabled); - - - ObjectTypeDB::bind_method(_MD("add_keyword_color","keyword","color"),&TextEdit::add_keyword_color); - ObjectTypeDB::bind_method(_MD("add_color_region","begin_key","end_key","color","line_only"),&TextEdit::add_color_region,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("set_symbol_color","color"),&TextEdit::set_symbol_color); - ObjectTypeDB::bind_method(_MD("set_custom_bg_color","color"),&TextEdit::set_custom_bg_color); - ObjectTypeDB::bind_method(_MD("clear_colors"),&TextEdit::clear_colors); - ObjectTypeDB::bind_method(_MD("menu_option"),&TextEdit::menu_option); - ObjectTypeDB::bind_method(_MD("get_menu:PopupMenu"),&TextEdit::get_menu); - - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret/caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled"));; - ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret/caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), _SCS("cursor_set_blink_speed"),_SCS("cursor_get_blink_speed") ); + ClassDB::bind_method(_MD("set_text","text"),&TextEdit::set_text); + ClassDB::bind_method(_MD("insert_text_at_cursor","text"),&TextEdit::insert_text_at_cursor); + + ClassDB::bind_method(_MD("get_line_count"),&TextEdit::get_line_count); + ClassDB::bind_method(_MD("get_text"),&TextEdit::get_text); + ClassDB::bind_method(_MD("get_line","line"),&TextEdit::get_line); + + ClassDB::bind_method(_MD("cursor_set_column","column","adjust_viewport"),&TextEdit::cursor_set_column,DEFVAL(false)); + ClassDB::bind_method(_MD("cursor_set_line","line","adjust_viewport"),&TextEdit::cursor_set_line,DEFVAL(false)); + + ClassDB::bind_method(_MD("cursor_get_column"),&TextEdit::cursor_get_column); + ClassDB::bind_method(_MD("cursor_get_line"),&TextEdit::cursor_get_line); + ClassDB::bind_method(_MD("cursor_set_blink_enabled", "enable"),&TextEdit::cursor_set_blink_enabled); + ClassDB::bind_method(_MD("cursor_get_blink_enabled"),&TextEdit::cursor_get_blink_enabled); + ClassDB::bind_method(_MD("cursor_set_blink_speed", "blink_speed"),&TextEdit::cursor_set_blink_speed); + ClassDB::bind_method(_MD("cursor_get_blink_speed"),&TextEdit::cursor_get_blink_speed); + ClassDB::bind_method(_MD("cursor_set_block_mode", "enable"), &TextEdit::cursor_set_block_mode); + ClassDB::bind_method(_MD("cursor_is_block_mode"), &TextEdit::cursor_is_block_mode); + + ClassDB::bind_method(_MD("set_readonly","enable"),&TextEdit::set_readonly); + ClassDB::bind_method(_MD("set_wrap","enable"),&TextEdit::set_wrap); + ClassDB::bind_method(_MD("set_max_chars","amount"),&TextEdit::set_max_chars); + + ClassDB::bind_method(_MD("cut"),&TextEdit::cut); + ClassDB::bind_method(_MD("copy"),&TextEdit::copy); + ClassDB::bind_method(_MD("paste"),&TextEdit::paste); + ClassDB::bind_method(_MD("select_all"),&TextEdit::select_all); + ClassDB::bind_method(_MD("select","from_line","from_column","to_line","to_column"),&TextEdit::select); + + ClassDB::bind_method(_MD("is_selection_active"),&TextEdit::is_selection_active); + ClassDB::bind_method(_MD("get_selection_from_line"),&TextEdit::get_selection_from_line); + ClassDB::bind_method(_MD("get_selection_from_column"),&TextEdit::get_selection_from_column); + ClassDB::bind_method(_MD("get_selection_to_line"),&TextEdit::get_selection_to_line); + ClassDB::bind_method(_MD("get_selection_to_column"),&TextEdit::get_selection_to_column); + ClassDB::bind_method(_MD("get_selection_text"),&TextEdit::get_selection_text); + ClassDB::bind_method(_MD("get_word_under_cursor"),&TextEdit::get_word_under_cursor); + ClassDB::bind_method(_MD("search","flags","from_line","from_column","to_line","to_column"),&TextEdit::_search_bind); + + ClassDB::bind_method(_MD("undo"),&TextEdit::undo); + ClassDB::bind_method(_MD("redo"),&TextEdit::redo); + ClassDB::bind_method(_MD("clear_undo_history"),&TextEdit::clear_undo_history); + + ClassDB::bind_method(_MD("set_show_line_numbers", "enable"), &TextEdit::set_show_line_numbers); + ClassDB::bind_method(_MD("is_show_line_numbers_enabled"), &TextEdit::is_show_line_numbers_enabled); + + ClassDB::bind_method(_MD("set_highlight_all_occurrences", "enable"), &TextEdit::set_highlight_all_occurrences); + ClassDB::bind_method(_MD("is_highlight_all_occurrences_enabled"), &TextEdit::is_highlight_all_occurrences_enabled); + + ClassDB::bind_method(_MD("set_syntax_coloring","enable"),&TextEdit::set_syntax_coloring); + ClassDB::bind_method(_MD("is_syntax_coloring_enabled"),&TextEdit::is_syntax_coloring_enabled); + + + ClassDB::bind_method(_MD("add_keyword_color","keyword","color"),&TextEdit::add_keyword_color); + ClassDB::bind_method(_MD("add_color_region","begin_key","end_key","color","line_only"),&TextEdit::add_color_region,DEFVAL(false)); + ClassDB::bind_method(_MD("clear_colors"),&TextEdit::clear_colors); + ClassDB::bind_method(_MD("menu_option"),&TextEdit::menu_option); + ClassDB::bind_method(_MD("get_menu:PopupMenu"),&TextEdit::get_menu); + + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "syntax_highlighting"), _SCS("set_syntax_coloring"), _SCS("is_syntax_coloring_enabled")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_line_numbers"), _SCS("set_show_line_numbers"), _SCS("is_show_line_numbers_enabled")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), _SCS("set_highlight_all_occurrences"), _SCS("is_highlight_all_occurrences_enabled")); + + + ADD_GROUP("Caret","caret_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_block_mode"), _SCS("cursor_set_block_mode"), _SCS("cursor_is_block_mode")); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled")); + ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), _SCS("cursor_set_blink_speed"),_SCS("cursor_get_blink_speed") ); ADD_SIGNAL(MethodInfo("cursor_changed")); ADD_SIGNAL(MethodInfo("text_changed")); ADD_SIGNAL(MethodInfo("request_completion")); + ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo( Variant::INT, "row"))); + ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING,"symbol"),PropertyInfo( Variant::INT, "row"),PropertyInfo( Variant::INT, "column"))); BIND_CONSTANT( MENU_CUT ); BIND_CONSTANT( MENU_COPY ); @@ -4397,6 +4708,7 @@ void TextEdit::_bind_methods() { BIND_CONSTANT( MENU_MAX ); + GLOBAL_DEF("gui/timers/text_edit_idle_detect_sec",3); } TextEdit::TextEdit() { @@ -4420,8 +4732,8 @@ TextEdit::TextEdit() { tab_size=4; text.set_tab_size(tab_size); text.clear(); - // text.insert(1,"Mongolia.."); - // text.insert(2,"PAIS GENEROSO!!"); + //text.insert(1,"Mongolia.."); + //text.insert(2,"PAIS GENEROSO!!"); text.set_color_regions(&color_regions); h_scroll = memnew( HScrollBar ); @@ -4446,6 +4758,7 @@ TextEdit::TextEdit() { selection.active=false; syntax_coloring=false; + block_caret=false; caret_blink_enabled=false; caret_blink_timer = memnew(Timer); add_child(caret_blink_timer); @@ -4453,11 +4766,10 @@ TextEdit::TextEdit() { caret_blink_timer->connect("timeout", this,"_toggle_draw_caret"); cursor_set_blink_enabled(false); - custom_bg_color=Color(0,0,0,0); idle_detect = memnew( Timer ); add_child(idle_detect); idle_detect->set_one_shot(true); - idle_detect->set_wait_time(GLOBAL_DEF("display/text_edit_idle_detect_sec",3)); + idle_detect->set_wait_time(GLOBAL_GET("gui/timers/text_edit_idle_detect_sec")); idle_detect->connect("timeout", this,"_push_current_op"); click_select_held = memnew( Timer ); @@ -4497,14 +4809,23 @@ TextEdit::TextEdit() { completion_line_ofs=0; tooltip_obj=NULL; line_numbers=false; + line_numbers_zero_padded=false; + line_length_guideline=false; + line_length_guideline_col=80; draw_breakpoint_gutter=false; next_operation_is_complex=false; scroll_past_end_of_file_enabled=false; auto_brace_completion_enabled=false; brace_matching_enabled=false; + highlight_all_occurrences=false; auto_indent=false; insert_mode = false; + window_has_focus=true; + select_identifiers_enabled=false; + + raised_from_completion = false; + context_menu_enabled=true; menu = memnew( PopupMenu ); add_child(menu); menu->add_item(TTR("Cut"),MENU_CUT,KEY_MASK_CMD|KEY_X); @@ -4515,7 +4836,7 @@ TextEdit::TextEdit() { menu->add_item(TTR("Clear"),MENU_CLEAR); menu->add_separator(); menu->add_item(TTR("Undo"),MENU_UNDO,KEY_MASK_CMD|KEY_Z); - menu->connect("item_pressed",this,"menu_option"); + menu->connect("id_pressed",this,"menu_option"); } |