Browse Source

Added split window, fixes #235

merge-requests/365/head
eidheim 10 years ago
parent
commit
d18e8bef2c
  1. 6
      src/directories.cc
  2. 5
      src/files.h
  3. 17
      src/juci.cc
  4. 2
      src/juci.h
  5. 7
      src/menu.cc
  6. 333
      src/notebook.cc
  7. 43
      src/notebook.h
  8. 56
      src/project.cc
  9. 2
      src/project.h
  10. 3
      src/terminal.cc
  11. 307
      src/window.cc
  12. 2
      src/window.h

6
src/directories.cc

@ -85,7 +85,7 @@ bool Directories::TreeStore::drag_data_received_vfunc(const TreeModel::Path &pat
return false; return false;
} }
for(int c=0;c<Notebook::get().size();c++) { for(size_t c=0;c<Notebook::get().size();c++) {
auto view=Notebook::get().get_view(c); auto view=Notebook::get().get_view(c);
if(is_directory) { if(is_directory) {
if(filesystem::file_in_path(view->file_path, source_path)) { if(filesystem::file_in_path(view->file_path, source_path)) {
@ -320,7 +320,7 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
update(); update();
select(target_path); select(target_path);
for(int c=0;c<Notebook::get().size();c++) { for(size_t c=0;c<Notebook::get().size();c++) {
auto view=Notebook::get().get_view(c); auto view=Notebook::get().get_view(c);
if(is_directory) { if(is_directory) {
if(filesystem::file_in_path(view->file_path, *source_path)) { if(filesystem::file_in_path(view->file_path, *source_path)) {
@ -379,7 +379,7 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
else { else {
update(); update();
for(int c=0;c<Notebook::get().size();c++) { for(size_t c=0;c<Notebook::get().size();c++) {
auto view=Notebook::get().get_view(c); auto view=Notebook::get().get_view(c);
if(is_directory) { if(is_directory) {

5
src/files.h

@ -2,7 +2,7 @@
#define JUCI_FILES_H_ #define JUCI_FILES_H_
#include <string> #include <string>
#define JUCI_VERSION "1.1.3-4" #define JUCI_VERSION "1.1.3-5"
const std::string default_config_file = R"RAW({ const std::string default_config_file = R"RAW({
"version": ")RAW"+std::string(JUCI_VERSION)+R"RAW(", "version": ")RAW"+std::string(JUCI_VERSION)+R"RAW(",
@ -132,7 +132,8 @@ R"RAW(
"previous_tab": "<primary><alt>Left",)RAW" "previous_tab": "<primary><alt>Left",)RAW"
#endif #endif
R"RAW( R"RAW(
"close_tab": "<primary>w" "close_tab": "<primary>w",
"window_toggle_split": ""
}, },
"project": { "project": {
"default_build_path_comment": "Use <project_directory_name> to insert the project top level directory name", "default_build_path_comment": "Use <project_directory_name> to insert the project top level directory name",

17
src/juci.cc

@ -19,7 +19,7 @@ int Application::on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine>
if(boost::filesystem::exists(p)) { if(boost::filesystem::exists(p)) {
p=boost::filesystem::canonical(p); p=boost::filesystem::canonical(p);
if(boost::filesystem::is_regular_file(p)) if(boost::filesystem::is_regular_file(p))
files.emplace_back(p); files.emplace_back(p, 0);
else if(boost::filesystem::is_directory(p)) else if(boost::filesystem::is_directory(p))
directories.emplace_back(p); directories.emplace_back(p);
} }
@ -29,7 +29,7 @@ int Application::on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine>
auto new_p=boost::filesystem::canonical(parent_p, ec); auto new_p=boost::filesystem::canonical(parent_p, ec);
if(!ec && boost::filesystem::is_directory(new_p)) { if(!ec && boost::filesystem::is_directory(new_p)) {
new_p/=p.filename(); new_p/=p.filename();
files.emplace_back(new_p); files.emplace_back(new_p, 0);
} }
else else
errors.emplace_back("Error: folder path "+parent_p.string()+" does not exist.\n"); 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<std::string>("folder"); auto folder=pt.get<std::string>("folder");
if(!folder.empty() && boost::filesystem::exists(folder) && boost::filesystem::is_directory(folder)) if(!folder.empty() && boost::filesystem::exists(folder) && boost::filesystem::is_directory(folder))
directories.emplace_back(folder); directories.emplace_back(folder);
for(auto &v: pt.get_child("files")) { for(auto &pt_file: pt.get_child("files")) {
std::string file=v.second.data(); auto notebook=pt_file.second.get<size_t>("notebook", -1);
auto file=pt_file.second.get<std::string>("file", "");
if(!file.empty() && boost::filesystem::exists(file) && !boost::filesystem::is_directory(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<std::string>("current_file"); last_current_file=pt.get<std::string>("current_file");
if(!boost::filesystem::exists(last_current_file) || boost::filesystem::is_directory(last_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 { else {
std::string files_in_directory; std::string files_in_directory;
for(auto it=files.begin();it!=files.end();) { for(auto it=files.begin();it!=files.end();) {
if(it->generic_string().substr(0, directory.generic_string().size()+1)==directory.generic_string()+'/') { if(it->first.generic_string().substr(0, directory.generic_string().size()+1)==directory.generic_string()+'/') {
files_in_directory+=" "+it->string(); files_in_directory+=" "+it->first.string();
it=files.erase(it); it=files.erase(it);
} }
else else
@ -90,7 +91,7 @@ void Application::on_activate() {
} }
for(auto &file: files) for(auto &file: files)
Notebook::get().open(file); Notebook::get().open(file.first, file.second);
for(auto &error: errors) for(auto &error: errors)
Terminal::get().print(error, true); Terminal::get().print(error, true);

2
src/juci.h

@ -39,7 +39,7 @@ public:
void on_startup() override; void on_startup() override;
private: private:
std::vector<boost::filesystem::path> directories; std::vector<boost::filesystem::path> directories;
std::vector<boost::filesystem::path> files; std::vector<std::pair<boost::filesystem::path, size_t> > files;
std::vector<std::string> errors; std::vector<std::string> errors;
}; };

7
src/menu.cc

@ -382,6 +382,13 @@ Menu::Menu() {
+accels["close_tab"]+ //For Ubuntu... +accels["close_tab"]+ //For Ubuntu...
" </item>" " </item>"
" </section>" " </section>"
" <section>"
" <item>"
" <attribute name='label' translatable='yes'>_Toggle _Split</attribute>"
" <attribute name='action'>app.window_toggle_split</attribute>"
+accels["window_toggle_split"]+ //For Ubuntu...
" </item>"
" </section>"
" </submenu>" " </submenu>"
" </menu>" " </menu>"
"</interface>"; "</interface>";

333
src/notebook.cc

@ -50,10 +50,38 @@ Notebook::TabLabel::TabLabel(const boost::filesystem::path &path, std::function<
show_all(); show_all();
} }
Notebook::Notebook() : Gtk::Notebook(), last_index(-1) { Notebook::Notebook() : Gtk::HPaned(), notebooks(2) {
Gsv::init(); Gsv::init();
set_scrollable(); for(auto &notebook: 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<Gtk::HBox*>(widget);
for(size_t c=0;c<hboxes.size();++c) {
if(hboxes[c].get()==hbox) {
focus_view(source_views[c]);
break;
}
}
last_index=-1;
if(on_switch_page)
on_switch_page();
});
notebook.signal_page_removed().connect([this](Gtk::Widget*, guint) {
if(on_page_removed)
on_page_removed();
});
notebook.signal_page_added().connect([this](Gtk::Widget* widget, guint) {
auto hbox=dynamic_cast<Gtk::HBox*>(widget);
for(size_t c=0;c<hboxes.size();++c) {
if(hboxes[c].get()==hbox) {
focus_view(source_views[c]);
break;
}
}
});
auto provider = Gtk::CssProvider::create(); auto provider = Gtk::CssProvider::create();
//GtkNotebook-tab-overlap got removed in gtk 3.20, but margin works in 3.20 //GtkNotebook-tab-overlap got removed in gtk 3.20, but margin works in 3.20
@ -62,38 +90,48 @@ Notebook::Notebook() : Gtk::Notebook(), last_index(-1) {
#else #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 #endif
get_style_context()->add_provider(provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); notebook.get_style_context()->add_provider(provider, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
signal_switch_page().connect([this](Gtk::Widget* page, guint page_num) { pack1(notebooks[0], true, true);
last_index=-1;
});
} }
int Notebook::size() { size_t Notebook::size() {
return get_n_pages(); return static_cast<int>(source_views.size());
} }
Source::View* Notebook::get_view(int page) { Source::View* Notebook::get_view(size_t index) {
return source_views.at(get_index(page)); if(index>=size())
return nullptr;
return source_views[index];
} }
size_t Notebook::get_index(int page) { Source::View* Notebook::get_current_view() {
for(size_t c=0;c<hboxes.size();c++) { for(auto &view: source_views) {
if(page_num(*hboxes.at(c))==page) if(view->has_focus())
return c; 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() { std::vector<Source::View*> &Notebook::get_views() {
return get_view(get_current_page()); return source_views;
} }
void Notebook::open(const boost::filesystem::path &file_path) { void Notebook::open(const boost::filesystem::path &file_path, size_t notebook_index) {
for(int c=0;c<size();c++) { if(notebook_index==1 && !split)
if(file_path==get_view(c)->file_path) { toggle_split();
set_current_page(c);
get_current_view()->grab_focus(); for(size_t c=0;c<size();c++) {
if(file_path==source_views[c]->file_path) {
auto notebook_page=get_notebook_page(c);
notebooks[notebook_page.first].set_current_page(notebook_page.second);
focus_view(source_views[c]);
return; return;
} }
} }
@ -107,6 +145,8 @@ void Notebook::open(const boost::filesystem::path &file_path) {
can_read.close(); can_read.close();
} }
auto last_view=get_current_view();
auto language=Source::guess_language(file_path); 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")) 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)); 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) { source_views.back()->scroll_to_cursor_delayed=[this](Source::View* view, bool center, bool show_tooltips) {
while(g_main_context_pending(NULL)) while(g_main_context_pending(NULL))
g_main_context_iteration(NULL, false); g_main_context_iteration(NULL, false);
if(get_current_page()!=-1 && get_current_view()==view) { if(get_current_view()==view) {
if(center) if(center)
view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5); view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5);
else 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) { 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+" "); status.set_text(status_text+" ");
}; };
source_views.back()->on_update_info=[this](Source::View* view, const std::string &info_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); info.set_text(" "+info_text);
}; };
@ -147,100 +187,148 @@ void Notebook::open(const boost::filesystem::path &file_path) {
//Set up tab label //Set up tab label
auto source_view=source_views.back(); auto source_view=source_views.back();
tab_labels.emplace_back(new TabLabel(file_path, [this, source_view](){ tab_labels.emplace_back(new TabLabel(file_path, [this, source_view]() {
for(int c=0;c<size();c++) { auto index=get_index(source_view);
if(get_view(c)==source_view) { if(index!=static_cast<size_t>(-1))
close(c); close(index);
break;
}
}
})); }));
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: //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(); std::string title=source_view->file_path.filename().string();
if(source_view->get_buffer()->get_modified()) if(source_view->get_buffer()->get_modified())
title+='*'; title+='*';
else else
title+=' '; title+=' ';
int page=-1;
for(int c=0;c<size();c++) { for(size_t c=0;c<size();c++) {
if(get_view(c)==source_view) { if(source_views[c]==source_view) {
page=c; auto &tab_label=tab_labels.at(c);
break;
}
}
if(page!=-1) {
auto &tab_label=tab_labels.at(get_index(page));
tab_label->label.set_text(title); tab_label->label.set_text(title);
tab_label->set_tooltip_text(source_view->file_path.string()); tab_label->set_tooltip_text(source_view->file_path.string());
return;
} }
}
});
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<size_t>(-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 &notebook=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 #if GTKSOURCEVIEWMM_MAJOR_VERSION > 2 & GTKSOURCEVIEWMM_MINOR_VERSION > 17
auto source_font_description=Pango::FontDescription(Config::get().source.font); auto source_font_description=Pango::FontDescription(Config::get().source.font);
auto source_map_font_desc=Pango::FontDescription(static_cast<std::string>(source_font_description.get_family())+" "+Config::get().source.map_font_size); auto source_map_font_desc=Pango::FontDescription(static_cast<std::string>(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(Config::get().source.show_map) {
if(hboxes.at(view_nr)->get_children().size()==1) if(hboxes.at(index)->get_children().size()==1)
hboxes.at(view_nr)->pack_end(*source_maps.at(view_nr), Gtk::PACK_SHRINK); hboxes.at(index)->pack_end(*source_maps.at(index), Gtk::PACK_SHRINK);
} }
else if(hboxes.at(view_nr)->get_children().size()==2) else if(hboxes.at(index)->get_children().size()==2)
hboxes.at(view_nr)->remove(*source_maps.at(view_nr)); hboxes.at(index)->remove(*source_maps.at(index));
#endif #endif
} }
bool Notebook::save(int page) { bool Notebook::save(size_t index) {
if(page>=size()) if(!source_views[index]->save(source_views))
return false;
auto view=get_view(page);
if(!view->save(source_views))
return false; return false;
Project::on_save(page); Project::on_save(index);
return true; return true;
} }
bool Notebook::save_current() { bool Notebook::save_current() {
if(get_current_page()==-1) if(auto view=get_current_view())
return save(get_index(view));
return false; return false;
return save(get_current_page());
} }
bool Notebook::close(int page) { void Notebook::save_session() {
if (page!=-1) { try {
auto view=get_view(page); boost::property_tree::ptree pt_root, pt_files;
pt_root.put("folder", Directories::get().path.string());
for(size_t notebook_index=0;notebook_index<notebooks.size();++notebook_index) {
for(int page=0;page<notebooks[notebook_index].get_n_pages();++page) {
auto view=get_view(notebook_index, page);
boost::property_tree::ptree pt_child;
pt_child.put("notebook", notebook_index);
pt_child.put("file", view->file_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(view->get_buffer()->get_modified()){
if(!save_modified_dialog(page)) if(!save_modified_dialog(index))
return false; return false;
} }
auto index=get_index(page); if(view==get_current_view()) {
if(page==get_current_page()) {
if(last_index!=static_cast<size_t>(-1)) { if(last_index!=static_cast<size_t>(-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; 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) else if(index==last_index)
last_index=-1; last_index=-1;
else if(index<last_index && last_index!=static_cast<size_t>(-1)) else if(index<last_index && last_index!=static_cast<size_t>(-1))
last_index--; 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 #if GTKSOURCEVIEWMM_MAJOR_VERSION > 2 & GTKSOURCEVIEWMM_MINOR_VERSION > 17
source_maps.erase(source_maps.begin()+index); source_maps.erase(source_maps.begin()+index);
#endif #endif
@ -258,28 +346,99 @@ bool Notebook::close(int page) {
return true; return true;
} }
bool Notebook::close_current_page() { bool Notebook::close_current() {
if(get_current_page()==-1) return close(get_index(get_current_view()));
return false; }
return close(get_current_page());
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<size_t>(-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() { boost::filesystem::path Notebook::get_current_folder() {
if(!Directories::get().path.empty()) if(!Directories::get().path.empty())
return Directories::get().path; return Directories::get().path;
else if(get_current_page()!=-1) else if(auto view=get_current_view())
return get_current_view()->file_path.parent_path(); return view->file_path.parent_path();
else else
return boost::filesystem::path(); 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<size();++c) {
if(source_views[c]==view)
return c;
}
return -1;
}
Source::View *Notebook::get_view(size_t notebook_index, int page) {
if(notebook_index==static_cast<size_t>(-1) || notebook_index>=notebooks.size() ||
page<0 || page>=notebooks[notebook_index].get_n_pages())
return nullptr;
auto hbox=dynamic_cast<Gtk::HBox*>(notebooks[notebook_index].get_nth_page(page));
auto scrolled_window=dynamic_cast<Gtk::ScrolledWindow*>(hbox->get_children()[0]);
return dynamic_cast<Source::View*>(scrolled_window->get_children()[0]);
}
void Notebook::focus_view(Source::View *view) {
if(!view)
return;
view->grab_focus();
}
std::pair<size_t, int> Notebook::get_notebook_page(size_t index) {
if(index>=hboxes.size())
return {-1, -1};
for(size_t c=0;c<notebooks.size();++c) {
auto page_num=notebooks[c].page_num(*hboxes[index]);
if(page_num>=0)
return {c, page_num};
}
return {-1, -1};
}
bool Notebook::save_modified_dialog(size_t index) {
Gtk::MessageDialog dialog(*static_cast<Gtk::Window*>(get_toplevel()), "Save file!", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO); Gtk::MessageDialog dialog(*static_cast<Gtk::Window*>(get_toplevel()), "Save file!", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO);
dialog.set_default_response(Gtk::RESPONSE_YES); 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(); int result = dialog.run();
if(result==Gtk::RESPONSE_YES) { if(result==Gtk::RESPONSE_YES) {
save(page); save(index);
return true; return true;
} }
else if(result==Gtk::RESPONSE_NO) { else if(result==Gtk::RESPONSE_NO) {

43
src/notebook.h

@ -9,7 +9,7 @@
#include <map> #include <map>
#include <sigc++/sigc++.h> #include <sigc++/sigc++.h>
class Notebook : public Gtk::Notebook { class Notebook : public Gtk::HPaned {
class TabLabel : public Gtk::EventBox { class TabLabel : public Gtk::EventBox {
Gtk::HBox hbox; Gtk::HBox hbox;
Gtk::Button button; Gtk::Button button;
@ -26,29 +26,46 @@ public:
return singleton; return singleton;
} }
Source::View* get_view(int page); //Source::View* get_view(int page);
size_t get_index(int page); size_t size();
int size(); Source::View* get_view(size_t index);
Source::View* get_current_view(); Source::View* get_current_view();
bool close(int page); std::vector<Source::View*> &get_views();
bool close_current_page();
void open(const boost::filesystem::path &file_path); void open(const boost::filesystem::path &file_path, size_t notebook_index=-1);
bool save(int page); void configure(size_t index);
bool save(size_t index);
bool save_current(); 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(); boost::filesystem::path get_current_folder();
std::vector<Source::View*> source_views; //Is NOT freed in destructor, this is intended for quick program exit.
Gtk::Label info; Gtk::Label info;
Gtk::Label status; Gtk::Label status;
std::function<void()> on_switch_page;
std::function<void()> on_page_removed;
private: 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<size_t, int> get_notebook_page(size_t index);
std::vector<Gtk::Notebook> notebooks;
std::vector<Source::View*> source_views; //Is NOT freed in destructor, this is intended for quick program exit.
std::vector<std::unique_ptr<Gtk::Widget> > source_maps; std::vector<std::unique_ptr<Gtk::Widget> > source_maps;
std::vector<std::unique_ptr<Gtk::ScrolledWindow> > scrolled_windows; std::vector<std::unique_ptr<Gtk::ScrolledWindow> > scrolled_windows;
std::vector<std::unique_ptr<Gtk::HBox> > hboxes; std::vector<std::unique_ptr<Gtk::HBox> > hboxes;
std::vector<std::unique_ptr<TabLabel> > tab_labels; std::vector<std::unique_ptr<TabLabel> > 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_ #endif // JUCI_NOTEBOOK_H_

56
src/project.cc

@ -25,9 +25,7 @@ Gtk::Label &Project::debug_status_label() {
} }
void Project::save_files(const boost::filesystem::path &path) { void Project::save_files(const boost::filesystem::path &path) {
if(Notebook::get().get_current_page()==-1) for(size_t c=0;c<Notebook::get().size();c++) {
return;
for(int c=0;c<Notebook::get().size();c++) {
auto view=Notebook::get().get_view(c); auto view=Notebook::get().get_view(c);
if(view->get_buffer()->get_modified()) { if(view->get_buffer()->get_modified()) {
if(filesystem::file_in_path(view->file_path, path)) 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) { void Project::on_save(size_t index) {
if(page>=Notebook::get().size()) auto view=Notebook::get().get_view(index);
if(!view)
return; return;
auto view=Notebook::get().get_view(page);
if(view->language && view->language->get_id()=="cmake") { if(view->language && view->language->get_id()=="cmake") {
boost::filesystem::path cmake_path; boost::filesystem::path cmake_path;
if(view->file_path.filename()=="CMakeLists.txt") 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())) if(boost::filesystem::exists(build->get_debug_path()))
build->update_debug(true); build->update_debug(true);
for(int c=0;c<Notebook::get().size();c++) { for(size_t c=0;c<Notebook::get().size();c++) {
auto source_view=Notebook::get().get_view(c); auto source_view=Notebook::get().get_view(c);
if(auto source_clang_view=dynamic_cast<Source::ClangView*>(source_view)) { if(auto source_clang_view=dynamic_cast<Source::ClangView*>(source_view)) {
if(filesystem::file_in_path(source_clang_view->file_path, build->project_path)) 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() { void Project::debug_update_stop() {
for(int c=0;c<Notebook::get().size();c++) { for(size_t c=0;c<Notebook::get().size();c++) {
auto view=Notebook::get().get_view(c); auto view=Notebook::get().get_view(c);
if(view->file_path==debug_last_stop_file_path) { if(view->file_path==debug_last_stop_file_path) {
view->get_source_buffer()->remove_source_marks(view->get_buffer()->begin(), view->get_buffer()->end(), "debug_stop"); 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 //Add debug stop source mark
for(int c=0;c<Notebook::get().size();c++) { for(size_t c=0;c<Notebook::get().size();c++) {
auto view=Notebook::get().get_view(c); auto view=Notebook::get().get_view(c);
if(view->file_path==debug_stop.first) { if(view->file_path==debug_stop.first) {
if(debug_stop.second.first-1<view->get_buffer()->get_line_count()) { if(debug_stop.second.first-1<view->get_buffer()->get_line_count()) {
@ -102,15 +100,14 @@ void Project::debug_update_stop() {
break; break;
} }
} }
if(Notebook::get().get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
Notebook::get().get_current_view()->get_buffer()->place_cursor(Notebook::get().get_current_view()->get_buffer()->get_insert()->get_iter()); view->get_buffer()->place_cursor(view->get_buffer()->get_insert()->get_iter());
} }
std::unique_ptr<Project::Base> Project::create() { std::unique_ptr<Project::Base> Project::create() {
std::unique_ptr<Project::Build> build; std::unique_ptr<Project::Build> build;
if(Notebook::get().get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=Notebook::get().get_current_view();
build=Build::create(view->file_path); build=Build::create(view->file_path);
if(view->language) { if(view->language) {
auto language_id=view->language->get_id(); auto language_id=view->language->get_id();
@ -167,7 +164,8 @@ std::pair<std::string, std::string> Project::Clang::get_run_arguments() {
arguments=run_arguments_it->second; arguments=run_arguments_it->second;
if(arguments.empty()) { 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!="") { if(executable!="") {
size_t pos=executable.find(project_path); size_t pos=executable.find(project_path);
@ -210,7 +208,8 @@ void Project::Clang::compile_and_run() {
arguments=run_arguments_it->second; arguments=run_arguments_it->second;
if(arguments.empty()) { 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()) { if(arguments.empty()) {
Terminal::get().print("Warning: could not find executable.\n"); 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); 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<std::string, std::string> Project::Clang::debug_get_run_arguments() {
arguments=run_arguments_it->second; arguments=run_arguments_it->second;
if(arguments.empty()) { 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!="") { if(executable!="") {
size_t pos=executable.find(project_path); size_t pos=executable.find(project_path);
@ -277,7 +277,8 @@ void Project::Clang::debug_start() {
run_arguments=run_arguments_it->second; run_arguments=run_arguments_it->second;
if(run_arguments.empty()) { 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()) { if(run_arguments.empty()) {
Terminal::get().print("Warning: could not find executable.\n"); 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); 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<std::vector<std::pair<boost::filesystem::path, int> > >(); auto breakpoints=std::make_shared<std::vector<std::pair<boost::filesystem::path, int> > >();
for(int c=0;c<Notebook::get().size();c++) { for(size_t c=0;c<Notebook::get().size();c++) {
auto view=Notebook::get().get_view(c); auto view=Notebook::get().get_view(c);
if(filesystem::file_in_path(view->file_path, project_path)) { if(filesystem::file_in_path(view->file_path, project_path)) {
auto iter=view->get_buffer()->begin(); auto iter=view->get_buffer()->begin();
@ -361,10 +362,10 @@ void Project::Clang::debug_step_out() {
} }
void Project::Clang::debug_backtrace() { 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 backtrace=Debug::Clang::get().get_backtrace();
auto view=Notebook::get().get_current_view();
auto iter=view->get_iter_for_dialog(); auto iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true)); view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true));
auto rows=std::make_shared<std::unordered_map<std::string, Debug::Clang::Frame> >(); auto rows=std::make_shared<std::unordered_map<std::string, Debug::Clang::Frame> >();
@ -392,9 +393,7 @@ void Project::Clang::debug_backtrace() {
auto frame=rows->at(selected); auto frame=rows->at(selected);
if(!frame.file_path.empty()) { if(!frame.file_path.empty()) {
Notebook::get().open(frame.file_path); Notebook::get().open(frame.file_path);
if(Notebook::get().get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=Notebook::get().get_current_view();
Debug::Clang::get().select_frame(frame.index); Debug::Clang::get().select_frame(frame.index);
view->place_cursor_at_line_index(frame.line_nr-1, frame.line_index-1); 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() { 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 variables=Debug::Clang::get().get_variables();
auto view=Notebook::get().get_current_view();
auto iter=view->get_iter_for_dialog(); auto iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true)); view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true));
auto rows=std::make_shared<std::unordered_map<std::string, Debug::Clang::Variable> >(); auto rows=std::make_shared<std::unordered_map<std::string, Debug::Clang::Variable> >();
@ -428,9 +427,7 @@ void Project::Clang::debug_show_variables() {
auto variable=rows->at(selected); auto variable=rows->at(selected);
if(!variable.file_path.empty()) { if(!variable.file_path.empty()) {
Notebook::get().open(variable.file_path); Notebook::get().open(variable.file_path);
if(Notebook::get().get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=Notebook::get().get_current_view();
Debug::Clang::get().select_frame(variable.frame_index, variable.thread_index_id); 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); 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(); debug_variable_tooltips.hide();
return; return;
} }
if(Notebook::get().get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=Notebook::get().get_current_view();
debug_variable_tooltips.clear(); debug_variable_tooltips.clear();
auto create_tooltip_buffer=[this, rows, view, selected]() { auto create_tooltip_buffer=[this, rows, view, selected]() {
auto variable=rows->at(selected); auto variable=rows->at(selected);

2
src/project.h

@ -14,7 +14,7 @@
namespace Project { namespace Project {
Gtk::Label &debug_status_label(); Gtk::Label &debug_status_label();
void save_files(const boost::filesystem::path &path); 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 boost::filesystem::path debug_last_stop_file_path;
extern std::unordered_map<std::string, std::string> run_arguments; extern std::unordered_map<std::string, std::string> run_arguments;

3
src/terminal.cc

@ -365,8 +365,7 @@ bool Terminal::on_button_press_event(GdkEventButton* button_event) {
path=boost::filesystem::canonical(path_str, ec); path=boost::filesystem::canonical(path_str, ec);
if(!ec && boost::filesystem::is_regular_file(path)) { if(!ec && boost::filesystem::is_regular_file(path)) {
Notebook::get().open(path); Notebook::get().open(path);
if(Notebook::get().get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=Notebook::get().get_current_view();
try { try {
int line = std::stoi(sm[3].str())-1; int line = std::stoi(sm[3].str())-1;
int index = std::stoi(sm[4].str())-1; int index = std::stoi(sm[4].str())-1;

307
src/window.cc

@ -23,18 +23,19 @@ namespace sigc {
#endif #endif
} }
Window::Window() : notebook(Notebook::get()) { Window::Window() {
set_title("juCi++"); set_title("juCi++");
set_events(Gdk::POINTER_MOTION_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::SCROLL_MASK|Gdk::LEAVE_NOTIFY_MASK); set_events(Gdk::POINTER_MOTION_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::SCROLL_MASK|Gdk::LEAVE_NOTIFY_MASK);
set_menu_actions(); set_menu_actions();
configure(); configure();
activate_menu_items(false);
set_default_size(Config::get().window.default_size.first, Config::get().window.default_size.second); set_default_size(Config::get().window.default_size.first, Config::get().window.default_size.second);
directories_scrolled_window.add(Directories::get()); directories_scrolled_window.add(Directories::get());
directory_and_notebook_panes.pack1(directories_scrolled_window, Gtk::SHRINK); 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); notebook_vbox.pack_end(EntryBox::get(), Gtk::PACK_SHRINK);
directory_and_notebook_panes.pack2(notebook_vbox, Gtk::SHRINK); directory_and_notebook_panes.pack2(notebook_vbox, Gtk::SHRINK);
directory_and_notebook_panes.set_position(static_cast<int>(0.2*Config::get().window.default_size.first)); directory_and_notebook_panes.set_position(static_cast<int>(0.2*Config::get().window.default_size.first));
@ -44,7 +45,7 @@ Window::Window() : notebook(Notebook::get()) {
terminal_scrolled_window.add(Terminal::get()); terminal_scrolled_window.add(Terminal::get());
terminal_vbox.pack_start(terminal_scrolled_window); 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) #if GTK_VERSION_GE(3, 12)
info_and_status_hbox.set_center_widget(Project::debug_status_label()); 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); Project::debug_status_label().set_halign(Gtk::Align::ALIGN_CENTER);
info_and_status_hbox.pack_start(Project::debug_status_label()); info_and_status_hbox.pack_start(Project::debug_status_label());
#endif #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); terminal_vbox.pack_end(info_and_status_hbox, Gtk::PACK_SHRINK);
vpaned.pack2(terminal_vbox, true, true); vpaned.pack2(terminal_vbox, true, true);
@ -77,7 +78,7 @@ Window::Window() : notebook(Notebook::get()) {
Info::get().hide(); Info::get().hide();
Directories::get().on_row_activated=[this](const boost::filesystem::path &path) { 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 //Scroll to end of terminal whenever info is printed
@ -98,14 +99,12 @@ Window::Window() : notebook(Notebook::get()) {
notebook_vbox.unset_focus_chain(); notebook_vbox.unset_focus_chain();
}); });
EntryBox::get().signal_hide().connect([this]() { EntryBox::get().signal_hide().connect([this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->grab_focus(); view->grab_focus();
}
}); });
notebook.signal_switch_page().connect([this](Gtk::Widget* page, guint page_num) { Notebook::get().on_switch_page=[this] {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=notebook.get_current_view();
if(search_entry_shown && EntryBox::get().labels.size()>0) { if(search_entry_shown && EntryBox::get().labels.size()>0) {
view->update_search_occurrences=[this](int number){ view->update_search_occurrences=[this](int number){
EntryBox::get().labels.begin()->update(0, std::to_string(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_status(view->status);
view->set_info(view->info); 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(); EntryBox::get().hide();
}); };
about.signal_response().connect([this](int d){ about.signal_response().connect([this](int d){
about.hide(); about.hide();
@ -175,14 +174,14 @@ void Window::set_menu_actions() {
about.present(); about.present();
}); });
menu.add_action("preferences", [this]() { 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]() { menu.add_action("quit", [this]() {
close(); close();
}); });
menu.add_action("new_file", [this]() { 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(path!="") {
if(boost::filesystem::exists(path)) { if(boost::filesystem::exists(path)) {
Terminal::get().print("Error: "+path.string()+" already exists.\n", true); Terminal::get().print("Error: "+path.string()+" already exists.\n", true);
@ -191,7 +190,7 @@ void Window::set_menu_actions() {
if(filesystem::write(path)) { if(filesystem::write(path)) {
if(Directories::get().path!="") if(Directories::get().path!="")
Directories::get().update(); Directories::get().update();
notebook.open(path); Notebook::get().open(path);
Terminal::get().print("New file "+path.string()+" created.\n"); Terminal::get().print("New file "+path.string()+" created.\n");
} }
else else
@ -201,7 +200,7 @@ void Window::set_menu_actions() {
}); });
menu.add_action("new_folder", [this]() { menu.add_action("new_folder", [this]() {
auto time_now=std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); 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)) { if(path!="" && boost::filesystem::exists(path)) {
boost::system::error_code ec; boost::system::error_code ec;
auto last_write_time=boost::filesystem::last_write_time(path, 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]() { 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!="") { if(project_path!="") {
auto project_name=project_path.filename().string(); auto project_name=project_path.filename().string();
for(size_t c=0;c<project_name.size();c++) { for(size_t c=0;c<project_name.size();c++) {
@ -239,7 +238,7 @@ void Window::set_menu_actions() {
std::string cpp_main="#include <iostream>\n\nint main() {\n std::cout << \"Hello World!\\n\";\n}\n"; std::string cpp_main="#include <iostream>\n\nint main() {\n std::cout << \"Hello World!\\n\";\n}\n";
if(filesystem::write(cmakelists_path, cmakelists) && filesystem::write(cpp_main_path, cpp_main)) { if(filesystem::write(cmakelists_path, cmakelists) && filesystem::write(cpp_main_path, cpp_main)) {
Directories::get().open(project_path); Directories::get().open(project_path);
notebook.open(cpp_main_path); Notebook::get().open(cpp_main_path);
Directories::get().update(); Directories::get().update();
Terminal::get().print("C++ project "+project_name+" created.\n"); Terminal::get().print("C++ project "+project_name+" created.\n");
} }
@ -249,43 +248,41 @@ void Window::set_menu_actions() {
}); });
menu.add_action("open_file", [this]() { menu.add_action("open_file", [this]() {
auto path=Dialog::open_file(notebook.get_current_folder()); auto path=Dialog::open_file(Notebook::get().get_current_folder());
if(path!="") if(path!="")
notebook.open(path); Notebook::get().open(path);
}); });
menu.add_action("open_folder", [this]() { menu.add_action("open_folder", [this]() {
auto path = Dialog::open_folder(notebook.get_current_folder()); auto path = Dialog::open_folder(Notebook::get().get_current_folder());
if (path!="" && boost::filesystem::exists(path)) if (path!="" && boost::filesystem::exists(path))
Directories::get().open(path); Directories::get().open(path);
}); });
menu.add_action("save", [this]() { menu.add_action("save", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
if(notebook.save_current()) { if(Notebook::get().save_current()) {
if(notebook.get_current_page()!=-1) { if(view->file_path==Config::get().juci_home_path()/"config"/"config.json") {
if(notebook.get_current_view()->file_path==Config::get().juci_home_path()/"config"/"config.json") {
configure(); configure();
for(int c=0;c<notebook.size();c++) { for(size_t c=0;c<Notebook::get().size();c++) {
notebook.get_view(c)->configure(); Notebook::get().get_view(c)->configure();
notebook.configure(c); Notebook::get().configure(c);
}
} }
} }
} }
} }
}); });
menu.add_action("save_as", [this]() { menu.add_action("save_as", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto path = Dialog::save_file_as(notebook.get_current_view()->file_path); auto path = Dialog::save_file_as(view->file_path);
if(path!="") { if(path!="") {
std::ofstream file(path); std::ofstream file(path);
if(file) { if(file) {
file << notebook.get_current_view()->get_buffer()->get_text(); file << view->get_buffer()->get_text();
file.close(); file.close();
if(Directories::get().path!="") if(Directories::get().path!="")
Directories::get().update(); Directories::get().update();
notebook.open(path); Notebook::get().open(path);
Terminal::get().print("File saved to: " + notebook.get_current_view()->file_path.string()+"\n"); Terminal::get().print("File saved to: " + Notebook::get().get_current_view()->file_path.string()+"\n");
} }
else else
Terminal::get().print("Error saving file\n"); Terminal::get().print("Error saving file\n");
@ -294,8 +291,7 @@ void Window::set_menu_actions() {
}); });
menu.add_action("print", [this]() { menu.add_action("print", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=notebook.get_current_view();
auto print_operation=Gtk::PrintOperation::create(); auto print_operation=Gtk::PrintOperation::create();
auto print_compositor=Gsv::PrintCompositor::create(*view); auto print_compositor=Gsv::PrintCompositor::create(*view);
@ -315,20 +311,20 @@ void Window::set_menu_actions() {
}); });
menu.add_action("edit_undo", [this]() { menu.add_action("edit_undo", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto undo_manager = notebook.get_current_view()->get_source_buffer()->get_undo_manager(); auto undo_manager = view->get_source_buffer()->get_undo_manager();
if (undo_manager->can_undo()) { if (undo_manager->can_undo()) {
undo_manager->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]() { menu.add_action("edit_redo", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto undo_manager = notebook.get_current_view()->get_source_buffer()->get_undo_manager(); auto undo_manager = view->get_source_buffer()->get_undo_manager();
if(undo_manager->can_redo()) { if(undo_manager->can_redo()) {
undo_manager->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(); auto widget=get_focus();
if(auto entry=dynamic_cast<Gtk::Entry*>(widget)) if(auto entry=dynamic_cast<Gtk::Entry*>(widget))
entry->cut_clipboard(); entry->cut_clipboard();
else if(notebook.get_current_page()!=-1) else if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->get_buffer()->cut_clipboard(Gtk::Clipboard::get()); view->get_buffer()->cut_clipboard(Gtk::Clipboard::get());
}); });
menu.add_action("edit_copy", [this]() { menu.add_action("edit_copy", [this]() {
auto widget=get_focus(); auto widget=get_focus();
@ -351,8 +347,8 @@ void Window::set_menu_actions() {
auto widget=get_focus(); auto widget=get_focus();
if(auto entry=dynamic_cast<Gtk::Entry*>(widget)) if(auto entry=dynamic_cast<Gtk::Entry*>(widget))
entry->paste_clipboard(); entry->paste_clipboard();
else if(notebook.get_current_page()!=-1) else if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->paste(); view->paste();
}); });
menu.add_action("edit_find", [this]() { menu.add_action("edit_find", [this]() {
@ -360,41 +356,39 @@ void Window::set_menu_actions() {
}); });
menu.add_action("source_spellcheck", [this]() { menu.add_action("source_spellcheck", [this]() {
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->spellcheck(); view->spellcheck();
}); });
menu.add_action("source_spellcheck_clear", [this]() { menu.add_action("source_spellcheck_clear", [this]() {
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->remove_spellcheck_errors(); view->remove_spellcheck_errors();
}); });
menu.add_action("source_spellcheck_next_error", [this]() { menu.add_action("source_spellcheck_next_error", [this]() {
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->goto_next_spellcheck_error(); view->goto_next_spellcheck_error();
}); });
menu.add_action("source_indentation_set_buffer_tab", [this]() { menu.add_action("source_indentation_set_buffer_tab", [this]() {
set_tab_entry(); set_tab_entry();
}); });
menu.add_action("source_indentation_auto_indent_buffer", [this]() { menu.add_action("source_indentation_auto_indent_buffer", [this]() {
if(notebook.get_current_page()!=-1 && notebook.get_current_view()->auto_indent) auto view=Notebook::get().get_current_view();
notebook.get_current_view()->auto_indent(); if(view && view->auto_indent)
view->auto_indent();
}); });
menu.add_action("source_goto_line", [this]() { menu.add_action("source_goto_line", [this]() {
goto_line_entry(); goto_line_entry();
}); });
menu.add_action("source_center_cursor", [this]() { menu.add_action("source_center_cursor", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view())
auto view=notebook.get_current_view();
view->scroll_to_cursor_delayed(view, true, false); view->scroll_to_cursor_delayed(view, true, false);
}
}); });
menu.add_action("source_find_documentation", [this]() { menu.add_action("source_find_documentation", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
if(notebook.get_current_view()->get_token_data) { if(view->get_token_data) {
auto data=notebook.get_current_view()->get_token_data(); auto data=view->get_token_data();
if(data.size()>0) { if(data.size()>0) {
auto documentation_search=Config::get().source.documentation_searches.find(data[0]); auto documentation_search=Config::get().source.documentation_searches.find(data[0]);
if(documentation_search!=Config::get().source.documentation_searches.end()) { 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]() { menu.add_action("source_goto_declaration", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
if(notebook.get_current_view()->get_declaration_location) { if(view->get_declaration_location) {
auto location=notebook.get_current_view()->get_declaration_location(notebook.source_views); auto location=view->get_declaration_location(Notebook::get().get_views());
if(location) { if(location) {
boost::filesystem::path declaration_file; boost::filesystem::path declaration_file;
boost::system::error_code ec; boost::system::error_code ec;
declaration_file=boost::filesystem::canonical(location.file_path, ec); declaration_file=boost::filesystem::canonical(location.file_path, ec);
if(ec) if(ec)
return; return;
notebook.open(declaration_file); Notebook::get().open(declaration_file);
auto view=notebook.get_current_view(); auto view=Notebook::get().get_current_view();
auto line=static_cast<int>(location.line)-1; auto line=static_cast<int>(location.line)-1;
auto index=static_cast<int>(location.index)-1; auto index=static_cast<int>(location.index)-1;
view->place_cursor_at_line_index(line, index); view->place_cursor_at_line_index(line, index);
@ -453,18 +447,17 @@ void Window::set_menu_actions() {
} }
}); });
menu.add_action("source_goto_implementation", [this]() { menu.add_action("source_goto_implementation", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=notebook.get_current_view();
if(view->get_implementation_location) { 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) { if(location) {
boost::filesystem::path implementation_path; boost::filesystem::path implementation_path;
boost::system::error_code ec; boost::system::error_code ec;
implementation_path=boost::filesystem::canonical(location.file_path, ec); implementation_path=boost::filesystem::canonical(location.file_path, ec);
if(ec) if(ec)
return; return;
notebook.open(implementation_path); Notebook::get().open(implementation_path);
auto view=notebook.get_current_view(); auto view=Notebook::get().get_current_view();
auto line=static_cast<int>(location.line)-1; auto line=static_cast<int>(location.line)-1;
auto index=static_cast<int>(location.index)-1; auto index=static_cast<int>(location.index)-1;
view->place_cursor_at_line_index(line, index); view->place_cursor_at_line_index(line, index);
@ -476,10 +469,9 @@ void Window::set_menu_actions() {
}); });
menu.add_action("source_goto_usage", [this]() { menu.add_action("source_goto_usage", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=notebook.get_current_view();
if(view->get_usages) { if(view->get_usages) {
auto usages=view->get_usages(notebook.source_views); auto usages=view->get_usages(Notebook::get().get_views());
if(!usages.empty()) { if(!usages.empty()) {
auto iter=view->get_iter_for_dialog(); auto iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true)); view->selection_dialog=std::unique_ptr<SelectionDialog>(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); declaration_file=boost::filesystem::canonical(offset.file_path, ec);
if(ec) if(ec)
return; return;
notebook.open(declaration_file); Notebook::get().open(declaration_file);
auto view=notebook.get_current_view(); auto view=Notebook::get().get_current_view();
view->place_cursor_at_line_index(offset.line, offset.index); 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->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5);
view->delayed_tooltips_connection.disconnect(); view->delayed_tooltips_connection.disconnect();
@ -516,10 +508,9 @@ void Window::set_menu_actions() {
} }
}); });
menu.add_action("source_goto_method", [this]() { menu.add_action("source_goto_method", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=notebook.get_current_view();
if(view->get_methods) { if(view->get_methods) {
auto methods=notebook.get_current_view()->get_methods(); auto methods=Notebook::get().get_current_view()->get_methods();
if(!methods.empty()) { if(!methods.empty()) {
auto iter=view->get_iter_for_dialog(); auto iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true)); view->selection_dialog=std::unique_ptr<SelectionDialog>(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]() { menu.add_action("source_goto_next_diagnostic", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
if(notebook.get_current_view()->goto_next_diagnostic) { if(view->goto_next_diagnostic) {
notebook.get_current_view()->goto_next_diagnostic(); view->goto_next_diagnostic();
} }
} }
}); });
menu.add_action("source_apply_fix_its", [this]() { menu.add_action("source_apply_fix_its", [this]() {
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=notebook.get_current_view();
if(view->get_fix_its) { if(view->get_fix_its) {
auto buffer=view->get_buffer(); auto buffer=view->get_buffer();
auto fix_its=view->get_fix_its(); 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){ EntryBox::get().entries.emplace_back(last_run_command, [this](const std::string& content){
if(content!="") { if(content!="") {
last_run_command=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_print("Running: "+content+'\n');
Terminal::get().async_process(content, run_path, [this, content](int exit_status){ Terminal::get().async_process(content, run_path, [this, content](int exit_status){
@ -760,8 +750,7 @@ void Window::set_menu_actions() {
EntryBox::get().show(); EntryBox::get().show();
}); });
menu.add_action("debug_toggle_breakpoint", [this](){ menu.add_action("debug_toggle_breakpoint", [this](){
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=notebook.get_current_view();
auto line_nr=view->get_buffer()->get_insert()->get_iter().get_line(); 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) { 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](){ menu.add_action("debug_goto_stop", [this](){
if(Project::debugging) { if(Project::debugging) {
if(!Project::debug_stop.first.empty()) { if(!Project::debug_stop.first.empty()) {
notebook.open(Project::debug_stop.first); Notebook::get().open(Project::debug_stop.first);
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=notebook.get_current_view();
int line=Project::debug_stop.second.first-1; int line=Project::debug_stop.second.first-1;
int index=Project::debug_stop.second.second-1; int index=Project::debug_stop.second.second-1;
view->place_cursor_at_line_index(line, index); view->place_cursor_at_line_index(line, index);
@ -800,36 +787,32 @@ void Window::set_menu_actions() {
#endif #endif
menu.add_action("next_tab", [this]() { menu.add_action("next_tab", [this]() {
if(notebook.get_current_page()!=-1) { Notebook::get().next();
notebook.open(notebook.get_view((notebook.get_current_page()+1)%notebook.size())->file_path);
}
}); });
menu.add_action("previous_tab", [this]() { menu.add_action("previous_tab", [this]() {
if(notebook.get_current_page()!=-1) { Notebook::get().previous();
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);
}
}); });
menu.add_action("close_tab", [this]() { menu.add_action("close_tab", [this]() {
notebook.close_current_page(); Notebook::get().close_current();
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
notebook.get_current_view()->set_status(notebook.get_current_view()->status); view->set_status(view->status);
notebook.get_current_view()->set_info(notebook.get_current_view()->info); view->set_info(view->info);
} }
else { else {
notebook.status.set_text(""); Notebook::get().status.set_text("");
notebook.info.set_text(""); Notebook::get().info.set_text("");
activate_menu_items(false); 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) { void Window::activate_menu_items(bool activate) {
auto &menu = Menu::get(); auto &menu = Menu::get();
auto &notebook = Notebook::get();
menu.actions["source_indentation_auto_indent_buffer"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->auto_indent) : false); menu.actions["source_indentation_auto_indent_buffer"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->auto_indent) : false);
menu.actions["source_find_documentation"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_token_data) : false); menu.actions["source_find_documentation"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_token_data) : false);
menu.actions["source_goto_declaration"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_declaration_location) : false); menu.actions["source_goto_declaration"]->set_enabled(activate ? static_cast<bool>(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<bool>(notebook.get_current_view()->goto_next_diagnostic) : false); menu.actions["source_goto_next_diagnostic"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->goto_next_diagnostic) : false);
menu.actions["source_apply_fix_its"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_fix_its) : false); menu.actions["source_apply_fix_its"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_fix_its) : false);
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
if(notebook.get_current_page()!=-1) { if(auto view=notebook.get_current_view()) {
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")) 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); menu.actions["debug_toggle_breakpoint"]->set_enabled(true);
else else
@ -887,24 +869,11 @@ bool Window::on_key_press_event(GdkEventKey *event) {
} }
bool Window::on_delete_event(GdkEventAny *event) { bool Window::on_delete_event(GdkEventAny *event) {
try { Notebook::get().save_session();
boost::property_tree::ptree pt_root, pt_files;
pt_root.put("folder", Directories::get().path.string()); auto size=Notebook::get().size();
for(int c=0;c<notebook.size();c++) { for(size_t c=0;c<size;c++) {
boost::property_tree::ptree pt_child; if(!Notebook::get().close_current())
pt_child.put("", notebook.get_view(c)->file_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 &) {}
auto size=notebook.size();
for(int c=0;c<size;c++) {
if(!notebook.close_current_page())
return true; return true;
} }
Terminal::get().kill_async_processes(); Terminal::get().kill_async_processes();
@ -912,6 +881,7 @@ bool Window::on_delete_event(GdkEventAny *event) {
if(Project::current) if(Project::current)
Project::current->debug_cancel(); Project::current->debug_cancel();
#endif #endif
return false; return false;
} }
@ -934,41 +904,41 @@ void Window::search_and_replace_entry() {
} }
}; };
EntryBox::get().entries.emplace_back(last_search, [this](const std::string& content){ EntryBox::get().entries.emplace_back(last_search, [this](const std::string& content){
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->search_forward(); view->search_forward();
}); });
auto search_entry_it=EntryBox::get().entries.begin(); auto search_entry_it=EntryBox::get().entries.begin();
search_entry_it->set_placeholder_text("Find"); search_entry_it->set_placeholder_text("Find");
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
notebook.get_current_view()->update_search_occurrences=[label_it](int number){ view->update_search_occurrences=[label_it](int number){
label_it->update(0, std::to_string(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){ search_entry_it->signal_key_press_event().connect([this](GdkEventKey* event){
if(event->keyval==GDK_KEY_Return && (event->state&GDK_SHIFT_MASK)>0) { if(event->keyval==GDK_KEY_Return && (event->state&GDK_SHIFT_MASK)>0) {
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->search_backward(); view->search_backward();
} }
return false; return false;
}); });
search_entry_it->signal_changed().connect([this, search_entry_it](){ search_entry_it->signal_changed().connect([this, search_entry_it](){
last_search=search_entry_it->get_text(); last_search=search_entry_it->get_text();
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
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);
}); });
EntryBox::get().entries.emplace_back(last_replace, [this](const std::string &content){ EntryBox::get().entries.emplace_back(last_replace, [this](const std::string &content){
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->replace_forward(content); view->replace_forward(content);
}); });
auto replace_entry_it=EntryBox::get().entries.begin(); auto replace_entry_it=EntryBox::get().entries.begin();
replace_entry_it++; replace_entry_it++;
replace_entry_it->set_placeholder_text("Replace"); replace_entry_it->set_placeholder_text("Replace");
replace_entry_it->signal_key_press_event().connect([this, replace_entry_it](GdkEventKey* event){ 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(event->keyval==GDK_KEY_Return && (event->state&GDK_SHIFT_MASK)>0) {
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->replace_backward(replace_entry_it->get_text()); view->replace_backward(replace_entry_it->get_text());
} }
return false; return false;
}); });
@ -977,24 +947,24 @@ void Window::search_and_replace_entry() {
}); });
EntryBox::get().buttons.emplace_back("", [this](){ EntryBox::get().buttons.emplace_back("", [this](){
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->search_backward(); view->search_backward();
}); });
EntryBox::get().buttons.back().set_tooltip_text("Find Previous\n\nShortcut: Shift+Enter in the Find entry field"); 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](){ EntryBox::get().buttons.emplace_back("", [this, replace_entry_it](){
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
notebook.get_current_view()->replace_forward(replace_entry_it->get_text()); 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.back().set_tooltip_text("Replace Next\n\nShortcut: Enter in the Replace entry field");
EntryBox::get().buttons.emplace_back("", [this](){ EntryBox::get().buttons.emplace_back("", [this](){
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->search_forward(); view->search_forward();
}); });
EntryBox::get().buttons.back().set_tooltip_text("Find Next\n\nShortcut: Enter in the Find entry field"); 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](){ EntryBox::get().buttons.emplace_back("Replace All", [this, replace_entry_it](){
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
notebook.get_current_view()->replace_all(replace_entry_it->get_text()); view->replace_all(replace_entry_it->get_text());
}); });
EntryBox::get().buttons.back().set_tooltip_text("Replace All"); 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().set_active(case_sensitive_search);
EntryBox::get().toggle_buttons.back().on_activate=[this, search_entry_it](){ EntryBox::get().toggle_buttons.back().on_activate=[this, search_entry_it](){
case_sensitive_search=!case_sensitive_search; case_sensitive_search=!case_sensitive_search;
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
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);
}; };
EntryBox::get().toggle_buttons.emplace_back(".*"); EntryBox::get().toggle_buttons.emplace_back(".*");
EntryBox::get().toggle_buttons.back().set_tooltip_text("Use Regex"); EntryBox::get().toggle_buttons.back().set_tooltip_text("Use Regex");
EntryBox::get().toggle_buttons.back().set_active(regex_search); EntryBox::get().toggle_buttons.back().set_active(regex_search);
EntryBox::get().toggle_buttons.back().on_activate=[this, search_entry_it](){ EntryBox::get().toggle_buttons.back().on_activate=[this, search_entry_it](){
regex_search=!regex_search; regex_search=!regex_search;
if(notebook.get_current_page()!=-1) if(auto view=Notebook::get().get_current_view())
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);
}; };
EntryBox::get().signal_hide().connect([this]() { EntryBox::get().signal_hide().connect([this]() {
for(int c=0;c<notebook.size();c++) { for(size_t c=0;c<Notebook::get().size();c++) {
notebook.get_view(c)->update_search_occurrences=nullptr; Notebook::get().get_view(c)->update_search_occurrences=nullptr;
notebook.get_view(c)->search_highlight("", case_sensitive_search, regex_search); Notebook::get().get_view(c)->search_highlight("", case_sensitive_search, regex_search);
} }
search_entry_shown=false; search_entry_shown=false;
}); });
@ -1027,8 +997,8 @@ void Window::search_and_replace_entry() {
void Window::set_tab_entry() { void Window::set_tab_entry() {
EntryBox::get().clear(); EntryBox::get().clear();
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto tab_char_and_size=notebook.get_current_view()->get_tab_char_and_size(); auto tab_char_and_size=view->get_tab_char_and_size();
EntryBox::get().labels.emplace_back(); EntryBox::get().labels.emplace_back();
auto label_it=EntryBox::get().labels.begin(); 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"); 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){ 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; char tab_char=0;
unsigned tab_size=0; unsigned tab_size=0;
try { try {
@ -1064,7 +1034,7 @@ void Window::set_tab_entry() {
catch(const std::exception &e) {} catch(const std::exception &e) {}
if(tab_char!=0 && tab_size>0) { 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(); EntryBox::get().hide();
} }
else { else {
@ -1086,10 +1056,9 @@ void Window::set_tab_entry() {
void Window::goto_line_entry() { void Window::goto_line_entry() {
EntryBox::get().clear(); 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){ EntryBox::get().entries.emplace_back("", [this](const std::string& content){
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=notebook.get_current_view();
try { try {
view->place_cursor_at_line_index(stoi(content)-1, 0); view->place_cursor_at_line_index(stoi(content)-1, 0);
view->scroll_to_cursor_delayed(view, true, false); view->scroll_to_cursor_delayed(view, true, false);
@ -1109,8 +1078,7 @@ void Window::goto_line_entry() {
void Window::rename_token_entry() { void Window::rename_token_entry() {
EntryBox::get().clear(); EntryBox::get().clear();
if(notebook.get_current_page()!=-1) { if(auto view=Notebook::get().get_current_view()) {
auto view=notebook.get_current_view();
if(view->get_token_spelling && view->rename_similar_tokens) { if(view->get_token_spelling && view->rename_similar_tokens) {
auto spelling=std::make_shared<std::string>(view->get_token_spelling()); auto spelling=std::make_shared<std::string>(view->get_token_spelling());
if(!spelling->empty()) { 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){ 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 //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 //iter->get_buffer() will print such a message, but no segfault will occur
if(notebook.get_current_page()!=-1 && notebook.get_current_view()==view && if(Notebook::get().get_current_view()==view && content!=*spelling && iter->get_buffer() && view->get_buffer()->get_insert()->get_iter()==*iter) {
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);
auto renamed_pairs=view->rename_similar_tokens(notebook.source_views, content);
for(auto &renamed: renamed_pairs) 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"); Terminal::get().print("Replaced "+std::to_string(renamed.second)+" occurrence"+(renamed.second>1?"s":"")+" in file "+renamed.first.string()+"\n");
} }

2
src/window.h

@ -6,9 +6,7 @@
#include <atomic> #include <atomic>
class Window : public Gtk::ApplicationWindow { class Window : public Gtk::ApplicationWindow {
private:
Window(); Window();
Notebook &notebook; //convenience reference
public: public:
static Window &get() { static Window &get() {
static Window singleton; static Window singleton;

Loading…
Cancel
Save