diff --git a/juci/selectiondialog.cc b/juci/selectiondialog.cc index 6bee4cb..0a34363 100644 --- a/juci/selectiondialog.cc +++ b/juci/selectiondialog.cc @@ -5,67 +5,63 @@ namespace sigc { SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE } -SelectionDialogBase::SelectionDialogBase(Gtk::TextView& text_view, bool popup): text_view(text_view), popup(popup) {} - -void SelectionDialogBase::init() { - if(popup) +SelectionDialogBase::SelectionDialogBase(Gtk::TextView& text_view, Glib::RefPtr start_mark, bool show_search_entry): text_view(text_view), +start_mark(start_mark), show_search_entry(show_search_entry), list_view_text(1, false, Gtk::SelectionMode::SELECTION_BROWSE) { + if(!show_search_entry) window=std::unique_ptr(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP)); else window=std::unique_ptr(new Gtk::Dialog()); - scrolled_window=std::unique_ptr(new Gtk::ScrolledWindow()); - list_view_text=std::unique_ptr(new Gtk::ListViewText(1, false, Gtk::SelectionMode::SELECTION_BROWSE)); - search_entry=std::unique_ptr(new Gtk::Entry()); - list_view_text->set_search_entry(*search_entry); + list_view_text.set_search_entry(search_entry); window->set_default_size(0, 0); window->property_decorated()=false; window->set_skip_taskbar_hint(true); - scrolled_window->set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, Gtk::PolicyType::POLICY_AUTOMATIC); - list_view_text->set_enable_search(true); - list_view_text->set_headers_visible(false); - list_view_text->set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL); - list_view_text->set_activate_on_single_click(true); - list_view_text->set_hover_selection(false); - list_view_text->set_rules_hint(true); - //list_view_text->set_fixed_height_mode(true); //TODO: This is buggy on OS X, remember to post an issue on GTK+ 3 - - last_selected=-1; + scrolled_window.set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, Gtk::PolicyType::POLICY_AUTOMATIC); + list_view_text.set_enable_search(true); + list_view_text.set_headers_visible(false); + list_view_text.set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL); + list_view_text.set_activate_on_single_click(true); + list_view_text.set_hover_selection(false); + list_view_text.set_rules_hint(true); + //list_view_text.set_fixed_height_mode(true); //TODO: This is buggy on OS X, remember to post an issue on GTK+ 3 - list_view_text->signal_cursor_changed().connect(sigc::mem_fun(*this, &SelectionDialog::cursor_changed), true); - list_view_text->signal_realize().connect([this](){ + list_view_text.signal_cursor_changed().connect(sigc::mem_fun(*this, &SelectionDialog::cursor_changed), true); + list_view_text.signal_realize().connect([this](){ resize(); }); - list_view_text->clear_items(); + scrolled_window.add(list_view_text); + if(!show_search_entry) + window->add(scrolled_window); + else { + auto dialog=(Gtk::Dialog*)window.get(); + dialog->get_vbox()->pack_start(search_entry, false, false); + dialog->get_vbox()->pack_start(scrolled_window, true, true); + dialog->set_transient_for((Gtk::Window&)(*text_view.get_toplevel())); + } +} + +SelectionDialogBase::~SelectionDialogBase() { + text_view.get_buffer()->delete_mark(start_mark); } -void SelectionDialogBase::append(const std::string& row) { - list_view_text->append(row); +void SelectionDialogBase::add_row(const std::string& row, const std::string& tooltip) { + list_view_text.append(row); + if(tooltip.size()>0) + tooltip_texts[row]=tooltip; } void SelectionDialogBase::show() { - scrolled_window->add(*list_view_text); - if(popup) - window->add(*scrolled_window); - else { - auto dialog=(Gtk::Dialog*)window.get(); - dialog->get_vbox()->pack_start(*search_entry, false, false); - dialog->get_vbox()->pack_start(*scrolled_window, true, true); - dialog->set_transient_for((Gtk::Window&)(*text_view.get_toplevel())); - } - if(rows.size()>0) { - list_view_text->get_selection()->select(*list_view_text->get_model()->children().begin()); - list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]); + if(list_view_text.get_model()->children().size()>0) { + list_view_text.set_cursor(list_view_text.get_model()->get_path(list_view_text.get_model()->children().begin())); } move(); window->show_all(); - search_entry->show(); - shown=true; + search_entry.show(); } void SelectionDialogBase::hide() { - shown=false; window->hide(); if(tooltips) tooltips->hide(); @@ -74,23 +70,25 @@ void SelectionDialogBase::hide() { } void SelectionDialogBase::cursor_changed() { - auto selected=list_view_text->get_selected(); + auto selected=list_view_text.get_selected(); if(selected.size()>0) { if(selected[0]!=last_selected || last_selected==-1) { if(tooltips) tooltips->hide(); - auto row = rows.at(list_view_text->get_text(selected[0])); - if(row.second.size()>0) { - tooltips=std::unique_ptr(new Tooltips()); - auto tooltip_text=row.second; - auto get_tooltip_buffer=[this, tooltip_text]() { - auto tooltip_buffer=Gtk::TextBuffer::create(text_view.get_buffer()->get_tag_table()); - //TODO: Insert newlines to tooltip_text (use 80 chars, then newline?) - tooltip_buffer->insert_at_cursor(tooltip_text); - return tooltip_buffer; - }; - tooltips->emplace_back(get_tooltip_buffer, text_view, text_view.get_buffer()->create_mark(start_mark->get_iter()), text_view.get_buffer()->create_mark(text_view.get_buffer()->get_insert()->get_iter())); - tooltips->show(true); + auto it=tooltip_texts.find(list_view_text.get_text(selected[0])); + if(it!=tooltip_texts.end()) { + auto tooltip_text=it->second; + if(tooltip_text.size()>0) { + tooltips=std::unique_ptr(new Tooltips()); + auto get_tooltip_buffer=[this, tooltip_text]() { + auto tooltip_buffer=Gtk::TextBuffer::create(text_view.get_buffer()->get_tag_table()); + //TODO: Insert newlines to tooltip_text (use 80 chars, then newline?) + tooltip_buffer->insert_at_cursor(tooltip_text); + return tooltip_buffer; + }; + tooltips->emplace_back(get_tooltip_buffer, text_view, text_view.get_buffer()->create_mark(start_mark->get_iter()), text_view.get_buffer()->create_mark(text_view.get_buffer()->get_insert()->get_iter())); + tooltips->show(true); + } } } } @@ -118,10 +116,10 @@ void SelectionDialogBase::move() { void SelectionDialogBase::resize() { INFO("SelectionDialog set size"); - if(list_view_text->get_realized()) { + if(list_view_text.get_realized()) { int row_width=0, row_height; Gdk::Rectangle rect; - list_view_text->get_cell_area(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin()), *(list_view_text->get_column(0)), rect); + list_view_text.get_cell_area(list_view_text.get_model()->get_path(list_view_text.get_model()->children().begin()), *(list_view_text.get_column(0)), rect); row_width=rect.get_width(); row_height=rect.get_height(); @@ -131,21 +129,21 @@ void SelectionDialogBase::resize() { if(row_width>text_view.get_width()/2) row_width=text_view.get_width()/2; else - scrolled_window->set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_AUTOMATIC); + scrolled_window.set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_AUTOMATIC); - int window_height=std::min(row_height*(int)rows.size(), row_height*10); - if(!popup) - window_height+=search_entry->get_height(); + int window_height=std::min(row_height*(int)list_view_text.get_model()->children().size(), row_height*10); + if(show_search_entry) + window_height+=search_entry.get_height(); window->resize(row_width, window_height); } } -SelectionDialog::SelectionDialog(Gtk::TextView& text_view) : SelectionDialogBase(text_view, false) {} +SelectionDialog::SelectionDialog(Gtk::TextView& text_view, Glib::RefPtr start_mark) : SelectionDialogBase(text_view, start_mark, true) {} void SelectionDialog::show() { SelectionDialogBase::show(); std::shared_ptr search_key(new std::string()); - auto filter_model=Gtk::TreeModelFilter::create(list_view_text->get_model()); + auto filter_model=Gtk::TreeModelFilter::create(list_view_text.get_model()); filter_model->set_visible_func([this, search_key](const Gtk::TreeModel::const_iterator& iter){ std::string row_lc; iter->get_value(0, row_lc); @@ -156,83 +154,85 @@ void SelectionDialog::show() { return true; return false; }); - list_view_text->set_model(filter_model); - list_view_text->set_search_equal_func([this](const Glib::RefPtr& model, int column, const Glib::ustring& key, const Gtk::TreeModel::iterator& iter) { + list_view_text.set_model(filter_model); + list_view_text.set_search_equal_func([this](const Glib::RefPtr& model, int column, const Glib::ustring& key, const Gtk::TreeModel::iterator& iter) { return false; }); - search_entry->signal_changed().connect([this, search_key, filter_model](){ - *search_key=search_entry->get_text(); + search_entry.signal_changed().connect([this, search_key, filter_model](){ + *search_key=search_entry.get_text(); filter_model->refilter(); - list_view_text->set_search_entry(*search_entry); //TODO:Report the need of this to GTK's git (bug) + list_view_text.set_search_entry(search_entry); //TODO:Report the need of this to GTK's git (bug) }); - search_entry->signal_event().connect([this, search_key, filter_model](GdkEvent* event) { + search_entry.signal_event().connect([this, search_key, filter_model](GdkEvent* event) { if(event->type==GDK_KEY_PRESS) { auto key=(GdkEventKey*)event; - if(key->keyval==GDK_KEY_Down) { - auto it=list_view_text->get_selection()->get_selected(); + if(key->keyval==GDK_KEY_Down && list_view_text.get_model()->children().size()>0) { + auto it=list_view_text.get_selection()->get_selected(); if(it) { it++; if(it) { - list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); + list_view_text.set_cursor(list_view_text.get_model()->get_path(it)); } } else - list_view_text->set_cursor(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin())); + list_view_text.set_cursor(list_view_text.get_model()->get_path(list_view_text.get_model()->children().begin())); return true; } - if(key->keyval==GDK_KEY_Up) { - auto it=list_view_text->get_selection()->get_selected(); + if(key->keyval==GDK_KEY_Up && list_view_text.get_model()->children().size()>0) { + auto it=list_view_text.get_selection()->get_selected(); if(it) { it--; if(it) { - list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); + list_view_text.set_cursor(list_view_text.get_model()->get_path(it)); } } + else { + auto last_it=list_view_text.get_model()->children().end(); + last_it--; + list_view_text.set_cursor(list_view_text.get_model()->get_path(last_it)); + } return true; } } return false; }); auto activate=[this](){ - if(on_select && list_view_text->get_selected().size()>0) { - auto it=list_view_text->get_selection()->get_selected(); + if(on_select && list_view_text.get_selected().size()>0) { + auto it=list_view_text.get_selection()->get_selected(); std::string row; it->get_value(0, row); - std::string selected = rows.at(row).first; - on_select(selected); + std::string selected = row; + on_select(selected, true); } window->hide(); }; - search_entry->signal_activate().connect([this, activate](){ + search_entry.signal_activate().connect([this, activate](){ activate(); }); - list_view_text->signal_row_activated().connect([this, activate](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { + list_view_text.signal_row_activated().connect([this, activate](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { activate(); }); window->signal_focus_out_event().connect([this](GdkEventFocus*){ window->hide(); return true; }); - list_view_text->set_cursor(list_view_text->get_model()->get_path(list_view_text->get_model()->children().begin())); } -CompletionDialog::CompletionDialog(Gtk::TextView& text_view) : SelectionDialogBase(text_view, true) {} +CompletionDialog::CompletionDialog(Gtk::TextView& text_view, Glib::RefPtr start_mark) : SelectionDialogBase(text_view, start_mark, false) {} void CompletionDialog::show() { SelectionDialogBase::show(); show_offset=text_view.get_buffer()->get_insert()->get_iter().get_offset(); - list_view_text->signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { - if(shown) { - select(); - } + list_view_text.signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { + select(); }); auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); if(text.size()>0) { - search_entry->set_text(text); - list_view_text->set_search_entry(*search_entry); + search_entry.set_text(text); + list_view_text.set_search_entry(search_entry); } row_in_entry=false; @@ -240,29 +240,13 @@ void CompletionDialog::show() { void CompletionDialog::select(bool hide_window) { row_in_entry=true; - auto selected=list_view_text->get_selected(); - std::pair select; + auto selected=list_view_text.get_selected(); if(selected.size()>0) { - select = rows.at(list_view_text->get_text(selected[0])); - text_view.get_buffer()->erase(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); - text_view.get_buffer()->insert(start_mark->get_iter(), select.first); + if(on_select) + on_select(list_view_text.get_text(selected[0]), hide_window); } if(hide_window) { hide(); - char find_char=select.first.back(); - if(find_char==')' || find_char=='>') { - if(find_char==')') - find_char='('; - else - find_char='<'; - size_t pos=select.first.find(find_char); - if(pos!=std::string::npos) { - auto start_offset=start_mark->get_iter().get_offset()+pos+1; - auto end_offset=start_mark->get_iter().get_offset()+select.first.size()-1; - if(start_offset!=end_offset) - text_view.get_buffer()->select_range(text_view.get_buffer()->get_iter_at_offset(start_offset), text_view.get_buffer()->get_iter_at_offset(end_offset)); - } - } } } @@ -276,8 +260,8 @@ bool CompletionDialog::on_key_release(GdkEventKey* key) { else { auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); if(text.size()>0) { - search_entry->set_text(text); - list_view_text->set_search_entry(*search_entry); + search_entry.set_text(text); + list_view_text.set_search_entry(search_entry); } cursor_changed(); } @@ -300,26 +284,33 @@ bool CompletionDialog::on_key_press(GdkEventKey* key) { } if(key->keyval==GDK_KEY_Shift_L || key->keyval==GDK_KEY_Shift_R || key->keyval==GDK_KEY_Alt_L || key->keyval==GDK_KEY_Alt_R || key->keyval==GDK_KEY_Control_L || key->keyval==GDK_KEY_Control_R || key->keyval==GDK_KEY_Meta_L || key->keyval==GDK_KEY_Meta_R) return false; - if(key->keyval==GDK_KEY_Down) { - auto it=list_view_text->get_selection()->get_selected(); + if(key->keyval==GDK_KEY_Down && list_view_text.get_model()->children().size()>0) { + auto it=list_view_text.get_selection()->get_selected(); if(it) { it++; if(it) { - list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); + list_view_text.set_cursor(list_view_text.get_model()->get_path(it)); } } + else + list_view_text.set_cursor(list_view_text.get_model()->get_path(list_view_text.get_model()->children().begin())); select(false); cursor_changed(); return true; } - if(key->keyval==GDK_KEY_Up) { - auto it=list_view_text->get_selection()->get_selected(); + if(key->keyval==GDK_KEY_Up && list_view_text.get_model()->children().size()>0) { + auto it=list_view_text.get_selection()->get_selected(); if(it) { it--; if(it) { - list_view_text->set_cursor(list_view_text->get_model()->get_path(it)); + list_view_text.set_cursor(list_view_text.get_model()->get_path(it)); } } + else { + auto last_it=list_view_text.get_model()->children().end(); + last_it--; + list_view_text.set_cursor(list_view_text.get_model()->get_path(last_it)); + } select(false); cursor_changed(); return true; diff --git a/juci/selectiondialog.h b/juci/selectiondialog.h index d55d9a3..7d9ec12 100644 --- a/juci/selectiondialog.h +++ b/juci/selectiondialog.h @@ -4,47 +4,44 @@ #include "gtkmm.h" #include "logging.h" #include "tooltips.h" +#include class SelectionDialogBase { public: - SelectionDialogBase(Gtk::TextView& text_view, bool popup); - virtual void init(); //TODO: use constructor instead of init - virtual void append(const std::string& row); + SelectionDialogBase(Gtk::TextView& text_view, Glib::RefPtr start_mark, bool show_search_entry); + ~SelectionDialogBase(); + virtual void add_row(const std::string& row, const std::string& tooltip=""); virtual void show(); virtual void hide(); virtual void move(); - std::map > rows; //TODO: remove, instead add on_select. Also remember to destroy start_mark in destructor std::function on_hide; - bool shown=false; + std::function on_select; Glib::RefPtr start_mark; protected: virtual void resize(); virtual void cursor_changed(); - Gtk::TextView& text_view; + std::unique_ptr window; - std::unique_ptr scrolled_window; - std::unique_ptr list_view_text; - std::unique_ptr search_entry; + Gtk::ScrolledWindow scrolled_window; + Gtk::ListViewText list_view_text; + Gtk::Entry search_entry; + bool show_search_entry; std::unique_ptr tooltips; - int last_selected; -private: - bool popup; + std::unordered_map tooltip_texts; + int last_selected=-1; }; class SelectionDialog : public SelectionDialogBase { public: - SelectionDialog(Gtk::TextView& text_view); - void init() {SelectionDialogBase::init();} + SelectionDialog(Gtk::TextView& text_view, Glib::RefPtr start_mark); void show(); - std::function on_select; }; class CompletionDialog : public SelectionDialogBase { public: - CompletionDialog(Gtk::TextView& text_view); - void init() {SelectionDialogBase::init();} + CompletionDialog(Gtk::TextView& text_view, Glib::RefPtr start_mark); void show(); bool on_key_release(GdkEventKey* key); bool on_key_press(GdkEventKey* key); diff --git a/juci/source.cc b/juci/source.cc index d2c7804..9aead05 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -547,32 +547,28 @@ bool Source::ClangViewParse::on_key_press_event(GdkEventKey* key) { //// ClangViewAutocomplete /// ////////////////////////////// Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path): -Source::ClangViewParse(file_path, project_path), completion_dialog(*this), autocomplete_cancel_starting(false) { - completion_dialog.on_hide=[this](){ - start_reparse(); - }; - +Source::ClangViewParse(file_path, project_path), autocomplete_cancel_starting(false) { get_buffer()->signal_changed().connect([this](){ - if(completion_dialog.shown) + if(completion_dialog_shown) delayed_reparse_connection.disconnect(); start_autocomplete(); }); get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr& mark){ if(mark->get_name()=="insert") { autocomplete_cancel_starting=true; - if(completion_dialog.shown) { - completion_dialog.hide(); + if(completion_dialog_shown) { + completion_dialog->hide(); } } }); signal_scroll_event().connect([this](GdkEventScroll* event){ - if(completion_dialog.shown) - completion_dialog.hide(); + if(completion_dialog_shown) + completion_dialog->hide(); return false; }, false); signal_key_release_event().connect([this](GdkEventKey* key){ - if(completion_dialog.shown) { - if(completion_dialog.on_key_release(key)) + if(completion_dialog_shown) { + if(completion_dialog->on_key_release(key)) return true; } @@ -582,16 +578,16 @@ Source::ClangViewParse(file_path, project_path), completion_dialog(*this), autoc bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) { last_keyval=key->keyval; - if(completion_dialog.shown) { - if(completion_dialog.on_key_press(key)) + if(completion_dialog_shown) { + if(completion_dialog->on_key_press(key)) return true; } return ClangViewParse::on_key_press_event(key); } bool Source::ClangViewAutocomplete::on_focus_out_event(GdkEventFocus* event) { - if(completion_dialog.shown) { - completion_dialog.hide(); + if(completion_dialog_shown) { + completion_dialog->hide(); } return Source::ClangViewParse::on_focus_out_event(event); @@ -613,7 +609,7 @@ void Source::ClangViewAutocomplete::start_autocomplete() { prefix_mutex.lock(); prefix=sm[3].str(); prefix_mutex.unlock(); - if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !completion_dialog.shown) { + if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !completion_dialog_shown) { autocomplete(); } else if(last_keyval=='.' && autocomplete_starting) @@ -623,13 +619,13 @@ void Source::ClangViewAutocomplete::start_autocomplete() { prefix_mutex.lock(); prefix=sm[3].str(); prefix_mutex.unlock(); - if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !completion_dialog.shown) { + if((prefix.size()==0 || prefix[0]<'0' || prefix[0]>'9') && !autocomplete_starting && !completion_dialog_shown) { autocomplete(); } } else autocomplete_cancel_starting=true; - if(autocomplete_starting || completion_dialog.shown) + if(autocomplete_starting || completion_dialog_shown) delayed_reparse_connection.disconnect(); } } @@ -644,15 +640,15 @@ void Source::ClangViewAutocomplete::autocomplete() { autocomplete_done_connection=autocomplete_done.connect([this, ac_data](){ autocomplete_starting=false; if(!autocomplete_cancel_starting) { - if(completion_dialog.start_mark) - get_buffer()->delete_mark(completion_dialog.start_mark); auto start_iter=get_buffer()->get_insert()->get_iter(); for(size_t c=0;ccreate_mark(start_iter); - - std::map > rows; - completion_dialog.init(); + completion_dialog=std::unique_ptr(new CompletionDialog(*this, get_buffer()->create_mark(start_iter))); + completion_dialog->on_hide=[this](){ + start_reparse(); + completion_dialog_shown=false; + }; + auto rows=std::make_shared >(); for (auto &data : *ac_data) { std::stringstream ss; std::string return_value; @@ -667,17 +663,37 @@ void Source::ClangViewAutocomplete::autocomplete() { } auto ss_str=ss.str(); if (ss_str.length() > 0) { // if length is 0 the result is empty - auto pair=std::pair(ss_str, data.brief_comments); - rows[ss.str() + " --> " + return_value] = pair; - completion_dialog.append(ss.str() + " --> " + return_value); + (*rows)[ss.str() + " --> " + return_value] = ss_str; + completion_dialog->add_row(ss.str() + " --> " + return_value, data.brief_comments); } } - if (rows.empty()) { - rows["No suggestions found..."] = std::pair(); - completion_dialog.append("No suggestions found..."); + if (rows->empty()) { + (*rows)["No suggestions found..."] = ""; + completion_dialog->add_row("No suggestions found..."); } - completion_dialog.rows=std::move(rows); - completion_dialog.show(); + completion_dialog->on_select=[this, rows](const std::string& selected, bool finished) { + auto row = rows->at(selected); + get_buffer()->erase(completion_dialog->start_mark->get_iter(), get_buffer()->get_insert()->get_iter()); + get_buffer()->insert(completion_dialog->start_mark->get_iter(), row); + if(finished) { + char find_char=row.back(); + if(find_char==')' || find_char=='>') { + if(find_char==')') + find_char='('; + else + find_char='<'; + size_t pos=row.find(find_char); + if(pos!=std::string::npos) { + auto start_offset=completion_dialog->start_mark->get_iter().get_offset()+pos+1; + auto end_offset=completion_dialog->start_mark->get_iter().get_offset()+row.size()-1; + if(start_offset!=end_offset) + get_buffer()->select_range(get_buffer()->get_iter_at_offset(start_offset), get_buffer()->get_iter_at_offset(end_offset)); + } + } + } + }; + completion_dialog_shown=true; + completion_dialog->show(); } else start_autocomplete(); @@ -743,7 +759,7 @@ get_autocomplete_suggestions(int line_number, int column, std::mapcreate_tag(); similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD; @@ -809,26 +825,22 @@ Source::ClangViewAutocomplete(file_path, project_path), selection_dialog(*this) goto_method=[this](){ if(clang_readable) { - if(selection_dialog.start_mark) - get_buffer()->delete_mark(selection_dialog.start_mark); - selection_dialog.start_mark=get_buffer()->create_mark(get_buffer()->get_insert()->get_iter()); - std::map > rows; - selection_dialog.init(); + selection_dialog=std::unique_ptr(new SelectionDialog(*this, get_buffer()->create_mark(get_buffer()->get_insert()->get_iter()))); + auto rows=std::make_shared >(); auto methods=clang_tokens->get_cxx_methods(); if(methods.size()==0) return; for(auto &method: methods) { - rows[method.first]=std::pair(std::to_string(method.second), ""); - selection_dialog.append(method.first); + (*rows)[method.first]=std::to_string(method.second); + selection_dialog->add_row(method.first); } - selection_dialog.rows=std::move(rows); - selection_dialog.on_select=[this](std::string selected) { - auto offset=stoul(selected); + selection_dialog->on_select=[this, rows](const std::string& selected, bool finished) { + auto offset=stoul(rows->at(selected)); get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(offset)); scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5); delayed_tooltips_connection.disconnect(); }; - selection_dialog.show(); + selection_dialog->show(); } }; } diff --git a/juci/source.h b/juci/source.h index 6a2c75b..f96d245 100644 --- a/juci/source.h +++ b/juci/source.h @@ -120,7 +120,8 @@ public: private: void start_autocomplete(); void autocomplete(); - CompletionDialog completion_dialog; + std::unique_ptr completion_dialog; + bool completion_dialog_shown=false; std::vector get_autocomplete_suggestions(int line_number, int column, std::map& buffer_map); Glib::Dispatcher autocomplete_done; sigc::connection autocomplete_done_connection; @@ -137,7 +138,7 @@ public: private: Glib::RefPtr similar_tokens_tag; std::string last_similar_tokens_tagged; - SelectionDialog selection_dialog; + std::unique_ptr selection_dialog; }; class ClangView : public ClangViewRefactor {