The list widget for magicgui/magicfactory does not inherit layout from top level
Describe the bug
If create magicgui widget with a vertical layout, the list widget still have horizontal layout.
It led to horizontal stretching of widgets.
To Reproduce
Use function
def combine_channels(channels: list['napari.layers.Image'], mode: CombineMode) -> 'napari.types.LayerDataTuple':
pass
Expected behavior
New elements should be added in the same layout as main widget.
Screenshots
Environment (please complete the following information):
- magicgui version 0.6.1
I have opened this issue to discuss how to solve this before open PR.
cc @hanjinliu, could you have a look?
Hi @Czaki ,
this is not a bug. The layout of a ListEdit is independent of the layout of the parent Container, because they are separate widgets. The default layout of ListEdit is horizontal.
As other widgets, you can configure the layout using Annotated.
@magicgui
def combine_channels(
channels: Annotated[list['napari.layers.Image'], {"layout": "vertical"}],
mode: CombineMode,
) -> 'napari.types.LayerDataTuple':
pass
I know that I could change it using annotation. I only claim that it is incorrect behavior to always set the layout to horizontal, not depending on the layout of main widget.
Especially when using magic_factory I could spawn one vertical and one horizontal widget. But could provide only one annotation.
Switching layout depending on the parent widget confuses the current implementation of magicgui a lot. When the annotation list[T] is to be converted in to a widget, it has to know the layout of the destination parent widget. However, at the time the ListEdit is built, it does not have the destination widget as the parent - this means that we cannot assign layout=None for the default behavior. Besides, the layout of containers cannot be changed after construction. The only way to allow the automatic determination of the layout is to add a if-else statement inside magicgui() that checks the incoming type annotation and determine whether to update the widget options. This implementation will cause inconsistency between @magicgui method and the "direct" method of widget construction - if one manually created a ListEdit and append it to a Container, its behavior may differ from the result of @magicgui.
Eitherway, I don't think there's any "correct" way to say which layout is better. I agree that in your example the layout should be vertical, but there are a lot of different use cases of ListEdit. For example, the sigma parameter of the n-D Gaussian filter accepts either a scalar or an array that matches the number of dimensions. Because a FloatEdit is small, using horizontal layout is more readable in this case. In my opinion, if one wants some rule to automate how to set layout, the rule should be explicitly defined by themselves.
I do not mean to do it in any container. I mean to do it in function that uses magicgui or magic_factory decorator. We know the layout of parents in such a situation.