comparison 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
comparison
equal deleted inserted replaced
58:7aa2ffff9067 59:2aa44a82d0e7
61 61
62 62
63 class SimpleXHTMLWidgetEscapedText(Label): 63 class SimpleXHTMLWidgetEscapedText(Label):
64 pass 64 pass
65 65
66
66 class SimpleXHTMLWidgetText(Label): 67 class SimpleXHTMLWidgetText(Label):
67 pass 68 pass
68 69
70
69 class SimpleXHTMLWidgetImage(AsyncImage): 71 class SimpleXHTMLWidgetImage(AsyncImage):
70 pass 72 # following properties are desired height/width
73 # i.e. the ones specified in height/width attributes of <img>
74 # (or wanted for whatever reason)
75 # set to 0 to ignore them
76 target_height = properties.NumericProperty()
77 target_width = properties.NumericProperty()
78
79 def _get_parent_container(self):
80 """get parent SimpleXHTMLWidget instance
81
82 @param warning(bool): if True display a log.error if nothing found
83 @return (SimpleXHTMLWidget, None): found SimpleXHTMLWidget instance
84 """
85 parent = self.parent
86 while parent and not isinstance(parent, SimpleXHTMLWidget):
87 parent = parent.parent
88 if parent is None:
89 log.error(u"no SimpleXHTMLWidget parent found")
90 return parent
91
92 def _on_source_load(self, value):
93 # this method is called when image is loaded
94 super(SimpleXHTMLWidgetImage, self)._on_source_load(value)
95 if self.parent is not None:
96 container = self._get_parent_container()
97 # image is loaded, we need to recalculate size
98 self.on_container_width(container, container.width)
99
100 def on_container_width(self, container, container_width):
101 """adapt size according to container width
102
103 called when parent container (SimpleXHTMLWidget) width change
104 """
105 target_size = (self.target_width or self.texture.width, self.target_height or self.texture.height)
106 padding = container.padding
107 padding_h = (padding[0] + padding[2]) if len(padding) == 4 else padding[0]
108 width = container_width - padding_h
109 if target_size[0] < width:
110 self.size = target_size
111 else:
112 height = width / self.image_ratio
113 self.size = (width, height)
114
115 def on_parent(self, instance, parent):
116 if parent is not None:
117 container = self._get_parent_container()
118 container.bind(width=self.on_container_width)
119
71 120
72 class SimpleXHTMLWidget(StackLayout): 121 class SimpleXHTMLWidget(StackLayout):
73 """widget handling simple XHTML parsing""" 122 """widget handling simple XHTML parsing"""
74 xhtml = properties.StringProperty() 123 xhtml = properties.StringProperty()
75 color = properties.ListProperty([1, 1, 1, 1]) 124 color = properties.ListProperty([1, 1, 1, 1])
382 try: 431 try:
383 src = elem.attrib['src'] 432 src = elem.attrib['src']
384 except KeyError: 433 except KeyError:
385 log.warning(u"<img> element without src: {}".format(ET.tostring(elem))) 434 log.warning(u"<img> element without src: {}".format(ET.tostring(elem)))
386 return 435 return
387 img = SimpleXHTMLWidgetImage(source=src) 436 try:
437 target_height = int(elem.get(u'height', 0))
438 except ValueError:
439 log.warning(u"Can't parse image height: {}".format(elem.get(u'height')))
440 target_height = 0
441 try:
442 target_width = int(elem.get(u'width', 0))
443 except ValueError:
444 log.warning(u"Can't parse image width: {}".format(elem.get(u'width')))
445 target_width = 0
446
447 img = SimpleXHTMLWidgetImage(source=src, target_height=target_height, target_width=target_width)
388 self.current_wid = img 448 self.current_wid = img
389 self.add_widget(img) 449 self.add_widget(img)
390 450
391 def xhtml_p(self, elem): 451 def xhtml_p(self, elem):
392 if isinstance(self.current_wid, Label): 452 if isinstance(self.current_wid, Label):