Ticket #3358: smooth_scrolling_patch.diff

File smooth_scrolling_patch.diff, 5.7 KB (added by Geobert, 3 years ago)

smooth scrolling patch

  • src/conversation_textview.py

     
    1010## 
    1111## This program is distributed in the hope that it will be useful, 
    1212## but WITHOUT ANY WARRANTY; without even the implied warranty of 
    13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
     13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    1414## GNU General Public License for more details. 
    1515## 
    1616 
    1717import random 
    1818from tempfile import gettempdir 
    1919from subprocess import Popen 
     20from threading import Timer # for smooth scrolling 
    2021 
    2122import gtk 
    2223import pango 
     
    4445        path_to_file = os.path.join(gajim.DATA_DIR, 'pixmaps', 'muc_separator.png') 
    4546        FOCUS_OUT_LINE_PIXBUF = gtk.gdk.pixbuf_new_from_file(path_to_file) 
    4647 
     48        # smooth scroll constants 
     49        MAX_SCROLL_TIME = 0.4 # seconds 
     50        SCROLL_DELAY = 33 # milliseconds 
     51 
    4752        def __init__(self, account, used_in_history_window = False): 
    4853                '''if used_in_history_window is True, then we do not show 
    4954                Clear menuitem in context menu''' 
     
    154159                self.line_tooltip = tooltips.BaseTooltip() 
    155160                # use it for hr too 
    156161                self.tv.focus_out_line_pixbuf = ConversationTextview.FOCUS_OUT_LINE_PIXBUF 
     162                self.smooth_id = None 
    157163 
    158164        def del_handlers(self): 
    159165                for i in self.handlers.keys(): 
     
    181187                        return True 
    182188                return False 
    183189 
     190        # Smooth scrolling inspired by Pidgin code 
     191        def smooth_scroll(self): 
     192                parent = self.tv.get_parent() 
     193                if not parent: 
     194                        return False 
     195                vadj = parent.get_vadjustment() 
     196                max_val = vadj.upper - vadj.page_size + 1 
     197                cur_val = vadj.get_value() 
     198                # scroll by 1/3rd of remaining distance 
     199                onethird = cur_val + ((max_val - cur_val) / 3.0) 
     200                vadj.set_value(onethird) 
     201                if max_val - onethird < 0.01: 
     202                        print "sroll finished" 
     203                        self.smooth_id = None 
     204                        self.smooth_scroll_timer.cancel() 
     205                        return False 
     206                return True                 
     207 
     208        def smooth_scroll_timeout(self): 
     209                print "-->smooth_scroll_timeout" 
     210                gobject.source_remove(self.smooth_id) 
     211                self.smooth_id = None 
     212                parent = self.tv.get_parent() 
     213                if parent: 
     214                        vadj = parent.get_vadjustment() 
     215                        vadj.set_value(vadj.upper - vadj.page_size + 1) 
     216 
     217        def smooth_scroll_to_end(self): 
     218                if None != self.smooth_id: # already scrolling 
     219                        return False 
     220                print "-->add timeout" 
     221                self.smooth_id = gobject.timeout_add(self.SCROLL_DELAY, 
     222                                                                                         self.smooth_scroll) 
     223                self.smooth_scroll_timer = Timer(self.MAX_SCROLL_TIME, 
     224                                                                                 self.smooth_scroll_timeout) 
     225                self.smooth_scroll_timer.start() 
     226                return False 
     227 
    184228        def scroll_to_end(self): 
    185229                parent = self.tv.get_parent() 
    186230                buffer = self.tv.get_buffer() 
     
    192236                adjustment.set_value(0) 
    193237                return False # when called in an idle_add, just do it once 
    194238 
    195         def bring_scroll_to_end(self, diff_y = 0): 
     239        def bring_scroll_to_end(self, diff_y = 0,\ 
     240                                                        use_smooth =\ 
     241                                                        gajim.config.get('use_smooth_scrolling')): 
    196242                ''' scrolls to the end of textview if end is not visible ''' 
    197243                buffer = self.tv.get_buffer() 
    198244                end_iter = buffer.get_end_iter() 
     
    200246                visible_rect = self.tv.get_visible_rect() 
    201247                # scroll only if expected end is not visible 
    202248                if end_rect.y >= (visible_rect.y + visible_rect.height + diff_y): 
    203                         gobject.idle_add(self.scroll_to_end_iter) 
     249                        if use_smooth: 
     250                                gobject.idle_add(self.smooth_scroll_to_end) 
     251                        else: 
     252                                gobject.idle_add(self.scroll_to_end_iter) 
    204253 
    205254        def scroll_to_end_iter(self): 
    206255                buffer = self.tv.get_buffer() 
     
    857906                if at_the_end or kind == 'outgoing': 
    858907                        # we are at the end or we are sending something 
    859908                        # scroll to the end (via idle in case the scrollbar has appeared) 
    860                         gobject.idle_add(self.scroll_to_end) 
     909                        if gajim.config.get('use_smooth_scrolling'): 
     910                                gobject.idle_add(self.smooth_scroll_to_end) 
     911                        else: 
     912                                gobject.idle_add(self.scroll_to_end) 
    861913 
    862914                buffer.end_user_action() 
    863915 
  • src/common/config.py

     
    218218                'hide_groupchat_occupants_list': [opt_bool, False, _('Hides the group chat occupants list in group chat window.')], 
    219219                'chat_merge_consecutive_nickname': [opt_bool, False, _('In a chat, show the nickname at the beginning of a line only when it\'s not the same person talking than in previous message.')], 
    220220                'chat_merge_consecutive_nickname_indent': [opt_str, '  ', _('Indentation when using merge consecutive nickname.')], 
     221        'use_smooth_scrolling': [opt_bool, True, _('Smooth scroll message in conversation window')], 
    221222                'gc_nicknames_colors': [ opt_str, '#a34526:#c000ff:#0012ff:#388a99:#045723:#7c7c7c:#ff8a00:#94452d:#244b5a:#32645a', _('List of colors that will be used to color nicknames in group chats.'), True ], 
    222223                'ctrl_tab_go_to_next_composing': [opt_bool, True, _('Ctrl-Tab go to next composing tab when none is unread.')], 
    223224                'confirm_metacontacts': [ opt_str, '', _('Should we show the confirm metacontacts creation dialog or not? Empty string means we never show the dialog.')], 
  • src/chat_control.py

     
    812812                                self.msg_scrolledwindow.set_property('vscrollbar-policy',  
    813813                                        gtk.POLICY_NEVER) 
    814814                                self.msg_scrolledwindow.set_property('height-request', -1) 
    815  
    816                 self.conv_textview.bring_scroll_to_end(diff_y - 18) 
     815                        # put inside "if diff_y != 0"" or it is called at each keystroke 
     816                        self.conv_textview.bring_scroll_to_end(diff_y - 18) 
    817817                 
    818818                # enable scrollbar automatic policy for horizontal scrollbar 
    819819                # if message we have in message_textview is too big