Changeset 59d556541d6603f37383223706bde8a4c5b11f47
- Timestamp:
- 01/06/07 23:33:53 (6 years ago)
- Author:
- Philipp Kern <phil@…>
- Parents:
- a70a4d03e72646528ab3a70b148d14e6fe390d4d
- Children:
- 33a22c5cf1a312bedace4f3e4dec3117cfceb221
- git-committer:
- Philipp Kern <phil@0x539.de> / 2007-01-06T22:33:53Z+0000
- Message:
-
[project @ User colourising]
Original author: Armin Burgmeier <armin@…>
Date: 2005-05-07 19:07:20+00:00
- Files:
-
Legend:
- Unmodified
- Added
- Removed
-
|
ra70a4d0
|
r59d5565
|
|
| 5 | 5 | * Opening large documents is _really_ slow on win32's timer implementation |
| 6 | 6 | * On connection loss: give a chance to save everything |
| 7 | | * User colourising |
| | 7 | * Gobby sometimes segfaults on exit |
| 8 | 8 | |
| 9 | 9 | Important: |
| 10 | 10 | * Compensate changes made by others by scrolling appropriately; the current |
| 11 | 11 | position should not change |
| | 12 | * User colourising does not always repaint correctly |
| 12 | 13 | |
| 13 | 14 | Normal: |
-
|
r1545139
|
r59d5565
|
|
| 46 | 46 | obby::document& get_document(); |
| 47 | 47 | |
| 48 | | // Statusbar information |
| | 48 | /** Writes the current cursor position into row and col. |
| | 49 | */ |
| 49 | 50 | void get_cursor_position(unsigned int& row, unsigned int& col); |
| | 51 | |
| | 52 | /** Returns the amount of unsynced operations in this document. |
| | 53 | */ |
| 50 | 54 | unsigned int get_unsynced_changes_count() const; |
| | 55 | |
| | 56 | /** Returns the currently selected Gtk::SourceLanguage. |
| | 57 | */ |
| 51 | 58 | #ifdef WITH_GTKSOURCEVIEW |
| 52 | 59 | Glib::RefPtr<Gtk::SourceLanguage> get_language() const; |
| … |
… |
|
| 58 | 65 | signal_update_type update_event() const; |
| 59 | 66 | |
| | 67 | /** Calls from the folder. |
| | 68 | */ |
| | 69 | void obby_user_join(obby::user& user); |
| | 70 | void obby_user_part(obby::user& user); |
| | 71 | |
| 60 | 72 | protected: |
| | 73 | /** Obby signal handlers. |
| | 74 | */ |
| | 75 | void on_obby_insert(const obby::insert_record& record); |
| | 76 | void on_obby_delete(const obby::delete_record& record); |
| | 77 | |
| | 78 | /** TextBuffer signal handlers. |
| | 79 | */ |
| 61 | 80 | void on_insert_before(const Gtk::TextBuffer::iterator& begin, |
| 62 | 81 | const Glib::ustring& text, |
| … |
… |
|
| 65 | 84 | const Gtk::TextBuffer::iterator& end); |
| 66 | 85 | |
| 67 | | void on_obby_insert(const obby::insert_record& record); |
| 68 | | void on_obby_delete(const obby::delete_record& record); |
| 69 | | |
| 70 | | void on_insert_after(const Gtk::TextBuffer::iterator& begin, |
| | 86 | void on_insert_after(const Gtk::TextBuffer::iterator& end, |
| 71 | 87 | const Glib::ustring& text, |
| 72 | 88 | int bytes); |
| … |
… |
|
| 74 | 90 | const Gtk::TextBuffer::iterator& end); |
| 75 | 91 | |
| | 92 | /** Cursor position changed signal hanlder. |
| | 93 | */ |
| 76 | 94 | void on_cursor_changed(const Gtk::TextBuffer::iterator& location, |
| 77 | 95 | const Glib::RefPtr<Gtk::TextBuffer::Mark>& mark); |
| | 96 | |
| | 97 | /** Marks the given part of the text as written by <em>user</em>. |
| | 98 | */ |
| | 99 | void update_user_colour(const Gtk::TextBuffer::iterator& begin, |
| | 100 | const Gtk::TextBuffer::iterator& end, |
| | 101 | const obby::user& user); |
| 78 | 102 | |
| 79 | 103 | obby::document& m_doc; |
| … |
… |
|
| 95 | 119 | |
| 96 | 120 | signal_update_type m_signal_update; |
| | 121 | private: |
| | 122 | /** Handler for update_user_colour(): It removes the given tag in |
| | 123 | * the given range if it is a gobby-user-tag. |
| | 124 | */ |
| | 125 | void on_remove_user_colour(Glib::RefPtr<Gtk::TextBuffer::Tag> tag, |
| | 126 | const Gtk::TextBuffer::iterator& begin, |
| | 127 | const Gtk::TextBuffer::iterator& end); |
| | 128 | |
| 97 | 129 | }; |
| 98 | 130 | |
-
|
r1545139
|
r59d5565
|
|
| 18 | 18 | |
| 19 | 19 | #include <obby/client_document.hpp> |
| | 20 | #include <obby/host_document.hpp> |
| | 21 | #include <obby/client_buffer.hpp> |
| | 22 | #include <obby/host_buffer.hpp> |
| 20 | 23 | #include "document.hpp" |
| 21 | 24 | #include "folder.hpp" |
| 22 | 25 | |
| | 26 | #include <iostream> |
| 23 | 27 | Gobby::Document::Document(obby::document& doc, const Folder& folder) |
| 24 | 28 | : Gtk::ScrolledWindow(), m_doc(doc), m_folder(folder), m_editing(true) |
| … |
… |
|
| 54 | 58 | buf->set_highlight(true); |
| 55 | 59 | #endif |
| | 60 | |
| | 61 | // Insert users from user table to insert users that have already |
| | 62 | // left the obby session. |
| | 63 | const obby::buffer& obbybuf = doc.get_buffer(); |
| | 64 | const obby::user_table& user_table = doc.get_buffer().get_user_table(); |
| | 65 | for(obby::user_table::user_iterator iter = user_table.user_begin(); |
| | 66 | iter != user_table.user_end(); |
| | 67 | ++ iter) |
| | 68 | { |
| | 69 | // Create new tag |
| | 70 | Glib::RefPtr<Gtk::TextBuffer::Tag> tag = |
| | 71 | buf->create_tag("gobby_user_" + iter->get_name() ); |
| | 72 | |
| | 73 | // Build user color |
| | 74 | Gdk::Color color; |
| | 75 | color.set_red(iter->get_red() * 65535 / 255); |
| | 76 | color.set_green(iter->get_green() * 65535 / 255); |
| | 77 | color.set_blue(iter->get_blue() * 65535 / 255); |
| | 78 | |
| | 79 | // Assign color to tag |
| | 80 | tag->property_background_gdk() = color; |
| | 81 | } |
| 56 | 82 | |
| 57 | 83 | // Textbuffer signal handlers |
| … |
… |
|
| 75 | 101 | // Set initial text |
| 76 | 102 | buf->set_text(doc.get_whole_buffer() ); |
| | 103 | |
| | 104 | // Set initial authors |
| | 105 | for(unsigned int i = 0; i < doc.get_line_count(); ++ i) |
| | 106 | { |
| | 107 | // Get current line |
| | 108 | const obby::line& line = doc.get_line(i); |
| | 109 | obby::line::author_iterator prev = line.author_begin(); |
| | 110 | obby::line::author_iterator cur = prev; |
| | 111 | |
| | 112 | // Iterate through it's authors list |
| | 113 | for(++ cur; prev != line.author_end(); ++ cur) |
| | 114 | { |
| | 115 | // Get current user |
| | 116 | const obby::user_table::user* user = prev->author; |
| | 117 | // user should never be NULL... |
| | 118 | if(user == NULL) continue; |
| | 119 | |
| | 120 | // Get the range to highlight |
| | 121 | obby::line::size_type endpos; |
| | 122 | if(cur != line.author_end() ) |
| | 123 | endpos = cur->position; |
| | 124 | else |
| | 125 | endpos = line.length(); |
| | 126 | |
| | 127 | Gtk::TextBuffer::iterator begin = |
| | 128 | buf->get_iter_at_line_index(i, prev->position); |
| | 129 | Gtk::TextBuffer::iterator end = |
| | 130 | buf->get_iter_at_line_index(i, endpos); |
| | 131 | |
| | 132 | // Apply corresponding tag |
| | 133 | buf->apply_tag_by_name( |
| | 134 | "gobby_user_" + user->get_name(), |
| | 135 | begin, |
| | 136 | end |
| | 137 | ); |
| | 138 | |
| | 139 | prev = cur; |
| | 140 | } |
| | 141 | } |
| | 142 | |
| 77 | 143 | m_editing = false; |
| 78 | 144 | |
| … |
… |
|
| 113 | 179 | const Gtk::TextBuffer::iterator iter = mark->get_iter(); |
| 114 | 180 | |
| 115 | | // Read line and column |
| | 181 | // Read line and column from iterator |
| 116 | 182 | row = iter.get_line(); |
| 117 | 183 | col = iter.get_line_offset(); |
| … |
… |
|
| 136 | 202 | } |
| 137 | 203 | #endif |
| | 204 | |
| | 205 | void Gobby::Document::obby_user_join(obby::user& user) |
| | 206 | { |
| | 207 | // Build tag name for this user |
| | 208 | Glib::ustring tag_name = "gobby_user_" + user.get_name(); |
| | 209 | |
| | 210 | // Find already existing tag |
| | 211 | Glib::RefPtr<Gtk::TextBuffer> buffer = m_view.get_buffer(); |
| | 212 | Glib::RefPtr<Gtk::TextBuffer::TagTable> tag_table = |
| | 213 | buffer->get_tag_table(); |
| | 214 | Glib::RefPtr<Gtk::TextBuffer::Tag> tag = tag_table->lookup(tag_name); |
| | 215 | |
| | 216 | // Create new tag, if it doesn't exist |
| | 217 | if(!tag) |
| | 218 | tag = buffer->create_tag(tag_name); |
| | 219 | |
| | 220 | // Build color |
| | 221 | Gdk::Color color; |
| | 222 | color.set_red(user.get_red() * 65535 / 255); |
| | 223 | color.set_green(user.get_green() * 65535 / 255); |
| | 224 | color.set_blue(user.get_blue() * 65535 / 255); |
| | 225 | |
| | 226 | // Set/Update color |
| | 227 | tag->property_background_gdk() = color; |
| | 228 | } |
| | 229 | |
| | 230 | void Gobby::Document::obby_user_part(obby::user& user) |
| | 231 | { |
| | 232 | } |
| 138 | 233 | |
| 139 | 234 | void Gobby::Document::on_insert_before(const Gtk::TextBuffer::iterator& begin, |
| … |
… |
|
| 180 | 275 | m_editing = true; |
| 181 | 276 | |
| | 277 | // Get textbuffer |
| 182 | 278 | Glib::RefPtr<Gtk::TextBuffer> buffer = m_view.get_buffer(); |
| 183 | 279 | |
| | 280 | // Translate position to row/column |
| 184 | 281 | unsigned int row, col; |
| 185 | 282 | m_doc.position_to_coord(record.get_position(), row, col); |
| 186 | | buffer->insert( |
| | 283 | |
| | 284 | // Find obby::user that inserted the text |
| | 285 | obby::user* user = m_doc.get_buffer().find_user(record.get_from() ); |
| | 286 | assert(user != NULL); |
| | 287 | |
| | 288 | // Insert text |
| | 289 | Gtk::TextBuffer::iterator end = buffer->insert( |
| 187 | 290 | buffer->get_iter_at_line_index(row, col), |
| 188 | 291 | record.get_text() |
| 189 | 292 | ); |
| 190 | 293 | |
| | 294 | // Colourize new text |
| | 295 | Gtk::TextBuffer::iterator begin = end; |
| | 296 | begin.backward_chars(record.get_text().length() ); |
| | 297 | update_user_colour(begin, end, *user); |
| | 298 | |
| | 299 | m_view.queue_draw(); |
| 191 | 300 | m_editing = false; |
| 192 | 301 | } |
| … |
… |
|
| 210 | 319 | } |
| 211 | 320 | |
| 212 | | void Gobby::Document::on_insert_after(const Gtk::TextBuffer::iterator& begin, |
| | 321 | void Gobby::Document::on_insert_after(const Gtk::TextBuffer::iterator& end, |
| 213 | 322 | const Glib::ustring& text, |
| 214 | 323 | int bytes) |
| 215 | 324 | { |
| | 325 | // Other editing function is at work. |
| | 326 | if(!m_editing) |
| | 327 | { |
| | 328 | // TODO: Find a better solution to access the local user object. |
| | 329 | obby::client_document* client_doc = |
| | 330 | dynamic_cast<obby::client_document*>(&m_doc); |
| | 331 | obby::host_document* host_doc = |
| | 332 | dynamic_cast<obby::host_document*>(&m_doc); |
| | 333 | |
| | 334 | const obby::user* user = NULL; |
| | 335 | if(client_doc != NULL) |
| | 336 | user = &client_doc->get_buffer().get_self(); |
| | 337 | if(host_doc != NULL) |
| | 338 | user = &host_doc->get_buffer().get_self(); |
| | 339 | |
| | 340 | assert(user != NULL); |
| | 341 | |
| | 342 | // Find start position of new text |
| | 343 | Gtk::TextBuffer::iterator pos = end; |
| | 344 | pos.backward_chars(text.length() ); |
| | 345 | |
| | 346 | // Update colour |
| | 347 | update_user_colour(pos, end, *user); |
| | 348 | } |
| | 349 | |
| 216 | 350 | // Document changed: Update statusbar |
| 217 | 351 | m_signal_update.emit(); |
| … |
… |
|
| 235 | 369 | } |
| 236 | 370 | |
| | 371 | void Gobby::Document::update_user_colour(const Gtk::TextBuffer::iterator& begin, |
| | 372 | const Gtk::TextBuffer::iterator& end, |
| | 373 | const obby::user& user) |
| | 374 | { |
| | 375 | // Remove other user tags in that range |
| | 376 | Glib::RefPtr<Gtk::TextBuffer> buffer = m_view.get_buffer(); |
| | 377 | Glib::RefPtr<Gtk::TextBuffer::TagTable> tag_table = |
| | 378 | buffer->get_tag_table(); |
| | 379 | |
| | 380 | tag_table->foreach( |
| | 381 | sigc::bind( |
| | 382 | sigc::mem_fun( |
| | 383 | *this, |
| | 384 | &Document::on_remove_user_colour |
| | 385 | ), |
| | 386 | sigc::ref(begin), |
| | 387 | sigc::ref(end) |
| | 388 | ) |
| | 389 | ); |
| | 390 | |
| | 391 | // Insert new user tag to the given range |
| | 392 | buffer->apply_tag_by_name("gobby_user_" + user.get_name(), begin, end); |
| | 393 | } |
| | 394 | |
| | 395 | void |
| | 396 | Gobby::Document::on_remove_user_colour(Glib::RefPtr<Gtk::TextBuffer::Tag> tag, |
| | 397 | const Gtk::TextBuffer::iterator& begin, |
| | 398 | const Gtk::TextBuffer::iterator& end) |
| | 399 | { |
| | 400 | // Remove tag if it is a user color tag. |
| | 401 | Glib::ustring tag_name = tag->property_name(); |
| | 402 | if(tag_name.compare(0, 10, "gobby_user") == 0) |
| | 403 | m_view.get_buffer()->remove_tag(tag, begin, end); |
| | 404 | } |
| | 405 | |
-
|
r1545139
|
r59d5565
|
|
| 69 | 69 | void Gobby::Folder::obby_user_join(obby::user& user) |
| 70 | 70 | { |
| | 71 | // Pass user join event to documents |
| | 72 | for(unsigned int i = 0; i < get_n_pages(); ++ i) |
| | 73 | static_cast<Document*>(get_nth_page(i) )->obby_user_join(user); |
| 71 | 74 | } |
| 72 | 75 | |
| 73 | 76 | void Gobby::Folder::obby_user_part(obby::user& user) |
| 74 | 77 | { |
| | 78 | // Pass user part event to documents |
| | 79 | for(unsigned int i = 0; i < get_n_pages(); ++ i) |
| | 80 | static_cast<Document*>(get_nth_page(i) )->obby_user_part(user); |
| 75 | 81 | } |
| 76 | 82 | |
| 77 | 83 | void Gobby::Folder::obby_document_insert(obby::document& document) |
| 78 | 84 | { |
| | 85 | // Create new document |
| 79 | 86 | Document* new_doc = new Document(document, *this); |
| | 87 | |
| | 88 | // Watch update signal to emit document_updated signal if a document |
| | 89 | // has been updated. |
| 80 | 90 | new_doc->update_event().connect( |
| 81 | 91 | sigc::bind( |
| … |
… |
|
| 85 | 95 | ); |
| 86 | 96 | |
| | 97 | // Append document's title as new page to the notebook |
| 87 | 98 | append_page(*new_doc, document.get_title()); |
| | 99 | |
| | 100 | // Show child |
| 88 | 101 | new_doc->show_all(); |
| 89 | 102 | } |
| … |
… |
|
| 91 | 104 | void Gobby::Folder::obby_document_remove(obby::document& document) |
| 92 | 105 | { |
| | 106 | // Find corresponding Document widget in notebook |
| 93 | 107 | for(int i = 0; i < get_n_pages(); ++ i) |
| 94 | 108 | { |
| … |
… |
|
| 96 | 110 | if(&static_cast<Document*>(doc)->get_document() == &document) |
| 97 | 111 | { |
| | 112 | // Delete it. |
| 98 | 113 | remove_page(i); |
| 99 | 114 | delete doc; |
| … |
… |
|
| 111 | 126 | void Gobby::Folder::on_switch_page(GtkNotebookPage* page, guint page_num) |
| 112 | 127 | { |
| | 128 | // Another document has been selected: Update statusbar |
| 113 | 129 | m_signal_document_update.emit( |
| 114 | 130 | *static_cast<Document*>(get_nth_page(page_num)) |
| 115 | 131 | ); |
| | 132 | |
| 116 | 133 | Gtk::Notebook::on_switch_page(page, page_num); |
| 117 | 134 | } |
| … |
… |
|
| 119 | 136 | void Gobby::Folder::on_document_update(Document& document) |
| 120 | 137 | { |
| | 138 | // Update in the currently visible document? Update statusbar. |
| 121 | 139 | if(get_current_page() == page_num(document) ) |
| 122 | 140 | m_signal_document_update.emit(document); |