Changeset 59d556541d6603f37383223706bde8a4c5b11f47

Show
Ignore:
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:
4 modified

Legend:

Unmodified
Added
Removed
  • TODO

    ra70a4d0 r59d5565  
    55 * Opening large documents is _really_ slow on win32's timer implementation 
    66 * On connection loss: give a chance to save everything 
    7  * User colourising  
     7 * Gobby sometimes segfaults on exit 
    88 
    99Important: 
    1010 * Compensate changes made by others by scrolling appropriately; the current 
    1111   position should not change 
     12 * User colourising does not always repaint correctly 
    1213 
    1314Normal: 
  • inc/document.hpp

    r1545139 r59d5565  
    4646        obby::document& get_document(); 
    4747 
    48         // Statusbar information 
     48        /** Writes the current cursor position into row and col. 
     49         */ 
    4950        void get_cursor_position(unsigned int& row, unsigned int& col); 
     51 
     52        /** Returns the amount of unsynced operations in this document. 
     53         */ 
    5054        unsigned int get_unsynced_changes_count() const; 
     55 
     56        /** Returns the currently selected Gtk::SourceLanguage. 
     57         */ 
    5158#ifdef WITH_GTKSOURCEVIEW 
    5259        Glib::RefPtr<Gtk::SourceLanguage> get_language() const; 
     
    5865        signal_update_type update_event() const; 
    5966 
     67        /** Calls from the folder. 
     68         */ 
     69        void obby_user_join(obby::user& user); 
     70        void obby_user_part(obby::user& user); 
     71 
    6072protected: 
     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         */ 
    6180        void on_insert_before(const Gtk::TextBuffer::iterator& begin, 
    6281                              const Glib::ustring& text, 
     
    6584                             const Gtk::TextBuffer::iterator& end); 
    6685 
    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, 
    7187                             const Glib::ustring& text, 
    7288                             int bytes); 
     
    7490                            const Gtk::TextBuffer::iterator& end); 
    7591 
     92        /** Cursor position changed signal hanlder. 
     93         */ 
    7694        void on_cursor_changed(const Gtk::TextBuffer::iterator& location, 
    7795                               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); 
    78102 
    79103        obby::document& m_doc; 
     
    95119         
    96120        signal_update_type m_signal_update; 
     121private: 
     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 
    97129}; 
    98130 
  • src/document.cpp

    r1545139 r59d5565  
    1818 
    1919#include <obby/client_document.hpp> 
     20#include <obby/host_document.hpp> 
     21#include <obby/client_buffer.hpp> 
     22#include <obby/host_buffer.hpp> 
    2023#include "document.hpp" 
    2124#include "folder.hpp" 
    2225 
     26#include <iostream> 
    2327Gobby::Document::Document(obby::document& doc, const Folder& folder) 
    2428 : Gtk::ScrolledWindow(), m_doc(doc), m_folder(folder), m_editing(true) 
     
    5458        buf->set_highlight(true); 
    5559#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        } 
    5682 
    5783        // Textbuffer signal handlers 
     
    75101        // Set initial text 
    76102        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 
    77143        m_editing = false; 
    78144         
     
    113179        const Gtk::TextBuffer::iterator iter = mark->get_iter(); 
    114180 
    115         // Read line and column 
     181        // Read line and column from iterator 
    116182        row = iter.get_line(); 
    117183        col = iter.get_line_offset(); 
     
    136202} 
    137203#endif 
     204 
     205void 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 
     230void Gobby::Document::obby_user_part(obby::user& user) 
     231{ 
     232} 
    138233 
    139234void Gobby::Document::on_insert_before(const Gtk::TextBuffer::iterator& begin, 
     
    180275        m_editing = true; 
    181276 
     277        // Get textbuffer 
    182278        Glib::RefPtr<Gtk::TextBuffer> buffer = m_view.get_buffer(); 
    183279 
     280        // Translate position to row/column 
    184281        unsigned int row, col; 
    185282        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( 
    187290                buffer->get_iter_at_line_index(row, col), 
    188291                record.get_text() 
    189292        ); 
    190293 
     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(); 
    191300        m_editing = false; 
    192301} 
     
    210319} 
    211320 
    212 void Gobby::Document::on_insert_after(const Gtk::TextBuffer::iterator& begin, 
     321void Gobby::Document::on_insert_after(const Gtk::TextBuffer::iterator& end, 
    213322                                      const Glib::ustring& text, 
    214323                                      int bytes) 
    215324{ 
     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 
    216350        // Document changed: Update statusbar 
    217351        m_signal_update.emit(); 
     
    235369} 
    236370 
     371void 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 
     395void 
     396Gobby::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 
  • src/folder.cpp

    r1545139 r59d5565  
    6969void Gobby::Folder::obby_user_join(obby::user& user) 
    7070{ 
     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); 
    7174} 
    7275 
    7376void Gobby::Folder::obby_user_part(obby::user& user) 
    7477{ 
     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); 
    7581} 
    7682 
    7783void Gobby::Folder::obby_document_insert(obby::document& document) 
    7884{ 
     85        // Create new document 
    7986        Document* new_doc = new Document(document, *this); 
     87 
     88        // Watch update signal to emit document_updated signal if a document 
     89        // has been updated. 
    8090        new_doc->update_event().connect( 
    8191                sigc::bind( 
     
    8595        ); 
    8696 
     97        // Append document's title as new page to the notebook 
    8798        append_page(*new_doc, document.get_title()); 
     99 
     100        // Show child 
    88101        new_doc->show_all(); 
    89102} 
     
    91104void Gobby::Folder::obby_document_remove(obby::document& document) 
    92105{ 
     106        // Find corresponding Document widget in notebook 
    93107        for(int i = 0; i < get_n_pages(); ++ i) 
    94108        { 
     
    96110                if(&static_cast<Document*>(doc)->get_document() == &document) 
    97111                { 
     112                        // Delete it. 
    98113                        remove_page(i); 
    99114                        delete doc; 
     
    111126void Gobby::Folder::on_switch_page(GtkNotebookPage* page, guint page_num) 
    112127{ 
     128        // Another document has been selected: Update statusbar 
    113129        m_signal_document_update.emit( 
    114130                *static_cast<Document*>(get_nth_page(page_num)) 
    115131        ); 
     132 
    116133        Gtk::Notebook::on_switch_page(page, page_num); 
    117134} 
     
    119136void Gobby::Folder::on_document_update(Document& document) 
    120137{ 
     138        // Update in the currently visible document? Update statusbar. 
    121139        if(get_current_page() == page_num(document) ) 
    122140                m_signal_document_update.emit(document);