Browse Source

Made new selectiondialog for code-completion. Might be in need of some smaller fixes. Max width set to halv of width of sourceview.

merge-requests/365/head
eidheim 11 years ago
parent
commit
54a1e7c90d
  1. 237
      juci/selectiondialog.cc
  2. 23
      juci/selectiondialog.h
  3. 27
      juci/source.cc
  4. 2
      juci/source.h

237
juci/selectiondialog.cc

@ -1,87 +1,180 @@
#include "selectiondialog.h" #include "selectiondialog.h"
#include <iostream>
using namespace std;
SelectionDialog::SelectionDialog(Gtk::TextView& text_view): text_view(text_view) {
SelectionDialog::SelectionDialog(Gtk::TextView& text_view): Gtk::Dialog(), text_view(text_view),
list_view_text(1, false, Gtk::SelectionMode::SELECTION_SINGLE) {
property_decorated()=false;
set_skip_taskbar_hint(true);
scrolled_window.set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_NEVER);
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);
} }
void SelectionDialog::show(const std::map<std::string, std::string>& rows) { void SelectionDialog::show() {
for (auto &i : rows) { if(rows.size()==0)
list_view_text.append(i.first); return;
}
scrolled_window.add(list_view_text); window=std::unique_ptr<Gtk::Window>(new Gtk::Window(Gtk::WindowType::WINDOW_POPUP));
get_vbox()->pack_start(scrolled_window); scrolled_window=std::unique_ptr<Gtk::ScrolledWindow>(new Gtk::ScrolledWindow());
set_transient_for((Gtk::Window&)(*text_view.get_toplevel())); list_view_text=std::unique_ptr<Gtk::ListViewText>(new Gtk::ListViewText(1, false, Gtk::SelectionMode::SELECTION_SINGLE));
show_all();
int popup_x = get_width(); window->set_default_size(0, 0);
int popup_y = rows.size() * 20; window->property_decorated()=false;
adjust(popup_x, popup_y); window->set_skip_taskbar_hint(true);
scrolled_window->set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, Gtk::PolicyType::POLICY_AUTOMATIC);
list_view_text.signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) { list_view_text->set_enable_search(true);
if(on_select) list_view_text->set_headers_visible(false);
on_select(list_view_text); list_view_text->set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL);
response(Gtk::RESPONSE_DELETE_EVENT); list_view_text->set_activate_on_single_click(true);
list_view_text->set_search_entry(search_entry);
list_view_text->set_hover_selection(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->signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn*) {
if(shown) {
select();
}
}); });
list_view_text->signal_realize().connect([this](){
resize();
});
if(start_mark)
text_view.get_buffer()->delete_mark(start_mark);
start_mark=text_view.get_buffer()->create_mark(text_view.get_buffer()->get_insert()->get_iter());
start_offset=start_mark->get_iter().get_offset();
list_view_text->clear_items();
for (auto &i : rows) {
list_view_text->append(i.first);
}
signal_focus_out_event().connect(sigc::mem_fun(*this, &SelectionDialog::close), false); scrolled_window->add(*list_view_text);
window->add(*scrolled_window);
run(); 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]);
} }
bool SelectionDialog::close(GdkEventFocus*) { move();
response(Gtk::RESPONSE_DELETE_EVENT);
return true; window->show_all();
shown=true;
} }
void SelectionDialog::adjust(int current_x, int current_y) { void SelectionDialog::hide() {
INFO("SelectionDialog set size"); window->hide();
int view_x = text_view.get_width(); shown=false;
int view_y = 150; }
bool is_never_scroll_x = true;
bool is_never_scroll_y = true; void SelectionDialog::select(bool hide_window) {
if (current_x > view_x) { auto selected=list_view_text->get_selected();
current_x = view_x; if(selected.size()>0) {
is_never_scroll_x = false; std::string 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());
if (current_y > view_y) { text_view.get_buffer()->insert(start_mark->get_iter(), select);
current_y = view_y; }
is_never_scroll_y = false; if(hide_window) {
} hide();
scrolled_window.set_size_request(current_x, current_y); }
if (!is_never_scroll_x && !is_never_scroll_y) { }
scrolled_window.set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, Gtk::PolicyType::POLICY_AUTOMATIC);
} else if (!is_never_scroll_x && is_never_scroll_y) { bool SelectionDialog::on_key_release(GdkEventKey* key) {
scrolled_window.set_policy(Gtk::PolicyType::POLICY_AUTOMATIC, Gtk::PolicyType::POLICY_NEVER); if(key->keyval==GDK_KEY_Down || key->keyval==GDK_KEY_Up)
} else if (is_never_scroll_x && !is_never_scroll_y) { return false;
scrolled_window.set_policy(Gtk::PolicyType::POLICY_NEVER, Gtk::PolicyType::POLICY_AUTOMATIC);
if(start_offset>text_view.get_buffer()->get_insert()->get_iter().get_offset()) {
hide();
}
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);
}
}
return false;
} }
bool SelectionDialog::on_key_press(GdkEventKey* key) {
if(key->keyval>=GDK_KEY_0 && key->keyval<=GDK_KEY_9)
return false;
if(key->keyval>=GDK_KEY_A && key->keyval<=GDK_KEY_Z)
return false;
if(key->keyval>=GDK_KEY_a && key->keyval<=GDK_KEY_z)
return false;
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_underscore)
return false;
if(key->keyval==GDK_KEY_BackSpace)
return false;
if(key->keyval==GDK_KEY_Down) {
auto it=list_view_text->get_selection()->get_selected();
if(it) {
it++;
if(it) {
list_view_text->get_selection()->select(it);
list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]);
}
}
select(false);
return true;
}
if(key->keyval==GDK_KEY_Up) {
auto it=list_view_text->get_selection()->get_selected();
if(it) {
it--;
if(it) {
list_view_text->get_selection()->select(it);
list_view_text->scroll_to_row(list_view_text->get_selection()->get_selected_rows()[0]);
}
}
select(false);
return true;
}
if(key->keyval==GDK_KEY_Return) {
select();
return true;
}
if(key->keyval==GDK_KEY_ISO_Left_Tab || key->keyval==GDK_KEY_Tab) {
select();
return true;
}
hide();
return false;
}
void SelectionDialog::move() {
INFO("SelectionDialog set position"); INFO("SelectionDialog set position");
Gdk::Rectangle temp1, temp2; Gdk::Rectangle rectangle;
text_view.get_cursor_locations(text_view.get_buffer()->get_insert()->get_iter(), temp1, temp2); text_view.get_iter_location(start_mark->get_iter(), rectangle);
int view_edge_x = 0; int buffer_x=rectangle.get_x();
int view_edge_y = 0; int buffer_y=rectangle.get_y()+rectangle.get_height();
int x, y; int window_x, window_y;
text_view.buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_WIDGET, text_view.buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, buffer_x, buffer_y, window_x, window_y);
temp1.get_x(), temp1.get_y(), x, y); int root_x, root_y;
Glib::RefPtr<Gdk::Window> gdkw = text_view.get_window(Gtk::TextWindowType::TEXT_WINDOW_WIDGET); text_view.get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(window_x, window_y, root_x, root_y);
gdkw->get_origin(view_edge_x, view_edge_y); window->move(root_x, root_y+1); //TODO: replace 1 with some margin
}
x += view_edge_x;
y += view_edge_y; void SelectionDialog::resize() {
if ((view_edge_x-x)*-1 > text_view.get_width()-current_x) { INFO("SelectionDialog set size");
x -= current_x;
if (x < view_edge_x) x = view_edge_x; if(list_view_text->get_realized()) {
} int row_width=0, row_height;
if ((view_edge_y-y)*-1 > text_view.get_height()-current_y) { Gdk::Rectangle rect;
y -= (current_y+14) + 15; 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);
if (x < view_edge_y) y = view_edge_y +15; row_width=rect.get_width();
} row_height=rect.get_height();
move(x, y+15);
row_width+=rect.get_x()*2; //TODO: Add correct margin x and y
row_height+=rect.get_y()*2;
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);
int window_height=std::min(row_height*(int)rows.size(), row_height*10);
window->resize(row_width, window_height);
}
} }

