(widgets-contribution-guide)=
## Widgets

Widget plugin contributions allow developers to add novel graphical
elements (aka "widgets") to the user interface. For a full introduction to
creating `napari` widgets see [](creating-widgets).

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.
Here "widget" means a subclass of `QtWidgets.QWidget` or `magicgui.widgets.Widget`,
or a `FunctionGui`. Additionally, the plugin can provide an arbitrary function if using
'autogenerate', which requests that napari autogenerate a widget using
`magicgui.magicgui` (see item 3 below).

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

1. Provide a `class` object that is a subclass of `QtWidgets.QWidget` or
   `magicgui.widgets.Widget`:

   ```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 `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).

For more examples see [](creating-widgets) and
[GUI gallery examples](https://napari.org/stable/_tags/gui.html) (only a subset
involve widgets). Additionally,
[napari-plugin-template](https://github.com/napari/napari-plugin-template)
has more robust widget examples that you can adapt to your needs.

```{note}
Notice that `napari` type annotations are strings and not imported. This is to
avoid including `napari` as a plugin dependency when not strictly required.
```

### 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]
```
:::
::::
