Browse Source

Cursor history implemented, fixes #292

merge-requests/365/head
eidheim 9 years ago
parent
commit
d165223af9
  1. 2
      CMakeLists.txt
  2. 2
      src/files.h
  3. 11
      src/menu.cc
  4. 86
      src/notebook.cc
  5. 14
      src/notebook.h
  6. 32
      src/window.cc

2
CMakeLists.txt

@ -1,7 +1,7 @@
cmake_minimum_required (VERSION 2.8.8) cmake_minimum_required (VERSION 2.8.8)
project(juci) project(juci)
set(JUCI_VERSION "1.2.1.6") set(JUCI_VERSION "1.2.1.7")
set(CPACK_PACKAGE_NAME "jucipp") set(CPACK_PACKAGE_NAME "jucipp")
set(CPACK_PACKAGE_CONTACT "Ole Christian Eidheim <eidheim@gmail.com>") set(CPACK_PACKAGE_CONTACT "Ole Christian Eidheim <eidheim@gmail.com>")

2
src/files.h

@ -105,6 +105,8 @@ R"RAW(
"source_indentation_auto_indent_buffer": "<primary><shift>i", "source_indentation_auto_indent_buffer": "<primary><shift>i",
"source_goto_line": "<primary>g", "source_goto_line": "<primary>g",
"source_center_cursor": "<primary>l", "source_center_cursor": "<primary>l",
"source_cursor_history_back": "<alt>Left",
"source_cursor_history_forward": "<alt>Right",
"source_find_symbol_ctags": "<primary><shift>f", "source_find_symbol_ctags": "<primary><shift>f",
"source_comments_toggle": "<primary>slash", "source_comments_toggle": "<primary>slash",
"source_comments_add_documentation": "<primary><alt>slash", "source_comments_add_documentation": "<primary><alt>slash",

11
src/menu.cc

@ -167,6 +167,17 @@ Menu::Menu() {
<attribute name='label' translatable='yes'>_Center _Cursor</attribute> <attribute name='label' translatable='yes'>_Center _Cursor</attribute>
<attribute name='action'>app.source_center_cursor</attribute> <attribute name='action'>app.source_center_cursor</attribute>
</item> </item>
<submenu>
<attribute name='label' translatable='yes'>_Cursor _History</attribute>
<item>
<attribute name='label' translatable='yes'>_Back</attribute>
<attribute name='action'>app.source_cursor_history_back</attribute>
</item>
<item>
<attribute name='label' translatable='yes'>_Forward</attribute>
<attribute name='action'>app.source_cursor_history_forward</attribute>
</item>
</submenu>
</section> </section>
<section> <section>
<item> <item>

86
src/notebook.cc

@ -303,9 +303,69 @@ void Notebook::open(const boost::filesystem::path &file_path, size_t notebook_in
source_view->update_tab_label(source_view); source_view->update_tab_label(source_view);
}); });
source_view->signal_focus_in_event().connect([this, source_view](GdkEventFocus *) { //Cursor history
set_current_view(source_view); auto update_cursor_locations=[this, source_view](const Gtk::TextBuffer::iterator &iter) {
return false; bool mark_moved=false;
if(current_cursor_location!=static_cast<size_t>(-1)) {
auto &cursor_location=cursor_locations.at(current_cursor_location);
if(cursor_location.view==source_view && abs(cursor_location.mark->get_iter().get_line()-iter.get_line())<=2) {
source_view->get_buffer()->move_mark(cursor_location.mark, iter);
mark_moved=true;
}
}
if(!mark_moved) {
if(current_cursor_location!=static_cast<size_t>(-1)) {
for(auto it=cursor_locations.begin()+current_cursor_location+1;it!=cursor_locations.end();) {
it->view->get_buffer()->delete_mark(it->mark);
it=cursor_locations.erase(it);
}
}
cursor_locations.emplace_back(source_view, source_view->get_buffer()->create_mark(iter));
current_cursor_location=cursor_locations.size()-1;
}
// Combine adjacent cursor histories that are similar
if(!cursor_locations.empty()) {
size_t cursor_locations_index=1;
auto last_it=cursor_locations.begin();
for(auto it=cursor_locations.begin()+1;it!=cursor_locations.end();) {
if(last_it->view==it->view && abs(last_it->mark->get_iter().get_line()-it->mark->get_iter().get_line())<=2) {
last_it->view->get_buffer()->delete_mark(last_it->mark);
last_it->mark=it->mark;
it=cursor_locations.erase(it);
if(current_cursor_location!=static_cast<size_t>(-1) && current_cursor_location>cursor_locations_index)
--current_cursor_location;
}
else {
++it;
++last_it;
++cursor_locations_index;
}
}
}
// Remove start of cache if cache limit is exceeded
while(cursor_locations.size()>10) {
cursor_locations.begin()->view->get_buffer()->delete_mark(cursor_locations.begin()->mark);
cursor_locations.erase(cursor_locations.begin());
if(current_cursor_location!=static_cast<size_t>(-1))
--current_cursor_location;
}
if(current_cursor_location>=cursor_locations.size())
current_cursor_location=cursor_locations.size()-1;
};
source_view->get_buffer()->signal_mark_set().connect([this, source_view, update_cursor_locations](const Gtk::TextBuffer::iterator &iter, const Glib::RefPtr<Gtk::TextBuffer::Mark> &mark) {
if(mark->get_name()=="insert") {
if(disable_next_update_cursor_locations) {
disable_next_update_cursor_locations=false;
return;
}
update_cursor_locations(iter);
}
});
source_view->get_buffer()->signal_changed().connect([source_view, update_cursor_locations] {
update_cursor_locations(source_view->get_buffer()->get_insert()->get_iter());
}); });
#ifdef JUCI_ENABLE_DEBUG #ifdef JUCI_ENABLE_DEBUG
@ -331,6 +391,11 @@ void Notebook::open(const boost::filesystem::path &file_path, size_t notebook_in
} }
#endif #endif
source_view->signal_focus_in_event().connect([this, source_view](GdkEventFocus *) {
set_current_view(source_view);
return false;
});
if(notebook_index==static_cast<size_t>(-1)) { if(notebook_index==static_cast<size_t>(-1)) {
if(!split) if(!split)
notebook_index=0; notebook_index=0;
@ -455,6 +520,21 @@ bool Notebook::close(size_t index) {
if(on_close_page) if(on_close_page)
on_close_page(view); on_close_page(view);
size_t cursor_locations_index=0;
for(auto it=cursor_locations.begin();it!=cursor_locations.end();) {
if(it->view==view) {
it=cursor_locations.erase(it);
if(current_cursor_location!=static_cast<size_t>(-1) && current_cursor_location>cursor_locations_index)
--current_cursor_location;
}
else {
++it;
++cursor_locations_index;
}
}
if(current_cursor_location>=cursor_locations.size())
current_cursor_location=cursor_locations.size()-1;
if(auto clang_view=dynamic_cast<Source::ClangView*>(view)) if(auto clang_view=dynamic_cast<Source::ClangView*>(view))
clang_view->async_delete(); clang_view->async_delete();
else else

14
src/notebook.h

@ -16,6 +16,13 @@ class Notebook : public Gtk::HPaned {
Gtk::Label label; Gtk::Label label;
}; };
class CursorLocation {
public:
CursorLocation(Source::View *view, Glib::RefPtr<Gtk::TextBuffer::Mark> mark) : view(view), mark(mark) {}
Source::View *view;
Glib::RefPtr<Gtk::TextBuffer::Mark> mark;
};
private: private:
Notebook(); Notebook();
public: public:
@ -24,7 +31,6 @@ public:
return singleton; return singleton;
} }
//Source::View* get_view(int page);
size_t size(); size_t size();
Source::View* get_view(size_t index); Source::View* get_view(size_t index);
Source::View* get_current_view(); Source::View* get_current_view();
@ -52,6 +58,12 @@ public:
std::function<void(Source::View*)> on_change_page; std::function<void(Source::View*)> on_change_page;
std::function<void(Source::View*)> on_close_page; std::function<void(Source::View*)> on_close_page;
/// Cursor history
std::vector<CursorLocation> cursor_locations;
size_t current_cursor_location=-1;
bool disable_next_update_cursor_locations=false;
private: private:
size_t get_index(Source::View *view); size_t get_index(Source::View *view);
Source::View *get_view(size_t notebook_index, int page); Source::View *get_view(size_t notebook_index, int page);

