From d18e8bef2c627f5e5817580da6b4d271b946c6ed Mon Sep 17 00:00:00 2001 From: eidheim Date: Wed, 1 Jun 2016 14:04:35 +0200 Subject: [PATCH] Added split window, fixes #235 --- src/directories.cc | 6 +- src/files.h | 5 +- src/juci.cc | 17 +-- src/juci.h | 2 +- src/menu.cc | 7 + src/notebook.cc | 345 +++++++++++++++++++++++++++++++++------------ src/notebook.h | 43 ++++-- src/project.cc | 56 ++++---- src/project.h | 2 +- src/terminal.cc | 3 +- src/window.cc | 307 ++++++++++++++++++---------------------- src/window.h | 2 - 12 files changed, 470 insertions(+), 325 deletions(-) diff --git a/src/directories.cc b/src/directories.cc index c4eb949..f3e08fa 100644 --- a/src/directories.cc +++ b/src/directories.cc @@ -85,7 +85,7 @@ bool Directories::TreeStore::drag_data_received_vfunc(const TreeModel::Path &pat return false; } - for(int c=0;cfile_path, source_path)) { @@ -320,7 +320,7 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) { update(); select(target_path); - for(int c=0;cfile_path, *source_path)) { @@ -379,7 +379,7 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) { else { update(); - for(int c=0;c -#define JUCI_VERSION "1.1.3-4" +#define JUCI_VERSION "1.1.3-5" const std::string default_config_file = R"RAW({ "version": ")RAW"+std::string(JUCI_VERSION)+R"RAW(", @@ -132,7 +132,8 @@ R"RAW( "previous_tab": "Left",)RAW" #endif R"RAW( - "close_tab": "w" + "close_tab": "w", + "window_toggle_split": "" }, "project": { "default_build_path_comment": "Use to insert the project top level directory name", diff --git a/src/juci.cc b/src/juci.cc index 2b04470..4deab78 100644 --- a/src/juci.cc +++ b/src/juci.cc @@ -19,7 +19,7 @@ int Application::on_command_line(const Glib::RefPtr if(boost::filesystem::exists(p)) { p=boost::filesystem::canonical(p); if(boost::filesystem::is_regular_file(p)) - files.emplace_back(p); + files.emplace_back(p, 0); else if(boost::filesystem::is_directory(p)) directories.emplace_back(p); } @@ -29,7 +29,7 @@ int Application::on_command_line(const Glib::RefPtr auto new_p=boost::filesystem::canonical(parent_p, ec); if(!ec && boost::filesystem::is_directory(new_p)) { new_p/=p.filename(); - files.emplace_back(new_p); + files.emplace_back(new_p, 0); } else errors.emplace_back("Error: folder path "+parent_p.string()+" does not exist.\n"); @@ -53,10 +53,11 @@ void Application::on_activate() { auto folder=pt.get("folder"); if(!folder.empty() && boost::filesystem::exists(folder) && boost::filesystem::is_directory(folder)) directories.emplace_back(folder); - for(auto &v: pt.get_child("files")) { - std::string file=v.second.data(); + for(auto &pt_file: pt.get_child("files")) { + auto notebook=pt_file.second.get("notebook", -1); + auto file=pt_file.second.get("file", ""); if(!file.empty() && boost::filesystem::exists(file) && !boost::filesystem::is_directory(file)) - files.emplace_back(file); + files.emplace_back(file, notebook); } last_current_file=pt.get("current_file"); if(!boost::filesystem::exists(last_current_file) || boost::filesystem::is_directory(last_current_file)) @@ -74,8 +75,8 @@ void Application::on_activate() { else { std::string files_in_directory; for(auto it=files.begin();it!=files.end();) { - if(it->generic_string().substr(0, directory.generic_string().size()+1)==directory.generic_string()+'/') { - files_in_directory+=" "+it->string(); + if(it->first.generic_string().substr(0, directory.generic_string().size()+1)==directory.generic_string()+'/') { + files_in_directory+=" "+it->first.string(); it=files.erase(it); } else @@ -90,7 +91,7 @@ void Application::on_activate() { } for(auto &file: files) - Notebook::get().open(file); + Notebook::get().open(file.first, file.second); for(auto &error: errors) Terminal::get().print(error, true); diff --git a/src/juci.h b/src/juci.h index 872b5ad..b56033f 100644 --- a/src/juci.h +++ b/src/juci.h @@ -39,7 +39,7 @@ public: void on_startup() override; private: std::vector directories; - std::vector files; + std::vector > files; std::vector errors; }; diff --git a/src/menu.cc b/src/menu.cc index f0665b9..6bddad0 100644 --- a/src/menu.cc +++ b/src/menu.cc @@ -382,6 +382,13 @@ Menu::Menu() { +accels["close_tab"]+ //For Ubuntu... " " " " + "
" + " " + " _Toggle _Split" + " app.window_toggle_split" + +accels["window_toggle_split"]+ //For Ubuntu... + " " + "
" " " " " ""; diff --git a/src/notebook.cc b/src/notebook.cc index d2cfe0a..03ce883 100644 --- a/src/notebook.cc +++ b/src/notebook.cc @@ -50,50 +50,88 @@ Notebook::TabLabel::TabLabel(const boost::filesystem::path &path, std::function< show_all(); } -Notebook::Notebook() : Gtk::Notebook(), last_index(-1) { +Notebook::Notebook() : Gtk::HPaned(), notebooks(2) { Gsv::init(); - set_scrollable(); - - auto provider = Gtk::CssProvider::create(); - //GtkNotebook-tab-overlap got removed in gtk 3.20, but margin works in 3.20 + for(auto ¬ebook: notebooks) { + notebook.set_scrollable(); + notebook.set_group_name("source_notebooks"); + notebook.signal_switch_page().connect([this](Gtk::Widget *widget, guint) { + //Sometimes focus is lost when tabs are reordered + auto hbox=dynamic_cast(widget); + for(size_t c=0;c(widget); + for(size_t c=0;cload_from_data("tab {border-radius: 5px 5px 0 0; padding: 0 4px; margin: 0;}"); + provider->load_from_data("tab {border-radius: 5px 5px 0 0; padding: 0 4px; margin: 0;}"); #else - provider->load_from_data(".notebook {-GtkNotebook-tab-overlap: 0px;} tab {border-radius: 5px 5px 0 0; padding: 4px 4px;}"); + provider->load_from_data(".notebook {-GtkNotebook-tab-overlap: 0px;} tab {border-radius: 5px 5px 0 0; padding: 4px 4px;}"); #endif - get_style_context()->add_provider(provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - - signal_switch_page().connect([this](Gtk::Widget* page, guint page_num) { - last_index=-1; - }); + notebook.get_style_context()->add_provider(provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + } + pack1(notebooks[0], true, true); } -int Notebook::size() { - return get_n_pages(); +size_t Notebook::size() { + return static_cast(source_views.size()); } -Source::View* Notebook::get_view(int page) { - return source_views.at(get_index(page)); +Source::View* Notebook::get_view(size_t index) { + if(index>=size()) + return nullptr; + return source_views[index]; } -size_t Notebook::get_index(int page) { - for(size_t c=0;chas_focus()) + return view; } - return -1; + for(auto &view: source_views) { + if(view==last_focused_view) + return view; + } + if(!source_views.empty()) + return source_views.back(); + return nullptr; } -Source::View* Notebook::get_current_view() { - return get_view(get_current_page()); +std::vector &Notebook::get_views() { + return source_views; } -void Notebook::open(const boost::filesystem::path &file_path) { - for(int c=0;cfile_path) { - set_current_page(c); - get_current_view()->grab_focus(); +void Notebook::open(const boost::filesystem::path &file_path, size_t notebook_index) { + if(notebook_index==1 && !split) + toggle_split(); + + for(size_t c=0;cfile_path) { + auto notebook_page=get_notebook_page(c); + notebooks[notebook_page.first].set_current_page(notebook_page.second); + focus_view(source_views[c]); return; } } @@ -107,6 +145,8 @@ void Notebook::open(const boost::filesystem::path &file_path) { can_read.close(); } + auto last_view=get_current_view(); + auto language=Source::guess_language(file_path); if(language && (language->get_id()=="chdr" || language->get_id()=="cpphdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc")) source_views.emplace_back(new Source::ClangView(file_path, language)); @@ -116,7 +156,7 @@ void Notebook::open(const boost::filesystem::path &file_path) { source_views.back()->scroll_to_cursor_delayed=[this](Source::View* view, bool center, bool show_tooltips) { while(g_main_context_pending(NULL)) g_main_context_iteration(NULL, false); - if(get_current_page()!=-1 && get_current_view()==view) { + if(get_current_view()==view) { if(center) view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5); else @@ -126,11 +166,11 @@ void Notebook::open(const boost::filesystem::path &file_path) { } }; source_views.back()->on_update_status=[this](Source::View* view, const std::string &status_text) { - if(get_current_page()!=-1 && get_current_view()==view) + if(get_current_view()==view) status.set_text(status_text+" "); }; source_views.back()->on_update_info=[this](Source::View* view, const std::string &info_text) { - if(get_current_page()!=-1 && get_current_view()==view) + if(get_current_view()==view) info.set_text(" "+info_text); }; @@ -147,100 +187,148 @@ void Notebook::open(const boost::filesystem::path &file_path) { //Set up tab label auto source_view=source_views.back(); - tab_labels.emplace_back(new TabLabel(file_path, [this, source_view](){ - for(int c=0;c(-1)) + close(index); })); - append_page(*hboxes.back(), *tab_labels.back()); - set_tab_reorderable(*hboxes.back(), true); - show_all_children(); - - size_t last_index_tmp=-1; - if(get_current_page()!=-1) - last_index_tmp=get_index(get_current_page()); - set_current_page(size()-1); - last_index=last_index_tmp; - - set_focus_child(*source_views.back()); - get_current_view()->get_buffer()->set_modified(false); - get_current_view()->grab_focus(); //Add star on tab label when the page is not saved: - get_current_view()->get_buffer()->signal_modified_changed().connect([this, source_view]() { + source_view->get_buffer()->signal_modified_changed().connect([this, source_view]() { std::string title=source_view->file_path.filename().string(); if(source_view->get_buffer()->get_modified()) title+='*'; else title+=' '; - int page=-1; - for(int c=0;clabel.set_text(title); + tab_label->set_tooltip_text(source_view->file_path.string()); + return; } } - if(page!=-1) { - auto &tab_label=tab_labels.at(get_index(page)); - tab_label->label.set_text(title); - tab_label->set_tooltip_text(source_view->file_path.string()); + }); + + source_view->signal_focus_in_event().connect([this, source_view](GdkEventFocus *) { + if(source_view!=last_focused_view) { + last_focused_view=source_view; + if(on_switch_page) + on_switch_page(); } + else + last_focused_view=source_view; + return false; }); + + if(notebook_index==static_cast(-1)) { + if(!split) + notebook_index=0; + else if(notebooks[0].get_n_pages()==0) + notebook_index=0; + else if(notebooks[1].get_n_pages()==0) + notebook_index=1; + else if(last_view) + notebook_index=get_notebook_page(get_index(last_view)).first; + } + auto ¬ebook=notebooks[notebook_index]; + + notebook.append_page(*hboxes.back(), *tab_labels.back()); + + notebook.set_tab_reorderable(*hboxes.back(), true); + notebook.set_tab_detachable(*hboxes.back(), true); + show_all_children(); + + notebook.set_current_page(notebook.get_n_pages()-1); + last_index=-1; + if(last_view) + last_index=get_index(last_view); + + set_focus_child(*source_views.back()); + source_view->get_buffer()->set_modified(false); + focus_view(source_view); } -void Notebook::configure(int view_nr) { +void Notebook::configure(size_t index) { #if GTKSOURCEVIEWMM_MAJOR_VERSION > 2 & GTKSOURCEVIEWMM_MINOR_VERSION > 17 auto source_font_description=Pango::FontDescription(Config::get().source.font); auto source_map_font_desc=Pango::FontDescription(static_cast(source_font_description.get_family())+" "+Config::get().source.map_font_size); - source_maps.at(view_nr)->override_font(source_map_font_desc); + source_maps.at(index)->override_font(source_map_font_desc); if(Config::get().source.show_map) { - if(hboxes.at(view_nr)->get_children().size()==1) - hboxes.at(view_nr)->pack_end(*source_maps.at(view_nr), Gtk::PACK_SHRINK); + if(hboxes.at(index)->get_children().size()==1) + hboxes.at(index)->pack_end(*source_maps.at(index), Gtk::PACK_SHRINK); } - else if(hboxes.at(view_nr)->get_children().size()==2) - hboxes.at(view_nr)->remove(*source_maps.at(view_nr)); + else if(hboxes.at(index)->get_children().size()==2) + hboxes.at(index)->remove(*source_maps.at(index)); #endif } -bool Notebook::save(int page) { - if(page>=size()) - return false; - auto view=get_view(page); - if(!view->save(source_views)) +bool Notebook::save(size_t index) { + if(!source_views[index]->save(source_views)) return false; - Project::on_save(page); + Project::on_save(index); return true; } bool Notebook::save_current() { - if(get_current_page()==-1) - return false; - return save(get_current_page()); + if(auto view=get_current_view()) + return save(get_index(view)); + return false; } -bool Notebook::close(int page) { - if (page!=-1) { - auto view=get_view(page); +void Notebook::save_session() { + try { + boost::property_tree::ptree pt_root, pt_files; + pt_root.put("folder", Directories::get().path.string()); + for(size_t notebook_index=0;notebook_indexfile_path.string()); + pt_files.push_back(std::make_pair("", pt_child)); + } + } + pt_root.add_child("files", pt_files); + if(auto view=Notebook::get().get_current_view()) + pt_root.put("current_file", view->file_path.string()); + boost::property_tree::write_json((Config::get().juci_home_path()/"last_session.json").string(), pt_root); + } + catch(const std::exception &) {} +} + +bool Notebook::close(size_t index) { + if(auto view=get_view(index)) { if(view->get_buffer()->get_modified()){ - if(!save_modified_dialog(page)) + if(!save_modified_dialog(index)) return false; } - auto index=get_index(page); - if(page==get_current_page()) { + if(view==get_current_view()) { if(last_index!=static_cast(-1)) { - set_current_page(page_num(*hboxes.at(last_index))); + auto notebook_page=get_notebook_page(last_index); + focus_view(source_views[last_index]); + notebooks[notebook_page.first].set_current_page(notebook_page.second); last_index=-1; } + else { + auto notebook_page=get_notebook_page(get_index(view)); + if(notebook_page.second>0) + focus_view(get_view(notebook_page.first, notebook_page.second-1)); + else { + size_t notebook_index=notebook_page.first==0?1:0; + if(notebooks[notebook_index].get_n_pages()>0) + focus_view(get_view(notebook_index, notebooks[notebook_index].get_current_page())); + } + } } else if(index==last_index) last_index=-1; else if(index(-1)) last_index--; - remove_page(page); + auto notebook_page=get_notebook_page(index); + notebooks[notebook_page.first].remove_page(notebook_page.second); #if GTKSOURCEVIEWMM_MAJOR_VERSION > 2 & GTKSOURCEVIEWMM_MINOR_VERSION > 17 source_maps.erase(source_maps.begin()+index); #endif @@ -258,28 +346,99 @@ bool Notebook::close(int page) { return true; } -bool Notebook::close_current_page() { - if(get_current_page()==-1) - return false; - return close(get_current_page()); +bool Notebook::close_current() { + return close(get_index(get_current_view())); +} + +void Notebook::next() { + if(auto view=get_current_view()) { + auto notebook_page=get_notebook_page(get_index(view)); + int page=notebook_page.second+1; + if(page>=notebooks[notebook_page.first].get_n_pages()) + notebooks[notebook_page.first].set_current_page(0); + else + notebooks[notebook_page.first].set_current_page(page); + } +} + +void Notebook::previous() { + if(auto view=get_current_view()) { + auto notebook_page=get_notebook_page(get_index(view)); + int page=notebook_page.second-1; + if(page<0) + notebooks[notebook_page.first].set_current_page(notebooks[notebook_page.first].get_n_pages()-1); + else + notebooks[notebook_page.first].set_current_page(page); + } +} + +void Notebook::toggle_split() { + if(!split) { + pack2(notebooks[1], true, true); + set_position(get_width()/2); + show_all(); + } + else { + for(size_t c=size();c!=static_cast(-1);--c) { + auto notebook_index=get_notebook_page(c).first; + if(notebook_index==1 && !close(c)) + return; + } + remove(notebooks[1]); + } + split=!split; } boost::filesystem::path Notebook::get_current_folder() { if(!Directories::get().path.empty()) return Directories::get().path; - else if(get_current_page()!=-1) - return get_current_view()->file_path.parent_path(); + else if(auto view=get_current_view()) + return view->file_path.parent_path(); else return boost::filesystem::path(); } -bool Notebook::save_modified_dialog(int page) { +size_t Notebook::get_index(Source::View *view) { + for(size_t c=0;c(-1) || notebook_index>=notebooks.size() || + page<0 || page>=notebooks[notebook_index].get_n_pages()) + return nullptr; + auto hbox=dynamic_cast(notebooks[notebook_index].get_nth_page(page)); + auto scrolled_window=dynamic_cast(hbox->get_children()[0]); + return dynamic_cast(scrolled_window->get_children()[0]); +} + +void Notebook::focus_view(Source::View *view) { + if(!view) + return; + view->grab_focus(); +} + +std::pair Notebook::get_notebook_page(size_t index) { + if(index>=hboxes.size()) + return {-1, -1}; + for(size_t c=0;c=0) + return {c, page_num}; + } + return {-1, -1}; +} + +bool Notebook::save_modified_dialog(size_t index) { Gtk::MessageDialog dialog(*static_cast(get_toplevel()), "Save file!", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO); dialog.set_default_response(Gtk::RESPONSE_YES); - dialog.set_secondary_text("Do you want to save: " + get_view(page)->file_path.string()+" ?"); + dialog.set_secondary_text("Do you want to save: " + get_view(index)->file_path.string()+" ?"); int result = dialog.run(); if(result==Gtk::RESPONSE_YES) { - save(page); + save(index); return true; } else if(result==Gtk::RESPONSE_NO) { diff --git a/src/notebook.h b/src/notebook.h index 1fad50d..2cb26b5 100644 --- a/src/notebook.h +++ b/src/notebook.h @@ -9,7 +9,7 @@ #include #include -class Notebook : public Gtk::Notebook { +class Notebook : public Gtk::HPaned { class TabLabel : public Gtk::EventBox { Gtk::HBox hbox; Gtk::Button button; @@ -26,29 +26,46 @@ public: return singleton; } - Source::View* get_view(int page); - size_t get_index(int page); - int size(); + //Source::View* get_view(int page); + size_t size(); + Source::View* get_view(size_t index); Source::View* get_current_view(); - bool close(int page); - bool close_current_page(); - void open(const boost::filesystem::path &file_path); - bool save(int page); + std::vector &get_views(); + + void open(const boost::filesystem::path &file_path, size_t notebook_index=-1); + void configure(size_t index); + bool save(size_t index); bool save_current(); - void configure(int view_nr); + void save_session(); + bool close(size_t index); + bool close_current(); + void next(); + void previous(); + void toggle_split(); boost::filesystem::path get_current_folder(); - std::vector source_views; //Is NOT freed in destructor, this is intended for quick program exit. - Gtk::Label info; Gtk::Label status; + + std::function on_switch_page; + std::function on_page_removed; private: - bool save_modified_dialog(int page); + size_t get_index(Source::View *view); + Source::View *get_view(size_t notebook_index, int page); + void focus_view(Source::View *view); + std::pair get_notebook_page(size_t index); + + std::vector notebooks; + std::vector source_views; //Is NOT freed in destructor, this is intended for quick program exit. std::vector > source_maps; std::vector > scrolled_windows; std::vector > hboxes; std::vector > tab_labels; - size_t last_index; + bool split=false; + size_t last_index=-1; + Source::View* last_focused_view=nullptr; + + bool save_modified_dialog(size_t index); }; #endif // JUCI_NOTEBOOK_H_ diff --git a/src/project.cc b/src/project.cc index 43dc663..ca817ac 100644 --- a/src/project.cc +++ b/src/project.cc @@ -25,9 +25,7 @@ Gtk::Label &Project::debug_status_label() { } void Project::save_files(const boost::filesystem::path &path) { - if(Notebook::get().get_current_page()==-1) - return; - for(int c=0;cget_buffer()->get_modified()) { if(filesystem::file_in_path(view->file_path, path)) @@ -36,10 +34,10 @@ void Project::save_files(const boost::filesystem::path &path) { } } -void Project::on_save(int page) { - if(page>=Notebook::get().size()) +void Project::on_save(size_t index) { + auto view=Notebook::get().get_view(index); + if(!view) return; - auto view=Notebook::get().get_view(page); if(view->language && view->language->get_id()=="cmake") { boost::filesystem::path cmake_path; if(view->file_path.filename()=="CMakeLists.txt") @@ -54,7 +52,7 @@ void Project::on_save(int page) { if(boost::filesystem::exists(build->get_debug_path())) build->update_debug(true); - for(int c=0;c(source_view)) { if(filesystem::file_in_path(source_clang_view->file_path, build->project_path)) @@ -84,7 +82,7 @@ void Project::debug_update_status(const std::string &debug_status) { } 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"); @@ -92,7 +90,7 @@ void Project::debug_update_stop() { } } //Add debug stop source mark - for(int c=0;cfile_path==debug_stop.first) { if(debug_stop.second.first-1get_buffer()->get_line_count()) { @@ -102,15 +100,14 @@ void Project::debug_update_stop() { break; } } - 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()); + if(auto view=Notebook::get().get_current_view()) + view->get_buffer()->place_cursor(view->get_buffer()->get_insert()->get_iter()); } std::unique_ptr Project::create() { std::unique_ptr build; - if(Notebook::get().get_current_page()!=-1) { - auto view=Notebook::get().get_current_view(); + if(auto view=Notebook::get().get_current_view()) { build=Build::create(view->file_path); if(view->language) { auto language_id=view->language->get_id(); @@ -167,7 +164,8 @@ std::pair Project::Clang::get_run_arguments() { arguments=run_arguments_it->second; if(arguments.empty()) { - auto executable=build->get_executable(Notebook::get().get_current_page()!=-1?Notebook::get().get_current_view()->file_path:"").string(); + auto view=Notebook::get().get_current_view(); + auto executable=build->get_executable(view?view->file_path:"").string(); if(executable!="") { size_t pos=executable.find(project_path); @@ -210,7 +208,8 @@ void Project::Clang::compile_and_run() { arguments=run_arguments_it->second; if(arguments.empty()) { - arguments=build->get_executable(Notebook::get().get_current_page()!=-1?Notebook::get().get_current_view()->file_path:"").string(); + auto view=Notebook::get().get_current_view(); + arguments=build->get_executable(view?view->file_path:"").string(); if(arguments.empty()) { Terminal::get().print("Warning: could not find executable.\n"); Terminal::get().print("Solution: either use Project Set Run Arguments, or open a source file within a directory where add_executable is set.\n", true); @@ -250,7 +249,8 @@ std::pair Project::Clang::debug_get_run_arguments() { arguments=run_arguments_it->second; if(arguments.empty()) { - auto executable=build->get_executable(Notebook::get().get_current_page()!=-1?Notebook::get().get_current_view()->file_path:"").string(); + auto view=Notebook::get().get_current_view(); + auto executable=build->get_executable(view?view->file_path:"").string(); if(executable!="") { size_t pos=executable.find(project_path); @@ -277,7 +277,8 @@ void Project::Clang::debug_start() { run_arguments=run_arguments_it->second; if(run_arguments.empty()) { - run_arguments=build->get_executable(Notebook::get().get_current_page()!=-1?Notebook::get().get_current_view()->file_path:"").string(); + auto view=Notebook::get().get_current_view(); + run_arguments=build->get_executable(view?view->file_path:"").string(); if(run_arguments.empty()) { Terminal::get().print("Warning: could not find executable.\n"); Terminal::get().print("Solution: either use Debug Set Run Arguments, or open a source file within a directory where add_executable is set.\n", true); @@ -290,7 +291,7 @@ void Project::Clang::debug_start() { } auto breakpoints=std::make_shared > >(); - for(int c=0;cfile_path, project_path)) { auto iter=view->get_buffer()->begin(); @@ -361,10 +362,10 @@ void Project::Clang::debug_step_out() { } void Project::Clang::debug_backtrace() { - if(debugging && Notebook::get().get_current_page()!=-1) { + auto view=Notebook::get().get_current_view(); + if(view && debugging) { auto backtrace=Debug::Clang::get().get_backtrace(); - 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 >(); @@ -392,9 +393,7 @@ void Project::Clang::debug_backtrace() { auto frame=rows->at(selected); if(!frame.file_path.empty()) { Notebook::get().open(frame.file_path); - if(Notebook::get().get_current_page()!=-1) { - auto view=Notebook::get().get_current_view(); - + if(auto view=Notebook::get().get_current_view()) { Debug::Clang::get().select_frame(frame.index); view->place_cursor_at_line_index(frame.line_nr-1, frame.line_index-1); @@ -407,10 +406,10 @@ void Project::Clang::debug_backtrace() { } void Project::Clang::debug_show_variables() { - if(debugging && Notebook::get().get_current_page()!=-1) { + auto view=Notebook::get().get_current_view(); + if(debugging && view) { auto variables=Debug::Clang::get().get_variables(); - 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 >(); @@ -428,9 +427,7 @@ void Project::Clang::debug_show_variables() { auto variable=rows->at(selected); if(!variable.file_path.empty()) { Notebook::get().open(variable.file_path); - if(Notebook::get().get_current_page()!=-1) { - auto view=Notebook::get().get_current_view(); - + if(auto view=Notebook::get().get_current_view()) { Debug::Clang::get().select_frame(variable.frame_index, variable.thread_index_id); view->place_cursor_at_line_index(variable.line_nr-1, variable.line_index-1); @@ -449,8 +446,7 @@ void Project::Clang::debug_show_variables() { debug_variable_tooltips.hide(); return; } - if(Notebook::get().get_current_page()!=-1) { - auto view=Notebook::get().get_current_view(); + if(auto view=Notebook::get().get_current_view()) { debug_variable_tooltips.clear(); auto create_tooltip_buffer=[this, rows, view, selected]() { auto variable=rows->at(selected); diff --git a/src/project.h b/src/project.h index f12556d..831eb87 100644 --- a/src/project.h +++ b/src/project.h @@ -14,7 +14,7 @@ namespace Project { Gtk::Label &debug_status_label(); void save_files(const boost::filesystem::path &path); - void on_save(int page); + void on_save(size_t index); extern boost::filesystem::path debug_last_stop_file_path; extern std::unordered_map run_arguments; diff --git a/src/terminal.cc b/src/terminal.cc index 98d9bfa..176b6d3 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -365,8 +365,7 @@ bool Terminal::on_button_press_event(GdkEventButton* button_event) { path=boost::filesystem::canonical(path_str, ec); if(!ec && boost::filesystem::is_regular_file(path)) { Notebook::get().open(path); - if(Notebook::get().get_current_page()!=-1) { - auto view=Notebook::get().get_current_view(); + if(auto view=Notebook::get().get_current_view()) { try { int line = std::stoi(sm[3].str())-1; int index = std::stoi(sm[4].str())-1; diff --git a/src/window.cc b/src/window.cc index a8b67f5..fca4488 100644 --- a/src/window.cc +++ b/src/window.cc @@ -23,18 +23,19 @@ namespace sigc { #endif } -Window::Window() : notebook(Notebook::get()) { +Window::Window() { set_title("juCi++"); set_events(Gdk::POINTER_MOTION_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::SCROLL_MASK|Gdk::LEAVE_NOTIFY_MASK); set_menu_actions(); - configure(); + activate_menu_items(false); + set_default_size(Config::get().window.default_size.first, Config::get().window.default_size.second); directories_scrolled_window.add(Directories::get()); directory_and_notebook_panes.pack1(directories_scrolled_window, Gtk::SHRINK); - notebook_vbox.pack_start(notebook); + notebook_vbox.pack_start(Notebook::get()); notebook_vbox.pack_end(EntryBox::get(), Gtk::PACK_SHRINK); directory_and_notebook_panes.pack2(notebook_vbox, Gtk::SHRINK); directory_and_notebook_panes.set_position(static_cast(0.2*Config::get().window.default_size.first)); @@ -44,7 +45,7 @@ Window::Window() : notebook(Notebook::get()) { terminal_scrolled_window.add(Terminal::get()); terminal_vbox.pack_start(terminal_scrolled_window); - info_and_status_hbox.pack_start(notebook.info, Gtk::PACK_SHRINK); + info_and_status_hbox.pack_start(Notebook::get().info, Gtk::PACK_SHRINK); #if GTK_VERSION_GE(3, 12) info_and_status_hbox.set_center_widget(Project::debug_status_label()); @@ -52,7 +53,7 @@ Window::Window() : notebook(Notebook::get()) { Project::debug_status_label().set_halign(Gtk::Align::ALIGN_CENTER); info_and_status_hbox.pack_start(Project::debug_status_label()); #endif - info_and_status_hbox.pack_end(notebook.status, Gtk::PACK_SHRINK); + info_and_status_hbox.pack_end(Notebook::get().status, Gtk::PACK_SHRINK); terminal_vbox.pack_end(info_and_status_hbox, Gtk::PACK_SHRINK); vpaned.pack2(terminal_vbox, true, true); @@ -77,7 +78,7 @@ Window::Window() : notebook(Notebook::get()) { Info::get().hide(); Directories::get().on_row_activated=[this](const boost::filesystem::path &path) { - notebook.open(path); + Notebook::get().open(path); }; //Scroll to end of terminal whenever info is printed @@ -98,14 +99,12 @@ Window::Window() : notebook(Notebook::get()) { notebook_vbox.unset_focus_chain(); }); EntryBox::get().signal_hide().connect([this]() { - if(notebook.get_current_page()!=-1) { - notebook.get_current_view()->grab_focus(); - } + if(auto view=Notebook::get().get_current_view()) + view->grab_focus(); }); - notebook.signal_switch_page().connect([this](Gtk::Widget* page, guint page_num) { - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + Notebook::get().on_switch_page=[this] { + if(auto view=Notebook::get().get_current_view()) { if(search_entry_shown && EntryBox::get().labels.size()>0) { view->update_search_occurrences=[this](int number){ EntryBox::get().labels.begin()->update(0, std::to_string(number)); @@ -127,10 +126,10 @@ Window::Window() : notebook(Notebook::get()) { view->set_status(view->status); view->set_info(view->info); } - }); - notebook.signal_page_removed().connect([this](Gtk::Widget* page, guint page_num) { + }; + Notebook::get().on_page_removed=[] { EntryBox::get().hide(); - }); + }; about.signal_response().connect([this](int d){ about.hide(); @@ -175,14 +174,14 @@ void Window::set_menu_actions() { about.present(); }); menu.add_action("preferences", [this]() { - notebook.open(Config::get().juci_home_path()/"config"/"config.json"); + Notebook::get().open(Config::get().juci_home_path()/"config"/"config.json"); }); menu.add_action("quit", [this]() { close(); }); menu.add_action("new_file", [this]() { - boost::filesystem::path path = Dialog::new_file(notebook.get_current_folder()); + boost::filesystem::path path = Dialog::new_file(Notebook::get().get_current_folder()); if(path!="") { if(boost::filesystem::exists(path)) { Terminal::get().print("Error: "+path.string()+" already exists.\n", true); @@ -191,7 +190,7 @@ void Window::set_menu_actions() { if(filesystem::write(path)) { if(Directories::get().path!="") Directories::get().update(); - notebook.open(path); + Notebook::get().open(path); Terminal::get().print("New file "+path.string()+" created.\n"); } else @@ -201,7 +200,7 @@ void Window::set_menu_actions() { }); menu.add_action("new_folder", [this]() { auto time_now=std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); - boost::filesystem::path path = Dialog::new_folder(notebook.get_current_folder()); + boost::filesystem::path path = Dialog::new_folder(Notebook::get().get_current_folder()); if(path!="" && boost::filesystem::exists(path)) { boost::system::error_code ec; auto last_write_time=boost::filesystem::last_write_time(path, ec); @@ -216,7 +215,7 @@ void Window::set_menu_actions() { } }); menu.add_action("new_project_cpp", [this]() { - boost::filesystem::path project_path = Dialog::new_folder(notebook.get_current_folder()); + boost::filesystem::path project_path = Dialog::new_folder(Notebook::get().get_current_folder()); if(project_path!="") { auto project_name=project_path.filename().string(); for(size_t c=0;cfile_path==Config::get().juci_home_path()/"config"/"config.json") { - configure(); - for(int c=0;cconfigure(); - notebook.configure(c); - } + if(auto view=Notebook::get().get_current_view()) { + if(Notebook::get().save_current()) { + if(view->file_path==Config::get().juci_home_path()/"config"/"config.json") { + configure(); + for(size_t c=0;cconfigure(); + Notebook::get().configure(c); } } } } }); menu.add_action("save_as", [this]() { - if(notebook.get_current_page()!=-1) { - auto path = Dialog::save_file_as(notebook.get_current_view()->file_path); + if(auto view=Notebook::get().get_current_view()) { + auto path = Dialog::save_file_as(view->file_path); if(path!="") { std::ofstream file(path); if(file) { - file << notebook.get_current_view()->get_buffer()->get_text(); + file << view->get_buffer()->get_text(); file.close(); if(Directories::get().path!="") Directories::get().update(); - notebook.open(path); - Terminal::get().print("File saved to: " + notebook.get_current_view()->file_path.string()+"\n"); + Notebook::get().open(path); + Terminal::get().print("File saved to: " + Notebook::get().get_current_view()->file_path.string()+"\n"); } else Terminal::get().print("Error saving file\n"); @@ -294,8 +291,7 @@ void Window::set_menu_actions() { }); menu.add_action("print", [this]() { - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + if(auto view=Notebook::get().get_current_view()) { auto print_operation=Gtk::PrintOperation::create(); auto print_compositor=Gsv::PrintCompositor::create(*view); @@ -315,20 +311,20 @@ void Window::set_menu_actions() { }); menu.add_action("edit_undo", [this]() { - if(notebook.get_current_page()!=-1) { - auto undo_manager = notebook.get_current_view()->get_source_buffer()->get_undo_manager(); + if(auto view=Notebook::get().get_current_view()) { + auto undo_manager = view->get_source_buffer()->get_undo_manager(); if (undo_manager->can_undo()) { undo_manager->undo(); - notebook.get_current_view()->scroll_to(notebook.get_current_view()->get_buffer()->get_insert()); + view->scroll_to(view->get_buffer()->get_insert()); } } }); menu.add_action("edit_redo", [this]() { - if(notebook.get_current_page()!=-1) { - auto undo_manager = notebook.get_current_view()->get_source_buffer()->get_undo_manager(); + if(auto view=Notebook::get().get_current_view()) { + auto undo_manager = view->get_source_buffer()->get_undo_manager(); if(undo_manager->can_redo()) { undo_manager->redo(); - notebook.get_current_view()->scroll_to(notebook.get_current_view()->get_buffer()->get_insert()); + view->scroll_to(view->get_buffer()->get_insert()); } } }); @@ -337,8 +333,8 @@ void Window::set_menu_actions() { auto widget=get_focus(); if(auto entry=dynamic_cast(widget)) entry->cut_clipboard(); - else if(notebook.get_current_page()!=-1) - notebook.get_current_view()->get_buffer()->cut_clipboard(Gtk::Clipboard::get()); + else if(auto view=Notebook::get().get_current_view()) + view->get_buffer()->cut_clipboard(Gtk::Clipboard::get()); }); menu.add_action("edit_copy", [this]() { auto widget=get_focus(); @@ -351,8 +347,8 @@ void Window::set_menu_actions() { auto widget=get_focus(); if(auto entry=dynamic_cast(widget)) entry->paste_clipboard(); - else if(notebook.get_current_page()!=-1) - notebook.get_current_view()->paste(); + else if(auto view=Notebook::get().get_current_view()) + view->paste(); }); menu.add_action("edit_find", [this]() { @@ -360,41 +356,39 @@ void Window::set_menu_actions() { }); menu.add_action("source_spellcheck", [this]() { - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->spellcheck(); + if(auto view=Notebook::get().get_current_view()) + view->spellcheck(); }); menu.add_action("source_spellcheck_clear", [this]() { - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->remove_spellcheck_errors(); + if(auto view=Notebook::get().get_current_view()) + view->remove_spellcheck_errors(); }); menu.add_action("source_spellcheck_next_error", [this]() { - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->goto_next_spellcheck_error(); + if(auto view=Notebook::get().get_current_view()) + view->goto_next_spellcheck_error(); }); menu.add_action("source_indentation_set_buffer_tab", [this]() { set_tab_entry(); }); menu.add_action("source_indentation_auto_indent_buffer", [this]() { - if(notebook.get_current_page()!=-1 && notebook.get_current_view()->auto_indent) - notebook.get_current_view()->auto_indent(); + auto view=Notebook::get().get_current_view(); + if(view && view->auto_indent) + view->auto_indent(); }); menu.add_action("source_goto_line", [this]() { goto_line_entry(); }); menu.add_action("source_center_cursor", [this]() { - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); - + if(auto view=Notebook::get().get_current_view()) view->scroll_to_cursor_delayed(view, true, false); - } }); menu.add_action("source_find_documentation", [this]() { - if(notebook.get_current_page()!=-1) { - if(notebook.get_current_view()->get_token_data) { - auto data=notebook.get_current_view()->get_token_data(); + if(auto view=Notebook::get().get_current_view()) { + if(view->get_token_data) { + auto data=view->get_token_data(); if(data.size()>0) { auto documentation_search=Config::get().source.documentation_searches.find(data[0]); if(documentation_search!=Config::get().source.documentation_searches.end()) { @@ -433,17 +427,17 @@ void Window::set_menu_actions() { }); menu.add_action("source_goto_declaration", [this]() { - if(notebook.get_current_page()!=-1) { - if(notebook.get_current_view()->get_declaration_location) { - auto location=notebook.get_current_view()->get_declaration_location(notebook.source_views); + if(auto view=Notebook::get().get_current_view()) { + if(view->get_declaration_location) { + auto location=view->get_declaration_location(Notebook::get().get_views()); if(location) { boost::filesystem::path declaration_file; boost::system::error_code ec; declaration_file=boost::filesystem::canonical(location.file_path, ec); if(ec) return; - notebook.open(declaration_file); - auto view=notebook.get_current_view(); + Notebook::get().open(declaration_file); + auto view=Notebook::get().get_current_view(); auto line=static_cast(location.line)-1; auto index=static_cast(location.index)-1; view->place_cursor_at_line_index(line, index); @@ -453,18 +447,17 @@ void Window::set_menu_actions() { } }); menu.add_action("source_goto_implementation", [this]() { - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + if(auto view=Notebook::get().get_current_view()) { if(view->get_implementation_location) { - auto location=view->get_implementation_location(notebook.source_views); + auto location=view->get_implementation_location(Notebook::get().get_views()); if(location) { boost::filesystem::path implementation_path; boost::system::error_code ec; implementation_path=boost::filesystem::canonical(location.file_path, ec); if(ec) return; - notebook.open(implementation_path); - auto view=notebook.get_current_view(); + Notebook::get().open(implementation_path); + auto view=Notebook::get().get_current_view(); auto line=static_cast(location.line)-1; auto index=static_cast(location.index)-1; view->place_cursor_at_line_index(line, index); @@ -476,10 +469,9 @@ void Window::set_menu_actions() { }); menu.add_action("source_goto_usage", [this]() { - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + if(auto view=Notebook::get().get_current_view()) { if(view->get_usages) { - auto usages=view->get_usages(notebook.source_views); + auto usages=view->get_usages(Notebook::get().get_views()); if(!usages.empty()) { auto iter=view->get_iter_for_dialog(); view->selection_dialog=std::unique_ptr(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true)); @@ -504,8 +496,8 @@ void Window::set_menu_actions() { declaration_file=boost::filesystem::canonical(offset.file_path, ec); if(ec) return; - notebook.open(declaration_file); - auto view=notebook.get_current_view(); + Notebook::get().open(declaration_file); + auto view=Notebook::get().get_current_view(); view->place_cursor_at_line_index(offset.line, offset.index); view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5); view->delayed_tooltips_connection.disconnect(); @@ -516,10 +508,9 @@ void Window::set_menu_actions() { } }); menu.add_action("source_goto_method", [this]() { - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + if(auto view=Notebook::get().get_current_view()) { if(view->get_methods) { - auto methods=notebook.get_current_view()->get_methods(); + auto methods=Notebook::get().get_current_view()->get_methods(); if(!methods.empty()) { auto iter=view->get_iter_for_dialog(); view->selection_dialog=std::unique_ptr(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true)); @@ -544,15 +535,14 @@ void Window::set_menu_actions() { }); menu.add_action("source_goto_next_diagnostic", [this]() { - if(notebook.get_current_page()!=-1) { - if(notebook.get_current_view()->goto_next_diagnostic) { - notebook.get_current_view()->goto_next_diagnostic(); + if(auto view=Notebook::get().get_current_view()) { + if(view->goto_next_diagnostic) { + view->goto_next_diagnostic(); } } }); menu.add_action("source_apply_fix_its", [this]() { - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + if(auto view=Notebook::get().get_current_view()) { if(view->get_fix_its) { auto buffer=view->get_buffer(); auto fix_its=view->get_fix_its(); @@ -648,7 +638,7 @@ void Window::set_menu_actions() { EntryBox::get().entries.emplace_back(last_run_command, [this](const std::string& content){ if(content!="") { last_run_command=content; - auto run_path=notebook.get_current_folder(); + auto run_path=Notebook::get().get_current_folder(); Terminal::get().async_print("Running: "+content+'\n'); Terminal::get().async_process(content, run_path, [this, content](int exit_status){ @@ -760,8 +750,7 @@ void Window::set_menu_actions() { EntryBox::get().show(); }); menu.add_action("debug_toggle_breakpoint", [this](){ - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + if(auto view=Notebook::get().get_current_view()) { auto line_nr=view->get_buffer()->get_insert()->get_iter().get_line(); if(view->get_source_buffer()->get_source_marks_at_line(line_nr, "debug_breakpoint").size()>0) { @@ -782,10 +771,8 @@ void Window::set_menu_actions() { menu.add_action("debug_goto_stop", [this](){ 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(); - + Notebook::get().open(Project::debug_stop.first); + if(auto view=Notebook::get().get_current_view()) { int line=Project::debug_stop.second.first-1; int index=Project::debug_stop.second.second-1; view->place_cursor_at_line_index(line, index); @@ -800,36 +787,32 @@ void Window::set_menu_actions() { #endif menu.add_action("next_tab", [this]() { - if(notebook.get_current_page()!=-1) { - notebook.open(notebook.get_view((notebook.get_current_page()+1)%notebook.size())->file_path); - } + Notebook::get().next(); }); menu.add_action("previous_tab", [this]() { - if(notebook.get_current_page()!=-1) { - int previous_page=notebook.get_current_page()-1; - if(previous_page<0) - previous_page=notebook.size()-1; - notebook.open(notebook.get_view(previous_page)->file_path); - } + Notebook::get().previous(); }); menu.add_action("close_tab", [this]() { - notebook.close_current_page(); - if(notebook.get_current_page()!=-1) { - notebook.get_current_view()->set_status(notebook.get_current_view()->status); - notebook.get_current_view()->set_info(notebook.get_current_view()->info); + Notebook::get().close_current(); + if(auto view=Notebook::get().get_current_view()) { + view->set_status(view->status); + view->set_info(view->info); } else { - notebook.status.set_text(""); - notebook.info.set_text(""); + Notebook::get().status.set_text(""); + Notebook::get().info.set_text(""); activate_menu_items(false); } }); - activate_menu_items(false); + menu.add_action("window_toggle_split", [this] { + Notebook::get().toggle_split(); + }); } void Window::activate_menu_items(bool activate) { auto &menu = Menu::get(); + auto ¬ebook = Notebook::get(); menu.actions["source_indentation_auto_indent_buffer"]->set_enabled(activate ? static_cast(notebook.get_current_view()->auto_indent) : false); menu.actions["source_find_documentation"]->set_enabled(activate ? static_cast(notebook.get_current_view()->get_token_data) : false); menu.actions["source_goto_declaration"]->set_enabled(activate ? static_cast(notebook.get_current_view()->get_declaration_location) : false); @@ -840,8 +823,7 @@ void Window::activate_menu_items(bool activate) { menu.actions["source_goto_next_diagnostic"]->set_enabled(activate ? static_cast(notebook.get_current_view()->goto_next_diagnostic) : false); menu.actions["source_apply_fix_its"]->set_enabled(activate ? static_cast(notebook.get_current_view()->get_fix_its) : false); #ifdef JUCI_ENABLE_DEBUG - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + if(auto view=notebook.get_current_view()) { if(view->language && (view->language->get_id()=="c" || view->language->get_id()=="cpp" || view->language->get_id()=="objc" || view->language->get_id()=="chdr" || view->language->get_id()=="cpphdr")) menu.actions["debug_toggle_breakpoint"]->set_enabled(true); else @@ -887,24 +869,11 @@ bool Window::on_key_press_event(GdkEventKey *event) { } bool Window::on_delete_event(GdkEventAny *event) { - try { - boost::property_tree::ptree pt_root, pt_files; - pt_root.put("folder", Directories::get().path.string()); - for(int c=0;cfile_path.string()); - pt_files.push_back(std::make_pair("", pt_child)); - } - pt_root.add_child("files", pt_files); - if(notebook.get_current_page()!=-1) - pt_root.put("current_file", notebook.get_current_view()->file_path.string()); - boost::property_tree::write_json((Config::get().juci_home_path()/"last_session.json").string(), pt_root); - } - catch(const std::exception &) {} + Notebook::get().save_session(); - auto size=notebook.size(); - for(int c=0;cdebug_cancel(); #endif + return false; } @@ -934,41 +904,41 @@ void Window::search_and_replace_entry() { } }; EntryBox::get().entries.emplace_back(last_search, [this](const std::string& content){ - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->search_forward(); + if(auto view=Notebook::get().get_current_view()) + view->search_forward(); }); auto search_entry_it=EntryBox::get().entries.begin(); search_entry_it->set_placeholder_text("Find"); - if(notebook.get_current_page()!=-1) { - notebook.get_current_view()->update_search_occurrences=[label_it](int number){ + if(auto view=Notebook::get().get_current_view()) { + view->update_search_occurrences=[label_it](int number){ label_it->update(0, std::to_string(number)); }; - notebook.get_current_view()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); + view->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); } search_entry_it->signal_key_press_event().connect([this](GdkEventKey* event){ if(event->keyval==GDK_KEY_Return && (event->state&GDK_SHIFT_MASK)>0) { - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->search_backward(); + if(auto view=Notebook::get().get_current_view()) + view->search_backward(); } return false; }); search_entry_it->signal_changed().connect([this, search_entry_it](){ last_search=search_entry_it->get_text(); - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); + if(auto view=Notebook::get().get_current_view()) + view->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); }); EntryBox::get().entries.emplace_back(last_replace, [this](const std::string &content){ - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->replace_forward(content); + if(auto view=Notebook::get().get_current_view()) + 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([this, replace_entry_it](GdkEventKey* event){ if(event->keyval==GDK_KEY_Return && (event->state&GDK_SHIFT_MASK)>0) { - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->replace_backward(replace_entry_it->get_text()); + if(auto view=Notebook::get().get_current_view()) + view->replace_backward(replace_entry_it->get_text()); } return false; }); @@ -977,24 +947,24 @@ void Window::search_and_replace_entry() { }); EntryBox::get().buttons.emplace_back("↑", [this](){ - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->search_backward(); + if(auto view=Notebook::get().get_current_view()) + 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("⇄", [this, replace_entry_it](){ - if(notebook.get_current_page()!=-1) { - notebook.get_current_view()->replace_forward(replace_entry_it->get_text()); + if(auto view=Notebook::get().get_current_view()) { + 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("↓", [this](){ - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->search_forward(); + if(auto view=Notebook::get().get_current_view()) + 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", [this, replace_entry_it](){ - if(notebook.get_current_page()!=-1) - notebook.get_current_view()->replace_all(replace_entry_it->get_text()); + if(auto view=Notebook::get().get_current_view()) + view->replace_all(replace_entry_it->get_text()); }); EntryBox::get().buttons.back().set_tooltip_text("Replace All"); @@ -1003,21 +973,21 @@ 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(notebook.get_current_page()!=-1) - notebook.get_current_view()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); + if(auto view=Notebook::get().get_current_view()) + 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(notebook.get_current_page()!=-1) - notebook.get_current_view()->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); + if(auto view=Notebook::get().get_current_view()) + view->search_highlight(search_entry_it->get_text(), case_sensitive_search, regex_search); }; EntryBox::get().signal_hide().connect([this]() { - for(int c=0;cupdate_search_occurrences=nullptr; - notebook.get_view(c)->search_highlight("", case_sensitive_search, regex_search); + for(size_t c=0;cupdate_search_occurrences=nullptr; + Notebook::get().get_view(c)->search_highlight("", case_sensitive_search, regex_search); } search_entry_shown=false; }); @@ -1027,8 +997,8 @@ void Window::search_and_replace_entry() { void Window::set_tab_entry() { EntryBox::get().clear(); - if(notebook.get_current_page()!=-1) { - auto tab_char_and_size=notebook.get_current_view()->get_tab_char_and_size(); + if(auto view=Notebook::get().get_current_view()) { + auto tab_char_and_size=view->get_tab_char_and_size(); EntryBox::get().labels.emplace_back(); auto label_it=EntryBox::get().labels.begin(); @@ -1049,7 +1019,7 @@ void Window::set_tab_entry() { entry_tab_char_it->set_placeholder_text("Tab char"); const auto activate_function=[this, entry_tab_char_it, entry_tab_size_it, label_it](const std::string& content){ - if(notebook.get_current_page()!=-1) { + if(auto view=Notebook::get().get_current_view()) { char tab_char=0; unsigned tab_size=0; try { @@ -1064,7 +1034,7 @@ void Window::set_tab_entry() { catch(const std::exception &e) {} if(tab_char!=0 && tab_size>0) { - notebook.get_current_view()->set_tab_char_and_size(tab_char, tab_size); + view->set_tab_char_and_size(tab_char, tab_size); EntryBox::get().hide(); } else { @@ -1086,10 +1056,9 @@ void Window::set_tab_entry() { void Window::goto_line_entry() { EntryBox::get().clear(); - if(notebook.get_current_page()!=-1) { + if(Notebook::get().get_current_view()) { EntryBox::get().entries.emplace_back("", [this](const std::string& content){ - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + if(auto view=Notebook::get().get_current_view()) { try { view->place_cursor_at_line_index(stoi(content)-1, 0); view->scroll_to_cursor_delayed(view, true, false); @@ -1109,8 +1078,7 @@ void Window::goto_line_entry() { void Window::rename_token_entry() { EntryBox::get().clear(); - if(notebook.get_current_page()!=-1) { - auto view=notebook.get_current_view(); + if(auto view=Notebook::get().get_current_view()) { if(view->get_token_spelling && view->rename_similar_tokens) { auto spelling=std::make_shared(view->get_token_spelling()); if(!spelling->empty()) { @@ -1124,9 +1092,8 @@ void Window::rename_token_entry() { EntryBox::get().entries.emplace_back(*spelling, [this, view, spelling, iter](const std::string& content){ //TODO: gtk needs a way to check if iter is valid without dumping g_error message //iter->get_buffer() will print such a message, but no segfault will occur - if(notebook.get_current_page()!=-1 && notebook.get_current_view()==view && - content!=*spelling && iter->get_buffer() && view->get_buffer()->get_insert()->get_iter()==*iter) { - auto renamed_pairs=view->rename_similar_tokens(notebook.source_views, content); + if(Notebook::get().get_current_view()==view && content!=*spelling && iter->get_buffer() && view->get_buffer()->get_insert()->get_iter()==*iter) { + auto renamed_pairs=view->rename_similar_tokens(Notebook::get().get_views(), content); for(auto &renamed: renamed_pairs) Terminal::get().print("Replaced "+std::to_string(renamed.second)+" occurrence"+(renamed.second>1?"s":"")+" in file "+renamed.first.string()+"\n"); } diff --git a/src/window.h b/src/window.h index 13fb024..2fb5c21 100644 --- a/src/window.h +++ b/src/window.h @@ -6,9 +6,7 @@ #include class Window : public Gtk::ApplicationWindow { -private: Window(); - Notebook ¬ebook; //convenience reference public: static Window &get() { static Window singleton;