23
juci/selectiondialog.h

@ -3,22 +3,31 @@
#include "gtkmm.h" #include "gtkmm.h"
#include "logging.h" #include "logging.h"
#include "source.h"
class SelectionDialog : public Gtk::Dialog { class SelectionDialog {
public: public:
SelectionDialog(Gtk::TextView& text_view); SelectionDialog(Gtk::TextView& text_view);
void show(const std::map<std::string, std::string>& rows); void show();
void hide();
bool close(GdkEventFocus*); bool close(GdkEventFocus*);
void select(bool hide_window=true);
void move();
bool on_key_release(GdkEventKey* key);
bool on_key_press(GdkEventKey* key);
std::function<void(Gtk::ListViewText& list_view_text)> on_select; std::map<std::string, std::string> rows;
bool shown=false;
Gtk::Entry search_entry;
Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark;
int start_offset;
private: private:
void adjust(int current_x, int current_y); void resize();
Gtk::TextView& text_view; Gtk::TextView& text_view;
Gtk::ScrolledWindow scrolled_window; std::unique_ptr<Gtk::Window> window;
Gtk::ListViewText list_view_text; std::unique_ptr<Gtk::ScrolledWindow> scrolled_window;
std::unique_ptr<Gtk::ListViewText> list_view_text;
}; };
#endif // JUCI_SELECTIONDIALOG_H_ #endif // JUCI_SELECTIONDIALOG_H_

27
juci/source.cc

