1 /* 2 * gnote 3 * 4 * Copyright (C) 2011-2017,2019 Aurimas Cernius 5 * Copyright (C) 2009 Hubert Figuiere 6 * 7 * This program is free software: you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation, either version 3 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 22 23 24 #ifndef __NOTE_BUFFER_HPP_ 25 #define __NOTE_BUFFER_HPP_ 26 27 #include <queue> 28 29 #include <gtkmm/textbuffer.h> 30 #include <gtkmm/textiter.h> 31 #include <gtkmm/texttag.h> 32 #include <gtkmm/widget.h> 33 34 #include "notetag.hpp" 35 36 namespace sharp { 37 class XmlReader; 38 class XmlWriter; 39 } 40 41 namespace gnote { 42 43 class Preferences; 44 class Note; 45 class UndoManager; 46 47 48 class NoteBuffer 49 : public Gtk::TextBuffer 50 { 51 public: 52 typedef Glib::RefPtr<NoteBuffer> Ptr; 53 typedef sigc::signal<void, int, int> NewBulletHandler; 54 typedef sigc::signal<void, int, bool> ChangeDepthHandler; 55 56 bool get_enable_auto_bulleted_lists() const; create(const NoteTagTable::Ptr & table,Note & note,Preferences & preferences)57 static Ptr create(const NoteTagTable::Ptr & table, Note & note, Preferences & preferences) 58 { 59 return Ptr(new NoteBuffer(table, note, preferences)); 60 } 61 ~NoteBuffer(); 62 note() const63 Note & note() const 64 { 65 return m_note; 66 } 67 68 // Signal that text has been inserted, and any active tags have 69 // been applied to the text. This allows undo to pull any 70 // active tags from the inserted text. 71 sigc::signal<void, const Gtk::TextIter &, const Glib::ustring &, int> signal_insert_text_with_tags; 72 ChangeDepthHandler signal_change_text_depth; 73 NewBulletHandler signal_new_bullet_inserted; 74 75 void toggle_active_tag(const Glib::ustring &); 76 void set_active_tag(const Glib::ustring &); 77 void remove_active_tag(const Glib::ustring &); 78 DynamicNoteTag::ConstPtr get_dynamic_tag(const Glib::ustring & tag_name, const Gtk::TextIter & iter); 79 void on_tag_applied(const Glib::RefPtr<Gtk::TextTag> &, 80 const Gtk::TextIter &,const Gtk::TextIter &); 81 bool is_active_tag(const Glib::ustring & ); 82 bool is_active_tag(const Glib::RefPtr<Gtk::TextTag> & tag); 83 bool is_bulleted_list_active(); 84 bool is_bulleted_list_active(Gtk::TextIter iter); 85 bool can_make_bulleted_list(); 86 bool add_tab(); 87 bool remove_tab(); 88 bool add_new_line(bool soft_break); 89 bool delete_key_handler(); 90 bool backspace_key_handler(); 91 void check_selection(); 92 bool run_widget_queue(); 93 void on_tag_changed(const Glib::RefPtr<Gtk::TextTag> &, bool); undoer()94 UndoManager & undoer() 95 { 96 return *m_undomanager; 97 } 98 Glib::ustring get_selection() const; 99 static void get_block_extents(Gtk::TextIter &, Gtk::TextIter &, 100 int threshold, const Glib::RefPtr<Gtk::TextTag> & avoid_tag); 101 void toggle_selection_bullets(); increase_cursor_depth()102 void increase_cursor_depth() 103 { 104 change_cursor_depth(true); 105 } decrease_cursor_depth()106 void decrease_cursor_depth() 107 { 108 change_cursor_depth(false); 109 } 110 void change_cursor_depth_directional(bool right); 111 void insert_bullet(Gtk::TextIter & iter, int depth); 112 void remove_bullet(Gtk::TextIter & iter); 113 void increase_depth(Gtk::TextIter & start); 114 void decrease_depth(Gtk::TextIter & start); 115 DepthNoteTag::Ptr find_depth_tag(Gtk::TextIter &); 116 static bool is_bullet(gunichar c); 117 void select_note_body(); 118 protected: 119 NoteBuffer(const NoteTagTable::Ptr &, Note &, Preferences &); 120 121 virtual void on_apply_tag(const Glib::RefPtr<Gtk::TextTag> & tag, 122 const Gtk::TextIter &, const Gtk::TextIter &) override; 123 virtual void on_remove_tag(const Glib::RefPtr<Gtk::TextTag> & tag, 124 const Gtk::TextIter &, const Gtk::TextIter &) override; 125 private: 126 void text_insert_event(const Gtk::TextIter & pos, const Glib::ustring & text, int); 127 bool line_needs_bullet(Gtk::TextIter iter); 128 void augment_selection(Gtk::TextIter &, Gtk::TextIter &); 129 void mark_set_event(const Gtk::TextIter &,const Glib::RefPtr<Gtk::TextBuffer::Mark> &); 130 void widget_swap (const NoteTag::Ptr & tag, const Gtk::TextIter & start, 131 const Gtk::TextIter & end_iter, bool adding); 132 void change_cursor_depth(bool increase); 133 typedef void (NoteBuffer::*DepthAction)(Gtk::TextIter & iter); 134 bool handle_tab(DepthAction depth_action); 135 136 UndoManager *m_undomanager; 137 static const gunichar s_indent_bullets[]; 138 139 // GODDAMN Gtk::TextBuffer. I hate you. Hate Hate Hate. 140 struct WidgetInsertData 141 { 142 bool adding; 143 Glib::RefPtr<Gtk::TextBuffer> buffer; 144 Glib::RefPtr<Gtk::TextMark> position; 145 Gtk::Widget *widget; 146 NoteTag::Ptr tag; 147 }; 148 std::queue<WidgetInsertData> m_widget_queue; 149 sigc::connection m_widget_queue_timeout; 150 // HATE. 151 152 // list of Glib::RefPtr<Gtk::TextTag>s to apply on insert 153 std::vector<Glib::RefPtr<Gtk::TextTag> > m_active_tags; 154 155 // The note that owns this buffer 156 Note & m_note; 157 Preferences & m_preferences; 158 }; 159 160 class NoteBufferArchiver 161 { 162 public: 163 static Glib::ustring serialize(const Glib::RefPtr<Gtk::TextBuffer> & ); 164 static Glib::ustring serialize(const Glib::RefPtr<Gtk::TextBuffer> & buffer, const Gtk::TextIter &, 165 const Gtk::TextIter &); 166 static void serialize(const Glib::RefPtr<Gtk::TextBuffer> & buffer, const Gtk::TextIter &, 167 const Gtk::TextIter &, sharp::XmlWriter & xml); deserialize(const Glib::RefPtr<Gtk::TextBuffer> & buffer,const Glib::ustring & content)168 static void deserialize(const Glib::RefPtr<Gtk::TextBuffer> &buffer, 169 const Glib::ustring & content) 170 { 171 deserialize(buffer, buffer->begin(), content); 172 } 173 static void deserialize(const Glib::RefPtr<Gtk::TextBuffer> &, const Gtk::TextIter & , 174 const Glib::ustring & ); 175 static void deserialize(const Glib::RefPtr<Gtk::TextBuffer> & buffer, 176 const Gtk::TextIter & iter, sharp::XmlReader & xml); 177 private: 178 179 static void write_tag(const Glib::RefPtr<const Gtk::TextTag> & tag, sharp::XmlWriter & xml, 180 bool start); 181 static bool tag_ends_here (const Glib::RefPtr<const Gtk::TextTag> & tag, 182 const Gtk::TextIter & iter, 183 const Gtk::TextIter & next_iter); 184 185 // 186 }; 187 188 189 } 190 191 #endif 192 193