diff --git a/pype/scripts/slate/base.py b/pype/scripts/slate/base.py index 5ae7109ed4..bb5d127a2d 100644 --- a/pype/scripts/slate/base.py +++ b/pype/scripts/slate/base.py @@ -9,6 +9,15 @@ class BaseObj: obj_type = None available_parents = [] + all_style_keys = [ + "font-family", "font-size", "font-color", "font-bold", "font-italic", + "bg-color", "bg-alter-color", + "alignment-vertical", "alignment-horizontal", + "padding", "padding-left", "padding-right", + "padding-top", "padding-bottom", + "margin", "margin-left", "margin-right", + "margin-top", "margin-bottom", "width", "height" + ] def __init__(self, parent, style={}, name=None): if not self.obj_type: @@ -34,9 +43,7 @@ class BaseObj: self._style = style self.id = uuid4() - self.parent = parent self.name = name - self._style = style self.items = {} self.final_style = None @@ -51,18 +58,41 @@ class BaseObj: "font-italic": False, "bg-color": None, "bg-alter-color": None, - "alignment-vertical": "left", + "alignment-vertical": "right", "alignment-horizontal": "top", "padding": 0, "margin": 0, }, - "layer": {}, - "image": {}, - "text": {}, - "table": {}, - "table-item": {}, - "table-item-col-0": {}, - "#MyName": {} + "main_frame": { + "padding": 0, + "margin": 0 + }, + "layer": { + "padding": 0, + "margin": 0 + }, + "image": { + "padding": 0, + "margin": 0 + }, + "text": { + # "alignment-vertical": "left", + # "alignment-horizontal": "top", + "padding": 0, + "margin": 0 + }, + "table": { + "padding": 0, + "margin": 0 + }, + "table-item": { + "padding": 0, + "margin": 0 + }, + "__not_implemented__": { + "table-item-col-0": {}, + "#MyName": {} + } } return default_style_v1 @@ -97,10 +127,18 @@ class BaseObj: style = self.main_style for key, value in self._style.items(): - if key in style: - style[key].update(value) - else: + if key in self.all_style_keys: + # TODO which variant is right? style[self.obj_type][key] = value + # style["*"][key] = value + else: + if key not in style: + style[key] = {} + + if isinstance(style[key], dict): + style[key].update(value) + else: + style[key] = value if self.is_drawing: self.final_style = style @@ -110,9 +148,8 @@ class BaseObj: @property def style(self): style = self.full_style - style.update(self._style) - base = style.get("*", style.get("global")) or {} + base = style.get("*") or {} obj_specific = style.get(self.obj_type) or {} name_specific = {} if self.name: @@ -128,49 +165,121 @@ class BaseObj: return output - @property - def pos_x(self): + def item_pos_x(self): return 0 @property - def pos_y(self): + def item_pos_y(self): return 0 @property - def pos_start(self): - return (self.pos_x, self.pos_y) + def content_pos_x(self): + pos_x = self.item_pos_x + margin = self.style["margin"] + margin_left = self.style.get("margin-left") or margin + margin_right = self.style.get("margin-right") or margin + return pos_x + margin_left @property - def pos_end(self): - pos_x, pos_y = self.pos_start + def content_pos_y(self): + pos_y = self.item_pos_y + margin = self.style["margin"] + margin_top = self.style.get("margin-top") or margin + margin_bottom = self.style.get("margin-bottom") or margin + return pos_y + margin_top + + @property + def value_pos_x(self): + pos_x = self.content_pos_x * 1 + padding = self.style["padding"] + padding_left = self.style.get("padding-left") or padding + pos_x += padding_left + + return pos_x + + @property + def value_pos_y(self): + pos_y = self.content_pos_y * 1 + padding = self.style["padding"] + padding_top = self.style.get("padding-top") or padding + pos_y += padding_top + + return pos_y + + @property + def value_pos_start(self): + return (self.value_pos_x, self.value_pos_y) + + @property + def value_pos_end(self): + pos_x, pos_y = self.value_pos_start pos_x += self.width pos_y += self.height return (pos_x, pos_y) @property - def max_width(self): - return self.style.get("max-width") or (self.width * 1) + def content_pos_start(self): + return (self.content_pos_x, self.content_pos_y) @property - def max_height(self): - return self.style.get("max-height") or (self.height * 1) + def content_pos_end(self): + pos_x, pos_y = self.content_pos_start + pos_x += self.content_width + pos_y += self.content_height + return (pos_x, pos_y) @property - def max_content_width(self): - width = self.max_width + def value_width(self): + raise NotImplementedError( + "Attribute is not implemented <{}>".format( + self.__class__.__name__ + ) + ) + + @property + def value_height(self): + raise NotImplementedError( + "Attribute is not implemented for <{}>".format( + self.__class__.__name__ + ) + ) + + @property + def content_width(self): + width = self.value_width padding = self.style["padding"] padding_left = self.style.get("padding-left") or padding padding_right = self.style.get("padding-right") or padding - return (width - (padding_left + padding_right)) + return width + padding_left + padding_right @property - def max_content_height(self): - height = self.max_height + def content_height(self): + height = self.value_height padding = self.style["padding"] padding_top = self.style.get("padding-top") or padding padding_bottom = self.style.get("padding-bottom") or padding - return (height - (padding_top + padding_bottom)) + return height + padding_top + padding_bottom + + @property + def width(self): + width = self.content_width + + margin = self.style["margin"] + margin_left = self.style.get("margin-left") or margin + margin_right = self.style.get("margin-right") or margin + + return width + margin_left + margin_right + + @property + def height(self): + height = self.content_height + + margin = self.style["margin"] + margin_top = self.style.get("margin-top") or margin + margin_bottom = self.style.get("margin-bottom") or margin + + return height + margin_bottom + margin_top def add_item(self, item): self.items[item.id] = item @@ -187,11 +296,26 @@ class MainFrame(BaseObj): available_parents = [None] def __init__(self, width, height, *args, **kwargs): + kwargs["parent"] = None super(MainFrame, self).__init__(*args, **kwargs) self._width = width self._height = height self._is_drawing = False + @property + def value_width(self): + width = 0 + for item in self.items.values(): + width += item.width + return width + + @property + def value_height(self): + height = 0 + for item in self.items.values(): + height += item.height + return height + @property def width(self): return self._width @@ -226,19 +350,19 @@ class Layer(BaseObj): self._direction = direction @property - def pos_x(self): + def item_pos_x(self): if self.parent.obj_type == self.obj_type: - pos_x = self.parent.item_pos_x(self.id) + pos_x = self.parent.child_pos_x(self.id) else: - pos_x = self.parent.pos_x + pos_x = self.parent.value_pos_x return pos_x @property - def pos_y(self): + def item_pos_y(self): if self.parent.obj_type == self.obj_type: - pos_y = self.parent.item_pos_y(self.id) + pos_y = self.parent.child_pos_y(self.id) else: - pos_y = self.parent.pos_y + pos_y = self.parent.value_pos_y return pos_y @property @@ -250,30 +374,21 @@ class Layer(BaseObj): return 0 return self._direction - def item_pos_x(self, item_id): - pos_x = self.pos_x + def child_pos_x(self, item_id): + pos_x = self.value_pos_x - margin = self.style["margin"] - margin_left = self.style.get("margin-left") or margin - - pos_x += margin_left if self.direction != 0: for id, item in self.items.items(): - if id == item_id: + if item_id == id: break - pos_x += item.width + pos_x += item.height if item.obj_type != "image": pos_x += 1 - return pos_x - def item_pos_y(self, item_id): - pos_y = self.pos_y + def child_pos_y(self, item_id): + pos_y = self.value_pos_y - margin = self.style["margin"] - margin_top = self.style.get("margin-top") or margin - - pos_y += margin_top if self.direction != 1: for id, item in self.items.items(): if item_id == id: @@ -281,21 +396,15 @@ class Layer(BaseObj): pos_y += item.height if item.obj_type != "image": pos_y += 1 - return pos_y @property - def height(self): - margin = self.style["margin"] - margin_top = self.style.get("margin-top") or margin - margin_bottom = self.style.get("margin-bottom") or margin - - height = (margin_top + margin_bottom) + def value_height(self): + height = 0 for item in self.items.values(): if self.direction == 0: if height > item.height: continue - # times 1 because won't get object pointer but number height = item.height * 1 else: @@ -308,24 +417,19 @@ class Layer(BaseObj): return height @property - def width(self): - margin = self.style["margin"] - margin_left = self.style.get("margin-left") or margin - margin_right = self.style.get("margin-right") or margin - - width = (margin_left + margin_right) + def value_width(self): + width = 0 for item in self.items.values(): if self.direction == 0: if width > item.width: continue - # times 1 because won't get object pointer but number width = item.width * 1 else: width += item.width min_width = self.style.get("min-width") - if min_width > width: + if min_width and min_width > width: return min_width return width @@ -344,80 +448,12 @@ class BaseItem(BaseObj): super(BaseItem, self).__init__(*args, **kwargs) @property - def pos_x(self): - return self.parent.item_pos_x(self.id) + def item_pos_x(self): + return self.parent.child_pos_x(self.id) @property - def pos_y(self): - return self.parent.item_pos_y(self.id) - - @property - def content_pos_x(self): - padding = self.style["padding"] - padding_left = self.style.get("padding-left") or padding - - margin = self.style["margin"] - margin_left = self.style.get("margin-left") or margin - - return self.pos_x + margin_left + padding_left - - @property - def content_pos_y(self): - padding = self.style["padding"] - padding_top = self.style.get("padding-top") or padding - - margin = self.style["margin"] - margin_top = self.style.get("margin-top") or margin - - return self.pos_y + margin_top + padding_top - - @property - def content_width(self): - raise NotImplementedError( - "Attribute is not implemented" - ) - - @property - def content_height(self): - raise NotImplementedError( - "Attribute is not implemented" - ) - - @property - def width(self): - width = self.content_width - - padding = self.style["padding"] - padding_left = self.style.get("padding-left") or padding - padding_right = self.style.get("padding-right") or padding - - margin = self.style["margin"] - margin_left = self.style.get("margin-left") or margin - margin_right = self.style.get("margin-right") or margin - - return ( - width + - margin_left + margin_right + - padding_left + padding_right - ) - - @property - def height(self): - height = self.content_height - - padding = self.style["padding"] - padding_top = self.style.get("padding-top") or padding - padding_bottom = self.style.get("padding-bottom") or padding - - margin = self.style["margin"] - margin_top = self.style.get("margin-top") or margin - margin_bottom = self.style.get("margin-bottom") or margin - - return ( - height - + margin_bottom + margin_top - + padding_top + padding_bottom - ) + def item_pos_y(self): + return self.parent.child_pos_y(self.id) def add_item(self, *args, **kwargs): raise Exception("Can't add item to an item, use layers instead.") @@ -440,20 +476,20 @@ class ItemImage(BaseItem): def draw(self, image, drawer): paste_image = Image.open(self.image_path) paste_image = paste_image.resize( - (self.content_width, self.content_height), + (self.value_width, self.value_height), Image.ANTIALIAS ) image.paste( paste_image, - (self.content_pos_x, self.content_pos_y) + (self.value_pos_x, self.value_pos_y) ) @property - def content_width(self): + def value_width(self): return self.style.get("width") @property - def content_height(self): + def value_height(self): return self.style.get("height") @@ -467,35 +503,27 @@ class ItemText(BaseItem): def draw(self, image, drawer): bg_color = self.style["bg-color"] if bg_color and bg_color.lower() != "transparent": - padding = self.style["padding"] - - padding_left = self.style.get("padding-left") or padding - padding_right = self.style.get("padding-right") or padding - padding_top = self.style.get("padding-top") or padding - padding_bottom = self.style.get("padding-bottom") or padding # TODO border outline styles drawer.rectangle( - (self.pos_start, self.pos_end), + (self.content_pos_start, self.content_pos_end), fill=bg_color, outline=None ) - text_pos_start = (self.content_pos_x, self.content_pos_y) - font_color = self.style["font-color"] font_family = self.style["font-family"] font_size = self.style["font-size"] font = ImageFont.truetype(font_family, font_size) drawer.text( - text_pos_start, + self.value_pos_start, self.value, font=font, fill=font_color ) @property - def content_width(self): + def value_width(self): font_family = self.style["font-family"] font_size = self.style["font-size"] @@ -504,7 +532,7 @@ class ItemText(BaseItem): return width @property - def content_height(self): + def value_height(self): font_family = self.style["font-family"] font_size = self.style["font-size"] @@ -571,15 +599,9 @@ class ItemTable(BaseItem): def draw(self, image, drawer): bg_color = self.style["bg-color"] if bg_color and bg_color.lower() != "transparent": - padding = self.style["padding"] - - padding_left = self.style.get("padding-left") or padding - padding_right = self.style.get("padding-right") or padding - padding_top = self.style.get("padding-top") or padding - padding_bottom = self.style.get("padding-bottom") or padding # TODO border outline styles drawer.rectangle( - (self.pos_start, self.pos_end), + (self.content_pos_start, self.content_pos_end), fill=bg_color, outline=None ) @@ -588,7 +610,7 @@ class ItemTable(BaseItem): value.draw(image, drawer) @property - def content_width(self): + def value_width(self): row_heights, col_widths = self.size_values width = 0 for _width in col_widths: @@ -599,7 +621,7 @@ class ItemTable(BaseItem): return width @property - def content_height(self): + def value_height(self): row_heights, col_widths = self.size_values height = 0 for _height in row_heights: @@ -611,8 +633,8 @@ class ItemTable(BaseItem): def pos_info_by_cord(self, cord_x, cord_y): row_heights, col_widths = self.size_values - pos_x = self.pos_x - pos_y = self.pos_y + pos_x = self.value_pos_x + pos_y = self.value_pos_y width = 0 height = 0 for idx, value in enumerate(col_widths): @@ -627,12 +649,6 @@ class ItemTable(BaseItem): break pos_y += value - padding = self.style["padding"] - - padding_left = self.style.get("padding-left") or padding - padding_top = self.style.get("padding-top") or padding - pos_x += padding_left - pos_y += padding_top return (pos_x, pos_y, width, height) def filled_style(self, cord_x, cord_y): @@ -652,7 +668,7 @@ class TableField(BaseItem): self.value = value @property - def content_width(self): + def value_width(self): font_family = self.style["font-family"] font_size = self.style["font-size"] @@ -661,7 +677,7 @@ class TableField(BaseItem): return width @property - def content_height(self): + def value_height(self): font_family = self.style["font-family"] font_size = self.style["font-size"] @@ -669,15 +685,19 @@ class TableField(BaseItem): height = font.getsize(self.value)[1] + 1 return height - def content_pos_x(self, pos_x, width): - padding = self.style["padding"] - padding_left = self.style.get("padding-left") or padding - return pos_x + padding_left + @property + def item_pos_x(self): + pos_x, pos_y, width, height = ( + self.parent.pos_info_by_cord(self.cord_x, self.cord_y) + ) + return pos_x - def content_pos_y(self, pos_y, height): - padding = self.style["padding"] - padding_top = self.style.get("padding-top") or padding - return pos_y + padding_top + @property + def item_pos_y(self): + pos_x, pos_y, width, height = ( + self.parent.pos_info_by_cord(self.cord_x, self.cord_y) + ) + return pos_y def draw(self, image, drawer): pos_x, pos_y, width, height = ( @@ -700,18 +720,13 @@ class TableField(BaseItem): outline=None ) - text_pos_start = ( - self.content_pos_x(pos_x, width), - self.content_pos_y(pos_y, height) - ) - font_color = self.style["font-color"] font_family = self.style["font-family"] font_size = self.style["font-size"] font = ImageFont.truetype(font_family, font_size) drawer.text( - text_pos_start, + self.value_pos_start, self.value, font=font, fill=font_color