"""Floating-action-button to be displayed in absolute mode on the page. It will display a menu when hovered."""
# 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 ipywidgets import HTML, widgets, Layout
from IPython.display import display
try:
from . import settings
from . import fontsettings
from . import button
from . import label
from . import tooltip
except:
import settings
import fontsettings
import button
import label
import tooltip
#########################################################################################################################################
# Class to manage a customizable FAB menu
#########################################################################################################################################
[docs]class fab():
"""
Floating-action-button to be displayed in absolute mode on the page. It will display a menu when hovered.
Parameters
----------
left : int or string, optional
Absolute left position of the button (example: '800px' or '90%' or 750)
top : int or string, optional
Absolute top position of the button (example: '100px' or '10%' or 120)
items : list of strings, optional
Strings to be displayed as text of the options (default is [])
onclick : list of function, optional
Python functions to call when the user clicks on one of the items. One function for each of the items (default is [])
tooltipitems : list of strings, optional
Tooltip text for the items (default is [])
iconsmall : bool, optional
Flag to display the icon in small dimension (default is True)
menumode : bool, optional
Flag to display the options as dropdown menu. If False, the items are displayed as horizontally displaced toggle buttons (default is True)
width : int, optional
Width in pixel of the toggle buttons when menumode is False (default is 200)
height : int, optional
Height in pixel of the toggle buttons when menumode is False (default is 36)
textcolor : str, optional
Color to be used for the text of the buttons when menumode is False (default is None)
selected : bool, optional
If True the buttons have the settings.color_first as background (default is False)
disabled : bool, optional
If True the buttons are disabled (default is False)
dark : bool, optional
Flag that controls the color of the text in foreground (if True, the text will be displayed in white, elsewhere in black)
large : bool, optional
Flag that displays the fab button larger
small : bool, optional
Flag that displays the fab button smaller
xsmall : bool, optional
Flag that displays the fab button extra smaller
outlined : bool, optional
Flag that displays the fab button outlined
textweight : int, optional
Weight of the text to be shown in the label (default is 500, Bold is any value greater or equal to 500)
zindex : int, optional
Z-index of the fab button (default is 9999)
output : ipywidgets.Output, optional
Output widget on which the widget has to be displayed
Example
-------
Creation and display of two fab widgets for the selection among 3 options::
from vois.vuetify import fab
from ipywidgets import widgets
from IPython.display import display
output = widgets.Output()
display(output)
def on1():
with output:
print('selected 1')
def on2():
with output:
print('selected 2')
def on3():
with output:
print('selected 3')
b1 = fab.fab(left='70%', top='150px',
items=['Option 1', 'Option 2', 'Option 3'],
tooltipitems=['Tooltip for Option 1'],
onclick=[on1,on2,on3], menumode=True,
width=180, selected=True,
dark=True, zindex=100, output=output)
b2 = fab.fab(left='70%', top='250px',
items=['Option 1', 'Option 2', 'Option 3'],
tooltipitems=['Tooltip for Option 1'],
onclick=[on1,on2,on3], menumode=False,
width=180, selected=True,
dark=True, zindex=100, output=output)
b1.seticon('mdi-arrow-left-bold')
b2.seticon('mdi-arrow-left',1)
.. figure:: figures/fab.png
:scale: 100 %
:alt: fab widget
Fab widget for selecting alternative options using a menu.
.. figure:: figures/fab2.png
:scale: 100 %
:alt: fab widget as toggle buttons
Fab widget for selecting alternative options using toggle buttons.
"""
# Initialization
def __init__(self, left=100, top=100, items=[], onclick=[], icon='mdi-arrow-down-thick', tooltipitems=[], iconsmall=True, menumode=True,
width=200, height=36, textcolor=None, selected=False, disabled=False,
dark=settings.dark_mode, large=False, small=False, xsmall=False, outlined=False, textweight=500, zindex=9999,
output=None):
# Positioning
self.left = left
self.top = top
self.zindex = zindex
# Callback functions to call
self.onclick = onclick
self.menumode = menumode
self.width = width
self.nav = None
self.iconsmall = iconsmall
self.iconcolor = settings.textcolor_notdark
if dark: self.iconcolor = settings.textcolor_dark
if self.menumode:
# Strings for the items to add to the menu
self.items = items
# Items in the menu
self.listitems = []
i = 0
for item in items:
li = v.ListItem(children=[item])
li.on_event( 'click', self.__on_item_clicked)
if type(tooltipitems) is list and i < len(tooltipitems):
li = tooltip.tooltip(tooltipitems[i],li)
self.listitems.append(li)
i += 1
# Creation of the menu
self.button = v.Btn(v_on='menuData.on', color=settings.color_first, fab=True, dark=settings.dark_mode, depressed=True,
x_small=True, disabled=False, width=40, height=40, rounded=True,
children=[v.Icon(small=self.iconsmall, color=self.iconcolor, children=[str(icon)])])
self.menu = v.Menu(offset_y=True, open_on_hover=True, dense=True, v_slots=[{
'name': 'activator',
'variable': 'menuData',
'children': self.button,
}],
children=[v.List(children=self.listitems)] )
else:
# Strings for the buttons
self.items = items
if not textcolor is None: color = textcolor
else:
if selected: color = settings.color_first
else: color = settings.color_second
# Buttons
self.listitems = []
self.buttons = []
i = 0
for item in items:
content = [item]
if type(icon) is list and i < len(icon):
content.append(v.Icon(small=self.iconsmall, color=self.iconcolor, children=[icon[i]]))
b = v.Btn(color=color, dark=dark, icon=False, depressed=True, outlined=outlined, large=large, small=small, x_small=xsmall,
disabled=disabled, width=width-38, height=height, fab=True,
children=content, style_='font-family: %s; font-size: 17; font-weight: %d; text-transform: none' % (fontsettings.font_name, textweight), rounded=True)
b.on_event( 'click', self.__on_item_clicked)
self.buttons.append(b)
if type(tooltipitems) is list and i < len(tooltipitems):
bt = tooltip.tooltip(tooltipitems[i],b)
else:
bt = b
self.listitems.append(bt)
i += 1
# Display of the panel
if not output is None:
with output:
self.show(True)
# Manage click menu item
def __on_item_clicked(self, widget=None, event=None, data=None):
txt = widget.children[0]
if txt in self.items:
index = self.items.index(txt)
if index >= 0 and index < len(self.onclick):
self.onclick[index]()
# Set the icon of one of the buttons
[docs] def seticon(self, iconname, index=0):
"""Set a different icon for the fab button"""
if self.menumode:
self.button.children = [v.Icon(small=self.iconsmall, color=self.iconcolor, children=[str(iconname)])]
else:
if index >= 0 and index < len(self.buttons):
self.buttons[index].children = [self.buttons[index].children[0], v.Icon(small=self.iconsmall, color=self.iconcolor, children=[str(iconname)])]
# Set the tooltip of one of the buttons (only if tooltip is already present and not in menumode!)
# Display/Hide the fab button
[docs] def show(self, flag=True):
"""Show/hide the fab button"""
if flag:
if self.menumode:
self.nav = v.NavigationDrawer(stateless=True, permanent=True, floating=True, fixed=True, left=True, color="transparent",
width="'100px'", height="'100px'",
style_="left:%s; top:%s; z-index:%d;" % (self.left,self.top,self.zindex), class_="pa-0 ma-0", children=[self.menu])
else:
# Add an element between any element of a list !!!
def intersperse(lst, item):
result = [item] * (len(lst) * 2 - 1)
result[0::2] = lst
return result
#buttons = intersperse(self.listitems, label.label('').draw())
buttons = self.listitems
if len(self.listitems) > 1: w = len(self.listitems)*(self.width - 30)
else: w = self.width
r = v.Row(no_gutters=True, justify="space-between", children=buttons)
self.nav = v.NavigationDrawer(stateless=True, permanent=True, floating=True, fixed=True, left=True, color="transparent",
width='%dpx'%w, height='100px',
style_="left:%s; top:%s; z-index:%d;" % (self.left,self.top,self.zindex), class_="pa-0 ma-0", children=[r])
display(self.nav)
else:
if not self.nav is None:
self.nav.close()
# Close/hide the fab button
[docs] def close(self):
"""Close/hide the fab button"""
if not self.nav is None:
self.nav.close()