Philipp Hörist pushed to branch master at gajim / gajim
Commits: c963fc5d by Philipp Hörist at 2017-07-28T20:40:09+02:00 Fix use of deprecated method
- - - - - b8aaf09c by Philipp Hörist at 2017-07-28T20:40:30+02:00 Fix infinite expand of MessageTextView
- The 'configure-event' does not trigger anymore when connected to the MessageTextView. The reason is unknown.
- Use our own ScrolledWindow Widget instead so we can better control the dimension of the MessageTextView
- - - - -
5 changed files:
- data/gui/chat_control.ui - gajim/chat_control_base.py - gajim/htmltextview.py - gajim/message_textview.py - + gajim/scrolled_window.py
Changes:
===================================== data/gui/chat_control.ui ===================================== --- a/data/gui/chat_control.ui +++ b/data/gui/chat_control.ui @@ -629,21 +629,7 @@ </packing> </child> <child> - <object class="GtkScrolledWindow" id="message_scrolledwindow"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">never</property> - <property name="vscrollbar_policy">never</property> - <property name="shadow_type">in</property> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> + <placeholder/> </child> </object> <packing>
===================================== gajim/chat_control_base.py ===================================== --- a/gajim/chat_control_base.py +++ b/gajim/chat_control_base.py @@ -44,6 +44,7 @@ import notify import re
import emoticons +from scrolled_window import ScrolledWindow from common import events from common import gajim from common import helpers @@ -327,15 +328,21 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): self.last_received_id = {} # one per name
# add MessageTextView to UI and connect signals - self.msg_scrolledwindow = self.xml.get_object('message_scrolledwindow') self.msg_textview = MessageTextView() + + self.msg_scrolledwindow = ScrolledWindow() + self.msg_scrolledwindow.set_max_content_height(100) + self.msg_scrolledwindow.set_min_content_height(23) + + self.msg_scrolledwindow.set_property('shadow_type', Gtk.ShadowType.IN) self.msg_scrolledwindow.add(self.msg_textview) + + hbox = self.xml.get_object('hbox') + hbox.pack_end(self.msg_scrolledwindow, True, True, 0) + id_ = self.msg_textview.connect('key_press_event', self._on_message_textview_key_press_event) self.handlers[id_] = self.msg_textview - id_ = self.msg_textview.connect('configure-event', - self.on_configure_event) - self.handlers[id_] = self.msg_textview id_ = self.msg_textview.connect('populate_popup', self.on_msg_textview_populate_popup) self.handlers[id_] = self.msg_textview @@ -369,8 +376,6 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): # For XEP-0172 self.user_nick = None
- self.smooth = True - self.command_hits = [] self.last_key_tabs = False
@@ -693,6 +698,10 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): self.send_message(message, xhtml=xhtml) else: message_buffer.insert_at_cursor('\n') + mark = message_buffer.get_insert() + iter_ = message_buffer.get_iter_at_mark(mark) + if message_buffer.get_end_iter().equal(iter_): + GLib.idle_add(gtkgui_helpers.scroll_to_end, self.msg_scrolledwindow)
return True elif event.keyval == Gdk.KEY_z: # CTRL+z @@ -1157,60 +1166,6 @@ class ChatControlBase(MessageControl, ChatCommandProcessor, CommandTools): self.conv_textview.scroll_to_end_iter() return False
- def on_configure_event(self, msg_textview, event): - """ - When message_textview changes its size: if the new height will enlarge - the window, enable the scrollbar automatic policy. Also enable scrollbar - automatic policy for horizontal scrollbar if message we have in - message_textview is too big - """ - if msg_textview.get_window() is None: - return - - min_height = self.conv_scrolledwindow.get_property('height-request') - conversation_height = self.conv_textview.tv.get_window().get_size()[1] - message_height = msg_textview.get_window().get_size()[1] - message_width = msg_textview.get_window().get_size()[0] - # new tab is not exposed yet - if conversation_height < 2: - return - - if conversation_height < min_height: - min_height = conversation_height - - # we don't want to always resize in height the message_textview - # so we have minimum on conversation_textview's scrolled window - # but we also want to avoid window resizing so if we reach that - # minimum for conversation_textview and maximum for message_textview - # we set to automatic the scrollbar policy - diff_y = message_height - event.height - if diff_y != 0: - if conversation_height + diff_y < min_height: - if message_height + conversation_height - min_height > min_height: - policy = self.msg_scrolledwindow.get_property( - 'vscrollbar-policy') - if policy != Gtk.PolicyType.AUTOMATIC: - self.msg_scrolledwindow.set_property('vscrollbar-policy', - Gtk.PolicyType.AUTOMATIC) - self.msg_scrolledwindow.set_property('height-request', - message_height + conversation_height - min_height) - else: - self.msg_scrolledwindow.set_property('vscrollbar-policy', - Gtk.PolicyType.NEVER) - self.msg_scrolledwindow.set_property('height-request', -1) - - self.smooth = True # reinit the flag - # enable scrollbar automatic policy for horizontal scrollbar - # if message we have in message_textview is too big - if event.width > message_width: - self.msg_scrolledwindow.set_property('hscrollbar-policy', - Gtk.PolicyType.AUTOMATIC) - else: - self.msg_scrolledwindow.set_property('hscrollbar-policy', - Gtk.PolicyType.NEVER) - - return True - def on_conversation_vadjustment_changed(self, adjustment): # used to stay at the end of the textview when we shrink conversation # textview.
===================================== gajim/htmltextview.py ===================================== --- a/gajim/htmltextview.py +++ b/gajim/htmltextview.py @@ -838,7 +838,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler): class HtmlTextView(Gtk.TextView):
def __init__(self): - GObject.GObject.__init__(self) + Gtk.TextView.__init__(self) self.set_wrap_mode(Gtk.WrapMode.CHAR) self.set_editable(False) self._changed_cursor = False @@ -1045,7 +1045,7 @@ class HtmlTextView(Gtk.TextView): clipboard = self.get_clipboard(Gdk.SELECTION_CLIPBOARD) selected = self.get_selected_text() clipboard.set_text(selected, -1) - self.emit_stop_by_name('copy-clipboard') + GObject.signal_stop_emission_by_name(self, 'copy-clipboard')
def on_html_text_view_realized(self, unused_data): self.get_buffer().remove_selection_clipboard(self.get_clipboard(
===================================== gajim/message_textview.py ===================================== --- a/gajim/message_textview.py +++ b/gajim/message_textview.py @@ -29,6 +29,7 @@ from gi.repository import GLib from gi.repository import Pango
from common import gajim +import gtkgui_helpers
class MessageTextView(Gtk.TextView): """ @@ -38,7 +39,7 @@ class MessageTextView(Gtk.TextView): UNDO_LIMIT = 20
def __init__(self): - GObject.GObject.__init__(self) + Gtk.TextView.__init__(self)
# set properties self.set_border_width(1) @@ -79,6 +80,15 @@ class MessageTextView(Gtk.TextView): self.begin_tags['strike'] = '<span style="text-decoration: line-through;">' self.end_tags['strike'] = '</span>'
+ self.connect_after('paste-clipboard', self.after_paste_clipboard) + + def after_paste_clipboard(self, textview): + buffer_ = textview.get_buffer() + mark = buffer_.get_insert() + iter_ = buffer_.get_iter_at_mark(mark) + if iter_.get_offset() == buffer_.get_end_iter().get_offset(): + GLib.idle_add(gtkgui_helpers.scroll_to_end, textview.get_parent()) + def make_clickable_urls(self, text): _buffer = self.get_buffer()
===================================== gajim/scrolled_window.py ===================================== --- /dev/null +++ b/gajim/scrolled_window.py @@ -0,0 +1,89 @@ +# -*- coding:utf-8 -*- +# Copyright (C) 2015 Patrick Griffis tingping@tingping.se +# Copyright (C) 2014 Christian Hergert christian@hergert.me +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranties of +# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see http://www.gnu.org/licenses/. + +from gi.repository import GObject, Gtk + +class ScrolledWindow(Gtk.ScrolledWindow): + """ + ScrolledWindow that sets a max size for the child to grow into. + Taken from the Gnome Builder project: + https://git.gnome.org/browse/gnome-builder/tree/contrib/egg/egg-scrolled-win... + """ + __gtype_name__ = "EggScrolledWindow" + + max_content_height = GObject.Property(type=int, default=-1, nick="Max Content Height", + blurb="The maximum height request that can be made") + max_content_width = GObject.Property(type=int, default=-1, nick="Max Content Width", + blurb="The maximum width request that can be made") + min_content_height = GObject.Property(type=int, default=-1, nick="Min Content Height", + blurb="The minimum height request that can be made") + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.connect_after("notify::max-content-height", lambda obj, param: self.queue_resize()) + self.connect_after("notify::max-content-width", lambda obj, param: self.queue_resize()) + + def set_min_content_height(self, value): + self.min_content_height = value + + def set_max_content_height(self, value): + self.max_content_height = value + + def set_max_content_width(self, value): + self.max_content_width = value + + def get_max_content_height(self): + return self.max_content_height + + def get_max_content_width(self): + return self.max_content_width + + def do_get_preferred_height(self): + min_height, natural_height = Gtk.ScrolledWindow.do_get_preferred_height(self) + child = self.get_child() + + if natural_height and self.max_content_height > -1 and child: + + style = self.get_style_context() + border = style.get_border(style.get_state()) + additional = border.top + border.bottom + + child_min_height, child_nat_height = child.get_preferred_height() + if child_nat_height > natural_height and self.max_content_height > natural_height: + natural_height = min(self.max_content_height, child_nat_height) + additional + elif natural_height > child_nat_height: + if child_nat_height < self.min_content_height: + return self.min_content_height, self.min_content_height + min_height, natural_height = child_min_height + additional, child_nat_height + additional + + return min_height, natural_height + + def do_get_preferred_width(self): + min_width, natural_width = Gtk.ScrolledWindow.do_get_preferred_width(self) + child = self.get_child() + + if natural_width and self.max_content_width > -1 and child: + + style = self.get_style_context() + border = style.get_border(style.get_state()) + additional = border.left + border.right + 1 + + child_min_width, child_nat_width = child.get_preferred_width() + if child_nat_width > natural_width and self.max_content_width > natural_width: + natural_width = min(self.max_content_width, child_nat_width) + additional + + return min_width, natural_width
View it on GitLab: https://dev.gajim.org/gajim/gajim/compare/766458f394d5360e423daf7c7467d54e09...