Hi @Marc
Have a look at the below and let me know if you think it’s too much or too little. Just a simple demo with three Unsync wrapped functions with non-blocking sleep calls manipulating panel objects.
If this is something you had in mind or not far off I can write a few sentences or something to give it some shape/form.
import panel as pn
import param
from unsync import unsync
from time import sleep as sl
from time import strftime as st
from panel.layout.gridstack import GridStack
CSS = """
#header {
background-color: rgba(255,255,255,0.33);
-ms-box-shadow: none !important;
-o-box-shadow: none !important;
-moz-box-shadow: none !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
}
.main-content {
transition: all 0.2s cubic-bezier(0.945, 0.020, 0.270, 0.665);
width: 100%;
height: calc(100vh - 76px);
padding: 10px;
}
body {
background: radial-gradient(#B8BEB4, #71685F);
}
.bk-root button.button {
width:65px;
height:55px;
position:absolute;
bottom:0px;
background-color: rgba(255,255,255,0.33);
color:#FFF;
border-radius:25px;
text-align:center;
box-shadow: 2px 2px 3px black;
transition: all 0.2s ease-in-out;
font-size:30px;
border-color: rgba(255,255,255,0.33);
}
.bk-root button.button:hover {
box-shadow: 4px 4px 3px black;
background-color: rgba(255,255,255,0.33);
transform: scale(1.05);
border-color: rgba(255,255,255,0.33);
cursor: pointer;
}
.bk-root button.button:active {
transform: translateY(1px);
}
"""
pn.config.sizing_mode = 'stretch_both'
pn.extension('gridstack', raw_css=[CSS])
playSVG="""<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 20 20" height="48px" viewBox="0 0 20 20" width="48px" fill="#000000"><g><rect fill="none" height="20" width="20"/></g><g><g><path d="M10,2c-4.42,0-8,3.58-8,8s3.58,8,8,8s8-3.58,8-8S14.42,2,10,2z M10,16.5c-3.58,0-6.5-2.92-6.5-6.5S6.42,3.5,10,3.5 s6.5,2.92,6.5,6.5S13.58,16.5,10,16.5z"/><polygon points="8,13.5 13.5,10 8,6.5"/></g></g></svg>
"""
pauseSVG="""<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 0 24 24" width="48px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>
"""
stopSVG="""<svg xmlns="http://www.w3.org/2000/svg" height="48px" viewBox="0 0 24 24" width="48px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M16 8v8H8V8h8m2-2H6v12h12V6z"/></svg>
"""
@unsync
def unsync_func1(name):
global stop_unsync1
print('unsync1', name)
if name == 'play':
stop_unsync1 = False
while 1:
if stop_unsync1 == True:
break
time_unsync1 = st("%H:%M:%S")
unsync_out1.object = f"<h1>{time_unsync1}</h1>"
sl(0.1)
# print('unsync1 running...')
elif name == 'pause':
stop_unsync1 = True
elif name == 'stop':
stop_unsync1 = True
unsync_out1.object = "<h1>00:00:00</h1>"
@unsync
def unsync_func2(name):
global stop_unsync2
print('unsync2', name)
if name == 'play':
stop_unsync2 = False
while 1:
if stop_unsync2 == True:
break
time_unsync2 = st("%H:%M:%S")
unsync_out2.object = f"<h1>{time_unsync2}</h1>"
sl(0.1)
# print('unsync2 running...')
elif name == 'pause':
stop_unsync2 = True
elif name == 'stop':
stop_unsync2 = True
unsync_out2.object = "<h1>00:00:00</h1>"
@unsync
def unsync_func3(name):
global stop_unsync3
print('unsync3', name)
if name == 'play':
stop_unsync3 = False
while 1:
if stop_unsync3 == True:
break
time_unsync3 = st("%H:%M:%S")
unsync_out3.object = f"<h1>{time_unsync3}</h1>"
sl(0.1)
# print('unsync3 running...')
elif name == 'pause':
stop_unsync3 = True
elif name == 'stop':
stop_unsync3 = True
unsync_out3.object = "<h1>00:00:00</h1>"
class SVGButton(pn.reactive.ReactiveHTML):
svg = param.String(doc="The SVG")
name = param.String(doc='Icon ID')
func_type = param.String(doc='Type of function')
_template = """<button class="button" type="button" id="button" onclick="${_do}">{{svg}}</button>"""
def _do(self, _):
if self.func_type == 'unsync1':
unsync_func1(self.name)
elif self.func_type == 'unsync2':
unsync_func2(self.name)
elif self.func_type == 'unsync3':
unsync_func3(self.name)
play_button_unsync1 = SVGButton(svg=playSVG, name='play', func_type='unsync1', height=60, width=60)
pause_button_unsync1 = SVGButton(svg=pauseSVG, name='pause', func_type='unsync1', height=60, width=60)
stop_button_unsync1 = SVGButton(svg=stopSVG, name='stop', func_type='unsync1', height=60, width=60)
unsync_buttons1 = pn.Row(play_button_unsync1, pause_button_unsync1, stop_button_unsync1)
play_button_unsync2 = SVGButton(svg=playSVG, name='play', func_type='unsync2', height=60, width=60)
pause_button_unsync2 = SVGButton(svg=pauseSVG, name='pause', func_type='unsync2', height=60, width=60)
stop_button_unsync2 = SVGButton(svg=stopSVG, name='stop', func_type='unsync2', height=60, width=60)
unsync_buttons2 = pn.Row(play_button_unsync2, pause_button_unsync2, stop_button_unsync2)
play_button_unsync3 = SVGButton(svg=playSVG, name='play', func_type='unsync3', height=60, width=60)
pause_button_unsync3 = SVGButton(svg=pauseSVG, name='pause', func_type='unsync3', height=60, width=60)
stop_button_unsync3 = SVGButton(svg=stopSVG, name='stop', func_type='unsync3', height=60, width=60)
unsync_buttons3 = pn.Row(play_button_unsync3, pause_button_unsync3, stop_button_unsync3)
unsync_out1 = pn.pane.HTML(object="""<h1>00:00:00</h1>""")
unsync_out2 = pn.pane.HTML(object="""<h1>00:00:00</h1>""")
unsync_out3 = pn.pane.HTML(object="""<h1>00:00:00</h1>""")
card_bg='rgba(255,255,255,0.33)'
gs = GridStack(sizing_mode='stretch_both', ncols=5, nrows=3, height=500, allow_resize=False, allow_drag=False)
gs[0:1, 0:5] = pn.Spacer(margin=5)
gs[1:2, 1:2] = pn.Card(unsync_out1, title='Unsync Function 1', background=card_bg, collapsible=False)
gs[1:2, 2:3] = pn.Card(unsync_out2, title='Unsync Function 2', background=card_bg, collapsible=False)
gs[1:2, 3:4] = pn.Card(unsync_out3, title='Unsync Function 3', background=card_bg, collapsible=False)
gs[2:3, 1:2] = unsync_buttons1
gs[2:3, 2:3] = unsync_buttons2
gs[2:3, 3:4] = unsync_buttons3
mt = pn.template.MaterialTemplate(
header_background='rgba(255,255,255,0.33)',
title='Unsync Demo',
main=[gs],
).show()