3030
3131import reacton .core
3232import solara
33- from solara .alias import rv
3433
3534import mesa .visualization .components .altair as components_altair
36- import mesa .visualization .components .matplotlib as components_matplotlib
3735from mesa .visualization .UserParam import Slider
3836from mesa .visualization .utils import force_update , update_counter
3937
4038if TYPE_CHECKING :
4139 from mesa .model import Model
4240
4341
44- # TODO: Turn this function into a Solara component once the current_step.value
45- # dependency is passed to measure()
46- def Card (
47- model , measures , agent_portrayal , space_drawer , dependencies , color , layout_type
48- ):
49- """Create a card component for visualizing model space or measures.
50-
51- Args:
52- model: The Mesa model instance
53- measures: List of measures to be plotted
54- agent_portrayal: Function to define agent appearance
55- space_drawer: Method to render agent space
56- dependencies: List of dependencies for updating the visualization
57- color: Background color of the card
58- layout_type: Type of layout (Space or Measure)
59-
60- Returns:
61- rv.Card: A card component containing the visualization
62- """
63- with rv .Card (
64- style_ = f"background-color: { color } ; width: 100%; height: 100%"
65- ) as main :
66- if "Space" in layout_type :
67- rv .CardTitle (children = ["Space" ])
68- if space_drawer == "default" :
69- # draw with the default implementation
70- components_matplotlib .SpaceMatplotlib (
71- model , agent_portrayal , dependencies = dependencies
72- )
73- elif space_drawer == "altair" :
74- components_altair .SpaceAltair (
75- model , agent_portrayal , dependencies = dependencies
76- )
77- elif space_drawer :
78- # if specified, draw agent space with an alternate renderer
79- space_drawer (model , agent_portrayal , dependencies = dependencies )
80- elif "Measure" in layout_type :
81- rv .CardTitle (children = ["Measure" ])
82- measure = measures [layout_type ["Measure" ]]
83- if callable (measure ):
84- # Is a custom object
85- measure (model )
86- else :
87- components_matplotlib .PlotMatplotlib (
88- model , measure , dependencies = dependencies
89- )
90- return main
91-
92-
9342@solara .component
9443def SolaraViz (
9544 model : Model | solara .Reactive [Model ],
@@ -207,10 +156,16 @@ def ComponentsView(
207156 model: Model instance to pass to each component
208157 """
209158 wrapped_components = [_wrap_component (component ) for component in components ]
210-
211- with solara .Column ():
212- for component in wrapped_components :
213- component (model )
159+ items = [component (model ) for component in wrapped_components ]
160+ grid_layout_initial = make_initial_grid_layout (num_components = len (items ))
161+ grid_layout , set_grid_layout = solara .use_state (grid_layout_initial )
162+ solara .GridDraggable (
163+ items = items ,
164+ grid_layout = grid_layout ,
165+ resizable = True ,
166+ draggable = True ,
167+ on_grid_layout = set_grid_layout ,
168+ )
214169
215170
216171JupyterViz = SolaraViz
@@ -448,11 +403,11 @@ def change_handler(value, name=name):
448403 raise ValueError (f"{ input_type } is not a supported input type" )
449404
450405
451- def make_initial_grid_layout (layout_types ):
406+ def make_initial_grid_layout (num_components ):
452407 """Create an initial grid layout for visualization components.
453408
454409 Args:
455- layout_types: List of layout types (Space or Measure)
410+ num_components: Number of components to display
456411
457412 Returns:
458413 list: Initial grid layout configuration
@@ -466,7 +421,7 @@ def make_initial_grid_layout(layout_types):
466421 "x" : 6 * (i % 2 ),
467422 "y" : 16 * (i - i % 2 ),
468423 }
469- for i in range (len ( layout_types ) )
424+ for i in range (num_components )
470425 ]
471426
472427
0 commit comments