@ -6,7 +6,6 @@
#include "logging.h" #include "logging.h"
#include <algorithm> #include <algorithm>
#include <regex> #include <regex>
#include "selectiondialog.h"
#include "singletons.h" #include "singletons.h"
namespace sigc { namespace sigc {
@ -147,7 +146,7 @@ bool Source::View::on_key_press(GdkEventKey* key) {
clang::Index Source::ClangView::clang_index(0, 0); clang::Index Source::ClangView::clang_index(0, 0);
Source::ClangView::ClangView(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal): Source::ClangView::ClangView(const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal):
Source::View(file_path, project_path), terminal(terminal), Source::View(file_path, project_path), terminal(terminal), selection_dialog(*this),
parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) {
int start_offset = get_source_buffer()->begin().get_offset(); int start_offset = get_source_buffer()->begin().get_offset();
int end_offset = get_source_buffer()->end().get_offset(); int end_offset = get_source_buffer()->end().get_offset();
@ -443,6 +442,9 @@ bool Source::ClangView::clangview_on_motion_notify_event(GdkEventMotion* event)
void Source::ClangView::clangview_on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark) { void Source::ClangView::clangview_on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark) {
if(mark->get_name()=="insert") { if(mark->get_name()=="insert") {
if(selection_dialog.shown) {
selection_dialog.hide();
}
on_mark_set_timeout_connection.disconnect(); on_mark_set_timeout_connection.disconnect();
on_mark_set_timeout_connection=Glib::signal_timeout().connect([this]() { on_mark_set_timeout_connection=Glib::signal_timeout().connect([this]() {
if(clang_updated) { if(clang_updated) {
@ -472,6 +474,9 @@ bool Source::ClangView::clangview_on_focus_out_event(GdkEventFocus* event) {
} }
bool Source::ClangView::clangview_on_scroll_event(GdkEventScroll* event) { bool Source::ClangView::clangview_on_scroll_event(GdkEventScroll* event) {
if(selection_dialog.shown)
selection_dialog.move();
on_mark_set_timeout_connection.disconnect(); on_mark_set_timeout_connection.disconnect();
type_tooltips.hide(); type_tooltips.hide();
diagnostic_tooltips.hide(); diagnostic_tooltips.hide();
@ -511,6 +516,11 @@ highlight_token(clang::Token *token,
} }
bool Source::ClangView::on_key_release(GdkEventKey* key) { bool Source::ClangView::on_key_release(GdkEventKey* key) {
if(selection_dialog.shown) {
if(selection_dialog.on_key_release(key))
return true;
}
INFO("Source::ClangView::on_key_release getting iters"); INFO("Source::ClangView::on_key_release getting iters");
// Get function to fill popup with suggests item vector under is for testing // Get function to fill popup with suggests item vector under is for testing
Gtk::TextIter beg = get_source_buffer()->get_insert()->get_iter(); Gtk::TextIter beg = get_source_buffer()->get_insert()->get_iter();
@ -569,13 +579,8 @@ bool Source::ClangView::on_key_release(GdkEventKey* key) {
if (rows.empty()) { if (rows.empty()) {
rows["No suggestions found..."] = ""; rows["No suggestions found..."] = "";
} }
selection_dialog.rows=std::move(rows);
SelectionDialog selection_dialog(*this); selection_dialog.show();
selection_dialog.on_select=[this, &rows](Gtk::ListViewText& list_view_text){
std::string selected = rows.at(list_view_text.get_text(list_view_text.get_selected()[0]));
get_source_buffer()->insert_at_cursor(selected);
};
selection_dialog.show(rows);
return true; return true;
} }
@ -583,6 +588,10 @@ bool Source::ClangView::on_key_release(GdkEventKey* key) {
//Clang indentation //Clang indentation
//TODO: replace indentation methods with a better implementation or maybe use libclang //TODO: replace indentation methods with a better implementation or maybe use libclang
bool Source::ClangView::on_key_press(GdkEventKey* key) { bool Source::ClangView::on_key_press(GdkEventKey* key) {
if(selection_dialog.shown) {
if(selection_dialog.on_key_press(key))
return true;
}
auto config=Singletons::Config::source(); auto config=Singletons::Config::source();
const std::regex bracket_regex(std::string("^(")+config->tab_char+"*).*\\{ *$"); const std::regex bracket_regex(std::string("^(")+config->tab_char+"*).*\\{ *$");
const std::regex no_bracket_statement_regex(std::string("^(")+config->tab_char+"*)(if|for|else if|catch|while) *\\(.*[^;}] *$"); const std::regex no_bracket_statement_regex(std::string("^(")+config->tab_char+"*)(if|for|else if|catch|while) *\\(.*[^;}] *$");

2
juci/source.h

@ -12,6 +12,7 @@
#include "gtksourceviewmm.h" #include "gtksourceviewmm.h"
#include "terminal.h" #include "terminal.h"
#include "tooltips.h" #include "tooltips.h"
#include "selectiondialog.h"
namespace Source { namespace Source {
class Config { class Config {
@ -93,6 +94,7 @@ namespace Source {
int end_offset, int end_offset,
clang::Index *index); clang::Index *index);
std::vector<Source::AutoCompleteData> get_autocomplete_suggestions(int line_number, int column); std::vector<Source::AutoCompleteData> get_autocomplete_suggestions(int line_number, int column);
SelectionDialog selection_dialog;
int reparse(const std::map<std::string, std::string> &buffers); int reparse(const std::map<std::string, std::string> &buffers);
std::vector<Range> extract_tokens(int, int); std::vector<Range> extract_tokens(int, int);
void update_syntax(const std::vector<Range> &locations); void update_syntax(const std::vector<Range> &locations);

Loading…
Cancel
Save