32
src/window.cc

@ -502,6 +502,38 @@ void Window::set_menu_actions() {
if(auto view=Notebook::get().get_current_view()) if(auto view=Notebook::get().get_current_view())
view->scroll_to_cursor_delayed(view, true, false); view->scroll_to_cursor_delayed(view, true, false);
}); });
menu.add_action("source_cursor_history_back", [this]() {
if(Notebook::get().cursor_locations.size()<=1)
return;
if(Notebook::get().current_cursor_location==static_cast<size_t>(-1))
Notebook::get().current_cursor_location=Notebook::get().cursor_locations.size()-1;
if(Notebook::get().current_cursor_location<1)
return;
--Notebook::get().current_cursor_location;
auto &cursor_location=Notebook::get().cursor_locations.at(Notebook::get().current_cursor_location);
if(Notebook::get().get_current_view()!=cursor_location.view)
Notebook::get().open(cursor_location.view->file_path);
Notebook::get().disable_next_update_cursor_locations=true;
cursor_location.view->get_buffer()->place_cursor(cursor_location.mark->get_iter());
cursor_location.view->scroll_to_cursor_delayed(cursor_location.view, true, false);
});
menu.add_action("source_cursor_history_forward", [this]() {
if(Notebook::get().cursor_locations.size()<=1)
return;
if(Notebook::get().current_cursor_location==static_cast<size_t>(-1))
Notebook::get().current_cursor_location=Notebook::get().cursor_locations.size()-1;
if(Notebook::get().current_cursor_location==Notebook::get().cursor_locations.size()-1)
return;
++Notebook::get().current_cursor_location;
auto &cursor_location=Notebook::get().cursor_locations.at(Notebook::get().current_cursor_location);
if(Notebook::get().get_current_view()!=cursor_location.view)
Notebook::get().open(cursor_location.view->file_path);
Notebook::get().disable_next_update_cursor_locations=true;
cursor_location.view->get_buffer()->place_cursor(cursor_location.mark->get_iter());
cursor_location.view->scroll_to_cursor_delayed(cursor_location.view, true, false);
});
menu.add_action("source_find_symbol_ctags", [this]() { menu.add_action("source_find_symbol_ctags", [this]() {
if(auto view=Notebook::get().get_current_view()) { if(auto view=Notebook::get().get_current_view()) {

Loading…
Cancel
Save