Merge branch 'scrolling' into 'master'
Improve Scrolling See merge request !65
This commit is contained in:
commit
55561b3dd0
|
@ -39,6 +39,7 @@ import gui_menu_builder
|
|||
import message_control
|
||||
import dialogs
|
||||
|
||||
from common import logger
|
||||
from common import gajim
|
||||
from common import helpers
|
||||
from common import exceptions
|
||||
|
@ -1626,10 +1627,9 @@ class ChatControl(ChatControlBase):
|
|||
rows = gajim.logger.get_last_conversation_lines(jid, restore_how_many,
|
||||
pending_how_many, timeout, self.account)
|
||||
except exceptions.DatabaseMalformed:
|
||||
import common.logger
|
||||
dialogs.ErrorDialog(_('Database Error'),
|
||||
_('The database file (%s) cannot be read. Try to repair it or '
|
||||
'remove it (all history will be lost).') % common.logger.LOG_DB_PATH)
|
||||
'remove it (all history will be lost).') % logger.LOG_DB_PATH)
|
||||
rows = []
|
||||
local_old_kind = None
|
||||
self.conv_textview.just_cleared = True
|
||||
|
|
|
@ -323,7 +323,6 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
id_ = widget.connect('changed',
|
||||
self.on_conversation_vadjustment_changed)
|
||||
self.handlers[id_] = widget
|
||||
self.scroll_to_end_id = None
|
||||
self.was_at_the_end = True
|
||||
self.correcting = False
|
||||
self.last_sent_msg = None
|
||||
|
@ -984,27 +983,8 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
# There were events to remove
|
||||
self.redraw_after_event_removed(jid)
|
||||
|
||||
def bring_scroll_to_end(self, textview, diff_y=0):
|
||||
"""
|
||||
Scroll to the end of textview if end is not visible
|
||||
"""
|
||||
if self.scroll_to_end_id:
|
||||
# a scroll is already planned
|
||||
return
|
||||
buffer_ = textview.get_buffer()
|
||||
end_iter = buffer_.get_end_iter()
|
||||
end_rect = textview.get_iter_location(end_iter)
|
||||
visible_rect = textview.get_visible_rect()
|
||||
# scroll only if expected end is not visible
|
||||
if end_rect.y >= (visible_rect.y + visible_rect.height + diff_y):
|
||||
self.scroll_to_end_id = GLib.idle_add(self.scroll_to_end_iter,
|
||||
textview)
|
||||
|
||||
def scroll_to_end_iter(self, textview):
|
||||
buffer_ = textview.get_buffer()
|
||||
end_iter = buffer_.get_end_iter()
|
||||
textview.scroll_to_iter(end_iter, 0, False, 1, 1)
|
||||
self.scroll_to_end_id = None
|
||||
def scroll_to_end_iter(self):
|
||||
self.conv_textview.scroll_to_end_iter()
|
||||
return False
|
||||
|
||||
def on_configure_event(self, msg_textview, event):
|
||||
|
@ -1065,18 +1045,11 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools):
|
|||
# used to stay at the end of the textview when we shrink conversation
|
||||
# textview.
|
||||
if self.was_at_the_end:
|
||||
if self.conv_textview.at_the_end():
|
||||
# we are at the end
|
||||
self.conv_textview.bring_scroll_to_end(-18)
|
||||
else:
|
||||
self.conv_textview.bring_scroll_to_end(-18, use_smooth=False)
|
||||
self.scroll_to_end_iter()
|
||||
self.was_at_the_end = (adjustment.get_upper() - adjustment.get_value()\
|
||||
- adjustment.get_page_size()) < 18
|
||||
|
||||
def on_conversation_vadjustment_value_changed(self, adjustment):
|
||||
# stop automatic scroll when we manually scroll
|
||||
if not self.conv_textview.auto_scrolling:
|
||||
self.conv_textview.stop_scrolling()
|
||||
self.was_at_the_end = (adjustment.get_upper() - adjustment.get_value() \
|
||||
- adjustment.get_page_size()) < 18
|
||||
if self.resource:
|
||||
|
|
|
@ -279,7 +279,6 @@ class Config:
|
|||
'hide_groupchat_occupants_list': [opt_bool, False, _('Hides the group chat occupants list in group chat window.')],
|
||||
'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.')],
|
||||
'chat_merge_consecutive_nickname_indent': [opt_str, ' ', _('Indentation when using merge consecutive nickname.')],
|
||||
'use_smooth_scrolling': [opt_bool, True, _('Smooth scroll message in conversation window')],
|
||||
'gc_nicknames_colors': [ opt_str, '#4e9a06:#f57900:#ce5c00:#3465a4:#204a87:#75507b:#5c3566:#c17d11:#8f5902:#ef2929:#cc0000:#a40000', _('List of colors, separated by ":", that will be used to color nicknames in group chats.'), True ],
|
||||
'ctrl_tab_go_to_next_composing': [opt_bool, True, _('Ctrl-Tab go to next composing tab when none is unread.')],
|
||||
'confirm_metacontacts': [ opt_str, '', _('Should we show the confirm metacontacts creation dialog or not? Empty string means we never show the dialog.')],
|
||||
|
|
|
@ -216,9 +216,6 @@ class ConversationTextview(GObject.GObject):
|
|||
# last_received_message_id[name] = (msg_stanza_id, line_start_mark)
|
||||
self.last_received_message_id = {}
|
||||
|
||||
# It's True when we scroll in the code, so we can detect scroll from user
|
||||
self.auto_scrolling = False
|
||||
|
||||
# connect signals
|
||||
id_ = self.tv.connect('populate_popup', self.on_textview_populate_popup)
|
||||
self.handlers[id_] = self.tv
|
||||
|
@ -325,7 +322,6 @@ class ConversationTextview(GObject.GObject):
|
|||
# holds a mark at the end of --- line
|
||||
self.focus_out_end_mark = None
|
||||
|
||||
self.smooth_id = None
|
||||
self.just_cleared = False
|
||||
|
||||
def query_tooltip(self, widget, x_pos, y_pos, keyboard_mode, tooltip):
|
||||
|
@ -398,87 +394,7 @@ class ConversationTextview(GObject.GObject):
|
|||
self.tv.tagSthAtSth.set_property('foreground', color)
|
||||
|
||||
def at_the_end(self):
|
||||
buffer_ = self.tv.get_buffer()
|
||||
end_iter = buffer_.get_end_iter()
|
||||
end_rect = self.tv.get_iter_location(end_iter)
|
||||
visible_rect = self.tv.get_visible_rect()
|
||||
if end_rect.y <= (visible_rect.y + visible_rect.height):
|
||||
return True
|
||||
return False
|
||||
|
||||
# Smooth scrolling inspired by Pidgin code
|
||||
def smooth_scroll(self):
|
||||
parent = self.tv.get_parent()
|
||||
if not parent:
|
||||
return False
|
||||
vadj = parent.get_vadjustment()
|
||||
max_val = vadj.get_upper() - vadj.get_page_size() + 1
|
||||
cur_val = vadj.get_value()
|
||||
# scroll by 1/3rd of remaining distance
|
||||
onethird = cur_val + ((max_val - cur_val) / 3.0)
|
||||
self.auto_scrolling = True
|
||||
vadj.set_value(onethird)
|
||||
self.auto_scrolling = False
|
||||
if max_val - onethird < 0.01:
|
||||
self.smooth_id = None
|
||||
self.smooth_scroll_timer.cancel()
|
||||
return False
|
||||
return True
|
||||
|
||||
def smooth_scroll_timeout(self):
|
||||
GLib.idle_add(self.do_smooth_scroll_timeout)
|
||||
return
|
||||
|
||||
def do_smooth_scroll_timeout(self):
|
||||
if not self.smooth_id:
|
||||
# we finished scrolling
|
||||
return
|
||||
GLib.source_remove(self.smooth_id)
|
||||
self.smooth_id = None
|
||||
parent = self.tv.get_parent()
|
||||
if parent:
|
||||
vadj = parent.get_vadjustment()
|
||||
self.auto_scrolling = True
|
||||
vadj.set_value(vadj.get_upper() - vadj.get_page_size() + 1)
|
||||
self.auto_scrolling = False
|
||||
|
||||
def smooth_scroll_to_end(self):
|
||||
if self.smooth_id is not None: # already scrolling
|
||||
return False
|
||||
self.smooth_id = GLib.timeout_add(self.SCROLL_DELAY,
|
||||
self.smooth_scroll)
|
||||
self.smooth_scroll_timer = Timer(self.MAX_SCROLL_TIME,
|
||||
self.smooth_scroll_timeout)
|
||||
self.smooth_scroll_timer.start()
|
||||
return False
|
||||
|
||||
def scroll_to_end(self):
|
||||
parent = self.tv.get_parent()
|
||||
buffer_ = self.tv.get_buffer()
|
||||
end_mark = buffer_.get_mark('end')
|
||||
if not end_mark:
|
||||
return False
|
||||
self.auto_scrolling = True
|
||||
self.tv.scroll_to_mark(end_mark, 0, True, 0, 1)
|
||||
adjustment = parent.get_hadjustment()
|
||||
adjustment.set_value(0)
|
||||
self.auto_scrolling = False
|
||||
return False # when called in an idle_add, just do it once
|
||||
|
||||
def bring_scroll_to_end(self, diff_y=0, use_smooth=None):
|
||||
''' scrolls to the end of textview if end is not visible '''
|
||||
if use_smooth is None:
|
||||
use_smooth = gajim.config.get('use_smooth_scrolling')
|
||||
buffer_ = self.tv.get_buffer()
|
||||
end_iter = buffer_.get_end_iter()
|
||||
end_rect = self.tv.get_iter_location(end_iter)
|
||||
visible_rect = self.tv.get_visible_rect()
|
||||
# scroll only if expected end is not visible
|
||||
if end_rect.y >= (visible_rect.y + visible_rect.height + diff_y):
|
||||
if use_smooth:
|
||||
GLib.idle_add(self.smooth_scroll_to_end)
|
||||
else:
|
||||
GLib.idle_add(self.scroll_to_end_iter)
|
||||
return gtkgui_helpers.at_the_end(self.tv.get_parent())
|
||||
|
||||
def scroll_to_end_iter(self):
|
||||
buffer_ = self.tv.get_buffer()
|
||||
|
@ -488,12 +404,6 @@ class ConversationTextview(GObject.GObject):
|
|||
self.tv.scroll_to_iter(end_iter, 0, False, 1, 1)
|
||||
return False # when called in an idle_add, just do it once
|
||||
|
||||
def stop_scrolling(self):
|
||||
if self.smooth_id:
|
||||
GLib.source_remove(self.smooth_id)
|
||||
self.smooth_id = None
|
||||
self.smooth_scroll_timer.cancel()
|
||||
|
||||
def correct_message(self, correct_id, kind, name):
|
||||
allowed = True
|
||||
if kind == 'incoming':
|
||||
|
@ -649,7 +559,7 @@ class ConversationTextview(GObject.GObject):
|
|||
if scroll:
|
||||
# scroll to the end (via idle in case the scrollbar has
|
||||
# appeared)
|
||||
GLib.idle_add(self.scroll_to_end)
|
||||
GLib.idle_add(self.scroll_to_end_iter)
|
||||
|
||||
def on_textview_draw(self, widget, ctx):
|
||||
return
|
||||
|
@ -1283,8 +1193,6 @@ class ConversationTextview(GObject.GObject):
|
|||
# even if we insert directly at the mark iter
|
||||
temp_mark = buffer_.create_mark('temp', iter_, left_gravity=True)
|
||||
|
||||
at_the_end = self.at_the_end()
|
||||
|
||||
if text.startswith('/me '):
|
||||
direction_mark = i18n.paragraph_direction_mark(str(text[3:]))
|
||||
else:
|
||||
|
@ -1369,13 +1277,9 @@ class ConversationTextview(GObject.GObject):
|
|||
self.last_sent_message_id = (msg_stanza_id, new_mark)
|
||||
|
||||
if not insert_mark:
|
||||
if at_the_end or kind == 'outgoing':
|
||||
if self.at_the_end() or kind == 'outgoing':
|
||||
# we are at the end or we are sending something
|
||||
# scroll to the end (via idle in case the scrollbar has appeared)
|
||||
if gajim.config.get('use_smooth_scrolling'):
|
||||
GLib.idle_add(self.smooth_scroll_to_end)
|
||||
else:
|
||||
GLib.idle_add(self.scroll_to_end)
|
||||
GLib.idle_add(self.scroll_to_end_iter)
|
||||
|
||||
self.just_cleared = False
|
||||
buffer_.end_user_action()
|
||||
|
|
|
@ -1831,7 +1831,7 @@ class Interface:
|
|||
# Using isinstance here because we want to catch all derived types
|
||||
if isinstance(ctrl, ChatControlBase):
|
||||
tv = ctrl.conv_textview
|
||||
tv.scroll_to_end()
|
||||
tv.scroll_to_end_iter()
|
||||
|
||||
################################################################################
|
||||
### Methods dealing with emoticons
|
||||
|
|
Loading…
Reference in New Issue