Browse Source

selectiondialog.* cleanup.

merge-requests/365/head
eidheim 11 years ago
parent
commit
cd28f0cf5c
  1. 217
      juci/selectiondialog.cc
  2. 31
      juci/selectiondialog.h
  3. 102
      juci/source.cc
  4. 5
      juci/source.h

217
juci/selectiondialog.cc

@ -5,67 +5,63 @@ namespace sigc {
SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
} }
SelectionDialogBase::SelectionDialogBase(Gtk::TextView& text_view, bool popup): text_view(text_view), popup(popup) {} SelectionDialogBase::SelectionDialogBase(Gtk::TextView& text_view, Glib::RefPtr<Gtk::TextBuffer::Mark> 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) {
void SelectionDialogBase::init() { if(!show_search_entry)
if(popup)
window=std::unique_ptr<Gtk::Window>(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP)); window=std::unique_ptr<Gtk::Window>(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP));
else else
window=std::unique_ptr<Gtk::Dialog>(new Gtk::Dialog()); window=std::unique_ptr<Gtk::Dialog>(new Gtk::Dialog());
scrolled_window=std::unique_ptr<Gtk::ScrolledWindow>(new Gtk::ScrolledWindow()); list_view_text.set_search_entry(search_entry);
list_view_text=std::unique_ptr<Gtk::ListViewText>(new Gtk::ListViewText(1, false, Gtk::SelectionMode::SELECTION_BROWSE));
search_entry=std::unique_ptr<Gtk::Entry>(new Gtk::Entry());
list_view_text->set_search_entry(*search_entry);
window->set_default_size(0, 0); window->set_default_size(0, 0);
window->property_decorated()=false; window->property_decorated()=false;
window->set_skip_taskbar_hint(true); window->set_skip_taskbar_hint(true);
scrolled_window->set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, Gtk::PolicyType::POLICY_AUTOMATIC); scrolled_window.set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, Gtk::PolicyType::POLICY_AUTOMATIC);
list_view_text->set_enable_search(true); list_view_text.set_enable_search(true);
list_view_text->set_headers_visible(false); list_view_text.set_headers_visible(false);
list_view_text->set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL); list_view_text.set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL);
list_view_text->set_activate_on_single_click(true); list_view_text.set_activate_on_single_click(true);
list_view_text->set_hover_selection(false); list_view_text.set_hover_selection(false);
list_view_text->set_rules_hint(true); 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.set_fixed_height_mode(true); //TODO: This is buggy on OS X, remember to post an issue on GTK+ 3
last_selected=-1;
list_view_text->signal_cursor_changed().connect(sigc::mem_fun(*this, &SelectionDialog::cursor_changed), true); 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_realize().connect([this](){
resize(); 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) { void SelectionDialogBase::add_row(const std::string& row, const std::string& tooltip) {
list_view_text->append(row); list_view_text.append(row);
if(tooltip.size()>0)
tooltip_texts[row]=tooltip;
} }
void SelectionDialogBase::show() { void SelectionDialogBase::show() {
scrolled_window->add(*list_view_text); if(list_view_text.get_model()->children().size()>0) {
if(popup) list_view_text.set_cursor(list_view_text.get_model()->get_path(list_view_text.get_model()->children().begin()));
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]);
} }
move(); move();
window->show_all(); window->show_all();
search_entry->show(); search_entry.show();
shown=true;
} }
void SelectionDialogBase::hide() { void SelectionDialogBase::hide() {
shown=false;
window->hide(); window->hide();
if(tooltips) if(tooltips)
tooltips->hide(); tooltips->hide();
@ -74,23 +70,25 @@ void SelectionDialogBase::hide() {
} }
void SelectionDialogBase::cursor_changed() { void SelectionDialogBase::cursor_changed() {
auto selected=list_view_text->get_selected(); auto selected=list_view_text.get_selected();
if(selected.size()>0) { if(selected.size()>0) {
if(selected[0]!=last_selected || last_selected==-1) { if(selected[0]!=last_selected || last_selected==-1) {
if(tooltips) if(tooltips)
tooltips->hide(); tooltips->hide();
auto row = rows.at(list_view_text->get_text(selected[0])); auto it=tooltip_texts.find(list_view_text.get_text(selected[0]));
if(row.second.size()>0) { if(it!=tooltip_texts.end()) {
tooltips=std::unique_ptr<Tooltips>(new Tooltips()); auto tooltip_text=it->second;
auto tooltip_text=row.second; if(tooltip_text.size()>0) {
auto get_tooltip_buffer=[this, tooltip_text]() { tooltips=std::unique_ptr<Tooltips>(new Tooltips());
auto tooltip_buffer=Gtk::TextBuffer::create(text_view.get_buffer()->get_tag_table()); auto get_tooltip_buffer=[this, tooltip_text]() {
//TODO: Insert newlines to tooltip_text (use 80 chars, then newline?) auto tooltip_buffer=Gtk::TextBuffer::create(text_view.get_buffer()->get_tag_table());
tooltip_buffer->insert_at_cursor(tooltip_text); //TODO: Insert newlines to tooltip_text (use 80 chars, then newline?)
return tooltip_buffer; 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); 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() { void SelectionDialogBase::resize() {
INFO("SelectionDialog set size"); INFO("SelectionDialog set size");
if(list_view_text->get_realized()) { if(list_view_text.get_realized()) {
int row_width=0, row_height; int row_width=0, row_height;
Gdk::Rectangle rect; 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_width=rect.get_width();
row_height=rect.get_height(); row_height=rect.get_height();
@ -131,21 +129,21 @@ void SelectionDialogBase::resize() {
if(row_width>text_view.get_width()/2) if(row_width>text_view.get_width()/2)
row_width=text_view.get_width()/2; row_width=text_view.get_width()/2;
else 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); int window_height=std::min(row_height*(int)list_view_text.get_model()->children().size(), row_height*10);
if(!popup) if(show_search_entry)
window_height+=search_entry->get_height(); window_height+=search_entry.get_height();
window->resize(row_width, window_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<Gtk::TextBuffer::Mark> start_mark) : SelectionDialogBase(text_view, start_mark, true) {}
void SelectionDialog::show() { void SelectionDialog::show() {
SelectionDialogBase::show(); SelectionDialogBase::show();
std::shared_ptr<std::string> search_key(new std::string()); std::shared_ptr<std::string> 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){ filter_model->set_visible_func([this, search_key](const Gtk::TreeModel::const_iterator& iter){
std::string row_lc; std::string row_lc;
iter->get_value(0, row_lc); iter->get_value(0, row_lc);
@ -156,83 +154,85 @@ void SelectionDialog::show() {
return true; return true;
return false; return false;
}); });
list_view_text->set_model(filter_model); list_view_text.set_model(filter_model);
list_view_text->set_search_equal_func([this](const Glib::RefPtr<Gtk::TreeModel>& model, int column, const Glib::ustring& key, const Gtk::TreeModel::iterator& iter) { list_view_text.set_search_equal_func([this](const Glib::RefPtr<Gtk::TreeModel>& model, int column, const Glib::ustring& key, const Gtk::TreeModel::iterator& iter) {
return false; return false;
}); });
search_entry->signal_changed().connect([this, search_key, filter_model](){ search_entry.signal_changed().connect([this, search_key, filter_model](){
*search_key=search_entry->get_text(); *search_key=search_entry.get_text();
filter_model->refilter(); 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) { if(event->type==GDK_KEY_PRESS) {
auto key=(GdkEventKey*)event; auto key=(GdkEventKey*)event;
if(key->keyval==GDK_KEY_Down) { if(key->keyval==GDK_KEY_Down && list_view_text.get_model()->children().size()>0) {
auto it=list_view_text->get_selection()->get_selected(); auto it=list_view_text.get_selection()->get_selected();
if(it) { if(it) {
it++; it++;
if(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 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; return true;
} }
if(key->keyval==GDK_KEY_Up) { if(key->keyval==GDK_KEY_Up && list_view_text.get_model()->children().size()>0) {
auto it=list_view_text->get_selection()->get_selected(); auto it=list_view_text.get_selection()->get_selected();
if(it) { if(it) {
it--; it--;
if(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 true;
} }
} }
return false; return false;
}); });
auto activate=[this](){ auto activate=[this](){
if(on_select && list_view_text->get_selected().size()>0) { if(on_select && list_view_text.get_selected().size()>0) {
auto it=list_view_text->get_selection()->get_selected(); auto it=list_view_text.get_selection()->get_selected();
std::string row; std::string row;
it->get_value(0, row); it->get_value(0, row);
std::string selected = rows.at(row).first; std::string selected = row;
on_select(selected); on_select(selected, true);
} }
window->hide(); window->hide();
}; };
search_entry->signal_activate().connect([this, activate](){ search_entry.signal_activate().connect([this, activate](){
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(); activate();
}); });
window->signal_focus_out_event().connect([this](GdkEventFocus*){ window->signal_focus_out_event().connect([this](GdkEventFocus*){
window->hide(); window->hide();
return true; 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<Gtk::TextBuffer::Mark> start_mark) : SelectionDialogBase(text_view, start_mark, false) {}
void CompletionDialog::show() { void CompletionDialog::show() {
SelectionDialogBase::show(); SelectionDialogBase::show();
show_offset=text_view.get_buffer()->get_insert()->get_iter().get_offset(); 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*) { list_view_text.signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) {
if(shown) { select();
select();
}
}); });
auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter());
if(text.size()>0) { if(text.size()>0) {
search_entry->set_text(text); search_entry.set_text(text);
list_view_text->set_search_entry(*search_entry); list_view_text.set_search_entry(search_entry);
} }
row_in_entry=false; row_in_entry=false;
@ -240,29 +240,13 @@ void CompletionDialog::show() {
void CompletionDialog::select(bool hide_window) { void CompletionDialog::select(bool hide_window) {
row_in_entry=true; row_in_entry=true;
auto selected=list_view_text->get_selected(); auto selected=list_view_text.get_selected();
std::pair<std::string, std::string> select;
if(selected.size()>0) { if(selected.size()>0) {
select = rows.at(list_view_text->get_text(selected[0])); if(on_select)
text_view.get_buffer()->erase(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); on_select(list_view_text.get_text(selected[0]), hide_window);
text_view.get_buffer()->insert(start_mark->get_iter(), select.first);
} }
if(hide_window) { if(hide_window) {
hide(); 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 { else {
auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter()); auto text=text_view.get_buffer()->get_text(start_mark->get_iter(), text_view.get_buffer()->get_insert()->get_iter());
if(text.size()>0) { if(text.size()>0) {
search_entry->set_text(text); search_entry.set_text(text);
list_view_text->set_search_entry(*search_entry); list_view_text.set_search_entry(search_entry);
} }
cursor_changed(); 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) 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; return false;
if(key->keyval==GDK_KEY_Down) { if(key->keyval==GDK_KEY_Down && list_view_text.get_model()->children().size()>0) {
auto it=list_view_text->get_selection()->get_selected(); auto it=list_view_text.get_selection()->get_selected();
if(it) { if(it) {
it++; it++;
if(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); select(false);
cursor_changed(); cursor_changed();
return true; return true;
} }
if(key->keyval==GDK_KEY_Up) { if(key->keyval==GDK_KEY_Up && list_view_text.get_model()->children().size()>0) {
auto it=list_view_text->get_selection()->get_selected(); auto it=list_view_text.get_selection()->get_selected();
if(it) { if(it) {
it--; it--;
if(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); select(false);
cursor_changed(); cursor_changed();
return true; return true;

31
juci/selectiondialog.h

@ -4,47 +4,44 @@
#include "gtkmm.h" #include "gtkmm.h"
#include "logging.h" #include "logging.h"
#include "tooltips.h" #include "tooltips.h"
#include <unordered_map>
class SelectionDialogBase { class SelectionDialogBase {
public: public:
SelectionDialogBase(Gtk::TextView& text_view, bool popup); SelectionDialogBase(Gtk::TextView& text_view, Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark, bool show_search_entry);
virtual void init(); //TODO: use constructor instead of init ~SelectionDialogBase();
virtual void append(const std::string& row); virtual void add_row(const std::string& row, const std::string& tooltip="");
virtual void show(); virtual void show();
virtual void hide(); virtual void hide();
virtual void move(); virtual void move();
std::map<std::string, std::pair<std::string, std::string> > rows; //TODO: remove, instead add on_select. Also remember to destroy start_mark in destructor
std::function<void()> on_hide; std::function<void()> on_hide;
bool shown=false; std::function<void(const std::string& selected, bool finished)> on_select;
Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark; Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark;
protected: protected:
virtual void resize(); virtual void resize();
virtual void cursor_changed(); virtual void cursor_changed();
Gtk::TextView& text_view; Gtk::TextView& text_view;
std::unique_ptr<Gtk::Window> window; std::unique_ptr<Gtk::Window> window;
std::unique_ptr<Gtk::ScrolledWindow> scrolled_window; Gtk::ScrolledWindow scrolled_window;
std::unique_ptr<Gtk::ListViewText> list_view_text; Gtk::ListViewText list_view_text;
std::unique_ptr<Gtk::Entry> search_entry; Gtk::Entry search_entry;
bool show_search_entry;
std::unique_ptr<Tooltips> tooltips; std::unique_ptr<Tooltips> tooltips;
int last_selected; std::unordered_map<std::string, std::string> tooltip_texts;
private: int last_selected=-1;
bool popup;
}; };
class SelectionDialog : public SelectionDialogBase { class SelectionDialog : public SelectionDialogBase {
public: public:
SelectionDialog(Gtk::TextView& text_view); SelectionDialog(Gtk::TextView& text_view, Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark);
void init() {SelectionDialogBase::init();}
void show(); void show();
std::function<void(std::string selected)> on_select;
}; };
class CompletionDialog : public SelectionDialogBase { class CompletionDialog : public SelectionDialogBase {
public: public:
CompletionDialog(Gtk::TextView& text_view); CompletionDialog(Gtk::TextView& text_view, Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark);
void init() {SelectionDialogBase::init();}
void show(); void show();
bool on_key_release(GdkEventKey* key); bool on_key_release(GdkEventKey* key);
bool on_key_press(GdkEventKey* key); bool on_key_press(GdkEventKey* key);

102
juci/source.cc

@ -547,32 +547,28 @@ bool Source::ClangViewParse::on_key_press_event(GdkEventKey* key) {
//// ClangViewAutocomplete /// //// ClangViewAutocomplete ///
////////////////////////////// //////////////////////////////
Source::ClangViewAutocomplete::ClangViewAutocomplete(const std::string& file_path, const std::string& project_path): 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) { Source::ClangViewParse(file_path, project_path), autocomplete_cancel_starting(false) {
completion_dialog.on_hide=[this](){
start_reparse();
};
get_buffer()->signal_changed().connect([this](){ get_buffer()->signal_changed().connect([this](){
if(completion_dialog.shown) if(completion_dialog_shown)
delayed_reparse_connection.disconnect(); delayed_reparse_connection.disconnect();
start_autocomplete(); start_autocomplete();
}); });
get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark){ get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark){
if(mark->get_name()=="insert") { if(mark->get_name()=="insert") {
autocomplete_cancel_starting=true; autocomplete_cancel_starting=true;
if(completion_dialog.shown) { if(completion_dialog_shown) {
completion_dialog.hide(); completion_dialog->hide();
} }
} }
}); });
signal_scroll_event().connect([this](GdkEventScroll* event){ signal_scroll_event().connect([this](GdkEventScroll* event){
if(completion_dialog.shown) if(completion_dialog_shown)
completion_dialog.hide(); completion_dialog->hide();
return false; return false;
}, false); }, false);
signal_key_release_event().connect([this](GdkEventKey* key){ signal_key_release_event().connect([this](GdkEventKey* key){
if(completion_dialog.shown) { if(completion_dialog_shown) {
if(completion_dialog.on_key_release(key)) if(completion_dialog->on_key_release(key))
return true; 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) { bool Source::ClangViewAutocomplete::on_key_press_event(GdkEventKey *key) {
last_keyval=key->keyval; last_keyval=key->keyval;
if(completion_dialog.shown) { if(completion_dialog_shown) {
if(completion_dialog.on_key_press(key)) if(completion_dialog->on_key_press(key))
return true; return true;
} }
return ClangViewParse::on_key_press_event(key); return ClangViewParse::on_key_press_event(key);
} }
bool Source::ClangViewAutocomplete::on_focus_out_event(GdkEventFocus* event) { bool Source::ClangViewAutocomplete::on_focus_out_event(GdkEventFocus* event) {
if(completion_dialog.shown) { if(completion_dialog_shown) {
completion_dialog.hide(); completion_dialog->hide();
} }
return Source::ClangViewParse::on_focus_out_event(event); return Source::ClangViewParse::on_focus_out_event(event);
@ -613,7 +609,7 @@ void Source::ClangViewAutocomplete::start_autocomplete() {
prefix_mutex.lock(); prefix_mutex.lock();
prefix=sm[3].str(); prefix=sm[3].str();
prefix_mutex.unlock(); 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(); autocomplete();
} }
else if(last_keyval=='.' && autocomplete_starting) else if(last_keyval=='.' && autocomplete_starting)
@ -623,13 +619,13 @@ void Source::ClangViewAutocomplete::start_autocomplete() {
prefix_mutex.lock(); prefix_mutex.lock();
prefix=sm[3].str(); prefix=sm[3].str();
prefix_mutex.unlock(); 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(); autocomplete();
} }
} }
else else
autocomplete_cancel_starting=true; autocomplete_cancel_starting=true;
if(autocomplete_starting || completion_dialog.shown) if(autocomplete_starting || completion_dialog_shown)
delayed_reparse_connection.disconnect(); delayed_reparse_connection.disconnect();
} }
} }
@ -644,15 +640,15 @@ void Source::ClangViewAutocomplete::autocomplete() {
autocomplete_done_connection=autocomplete_done.connect([this, ac_data](){ autocomplete_done_connection=autocomplete_done.connect([this, ac_data](){
autocomplete_starting=false; autocomplete_starting=false;
if(!autocomplete_cancel_starting) { 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(); auto start_iter=get_buffer()->get_insert()->get_iter();
for(size_t c=0;c<prefix.size();c++) for(size_t c=0;c<prefix.size();c++)
start_iter--; start_iter--;
completion_dialog.start_mark=get_buffer()->create_mark(start_iter); completion_dialog=std::unique_ptr<CompletionDialog>(new CompletionDialog(*this, get_buffer()->create_mark(start_iter)));
completion_dialog->on_hide=[this](){
std::map<std::string, std::pair<std::string, std::string> > rows; start_reparse();
completion_dialog.init(); completion_dialog_shown=false;
};
auto rows=std::make_shared<std::unordered_map<std::string, std::string> >();
for (auto &data : *ac_data) { for (auto &data : *ac_data) {
std::stringstream ss; std::stringstream ss;
std::string return_value; std::string return_value;
@ -667,17 +663,37 @@ void Source::ClangViewAutocomplete::autocomplete() {
} }
auto ss_str=ss.str(); auto ss_str=ss.str();
if (ss_str.length() > 0) { // if length is 0 the result is empty if (ss_str.length() > 0) { // if length is 0 the result is empty
auto pair=std::pair<std::string, std::string>(ss_str, data.brief_comments); (*rows)[ss.str() + " --> " + return_value] = ss_str;
rows[ss.str() + " --> " + return_value] = pair; completion_dialog->add_row(ss.str() + " --> " + return_value, data.brief_comments);
completion_dialog.append(ss.str() + " --> " + return_value);
} }
} }
if (rows.empty()) { if (rows->empty()) {
rows["No suggestions found..."] = std::pair<std::string, std::string>(); (*rows)["No suggestions found..."] = "";
completion_dialog.append("No suggestions found..."); completion_dialog->add_row("No suggestions found...");
} }
completion_dialog.rows=std::move(rows); completion_dialog->on_select=[this, rows](const std::string& selected, bool finished) {
completion_dialog.show(); 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 else
start_autocomplete(); start_autocomplete();
@ -743,7 +759,7 @@ get_autocomplete_suggestions(int line_number, int column, std::map<std::string,
//////////////////////////// ////////////////////////////
Source::ClangViewRefactor::ClangViewRefactor(const std::string& file_path, const std::string& project_path): Source::ClangViewRefactor::ClangViewRefactor(const std::string& file_path, const std::string& project_path):
Source::ClangViewAutocomplete(file_path, project_path), selection_dialog(*this) { Source::ClangViewAutocomplete(file_path, project_path) {
similar_tokens_tag=get_buffer()->create_tag(); similar_tokens_tag=get_buffer()->create_tag();
similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD; similar_tokens_tag->property_weight()=Pango::WEIGHT_BOLD;
@ -809,26 +825,22 @@ Source::ClangViewAutocomplete(file_path, project_path), selection_dialog(*this)
goto_method=[this](){ goto_method=[this](){
if(clang_readable) { if(clang_readable) {
if(selection_dialog.start_mark) selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*this, get_buffer()->create_mark(get_buffer()->get_insert()->get_iter())));
get_buffer()->delete_mark(selection_dialog.start_mark); auto rows=std::make_shared<std::unordered_map<std::string, std::string> >();
selection_dialog.start_mark=get_buffer()->create_mark(get_buffer()->get_insert()->get_iter());
std::map<std::string, std::pair<std::string, std::string> > rows;
selection_dialog.init();
auto methods=clang_tokens->get_cxx_methods(); auto methods=clang_tokens->get_cxx_methods();
if(methods.size()==0) if(methods.size()==0)
return; return;
for(auto &method: methods) { for(auto &method: methods) {
rows[method.first]=std::pair<std::string, std::string>(std::to_string(method.second), ""); (*rows)[method.first]=std::to_string(method.second);
selection_dialog.append(method.first); selection_dialog->add_row(method.first);
} }
selection_dialog.rows=std::move(rows); selection_dialog->on_select=[this, rows](const std::string& selected, bool finished) {
selection_dialog.on_select=[this](std::string selected) { auto offset=stoul(rows->at(selected));
auto offset=stoul(selected);
get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(offset)); get_buffer()->place_cursor(get_buffer()->get_iter_at_offset(offset));
scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5); scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5);
delayed_tooltips_connection.disconnect(); delayed_tooltips_connection.disconnect();
}; };
selection_dialog.show(); selection_dialog->show();
} }
}; };
} }

5
juci/source.h

@ -120,7 +120,8 @@ public:
private: private:
void start_autocomplete(); void start_autocomplete();
void autocomplete(); void autocomplete();
CompletionDialog completion_dialog; std::unique_ptr<CompletionDialog> completion_dialog;
bool completion_dialog_shown=false;
std::vector<Source::AutoCompleteData> get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map); std::vector<Source::AutoCompleteData> get_autocomplete_suggestions(int line_number, int column, std::map<std::string, std::string>& buffer_map);
Glib::Dispatcher autocomplete_done; Glib::Dispatcher autocomplete_done;
sigc::connection autocomplete_done_connection; sigc::connection autocomplete_done_connection;
@ -137,7 +138,7 @@ public:
private: private:
Glib::RefPtr<Gtk::TextTag> similar_tokens_tag; Glib::RefPtr<Gtk::TextTag> similar_tokens_tag;
std::string last_similar_tokens_tagged; std::string last_similar_tokens_tagged;
SelectionDialog selection_dialog; std::unique_ptr<SelectionDialog> selection_dialog;
}; };
class ClangView : public ClangViewRefactor { class ClangView : public ClangViewRefactor {

Loading…
Cancel
Save