diff --git a/src/dialogs.cc b/src/dialogs.cc index a62c9ac..32d234b 100644 --- a/src/dialogs.cc +++ b/src/dialogs.cc @@ -1,5 +1,6 @@ #include "dialogs.h" #include "window.h" +#include "notebook.h" #include namespace sigc { @@ -34,7 +35,7 @@ std::string Dialog::gtk_dialog(const std::string &title, dialog.set_transient_for(Window::get()); - auto current_path=Window::get().notebook.get_current_folder(); + auto current_path=Notebook::get().get_current_folder(); boost::system::error_code ec; if(current_path.empty()) current_path=boost::filesystem::current_path(ec); diff --git a/src/juci.cc b/src/juci.cc index 3c52331..db28c40 100644 --- a/src/juci.cc +++ b/src/juci.cc @@ -1,5 +1,6 @@ #include "juci.h" #include "window.h" +#include "notebook.h" #include "directories.h" #include "menu.h" #include "config.h" @@ -68,7 +69,7 @@ void Application::on_activate() { } for(auto &file: files) - Window::get().notebook.open(file); + Notebook::get().open(file); for(auto &error: errors) Terminal::get().print(error, true); diff --git a/src/notebook.h b/src/notebook.h index 1b6f2d8..17dde63 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -16,8 +16,15 @@ class Notebook : public Gtk::Notebook { Gtk::Label label; Gtk::Button button; }; -public: + +private: Notebook(); +public: + static Notebook &get() { + static Notebook singleton; + return singleton; + } + Source::View* get_view(int page); size_t get_index(int page); int size(); diff --git a/src/project.cc b/src/project.cc index 61310bd..83389e3 100644 --- a/src/project.cc +++ b/src/project.cc @@ -3,16 +3,98 @@ #include "terminal.h" #include "filesystem.h" #include +#include "menu.h" #ifdef JUCI_ENABLE_DEBUG #include "debug.h" #endif -std::unordered_map Project::run_arguments; -std::unordered_map Project::debug_run_arguments; -std::atomic Project::compiling(false); -std::atomic Project::debugging(false); +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; + } + } + //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(); + }); +} -std::unique_ptr ProjectClang::get_cmake() { +std::unique_ptr Project::get_language() { + if(notebook.get_current_page()!=-1) { + auto language_id=notebook.get_current_view()->language->get_id(); + if(language_id=="markdown") + return std::unique_ptr(new Project::Markdown()); + if(language_id=="python") + return std::unique_ptr(new Project::Python()); + if(language_id=="js") + return std::unique_ptr(new Project::JavaScript()); + if(language_id=="html") + return std::unique_ptr(new Project::HTML()); + } + + return std::unique_ptr(new Project::Clang()); +} + +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(); @@ -28,15 +110,15 @@ std::unique_ptr ProjectClang::get_cmake() { return cmake; } -std::pair ProjectClang::get_run_arguments() { +std::pair Project::Clang::get_run_arguments() { auto cmake=get_cmake(); if(!cmake) return {"", ""}; auto project_path=cmake->project_path.string(); - auto run_arguments_it=run_arguments.find(project_path); + auto run_arguments_it=Project::get().run_arguments.find(project_path); std::string arguments; - if(run_arguments_it!=run_arguments.end()) + if(run_arguments_it!=Project::get().run_arguments.end()) arguments=run_arguments_it->second; if(arguments.empty()) { @@ -59,7 +141,7 @@ std::pair ProjectClang::get_run_arguments() { return {project_path, arguments}; } -void ProjectClang::compile() { +void Project::Clang::compile() { auto cmake=get_cmake(); if(!cmake) return; @@ -67,14 +149,14 @@ void ProjectClang::compile() { auto default_build_path=CMake::get_default_build_path(cmake->project_path); if(default_build_path.empty()) return; - compiling=true; + Project::get().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) { - compiling=false; + Project::get().compiling=false; }); } -void ProjectClang::compile_and_run() { +void Project::Clang::compile_and_run() { auto cmake=get_cmake(); if(!cmake) return; @@ -84,9 +166,9 @@ void ProjectClang::compile_and_run() { if(default_build_path.empty()) return; - auto run_arguments_it=run_arguments.find(project_path.string()); + auto run_arguments_it=Project::get().run_arguments.find(project_path.string()); std::string arguments; - if(run_arguments_it!=run_arguments.end()) + if(run_arguments_it!=Project::get().run_arguments.end()) arguments=run_arguments_it->second; if(arguments.empty()) { @@ -104,10 +186,10 @@ void ProjectClang::compile_and_run() { arguments=filesystem::escape_argument(arguments); } - compiling=true; + Project::get().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){ - compiling=false; + Project::get().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'); @@ -117,15 +199,15 @@ void ProjectClang::compile_and_run() { } #ifdef JUCI_ENABLE_DEBUG -std::pair ProjectClang::debug_get_run_arguments() { +std::pair Project::Clang::debug_get_run_arguments() { auto cmake=get_cmake(); if(!cmake) return {"", ""}; auto project_path=cmake->project_path.string(); - auto run_arguments_it=debug_run_arguments.find(project_path); + auto run_arguments_it=Project::get().debug_run_arguments.find(project_path); std::string arguments; - if(run_arguments_it!=debug_run_arguments.end()) + if(run_arguments_it!=Project::get().debug_run_arguments.end()) arguments=run_arguments_it->second; if(arguments.empty()) { @@ -148,8 +230,7 @@ std::pair ProjectClang::debug_get_run_arguments() { return {project_path, arguments}; } -void ProjectClang::debug_start(std::function status_callback, - std::function stop_callback) { +void Project::Clang::debug_start() { auto cmake=get_cmake(); if(!cmake) return; @@ -161,9 +242,9 @@ void ProjectClang::debug_start(std::function st if(!CMake::create_debug_build(project_path)) return; - auto run_arguments_it=debug_run_arguments.find(project_path.string()); + auto run_arguments_it=Project::get().debug_run_arguments.find(project_path.string()); std::string run_arguments; - if(run_arguments_it!=debug_run_arguments.end()) + if(run_arguments_it!=Project::get().debug_run_arguments.end()) run_arguments=run_arguments_it->second; if(run_arguments.empty()) { @@ -193,53 +274,67 @@ void ProjectClang::debug_start(std::function st } } - debugging=true; + Project::get().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, status_callback, stop_callback](int exit_status){ + 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) - debugging=false; + Project::get().debugging=false; else { debug_start_mutex.lock(); Debug::get().start(run_arguments, debug_build_path, *breakpoints, [this, run_arguments](int exit_status){ - debugging=false; + Project::get().debugging=false; Terminal::get().async_print(run_arguments+" returned: "+std::to_string(exit_status)+'\n'); - }, status_callback, stop_callback); + }, [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(); + }); debug_start_mutex.unlock(); } }); } -void ProjectClang::debug_continue() { +void Project::Clang::debug_continue() { Debug::get().continue_debug(); } -void ProjectClang::debug_stop() { - if(debugging) +void Project::Clang::debug_stop() { + if(Project::get().debugging) Debug::get().stop(); } -void ProjectClang::debug_kill() { - if(debugging) +void Project::Clang::debug_kill() { + if(Project::get().debugging) Debug::get().kill(); } -void ProjectClang::debug_step_over() { - if(debugging) +void Project::Clang::debug_step_over() { + if(Project::get().debugging) Debug::get().step_over(); } -void ProjectClang::debug_step_into() { - if(debugging) +void Project::Clang::debug_step_into() { + if(Project::get().debugging) Debug::get().step_into(); } -void ProjectClang::debug_step_out() { - if(debugging) +void Project::Clang::debug_step_out() { + if(Project::get().debugging) Debug::get().step_out(); } -void ProjectClang::debug_backtrace() { - if(debugging && notebook.get_current_page()!=-1) { +void Project::Clang::debug_backtrace() { + if(Project::get().debugging && notebook.get_current_page()!=-1) { auto backtrace=Debug::get().get_backtrace(); auto view=notebook.get_current_view(); @@ -288,8 +383,8 @@ void ProjectClang::debug_backtrace() { } } -void ProjectClang::debug_show_variables() { - if(debugging && notebook.get_current_page()!=-1) { +void Project::Clang::debug_show_variables() { + if(Project::get().debugging && notebook.get_current_page()!=-1) { auto variables=Debug::get().get_variables(); auto view=notebook.get_current_view(); @@ -366,29 +461,62 @@ void ProjectClang::debug_show_variables() { } } -void ProjectClang::debug_run_command(const std::string &command) { - if(debugging) { +void Project::Clang::debug_run_command(const std::string &command) { + if(Project::get().debugging) { auto command_return=Debug::get().run_command(command); Terminal::get().async_print(command_return.first); Terminal::get().async_print(command_return.second, true); } } -void ProjectClang::debug_delete() { +void Project::Clang::debug_goto_stop() { + 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(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; + if(line_nrget_buffer()->get_line_count()) { + auto iter=view->get_buffer()->get_iter_at_line(line_nr); + auto end_line_iter=iter; + while(!iter.ends_line() && iter.forward_char()) {} + auto line=view->get_buffer()->get_text(iter, end_line_iter); + if(static_cast(line_index)>=line.bytes()) + line_index=0; + view->get_buffer()->place_cursor(view->get_buffer()->get_iter_at_line_index(line_nr, line_index)); + + while(g_main_context_pending(NULL)) + g_main_context_iteration(NULL, false); + 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(); + } + } + } +} + +void Project::Clang::debug_delete() { debug_start_mutex.lock(); Debug::get().delete_debug(); debug_start_mutex.unlock(); } #endif -ProjectMarkdown::~ProjectMarkdown() { +Project::Markdown::~Markdown() { if(!last_temp_path.empty()) { boost::filesystem::remove(last_temp_path); last_temp_path=boost::filesystem::path(); } } -void ProjectMarkdown::compile_and_run() { +void Project::Markdown::compile_and_run() { if(!last_temp_path.empty()) { boost::filesystem::remove(last_temp_path); last_temp_path=boost::filesystem::path(); @@ -424,7 +552,7 @@ void ProjectMarkdown::compile_and_run() { } } -void ProjectPython::compile_and_run() { +void Project::Python::compile_and_run() { auto command="python "+notebook.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) { @@ -432,7 +560,7 @@ void ProjectPython::compile_and_run() { }); } -void ProjectJavaScript::compile_and_run() { +void Project::JavaScript::compile_and_run() { auto command="node "+notebook.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) { @@ -440,7 +568,7 @@ void ProjectJavaScript::compile_and_run() { }); } -void ProjectHTML::compile_and_run() { +void Project::HTML::compile_and_run() { auto uri=notebook.get_current_view()->file_path.string(); #ifdef __APPLE__ Terminal::get().process("open \""+uri+"\""); diff --git a/src/project.h b/src/project.h index c6eded8..9e2b14f 100644 --- a/src/project.h +++ b/src/project.h @@ -1,6 +1,7 @@ #ifndef JUCI_PROJECT_H_ #define JUCI_PROJECT_H_ +#include #include "notebook.h" #include "cmake.h" #include @@ -10,93 +11,115 @@ #include "tooltips.h" class Project { -public: - Project(Notebook ¬ebook) : notebook(notebook) {} - virtual ~Project() {} - - Notebook ¬ebook; - - static std::unordered_map run_arguments; - static std::unordered_map debug_run_arguments; - static std::atomic compiling; - static std::atomic debugging; - - virtual std::pair get_run_arguments() {return {"", ""};} - virtual void compile() {} - virtual void compile_and_run() {} - - virtual std::pair debug_get_run_arguments() {return {"", ""};} - Tooltips debug_variable_tooltips; - virtual void debug_start(std::function status_callback, - std::function stop_callback) {} - virtual void debug_continue() {} - virtual void debug_stop() {} - virtual void debug_kill() {} - virtual void debug_step_over() {} - virtual void debug_step_into() {} - virtual void debug_step_out() {} - virtual void debug_backtrace() {} - virtual void debug_show_variables() {} - virtual void debug_run_command(const std::string &command) {} - virtual void debug_delete() {} -}; +private: + std::pair > debug_stop; + std::mutex debug_stop_mutex; + boost::filesystem::path debug_last_stop_file_path; + Glib::Dispatcher debug_update_stop; + std::string debug_status; + std::mutex debug_status_mutex; + Glib::Dispatcher debug_update_status; -class ProjectClang : public Project { + Project(); + Notebook ¬ebook; //convenience reference public: - ProjectClang(Notebook ¬ebook) : Project(notebook) {} + static Project &get() { + static Project singleton; + return singleton; + } + + Gtk::Label debug_status_label; + std::unordered_map run_arguments; + std::unordered_map debug_run_arguments; + std::atomic compiling; + std::atomic debugging; - std::unique_ptr get_cmake(); + class Language { + protected: + Notebook ¬ebook; //convenience reference + public: + Language() : notebook(Notebook::get()) {} + virtual ~Language() {} + + virtual std::pair get_run_arguments() {return {"", ""};} + virtual void compile() {} + virtual void compile_and_run() {} + + virtual std::pair debug_get_run_arguments() {return {"", ""};} + Tooltips debug_variable_tooltips; + virtual void debug_start() {} + virtual void debug_continue() {} + virtual void debug_stop() {} + virtual void debug_kill() {} + virtual void debug_step_over() {} + virtual void debug_step_into() {} + virtual void debug_step_out() {} + virtual void debug_backtrace() {} + virtual void debug_show_variables() {} + virtual void debug_run_command(const std::string &command) {} + virtual void debug_goto_stop() {} + virtual void debug_delete() {} + }; - std::pair get_run_arguments() override; - void compile() override; - void compile_and_run() override; + class Clang : public Language { + public: + Clang() : Language() {} + + std::unique_ptr get_cmake(); + + std::pair get_run_arguments() override; + void compile() override; + void compile_and_run() override; + + std::mutex debug_start_mutex; + #ifdef JUCI_ENABLE_DEBUG + std::pair debug_get_run_arguments() override; + void debug_start() override; + void debug_continue() override; + void debug_stop() override; + void debug_kill() override; + void debug_step_over() override; + void debug_step_into() override; + void debug_step_out() override; + void debug_backtrace() override; + void debug_show_variables() override; + void debug_run_command(const std::string &command) override; + void debug_goto_stop() override; + void debug_delete() override; + #endif + }; - std::mutex debug_start_mutex; -#ifdef JUCI_ENABLE_DEBUG - std::pair debug_get_run_arguments() override; - void debug_start(std::function status_callback, - std::function stop_callback) override; - void debug_continue() override; - void debug_stop() override; - void debug_kill() override; - void debug_step_over() override; - void debug_step_into() override; - void debug_step_out() override; - void debug_backtrace() override; - void debug_show_variables() override; - void debug_run_command(const std::string &command) override; - void debug_delete() override; -#endif -}; - -class ProjectMarkdown : public Project { -public: - ProjectMarkdown(Notebook ¬ebook) : Project(notebook) {} - ~ProjectMarkdown(); + class Markdown : public Language { + public: + Markdown() : Language() {} + ~Markdown(); + + boost::filesystem::path last_temp_path; + void compile_and_run() override; + }; - boost::filesystem::path last_temp_path; - void compile_and_run() override; -}; - -class ProjectPython : public Project { -public: - ProjectPython(Notebook ¬ebook) : Project(notebook) {} + class Python : public Language { + public: + Python() : Language() {} + + void compile_and_run() override; + }; - void compile_and_run() override; -}; - -class ProjectJavaScript : public Project { -public: - ProjectJavaScript(Notebook ¬ebook) : Project(notebook) {} + class JavaScript : public Language { + public: + JavaScript() : Language() {} + + void compile_and_run() override; + }; - void compile_and_run() override; -}; - -class ProjectHTML : public Project { -public: - ProjectHTML(Notebook ¬ebook) : Project(notebook) {} + class HTML : public Language { + public: + HTML() : Language() {} + + void compile_and_run() override; + }; - void compile_and_run() override; + std::unique_ptr get_language(); }; #endif // JUCI_PROJECT_H_ diff --git a/src/window.cc b/src/window.cc index 1da6258..d583fc1 100644 --- a/src/window.cc +++ b/src/window.cc @@ -24,7 +24,7 @@ namespace sigc { #endif } -Window::Window() { +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); @@ -50,7 +50,7 @@ Window::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(debug_status_label); + info_and_status_hbox.set_center_widget(Project::get().debug_status_label); #else debug_status_label.set_halign(Gtk::Align::ALIGN_CENTER); info_and_status_hbox.pack_start(debug_status_label); @@ -121,74 +121,6 @@ Window::Window() { about.hide(); }); - 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; - } - } - //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(); - }); - about.set_version(Config::get().window.version); about.set_authors({"(in order of appearance)", "Ted Johan Kristoffersen", @@ -575,8 +507,8 @@ void Window::set_menu_actions() { }); menu.add_action("project_set_run_arguments", [this]() { - project=get_project(); - auto run_arguments=std::make_shared >(project->get_run_arguments()); + auto project_language=Project::get().get_language(); + auto run_arguments=std::make_shared >(project_language->get_run_arguments()); if(run_arguments->second.empty()) return; @@ -588,7 +520,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::run_arguments[run_arguments->first]=content; + Project::get().run_arguments[run_arguments->first]=content; entry_box.hide(); }, 50); auto entry_it=entry_box.entries.begin(); @@ -599,24 +531,24 @@ void Window::set_menu_actions() { entry_box.show(); }); menu.add_action("compile_and_run", [this]() { - if(Project::compiling) + if(Project::get().compiling) return; if(Config::get().window.save_on_compile_or_run) notebook.save_project_files(); - project=get_project(); - project->compile_and_run(); + project_language=Project::get().get_language(); + project_language->compile_and_run(); }); menu.add_action("compile", [this]() { - if(Project::compiling) + if(Project::get().compiling) return; if(Config::get().window.save_on_compile_or_run) notebook.save_project_files(); - project=get_project(); - project->compile(); + project_language=Project::get().get_language(); + project_language->compile(); }); menu.add_action("run_command", [this]() { @@ -656,8 +588,8 @@ void Window::set_menu_actions() { #ifdef JUCI_ENABLE_DEBUG menu.add_action("debug_set_run_arguments", [this]() { - project=get_project(); - auto run_arguments=std::make_shared >(project->debug_get_run_arguments()); + auto project_language=Project::get().get_language(); + auto run_arguments=std::make_shared >(project_language->debug_get_run_arguments()); if(run_arguments->second.empty()) return; @@ -669,7 +601,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::debug_run_arguments[run_arguments->first]=content; + Project::get().debug_run_arguments[run_arguments->first]=content; entry_box.hide(); }, 50); auto entry_it=entry_box.entries.begin(); @@ -680,64 +612,52 @@ void Window::set_menu_actions() { entry_box.show(); }); menu.add_action("debug_start_continue", [this](){ - if(Project::debugging) { - project->debug_continue(); + if(Project::get().debugging) { + project_language->debug_continue(); return; } if(Config::get().window.save_on_compile_or_run) notebook.save_project_files(); - project=get_project(); + project_language=Project::get().get_language(); - project->debug_start([this](const std::string &status) { - debug_status_mutex.lock(); - debug_status=status; - debug_status_mutex.unlock(); - debug_update_status(); - }, [this](const boost::filesystem::path &file_path, int line_nr, int line_index) { - debug_stop_mutex.lock(); - debug_stop.first=file_path; - debug_stop.second.first=line_nr; - debug_stop.second.second=line_index; - debug_stop_mutex.unlock(); - debug_update_stop(); - }); + project_language->debug_start(); }); menu.add_action("debug_stop", [this]() { - if(project) - project->debug_stop(); + if(project_language) + project_language->debug_stop(); }); menu.add_action("debug_kill", [this]() { - if(project) - project->debug_kill(); + if(project_language) + project_language->debug_kill(); }); menu.add_action("debug_step_over", [this]() { - if(project) - project->debug_step_over(); + if(project_language) + project_language->debug_step_over(); }); menu.add_action("debug_step_into", [this]() { - if(project) - project->debug_step_into(); + if(project_language) + project_language->debug_step_into(); }); menu.add_action("debug_step_out", [this]() { - if(project) - project->debug_step_out(); + if(project_language) + project_language->debug_step_out(); }); menu.add_action("debug_backtrace", [this]() { - if(project) - project->debug_backtrace(); + if(project_language) + project_language->debug_backtrace(); }); menu.add_action("debug_show_variables", [this]() { - if(project) - project->debug_show_variables(); + if(project_language) + project_language->debug_show_variables(); }); menu.add_action("debug_run_command", [this]() { entry_box.clear(); entry_box.entries.emplace_back(last_run_debug_command, [this](const std::string& content){ if(content!="") { - if(project) - project->debug_run_command(content); + if(project_language) + project_language->debug_run_command(content); last_run_debug_command=content; } entry_box.hide(); @@ -773,35 +693,8 @@ void Window::set_menu_actions() { } }); menu.add_action("debug_goto_stop", [this](){ - if(project && project->debugging) { - debug_stop_mutex.lock(); - auto debug_stop_copy=debug_stop; - debug_stop_mutex.unlock(); - if(!debug_stop_copy.first.empty()) { - notebook.open(debug_stop_copy.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; - if(line_nrget_buffer()->get_line_count()) { - auto iter=view->get_buffer()->get_iter_at_line(line_nr); - auto end_line_iter=iter; - while(!iter.ends_line() && iter.forward_char()) {} - auto line=view->get_buffer()->get_text(iter, end_line_iter); - if(static_cast(line_index)>=line.bytes()) - line_index=0; - view->get_buffer()->place_cursor(view->get_buffer()->get_iter_at_line_index(line_nr, line_index)); - - while(g_main_context_pending(NULL)) - g_main_context_iteration(NULL, false); - 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); - } - debug_update_stop(); - } - } - } + if(project_language) + project_language->debug_goto_stop(); }); #endif @@ -899,8 +792,8 @@ bool Window::on_delete_event(GdkEventAny *event) { } Terminal::get().kill_async_processes(); #ifdef JUCI_ENABLE_DEBUG - if(project) - project->debug_delete(); + if(project_language) + project_language->debug_delete(); #endif return false; } @@ -1126,19 +1019,3 @@ void Window::rename_token_entry() { } } } - -std::unique_ptr Window::get_project() { - if(notebook.get_current_page()!=-1) { - auto language_id=notebook.get_current_view()->language->get_id(); - if(language_id=="markdown") - return std::unique_ptr(new ProjectMarkdown(notebook)); - if(language_id=="python") - return std::unique_ptr(new ProjectPython(notebook)); - if(language_id=="js") - return std::unique_ptr(new ProjectJavaScript(notebook)); - if(language_id=="html") - return std::unique_ptr(new ProjectHTML(notebook)); - } - - return std::unique_ptr(new ProjectClang(notebook)); -} diff --git a/src/window.h b/src/window.h index 4fbfce5..191b592 100644 --- a/src/window.h +++ b/src/window.h @@ -1,7 +1,7 @@ #ifndef JUCI_WINDOW_H_ #define JUCI_WINDOW_H_ -#include "gtkmm.h" +#include #include "entrybox.h" #include "notebook.h" #include "cmake.h" @@ -11,13 +11,12 @@ class Window : public Gtk::ApplicationWindow { private: Window(); + Notebook ¬ebook; //convenience reference public: static Window &get() { static Window singleton; return singleton; } - - Notebook notebook; protected: bool on_key_press_event(GdkEventKey *event) override; @@ -34,17 +33,7 @@ private: Gtk::AboutDialog about; EntryBox entry_box; - std::unique_ptr project; - - Gtk::Label debug_status_label; - - std::pair > debug_stop; - boost::filesystem::path debug_last_stop_file_path; - std::mutex debug_stop_mutex; - Glib::Dispatcher debug_update_stop; - std::string debug_status; - std::mutex debug_status_mutex; - Glib::Dispatcher debug_update_status; + std::unique_ptr project_language; void configure(); void set_menu_actions(); @@ -60,8 +49,6 @@ private: bool case_sensitive_search=true; bool regex_search=false; bool search_entry_shown=false; - - std::unique_ptr get_project(); }; #endif // JUCI_WINDOW_H