from kivy.event import EventDispatcher from kivy.uix.abstractview import AbstractView from kivy.properties import ListProperty, NumericProperty from kivy.adapters.simplelistadapter import SimpleListAdapter from kivy.utils import escape_markup from kivy.clock import Clock from kivy.uix.label import Label # from utils import log_method from textutils import (links_to_markup, replace_emotes, preprocess, remove_formatting) class ChatLog(AbstractView, EventDispatcher): def __init__(self, **kwargs): # Check for adapter argument if 'adapter' not in kwargs: list_adapter = SimpleListAdapter(data=[], cls=Label) kwargs['adapter'] = list_adapter super(ChatLog, self).__init__(**kwargs) self._views = [] populate = self._trigger_populate = Clock.create_trigger( self._populate, -1) fbind = self.fbind fbind('adapter', populate) fbind('size', populate) fbind('pos', populate) max_lines = NumericProperty(100) cut_lines = NumericProperty(10) def _populate(self, *args): container = self.container adapter = self.adapter container.clear_widgets() self._views = [] for index in range(adapter.get_count()): item_view = adapter.get_view(index) self.container.add_widget(item_view) self._views.append(item_view) container.height = self._container_height() def _append(self, msg): container = self.container adapter = self.adapter views = self._views cl = self.cut_lines if len(views) >= self.max_lines: container.clear_widgets(views[:cl]) self._views = views[cl:] adapter.data = adapter.data[cl:] adapter.data.append(msg) item_view = adapter.get_view(adapter.get_count() - 1) item_view.texture_update() self._views.append(item_view) container.add_widget(item_view) def _container_height(self, *args): h = 0 for v in self._views: h += v.height return h def append_message(self, msg): msg = preprocess(msg, (replace_emotes, remove_formatting)) msg = links_to_markup(escape_markup(msg)) self._append(msg) self.container.height = self._container_height() self.children[0].scroll_y = 0 def msg_converter(self, index, msg): b = (index % 2) * 0.04 return {'text': msg, 'width': self.width, 'background_color': (0 + b, 0.17 + b, 0.21 + b, 1)}