diff --git a/src/bin/editor/edi_editor.c b/src/bin/editor/edi_editor.c index b9caa2a..9ca6bfd 100644 --- a/src/bin/editor/edi_editor.c +++ b/src/bin/editor/edi_editor.c @@ -17,6 +17,8 @@ #include "edi_private.h" +static Evas_Object *_suggest_hint; + static void _suggest_popup_show(Edi_Editor *editor); typedef struct @@ -598,8 +600,147 @@ _edi_editor_snippet_insert(Edi_Editor *editor, Evas_Event_Key_Down *ev) elm_code_widget_selection_delete(editor->entry); elm_code_widget_text_at_cursor_insert(editor->entry, snippet); - ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; + if (ev) + ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD; free(key); + return; +} + +static void +_suggest_hint_hide(Edi_Editor *editor EINA_UNUSED) +{ + if (!_suggest_hint) + return; + + evas_object_hide(_suggest_hint); +} + +static Evas_Object * +_suggest_hint_popup_add(Edi_Editor *editor, const char *content, Evas_Smart_Cb fn) +{ + Evas_Object *pop, *btn, *text; + unsigned int row, col; + Evas_Coord cx, cy, cw, ch; + + elm_code_widget_cursor_position_get(editor->entry, &row, &col); + + elm_code_widget_cursor_position_get(editor->entry, &row, &col); + elm_code_widget_geometry_for_position_get(editor->entry, row, col, + &cx, &cy, &cw, &ch); + + pop = elm_box_add(editor->entry); + evas_object_size_hint_weight_set(pop, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(pop, EVAS_HINT_FILL, EVAS_HINT_FILL); + + evas_object_size_hint_weight_set(pop, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(pop, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_move(pop, cx, cy - ch); + + btn = elm_button_add(pop); + evas_object_smart_callback_add(btn, "clicked", fn, editor); + evas_object_size_hint_weight_set(btn, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(btn, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(pop, btn); + evas_object_show(btn); + + text = elm_label_add(btn); + evas_object_size_hint_weight_set(text, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(text, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_object_text_set(text, content); + + elm_layout_content_set(btn, "elm.swallow.content", text); + evas_object_show(text); + + return pop; +} + +static void +_suggest_hint_click_snippet(void *data, Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + Edi_Editor *editor = data; + + _suggest_hint_hide(editor); + _edi_editor_snippet_insert(editor, NULL); +} + +static void +_suggest_hint_show_snippet(Edi_Editor *editor, const char *word) +{ + unsigned int row, col; + const char *snippet; + + if (!word || strlen(word) == 0) + return; + + elm_code_widget_cursor_position_get(editor->entry, &row, &col); + + snippet = edi_language_provider_get(editor)->snippet_get(word); + if (!snippet) + return; + + _suggest_hint = _suggest_hint_popup_add(editor, + eina_slstr_printf("Press tab to insert snippet %s", word), + _suggest_hint_click_snippet); + evas_object_show(_suggest_hint); +} + +Edi_Language_Suggest_Item * +_suggest_match_get(Edi_Editor *editor, const char *word) +{ + Edi_Language_Suggest_Item *suggest_it; + unsigned int row, col, wordlen; + + elm_code_widget_cursor_position_get(editor->entry, &row, &col); + Eina_List *l, *list = edi_language_provider_get(editor)->lookup(editor, row, col - strlen(word)); + + wordlen = strlen(word); + EINA_LIST_FOREACH(list, l, suggest_it) + { + if (strlen(suggest_it->summary) <= wordlen) + continue; + if (eina_str_has_prefix(suggest_it->summary, word)) + return suggest_it; + } + + return NULL; +} + +static void +_suggest_hint_click_suggest(void *data, Evas_Object *obj EINA_UNUSED, + void *event_info EINA_UNUSED) +{ + Edi_Editor *editor = data; + Edi_Language_Suggest_Item *match; + unsigned int row, col; + char *word; + + _suggest_hint_hide(editor); + + elm_code_widget_cursor_position_get(editor->entry, &row, &col); + word = _edi_editor_current_word_get(editor, row, col); + + match = _suggest_match_get(editor, word); + if (match) + _suggest_list_selection_insert(editor, match->summary); + + free(word); +} + +static void +_suggest_hint_show_match(Edi_Editor *editor, const char *word) +{ + Edi_Language_Suggest_Item *match; + + match = _suggest_match_get(editor, word); + if (!match) + return; + + _suggest_hint = _suggest_hint_popup_add(editor, + eina_slstr_printf("Press tab to insert suggestion %s", match->summary), + _suggest_hint_click_suggest); + + evas_object_show(_suggest_hint); } static void @@ -608,6 +749,7 @@ _smart_cb_key_down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, { Edi_Mainview_Item *item; Edi_Editor *editor; + Edi_Language_Provider *provider; Eina_Bool ctrl, alt, shift; Evas_Event_Key_Down *ev = event; @@ -621,6 +763,7 @@ _smart_cb_key_down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, return; editor = (Edi_Editor *)evas_object_data_get(item->view, "editor"); + _suggest_hint_hide(editor); if ((!alt) && (ctrl) && (!shift)) { @@ -657,17 +800,45 @@ _smart_cb_key_down(void *data EINA_UNUSED, Evas *e EINA_UNUSED, } } - if ((!alt) && (!ctrl)) + if (alt || ctrl) + return; + + provider = edi_language_provider_get(editor); + if (!provider) + return; + + if (evas_object_visible_get(editor->suggest_bg)) { - if (!strcmp(ev->key, "Tab") && edi_language_provider_has(editor)) + _suggest_popup_key_down_cb(editor, ev->key, ev->string); + return; + } + + if (!strcmp(ev->key, "Tab")) + { + char *word; + const char *snippet; + unsigned int row, col; + Edi_Language_Suggest_Item *suggest; + + elm_code_widget_cursor_position_get(editor->entry, &row, &col); + word = _edi_editor_current_word_get(editor, row, col); + + snippet = provider->snippet_get(word); + if (snippet) _edi_editor_snippet_insert(editor, ev); - else if (edi_language_provider_has(editor)) - _suggest_popup_key_down_cb(editor, ev->key, ev->string); + else if (strlen(word) >= 3) + { + suggest = _suggest_match_get(editor, word); + if (suggest) + _suggest_list_selection_insert(editor, suggest->summary); + } + + free(word); } } static void -_edit_cursor_moved(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) +_edit_cursor_moved(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { Elm_Code_Widget *widget; char buf[30]; @@ -682,9 +853,40 @@ _edit_cursor_moved(void *data EINA_UNUSED, Evas_Object *obj, void *event_info EI } static void -_edit_file_changed(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) +_edit_file_changed(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) { + Elm_Code_Widget *widget; + Edi_Editor *editor; + Edi_Language_Provider *provider; + char *word; + const char *snippet; + unsigned int row, col; + ecore_event_add(EDI_EVENT_FILE_CHANGED, NULL, NULL, NULL); + + widget = (Elm_Code_Widget *)obj; + editor = (Edi_Editor *)data; + + if (evas_object_visible_get(editor->suggest_bg)) + return; + + provider = edi_language_provider_get(editor); + if (!provider) + return; + + elm_code_widget_cursor_position_get(widget, &row, &col); + word = _edi_editor_current_word_get(editor, row, col); + + if (word && strlen(word) > 1) + { + snippet = provider->snippet_get(word); + if (snippet) + _suggest_hint_show_snippet(editor, word); + else if (strlen(word) >= 3) + _suggest_hint_show_match(editor, word); + } + + free(word); } static void @@ -738,7 +940,7 @@ _edi_editor_statusbar_add(Evas_Object *panel, Edi_Editor *editor, Edi_Mainview_I _edit_cursor_moved(position, editor->entry, NULL); evas_object_smart_callback_add(editor->entry, "cursor,changed", _edit_cursor_moved, position); - evas_object_smart_callback_add(editor->entry, "changed,user", _edit_file_changed, position); + evas_object_smart_callback_add(editor->entry, "changed,user", _edit_file_changed, editor); } #if HAVE_LIBCLANG