(widgets-contribution-guide)=
## Widgets

Widget plugins allow developers to contribute novel graphical
elements (aka "widgets") to the user interface.  These widgets can request
access to the viewer instance in which they are docked, enabling a broad
range of functionality: essentially, anything that can be done with the
napari `Viewer` and `Layer` APIs can be accomplished with widgets.

```{important}
Because this is a powerful and open-ended plugin specification, we
ask that plugin developers take additional care when providing widget plugins.
Make sure to only use public methods on the `viewer` and `layer` instances.
Also, be mindful of the fact that the user may be using your plugin along with
other plugins or workflows: try to only modify layers added by your plugin, or
specifically requested by the user.
```

The widget specification requires that the plugin provide napari with a
*callable* object that, when called, returns an *instance* of a widget
(where a "widget" is an instance of `QtWidgets.QWidget` or `magicgui.widgets.Widget`).

There are a few commonly used patterns that fulfill this `Callable[..., Widget]`
specification:

1. Provide a `class` object directly, such as a `QtWidgets.QWidget` or
   `magicgui.widgets.Widget` subclass:

   ```python
   from qtpy.QtWidgets import QWidget

   class MyPluginWidget(QWidget):
       def __init__(self, viewer: 'napari.viewer.Viewer', parent=None):
           super().__init__(parent)
           self._viewer = viewer
   ```

2. Provide a wrapper function, or `magicgui.magic_factory` object:

    ```python
    from magicgui import magic_factory

    @magic_factory
    def create_widget(image: 'napari.types.ImageData') -> 'napari.types.ImageData':
        ...
    ```

    *(reminder, in the example above, each time the `magic_factory`-decorated
    `create_widget()` function is called, it returns a new widget instance ––
    just as we need for the widget specification.)*

3. Lastly, you can provide an arbitrary function and request that napari
   autogenerate a widget using `magicgui.magicgui`.  In the first generation
   `napari_plugin_engine`, this was the `napari_experimental_provide_function`
   hook specification.  In the new `npe2` pattern, one uses the `autogenerate`
   field in the [WidgetContribution](contributions-widgets).


### Widget example

::::{tab-set}
:::{tab-item} npe2
**python implementation**

```python
# example_plugin.some_module
{{ 'widgets'|example_implementation }}
```

**manifest**

See [Widgets contribution reference](contributions-widgets) for field details.

```yaml
{{ 'widgets'|example_contribution }}
```
:::

:::{tab-item} napari-plugin-engine

```{admonition} Deprecated!
This demonstrates the now-deprecated `napari-plugin-engine` pattern.
```

**python implementation**

[hook_specification](https://napari.org/stable/plugins/npe1.html#napari.plugins.hook_specifications.napari_experimental_provide_dock_widget)

```python
from qtpy.QtWidgets import QWidget
from napari_plugin_engine import napari_hook_implementation


class AnimationWizard(QWidget):
    def __init__(self, viewer: "napari.viewer.Viewer", parent=None):
        super().__init__(parent)
        ...


@magic_factory
def widget_factory(
    image: "napari.types.ImageData", threshold: int
) -> "napari.types.LabelsData":
    """Generate thresholded image.

    This pattern uses magicgui.magic_factory directly to turn a function
    into a callable that returns a widget.
    """
    return (image > threshold).astype(int)


def threshold(
    image: "napari.types.ImageData", threshold: int
) -> "napari.types.LabelsData":
    """Generate thresholded image.

    This function will be turned into a widget using `autogenerate: true`.
    """
    return (image > threshold).astype(int)


# in the first generation plugin engine, these widgets were declared
# using special `napari_hook_implementation`-decorated functions.

@napari_hook_implementation
def napari_experimental_provide_dock_widget():
    return [AnimationWizard, widget_factory]


@napari_hook_implementation
def napari_experimental_provide_function():
    return [threshold]
```
:::
::::
