diff --git a/src/notebook.cc b/src/notebook.cc index b1877d1..b8a7dda 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -415,6 +415,8 @@ void Notebook::open(const boost::filesystem::path &file_path_, Position position #endif view->signal_focus_in_event().connect([this, view](GdkEventFocus *) { + if(on_focus_page) + on_focus_page(view); set_current_view(view); return false; }); diff --git a/src/notebook.h b/src/notebook.h index f8caea8..4c8db79 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -57,6 +57,7 @@ public: void update_status(Source::BaseView *view); void clear_status(); + std::function on_focus_page; std::function on_change_page; std::function on_close_page; diff --git a/src/source_base.cc b/src/source_base.cc index 3fc14fb..10c1740 100644 --- a/src/source_base.cc +++ b/src/source_base.cc @@ -10,7 +10,119 @@ #include #include -Source::BaseView::BaseView(const boost::filesystem::path &file_path, const Glib::RefPtr &language) : Gsv::View(), file_path(file_path), language(language), status_diagnostics(0, 0, 0) { +Source::SearchView::SearchView() : Gsv::View() { + search_settings = gtk_source_search_settings_new(); + gtk_source_search_settings_set_wrap_around(search_settings, true); + search_context = gtk_source_search_context_new(get_source_buffer()->gobj(), search_settings); + gtk_source_search_context_set_highlight(search_context, true); + g_signal_connect(search_context, "notify::occurrences-count", G_CALLBACK(search_occurrences_updated), this); +} + +Source::SearchView::~SearchView() { + g_clear_object(&search_context); + g_clear_object(&search_settings); +} + +void Source::SearchView::search_highlight(const std::string &text, bool case_sensitive, bool regex) { + gtk_source_search_settings_set_case_sensitive(search_settings, case_sensitive); + gtk_source_search_settings_set_regex_enabled(search_settings, regex); + gtk_source_search_settings_set_search_text(search_settings, text.c_str()); + search_occurrences_updated(nullptr, nullptr, this); +} + +void Source::SearchView::search_forward() { + Gtk::TextIter start, end; + get_buffer()->get_selection_bounds(start, end); + Gtk::TextIter match_start, match_end; +#if defined(GTK_SOURCE_MAJOR_VERSION) && (GTK_SOURCE_MAJOR_VERSION > 3 || (GTK_SOURCE_MAJOR_VERSION == 3 && GTK_SOURCE_MINOR_VERSION >= 22)) + gboolean has_wrapped_around; + if(gtk_source_search_context_forward2(search_context, end.gobj(), match_start.gobj(), match_end.gobj(), &has_wrapped_around)) { + get_buffer()->select_range(match_start, match_end); + scroll_to(get_buffer()->get_insert()); + } +#else + if(gtk_source_search_context_forward(search_context, end.gobj(), match_start.gobj(), match_end.gobj())) { + get_buffer()->select_range(match_start, match_end); + scroll_to(get_buffer()->get_insert()); + } +#endif +} + +void Source::SearchView::search_backward() { + Gtk::TextIter start, end; + get_buffer()->get_selection_bounds(start, end); + Gtk::TextIter match_start, match_end; +#if defined(GTK_SOURCE_MAJOR_VERSION) && (GTK_SOURCE_MAJOR_VERSION > 3 || (GTK_SOURCE_MAJOR_VERSION == 3 && GTK_SOURCE_MINOR_VERSION >= 22)) + gboolean has_wrapped_around; + if(gtk_source_search_context_backward2(search_context, start.gobj(), match_start.gobj(), match_end.gobj(), &has_wrapped_around)) { + get_buffer()->select_range(match_start, match_end); + scroll_to(get_buffer()->get_insert()); + } +#else + if(gtk_source_search_context_backward(search_context, start.gobj(), match_start.gobj(), match_end.gobj())) { + get_buffer()->select_range(match_start, match_end); + scroll_to(get_buffer()->get_insert()); + } +#endif +} + +void Source::SearchView::replace_forward(const std::string &replacement) { + Gtk::TextIter start, end; + get_buffer()->get_selection_bounds(start, end); + Gtk::TextIter match_start, match_end; +#if defined(GTK_SOURCE_MAJOR_VERSION) && (GTK_SOURCE_MAJOR_VERSION > 3 || (GTK_SOURCE_MAJOR_VERSION == 3 && GTK_SOURCE_MINOR_VERSION >= 22)) + gboolean has_wrapped_around; + if(gtk_source_search_context_forward2(search_context, start.gobj(), match_start.gobj(), match_end.gobj(), &has_wrapped_around)) { + auto offset = match_start.get_offset(); + gtk_source_search_context_replace2(search_context, match_start.gobj(), match_end.gobj(), replacement.c_str(), replacement.size(), nullptr); + Glib::ustring replacement_ustring = replacement; + get_buffer()->select_range(get_buffer()->get_iter_at_offset(offset), get_buffer()->get_iter_at_offset(offset + replacement_ustring.size())); + scroll_to(get_buffer()->get_insert()); + } +#else + if(gtk_source_search_context_forward(search_context, start.gobj(), match_start.gobj(), match_end.gobj())) { + auto offset = match_start.get_offset(); + gtk_source_search_context_replace(search_context, match_start.gobj(), match_end.gobj(), replacement.c_str(), replacement.size(), nullptr); + Glib::ustring replacement_ustring = replacement; + get_buffer()->select_range(get_buffer()->get_iter_at_offset(offset), get_buffer()->get_iter_at_offset(offset + replacement_ustring.size())); + scroll_to(get_buffer()->get_insert()); + } +#endif +} + +void Source::SearchView::replace_backward(const std::string &replacement) { + Gtk::TextIter start, end; + get_buffer()->get_selection_bounds(start, end); + Gtk::TextIter match_start, match_end; +#if defined(GTK_SOURCE_MAJOR_VERSION) && (GTK_SOURCE_MAJOR_VERSION > 3 || (GTK_SOURCE_MAJOR_VERSION == 3 && GTK_SOURCE_MINOR_VERSION >= 22)) + gboolean has_wrapped_around; + if(gtk_source_search_context_backward2(search_context, end.gobj(), match_start.gobj(), match_end.gobj(), &has_wrapped_around)) { + auto offset = match_start.get_offset(); + gtk_source_search_context_replace2(search_context, match_start.gobj(), match_end.gobj(), replacement.c_str(), replacement.size(), nullptr); + get_buffer()->select_range(get_buffer()->get_iter_at_offset(offset), get_buffer()->get_iter_at_offset(offset + replacement.size())); + scroll_to(get_buffer()->get_insert()); + } +#else + if(gtk_source_search_context_backward(search_context, end.gobj(), match_start.gobj(), match_end.gobj())) { + auto offset = match_start.get_offset(); + gtk_source_search_context_replace(search_context, match_start.gobj(), match_end.gobj(), replacement.c_str(), replacement.size(), nullptr); + get_buffer()->select_range(get_buffer()->get_iter_at_offset(offset), get_buffer()->get_iter_at_offset(offset + replacement.size())); + scroll_to(get_buffer()->get_insert()); + } +#endif +} + +void Source::SearchView::replace_all(const std::string &replacement) { + gtk_source_search_context_replace_all(search_context, replacement.c_str(), replacement.size(), nullptr); +} + +void Source::SearchView::search_occurrences_updated(GtkWidget *widget, GParamSpec *property, gpointer data) { + auto view = static_cast(data); + if(view->update_search_occurrences) + view->update_search_occurrences(gtk_source_search_context_get_occurrences_count(view->search_context)); +} + +Source::BaseView::BaseView(const boost::filesystem::path &file_path, const Glib::RefPtr &language) : SearchView(), file_path(file_path), language(language), status_diagnostics(0, 0, 0) { get_style_context()->add_class("juci_source_view"); load(true); @@ -59,13 +171,6 @@ Source::BaseView::BaseView(const boost::filesystem::path &file_path, const Glib: #endif - search_settings = gtk_source_search_settings_new(); - gtk_source_search_settings_set_wrap_around(search_settings, true); - search_context = gtk_source_search_context_new(get_source_buffer()->gobj(), search_settings); - gtk_source_search_context_set_highlight(search_context, true); - g_signal_connect(search_context, "notify::occurrences-count", G_CALLBACK(search_occurrences_updated), this); - - set_snippets(); snippet_argument_tag = get_buffer()->create_tag(); @@ -85,9 +190,6 @@ Source::BaseView::BaseView(const boost::filesystem::path &file_path, const Glib: } Source::BaseView::~BaseView() { - g_clear_object(&search_context); - g_clear_object(&search_settings); - monitor_changed_connection.disconnect(); delayed_monitor_changed_connection.disconnect(); } @@ -819,105 +921,6 @@ std::string Source::BaseView::get_selected_text() { return get_buffer()->get_text(start, end); } -void Source::BaseView::search_highlight(const std::string &text, bool case_sensitive, bool regex) { - gtk_source_search_settings_set_case_sensitive(search_settings, case_sensitive); - gtk_source_search_settings_set_regex_enabled(search_settings, regex); - gtk_source_search_settings_set_search_text(search_settings, text.c_str()); - search_occurrences_updated(nullptr, nullptr, this); -} - -void Source::BaseView::search_forward() { - Gtk::TextIter start, end; - get_buffer()->get_selection_bounds(start, end); - Gtk::TextIter match_start, match_end; -#if defined(GTK_SOURCE_MAJOR_VERSION) && (GTK_SOURCE_MAJOR_VERSION > 3 || (GTK_SOURCE_MAJOR_VERSION == 3 && GTK_SOURCE_MINOR_VERSION >= 22)) - gboolean has_wrapped_around; - if(gtk_source_search_context_forward2(search_context, end.gobj(), match_start.gobj(), match_end.gobj(), &has_wrapped_around)) { - get_buffer()->select_range(match_start, match_end); - scroll_to(get_buffer()->get_insert()); - } -#else - if(gtk_source_search_context_forward(search_context, end.gobj(), match_start.gobj(), match_end.gobj())) { - get_buffer()->select_range(match_start, match_end); - scroll_to(get_buffer()->get_insert()); - } -#endif -} - -void Source::BaseView::search_backward() { - Gtk::TextIter start, end; - get_buffer()->get_selection_bounds(start, end); - Gtk::TextIter match_start, match_end; -#if defined(GTK_SOURCE_MAJOR_VERSION) && (GTK_SOURCE_MAJOR_VERSION > 3 || (GTK_SOURCE_MAJOR_VERSION == 3 && GTK_SOURCE_MINOR_VERSION >= 22)) - gboolean has_wrapped_around; - if(gtk_source_search_context_backward2(search_context, start.gobj(), match_start.gobj(), match_end.gobj(), &has_wrapped_around)) { - get_buffer()->select_range(match_start, match_end); - scroll_to(get_buffer()->get_insert()); - } -#else - if(gtk_source_search_context_backward(search_context, start.gobj(), match_start.gobj(), match_end.gobj())) { - get_buffer()->select_range(match_start, match_end); - scroll_to(get_buffer()->get_insert()); - } -#endif -} - -void Source::BaseView::replace_forward(const std::string &replacement) { - Gtk::TextIter start, end; - get_buffer()->get_selection_bounds(start, end); - Gtk::TextIter match_start, match_end; -#if defined(GTK_SOURCE_MAJOR_VERSION) && (GTK_SOURCE_MAJOR_VERSION > 3 || (GTK_SOURCE_MAJOR_VERSION == 3 && GTK_SOURCE_MINOR_VERSION >= 22)) - gboolean has_wrapped_around; - if(gtk_source_search_context_forward2(search_context, start.gobj(), match_start.gobj(), match_end.gobj(), &has_wrapped_around)) { - auto offset = match_start.get_offset(); - gtk_source_search_context_replace2(search_context, match_start.gobj(), match_end.gobj(), replacement.c_str(), replacement.size(), nullptr); - Glib::ustring replacement_ustring = replacement; - get_buffer()->select_range(get_buffer()->get_iter_at_offset(offset), get_buffer()->get_iter_at_offset(offset + replacement_ustring.size())); - scroll_to(get_buffer()->get_insert()); - } -#else - if(gtk_source_search_context_forward(search_context, start.gobj(), match_start.gobj(), match_end.gobj())) { - auto offset = match_start.get_offset(); - gtk_source_search_context_replace(search_context, match_start.gobj(), match_end.gobj(), replacement.c_str(), replacement.size(), nullptr); - Glib::ustring replacement_ustring = replacement; - get_buffer()->select_range(get_buffer()->get_iter_at_offset(offset), get_buffer()->get_iter_at_offset(offset + replacement_ustring.size())); - scroll_to(get_buffer()->get_insert()); - } -#endif -} - -void Source::BaseView::replace_backward(const std::string &replacement) { - Gtk::TextIter start, end; - get_buffer()->get_selection_bounds(start, end); - Gtk::TextIter match_start, match_end; -#if defined(GTK_SOURCE_MAJOR_VERSION) && (GTK_SOURCE_MAJOR_VERSION > 3 || (GTK_SOURCE_MAJOR_VERSION == 3 && GTK_SOURCE_MINOR_VERSION >= 22)) - gboolean has_wrapped_around; - if(gtk_source_search_context_backward2(search_context, end.gobj(), match_start.gobj(), match_end.gobj(), &has_wrapped_around)) { - auto offset = match_start.get_offset(); - gtk_source_search_context_replace2(search_context, match_start.gobj(), match_end.gobj(), replacement.c_str(), replacement.size(), nullptr); - get_buffer()->select_range(get_buffer()->get_iter_at_offset(offset), get_buffer()->get_iter_at_offset(offset + replacement.size())); - scroll_to(get_buffer()->get_insert()); - } -#else - if(gtk_source_search_context_backward(search_context, end.gobj(), match_start.gobj(), match_end.gobj())) { - auto offset = match_start.get_offset(); - gtk_source_search_context_replace(search_context, match_start.gobj(), match_end.gobj(), replacement.c_str(), replacement.size(), nullptr); - get_buffer()->select_range(get_buffer()->get_iter_at_offset(offset), get_buffer()->get_iter_at_offset(offset + replacement.size())); - scroll_to(get_buffer()->get_insert()); - } -#endif -} - -void Source::BaseView::replace_all(const std::string &replacement) { - gtk_source_search_context_replace_all(search_context, replacement.c_str(), replacement.size(), nullptr); -} - -void Source::BaseView::search_occurrences_updated(GtkWidget *widget, GParamSpec *property, gpointer data) { - auto view = static_cast(data); - if(view->update_search_occurrences) - view->update_search_occurrences(gtk_source_search_context_get_occurrences_count(view->search_context)); -} - void Source::BaseView::set_snippets() { LockGuard lock(snippets_mutex); diff --git a/src/source_base.h b/src/source_base.h index 7d416f9..8020fce 100644 --- a/src/source_base.h +++ b/src/source_base.h @@ -10,7 +10,26 @@ #include namespace Source { - class BaseView : public Gsv::View { + class SearchView : public Gsv::View { + public: + SearchView(); + ~SearchView() override; + void search_highlight(const std::string &text, bool case_sensitive, bool regex); + void search_forward(); + void search_backward(); + void replace_forward(const std::string &replacement); + void replace_backward(const std::string &replacement); + void replace_all(const std::string &replacement); + + std::function update_search_occurrences; + + private: + GtkSourceSearchContext *search_context; + GtkSourceSearchSettings *search_settings; + static void search_occurrences_updated(GtkWidget *widget, GParamSpec *property, gpointer data); + }; + + class BaseView : public SearchView { public: BaseView(const boost::filesystem::path &file_path, const Glib::RefPtr &language); ~BaseView() override; @@ -62,7 +81,6 @@ namespace Source { std::string status_state; std::function update_status_branch; std::string status_branch; - std::function update_search_occurrences; void cut(); void cut_line(); @@ -70,22 +88,11 @@ namespace Source { std::string get_selected_text(); - void search_highlight(const std::string &text, bool case_sensitive, bool regex); - void search_forward(); - void search_backward(); - void replace_forward(const std::string &replacement); - void replace_backward(const std::string &replacement); - void replace_all(const std::string &replacement); - bool disable_spellcheck = false; void set_snippets(); private: - GtkSourceSearchContext *search_context; - GtkSourceSearchSettings *search_settings; - static void search_occurrences_updated(GtkWidget *widget, GParamSpec *property, gpointer data); - bool keep_clipboard = false; protected: diff --git a/src/terminal.cc b/src/terminal.cc index 19f4bc2..a9d6cf5 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -8,7 +8,7 @@ #include #include -Terminal::Terminal() { +Terminal::Terminal() : Source::SearchView() { get_style_context()->add_class("juci_terminal"); set_editable(false); @@ -321,6 +321,22 @@ void Terminal::async_print(size_t line_nr, const std::string &message) { void Terminal::configure() { link_tag->property_foreground_rgba() = get_style_context()->get_color(Gtk::StateFlags::STATE_FLAG_LINK); + + // Set search match style: + get_buffer()->get_tag_table()->foreach([](const Glib::RefPtr &tag) { + if(tag->property_background_set()) { + auto scheme = Source::StyleSchemeManager::get_default()->get_scheme(Config::get().source.style); + if(scheme) { + auto style = scheme->get_style("search-match"); + if(style) { + if(style->property_background_set()) + tag->property_background() = style->property_background(); + if(style->property_foreground_set()) + tag->property_foreground() = style->property_foreground(); + } + } + } + }); } void Terminal::clear() { diff --git a/src/terminal.h b/src/terminal.h index 5712f0c..3001f9c 100644 --- a/src/terminal.h +++ b/src/terminal.h @@ -3,12 +3,13 @@ #include "gtkmm.h" #include "mutex.h" #include "process.hpp" +#include "source_base.h" #include #include #include #include -class Terminal : public Gtk::TextView { +class Terminal : public Source::SearchView { Terminal(); public: diff --git a/src/window.cc b/src/window.cc index 11fc3ea..30b34b1 100644 --- a/src/window.cc +++ b/src/window.cc @@ -56,19 +56,18 @@ Window::Window() { Menu::get().right_click_line_menu->attach_to_widget(*this); Menu::get().right_click_selected_menu->attach_to_widget(*this); - EntryBox::get().signal_hide().connect([]() { - if(auto view = Notebook::get().get_current_view()) - view->grab_focus(); + EntryBox::get().signal_hide().connect([this]() { + if(focused_view) + focused_view->grab_focus(); }); - Notebook::get().on_change_page = [this](Source::View *view) { - if(search_entry_shown && EntryBox::get().labels.size() > 0) { - view->update_search_occurrences = [](int number) { - EntryBox::get().labels.begin()->update(0, std::to_string(number)); - }; - view->search_highlight(last_search, case_sensitive_search, regex_search); + Notebook::get().on_focus_page = [this](Source::View *view) { + if(focused_view != view) { + focused_view = view; + update_search_and_replace_entry(); } - + }; + Notebook::get().on_change_page = [](Source::View *view) { Menu::get().toggle_menu_items(); Directories::get().select(view->file_path); @@ -85,7 +84,7 @@ Window::Window() { Project::debug_update_stop(); #endif }; - Notebook::get().on_close_page = [](Source::View *view) { + Notebook::get().on_close_page = [this](Source::View *view) { #ifdef JUCI_ENABLE_DEBUG if(Project::current && Project::debugging) { auto iter = view->get_buffer()->begin(); @@ -102,11 +101,20 @@ Window::Window() { Notebook::get().update_status(view); else { Notebook::get().clear_status(); - Menu::get().toggle_menu_items(); + if(dynamic_cast(focused_view)) + focused_view = nullptr; } }; + Terminal::get().signal_focus_in_event().connect([this](GdkEventFocus *) { + if(focused_view != &Terminal::get()) { + focused_view = &Terminal::get(); + update_search_and_replace_entry(); + } + return false; + }); + signal_focus_out_event().connect([](GdkEventFocus *event) { if(auto view = Notebook::get().get_current_view()) { view->hide_tooltips(); @@ -1809,49 +1817,43 @@ void Window::search_and_replace_entry() { } }; - if(auto view = Notebook::get().get_current_view()) { + if(focused_view) { if(Config::get().source.search_for_selection) { - auto const selected = view->get_selected_text(); - if(!selected.empty()) - last_search = selected; + Gtk::TextIter start, end; + if(focused_view->get_buffer()->get_selection_bounds(start, end)) + last_search = focused_view->get_buffer()->get_text(start, end); } } - EntryBox::get().entries.emplace_back(last_search, [](const std::string &content) { - if(auto view = Notebook::get().get_current_view()) - view->search_forward(); + EntryBox::get().entries.emplace_back(last_search, [this](const std::string &content) { + if(focused_view) + focused_view->search_forward(); }); auto search_entry_it = EntryBox::get().entries.begin(); search_entry_it->set_placeholder_text("Find"); - if(auto view = Notebook::get().get_current_view()) { - view->update_search_occurrences = [label_it](int number) { - label_it->update(0, std::to_string(number)); - }; - view->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); - } - search_entry_it->signal_key_press_event().connect([](GdkEventKey *event) { + search_entry_it->signal_key_press_event().connect([this](GdkEventKey *event) { if((event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter) && (event->state & GDK_SHIFT_MASK) > 0) { - if(auto view = Notebook::get().get_current_view()) - view->search_backward(); + if(focused_view) + focused_view->search_backward(); } return false; }); search_entry_it->signal_changed().connect([this, search_entry_it]() { last_search = search_entry_it->get_text(); - if(auto view = Notebook::get().get_current_view()) - view->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); + if(focused_view) + focused_view->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); }); - EntryBox::get().entries.emplace_back(last_replace, [](const std::string &content) { - if(auto view = Notebook::get().get_current_view()) - view->replace_forward(content); + EntryBox::get().entries.emplace_back(last_replace, [this](const std::string &content) { + if(focused_view) + focused_view->replace_forward(content); }); auto replace_entry_it = EntryBox::get().entries.begin(); replace_entry_it++; replace_entry_it->set_placeholder_text("Replace"); - replace_entry_it->signal_key_press_event().connect([replace_entry_it](GdkEventKey *event) { + replace_entry_it->signal_key_press_event().connect([this, replace_entry_it](GdkEventKey *event) { if((event->keyval == GDK_KEY_Return || event->keyval == GDK_KEY_KP_Enter) && (event->state & GDK_SHIFT_MASK) > 0) { - if(auto view = Notebook::get().get_current_view()) - view->replace_backward(replace_entry_it->get_text()); + if(focused_view) + focused_view->replace_backward(replace_entry_it->get_text()); } return false; }); @@ -1859,25 +1861,24 @@ void Window::search_and_replace_entry() { last_replace = replace_entry_it->get_text(); }); - EntryBox::get().buttons.emplace_back("↑", []() { - if(auto view = Notebook::get().get_current_view()) - view->search_backward(); + EntryBox::get().buttons.emplace_back("↑", [this]() { + if(focused_view) + focused_view->search_backward(); }); EntryBox::get().buttons.back().set_tooltip_text("Find Previous\n\nShortcut: Shift+Enter in the Find entry field"); - EntryBox::get().buttons.emplace_back("⇄", [replace_entry_it]() { - if(auto view = Notebook::get().get_current_view()) { - view->replace_forward(replace_entry_it->get_text()); - } + EntryBox::get().buttons.emplace_back("⇄", [this, replace_entry_it]() { + if(focused_view) + focused_view->replace_forward(replace_entry_it->get_text()); }); EntryBox::get().buttons.back().set_tooltip_text("Replace Next\n\nShortcut: Enter in the Replace entry field"); - EntryBox::get().buttons.emplace_back("↓", []() { - if(auto view = Notebook::get().get_current_view()) - view->search_forward(); + EntryBox::get().buttons.emplace_back("↓", [this]() { + if(focused_view) + focused_view->search_forward(); }); EntryBox::get().buttons.back().set_tooltip_text("Find Next\n\nShortcut: Enter in the Find entry field"); - EntryBox::get().buttons.emplace_back("Replace All", [replace_entry_it]() { - if(auto view = Notebook::get().get_current_view()) - view->replace_all(replace_entry_it->get_text()); + EntryBox::get().buttons.emplace_back("Replace All", [this, replace_entry_it]() { + if(focused_view) + focused_view->replace_all(replace_entry_it->get_text()); }); EntryBox::get().buttons.back().set_tooltip_text("Replace All"); @@ -1886,28 +1887,56 @@ void Window::search_and_replace_entry() { EntryBox::get().toggle_buttons.back().set_active(case_sensitive_search); EntryBox::get().toggle_buttons.back().on_activate = [this, search_entry_it]() { case_sensitive_search = !case_sensitive_search; - if(auto view = Notebook::get().get_current_view()) - view->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); + if(focused_view) + focused_view->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); }; EntryBox::get().toggle_buttons.emplace_back(".*"); EntryBox::get().toggle_buttons.back().set_tooltip_text("Use Regex"); EntryBox::get().toggle_buttons.back().set_active(regex_search); EntryBox::get().toggle_buttons.back().on_activate = [this, search_entry_it]() { regex_search = !regex_search; - if(auto view = Notebook::get().get_current_view()) - view->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); + if(focused_view) + focused_view->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); }; + EntryBox::get().signal_hide().connect([this]() { for(size_t c = 0; c < Notebook::get().size(); c++) { Notebook::get().get_view(c)->update_search_occurrences = nullptr; Notebook::get().get_view(c)->search_highlight("", case_sensitive_search, regex_search); } + Terminal::get().update_search_occurrences = nullptr; + Terminal::get().search_highlight("", case_sensitive_search, regex_search); search_entry_shown = false; }); + search_entry_shown = true; + update_search_and_replace_entry(); EntryBox::get().show(); } +void Window::update_search_and_replace_entry() { + if(!search_entry_shown || !focused_view) + return; + + focused_view->update_search_occurrences = [](int number) { + EntryBox::get().labels.begin()->update(0, std::to_string(number)); + }; + focused_view->search_highlight(last_search, case_sensitive_search, regex_search); + + auto source_view = dynamic_cast(focused_view); + + auto entry = EntryBox::get().entries.begin(); + entry++; + entry->set_sensitive(source_view); + + auto button = EntryBox::get().buttons.begin(); + button++; + button->set_sensitive(source_view); + button++; + button++; + button->set_sensitive(source_view); +} + void Window::set_tab_entry() { EntryBox::get().clear(); if(auto view = Notebook::get().get_current_view()) { diff --git a/src/window.h b/src/window.h index 6b96061..f36f149 100644 --- a/src/window.h +++ b/src/window.h @@ -1,4 +1,5 @@ #pragma once +#include "source_base.h" #include #include #include @@ -25,6 +26,7 @@ private: void configure(); void set_menu_actions(); void search_and_replace_entry(); + void update_search_and_replace_entry(); void set_tab_entry(); void goto_line_entry(); void rename_token_entry(); @@ -36,6 +38,8 @@ private: bool case_sensitive_search = true; bool regex_search = false; bool search_entry_shown = false; + /// Last source view focused + Source::SearchView *focused_view = nullptr; bool find_pattern_case_sensitive = true; bool find_pattern_extended_regex = false; }; diff --git a/tests/compile_commands_test.cc b/tests/compile_commands_test.cc index b1033e2..d88538a 100644 --- a/tests/compile_commands_test.cc +++ b/tests/compile_commands_test.cc @@ -1,9 +1,11 @@ #include "compile_commands.h" #include #include +#include int main() { auto app = Gtk::Application::create(); + Gsv::init(); auto tests_path = boost::filesystem::canonical(JUCI_TESTS_PATH); diff --git a/tests/ctags_grep_test.cc b/tests/ctags_grep_test.cc index 0b6e76e..8f78584 100644 --- a/tests/ctags_grep_test.cc +++ b/tests/ctags_grep_test.cc @@ -3,6 +3,7 @@ #include "grep.h" #include #include +#include void ctags_grep_test_function() { } @@ -14,6 +15,8 @@ class Test { int main() { auto app = Gtk::Application::create(); + Gsv::init(); + #ifdef JUCI_USE_UCTAGS Config::get().project.ctags_command = "uctags"; #else @@ -36,7 +39,7 @@ int main() { auto location = ctags.get_location(line, false); g_assert(location.source == "void ctags_grep_test_function() {"); g_assert(ctags.project_path / location.file_path == tests_path / "ctags_grep_test.cc"); - g_assert_cmpint(location.line, ==, 6); + g_assert_cmpint(location.line, ==, 7); g_assert_cmpint(location.index, ==, 5); g_assert(location.symbol == "ctags_grep_test_function"); g_assert(location.scope.empty()); @@ -46,7 +49,7 @@ int main() { auto location = ctags.get_location(line, true); g_assert(location.source == "void ctags_grep_test_function() {"); g_assert(ctags.project_path / location.file_path == tests_path / "ctags_grep_test.cc"); - g_assert_cmpint(location.line, ==, 6); + g_assert_cmpint(location.line, ==, 7); g_assert_cmpint(location.index, ==, 5); g_assert(location.symbol == "ctags_grep_test_function"); g_assert(location.scope.empty()); @@ -69,7 +72,7 @@ int main() { auto location = ctags.get_location(line, false); g_assert(location.source == "void ctags_grep_test_function() {"); g_assert(ctags.project_path / location.file_path == tests_path / "ctags_grep_test.cc"); - g_assert_cmpint(location.line, ==, 6); + g_assert_cmpint(location.line, ==, 7); g_assert_cmpint(location.index, ==, 5); g_assert(location.symbol == "ctags_grep_test_function"); g_assert(location.scope.empty()); @@ -79,7 +82,7 @@ int main() { auto location = ctags.get_location(line, true); g_assert(location.source == "void ctags_grep_test_function() {"); g_assert(ctags.project_path / location.file_path == tests_path / "ctags_grep_test.cc"); - g_assert_cmpint(location.line, ==, 6); + g_assert_cmpint(location.line, ==, 7); g_assert_cmpint(location.index, ==, 5); g_assert(location.symbol == "ctags_grep_test_function"); g_assert(location.scope.empty()); @@ -102,7 +105,7 @@ int main() { auto location = ctags.get_location(line, false); g_assert(location.source == "void ctags_grep_test_function2() {"); g_assert(ctags.project_path / location.file_path == tests_path / "ctags_grep_test.cc"); - g_assert_cmpint(location.line, ==, 10); + g_assert_cmpint(location.line, ==, 11); g_assert_cmpint(location.index, ==, 7); g_assert(location.symbol == "ctags_grep_test_function2"); g_assert(location.scope == "Test"); @@ -125,43 +128,43 @@ int main() { if(line.find("ctags_grep_test_function") != std::string::npos) { { auto location = grep.get_location(line, true, true); - g_assert(location.markup == "tests/ctags_grep_test.cc:7:void ctags_grep_test_function() {"); + g_assert(location.markup == "tests/ctags_grep_test.cc:8:void ctags_grep_test_function() {"); g_assert(grep.project_path / location.file_path == tests_path / "ctags_grep_test.cc"); - g_assert_cmpint(location.line, ==, 6); + g_assert_cmpint(location.line, ==, 7); g_assert_cmpint(location.offset, ==, 5); { auto location2 = grep.get_location(location.markup, false, true); - g_assert(location2.markup == "tests/ctags_grep_test.cc:7:void ctags_grep_test_function() {"); + g_assert(location2.markup == "tests/ctags_grep_test.cc:8:void ctags_grep_test_function() {"); g_assert(grep.project_path / location2.file_path == tests_path / "ctags_grep_test.cc"); - g_assert_cmpint(location2.line, ==, 6); + g_assert_cmpint(location2.line, ==, 7); g_assert_cmpint(location2.offset, ==, 5); } } { auto location = grep.get_location(line, true, false); - g_assert(location.markup == "tests/ctags_grep_test.cc:7:void ctags_grep_test_function() {"); + g_assert(location.markup == "tests/ctags_grep_test.cc:8:void ctags_grep_test_function() {"); g_assert(grep.project_path / location.file_path == tests_path / "ctags_grep_test.cc"); - g_assert_cmpint(location.line, ==, 6); + g_assert_cmpint(location.line, ==, 7); g_assert_cmpint(location.offset, ==, 0); { auto location2 = grep.get_location(location.markup, false, false); - g_assert(location2.markup == "tests/ctags_grep_test.cc:7:void ctags_grep_test_function() {"); + g_assert(location2.markup == "tests/ctags_grep_test.cc:8:void ctags_grep_test_function() {"); g_assert(grep.project_path / location2.file_path == tests_path / "ctags_grep_test.cc"); - g_assert_cmpint(location2.line, ==, 6); + g_assert_cmpint(location2.line, ==, 7); g_assert_cmpint(location2.offset, ==, 0); } } { auto location = grep.get_location(line, true, true, (boost::filesystem::path("tests") / "ctags_grep_test.cc").string()); - g_assert(location.markup == "tests/ctags_grep_test.cc:7:void ctags_grep_test_function() {"); + g_assert(location.markup == "tests/ctags_grep_test.cc:8:void ctags_grep_test_function() {"); g_assert(grep.project_path / location.file_path == tests_path / "ctags_grep_test.cc"); g_assert(location); - g_assert_cmpint(location.line, ==, 6); + g_assert_cmpint(location.line, ==, 7); g_assert_cmpint(location.offset, ==, 5); } { auto location = grep.get_location(line, true, true, "CMakeLists.txt"); - g_assert(location.markup == "tests/ctags_grep_test.cc:7:void ctags_grep_test_function() {"); + g_assert(location.markup == "tests/ctags_grep_test.cc:8:void ctags_grep_test_function() {"); g_assert(location.file_path.empty()); g_assert(!location); } diff --git a/tests/terminal_test.cc b/tests/terminal_test.cc index 5eda0a3..5e04a0e 100644 --- a/tests/terminal_test.cc +++ b/tests/terminal_test.cc @@ -1,5 +1,6 @@ #include "terminal.h" #include +#include //Requires display server to work //However, it is possible to use the Broadway backend if the test is run in a pure terminal environment: @@ -8,6 +9,7 @@ int main() { auto app = Gtk::Application::create(); + Gsv::init(); { auto link = Terminal::get().find_link("~/test/test.cc:7:41: error: expected ';' after expression.");