# default_exp custom_input.buttons

Image buttonΒΆ

#export

class ImageButton(VBox, HasTraits):
    """
    Represents simple image with label and toggle button functionality.

    # Class methods

    - clear(): Clear image infos

    - on_click(p_function): Handle click events

    # Class methods

    - clear(): Clear image infos

    - on_click(p_function): Handle click events

    - reset_callbacks(): Reset event callbacks
    """
    debug_output = Output(layout={'border': '1px solid black'})
    active = Bool()
    image_path = Unicode()
    label_value = Unicode()

    def __init__(self, setting: ImageButtonSetting):

        self.setting = setting
        self.image = Image(
            layout=Layout(display='flex',
                          justify_content='center',
                          align_items='center',
                          align_content='center',
                          width=setting.image_width,
                          margin='0 0 0 0',
                          height=setting.image_height),
        )

        if self.setting.display_label:  # both image and label
            self.setting.label = HTML(
                value='?',
                layout=Layout(display='flex',
                              justify_content='center',
                              align_items='center',
                              align_content='center'),
            )
        else:  # no label (capture image case)
            self.im_name = self.setting.im_name
            self.im_index = self.setting.im_index
            self.image.layout.border = 'solid 1px gray'
            self.image.layout.object_fit = 'contain'
            self.image.margin = '0 0 0 0'
            self.image.layout.overflow = 'hidden'

        super().__init__(layout=Layout(align_items='center',
                                       margin='3px',
                                       overflow='hidden',
                                       padding='2px'))
        if not setting.im_path:
            self.clear()

        self.d = Event(source=self, watched_events=['click'])

    @observe('image_path')
    def _read_image(self, change=None):
        new_path = change['new']
        if new_path:
            self.image.value = open(new_path, "rb").read()
            if not self.children:
                self.children = (self.image,)
                if self.setting.display_label:
                    self.children += (self.setting.label,)
        else:
            #do not display image widget
            self.children = tuple()

    @observe('label_value')
    def _read_label(self, change=None):
        new_label = change['new']

        if isinstance(self.setting.label, HTML):
            self.setting.label.value = new_label
        else:
            self.setting.label = new_label

    def clear(self):
        if isinstance(self.setting.label, HTML):
            self.setting.label.value = ''
        else:
            self.setting.label = ''
        self.image_path = ''
        self.active = False

    @observe('active')
    def mark(self, ev):
        # pad to compensate self size with border
        if self.active:
            active_color = '#f7f01e'
            padding = '0px'
            if self.setting.display_label:
                self.layout.border = f'solid 2px {active_color}'
                self.layout.padding = padding
            else:
                self.image.layout.border = f'solid 3px {active_color}'
                self.image.layout.padding = padding
        else:
            if self.setting.display_label:
                self.layout.border = 'none'
                self.layout.padding = '2px'
            else:
                self.image.layout.border = 'solid 1px gray'

    def __eq__(self, other):
        equals = [
            other.image_path == self.image_path,
            other.label_value == self.label_value,
            other.active == self.active,
        ]

        return all(equals)

    def update(self, other):
        if self != other:
            self.image_path = other.image_path
            self.label_value = other.label_value
            self.active = other.active

    @property
    def value(self):
        return Path(self.image_path).name

    @debug_output.capture(clear_output=False)
    def on_click(self, cb):
        self.d.on_dom_event(cb)

    def reset_callbacks(self):
        self.d.reset_callbacks()