From 78659e517791f3fe4474e87f86e1511f7879f72c Mon Sep 17 00:00:00 2001 From: eidheim Date: Fri, 29 Nov 2019 11:47:00 +0100 Subject: [PATCH] Cleanup and fixes to dialog and tooltip positioning. Dialogs and tooltips should now not be partially shown outside of screen --- src/project.cc | 31 +++++++++++----------------- src/selection_dialog.cc | 44 ++++++++++++++++++++++++++++------------ src/selection_dialog.h | 4 ++-- src/source_base.cc | 16 --------------- src/source_base.h | 1 - src/source_spellcheck.cc | 2 +- src/tooltips.cc | 21 +++++++++++-------- src/window.cc | 18 ++++++---------- 8 files changed, 65 insertions(+), 72 deletions(-) diff --git a/src/project.cc b/src/project.cc index 06acd8b..4d439ab 100644 --- a/src/project.cc +++ b/src/project.cc @@ -216,10 +216,8 @@ void Project::Base::show_symbols() { } stream->seekg(0, std::ios::beg); - if(view) { - auto dialog_iter = view->get_iter_for_dialog(); - SelectionDialog::create(view, view->get_buffer()->create_mark(dialog_iter), true, true); - } + if(view) + SelectionDialog::create(view, true, true); else SelectionDialog::create(true, true); @@ -512,10 +510,8 @@ void Project::LLDB::debug_backtrace() { auto view = Notebook::get().get_current_view(); auto backtrace = Debug::LLDB::get().get_backtrace(); - if(view) { - auto iter = view->get_iter_for_dialog(); - SelectionDialog::create(view, view->get_buffer()->create_mark(iter), true, true); - } + if(view) + SelectionDialog::create(view, true, true); else SelectionDialog::create(true, true); std::vector rows; @@ -571,11 +567,8 @@ void Project::LLDB::debug_show_variables() { auto view = Notebook::get().get_current_view(); auto variables = Debug::LLDB::get().get_variables(); - Gtk::TextIter iter; - if(view) { - iter = view->get_iter_for_dialog(); - SelectionDialog::create(view, view->get_buffer()->create_mark(iter), true, true); - } + if(view) + SelectionDialog::create(view, true, true); else SelectionDialog::create(true, true); auto rows = std::make_shared>(); @@ -612,7 +605,7 @@ void Project::LLDB::debug_show_variables() { self->debug_variable_tooltips.clear(); }; - SelectionDialog::get()->on_changed = [self = this->shared_from_this(), rows, view, iter](unsigned int index, const std::string &text) { + SelectionDialog::get()->on_changed = [self = this->shared_from_this(), rows, view](unsigned int index, const std::string &text) { if(index >= rows->size()) { self->debug_variable_tooltips.hide(); return; @@ -633,8 +626,10 @@ void Project::LLDB::debug_show_variables() { buffer->insert(buffer->get_insert()->get_iter(), value.substr(0, value.size() - 1)); } }; - if(view) + if(view) { + auto iter = view->get_buffer()->get_insert()->get_iter(); self->debug_variable_tooltips.emplace_back(view, view->get_buffer()->create_mark(iter), view->get_buffer()->create_mark(iter), std::move(set_tooltip_buffer)); + } else self->debug_variable_tooltips.emplace_back(std::move(set_tooltip_buffer)); @@ -697,10 +692,8 @@ void Project::LanguageProtocol::show_symbols() { if(!capabilities.workspace_symbol && !(capabilities.document_symbol && language_protocol_view)) return Base::show_symbols(); - if(view) { - auto dialog_iter = view->get_iter_for_dialog(); - SelectionDialog::create(view, view->get_buffer()->create_mark(dialog_iter), true, true); - } + if(view) + SelectionDialog::create(view, true, true); else SelectionDialog::create(true, true); diff --git a/src/selection_dialog.cc b/src/selection_dialog.cc index 5ef5709..822b226 100644 --- a/src/selection_dialog.cc +++ b/src/selection_dialog.cc @@ -97,26 +97,44 @@ SelectionDialogBase::SelectionDialogBase(Gtk::TextView *text_view, const Glib::R int window_width = row_width + 1; window.resize(window_width, window_height); + auto move_window_to_center = [this, application_window, window_width, window_height] { + int root_x, root_y; + application_window->get_position(root_x, root_y); + root_x += application_window->get_width() / 2 - window_width / 2; + root_y += application_window->get_height() / 2 - window_height / 2; + window.move(root_x, root_y); + }; + if(this->text_view) { - Gdk::Rectangle iter_rect; - this->text_view->get_iter_location(this->start_mark->get_iter(), iter_rect); Gdk::Rectangle visible_rect; this->text_view->get_visible_rect(visible_rect); - int buffer_x = std::max(iter_rect.get_x(), visible_rect.get_x()); + int visible_window_x, visible_window_max_y; + this->text_view->buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, visible_rect.get_x(), visible_rect.get_y() + visible_rect.get_height(), visible_window_x, visible_window_max_y); + + Gdk::Rectangle iter_rect; + this->text_view->get_iter_location(this->start_mark->get_iter(), iter_rect); + int buffer_x = iter_rect.get_x(); int buffer_y = iter_rect.get_y() + iter_rect.get_height(); int window_x, window_y; this->text_view->buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, buffer_x, buffer_y, window_x, window_y); - int root_x, root_y; - this->text_view->get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(window_x, window_y, root_x, root_y); - window.move(root_x, root_y + 1); //TODO: replace 1 with some margin - } - else { - int root_x, root_y; - application_window->get_position(root_x, root_y); - root_x += application_window->get_width() / 2 - window_width / 2; - root_y += application_window->get_height() / 2 - window_height / 2; - window.move(root_x, root_y); + + if(window_y < 0 || window_y > visible_window_max_y) // Move dialog to center if it is above or below visible parts of text_view + move_window_to_center(); + else { + window_x = std::max(window_x, visible_window_x); // Adjust right if dialog is left of text_view + + int root_x, root_y; + this->text_view->get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(window_x, window_y, root_x, root_y); + + // Adjust left if dialog is right of screen + auto screen_width = Gdk::Screen::get_default()->get_width(); + root_x = root_x + window_width > screen_width ? screen_width - window_width : root_x; + + window.move(root_x, root_y + 1); //TODO: replace 1 with some margin + } } + else + move_window_to_center(); }); list_view_text.signal_cursor_changed().connect([this] { diff --git a/src/selection_dialog.h b/src/selection_dialog.h index 7a7efbb..8384552 100644 --- a/src/selection_dialog.h +++ b/src/selection_dialog.h @@ -75,8 +75,8 @@ class SelectionDialog : public SelectionDialogBase { public: bool on_key_press(GdkEventKey *key); - static void create(Gtk::TextView *text_view, const Glib::RefPtr &start_mark, bool show_search_entry = true, bool use_markup = false) { - instance = std::unique_ptr(new SelectionDialog(text_view, start_mark, show_search_entry, use_markup)); + static void create(Gtk::TextView *text_view, bool show_search_entry = true, bool use_markup = false) { + instance = std::unique_ptr(new SelectionDialog(text_view, text_view->get_buffer()->create_mark(text_view->get_buffer()->get_insert()->get_iter()), show_search_entry, use_markup)); } static void create(bool show_search_entry = true, bool use_markup = false) { instance = std::unique_ptr(new SelectionDialog(nullptr, Glib::RefPtr(), show_search_entry, use_markup)); diff --git a/src/source_base.cc b/src/source_base.cc index 023f688..599b501 100644 --- a/src/source_base.cc +++ b/src/source_base.cc @@ -511,22 +511,6 @@ Gtk::TextIter Source::BaseView::get_iter_at_line_end(int line_nr) { } } -Gtk::TextIter Source::BaseView::get_iter_for_dialog() { - auto iter = get_buffer()->get_insert()->get_iter(); - Gdk::Rectangle visible_rect; - get_visible_rect(visible_rect); - Gdk::Rectangle iter_rect; - get_iter_location(iter, iter_rect); - iter_rect.set_width(1); - if(iter.get_line_offset() >= 80) { - get_iter_at_location(iter, visible_rect.get_x(), iter_rect.get_y()); - get_iter_location(iter, iter_rect); - } - if(!visible_rect.intersects(iter_rect)) - get_iter_at_location(iter, visible_rect.get_x(), visible_rect.get_y() + visible_rect.get_height() / 3); - return iter; -} - void Source::BaseView::place_cursor_at_line_pos(int line, int pos) { get_buffer()->place_cursor(get_iter_at_line_pos(line, pos)); } diff --git a/src/source_base.h b/src/source_base.h index 4901086..7d416f9 100644 --- a/src/source_base.h +++ b/src/source_base.h @@ -43,7 +43,6 @@ namespace Source { Gtk::TextIter get_iter_at_line_index(int line, int index); Gtk::TextIter get_iter_at_line_end(int line_nr); - Gtk::TextIter get_iter_for_dialog(); /// Safely places cursor at line using get_iter_at_line_pos. void place_cursor_at_line_pos(int line, int pos); diff --git a/src/source_spellcheck.cc b/src/source_spellcheck.cc index 18c648d..16f0e24 100644 --- a/src/source_spellcheck.cc +++ b/src/source_spellcheck.cc @@ -154,7 +154,7 @@ Source::SpellCheckView::SpellCheckView(const boost::filesystem::path &file_path, delayed_spellcheck_suggestions_connection.disconnect(); delayed_spellcheck_suggestions_connection = Glib::signal_timeout().connect([this]() { if(get_buffer()->get_insert()->get_iter().has_tag(spellcheck_error_tag)) { - SelectionDialog::create(this, get_buffer()->create_mark(get_buffer()->get_insert()->get_iter()), false); + SelectionDialog::create(this, false); auto word = get_word(get_buffer()->get_insert()->get_iter()); if(*word.first == '\'' && word.second.get_offset() - word.first.get_offset() >= 3) { auto before_end = word.second; diff --git a/src/tooltips.cc b/src/tooltips.cc index a84af9e..21a1451 100644 --- a/src/tooltips.cc +++ b/src/tooltips.cc @@ -185,20 +185,25 @@ void Tooltip::show(bool disregard_drawn, const std::function &on_motion) int root_x = 0, root_y = 0; if(text_view) { - //Adjust if tooltip is left of text_view Gdk::Rectangle visible_rect; text_view->get_visible_rect(visible_rect); - int visible_x, visible_y; - text_view->buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, visible_rect.get_x(), visible_rect.get_y(), visible_x, visible_y); - auto activation_rectangle_x = std::max(activation_rectangle.get_x(), visible_x); + int visible_window_x, visible_window_y; + text_view->buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, visible_rect.get_x(), visible_rect.get_y(), visible_window_x, visible_window_y); - text_view->get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(activation_rectangle_x, activation_rectangle.get_y(), root_x, root_y); + auto window_x = std::max(activation_rectangle.get_x(), visible_window_x); // Adjust tooltip right if it is left of text_view + auto window_y = activation_rectangle.get_y(); + text_view->get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(window_x, window_y, root_x, root_y); root_x -= 3; // -1xpadding + if(root_y < size.second) - root_x += visible_rect.get_width() * 0.1; + root_x += visible_rect.get_width() * 0.1; // Adjust tooltip right if it might be above cursor + rectangle.set_y(std::max(0, root_y - size.second)); // Move tooptip down if it is above screen + + // Move tooltip left if it is right of screen + auto screen_width = Gdk::Screen::get_default()->get_width(); + rectangle.set_x(root_x + size.first > screen_width ? screen_width - size.first : root_x); } - rectangle.set_x(root_x); - rectangle.set_y(std::max(0, root_y - size.second)); + rectangle.set_width(size.first); rectangle.set_height(size.second); diff --git a/src/window.cc b/src/window.cc index c7c9dc9..9c51aaf 100644 --- a/src/window.cc +++ b/src/window.cc @@ -769,10 +769,8 @@ void Window::set_menu_actions() { debug_path = build->get_debug_path(); } - if(view) { - auto dialog_iter = view->get_iter_for_dialog(); - SelectionDialog::create(view, view->get_buffer()->create_mark(dialog_iter), true, true); - } + if(view) + SelectionDialog::create(view, true, true); else SelectionDialog::create(true, true); @@ -919,8 +917,7 @@ void Window::set_menu_actions() { }); auto goto_selected_location = [](Source::View *view, const std::vector &locations) { if(!locations.empty()) { - auto dialog_iter = view->get_iter_for_dialog(); - SelectionDialog::create(view, view->get_buffer()->create_mark(dialog_iter), true, true); + SelectionDialog::create(view, true, true); std::vector rows; auto project_path = Project::Build::create(view->file_path)->project_path; if(project_path.empty()) { @@ -983,8 +980,7 @@ void Window::set_menu_actions() { if(view->get_usages) { auto usages = view->get_usages(); if(!usages.empty()) { - auto dialog_iter = view->get_iter_for_dialog(); - SelectionDialog::create(view, view->get_buffer()->create_mark(dialog_iter), true, true); + SelectionDialog::create(view, true, true); std::vector rows; auto iter = view->get_buffer()->get_insert()->get_iter(); @@ -1031,8 +1027,7 @@ void Window::set_menu_actions() { if(view->get_methods) { auto methods = Notebook::get().get_current_view()->get_methods(); if(!methods.empty()) { - auto dialog_iter = view->get_iter_for_dialog(); - SelectionDialog::create(view, view->get_buffer()->create_mark(dialog_iter), true, true); + SelectionDialog::create(view, true, true); std::vector rows; auto iter = view->get_buffer()->get_insert()->get_iter(); for(auto &method : methods) { @@ -1336,8 +1331,7 @@ void Window::set_menu_actions() { return; } - auto dialog_iter = current_view->get_iter_for_dialog(); - SelectionDialog::create(current_view, current_view->get_buffer()->create_mark(dialog_iter), true); + SelectionDialog::create(current_view, true); std::vector rows;