diff --git a/juci/config.json b/juci/config.json index 0d35a91..61d9721 100644 --- a/juci/config.json +++ b/juci/config.json @@ -8,7 +8,9 @@ "type": "#0066FF", "keyword": "blue", "comment": "grey", - "own": "pink" + "own": "pink", + "diagnostic_warning": "orange", + "diagnostic_error": "red" }, "syntax": { "43": "type", diff --git a/juci/source.cc b/juci/source.cc index c8e9960..688405a 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -136,7 +136,7 @@ clang::Index Source::ClangView::clang_index(0, 0); Source::ClangView::ClangView(const Source::Config& config, const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal): Source::View(config, file_path, project_path), terminal(terminal), -parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false), diagnostic_tooltips(*this) { +parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { override_font(Pango::FontDescription(config.font)); override_background_color(Gdk::RGBA(config.background)); for (auto &item : config.tags) { @@ -357,20 +357,26 @@ void Source::ClangView::update_diagnostics() { if(diagnostic.path==file_path) { auto start=buffer->get_iter_at_offset(diagnostic.start_location.offset); auto end=buffer->get_iter_at_offset(diagnostic.end_location.offset); - diagnostic_tooltips.add(diagnostic.severity_spelling+": "+diagnostic.spelling, get_source_buffer()->create_mark(start), get_source_buffer()->create_mark(end)); + std::string diagnostic_tag_name; + if(diagnostic.severity<=CXDiagnostic_Warning) + diagnostic_tag_name="diagnostic_warning"; + else + diagnostic_tag_name="diagnostic_error"; + + auto tooltip_widget=std::make_shared(Gtk::TextBuffer::create(buffer->get_tag_table())); + tooltip_widget->set_editable(false); + tooltip_widget->get_buffer()->insert_with_tag(tooltip_widget->get_buffer()->get_insert()->get_iter(), diagnostic.severity_spelling, diagnostic_tag_name); + tooltip_widget->get_buffer()->insert_at_cursor(": "+diagnostic.spelling); + diagnostic_tooltips.emplace_back(tooltip_widget, *this, get_source_buffer()->create_mark(start), get_source_buffer()->create_mark(end)); + auto tag=buffer->create_tag(); tag->property_underline()=Pango::Underline::UNDERLINE_ERROR; auto tag_class=G_OBJECT_GET_CLASS(tag->gobj()); //For older GTK+ 3 versions: auto param_spec=g_object_class_find_property(tag_class, "underline-rgba"); if(param_spec!=NULL) { - if(diagnostic.severity<=CXDiagnostic_Warning) { - //TODO: get color from config.json - tag->set_property("underline-rgba", Gdk::RGBA("orange")); - } - else { - //TODO: get color from config.json - tag->set_property("underline-rgba", Gdk::RGBA("red")); - } + auto diagnostic_tag=buffer->get_tag_table()->lookup(diagnostic_tag_name); + if(diagnostic_tag!=0) + tag->set_property("underline-rgba", diagnostic_tag->property_foreground_rgba().get_value()); } buffer->apply_tag(tag, start, end); } @@ -380,6 +386,7 @@ void Source::ClangView::update_diagnostics() { bool Source::ClangView::clangview_on_motion_notify_event(GdkEventMotion* event) { Gdk::Rectangle rectangle(event->x, event->y, 1, 1); + diagnostic_tooltips.init(); diagnostic_tooltips.show(rectangle); return false; } @@ -393,6 +400,7 @@ void Source::ClangView::clangview_on_mark_set(const Gtk::TextBuffer::iterator& i rectangle.set_x(location_window_x-2); rectangle.set_y(location_window_y); rectangle.set_width(4); + diagnostic_tooltips.init(); diagnostic_tooltips.show(rectangle); } } diff --git a/juci/tooltips.cc b/juci/tooltips.cc index 5c2172e..8d063cb 100644 --- a/juci/tooltips.cc +++ b/juci/tooltips.cc @@ -1,94 +1,89 @@ #include "tooltips.h" +#include -Gdk::Rectangle Tooltips::tooltips_rectangle=Gdk::Rectangle(); +Gdk::Rectangle Tooltips::drawn_tooltips_rectangle=Gdk::Rectangle(); -Tooltip::Tooltip(Gtk::TextView& text_view, const std::string& label_text, +Tooltip::Tooltip(std::shared_ptr widget, Gtk::TextView& text_view, Glib::RefPtr start_mark, Glib::RefPtr end_mark): -text_view(text_view), Gtk::Dialog("", (Gtk::Window&)*text_view.get_toplevel()), label(label_text), +widget(widget), text_view(text_view), Gtk::Dialog("", (Gtk::Window&)*text_view.get_toplevel()), start_mark(start_mark), end_mark(end_mark) { - get_content_area()->add(label); + get_content_area()->add(*widget); property_decorated()=false; set_accept_focus(false); + signal_realize().connect([this](){ + adjust(); //Fix for older GTK+ versions? + }); } void Tooltip::update() { auto iter=start_mark->get_iter(); auto end_iter=end_mark->get_iter(); if(iter.get_offset()get_root_coords(text_rectangle.get_x(), text_rectangle.get_y(), root_x, root_y); + text_view.get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(activation_rectangle.get_x(), activation_rectangle.get_y(), root_x, root_y); Gdk::Rectangle rectangle; rectangle.set_x(root_x); rectangle.set_y(root_y-tooltip_height); rectangle.set_width(tooltip_width); rectangle.set_height(tooltip_height); - if(Tooltips::tooltips_rectangle.get_width()!=0) { - if(rectangle.intersects(Tooltips::tooltips_rectangle)) - rectangle.set_y(Tooltips::tooltips_rectangle.get_y()-tooltip_height); - Tooltips::tooltips_rectangle.join(rectangle); + if(Tooltips::drawn_tooltips_rectangle.get_width()!=0) { + if(rectangle.intersects(Tooltips::drawn_tooltips_rectangle)) + rectangle.set_y(Tooltips::drawn_tooltips_rectangle.get_y()-tooltip_height); + Tooltips::drawn_tooltips_rectangle.join(rectangle); } else - Tooltips::tooltips_rectangle=rectangle; + Tooltips::drawn_tooltips_rectangle=rectangle; - if(rectangle.get_y()<0) - rectangle.set_y(0); move(rectangle.get_x(), rectangle.get_y()); + adjusted=true; } -void Tooltips::add(const std::string& text, Glib::RefPtr start_mark, Glib::RefPtr end_mark) { - tooltips.emplace_back(new Tooltip(text_view, text, start_mark, end_mark)); -} - -//If you want to show tooltips from several Tooltips-objects at once, you might want to set clear_tooltips_rectangle=true only on the first one. -//If not, they would overlap (clear_tooltips_rectangle=false to avoid this on the following Tooltips-objects) -void Tooltips::show(const Gdk::Rectangle& rectangle, bool clear_tooltips_rectangle) { - if(clear_tooltips_rectangle) - tooltips_rectangle=Gdk::Rectangle(); - for(auto& tooltip: tooltips) { - tooltip->update(); - if(rectangle.intersects(tooltip->text_rectangle)) { - tooltip->show_all(); - tooltip->adjust(); +void Tooltips::show(const Gdk::Rectangle& rectangle) { + for(auto& tooltip: *this) { + tooltip.update(); + if(rectangle.intersects(tooltip.activation_rectangle)) { + tooltip.show_all(); + if(tooltip.get_realized()) + tooltip.adjust(); } else - tooltip->hide(); + tooltip.hide(); } - text_view.grab_focus(); } -//See Tooltips::show(const Gdk::Rectangle& rectangle, bool clear_tooltips_rectangle=true) -void Tooltips::show(bool clear_tooltips_rectangle) { - if(clear_tooltips_rectangle) - tooltips_rectangle=Gdk::Rectangle(); - for(auto& tooltip: tooltips) { - tooltip->update(); - tooltip->show_all(); - tooltip->adjust(); +void Tooltips::show() { + for(auto& tooltip: *this) { + tooltip.update(); + tooltip.show_all(); + if(tooltip.get_realized()) + tooltip.adjust(); } - text_view.grab_focus(); } void Tooltips::hide() { - for(auto& tooltip: tooltips) { - tooltip->hide(); + for(auto& tooltip: *this) { + tooltip.hide(); } } diff --git a/juci/tooltips.h b/juci/tooltips.h index 9375801..b8d86ae 100644 --- a/juci/tooltips.h +++ b/juci/tooltips.h @@ -2,40 +2,32 @@ #define JUCI_TOOLTIPS_H_ #include "gtkmm.h" #include -#include +#include class Tooltip : public Gtk::Dialog { public: - Tooltip(Gtk::TextView& text_view, const std::string& label_text, Glib::RefPtr start_mark, Glib::RefPtr end_mark); + Tooltip(std::shared_ptr widget, Gtk::TextView& text_view, Glib::RefPtr start_mark, Glib::RefPtr end_mark); void update(); void adjust(); - Gtk::Label label; + Gdk::Rectangle activation_rectangle; + bool adjusted=false; +private: + std::shared_ptr widget; Glib::RefPtr start_mark; Glib::RefPtr end_mark; - Gdk::Rectangle text_rectangle; - -private: Gtk::TextView& text_view; }; -class Tooltips { +class Tooltips : public std::list { public: - Tooltips(Gtk::TextView& text_view): text_view(text_view) {} - - void clear() {tooltips.clear();} - - void add(const std::string& text, Glib::RefPtr start_mark, Glib::RefPtr end_mark); - - void show(const Gdk::Rectangle& rectangle, bool clear_tooltips_rectangle=true); - void show(bool clear_tooltips_rectangle=true); + void init() {drawn_tooltips_rectangle=Gdk::Rectangle();} + void show(const Gdk::Rectangle& rectangle); + void show(); void hide(); - static Gdk::Rectangle tooltips_rectangle; -private: - Gtk::TextView& text_view; - std::vector > tooltips; + static Gdk::Rectangle drawn_tooltips_rectangle; }; #endif // JUCI_TOOLTIPS_H_