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;
}
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);
if(is_directory) {
if(filesystem::file_in_path(view->file_path, source_path)) {
@ -320,7 +320,7 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
update();
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);
if(is_directory) {
if(filesystem::file_in_path(view->file_path, *source_path)) {
@ -379,7 +379,7 @@ Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
else {
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);
if(is_directory) {

5
src/files.h

@ -2,7 +2,7 @@
#define JUCI_FILES_H_
#include <string>
#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": "<primary><alt>Left",)RAW"
#endif
R"RAW(
"close_tab": "<primary>w"
"close_tab": "<primary>w",
"window_toggle_split": ""
},
"project": {
"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)) {
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<Gio::ApplicationCommandLine>
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<std::string>("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<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))
files.emplace_back(file);
files.emplace_back(file, notebook);
}
last_current_file=pt.get<std::string>("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);

2
src/juci.h

@ -39,7 +39,7 @@ public:
void on_startup() override;
private:
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;
};

7
src/menu.cc

@ -382,6 +382,13 @@ Menu::Menu() {
+accels["close_tab"]+ //For Ubuntu...
" </item>"
" </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>"
" </menu>"
"</interface>";

333
src/notebook.cc

@ -50,10 +50,38 @@ 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();
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();
//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
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<int>(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;c<hboxes.size();c++) {
if(page_num(*hboxes.at(c))==page)
return c;
Source::View* Notebook::get_current_view() {
for(auto &view: source_views) {
if(view->has_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<Source::View*> &Notebook::get_views() {
return source_views;
}
void Notebook::open(const boost::filesystem::path &file_path) {
for(int c=0;c<size();c++) {
if(file_path==get_view(c)->file_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;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;
}
}
@ -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<size();c++) {
if(get_view(c)==source_view) {
close(c);
break;
}
}
tab_labels.emplace_back(new TabLabel(file_path, [this, source_view]() {
auto index=get_index(source_view);
if(index!=static_cast<size_t>(-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;c<size();c++) {
if(get_view(c)==source_view) {
page=c;
break;
}
}
if(page!=-1) {
auto &tab_label=tab_labels.at(get_index(page));
for(size_t c=0;c<size();c++) {
if(source_views[c]==source_view) {
auto &tab_label=tab_labels.at(c);
tab_label->label.set_text(title);
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
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);
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)
if(auto view=get_current_view())
return save(get_index(view));
return false;
return save(get_current_page());
}
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_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(!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<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;
}
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<last_index && last_index!=static_cast<size_t>(-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<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() {
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<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);
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) {

43
src/notebook.h

@ -9,7 +9,7 @@
#include <map>
#include <sigc++/sigc++.h>
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<Source::View*> &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::View*> source_views; //Is NOT freed in destructor, this is intended for quick program exit.
Gtk::Label info;
Gtk::Label status;
std::function<void()> on_switch_page;
std::function<void()> 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<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::ScrolledWindow> > scrolled_windows;
std::vector<std::unique_ptr<Gtk::HBox> > hboxes;
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_

56
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;c<Notebook::get().size();c++) {
for(size_t c=0;c<Notebook::get().size();c++) {
auto view=Notebook::get().get_view(c);
if(view->get_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<Notebook::get().size();c++) {
for(size_t c=0;c<Notebook::get().size();c++) {
auto source_view=Notebook::get().get_view(c);
if(auto source_clang_view=dynamic_cast<Source::ClangView*>(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;c<Notebook::get().size();c++) {
for(size_t c=0;c<Notebook::get().size();c++) {
auto view=Notebook::get().get_view(c);
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");
@ -92,7 +90,7 @@ void Project::debug_update_stop() {
}
}
//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);
if(view->file_path==debug_stop.first) {
if(debug_stop.second.first-1<view->get_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::Base> Project::create() {
std::unique_ptr<Project::Build> 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<std::string, std::string> 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<std::string, std::string> 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<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);
if(filesystem::file_in_path(view->file_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<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> >();
@ -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<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> >();
@ -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);

2
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<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);
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;

307
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<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_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;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";
if(filesystem::write(cmakelists_path, cmakelists) && filesystem::write(cpp_main_path, cpp_main)) {
Directories::get().open(project_path);
notebook.open(cpp_main_path);
Notebook::get().open(cpp_main_path);
Directories::get().update();
Terminal::get().print("C++ project "+project_name+" created.\n");
}
@ -249,43 +248,41 @@ void Window::set_menu_actions() {
});
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!="")
notebook.open(path);
Notebook::get().open(path);
});
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))
Directories::get().open(path);
});
menu.add_action("save", [this]() {
if(notebook.get_current_page()!=-1) {
if(notebook.save_current()) {
if(notebook.get_current_page()!=-1) {
if(notebook.get_current_view()->file_path==Config::get().juci_home_path()/"config"/"config.json") {
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(int c=0;c<notebook.size();c++) {
notebook.get_view(c)->configure();
notebook.configure(c);
}
for(size_t c=0;c<Notebook::get().size();c++) {
Notebook::get().get_view(c)->configure();
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<Gtk::Entry*>(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<Gtk::Entry*>(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<int>(location.line)-1;
auto index=static_cast<int>(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<int>(location.line)-1;
auto index=static_cast<int>(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<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);
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<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]() {
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 &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_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);
@ -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_apply_fix_its"]->set_enabled(activate ? static_cast<bool>(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;c<notebook.size();c++) {
boost::property_tree::ptree pt_child;
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())
Notebook::get().save_session();
auto size=Notebook::get().size();
for(size_t c=0;c<size;c++) {
if(!Notebook::get().close_current())
return true;
}
Terminal::get().kill_async_processes();
@ -912,6 +881,7 @@ bool Window::on_delete_event(GdkEventAny *event) {
if(Project::current)
Project::current->debug_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;c<notebook.size();c++) {
notebook.get_view(c)->update_search_occurrences=nullptr;
notebook.get_view(c)->search_highlight("", case_sensitive_search, regex_search);
for(size_t c=0;c<Notebook::get().size();c++) {
Notebook::get().get_view(c)->update_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<std::string>(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");
}

2
src/window.h

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

Loading…
Cancel
Save