Browse Source

Added diagnostics; warning and error messages while writing code.

merge-requests/365/head
eidheim 11 years ago
parent
commit
e95c89ccbe
  1. 2
      juci/CMakeLists.txt
  2. 1
      juci/notebook.cc
  3. 51
      juci/source.cc
  4. 5
      juci/source.h
  5. 71
      juci/tooltips.cc
  6. 42
      juci/tooltips.h
  7. 1
      juci/window.cc

2
juci/CMakeLists.txt

@ -125,6 +125,8 @@ add_executable(${project_name}
directories.cc directories.cc
terminal.h terminal.h
terminal.cc terminal.cc
tooltips.h
tooltips.cc
) )
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

1
juci/notebook.cc

@ -187,6 +187,7 @@ void Notebook::Controller::OnOpenFile(std::string path) {
Notebook().set_current_page(Pages()-1); Notebook().set_current_page(Pages()-1);
Notebook().set_focus_child(*text_vec_.back()->view); Notebook().set_focus_child(*text_vec_.back()->view);
//Add star on tab label when the page is not saved: //Add star on tab label when the page is not saved:
//TODO: instead use Gtk::TextBuffer::set_modified and Gtk::TextBuffer::get_modified
text_vec_.back()->buffer()->signal_changed().connect([this]() { text_vec_.back()->buffer()->signal_changed().connect([this]() {
if(text_vec_.at(CurrentPage())->is_saved) { if(text_vec_.at(CurrentPage())->is_saved) {
std::string path=CurrentTextView().file_path; std::string path=CurrentTextView().file_path;

51
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::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), Source::View(config, file_path, project_path), terminal(terminal),
parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false), diagnostic_tooltips(*this) {
override_font(Pango::FontDescription(config.font)); override_font(Pango::FontDescription(config.font));
override_background_color(Gdk::RGBA(config.background)); override_background_color(Gdk::RGBA(config.background));
for (auto &item : config.tags) { for (auto &item : config.tags) {
@ -183,6 +183,7 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) {
update_syntax(extract_tokens(0, get_source_buffer()->get_text().size())); update_syntax(extract_tokens(0, get_source_buffer()->get_text().size()));
parsing_in_progress->done("done"); parsing_in_progress->done("done");
INFO("Syntax updated"); INFO("Syntax updated");
update_diagnostics();
} }
else { else {
parse_thread_go=true; parse_thread_go=true;
@ -216,6 +217,8 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) {
signal_key_press_event().connect(sigc::mem_fun(*this, &Source::ClangView::on_key_press), false); signal_key_press_event().connect(sigc::mem_fun(*this, &Source::ClangView::on_key_press), false);
signal_key_release_event().connect(sigc::mem_fun(*this, &Source::ClangView::on_key_release), false); signal_key_release_event().connect(sigc::mem_fun(*this, &Source::ClangView::on_key_release), false);
signal_motion_notify_event().connect(sigc::mem_fun(*this, &Source::ClangView::on_motion_notify_event), false);
get_buffer()->signal_mark_set().connect(sigc::mem_fun(*this, &Source::ClangView::on_mark_set), false);
} }
Source::ClangView::~ClangView() { Source::ClangView::~ClangView() {
@ -346,6 +349,52 @@ void Source::ClangView::update_syntax(const std::vector<Source::Range> &ranges)
} }
} }
void Source::ClangView::update_diagnostics() {
diagnostic_tooltips.clear();
auto diagnostics=tu_->get_diagnostics();
auto buffer=get_source_buffer();
for(auto& diagnostic: 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));
auto tag=buffer->create_tag();
tag->property_underline()=Pango::Underline::UNDERLINE_ERROR;
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"));
}
buffer->apply_tag(tag, start, end);
}
}
on_mark_set(get_buffer()->get_insert()->get_iter(), get_buffer()->get_mark("insert"));
}
bool Source::ClangView::on_motion_notify_event(GdkEventMotion* event) {
Gdk::Rectangle rectangle(event->x, event->y, 1, 1);
diagnostic_tooltips.show(rectangle);
auto cursor=Gdk::Cursor::create(Gdk::CursorType::XTERM);
get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->set_cursor(cursor);
return false;
}
void Source::ClangView::on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark) {
if(mark->get_name()=="insert") {
Gdk::Rectangle rectangle;
get_iter_location(iterator, rectangle);
int location_window_x, location_window_y;
buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, rectangle.get_x(), rectangle.get_y(), location_window_x, location_window_y);
rectangle.set_x(location_window_x-2);
rectangle.set_y(location_window_y);
rectangle.set_width(4);
diagnostic_tooltips.show(rectangle);
}
}
void Source::ClangView:: void Source::ClangView::
highlight_cursor(clang::Token *token, highlight_cursor(clang::Token *token,
std::vector<Source::Range> *source_ranges) { std::vector<Source::Range> *source_ranges) {

5
juci/source.h

@ -11,6 +11,7 @@
#include <atomic> #include <atomic>
#include "gtksourceviewmm.h" #include "gtksourceviewmm.h"
#include "terminal.h" #include "terminal.h"
#include "tooltips.h"
namespace Source { namespace Source {
class Config { class Config {
@ -95,6 +96,10 @@ namespace Source {
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);
void update_diagnostics();
Tooltips diagnostic_tooltips;
bool on_motion_notify_event(GdkEventMotion* event);
void on_mark_set(const Gtk::TextBuffer::iterator& iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark);
static clang::Index clang_index; static clang::Index clang_index;
std::map<std::string, std::string> get_buffer_map() const; std::map<std::string, std::string> get_buffer_map() const;

71
juci/tooltips.cc

@ -0,0 +1,71 @@
#include "tooltips.h"
#include <iostream>
Tooltip::Tooltip(Gtk::TextView& text_view, const std::string& label_text,
Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark, Glib::RefPtr<Gtk::TextBuffer::Mark> end_mark, Gdk::Rectangle &tooltips_rectangle):
text_view(text_view), Gtk::Dialog("", (Gtk::Window&)*text_view.get_toplevel()), label(label_text),
start_mark(start_mark), end_mark(end_mark), tooltips_rectangle(tooltips_rectangle) {
get_content_area()->add(label);
property_decorated()=false;
set_accept_focus(false);
}
void Tooltip::update() {
auto iter=start_mark->get_iter();
auto end_iter=end_mark->get_iter();
if(iter.get_offset()<end_iter.get_offset()) {
text_view.get_iter_location(iter, text_rectangle);
iter++;
while(iter!=end_iter) {
Gdk::Rectangle rectangle;
text_view.get_iter_location(iter, rectangle);
text_rectangle.join(rectangle);
iter++;
}
}
int location_window_x, location_window_y;
text_view.buffer_to_window_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, text_rectangle.get_x(), text_rectangle.get_y(), location_window_x, location_window_y);
text_rectangle.set_x(location_window_x);
text_rectangle.set_y(location_window_y);
}
void Tooltip::adjust() {
int tooltip_width, tooltip_height;
get_size(tooltip_width, tooltip_height);
int root_x, root_y;
text_view.get_window(Gtk::TextWindowType::TEXT_WINDOW_TEXT)->get_root_coords(text_rectangle.get_x(), text_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_rectangle.get_width()!=0) {
if(rectangle.intersects(tooltips_rectangle))
rectangle.set_y(tooltips_rectangle.get_y()-tooltip_height);
tooltips_rectangle.join(rectangle);
}
else
tooltips_rectangle=rectangle;
if(rectangle.get_y()<0)
rectangle.set_y(0);
move(rectangle.get_x(), rectangle.get_y());
}
void Tooltips::add(const std::string& text, Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark, Glib::RefPtr<Gtk::TextBuffer::Mark> end_mark) {
tooltips.emplace_back(new Tooltip(text_view, text, start_mark, end_mark, tooltips_rectangle));
}
void Tooltips::show(const Gdk::Rectangle& rectangle) {
init_adjustments();
for(auto& tooltip: tooltips) {
tooltip->update();
if(rectangle.intersects(tooltip->text_rectangle)) {
tooltip->show_all();
tooltip->adjust();
}
else
tooltip->hide();
}
}

42
juci/tooltips.h

@ -0,0 +1,42 @@
#ifndef JUCI_TOOLTIPS_H_
#define JUCI_TOOLTIPS_H_
#include "gtkmm.h"
#include <string>
#include <vector>
class Tooltip : public Gtk::Dialog {
public:
Tooltip(Gtk::TextView& text_view, const std::string& label_text, Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark, Glib::RefPtr<Gtk::TextBuffer::Mark> end_mark, Gdk::Rectangle &tooltips_rectangle);
void update();
void adjust();
Gtk::Label label;
Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark;
Glib::RefPtr<Gtk::TextBuffer::Mark> end_mark;
Gdk::Rectangle text_rectangle;
private:
Gtk::TextView& text_view;
Gdk::Rectangle &tooltips_rectangle;
};
class Tooltips {
public:
Tooltips(Gtk::TextView& text_view): text_view(text_view) {}
void init_adjustments() {tooltips_rectangle=Gdk::Rectangle();}
void clear() {tooltips.clear();}
void add(const std::string& text, Glib::RefPtr<Gtk::TextBuffer::Mark> start_mark, Glib::RefPtr<Gtk::TextBuffer::Mark> end_mark);
void show(const Gdk::Rectangle& rectangle);
Gdk::Rectangle tooltips_rectangle;
private:
Gtk::TextView& text_view;
std::vector<std::unique_ptr<Tooltip> > tooltips;
};
#endif // JUCI_TOOLTIPS_H_

1
juci/window.cc

@ -14,6 +14,7 @@ Window::Window() :
INFO("Create Window"); INFO("Create Window");
set_title("juCi++"); set_title("juCi++");
set_default_size(600, 400); set_default_size(600, 400);
set_events(Gdk::POINTER_MOTION_MASK);
add(window_box_); add(window_box_);
keybindings_.action_group_menu()->add(Gtk::Action::create("FileQuit", keybindings_.action_group_menu()->add(Gtk::Action::create("FileQuit",
"Quit juCi++"), "Quit juCi++"),

Loading…
Cancel
Save