File Viewer

Download
from .vector_elements import Vector, Rectangle

TEXT_INPUT_ELEMENT_TYPES = {
    "TextArea": "Text",
    "TextBox": "Entry"
}
position_id_map ={}


class Button(Rectangle):
    def __init__(self, node, frame, image_path, *, id_):
        super().__init__(node, frame)
        self.image_path = image_path
        self.id_ = id_
        position_id_map[(self.x, self.y)] = self.id_

    def to_code(self):
        return f"""
button_image_{self.id_} = PhotoImage(
    file=relative_to_assets("{self.image_path}"))
button_{self.id_} = Button(
    image=button_image_{self.id_},
    borderwidth=0,
    highlightthickness=0,
    command=lambda: print("button_{self.id_} clicked"),
    relief="flat"
)
button_{self.id_}.place(
    x={self.x},
    y={self.y},
    width={self.width},
    height={self.height}
)
"""

#EXPERIMENTAL FEATURE
class ButtonHover(Rectangle):
    def __init__(self, node, frame, image_path):
        super().__init__(node, frame)
        self.image_path = image_path

        if((self.x, self.y) in position_id_map):
            self.id_ = position_id_map[(self.x, self.y)]
        else:
            print(
                f"`ButtonHover` element must be placed on top of Button element with the same position.\n"
                "`ButtonHover` element will not be rendered") 

    def to_code(self):
        if((self.x, self.y) in position_id_map):
            return f"""
button_image_hover_{self.id_} = PhotoImage(
    file=relative_to_assets("{self.image_path}"))

def button_{self.id_}_hover(e):
    button_{self.id_}.config(
        image=button_image_hover_{self.id_}
    )
def button_{self.id_}_leave(e):
    button_{self.id_}.config(
        image=button_image_{self.id_}
    )

button_{self.id_}.bind('<Enter>', button_{self.id_}_hover)
button_{self.id_}.bind('<Leave>', button_{self.id_}_leave)

"""
        else:
            return ""


class Text(Vector):
    def __init__(self, node, frame):
        super().__init__(node)

        self.x, self.y = self.position(frame)
        self.width, self.height = self.size()

        self.text_color = self.color()
        self.font, self.font_size = self.font_property()
        self.text = self.characters.replace("\n", "\\n")

    @property
    def characters(self) -> str:
        string: str = self.node.get("characters")
        text_case: str = self.style.get("textCase", "ORIGINAL")

        if text_case == "UPPER":
            string = string.upper()
        elif text_case == "LOWER":
            string = string.lower()
        elif text_case == "TITLE":
            string = string.title()

        return string

    @property
    def style(self):
        # TODO: Native conversion
        return self.node.get("style")

    @property
    def character_style_overrides(self):
        return self.node.get("characterStyleOverrides")

    @property
    def style_override_table(self):
        # TODO: Native conversion
        return self.node.get("styleOverrideTable")

    def font_property(self):
        style = self.node.get("style")

        font_name = style.get("fontPostScriptName")
        if font_name is None:
            font_name = style["fontFamily"]

        font_name = font_name.replace('-', ' ')
        font_size = style["fontSize"]
        return font_name, font_size

    def to_code(self):
        return f"""
canvas.create_text(
    {self.x},
    {self.y},
    anchor="nw",
    text="{self.text}",
    fill="{self.text_color}",
    font=("{self.font}", {int(self.font_size)} * -1)
)
"""


class Image(Vector):
    def __init__(self, node, frame, image_path, *, id_):
        super().__init__(node)

        self.x, self.y = self.position(frame)

        width, height = self.size()
        self.x += width // 2
        self.y += height // 2

        self.image_path = image_path
        self.id_ = id_

    def to_code(self):
        return f"""
image_image_{self.id_} = PhotoImage(
    file=relative_to_assets("{self.image_path}"))
image_{self.id_} = canvas.create_image(
    {self.x},
    {self.y},
    image=image_image_{self.id_}
)
"""


class TextEntry(Vector):
    def __init__(self, node, frame, image_path, *, id_):
        super().__init__(node)

        self.id_ = id_
        self.image_path = image_path

        self.x, self.y = self.position(frame)
        width, height = self.size()
        self.x += width / 2
        self.y += height / 2

        self.bg_color = self.color()

        corner_radius = self.get("cornerRadius", 0)
        corner_radius = min(corner_radius, height / 2)
        self.entry_width = width - (corner_radius * 2)
        self.entry_height = height - 2

        self.entry_x, self.entry_y = self.position(frame)
        self.entry_x += corner_radius

        self.entry_type = TEXT_INPUT_ELEMENT_TYPES.get(self.get("name"))

    def to_code(self):
        return f"""
entry_image_{self.id_} = PhotoImage(
    file=relative_to_assets("{self.image_path}"))
entry_bg_{self.id_} = canvas.create_image(
    {self.x},
    {self.y},
    image=entry_image_{self.id_}
)
entry_{self.id_} = {self.entry_type}(
    bd=0,
    bg="{self.bg_color}",
    fg="#000716",
    highlightthickness=0
)
entry_{self.id_}.place(
    x={self.entry_x},
    y={self.entry_y},
    width={self.entry_width},
    height={self.entry_height}
)
"""