Skip to content

Side Icon (Modified)

Based on the original IconSide class

class IconSide(Icon):  # modified Representation IconSide class 
    def __init__(self, config: dict, button: "Button"):
        config['icon-color'] = config['side'].get("icon-color", button.get_attribute("default-icon-color"))
        Icon.__init__(self, config=config, button=button)

        self.side = config.get("side")  # multi-labels
        self.centers = self.side.get("centers", [43, 150, 227])  # type: ignore
        self.labels: str | None = self.side.get("labels")  # type: ignore
        self.label_position = config.get("label-position", "cm")  # "centered" on middle of side image

    def get_datarefs(self):
        datarefs = []
        for label in self.labels:
            drefs = self.button.scan_datarefs(label)
            if len(drefs) > 0:
                datarefs = datarefs + drefs
        return datarefs

    # def get_datarefs(self):
    #     if self.datarefs is None:
    #         self.datarefs = []
    #         if self.labels is not None:
    #             for label in self.labels:
    #                 dref = label.get('dataref')
    #                 if dref is not None:
    #                     logger.debug(f"button {self.button_name()}: added label dataref {dref}")
    #                     self.datarefs.append(dref)
    #     return self.datarefs

    def is_valid(self):
        if self.button.index not in ["left", "right"]:
            logger.debug(f"button {self.button_name()}: {type(self).__name__}: not a valid index {self.button.index}")
            return False
        return super().is_valid()

    def get_image_for_icon(self):
        """
        Helper function to get button image and overlay label on top of it for SIDE keys (60x270).
        Side keys can have 3 labels placed in front of each knob.
        (Currently those labels are static only. Working to make them dynamic.)
        """
        image = super().get_image_for_icon()

        if image is None:
            return None

        draw = None

        if self.labels is not None:
            image = image.copy()  # we will add text over it
            draw = ImageDraw.Draw(image)
            inside = round(0.04 * image.width + 0.5)
            vheight = 38 - inside

            vcenter = [35, 124, 213]  # this determines the number of acceptable labels, organized vertically
            cnt = self.side.get("centers")

            if cnt is not None:
                vcenter = [round(270 * i / 100, 0) for i in convert_color(cnt)]  # !

            li = 0
            for label in self.labels:
                txt = label.get("label")

                get_text = self.button.get_text(label, root="text")

                if li >= len(vcenter) or txt is None:
                    continue

                txto = get_text

                lfont = label.get("label-font", self.label_font)
                lsize = label.get("label-size", self.label_size)
                font = self.get_font(lfont, lsize)

                # Horizontal centering is not an issue...
                label_position = label.get("label-position", self.label_position)
                w = image.width / 2
                p = "m"
                a = "center"
                if label_position == "l":
                    w = inside
                    p = "l"
                    a = "left"
                elif label_position == "r":
                    w = image.width - inside
                    p = "r"
                    a = "right"
                # Vertical centering is black magic...
                h = vcenter[li] - lsize / 2
                if label_position[1] == "t":
                    h = vcenter[li] - vheight
                elif label_position[1] == "b":
                    h = vcenter[li] + vheight - lsize

                draw.multiline_text(
                    (w, h), text=txt, font=font, anchor=p + "m", align=a, fill=label.get("label-color", self.label_color)  # (image.width / 2, 15)
                )

                # Text below LABEL
                tfont = label.get("text-font")
                tsize = label.get("text-size")
                tfont = self.get_font(tfont, tsize)

                text_position = h + lsize + 5  # Adjust based on your needs, adding lsize for simplicity
                draw.text(
                    (w, text_position), text=txto, font=tfont, anchor=p + "m", align=a, fill=label.get("text-color")
                )

                li = li + 1
        return image

    def describe(self):
        return "The representation produces an icon with optional label overlay for larger side buttons on LoupedeckLive."