diff src/cagou/plugins/plugin_wid_chat.py @ 59:2aa44a82d0e7

chat: XHTML image size handling: display image full size if possible, else resize it to fit in container. if height and or width attribute of <img> are specified, they are used instead of actual image size.
author Goffi <goffi@goffi.org>
date Sun, 02 Oct 2016 13:29:37 +0200
parents 7aa2ffff9067
children 5f7f72c2635f
line wrap: on
line diff
--- a/src/cagou/plugins/plugin_wid_chat.py	Wed Sep 28 22:02:36 2016 +0200
+++ b/src/cagou/plugins/plugin_wid_chat.py	Sun Oct 02 13:29:37 2016 +0200
@@ -63,11 +63,60 @@
 class SimpleXHTMLWidgetEscapedText(Label):
     pass
 
+
 class SimpleXHTMLWidgetText(Label):
     pass
 
+
 class SimpleXHTMLWidgetImage(AsyncImage):
-    pass
+    # following properties are desired height/width
+    # i.e. the ones specified in height/width attributes of <img>
+    # (or wanted for whatever reason)
+    # set to 0 to ignore them
+    target_height = properties.NumericProperty()
+    target_width = properties.NumericProperty()
+
+    def _get_parent_container(self):
+        """get parent SimpleXHTMLWidget instance
+
+        @param warning(bool): if True display a log.error if nothing found
+        @return (SimpleXHTMLWidget, None): found SimpleXHTMLWidget instance
+        """
+        parent = self.parent
+        while parent and not isinstance(parent, SimpleXHTMLWidget):
+            parent = parent.parent
+        if parent is None:
+            log.error(u"no SimpleXHTMLWidget parent found")
+        return parent
+
+    def _on_source_load(self, value):
+        # this method is called when image is loaded
+        super(SimpleXHTMLWidgetImage, self)._on_source_load(value)
+        if self.parent is not None:
+            container = self._get_parent_container()
+            # image is loaded, we need to recalculate size
+            self.on_container_width(container, container.width)
+
+    def on_container_width(self, container, container_width):
+        """adapt size according to container width
+
+        called when parent container (SimpleXHTMLWidget) width change
+        """
+        target_size = (self.target_width or self.texture.width, self.target_height or self.texture.height)
+        padding = container.padding
+        padding_h = (padding[0] + padding[2]) if len(padding) == 4 else padding[0]
+        width = container_width - padding_h
+        if target_size[0] < width:
+            self.size = target_size
+        else:
+            height = width / self.image_ratio
+            self.size = (width, height)
+
+    def on_parent(self, instance, parent):
+        if parent is not None:
+            container = self._get_parent_container()
+            container.bind(width=self.on_container_width)
+
 
 class SimpleXHTMLWidget(StackLayout):
     """widget handling simple XHTML parsing"""
@@ -384,7 +433,18 @@
         except KeyError:
             log.warning(u"<img> element without src: {}".format(ET.tostring(elem)))
             return
-        img = SimpleXHTMLWidgetImage(source=src)
+        try:
+            target_height = int(elem.get(u'height', 0))
+        except ValueError:
+            log.warning(u"Can't parse image height: {}".format(elem.get(u'height')))
+            target_height = 0
+        try:
+            target_width = int(elem.get(u'width', 0))
+        except ValueError:
+            log.warning(u"Can't parse image width: {}".format(elem.get(u'width')))
+            target_width = 0
+
+        img = SimpleXHTMLWidgetImage(source=src, target_height=target_height, target_width=target_width)
         self.current_wid = img
         self.add_widget(img)