#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()