mirror of
https://git.lynn.is/Gwen/python-layout.git
synced 2024-01-13 01:31:55 +01:00
clean up
This commit is contained in:
parent
cd4c111c78
commit
4d4dc38fe9
74
box.py
74
box.py
|
@ -19,82 +19,82 @@ class Box(Layout):
|
|||
**kwargs
|
||||
):
|
||||
super().__init__(**kwargs)
|
||||
self._title = title
|
||||
self._title_font = title_font
|
||||
self._title_color = title_color
|
||||
self._title_anchor = title_anchor
|
||||
self._title_position = title_position
|
||||
self._title_padding = title_padding
|
||||
self._content = content
|
||||
self.title = title
|
||||
self.title_font = title_font
|
||||
self.title_color = title_color
|
||||
self.title_anchor = title_anchor
|
||||
self.title_position = title_position
|
||||
self.title_padding = title_padding
|
||||
self.content = content
|
||||
|
||||
def _children(self):
|
||||
if self._content is not None:
|
||||
return [self._content]
|
||||
def children(self):
|
||||
if self.content is not None:
|
||||
return [self.content]
|
||||
else:
|
||||
return []
|
||||
|
||||
def _get_title_font(self):
|
||||
if self._title_font is not None:
|
||||
return self._title_font
|
||||
def get_title_font(self):
|
||||
if self.title_font is not None:
|
||||
return self.title_font
|
||||
else:
|
||||
return self.get_font()
|
||||
|
||||
def _get_title_color(self):
|
||||
if self._title_color is not None:
|
||||
return self._title_color
|
||||
def get_title_color(self):
|
||||
if self.title_color is not None:
|
||||
return self.title_color
|
||||
else:
|
||||
return self.get_fg_color()
|
||||
|
||||
def get_min_inner_width(self, max_height=None):
|
||||
if self._content is None:
|
||||
if self.content is None:
|
||||
return 0
|
||||
else:
|
||||
return self._content.get_min_outer_width(max_height)
|
||||
return self.content.get_min_outer_width(max_height)
|
||||
|
||||
def get_min_inner_height(self, max_width=None):
|
||||
if self._content is None:
|
||||
if self.content is None:
|
||||
return 0
|
||||
else:
|
||||
return self._content.get_min_outer_height(max_width)
|
||||
return self.content.get_min_outer_height(max_width)
|
||||
|
||||
def get_ideal_inner_dimensions(self, min_width=None, min_height=None, available_width=None, available_height=None):
|
||||
if self._content is None:
|
||||
if self.content is None:
|
||||
return 0, 0
|
||||
else:
|
||||
return self._content.get_ideal_outer_dimensions(min_width, min_height, available_width, available_height)
|
||||
return self.content.get_ideal_outer_dimensions(min_width, min_height, available_width, available_height)
|
||||
|
||||
def render_content(self, rect):
|
||||
if self._content is None:
|
||||
if self.content is None:
|
||||
return self.make_canvas()
|
||||
else:
|
||||
return self._content.render(rect)
|
||||
return self.content.render(rect)
|
||||
|
||||
def _title_pos(self, rect):
|
||||
left, top, right, bottom = self._get_title_font().getbbox(self._title)
|
||||
def title_pos(self, rect):
|
||||
left, top, right, bottom = self.get_title_font().getbbox(self.title)
|
||||
height = bottom - top
|
||||
width = right - left
|
||||
border_radius = self.border_radius()
|
||||
border_radius = self.get_border_radius()
|
||||
available_width = rect[2] - rect[0] + 1 - border_radius[1] - border_radius[0]
|
||||
pos_x = rect[0] + border_radius[0] + self._title_position
|
||||
if self._title_anchor == BoxTitleAnchor.LEFT:
|
||||
pos_x = rect[0] + border_radius[0] + self.title_position
|
||||
if self.title_anchor == BoxTitleAnchor.LEFT:
|
||||
pos_x += 0
|
||||
elif self._title_anchor == BoxTitleAnchor.CENTER:
|
||||
elif self.title_anchor == BoxTitleAnchor.CENTER:
|
||||
pos_x += (available_width - width) / 2
|
||||
elif self._title_anchor == BoxTitleAnchor.RIGHT:
|
||||
elif self.title_anchor == BoxTitleAnchor.RIGHT:
|
||||
pos_x += available_width - width
|
||||
pos_y = rect[1] - height / 2
|
||||
return (pos_x, pos_y), (left - self._title_padding, top, right + self._title_padding, bottom)
|
||||
return (pos_x, pos_y), (left - self.title_padding, top, right + self.title_padding, bottom)
|
||||
|
||||
def modify_border_mask(self, border_mask, rect):
|
||||
if self._title is None:
|
||||
if self.title is None:
|
||||
return
|
||||
(x, y), (left, top, right, bottom) = self._title_pos(rect)
|
||||
(x, y), (left, top, right, bottom) = self.title_pos(rect)
|
||||
d = ImageDraw.Draw(border_mask)
|
||||
d.rectangle((x + left, y + top, x + right, y + bottom), fill=0)
|
||||
|
||||
def render_after_border(self, image, rect):
|
||||
if self._title is None:
|
||||
if self.title is None:
|
||||
return
|
||||
(x, y), _ = self._title_pos(rect)
|
||||
(x, y), _ = self.title_pos(rect)
|
||||
d = ImageDraw.Draw(image)
|
||||
d.text((x, y), self._title, font=self._get_title_font(), fill=self._get_title_color())
|
||||
d.text((x, y), self.title, font=self.get_title_font(), fill=self.get_title_color())
|
||||
|
|
106
container.py
106
container.py
|
@ -17,20 +17,20 @@ class Container(Layout):
|
|||
contents = []
|
||||
self._contents = contents
|
||||
|
||||
def _children(self):
|
||||
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
|
||||
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)
|
||||
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):
|
||||
|
@ -38,17 +38,17 @@ class Container(Layout):
|
|||
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:
|
||||
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
|
||||
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)
|
||||
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):
|
||||
|
@ -56,24 +56,24 @@ class Container(Layout):
|
|||
|
||||
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
|
||||
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:
|
||||
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
|
||||
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):
|
||||
|
@ -83,29 +83,29 @@ class Container(Layout):
|
|||
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)
|
||||
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
|
||||
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)
|
||||
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
|
||||
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)
|
||||
|
@ -115,26 +115,26 @@ class Container(Layout):
|
|||
height = min_with_none(height, hard_max_height)
|
||||
|
||||
if is_absolute:
|
||||
if c._left is None:
|
||||
if c._right is None:
|
||||
if c.left is None:
|
||||
if c.right is None:
|
||||
cx1 = x1
|
||||
cx2 = cx1 + width - 1
|
||||
else:
|
||||
cx2 = x2 - c._right
|
||||
cx2 = x2 - c.right
|
||||
cx1 = cx2 - width + 1
|
||||
else:
|
||||
cx1 = x1 + c._left
|
||||
cx1 = x1 + c.left
|
||||
cx2 = cx1 + width - 1
|
||||
|
||||
if c._top is None:
|
||||
if c._bottom is None:
|
||||
if c.top is None:
|
||||
if c.bottom is None:
|
||||
cy1 = y1
|
||||
cy2 = cy1 + height - 1
|
||||
else:
|
||||
cy2 = y2 - c._bottom
|
||||
cy2 = y2 - c.bottom
|
||||
cy1 = cy2 - height + 1
|
||||
else:
|
||||
cy1 = y1 + c._top
|
||||
cy1 = y1 + c.top
|
||||
cy2 = cy1 + height - 1
|
||||
else:
|
||||
cx1 = x1
|
||||
|
|
58
document.py
58
document.py
|
@ -14,67 +14,67 @@ class Document(Layout):
|
|||
**kwargs
|
||||
):
|
||||
super().__init__(**kwargs)
|
||||
if self._overflow is None:
|
||||
self._overflow = True
|
||||
if self._font is None:
|
||||
self._font = ImageFont.load_default()
|
||||
self._content = content
|
||||
self._actual_size = None
|
||||
if self.overflow is None:
|
||||
self.overflow = True
|
||||
if self.font is None:
|
||||
self.font = ImageFont.load_default()
|
||||
self.content = content
|
||||
self.actual_size = None
|
||||
self.complete_init(None)
|
||||
|
||||
def _children(self):
|
||||
if self._content is not None:
|
||||
return [self._content]
|
||||
def children(self):
|
||||
if self.content is not None:
|
||||
return [self.content]
|
||||
else:
|
||||
return []
|
||||
|
||||
def get_ideal_inner_dimensions(self, min_width=None, min_height=None, available_width=None, available_height=None):
|
||||
if self._content is None:
|
||||
if self.content is None:
|
||||
return 0,0
|
||||
else:
|
||||
return self._content.get_ideal_outer_dimensions(min_width, min_height, available_width, available_height)
|
||||
return self.content.get_ideal_outer_dimensions(min_width, min_height, available_width, available_height)
|
||||
|
||||
def get_min_inner_height(self, max_width=None):
|
||||
if self._content is None:
|
||||
if self.content is None:
|
||||
return 0
|
||||
else:
|
||||
return self._content.get_min_outer_height(max_width)
|
||||
return self.content.get_min_outer_height(max_width)
|
||||
|
||||
def get_min_inner_width(self, max_height=None):
|
||||
if self._content is None:
|
||||
if self.content is None:
|
||||
return 0
|
||||
else:
|
||||
return self._content.get_min_outer_width(max_height)
|
||||
return self.content.get_min_outer_width(max_height)
|
||||
|
||||
def render_content(self, rect):
|
||||
image = self.make_canvas()
|
||||
if self._content is not None:
|
||||
content_image = self._content.render(rect)
|
||||
if self.content is not None:
|
||||
content_image = self.content.render(rect)
|
||||
image.alpha_composite(content_image)
|
||||
return image
|
||||
|
||||
def get_image(self):
|
||||
min_width = max_with_none(self._width, self._min_width)
|
||||
min_height = max_with_none(self._height, self._min_height)
|
||||
max_width = min_with_none(self._width, self._max_width)
|
||||
max_height = min_with_none(self._height, self._max_height)
|
||||
min_width = max_with_none(self.width, self.min_width)
|
||||
min_height = max_with_none(self.height, self.min_height)
|
||||
max_width = min_with_none(self.width, self.max_width)
|
||||
max_height = min_with_none(self.height, self.max_height)
|
||||
|
||||
width, height = self.get_ideal_outer_dimensions(min_width=min_width,
|
||||
min_height=min_height,
|
||||
available_width=max_width,
|
||||
available_height=max_height)
|
||||
|
||||
if self._width is not None:
|
||||
width = self._width
|
||||
if self.width is not None:
|
||||
width = self.width
|
||||
else:
|
||||
width = min_with_none(max_with_none(width, self._min_width), self._max_width)
|
||||
if self._height is not None:
|
||||
height = self._height
|
||||
width = min_with_none(max_with_none(width, self.min_width), self.max_width)
|
||||
if self.height is not None:
|
||||
height = self.height
|
||||
else:
|
||||
height = min_with_none(max_with_none(height, self._min_height), self._max_height)
|
||||
height = min_with_none(max_with_none(height, self.min_height), self.max_height)
|
||||
|
||||
self._actual_size = (width, height)
|
||||
self.actual_size = (width, height)
|
||||
|
||||
background = Image.new('RGBA', (width, height), self._bg_color)
|
||||
background = Image.new('RGBA', (width, height), self.bg_color)
|
||||
content = self.render((0, 0, width - 1, height - 1))
|
||||
return Image.alpha_composite(background, content)
|
||||
|
|
44
flex.py
44
flex.py
|
@ -21,43 +21,43 @@ class Flex(Layout):
|
|||
super().__init__(**kwargs)
|
||||
if contents is None:
|
||||
contents = []
|
||||
self._direction = direction
|
||||
self._wrap = wrap
|
||||
self._justify = justify
|
||||
self._align_items = align_items
|
||||
self._align_content = align_content
|
||||
self._gap = gap
|
||||
self._contents = contents
|
||||
self._flex_layouter = FlexLayouter(contents, gap, direction, wrap, justify, align_content, align_items)
|
||||
self.direction = direction
|
||||
self.wrap = wrap
|
||||
self.justify = justify
|
||||
self.align_items = align_items
|
||||
self.align_content = align_content
|
||||
self.gap = gap
|
||||
self.contents = contents
|
||||
self.flex_layouter = FlexLayouter(contents, gap, direction, wrap, justify, align_content, align_items)
|
||||
|
||||
def _children(self):
|
||||
return self._contents
|
||||
def children(self):
|
||||
return self.contents
|
||||
|
||||
def get_min_inner_width(self, max_height=None):
|
||||
max_width = min_with_none(self._max_width, 0)
|
||||
width, _ = self._flex_layouter.get_dimensions(self._min_width, self._min_height, max_width,
|
||||
min_with_none(self._max_height, max_height))
|
||||
max_width = min_with_none(self.max_width, 0)
|
||||
width, _ = self.flex_layouter.get_dimensions(self.min_width, self.min_height, max_width,
|
||||
min_with_none(self.max_height, max_height))
|
||||
return width
|
||||
|
||||
def get_min_inner_height(self, max_width=None):
|
||||
max_height = min_with_none(self._min_height, 0)
|
||||
_, height = self._flex_layouter.get_dimensions(self._min_width, self._min_height,
|
||||
min_with_none(self._max_width, max_width), max_height)
|
||||
max_height = min_with_none(self.min_height, 0)
|
||||
_, height = self.flex_layouter.get_dimensions(self.min_width, self.min_height,
|
||||
min_with_none(self.max_width, max_width), max_height)
|
||||
return height
|
||||
|
||||
def get_ideal_inner_dimensions(self, min_width=None, min_height=None, available_width=None, available_height=None):
|
||||
min_width = max_with_none(min_width, self._min_width)
|
||||
min_height = max_with_none(min_height, self._min_height)
|
||||
available_width = min_with_none(available_width, self._max_width, self._width)
|
||||
available_height = min_with_none(available_height, self._max_height, self._height)
|
||||
return self._flex_layouter.get_dimensions(min_width, min_height, available_width, available_height)
|
||||
min_width = max_with_none(min_width, self.min_width)
|
||||
min_height = max_with_none(min_height, self.min_height)
|
||||
available_width = min_with_none(available_width, self.max_width, self.width)
|
||||
available_height = min_with_none(available_height, self.max_height, self.height)
|
||||
return self.flex_layouter.get_dimensions(min_width, min_height, available_width, available_height)
|
||||
|
||||
def render_content(self, rect):
|
||||
image = self.make_canvas()
|
||||
x1, y1, x2, y2 = rect
|
||||
width = x2 - x1 + 1
|
||||
height = y2 - y1 + 1
|
||||
contents = self._flex_layouter.arrange(self._min_width, self._min_height, width, height)
|
||||
contents = self.flex_layouter.arrange(self.min_width, self.min_height, width, height)
|
||||
for (cx1, cy1, cx2, cy2), content in contents:
|
||||
content_image = content.render((cx1 + x1, cy1 + y1, cx2 + x1, cy2 + y1))
|
||||
image.alpha_composite(content_image)
|
||||
|
|
202
image.py
202
image.py
|
@ -19,69 +19,69 @@ class Image(Layout):
|
|||
**kwargs
|
||||
):
|
||||
super().__init__(**kwargs)
|
||||
self._image = image
|
||||
self._mode = mode
|
||||
self._scale = scale
|
||||
self._position = position
|
||||
self._offset_x = offset_x
|
||||
self._offset_y = offset_y
|
||||
self.image = image
|
||||
self.mode = mode
|
||||
self.scale = scale
|
||||
self.position = position
|
||||
self.offset_x = offset_x
|
||||
self.offset_y = offset_y
|
||||
|
||||
def scale(self):
|
||||
if isinstance(self._scale, (tuple, list)):
|
||||
if len(self._scale) == 0:
|
||||
def get_scale(self):
|
||||
if isinstance(self.scale, (tuple, list)):
|
||||
if len(self.scale) == 0:
|
||||
return 1, 1
|
||||
elif len(self._scale) == 1:
|
||||
return self._scale[0], self._scale[0]
|
||||
elif len(self.scale) == 1:
|
||||
return self.scale[0], self.scale[0]
|
||||
else:
|
||||
return self._scale[0], self._scale[1]
|
||||
elif isinstance(self._scale, (int, float)):
|
||||
return self._scale, self._scale
|
||||
return self.scale[0], self.scale[1]
|
||||
elif isinstance(self.scale, (int, float)):
|
||||
return self.scale, self.scale
|
||||
else:
|
||||
return 1, 1
|
||||
|
||||
def _get_image_width(self):
|
||||
if self._image is None:
|
||||
def get_image_width(self):
|
||||
if self.image is None:
|
||||
return 0
|
||||
return self._image.size[0]
|
||||
return self.image.size[0]
|
||||
|
||||
def _get_image_height(self):
|
||||
if self._image is None:
|
||||
def get_image_height(self):
|
||||
if self.image is None:
|
||||
return 0
|
||||
return self._image.size[1]
|
||||
return self.image.size[1]
|
||||
|
||||
def get_min_inner_width(self, max_height=None):
|
||||
if self._mode in (ImageMode.ORIGINAL, ImageMode.REPEAT_Y, ImageMode.STRETCH_Y):
|
||||
width = self._get_image_width()
|
||||
if self.mode in (ImageMode.ORIGINAL, ImageMode.REPEAT_Y, ImageMode.STRETCH_Y):
|
||||
width = self.get_image_width()
|
||||
else:
|
||||
width = 0
|
||||
return max_with_none(width, self._min_width)
|
||||
return max_with_none(width, self.min_width)
|
||||
|
||||
def get_min_inner_height(self, max_width=None):
|
||||
if self._mode in (ImageMode.ORIGINAL, ImageMode.REPEAT_X, ImageMode.STRETCH_X):
|
||||
height = self._get_image_height()
|
||||
if self.mode in (ImageMode.ORIGINAL, ImageMode.REPEAT_X, ImageMode.STRETCH_X):
|
||||
height = self.get_image_height()
|
||||
else:
|
||||
height = 0
|
||||
return max_with_none(height, self._min_height)
|
||||
return max_with_none(height, self.min_height)
|
||||
|
||||
def get_ideal_inner_dimensions(self, min_width=None, min_height=None, available_width=None, available_height=None):
|
||||
width, height = 0, 0
|
||||
if self._mode in (ImageMode.ORIGINAL, ImageMode.REPEAT_Y, ImageMode.STRETCH_Y):
|
||||
width = self._get_image_width()
|
||||
if self._mode in (ImageMode.ORIGINAL, ImageMode.REPEAT_X, ImageMode.STRETCH_X):
|
||||
height = self._get_image_height()
|
||||
if self._width is not None:
|
||||
width = self._width
|
||||
if self._height is not None:
|
||||
height = self._height
|
||||
width = min_with_none(width, available_width, self._max_width)
|
||||
height = min_with_none(height, available_height, self._max_height)
|
||||
width = max_with_none(width, min_width, self._min_width)
|
||||
height = max_with_none(height, min_height, self._min_height)
|
||||
if self.mode in (ImageMode.ORIGINAL, ImageMode.REPEAT_Y, ImageMode.STRETCH_Y):
|
||||
width = self.get_image_width()
|
||||
if self.mode in (ImageMode.ORIGINAL, ImageMode.REPEAT_X, ImageMode.STRETCH_X):
|
||||
height = self.get_image_height()
|
||||
if self.width is not None:
|
||||
width = self.width
|
||||
if self.height is not None:
|
||||
height = self.height
|
||||
width = min_with_none(width, available_width, self.max_width)
|
||||
height = min_with_none(height, available_height, self.max_height)
|
||||
width = max_with_none(width, min_width, self.min_width)
|
||||
height = max_with_none(height, min_height, self.min_height)
|
||||
return width, height
|
||||
|
||||
def render_content(self, rect):
|
||||
image = self.make_canvas()
|
||||
if self._image is None:
|
||||
if self.image is None:
|
||||
return image
|
||||
|
||||
x1, y1, x2, y2 = rect
|
||||
|
@ -91,24 +91,24 @@ class Image(Layout):
|
|||
if width == 0 or height == 0:
|
||||
return image
|
||||
|
||||
image_width = int(self._image.size[0] * self.scale()[0])
|
||||
image_height = int(self._image.size[1] * self.scale()[1])
|
||||
image_width = int(self.image.size[0] * self.get_scale()[0])
|
||||
image_height = int(self.image.size[1] * self.get_scale()[1])
|
||||
|
||||
offset_x = self._offset_x
|
||||
offset_y = self._offset_y
|
||||
offset_x = self.offset_x
|
||||
offset_y = self.offset_y
|
||||
|
||||
if self._mode == ImageMode.ORIGINAL:
|
||||
if image_width != self._image.size[0] or image_height != self._image.size[1]:
|
||||
img = self._image.resize((image_width, image_height), reducing_gap=3.0)
|
||||
if self.mode == ImageMode.ORIGINAL:
|
||||
if image_width != self.image.size[0] or image_height != self.image.size[1]:
|
||||
img = self.image.resize((image_width, image_height), reducing_gap=3.0)
|
||||
else:
|
||||
img = self._image
|
||||
elif self._mode == ImageMode.STRETCH:
|
||||
img = self._image.resize((width, height), reducing_gap=3.0)
|
||||
elif self._mode == ImageMode.STRETCH_X:
|
||||
img = self._image.resize((width, image_height), reducing_gap=3.0)
|
||||
elif self._mode == ImageMode.STRETCH_Y:
|
||||
img = self._image.resize((image_width, height), reducing_gap=3.0)
|
||||
elif self._mode == ImageMode.CONTAIN:
|
||||
img = self.image
|
||||
elif self.mode == ImageMode.STRETCH:
|
||||
img = self.image.resize((width, height), reducing_gap=3.0)
|
||||
elif self.mode == ImageMode.STRETCH_X:
|
||||
img = self.image.resize((width, image_height), reducing_gap=3.0)
|
||||
elif self.mode == ImageMode.STRETCH_Y:
|
||||
img = self.image.resize((image_width, height), reducing_gap=3.0)
|
||||
elif self.mode == ImageMode.CONTAIN:
|
||||
ratio_width = width / image_width
|
||||
ratio_height = height / image_height
|
||||
if ratio_width < ratio_height:
|
||||
|
@ -120,8 +120,8 @@ class Image(Layout):
|
|||
else:
|
||||
w = width
|
||||
h = height
|
||||
img = self._image.resize((w, h), reducing_gap=3.0)
|
||||
elif self._mode == ImageMode.COVER:
|
||||
img = self.image.resize((w, h), reducing_gap=3.0)
|
||||
elif self.mode == ImageMode.COVER:
|
||||
ratio_width = width / image_width
|
||||
ratio_height = height / image_height
|
||||
if ratio_width > ratio_height:
|
||||
|
@ -133,42 +133,42 @@ class Image(Layout):
|
|||
else:
|
||||
w = width
|
||||
h = height
|
||||
img = self._image.resize((w, h), reducing_gap=3.0)
|
||||
img = self.image.resize((w, h), reducing_gap=3.0)
|
||||
|
||||
if self._mode == ImageMode.REPEAT_X_FILL:
|
||||
if self.mode == ImageMode.REPEAT_X_FILL:
|
||||
repeat_width = int(image_width * height / image_height)
|
||||
repeat_height = height
|
||||
elif self._mode == ImageMode.REPEAT_Y_FILL:
|
||||
elif self.mode == ImageMode.REPEAT_Y_FILL:
|
||||
repeat_width = width
|
||||
repeat_height = int(image_height * width / image_width)
|
||||
else:
|
||||
repeat_width = image_width
|
||||
repeat_height = image_height
|
||||
|
||||
if self._mode in (ImageMode.REPEAT, ImageMode.REPEAT_X, ImageMode.REPEAT_X_FILL, ImageMode.REPEAT_X_STRETCH):
|
||||
if self._position in (ImageAnchor.TOP_LEFT, ImageAnchor.MIDDLE_LEFT, ImageAnchor.BOTTOM_LEFT):
|
||||
if self.mode in (ImageMode.REPEAT, ImageMode.REPEAT_X, ImageMode.REPEAT_X_FILL, ImageMode.REPEAT_X_STRETCH):
|
||||
if self.position in (ImageAnchor.TOP_LEFT, ImageAnchor.MIDDLE_LEFT, ImageAnchor.BOTTOM_LEFT):
|
||||
repeat_offset_x = offset_x
|
||||
elif self._position in (ImageAnchor.TOP_CENTER, ImageAnchor.MIDDLE_CENTER, ImageAnchor.BOTTOM_CENTER):
|
||||
elif self.position in (ImageAnchor.TOP_CENTER, ImageAnchor.MIDDLE_CENTER, ImageAnchor.BOTTOM_CENTER):
|
||||
repeat_offset_x = (width // 2) - repeat_width // 2 + offset_x
|
||||
elif self._position in (ImageAnchor.TOP_RIGHT, ImageAnchor.MIDDLE_RIGHT, ImageAnchor.BOTTOM_RIGHT):
|
||||
elif self.position in (ImageAnchor.TOP_RIGHT, ImageAnchor.MIDDLE_RIGHT, ImageAnchor.BOTTOM_RIGHT):
|
||||
repeat_offset_x = width - repeat_width + offset_x
|
||||
else:
|
||||
raise Exception('invalid image position')
|
||||
if self._mode in (ImageMode.REPEAT, ImageMode.REPEAT_Y, ImageMode.REPEAT_Y_FILL, ImageMode.REPEAT_Y_STRETCH):
|
||||
if self._position in (ImageAnchor.TOP_LEFT, ImageAnchor.TOP_CENTER, ImageAnchor.TOP_RIGHT):
|
||||
if self.mode in (ImageMode.REPEAT, ImageMode.REPEAT_Y, ImageMode.REPEAT_Y_FILL, ImageMode.REPEAT_Y_STRETCH):
|
||||
if self.position in (ImageAnchor.TOP_LEFT, ImageAnchor.TOP_CENTER, ImageAnchor.TOP_RIGHT):
|
||||
repeat_offset_y = offset_y
|
||||
elif self._position in (ImageAnchor.MIDDLE_LEFT, ImageAnchor.MIDDLE_CENTER, ImageAnchor.MIDDLE_RIGHT):
|
||||
elif self.position in (ImageAnchor.MIDDLE_LEFT, ImageAnchor.MIDDLE_CENTER, ImageAnchor.MIDDLE_RIGHT):
|
||||
repeat_offset_y = (height // 2) - repeat_height // 2 + offset_y
|
||||
elif self._position in (ImageAnchor.BOTTOM_LEFT, ImageAnchor.BOTTOM_CENTER, ImageAnchor.BOTTOM_RIGHT):
|
||||
elif self.position in (ImageAnchor.BOTTOM_LEFT, ImageAnchor.BOTTOM_CENTER, ImageAnchor.BOTTOM_RIGHT):
|
||||
repeat_offset_y = height - repeat_height + offset_y
|
||||
else:
|
||||
raise Exception('invalid image position')
|
||||
|
||||
if self._mode == ImageMode.REPEAT:
|
||||
if repeat_width != self._image.size[0] or repeat_height != self._image.size[1]:
|
||||
img_part = self._image.resize((repeat_width, repeat_height), reducing_gap=3.0)
|
||||
if self.mode == ImageMode.REPEAT:
|
||||
if repeat_width != self.image.size[0] or repeat_height != self.image.size[1]:
|
||||
img_part = self.image.resize((repeat_width, repeat_height), reducing_gap=3.0)
|
||||
else:
|
||||
img_part = self._image
|
||||
img_part = self.image
|
||||
img = PilImage.new('RGBA', (width, height), (0,0,0,0))
|
||||
num_x = width // repeat_width + 1
|
||||
num_y = height // repeat_height + 1
|
||||
|
@ -179,66 +179,66 @@ class Image(Layout):
|
|||
img.paste(img_part, (i * repeat_width + ox, j * repeat_height + oy))
|
||||
offset_x = 0
|
||||
offset_y = 0
|
||||
elif self._mode == ImageMode.REPEAT_X:
|
||||
if repeat_width != self._image.size[0] or repeat_height != self._image.size[1]:
|
||||
img_part = self._image.resize((repeat_width, repeat_height), reducing_gap=3.0)
|
||||
elif self.mode == ImageMode.REPEAT_X:
|
||||
if repeat_width != self.image.size[0] or repeat_height != self.image.size[1]:
|
||||
img_part = self.image.resize((repeat_width, repeat_height), reducing_gap=3.0)
|
||||
else:
|
||||
img_part = self._image
|
||||
img_part = self.image
|
||||
img = PilImage.new('RGBA', (width, repeat_height), (0,0,0,0))
|
||||
num_x = width // repeat_width + 1
|
||||
ox = repeat_offset_x % (repeat_width if repeat_offset_x >= 0 else -repeat_width)
|
||||
for i in range(-1, num_x):
|
||||
img.paste(img_part, (i * repeat_width + ox, 0))
|
||||
offset_x = 0
|
||||
elif self._mode == ImageMode.REPEAT_Y:
|
||||
if repeat_width != self._image.size[0] or repeat_height != self._image.size[1]:
|
||||
img_part = self._image.resize((repeat_width, repeat_height), reducing_gap=3.0)
|
||||
elif self.mode == ImageMode.REPEAT_Y:
|
||||
if repeat_width != self.image.size[0] or repeat_height != self.image.size[1]:
|
||||
img_part = self.image.resize((repeat_width, repeat_height), reducing_gap=3.0)
|
||||
else:
|
||||
img_part = self._image
|
||||
img_part = self.image
|
||||
img = PilImage.new('RGBA', (repeat_width, height), (0,0,0,0))
|
||||
num_y = height // repeat_height + 1
|
||||
oy = repeat_offset_y % (repeat_height if repeat_offset_y >= 0 else -repeat_height)
|
||||
for i in range(-1, num_y):
|
||||
img.paste(img_part, (0, i * repeat_height + oy))
|
||||
offset_y = 0
|
||||
elif self._mode == ImageMode.REPEAT_X_STRETCH:
|
||||
if repeat_width != self._image.size[0] or height != self._image.size[1]:
|
||||
img_part = self._image.resize((repeat_width, height), reducing_gap=3.0)
|
||||
elif self.mode == ImageMode.REPEAT_X_STRETCH:
|
||||
if repeat_width != self.image.size[0] or height != self.image.size[1]:
|
||||
img_part = self.image.resize((repeat_width, height), reducing_gap=3.0)
|
||||
else:
|
||||
img_part = self._image
|
||||
img_part = self.image
|
||||
img = PilImage.new('RGBA', (width, height), (0,0,0,0))
|
||||
num_x = width // repeat_width + 1
|
||||
ox = repeat_offset_x % (repeat_width if repeat_offset_x >= 0 else -repeat_width)
|
||||
for i in range(-1, num_x):
|
||||
img.paste(img_part, (i * repeat_width + ox, 0))
|
||||
offset_x = 0
|
||||
elif self._mode == ImageMode.REPEAT_Y_STRETCH:
|
||||
if width != self._image.size[0] or repeat_height != self._image.size[1]:
|
||||
img_part = self._image.resize((width, repeat_height), reducing_gap=3.0)
|
||||
elif self.mode == ImageMode.REPEAT_Y_STRETCH:
|
||||
if width != self.image.size[0] or repeat_height != self.image.size[1]:
|
||||
img_part = self.image.resize((width, repeat_height), reducing_gap=3.0)
|
||||
else:
|
||||
img_part = self._image
|
||||
img_part = self.image
|
||||
img = PilImage.new('RGBA', (width, height), (0,0,0,0))
|
||||
num_y = height // repeat_height + 1
|
||||
oy = repeat_offset_y % (repeat_height if repeat_offset_y >= 0 else -repeat_height)
|
||||
for i in range(-1, num_y):
|
||||
img.paste(img_part, (0, i * repeat_height + oy))
|
||||
offset_y = 0
|
||||
elif self._mode == ImageMode.REPEAT_X_FILL:
|
||||
if repeat_width != self._image.size[0] or repeat_height != self._image.size[1]:
|
||||
img_part = self._image.resize((repeat_width, repeat_height), reducing_gap=3.0)
|
||||
elif self.mode == ImageMode.REPEAT_X_FILL:
|
||||
if repeat_width != self.image.size[0] or repeat_height != self.image.size[1]:
|
||||
img_part = self.image.resize((repeat_width, repeat_height), reducing_gap=3.0)
|
||||
else:
|
||||
img_part = self._image
|
||||
img_part = self.image
|
||||
img = PilImage.new('RGBA', (width, height), (0,0,0,0))
|
||||
num_x = width // repeat_width + 1
|
||||
ox = repeat_offset_x % (repeat_width if repeat_offset_x >= 0 else -w)
|
||||
for i in range(-1, num_x):
|
||||
img.paste(img_part, (i * repeat_width + ox, 0))
|
||||
offset_x = 0
|
||||
elif self._mode == ImageMode.REPEAT_Y_FILL:
|
||||
if repeat_width != self._image.size[0] or repeat_height != self._image.size[1]:
|
||||
img_part = self._image.resize((repeat_width, repeat_height), reducing_gap=3.0)
|
||||
elif self.mode == ImageMode.REPEAT_Y_FILL:
|
||||
if repeat_width != self.image.size[0] or repeat_height != self.image.size[1]:
|
||||
img_part = self.image.resize((repeat_width, repeat_height), reducing_gap=3.0)
|
||||
else:
|
||||
img_part = self._image
|
||||
img_part = self.image
|
||||
img = PilImage.new('RGBA', (width, height), (0,0,0,0))
|
||||
num_y = height // repeat_height + 1
|
||||
oy = repeat_offset_y % (repeat_height if repeat_offset_y >= 0 else -repeat_height)
|
||||
|
@ -246,19 +246,19 @@ class Image(Layout):
|
|||
img.paste(img_part, (0, i * repeat_height + oy))
|
||||
offset_y = 0
|
||||
|
||||
if self._position in (ImageAnchor.TOP_LEFT, ImageAnchor.MIDDLE_LEFT, ImageAnchor.BOTTOM_LEFT):
|
||||
if self.position in (ImageAnchor.TOP_LEFT, ImageAnchor.MIDDLE_LEFT, ImageAnchor.BOTTOM_LEFT):
|
||||
x = x1 + offset_x
|
||||
elif self._position in (ImageAnchor.TOP_CENTER, ImageAnchor.MIDDLE_CENTER, ImageAnchor.BOTTOM_CENTER):
|
||||
elif self.position in (ImageAnchor.TOP_CENTER, ImageAnchor.MIDDLE_CENTER, ImageAnchor.BOTTOM_CENTER):
|
||||
x = x1 + (width // 2) - img.size[0] // 2 + offset_x
|
||||
elif self._position in (ImageAnchor.TOP_RIGHT, ImageAnchor.MIDDLE_RIGHT, ImageAnchor.BOTTOM_RIGHT):
|
||||
elif self.position in (ImageAnchor.TOP_RIGHT, ImageAnchor.MIDDLE_RIGHT, ImageAnchor.BOTTOM_RIGHT):
|
||||
x = x1 + width - img.size[0] + offset_x
|
||||
else:
|
||||
raise Exception('invalid image position')
|
||||
if self._position in (ImageAnchor.TOP_LEFT, ImageAnchor.TOP_CENTER, ImageAnchor.TOP_RIGHT):
|
||||
if self.position in (ImageAnchor.TOP_LEFT, ImageAnchor.TOP_CENTER, ImageAnchor.TOP_RIGHT):
|
||||
y = y1 + offset_y
|
||||
elif self._position in (ImageAnchor.MIDDLE_LEFT, ImageAnchor.MIDDLE_CENTER, ImageAnchor.MIDDLE_RIGHT):
|
||||
elif self.position in (ImageAnchor.MIDDLE_LEFT, ImageAnchor.MIDDLE_CENTER, ImageAnchor.MIDDLE_RIGHT):
|
||||
y = y1 + (height // 2) - img.size[1] // 2 + offset_y
|
||||
elif self._position in (ImageAnchor.BOTTOM_LEFT, ImageAnchor.BOTTOM_CENTER, ImageAnchor.BOTTOM_RIGHT):
|
||||
elif self.position in (ImageAnchor.BOTTOM_LEFT, ImageAnchor.BOTTOM_CENTER, ImageAnchor.BOTTOM_RIGHT):
|
||||
y = y1 + height - img.size[1] + offset_y
|
||||
else:
|
||||
raise Exception('invalid image position')
|
||||
|
|
|
@ -2,7 +2,7 @@ from ..enums import FlexDirection, FlexWrap, FlexJustify, FlexAlignItems, FlexAl
|
|||
from .helpers import min_with_none, max_with_none
|
||||
|
||||
|
||||
class FlexLineItem():
|
||||
class FlexLineItem:
|
||||
def __init__(self, content, max_width, max_height, direction):
|
||||
self.__content = content
|
||||
self.__max_width = max_width
|
||||
|
@ -20,14 +20,14 @@ class FlexLineItem():
|
|||
|
||||
def base_size(self):
|
||||
if self.__direction in (FlexDirection.ROW, FlexDirection.ROW_REVERSE):
|
||||
if self.__content._width is not None:
|
||||
return self.__content._width
|
||||
if self.__content.width is not None:
|
||||
return self.__content.width
|
||||
else:
|
||||
return self.__content.get_ideal_outer_dimensions(available_width=self.__max_width,
|
||||
available_height=self.__max_height)[0]
|
||||
else:
|
||||
if self.__content._height is not None:
|
||||
return self.__content._height
|
||||
if self.__content.height is not None:
|
||||
return self.__content.height
|
||||
else:
|
||||
return self.__content.get_ideal_outer_dimensions(available_width=self.__max_width,
|
||||
available_height=self.__max_height)[1]
|
||||
|
@ -46,15 +46,15 @@ class FlexLineItem():
|
|||
|
||||
def max_main_size(self):
|
||||
if self.__direction in (FlexDirection.ROW, FlexDirection.ROW_REVERSE):
|
||||
return self.__content._max_width
|
||||
return self.__content.max_width
|
||||
else:
|
||||
return self.__content._max_height
|
||||
return self.__content.max_height
|
||||
|
||||
def max_cross_size(self):
|
||||
if self.__direction in (FlexDirection.ROW, FlexDirection.ROW_REVERSE):
|
||||
return self.__content._max_height
|
||||
return self.__content.max_height
|
||||
else:
|
||||
return self.__content._max_width
|
||||
return self.__content.max_width
|
||||
|
||||
def hypothetical_main_size(self):
|
||||
return min_with_none(self.max_main_size(), max_with_none(self.min_main_size(), self.base_size()))
|
||||
|
@ -81,10 +81,10 @@ class FlexLineItem():
|
|||
return self.__cross_pos
|
||||
|
||||
def grow_factor(self):
|
||||
return self.__content._flex_grow
|
||||
return self.__content.flex_grow
|
||||
|
||||
def shrink_factor(self):
|
||||
return self.__content._flex_shrink
|
||||
return self.__content.flex_shrink
|
||||
|
||||
def scaled_shrink_factor(self):
|
||||
return self.shrink_factor() * self.base_size()
|
||||
|
|
124
layout.py
124
layout.py
|
@ -32,68 +32,68 @@ class Layout:
|
|||
flex_shrink=0,
|
||||
debug_layout=False,
|
||||
):
|
||||
self._width = width
|
||||
self._height = height
|
||||
self._min_width = min_width
|
||||
self._min_height = min_height
|
||||
self._max_width = max_width
|
||||
self._max_height = max_height
|
||||
self._fg_color = fg_color
|
||||
self._bg_color = bg_color
|
||||
self._border_color = border_color
|
||||
self._border_width = border_width
|
||||
self._border_radius = border_radius
|
||||
self._padding = padding
|
||||
self._font = font
|
||||
self._overflow = overflow
|
||||
self._left = left
|
||||
self._top = top
|
||||
self._right = right
|
||||
self._bottom = bottom
|
||||
self._flex_grow = flex_grow
|
||||
self._flex_shrink = flex_shrink
|
||||
self._debug_layout = debug_layout
|
||||
self._container = None
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.min_width = min_width
|
||||
self.min_height = min_height
|
||||
self.max_width = max_width
|
||||
self.max_height = max_height
|
||||
self.fg_color = fg_color
|
||||
self.bg_color = bg_color
|
||||
self.border_color = border_color
|
||||
self.border_width = border_width
|
||||
self.border_radius = border_radius
|
||||
self.padding = padding
|
||||
self.font = font
|
||||
self.overflow = overflow
|
||||
self.left = left
|
||||
self.top = top
|
||||
self.right = right
|
||||
self.bottom = bottom
|
||||
self.flex_grow = flex_grow
|
||||
self.flex_shrink = flex_shrink
|
||||
self.debug_layout = debug_layout
|
||||
self.container = None
|
||||
|
||||
def complete_init(self, container):
|
||||
self._container = container
|
||||
for c in self._children():
|
||||
self.container = container
|
||||
for c in self.children():
|
||||
c.complete_init(self)
|
||||
|
||||
def _children(self):
|
||||
def children(self):
|
||||
return []
|
||||
|
||||
def get_document_size(self):
|
||||
if isinstance(self, layout.Document):
|
||||
return self._actual_size
|
||||
return self.actual_size
|
||||
else:
|
||||
return self._container.get_document_size()
|
||||
return self.container.get_document_size()
|
||||
|
||||
def get_fg_color(self):
|
||||
if self._fg_color is not None:
|
||||
return self._fg_color
|
||||
elif self._container is not None:
|
||||
return self._container.get_fg_color()
|
||||
if self.fg_color is not None:
|
||||
return self.fg_color
|
||||
elif self.container is not None:
|
||||
return self.container.get_fg_color()
|
||||
else:
|
||||
return None
|
||||
|
||||
def get_font(self):
|
||||
if self._font is not None:
|
||||
return self._font
|
||||
elif self._container is not None:
|
||||
return self._container.get_font()
|
||||
if self.font is not None:
|
||||
return self.font
|
||||
elif self.container is not None:
|
||||
return self.container.get_font()
|
||||
else:
|
||||
raise Exception('no font defined in {0}'.format(self.__class__))
|
||||
|
||||
def get_overflow(self):
|
||||
if self._overflow is not None:
|
||||
return self._overflow
|
||||
elif self._container is not None:
|
||||
return self._container.get_overflow()
|
||||
if self.overflow is not None:
|
||||
return self.overflow
|
||||
elif self.container is not None:
|
||||
return self.container.get_overflow()
|
||||
else:
|
||||
return None
|
||||
|
||||
def _get_tuple_property(self, name, default, allow_tuple=True):
|
||||
def get_tuple_property(self, name, default, allow_tuple=True):
|
||||
value = getattr(self, name)
|
||||
if isinstance(value, list) or (allow_tuple and isinstance(value, tuple)):
|
||||
if len(value) == 0:
|
||||
|
@ -111,33 +111,33 @@ class Layout:
|
|||
else:
|
||||
return value, value, value, value
|
||||
|
||||
def padding(self):
|
||||
return self._get_tuple_property('_padding', 0)
|
||||
def get_padding(self):
|
||||
return self.get_tuple_property('padding', 0)
|
||||
|
||||
def border_width(self):
|
||||
return self._get_tuple_property('_border_width', 0)
|
||||
def get_border_width(self):
|
||||
return self.get_tuple_property('border_width', 0)
|
||||
|
||||
def border_color(self):
|
||||
return self._get_tuple_property('_border_color', None, False)
|
||||
def get_border_color(self):
|
||||
return self.get_tuple_property('border_color', None, False)
|
||||
|
||||
def border_radius(self):
|
||||
return self._get_tuple_property('_border_radius', None)
|
||||
def get_border_radius(self):
|
||||
return self.get_tuple_property('border_radius', None)
|
||||
|
||||
def get_min_inner_width(self, max_height=None):
|
||||
return self._min_width
|
||||
return self.min_width
|
||||
|
||||
def get_min_inner_height(self, max_width=None):
|
||||
return self._min_height
|
||||
return self.min_height
|
||||
|
||||
def get_ideal_inner_dimensions(self, min_width=None, min_height=None, available_width=None, available_height=None):
|
||||
return self._width, self._height
|
||||
return self.width, self.height
|
||||
|
||||
def get_x_padding_border_size(self):
|
||||
border, padding = self.border_width(), self.padding()
|
||||
border, padding = self.get_border_width(), self.get_padding()
|
||||
return border[0] + border[2] + padding[0] + padding[2]
|
||||
|
||||
def get_y_padding_border_size(self):
|
||||
border, padding = self.border_width(), self.padding()
|
||||
border, padding = self.get_border_width(), self.get_padding()
|
||||
return border[1] + border[3] + padding[1] + padding[3]
|
||||
|
||||
def get_min_outer_width(self, max_outer_height=None):
|
||||
|
@ -208,7 +208,7 @@ class Layout:
|
|||
def make_border_inside_mask(self, rect, border_radii):
|
||||
mask = Image.new('1', self.get_document_size(), 0)
|
||||
x1, y1, x2, y2 = rect
|
||||
width_left, width_top, width_right, width_bottom = self.border_width()
|
||||
width_left, width_top, width_right, width_bottom = self.get_border_width()
|
||||
radius_top_left, radius_top_right, radius_bottom_right, radius_bottom_left = border_radii
|
||||
|
||||
inner_rect = (x1 + width_left, y1 + width_top, x2 - width_right, y2 - width_bottom)
|
||||
|
@ -236,8 +236,8 @@ class Layout:
|
|||
|
||||
def make_border_color_image(self, rect, border_radii):
|
||||
x1, y1, x2, y2 = rect
|
||||
color_left, color_top, color_right, color_bottom = self.border_color()
|
||||
width_left, width_top, width_right, width_bottom = self.border_width()
|
||||
color_left, color_top, color_right, color_bottom = self.get_border_color()
|
||||
width_left, width_top, width_right, width_bottom = self.get_border_width()
|
||||
radius_top_left, radius_top_right, radius_bottom_right, radius_bottom_left = border_radii
|
||||
|
||||
image = self.make_canvas()
|
||||
|
@ -297,7 +297,7 @@ class Layout:
|
|||
x1, y1, x2, y2 = rect
|
||||
width, height = x2 - x1 + 1, y2 - y1 + 1
|
||||
|
||||
border_radii = self.border_radius()
|
||||
border_radii = self.get_border_radius()
|
||||
radius_sum_top = border_radii[0] + border_radii[1]
|
||||
radius_sum_right = border_radii[1] + border_radii[2]
|
||||
radius_sum_bottom = border_radii[2] + border_radii[3]
|
||||
|
@ -354,8 +354,8 @@ class Layout:
|
|||
self.modify_inside_mask(inside_mask, rect)
|
||||
self.modify_border_mask(border_mask, rect)
|
||||
|
||||
if self._bg_color is not None:
|
||||
image.paste(self._bg_color, mask=outside_mask)
|
||||
if self.bg_color is not None:
|
||||
image.paste(self.bg_color, mask=outside_mask)
|
||||
self.render_after_background(image, rect)
|
||||
|
||||
border_color = self.make_border_color_image(rect, border_radii)
|
||||
|
@ -365,8 +365,8 @@ class Layout:
|
|||
image.alpha_composite(border_image)
|
||||
self.render_after_border(image, rect)
|
||||
|
||||
border_width = self.border_width()
|
||||
padding = self.padding()
|
||||
border_width = self.get_border_width()
|
||||
padding = self.get_padding()
|
||||
content_x1 = rect[0] + border_width[0] + padding[0]
|
||||
content_y1 = rect[1] + border_width[1] + padding[1]
|
||||
content_x2 = rect[2] - border_width[2] - padding[2]
|
||||
|
@ -380,7 +380,7 @@ class Layout:
|
|||
image.alpha_composite(content_image)
|
||||
self.render_after_content(image, rect)
|
||||
|
||||
if self._debug_layout:
|
||||
if self.debug_layout:
|
||||
dc = Image.new('RGBA', image.size, (0, 0, 0, 0))
|
||||
d = ImageDraw.Draw(dc)
|
||||
|
||||
|
|
|
@ -485,7 +485,11 @@ Where the image is anchored for positioning with `offset_x` and `offset_y`.
|
|||
|
||||
#### ImageAnchor.BOTTOM_RIGHT
|
||||
|
||||
####
|
||||
# custom layouts
|
||||
|
||||
A layout should extend the `Layout` class and implement the following methods:
|
||||
|
||||
|
||||
|
||||
# possible future features
|
||||
|
||||
|
|
96
text.py
96
text.py
|
@ -18,65 +18,65 @@ class Text(Layout):
|
|||
**kwargs
|
||||
):
|
||||
super().__init__(**kwargs)
|
||||
self._text_layouter = None
|
||||
self._text = text
|
||||
self._text_align = text_align
|
||||
self._vertical_text_align = vertical_text_align
|
||||
self._text_wrap = text_wrap
|
||||
self._line_spacing = line_spacing
|
||||
self.text_layouter = None
|
||||
self.text = text
|
||||
self.text_align = text_align
|
||||
self.vertical_text_align = vertical_text_align
|
||||
self.text_wrap = text_wrap
|
||||
self.line_spacing = line_spacing
|
||||
|
||||
def complete_init(self, container):
|
||||
super().complete_init(container)
|
||||
if self._is_empty():
|
||||
if self.is_empty():
|
||||
lines = []
|
||||
elif isinstance(self._text, list):
|
||||
lines = self._text
|
||||
elif isinstance(self.text, list):
|
||||
lines = self.text
|
||||
else:
|
||||
lines = self._text.splitlines()
|
||||
self._text_layouter = TextLayouter(lines=lines,
|
||||
align=self._text_align,
|
||||
vertical_align=self._vertical_text_align,
|
||||
wrap=self._text_wrap,
|
||||
lines = self.text.splitlines()
|
||||
self.text_layouter = TextLayouter(lines=lines,
|
||||
align=self.text_align,
|
||||
vertical_align=self.vertical_text_align,
|
||||
wrap=self.text_wrap,
|
||||
font=self.get_font(),
|
||||
line_height=self._get_line_height_with_spacing())
|
||||
line_height=self.get_line_height_with_spacing())
|
||||
|
||||
def _is_empty(self):
|
||||
return self._text is None or self._text == '' or (isinstance(self._text, list)
|
||||
and len(self._text) == 0)
|
||||
def is_empty(self):
|
||||
return self.text is None or self.text == '' or (isinstance(self.text, list)
|
||||
and len(self.text) == 0)
|
||||
|
||||
def get_min_inner_width(self, max_height=None):
|
||||
if self._is_empty():
|
||||
if self.is_empty():
|
||||
width = 0
|
||||
else:
|
||||
if max_height is not None:
|
||||
max_height += self._line_spacing
|
||||
width = self._text_layouter.get_dimensions(0, max_height)[0]
|
||||
return max_with_none(width, self._min_width)
|
||||
max_height += self.line_spacing
|
||||
width = self.text_layouter.get_dimensions(0, max_height)[0]
|
||||
return max_with_none(width, self.min_width)
|
||||
|
||||
def get_min_inner_height(self, max_width=None):
|
||||
if self._is_empty():
|
||||
if self.is_empty():
|
||||
height = 0
|
||||
else:
|
||||
# no spacing after the last line
|
||||
height = self._text_layouter.get_dimensions(max_width, 0)[1] - self._line_spacing
|
||||
return max_with_none(height, self._min_height)
|
||||
height = self.text_layouter.get_dimensions(max_width, 0)[1] - self.line_spacing
|
||||
return max_with_none(height, self.min_height)
|
||||
|
||||
def get_ideal_inner_dimensions(self, min_width=None, min_height=None, available_width=None, available_height=None):
|
||||
available_width = min_with_none(available_width, self._width)
|
||||
available_height = min_with_none(available_height, self._height)
|
||||
available_width = min_with_none(available_width, self.width)
|
||||
available_height = min_with_none(available_height, self.height)
|
||||
|
||||
width, height = self._text_layouter.get_dimensions(available_width, available_height)
|
||||
height -= self._line_spacing # no spacing after the last line
|
||||
width, height = self.text_layouter.get_dimensions(available_width, available_height)
|
||||
height -= self.line_spacing # no spacing after the last line
|
||||
|
||||
if self._width is not None:
|
||||
width = self._width
|
||||
if self._height is not None:
|
||||
height = self._height
|
||||
if self.width is not None:
|
||||
width = self.width
|
||||
if self.height is not None:
|
||||
height = self.height
|
||||
|
||||
width = max_with_none(width, self._min_width)
|
||||
height = max_with_none(height, self._min_height)
|
||||
width = min_with_none(width, self._max_width)
|
||||
height = min_with_none(height, self._max_height)
|
||||
width = max_with_none(width, self.min_width)
|
||||
height = max_with_none(height, self.min_height)
|
||||
width = min_with_none(width, self.max_width)
|
||||
height = min_with_none(height, self.max_height)
|
||||
|
||||
return width, height
|
||||
|
||||
|
@ -86,21 +86,21 @@ class Text(Layout):
|
|||
|
||||
x1, y1, x2, y2 = rect
|
||||
width, height = x2 - x1 + 1, y2 - y1 + 1
|
||||
if self._max_width is not None:
|
||||
width = min(width, self._max_width)
|
||||
if self._min_width is not None:
|
||||
width = max(width, self._min_width)
|
||||
if self._max_height is not None:
|
||||
height = min(height, self._max_height)
|
||||
if self._min_height is not None:
|
||||
height = max(height, self._min_height)
|
||||
if self.max_width is not None:
|
||||
width = min(width, self.max_width)
|
||||
if self.min_width is not None:
|
||||
width = max(width, self.min_width)
|
||||
if self.max_height is not None:
|
||||
height = min(height, self.max_height)
|
||||
if self.min_height is not None:
|
||||
height = max(height, self.min_height)
|
||||
|
||||
lines = self._text_layouter.get_lines(width, height)
|
||||
lines = self.text_layouter.get_lines(width, height)
|
||||
color = self.get_fg_color()
|
||||
font = self.get_font()
|
||||
for posx, posy, text in lines:
|
||||
d.text((x1 + posx, y1 + posy), text, font=font, fill=color)
|
||||
return image
|
||||
|
||||
def _get_line_height_with_spacing(self):
|
||||
return get_line_height(self.get_font()) + self._line_spacing
|
||||
def get_line_height_with_spacing(self):
|
||||
return get_line_height(self.get_font()) + self.line_spacing
|
||||
|
|
Loading…
Reference in a new issue