from PIL import ImageDraw from . import Layout from .internal.helpers import min_with_none, max_with_none class Container(Layout): def __init__( self, contents=None, **kwargs ): super().__init__(**kwargs) if contents is None: contents = [] self._contents = contents def children(self): return self._contents def get_min_inner_width(self, max_height=None): min_width = 0 for c in self._contents: width = c.get_min_outer_width(max_height) if c.left is not None: width += c.left if c.right is not None: width += c.right min_width = max(min_width, width) if self.min_width is not None: min_width = max(min_width, self.min_width) return min_width def get_min_inner_height(self, max_width=None): min_height_automatic = 0 min_height_absolute = 0 for c in self._contents: height = c.get_min_outer_height(max_width) if c.top is None and c.bottom is None and c.left is None and c.right is None: min_height_automatic += height else: if c.top is not None: height += c.top if c.bottom is not None: height += c.bottom min_height_absolute = max(min_height_absolute, height) min_height = max(min_height_automatic, min_height_absolute) if self.min_height is not None: min_height = max(min_height, self.min_height) return min_height def get_ideal_inner_dimensions(self, min_width=None, min_height=None, available_width=None, available_height=None): width, height_automatic, height_absolute = 0, 0, 0 for c in self._contents: w, h = c.get_ideal_outer_dimensions(min_width, min_height, available_width, available_height) if c.left is not None: w += c.left if c.right is not None: w += c.right if c.top is not None: h += c.top if c.bottom is not None: h += c.bottom width = max(width, w) if c.top is None and c.bottom is None and c.left is None and c.right is None: height_automatic += h else: height_absolute = max(height_absolute, h) height = max(height_automatic, height_absolute) if self.width is not None: width = self.width if self.height is not None: height = self.height return width, height def render_content(self, rect): image = self.make_canvas() x1, y1, x2, y2 = rect automatic_y = 0 for c in self._contents: soft_max_width, soft_max_height = x2 - x1 + 1, y2 - y1 + 1 is_absolute = not (c.top is None and c.bottom is None and c.left is None and c.right is None) if c.left is not None: soft_max_width -= c.left if c.right is not None: soft_max_width -= c.right if c.top is not None: soft_max_height -= c.top if c.bottom is not None: soft_max_height -= c.bottom hard_max_width, hard_max_height = c.max_width, c.max_height if c.left is not None and c.right is not None: hard_max_width = min_with_none(hard_max_width, x2 - x1 + 1 - c.left - c.right) if c.top is not None and c.bottom is not None: hard_max_height = min_with_none(hard_max_height, y2 - y1 + 1 - c.top - c.bottom) width, height = c.get_ideal_outer_dimensions(available_width=soft_max_width, available_height=soft_max_height) if c.left is not None and c.right is not None: width = (x2 - c.right) - (x1 + c.left) + 1 if c.top is not None and c.bottom is not None: height = (y2 - c.bottom) - (y1 + c.top) + 1 min_width, min_height = c.get_min_outer_width(hard_max_height), c.get_min_outer_height(hard_max_width) width = max_with_none(width, min_width) height = max_with_none(height, min_height) width = min_with_none(width, hard_max_width) height = min_with_none(height, hard_max_height) if is_absolute: if c.left is None: if c.right is None: cx1 = x1 cx2 = cx1 + width - 1 else: cx2 = x2 - c.right cx1 = cx2 - width + 1 else: cx1 = x1 + c.left cx2 = cx1 + width - 1 if c.top is None: if c.bottom is None: cy1 = y1 cy2 = cy1 + height - 1 else: cy2 = y2 - c.bottom cy1 = cy2 - height + 1 else: cy1 = y1 + c.top cy2 = cy1 + height - 1 else: cx1 = x1 cx2 = cx1 + width - 1 cy1 = y1 + automatic_y cy2 = cy1 + height - 1 automatic_y += height content_image = c.render((cx1, cy1, cx2, cy2)) image.alpha_composite(content_image) return image