1
0
Fork 0
mirror of https://git.lynn.is/Gwen/python-layout.git synced 2024-01-13 01:31:55 +01:00
python-layout/pillow_layout/container.py
2023-02-07 23:56:17 +01:00

150 lines
5.4 KiB
Python

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