@@ -186,9 +186,10 @@ def listen_setting_changes(view):
186186
187187class PanelMainWindow :
188188
189- def __init__ (self , controller , layout_preset = None ):
189+ def __init__ (self , controller , layout_preset = None , layout = None ):
190190 self .controller = controller
191191 self .layout_preset = layout_preset
192+ self .layout = layout
192193 self .verbose = controller .verbose
193194
194195 self .make_views ()
@@ -251,7 +252,7 @@ def create_main_layout(self):
251252
252253 pn .extension ("gridstack" )
253254
254- preset = get_layout_description (self .layout_preset )
255+ preset = get_layout_description (self .layout_preset , self . layout )
255256
256257 layout_zone = {}
257258 for zone , view_names in preset .items ():
@@ -359,19 +360,89 @@ def update_visibility(self, event):
359360 view .notify_active_view_updated ()
360361
361362
363+ def get_local_ip ():
364+ """
365+ Get the local IP address of the machine.
366+ """
367+ import socket
368+ s = socket .socket (socket .AF_INET , socket .SOCK_DGRAM )
369+ try :
370+ # Doesn't actually need to connect
371+ s .connect (('10.255.255.255' , 1 ))
372+ ip = s .getsockname ()[0 ]
373+ except Exception :
374+ ip = '127.0.0.1'
375+ finally :
376+ s .close ()
377+ return ip
378+
379+ def find_free_port ():
380+ """
381+ Find a free port on the local machine.
382+ This is useful for starting a server without specifying a port.
362383
363- def start_server (mainwindow , address = "localhost" , port = 0 ):
384+ Returns
385+ -------
386+ int
387+ A free port number.
388+ """
389+ import socket
390+ with socket .socket (socket .AF_INET , socket .SOCK_STREAM ) as s :
391+ s .bind (('' , 0 )) # Bind to a free port assigned by the OS
392+ return s .getsockname ()[1 ]
364393
365- pn .config .sizing_mode = "stretch_width"
394+ def start_server (window_or_dict , address = "localhost" , port = 0 , ** panel_kwargs ):
395+ """
396+ Start a Panel server with the main window layout.
397+
398+ Parameters
399+ ----------
400+ window_or_dict : Panel window or dict
401+ The main window instance containing the layout to serve or a dictionary of
402+ windows to serve. If a dictionary is provided, it should contain the names
403+ of the views as keys and their corresponding Panel objects as values.
404+ address : str, optional
405+ The address to bind the server to. Defaults to "localhost".
406+ If "auto-ip" is specified, it will use the local IP address.
407+ port : int, optional
408+ The port to bind the server to. If 0, a free port will be found
409+ automatically. Defaults to 0.
410+ panel_kwargs : dict, optional
411+ Additional keyword arguments to pass to the Panel server.
412+ These can include options like `show`, `start`, `dev`, `autoreload`,
413+ and `websocket_origin`.
414+ """
415+ if port == 0 :
416+ port = find_free_port ()
417+ print (f"Found available port: { port } " )
366418
367- # mainwindow.main_layout.servable()
368- # TODO alessio : find automatically a port when port = 0
419+ if address == "auto-ip" :
420+ address = get_local_ip ()
369421
370422 if address != "localhost" :
371423 websocket_origin = f"{ address } :{ port } "
372424 else :
373425 websocket_origin = None
374-
375- server = pn .serve ({"/" : mainwindow .main_layout }, address = address , port = port ,
376- show = False , start = True , dev = True , autoreload = True ,websocket_origin = websocket_origin ,
377- title = "SpikeInterface GUI" )
426+
427+ dev = panel_kwargs .get ("dev" , False )
428+ autoreload = panel_kwargs .get ("autoreload" , False )
429+ start = panel_kwargs .get ("start" , True )
430+ show = panel_kwargs .get ("show" , True )
431+ verbose = panel_kwargs .get ("verbose" , True )
432+
433+ if not isinstance (window_or_dict , dict ):
434+ # If a single window is provided, convert it to a dictionary
435+ mainwindow = window_or_dict
436+ mainwindow .main_layout = mainwindow .main_layout if hasattr (mainwindow , 'main_layout' ) else mainwindow .layout
437+ window_dict = {"/" : mainwindow .main_layout }
438+ else :
439+ # If a dictionary is provided, use it directly
440+ window_dict = window_or_dict
441+
442+ server = pn .serve (
443+ window_dict , address = address , port = port ,
444+ show = show , start = start , dev = dev , autoreload = autoreload ,
445+ websocket_origin = websocket_origin , verbose = verbose ,
446+ title = "SpikeInterface GUI"
447+ )
448+ return server , address , port , websocket_origin
0 commit comments