Source code for Button

"""Button widget to call a python function when clicked."""
# Author(s): Davide.De-Marchi@ec.europa.eu
# Copyright © European Union 2022-2023
# 
# Licensed under the EUPL, Version 1.2 or as soon they will be approved by 
# the European Commission subsequent versions of the EUPL (the "Licence");
# 
# You may not use this work except in compliance with the Licence.
# 
# You may obtain a copy of the Licence at:
# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12

# Unless required by applicable law or agreed to in writing, software
# distributed under the Licence is distributed on an "AS IS"
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied.
# 
# See the Licence for the specific language governing permissions and
# limitations under the Licence.

import ipyvuetify as v

from vois.vuetify.utils.util import *
from typing import Callable, Any, Union, Optional


#######################################################################################################################
# Button class. On click python function called when clicked
# Uses settings font to display the button text and interactivity when hover
#######################################################################################################################
[docs] class Button(v.Html): """ Button widget to call a python function when clicked. Parameters ---------- text : str Test string to be displayed on the button widget on_click : function, optional Python function to call when the user clicks on the button. The function will receive as parameter the value of the argument (default is None) on_dblclick : function, optional Python function to call when the user double-clicks on the button. The function will receive as parameter the value of the argument (default is None) argument : any, optional Argument to be passed to the onclick function when user click on the label (default is None) width : int, optional Width of the button widget in pixels (default is 100) height : int, optional Height of the button widget in pixels (default is 36) selected : bool, optional Flag to show the button as selected (default is False) disabled : bool, optional Flag to show the button as disabled (default is False) tooltip : str, optional Tooltip text to show when the user hovers on the button (default is '') large : bool, optional Flag that sets the large version of the button (default is False) x_large : bool, optional Flag that sets the xlarge version of the button (default is False) small : bool, optional Flag that sets the small version of the button (default is False) x_small : bool, optional Flag that sets the xsmall version of the button (default is False) outlined : bool, optional Flag to show the button as outlined (default is False) text_weight : int, optional Weight of the text to be shown in the label (default is 500, Bold is any value greater or equal to 500) href : str, optional URL to open when the button is clicked (default is None) target : str, optional Designates the target attribute (where the URL page is opened, for instance: '_blank' to open it in a new browser tab). This should only be applied when using the href parameter (default is None) only_text : bool, optional If True, the button will contain only the text (default is False) text_color : str, optional Color used for the button text (default is None) icon: str, optional Name of the icon to display aside the text of the label (default is None) icon_large : bool, optional Flag that sets the large version of the icon (default is False) icon_small : bool, optional Flag that sets the small version of the icon (default is False) icon_left : bool, optional Flag that sets the position of the icon to the left of the text of the label (default is False) icon_color : str, optional Color of the icon (default is 'black' if settings.dark_mode is False and 'white if settings.dark_mode is True) auto_select : bool, optional If True, the button becomes selected when clicked (default is False) dark : bool, optional Flag to invert the text and backcolor (default is the value of settings.dark_mode) rounded : bool, optional Flag to display the button with rounded corners (default is the value of settings.button_rounded) tile : bool, optional Flag to remove the button small border (default is False) color_selected : str, optional Color used for the button when it is selected (default is settings.color_first) color_unselected : str, optional Color used for the button when it is not selected (default is settings.color_second) Note ---- All the icons from https://materialdesignicons.com/ site can be used, just by prepending 'mdi-' to their name. All the free icons from https://fontawesome.com/ site can be used, just by prepending 'fa-' to their name. Example ------- Creation and display of a some button widgets playing with the parameters:: from vois.vuetify import settings, Button def onclick(arg=None): if arg==1: b1.selected = not b1.selected if arg==2: b2.selected = not b2.selected else: b3.selected = not b3.selected b1 = Button('Test button 1', text_weight=300, on_click=onclick, argument=1, width=150, height=36, tooltip='Tooltip for button 1', selected=False, rounded=True, icon='mdi-car-light-high', iconColor='black') b2 = Button('Test button 2', text_weight=450, on_click=onclick, argument=2, width=150, height=48, tooltip='Tooltip for button 2', selected=True, rounded=False) b3 = Button('Test button 3', text_weight=450, on_click=onclick, argument=3, width=150, height=38, text_color=settings.color_first, tooltip='Tooltip for button 3', outlined=True, rounded=True) b4 = Button('Contacts', only_text=True, text_color=settings.color_first, width=150, height=28, href='https://ec.europa.eu/info/contact_en', target="_blank", tooltip='Open a URL') display(b1) display(b2) display(b3) display(b4) .. figure:: figures/button.png :scale: 100 % :alt: button widget Example of a 4 button widgets with different display modes. """ deprecation_alias = dict(onclick='on_click', xlarge='x_large', xsmall='x_small', textweight='text_weight', onlytext='only_text', textcolor='text_color', iconlarge='icon_large', iconsmall='icon_small', iconleft='icon_left', iconcolor='icon_color', autoselect='auto_select', colorselected='color_selected', colorunselected='color_unselected', ondblclick='on_dblclick') # Initialization @deprecated_init_alias(**deprecation_alias) def __init__(self, text: str, on_click: Optional[Union[Callable[[], None], Callable[[dict[str, Any]], None]]] = None, argument: Optional[Any] = None, # TODO forzare a dict per **kwargs width: int = 100, height: int = 36, selected: bool = False, disabled: bool = False, tooltip: str = '', large: bool = False, x_large: bool = False, small: bool = False, x_small: bool = False, outlined: bool = False, text_weight: int = 500, href: Optional[str] = None, target: Optional[str] = None, only_text: bool = False, text_color: Optional[str] = None, # TODO to be fixed. It is competitive with color_selected. Maybe text-color css? class_: str = "pa-0 ma-0", icon: Optional[str] = None, icon_large: bool = False, icon_small: bool = False, icon_left: bool = False, icon_color: str = None, auto_select: bool = False, dark: bool = None, rounded: bool = None, tile: bool = False, color_selected: str = None, color_unselected: str = None, on_dblclick: Optional[Union[Callable[[], None], Callable[[dict[str, Any]], None]]] = None, style_: str = '', **kwargs) -> None: from vois.vuetify import settings, fontsettings super().__init__(**kwargs) self.on_click = on_click self.on_dblclick = on_dblclick self.argument = argument self._selected = selected self._disabled = disabled self.auto_select = auto_select self._text = text self.icon_large = icon_large self.icon_small = icon_small self._color_selected = settings.color_first if color_selected is None else color_selected self._color_unselected = settings.color_second if color_unselected is None else color_unselected self._dark = settings.dark_mode if dark is None else dark self._rounded = settings.button_rounded if rounded is None else rounded if icon_color is None: self.icon_color = 'white' if settings.dark_mode else 'black' else: self.icon_color = icon_color self._icon = icon self.icon_distance = " ml-2" if text_color: color = text_color else: color = self._color_selected if self._selected else self._color_unselected if self._icon is None: childs = [self._text] else: if not self._text: self.icon_distance = "" elif icon_left: self.icon_distance = " mr-2" icn = v.Icon(class_="pa-0 ma-0 %s" % self.icon_distance, large=self.icon_large, small=self.icon_small, color=self.icon_color, children=[self._icon]) if icon_left: if not self._text: childs = [icn] else: childs = [icn, self._text] else: if not self._text: childs = [icn] else: childs = [self._text, icn] self.b = v.Btn(color=color, dark=self._dark, icon=only_text, depressed=True, outlined=outlined, large=large, x_large=x_large, small=small, x_small=x_small, disabled=disabled, width=width, min_width=width, height=height, min_height=height, href=href, target=target, tile=tile, children=childs, style_='font-family: %s; font-size: 17; font-weight: %d; text-transform: none; ' % ( fontsettings.font_name, text_weight) + style_, rounded=self._rounded) self.b.on_event('click', self.__internal_onclick) self.b.on_event('dblclick', self.__internal_ondblclick) if len(tooltip) > 0: self.b.v_on = 'tooltip.on' self.container = v.Container(class_=class_, children=[ v.Tooltip(color=settings.tooltip_backcolor, transition="scale-transition", bottom=True, v_slots=[{'name': 'activator', 'variable': 'tooltip', 'children': self.b}], children=[tooltip])]) self.tag = 'div' self.children = [self.container] for alias, new in self.deprecation_alias.items(): create_deprecated_alias(self, alias, new) def draw(self): warnings.warn('The "draw" method is deprecated, please just use the object widget itself.', category=DeprecationWarning, stacklevel=2) return self # Manage click event def __internal_onclick(self, widget=None, event=None, data=None): if self.on_click: if self.argument is not None: self.on_click(self.argument) # TODO switch to kwargs else: self.on_click() if self.auto_select: self.selected = True # Manage dblclick event def __internal_ondblclick(self, widget=None, event=None, data=None): if self.on_dblclick: if self.argument: # TODO usare argument diversi da onclick self.on_dblclick(self.argument) else: self.on_dblclick() @property def selected(self): """ Get/Set the selected state of the button widget. Returns -------- selected status : bool True if the button is selected, False otherwise Example ------- Programmatically select a button:: b.selected = True print(b.selected) """ return self._selected @selected.setter def selected(self, flag): self._selected = bool(flag) if self._selected: color = self._color_selected else: color = self._color_unselected self.b.color = color @property def disabled(self): """ Get/Set the disabled state of the button widget. Returns -------- disabled status : bool True if the button is disabled, False otherwise """ return self._disabled @disabled.setter def disabled(self, flag): self._disabled = bool(flag) self.b.disabled = self._disabled # Change the icon for the button
[docs] def setIcon(self, iconname): # TODO da fare come text """ Change the icon for the button Example ------- Creation of a button and programmatically change its icon:: from vois.vuetify import settings, button b = Button('Test button', text_weight=450, width=150, height=46, selected=True, rounded=True, icon='mdi-menu-open', icon_color='black', icon_large=True) display(b.draw()) b.setIcon('mdi-menu') """ warnings.warn("This method is deprecate used instead button_obj.icon = 'your_icon_name'", DeprecationWarning, stacklevel=2) self.icon = iconname
@property def icon(self): return self._icon @icon.setter def icon(self, icon_name: str): """ Change the icon for the button Example ------- Creation of a button and programmatically change its icon:: from vois.vuetify import settings, Button b = Button('Test button', text_weight=450, width=150, height=46, selected=True, rounded=True, icon='mdi-menu-open', icon_color='black', icon_large=True) display(b) b.icon = 'mdi-menu' """ self._icon = icon_name for item in self.b.children: if type(item).__name__ == 'Icon': newicon = v.Icon(class_="pa-0 ma-0 %s" % self.icon_distance, large=self.icon_large, small=self.icon_small, color=self.icon_color, children=[self._icon]) self.b.children = [newicon if x == item else x for x in self.b.children] break # Change the text for the button
[docs] def setText(self, newtext: str): """ Change the text for the button Example ------- Creation of a button and programmatically change its text:: from vois.vuetify import settings, Button b = Button('Test button', text_weight=450, width=250, height=46, selected=True, rounded=True) display(b.draw()) b.setText('New button text') """ warnings.warn("This method is deprecate used instead button_obj.text = 'your_new_text'", DeprecationWarning, stacklevel=2) self.text = newtext
@property def text(self): return self._text @text.setter def text(self, value): """ Change the text for the button Example ------- Creation of a button and programmatically change its text:: from vois.vuetify import settings, Button b = Button('Test button', text_weight=450, width=250, height=46, selected=True, rounded=True) display(b) b.text = 'New button text' """ tmp = self.b.children tmp[tmp.index(self._text)] = value self.b.children = [] self.b.children = tmp self._text = value @property def color_selected(self): """ Get/Set the color of the button when it is in the selected state. Returns -------- c : str widget color Example ------- Programmatically change the widget color:: s.color_selected = '#00FF00' print(s.color_selected) """ return self._color_selected @color_selected.setter def color_selected(self, color): self._color_selected = color if self._selected: self.b.color = self._color_selected @property def color_unselected(self): """ Get/Set the color of the button when it is in the unselected state. Returns -------- c : str widget color Example ------- Programmatically change the widget color:: s.color_unselected = '#00FF00' print(s.color_unselected) """ return self._color_selected @color_unselected.setter def color_unselected(self, color): self._color_unselected = color if not self._selected: self.b.color = self._color_unselected @property def dark(self): return self._dark @dark.setter def dark(self, flag): """ Change the dark mode for the button Example ------- Creation of a button and programmatically change its dark mode:: from vois.vuetify import settings, Button b = Button('Test button', text_weight=450, width=250, height=46, selected=True, rounded=True) display(b) b.dark = True """ self._dark = flag self.icon_color = 'black' if self._dark: self.icon_color = 'white' self.b.dark = self._dark for item in self.b.children: if type(item).__name__ == 'Icon': newicon = v.Icon(class_="pa-0 ma-0 %s" % self.icon_distance, large=self.icon_large, small=self.icon_small, color=self.icon_color, children=[self._icon]) self.b.children = [newicon if x == item else x for x in self.b.children] break @property def rounded(self): return self._dark @rounded.setter def rounded(self, flag): """ Change the rounded state for the button Example ------- Creation of a button and programmatically change its rounded state:: from vois.vuetify import settings, Button b = Button('Test button', text_weight=450, width=250, height=46, selected=True, rounded=True) display(b) b.rounded = False """ self._rounded = flag self.b.rounded = self._rounded