diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e98ca99..ff2e207 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -86,6 +86,8 @@ set(source_files juci.h dialogs.cc project.h project.cc + dispatcher.h + dispatcher.cc ../libclangmm/src/CodeCompleteResults.cc ../libclangmm/src/CompilationDatabase.cc diff --git a/src/dispatcher.cc b/src/dispatcher.cc new file mode 100644 index 0000000..4a1d80c --- /dev/null +++ b/src/dispatcher.cc @@ -0,0 +1,30 @@ +#include "dispatcher.h" + +Dispatcher::Dispatcher() { + connection=dispatcher.connect([this] { + functions_mutex.lock(); + for(auto &function: functions) { + function(); + } + functions.clear(); + functions_mutex.unlock(); + }); +} + +Dispatcher::~Dispatcher() { + disconnect(); + functions_mutex.lock(); + functions.clear(); + functions_mutex.unlock(); +} + +void Dispatcher::add(std::function function) { + functions_mutex.lock(); + functions.emplace_back(function); + functions_mutex.unlock(); + dispatcher(); +} + +void Dispatcher::disconnect() { + connection.disconnect(); +} diff --git a/src/dispatcher.h b/src/dispatcher.h new file mode 100644 index 0000000..70312f1 --- /dev/null +++ b/src/dispatcher.h @@ -0,0 +1,20 @@ +#ifndef DISPATCHER_H_ +#define DISPATCHER_H_ +#include +#include +#include + +class Dispatcher { +private: + std::vector> functions; + std::mutex functions_mutex; + Glib::Dispatcher dispatcher; + sigc::connection connection; +public: + Dispatcher(); + ~Dispatcher(); + void add(std::function function); + void disconnect(); +}; + +#endif /* DISPATCHER_H_ */ diff --git a/src/project.cc b/src/project.cc index 9ab0f9b..a28352f 100644 --- a/src/project.cc +++ b/src/project.cc @@ -4,83 +4,74 @@ #include "filesystem.h" #include #include "menu.h" +#include "notebook.h" #ifdef JUCI_ENABLE_DEBUG #include "debug.h" #endif -Project::Project() : notebook(Notebook::get()), compiling(false), debugging(false) { - debug_update_stop.connect([this](){ - debug_stop_mutex.lock(); - for(int c=0;cfile_path==debug_last_stop_file_path) { - view->get_source_buffer()->remove_source_marks(view->get_buffer()->begin(), view->get_buffer()->end(), "debug_stop"); - break; - } +std::unordered_map Project::run_arguments; +std::unordered_map Project::debug_run_arguments; +std::atomic Project::compiling; +std::atomic Project::debugging; +std::pair > Project::debug_stop; +boost::filesystem::path Project::debug_last_stop_file_path; +std::unique_ptr Project::debug_status_label; + +void Project::debug_update_status(const std::string &debug_status) { + if(debug_status.empty()) { + debug_status_label->set_text(""); + auto &menu=Menu::get(); + menu.actions["debug_stop"]->set_enabled(false); + menu.actions["debug_kill"]->set_enabled(false); + menu.actions["debug_step_over"]->set_enabled(false); + menu.actions["debug_step_into"]->set_enabled(false); + menu.actions["debug_step_out"]->set_enabled(false); + menu.actions["debug_backtrace"]->set_enabled(false); + menu.actions["debug_show_variables"]->set_enabled(false); + menu.actions["debug_run_command"]->set_enabled(false); + menu.actions["debug_goto_stop"]->set_enabled(false); + } + else { + debug_status_label->set_text("debug: "+debug_status); + auto &menu=Menu::get(); + menu.actions["debug_stop"]->set_enabled(); + menu.actions["debug_kill"]->set_enabled(); + menu.actions["debug_step_over"]->set_enabled(); + menu.actions["debug_step_into"]->set_enabled(); + menu.actions["debug_step_out"]->set_enabled(); + menu.actions["debug_backtrace"]->set_enabled(); + menu.actions["debug_show_variables"]->set_enabled(); + menu.actions["debug_run_command"]->set_enabled(); + menu.actions["debug_goto_stop"]->set_enabled(); + } +} + +void Project::debug_update_stop() { + for(int c=0;cfile_path==debug_last_stop_file_path) { + view->get_source_buffer()->remove_source_marks(view->get_buffer()->begin(), view->get_buffer()->end(), "debug_stop"); + break; } - //Add debug stop source mark - for(int c=0;cfile_path==debug_stop.first) { - if(debug_stop.second.first-1get_buffer()->get_line_count()) { - view->get_source_buffer()->create_source_mark("debug_stop", view->get_buffer()->get_iter_at_line(debug_stop.second.first-1)); - debug_last_stop_file_path=debug_stop.first; - } - break; + } + //Add debug stop source mark + for(int c=0;cfile_path==debug_stop.first) { + if(debug_stop.second.first-1get_buffer()->get_line_count()) { + view->get_source_buffer()->create_source_mark("debug_stop", view->get_buffer()->get_iter_at_line(debug_stop.second.first-1)); + debug_last_stop_file_path=debug_stop.first; } + break; } - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->get_buffer()->place_cursor(notebook.get_current_view()->get_buffer()->get_insert()->get_iter()); - debug_stop_mutex.unlock(); - }); - -#ifdef JUCI_ENABLE_DEBUG - auto &menu=Menu::get(); - menu.actions["debug_stop"]->set_enabled(false); - menu.actions["debug_kill"]->set_enabled(false); - menu.actions["debug_step_over"]->set_enabled(false); - menu.actions["debug_step_into"]->set_enabled(false); - menu.actions["debug_step_out"]->set_enabled(false); - menu.actions["debug_backtrace"]->set_enabled(false); - menu.actions["debug_show_variables"]->set_enabled(false); - menu.actions["debug_run_command"]->set_enabled(false); - menu.actions["debug_goto_stop"]->set_enabled(false); -#endif - debug_update_status.connect([this](){ - debug_status_mutex.lock(); - if(debug_status.empty()) { - debug_status_label.set_text(""); - auto &menu=Menu::get(); - menu.actions["debug_stop"]->set_enabled(false); - menu.actions["debug_kill"]->set_enabled(false); - menu.actions["debug_step_over"]->set_enabled(false); - menu.actions["debug_step_into"]->set_enabled(false); - menu.actions["debug_step_out"]->set_enabled(false); - menu.actions["debug_backtrace"]->set_enabled(false); - menu.actions["debug_show_variables"]->set_enabled(false); - menu.actions["debug_run_command"]->set_enabled(false); - menu.actions["debug_goto_stop"]->set_enabled(false); - } - else { - debug_status_label.set_text("debug: "+debug_status); - auto &menu=Menu::get(); - menu.actions["debug_stop"]->set_enabled(); - menu.actions["debug_kill"]->set_enabled(); - menu.actions["debug_step_over"]->set_enabled(); - menu.actions["debug_step_into"]->set_enabled(); - menu.actions["debug_step_out"]->set_enabled(); - menu.actions["debug_backtrace"]->set_enabled(); - menu.actions["debug_show_variables"]->set_enabled(); - menu.actions["debug_run_command"]->set_enabled(); - menu.actions["debug_goto_stop"]->set_enabled(); - } - debug_status_mutex.unlock(); - }); + } + if(Notebook::get().get_current_page()!=-1) + Notebook::get().get_current_view()->get_buffer()->place_cursor(Notebook::get().get_current_view()->get_buffer()->get_insert()->get_iter()); } std::unique_ptr Project::get_language() { - if(notebook.get_current_page()!=-1) { - auto language_id=notebook.get_current_view()->language->get_id(); + if(Notebook::get().get_current_page()!=-1) { + auto language_id=Notebook::get().get_current_view()->language->get_id(); if(language_id=="markdown") return std::unique_ptr(new Project::Markdown()); if(language_id=="python") @@ -96,8 +87,8 @@ std::unique_ptr Project::get_language() { std::unique_ptr Project::Clang::get_cmake() { boost::filesystem::path path; - if(notebook.get_current_page()!=-1) - path=notebook.get_current_view()->file_path.parent_path(); + if(Notebook::get().get_current_page()!=-1) + path=Notebook::get().get_current_view()->file_path.parent_path(); else path=Directories::get().current_path; if(path.empty()) @@ -116,13 +107,13 @@ std::pair Project::Clang::get_run_arguments() { return {"", ""}; auto project_path=cmake->project_path.string(); - auto run_arguments_it=Project::get().run_arguments.find(project_path); + auto run_arguments_it=run_arguments.find(project_path); std::string arguments; - if(run_arguments_it!=Project::get().run_arguments.end()) + if(run_arguments_it!=run_arguments.end()) arguments=run_arguments_it->second; if(arguments.empty()) { - auto executable=cmake->get_executable(notebook.get_current_page()!=-1?notebook.get_current_view()->file_path:"").string(); + auto executable=cmake->get_executable(Notebook::get().get_current_page()!=-1?Notebook::get().get_current_view()->file_path:"").string(); if(executable!="") { auto project_path=cmake->project_path; @@ -149,10 +140,10 @@ void Project::Clang::compile() { auto default_build_path=CMake::get_default_build_path(cmake->project_path); if(default_build_path.empty()) return; - Project::get().compiling=true; + compiling=true; Terminal::get().print("Compiling project "+cmake->project_path.string()+"\n"); Terminal::get().async_process(Config::get().terminal.make_command, default_build_path, [this](int exit_status) { - Project::get().compiling=false; + compiling=false; }); } @@ -166,13 +157,13 @@ void Project::Clang::compile_and_run() { if(default_build_path.empty()) return; - auto run_arguments_it=Project::get().run_arguments.find(project_path.string()); + auto run_arguments_it=run_arguments.find(project_path.string()); std::string arguments; - if(run_arguments_it!=Project::get().run_arguments.end()) + if(run_arguments_it!=run_arguments.end()) arguments=run_arguments_it->second; if(arguments.empty()) { - arguments=cmake->get_executable(notebook.get_current_page()!=-1?notebook.get_current_view()->file_path:"").string(); + arguments=cmake->get_executable(Notebook::get().get_current_page()!=-1?Notebook::get().get_current_view()->file_path:"").string(); if(arguments.empty()) { Terminal::get().print("Could not find add_executable in the following paths:\n"); for(auto &path: cmake->paths) @@ -186,10 +177,10 @@ void Project::Clang::compile_and_run() { arguments=filesystem::escape_argument(arguments); } - Project::get().compiling=true; + compiling=true; Terminal::get().print("Compiling and running "+arguments+"\n"); Terminal::get().async_process(Config::get().terminal.make_command, default_build_path, [this, arguments, default_build_path](int exit_status){ - Project::get().compiling=false; + compiling=false; if(exit_status==EXIT_SUCCESS) { Terminal::get().async_process(arguments, default_build_path, [this, arguments](int exit_status){ Terminal::get().async_print(arguments+" returned: "+std::to_string(exit_status)+'\n'); @@ -205,13 +196,13 @@ std::pair Project::Clang::debug_get_run_arguments() { return {"", ""}; auto project_path=cmake->project_path.string(); - auto run_arguments_it=Project::get().debug_run_arguments.find(project_path); + auto run_arguments_it=debug_run_arguments.find(project_path); std::string arguments; - if(run_arguments_it!=Project::get().debug_run_arguments.end()) + if(run_arguments_it!=debug_run_arguments.end()) arguments=run_arguments_it->second; if(arguments.empty()) { - auto executable=cmake->get_executable(notebook.get_current_page()!=-1?notebook.get_current_view()->file_path:"").string(); + auto executable=cmake->get_executable(Notebook::get().get_current_page()!=-1?Notebook::get().get_current_view()->file_path:"").string(); if(executable!="") { auto project_path=cmake->project_path; @@ -242,13 +233,13 @@ void Project::Clang::debug_start() { if(!CMake::create_debug_build(project_path)) return; - auto run_arguments_it=Project::get().debug_run_arguments.find(project_path.string()); + auto run_arguments_it=debug_run_arguments.find(project_path.string()); std::string run_arguments; - if(run_arguments_it!=Project::get().debug_run_arguments.end()) + if(run_arguments_it!=debug_run_arguments.end()) run_arguments=run_arguments_it->second; if(run_arguments.empty()) { - run_arguments=cmake->get_executable(notebook.get_current_page()!=-1?notebook.get_current_view()->file_path:"").string(); + run_arguments=cmake->get_executable(Notebook::get().get_current_page()!=-1?Notebook::get().get_current_view()->file_path:"").string(); if(run_arguments.empty()) { Terminal::get().print("Could not find add_executable in the following paths:\n"); for(auto &path: cmake->paths) @@ -263,8 +254,8 @@ void Project::Clang::debug_start() { } auto breakpoints=std::make_shared > >(); - for(int c=0;cproject_path) { auto iter=view->get_buffer()->begin(); if(view->get_source_buffer()->get_source_marks_at_iter(iter, "debug_breakpoint").size()>0) @@ -274,30 +265,29 @@ void Project::Clang::debug_start() { } } - Project::get().debugging=true; + debugging=true; Terminal::get().print("Compiling and debugging "+run_arguments+"\n"); Terminal::get().async_process(Config::get().terminal.make_command, debug_build_path, [this, breakpoints, run_arguments, debug_build_path](int exit_status){ if(exit_status!=EXIT_SUCCESS) - Project::get().debugging=false; + debugging=false; else { debug_start_mutex.lock(); Debug::get().start(run_arguments, debug_build_path, *breakpoints, [this, run_arguments](int exit_status){ - Project::get().debugging=false; + debugging=false; Terminal::get().async_print(run_arguments+" returned: "+std::to_string(exit_status)+'\n'); }, [this](const std::string &status) { - auto &project=Project::get(); - project.debug_status_mutex.lock(); - project.debug_status=status; - project.debug_status_mutex.unlock(); - project.debug_update_status(); - }, [this](const boost::filesystem::path &file_path, int line_nr, int line_index) { - auto &project=Project::get(); - project.debug_stop_mutex.lock(); - project.debug_stop.first=file_path; - project.debug_stop.second.first=line_nr; - project.debug_stop.second.second=line_index; - project.debug_stop_mutex.unlock(); - project.debug_update_stop(); + dispatcher.add([this, status] { + debug_update_status(status); + }); + }, [this](const boost::filesystem::path &file_path, int line_nr, int line_index) { + dispatcher.add([this, file_path, line_nr, line_index] { + Project::debug_stop.first=file_path; + Project::debug_stop.second.first=line_nr; + Project::debug_stop.second.second=line_index; + + debug_update_stop(); + }); + }); debug_start_mutex.unlock(); } @@ -309,35 +299,35 @@ void Project::Clang::debug_continue() { } void Project::Clang::debug_stop() { - if(Project::get().debugging) + if(debugging) Debug::get().stop(); } void Project::Clang::debug_kill() { - if(Project::get().debugging) + if(debugging) Debug::get().kill(); } void Project::Clang::debug_step_over() { - if(Project::get().debugging) + if(debugging) Debug::get().step_over(); } void Project::Clang::debug_step_into() { - if(Project::get().debugging) + if(debugging) Debug::get().step_into(); } void Project::Clang::debug_step_out() { - if(Project::get().debugging) + if(debugging) Debug::get().step_out(); } void Project::Clang::debug_backtrace() { - if(Project::get().debugging && notebook.get_current_page()!=-1) { + if(debugging && Notebook::get().get_current_page()!=-1) { auto backtrace=Debug::get().get_backtrace(); - auto view=notebook.get_current_view(); + auto view=Notebook::get().get_current_view(); auto iter=view->get_iter_for_dialog(); view->selection_dialog=std::unique_ptr(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true)); auto rows=std::make_shared >(); @@ -364,9 +354,9 @@ void Project::Clang::debug_backtrace() { view->selection_dialog->on_select=[this, rows](const std::string& selected, bool hide_window) { auto frame=rows->at(selected); if(!frame.file_path.empty()) { - notebook.open(frame.file_path); - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + Notebook::get().open(frame.file_path); + if(Notebook::get().get_current_page()!=-1) { + auto view=Notebook::get().get_current_view(); Debug::get().select_frame(frame.index); @@ -374,7 +364,7 @@ void Project::Clang::debug_backtrace() { while(g_main_context_pending(NULL)) g_main_context_iteration(NULL, false); - if(notebook.get_current_page()!=-1 && notebook.get_current_view()==view) + if(Notebook::get().get_current_page()!=-1 && Notebook::get().get_current_view()==view) view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5); } } @@ -384,10 +374,10 @@ void Project::Clang::debug_backtrace() { } void Project::Clang::debug_show_variables() { - if(Project::get().debugging && notebook.get_current_page()!=-1) { + if(debugging && Notebook::get().get_current_page()!=-1) { auto variables=Debug::get().get_variables(); - auto view=notebook.get_current_view(); + auto view=Notebook::get().get_current_view(); auto iter=view->get_iter_for_dialog(); view->selection_dialog=std::unique_ptr(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true)); auto rows=std::make_shared >(); @@ -404,9 +394,9 @@ void Project::Clang::debug_show_variables() { view->selection_dialog->on_select=[this, rows](const std::string& selected, bool hide_window) { auto variable=rows->at(selected); if(!variable.file_path.empty()) { - notebook.open(variable.file_path); - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + Notebook::get().open(variable.file_path); + if(Notebook::get().get_current_page()!=-1) { + auto view=Notebook::get().get_current_view(); Debug::get().select_frame(variable.frame_index, variable.thread_index_id); @@ -414,7 +404,7 @@ void Project::Clang::debug_show_variables() { while(g_main_context_pending(NULL)) g_main_context_iteration(NULL, false); - if(notebook.get_current_page()!=-1 && notebook.get_current_view()==view) + if(Notebook::get().get_current_page()!=-1 && Notebook::get().get_current_view()==view) view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5); } } @@ -430,8 +420,8 @@ void Project::Clang::debug_show_variables() { debug_variable_tooltips.hide(); return; } - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + if(Notebook::get().get_current_page()!=-1) { + auto view=Notebook::get().get_current_view(); debug_variable_tooltips.clear(); auto create_tooltip_buffer=[this, rows, view, selected]() { auto variable=rows->at(selected); @@ -462,7 +452,7 @@ void Project::Clang::debug_show_variables() { } void Project::Clang::debug_run_command(const std::string &command) { - if(Project::get().debugging) { + if(debugging) { auto command_return=Debug::get().run_command(command); Terminal::get().async_print(command_return.first); Terminal::get().async_print(command_return.second, true); @@ -498,7 +488,7 @@ void Project::Markdown::compile_and_run() { } std::stringstream stdin_stream, stdout_stream; - auto exit_status=Terminal::get().process(stdin_stream, stdout_stream, "markdown "+notebook.get_current_view()->file_path.string()); + auto exit_status=Terminal::get().process(stdin_stream, stdout_stream, "markdown "+Notebook::get().get_current_view()->file_path.string()); if(exit_status==0) { boost::system::error_code ec; auto temp_path=boost::filesystem::temp_directory_path(ec); @@ -528,23 +518,23 @@ void Project::Markdown::compile_and_run() { } void Project::Python::compile_and_run() { - auto command="python "+notebook.get_current_view()->file_path.string(); + auto command="python "+Notebook::get().get_current_view()->file_path.string(); Terminal::get().print("Running "+command+"\n"); - Terminal::get().async_process(command, notebook.get_current_view()->file_path.parent_path(), [command](int exit_status) { + Terminal::get().async_process(command, Notebook::get().get_current_view()->file_path.parent_path(), [command](int exit_status) { Terminal::get().async_print(command+" returned: "+std::to_string(exit_status)+'\n'); }); } void Project::JavaScript::compile_and_run() { - auto command="node "+notebook.get_current_view()->file_path.string(); + auto command="node "+Notebook::get().get_current_view()->file_path.string(); Terminal::get().print("Running "+command+"\n"); - Terminal::get().async_process(command, notebook.get_current_view()->file_path.parent_path(), [command](int exit_status) { + Terminal::get().async_process(command, Notebook::get().get_current_view()->file_path.parent_path(), [command](int exit_status) { Terminal::get().async_print(command+" returned: "+std::to_string(exit_status)+'\n'); }); } void Project::HTML::compile_and_run() { - auto uri=notebook.get_current_view()->file_path.string(); + auto uri=Notebook::get().get_current_view()->file_path.string(); #ifdef __APPLE__ Terminal::get().process("open \""+uri+"\""); #else diff --git a/src/project.h b/src/project.h index 5370e2d..02476bb 100644 --- a/src/project.h +++ b/src/project.h @@ -2,43 +2,31 @@ #define JUCI_PROJECT_H_ #include -#include "notebook.h" #include "cmake.h" #include #include "directories.h" #include #include #include "tooltips.h" +#include "dispatcher.h" +#include class Project { private: - boost::filesystem::path debug_last_stop_file_path; - std::string debug_status; - std::mutex debug_status_mutex; - Glib::Dispatcher debug_update_status; - - Project(); - Notebook ¬ebook; //convenience reference + static boost::filesystem::path debug_last_stop_file_path; public: - static Project &get() { - static Project singleton; - return singleton; - } - - Gtk::Label debug_status_label; - std::pair > debug_stop; - std::mutex debug_stop_mutex; - Glib::Dispatcher debug_update_stop; - std::unordered_map run_arguments; - std::unordered_map debug_run_arguments; - std::atomic compiling; - std::atomic debugging; + static std::unordered_map run_arguments; + static std::unordered_map debug_run_arguments; + static std::atomic compiling; + static std::atomic debugging; + static std::pair > debug_stop; + static void debug_update_stop(); + static std::unique_ptr debug_status_label; + static void debug_update_status(const std::string &debug_status); class Language { - protected: - Notebook ¬ebook; //convenience reference public: - Language() : notebook(Notebook::get()) {} + Language() {} virtual ~Language() {} virtual std::pair get_run_arguments() {return {"", ""};} @@ -63,8 +51,11 @@ public: }; class Clang : public Language { + private: + Dispatcher dispatcher; public: Clang() : Language() {} + ~Clang() { dispatcher.disconnect(); } std::unique_ptr get_cmake(); @@ -121,7 +112,7 @@ public: void compile_and_run() override; }; - std::unique_ptr get_language(); + static std::unique_ptr get_language(); }; #endif // JUCI_PROJECT_H_ diff --git a/src/terminal.cc b/src/terminal.cc index 3738356..f3da34a 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -7,9 +7,6 @@ #endif Terminal::InProgress::InProgress(const std::string& start_msg): stop(false) { - waiting_print.connect([this](){ - Terminal::get().async_print(line_nr-1, "."); - }); start(start_msg); } @@ -24,8 +21,11 @@ void Terminal::InProgress::start(const std::string& msg) { wait_thread=std::thread([this](){ size_t c=0; while(!stop) { - if(c%100==0) - waiting_print(); + if(c%100==0) { + dispatcher.add([this] { + Terminal::get().print(line_nr-1, "."); + }); + } std::this_thread::sleep_for(std::chrono::milliseconds(10)); c++; } @@ -35,39 +35,24 @@ void Terminal::InProgress::start(const std::string& msg) { void Terminal::InProgress::done(const std::string& msg) { if(!stop) { stop=true; - Terminal::get().async_print(line_nr-1, msg); + dispatcher.add([this, msg] { + Terminal::get().print(line_nr-1, msg); + }); } } void Terminal::InProgress::cancel(const std::string& msg) { if(!stop) { stop=true; - Terminal::get().async_print(line_nr-1, msg); + dispatcher.add([this, msg] { + Terminal::get().print(line_nr-1, msg); + }); } } Terminal::Terminal() { bold_tag=get_buffer()->create_tag(); bold_tag->property_weight()=PANGO_WEIGHT_BOLD; - - async_print_dispatcher.connect([this](){ - async_print_strings_mutex.lock(); - if(async_print_strings.size()>0) { - for(auto &string_bold: async_print_strings) - print(string_bold.first, string_bold.second); - async_print_strings.clear(); - } - async_print_strings_mutex.unlock(); - }); - async_print_on_line_dispatcher.connect([this](){ - async_print_on_line_strings_mutex.lock(); - if(async_print_on_line_strings.size()>0) { - for(auto &line_string: async_print_on_line_strings) - print(line_string.first, line_string.second); - async_print_on_line_strings.clear(); - } - async_print_on_line_strings_mutex.unlock(); - }); } int Terminal::process(const std::string &command, const boost::filesystem::path &path, bool use_pipes) { @@ -251,25 +236,9 @@ std::shared_ptr Terminal::print_in_progress(std::string st } void Terminal::async_print(const std::string &message, bool bold) { - async_print_strings_mutex.lock(); - bool dispatch=true; - if(async_print_strings.size()>0) - dispatch=false; - async_print_strings.emplace_back(message, bold); - async_print_strings_mutex.unlock(); - if(dispatch) - async_print_dispatcher(); -} - -void Terminal::async_print(int line_nr, const std::string &message) { - async_print_on_line_strings_mutex.lock(); - bool dispatch=true; - if(async_print_on_line_strings.size()>0) - dispatch=false; - async_print_on_line_strings.emplace_back(line_nr, message); - async_print_on_line_strings_mutex.unlock(); - if(dispatch) - async_print_on_line_dispatcher(); + dispatcher.add([this, message, bold] { + Terminal::get().print(message, bold); + }); } bool Terminal::on_key_press_event(GdkEventKey *event) { diff --git a/src/terminal.h b/src/terminal.h index 5137510..fca6ec0 100644 --- a/src/terminal.h +++ b/src/terminal.h @@ -9,6 +9,7 @@ #include #include #include "process.hpp" +#include "dispatcher.h" class Terminal : public Gtk::TextView { public: @@ -22,7 +23,8 @@ public: void start(const std::string& msg); size_t line_nr; std::atomic stop; - Glib::Dispatcher waiting_print; + Dispatcher dispatcher; + std::thread wait_thread; }; @@ -44,16 +46,10 @@ public: void print(size_t line_nr, const std::string &message); std::shared_ptr print_in_progress(std::string start_msg); void async_print(const std::string &message, bool bold=false); - void async_print(int line_nr, const std::string &message); protected: bool on_key_press_event(GdkEventKey *event); private: - Glib::Dispatcher async_print_dispatcher; - Glib::Dispatcher async_print_on_line_dispatcher; - std::vector > async_print_strings; - std::vector > async_print_on_line_strings; - std::mutex async_print_strings_mutex; - std::mutex async_print_on_line_strings_mutex; + Dispatcher dispatcher; Glib::RefPtr bold_tag; std::vector > processes; diff --git a/src/window.cc b/src/window.cc index 1c208c5..9ca1113 100644 --- a/src/window.cc +++ b/src/window.cc @@ -25,7 +25,11 @@ Window::Window() : notebook(Notebook::get()) { JDEBUG("start"); set_title("juCi++"); set_events(Gdk::POINTER_MOTION_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::SCROLL_MASK|Gdk::LEAVE_NOTIFY_MASK); + + Project::debug_status_label=std::unique_ptr(new Gtk::Label()); + set_menu_actions(); + configure(); set_default_size(Config::get().window.default_size.first, Config::get().window.default_size.second); @@ -46,11 +50,12 @@ Window::Window() : notebook(Notebook::get()) { terminal_vbox.pack_start(terminal_scrolled_window); info_and_status_hbox.pack_start(notebook.info, Gtk::PACK_SHRINK); + #if GTK_VERSION_GE(3, 12) - info_and_status_hbox.set_center_widget(Project::get().debug_status_label); + info_and_status_hbox.set_center_widget(*Project::debug_status_label); #else Project::get().debug_status_label.set_halign(Gtk::Align::ALIGN_CENTER); - info_and_status_hbox.pack_start(Project::get().debug_status_label); + info_and_status_hbox.pack_start(*Project::debug_status_label); #endif info_and_status_hbox.pack_end(notebook.status, Gtk::PACK_SHRINK); terminal_vbox.pack_end(info_and_status_hbox, Gtk::PACK_SHRINK); @@ -504,7 +509,7 @@ void Window::set_menu_actions() { }); menu.add_action("project_set_run_arguments", [this]() { - auto project_language=Project::get().get_language(); + auto project_language=Project::get_language(); auto run_arguments=std::make_shared >(project_language->get_run_arguments()); if(run_arguments->second.empty()) return; @@ -517,7 +522,7 @@ void Window::set_menu_actions() { }; label_it->update(0, ""); entry_box.entries.emplace_back(run_arguments->second, [this, run_arguments](const std::string& content){ - Project::get().run_arguments[run_arguments->first]=content; + Project::run_arguments[run_arguments->first]=content; entry_box.hide(); }, 50); auto entry_it=entry_box.entries.begin(); @@ -528,23 +533,23 @@ void Window::set_menu_actions() { entry_box.show(); }); menu.add_action("compile_and_run", [this]() { - if(Project::get().compiling) + if(Project::compiling) return; if(Config::get().window.save_on_compile_or_run) notebook.save_project_files(); - project_language=Project::get().get_language(); + project_language=Project::get_language(); project_language->compile_and_run(); }); menu.add_action("compile", [this]() { - if(Project::get().compiling) + if(Project::compiling) return; if(Config::get().window.save_on_compile_or_run) notebook.save_project_files(); - project_language=Project::get().get_language(); + project_language=Project::get_language(); project_language->compile(); }); @@ -585,7 +590,7 @@ void Window::set_menu_actions() { #ifdef JUCI_ENABLE_DEBUG menu.add_action("debug_set_run_arguments", [this]() { - auto project_language=Project::get().get_language(); + auto project_language=Project::get_language(); auto run_arguments=std::make_shared >(project_language->debug_get_run_arguments()); if(run_arguments->second.empty()) return; @@ -598,7 +603,7 @@ void Window::set_menu_actions() { }; label_it->update(0, ""); entry_box.entries.emplace_back(run_arguments->second, [this, run_arguments](const std::string& content){ - Project::get().debug_run_arguments[run_arguments->first]=content; + Project::debug_run_arguments[run_arguments->first]=content; entry_box.hide(); }, 50); auto entry_it=entry_box.entries.begin(); @@ -609,7 +614,7 @@ void Window::set_menu_actions() { entry_box.show(); }); menu.add_action("debug_start_continue", [this](){ - if(Project::get().debugging) { + if(Project::debugging) { project_language->debug_continue(); return; } @@ -617,7 +622,7 @@ void Window::set_menu_actions() { if(Config::get().window.save_on_compile_or_run) notebook.save_project_files(); - project_language=Project::get().get_language(); + project_language=Project::get_language(); project_language->debug_start(); }); @@ -687,18 +692,14 @@ void Window::set_menu_actions() { } }); menu.add_action("debug_goto_stop", [this](){ - if(Project::get().debugging) { - auto &project=Project::get(); - project.debug_stop_mutex.lock(); - auto debug_stop_copy=project.debug_stop; - project.debug_stop_mutex.unlock(); - if(!debug_stop_copy.first.empty()) { - notebook.open(debug_stop_copy.first); + if(Project::debugging) { + if(!Project::debug_stop.first.empty()) { + notebook.open(Project::debug_stop.first); if(notebook.get_current_page()!=-1) { auto view=notebook.get_current_view(); - int line_nr=debug_stop_copy.second.first-1; - int line_index=debug_stop_copy.second.second-1; + int line_nr=Project::debug_stop.second.first-1; + int line_index=Project::debug_stop.second.second-1; if(line_nrget_buffer()->get_line_count()) { auto iter=view->get_buffer()->get_iter_at_line(line_nr); auto end_line_iter=iter; @@ -713,11 +714,13 @@ void Window::set_menu_actions() { if(notebook.get_current_page()!=-1 && notebook.get_current_view()==view) view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5); } - project.debug_update_stop(); + Project::debug_update_stop(); } } } }); + + Project::debug_update_status(""); #endif menu.add_action("next_tab", [this]() {