Repository: napari/napari

Issue:
Adding points resets the view to data center
## 🐛 Bug

I think this is probably caused by #3718, but I haven't done a bisect yet.

## To Reproduce

```python
import napari
import numpy as np

image = np.zeros((5, 10, 10))

viewer = napari.Viewer()
viewer.add_image(image)

viewer.dims.set_point(0, 0)

print(viewer.dims.point)

pts_layer = viewer.add_points(ndim=3)  # resets back to (2, 5, 5)

print(viewer.dims.point)

viewer.dims.set_point(0, 0)

pts_layer.add([(0, 8, 8)])  # resets back to (2, 5, 5)

print(viewer.dims.point)

napari.run()
```

## Expected behavior

To be honest, I think setting the view to the data center should only be done for the first layer, and never after the user has already adjusted the view. For example, in my use case, I started to explore a dataset, found a bit of interest, then clicked on "add points layer", and found my view was reset back to the center of the dataset. This is jarring.

Worse, though, and definitely a bug, was that every time I clicked on a point to add, the view *also* reset to the data center.

## Environment

```
napari: 0.4.13.dev95+gfc133a62
Platform: Linux-4.15.0-29-generic-x86_64-with-glibc2.27
System: Ubuntu 18.04.6 LTS
Python: 3.9.6 | packaged by conda-forge | (default, Jul 11 2021, 03:39:48)  [GCC 9.3.0]
Qt: 5.15.2
PyQt5: 5.15.4
NumPy: 1.20.3
SciPy: 1.7.1
Dask: 2021.08.0
VisPy: 0.9.4

OpenGL:
  - GL version:  3.0 Mesa 20.0.8
  - MAX_TEXTURE_SIZE: 16384

Screens:
  - screen 1: resolution 2560x1440, scale 1.0

Plugins:
  - affinder
  - bioformats: 0.2.1
  - console: 0.0.4
  - explode-view: 0.0.1
  - napari-ome-zarr: 0.3.1
  - ome-types: 0.2.9
  - scikit-image: 0.4.13.dev95+gfc133a62
  - svg: 0.1.5
  - zarpaint: 0.1.1.dev7+gf907586.d20211212
```



Discussion:

Resolving patch:
diff --git a/napari/components/viewer_model.py b/napari/components/viewer_model.py
--- a/napari/components/viewer_model.py
+++ b/napari/components/viewer_model.py
@@ -344,8 +344,6 @@ def _on_layers_change(self):
             ndim = len(ranges)
             self.dims.ndim = ndim
             self.dims.set_range(range(ndim), ranges)
-            midpoint = [self.rounded_division(*_range) for _range in ranges]
-            self.dims.set_point(range(ndim), midpoint)
 
         new_dim = self.dims.ndim
         dim_diff = new_dim - len(self.cursor.position)
@@ -468,6 +466,9 @@ def _on_add_layer(self, event):
 
         if len(self.layers) == 1:
             self.reset_view()
+            ranges = self.layers._ranges
+            midpoint = [self.rounded_division(*_range) for _range in ranges]
+            self.dims.set_point(range(len(ranges)), midpoint)
 
     def _on_remove_layer(self, event):
         """Disconnect old layer events.


Test patch:
diff --git a/napari/components/_tests/test_viewer_model.py b/napari/components/_tests/test_viewer_model.py
--- a/napari/components/_tests/test_viewer_model.py
+++ b/napari/components/_tests/test_viewer_model.py
@@ -287,6 +287,28 @@ def test_new_points():
     assert viewer.dims.ndim == 2
 
 
+def test_view_centering_with_points_add():
+    """Test if the viewer is only centered when the first
+    points were added
+    Regression test for issue  #3803
+    """
+    image = np.zeros((5, 10, 10))
+
+    viewer = ViewerModel()
+    viewer.add_image(image)
+    assert tuple(viewer.dims.point) == (2, 5, 5)
+
+    viewer.dims.set_point(0, 0)
+    # viewer point shouldn't change after this
+    assert tuple(viewer.dims.point) == (0, 5, 5)
+
+    pts_layer = viewer.add_points(ndim=3)
+    assert tuple(viewer.dims.point) == (0, 5, 5)
+
+    pts_layer.add([(0, 8, 8)])
+    assert tuple(viewer.dims.point) == (0, 5, 5)
+
+
 def test_new_shapes():
     """Test adding new shapes layer."""
     # Add labels to empty viewer
@@ -328,17 +350,17 @@ def test_swappable_dims():
     # midpoints indices into the data below depend on the data range.
     # This depends on the values in vectors_data and thus the random seed.
     assert np.all(
-        viewer.layers[labels_name]._slice.image.raw == labels_data[4, 6, :, :]
+        viewer.layers[labels_name]._slice.image.raw == labels_data[3, 6, :, :]
     )
 
     # Swap dims
     viewer.dims.order = [0, 2, 1, 3]
     assert viewer.dims.order == (0, 2, 1, 3)
     assert np.all(
-        viewer.layers[image_name]._data_view == image_data[4, :, 5, :]
+        viewer.layers[image_name]._data_view == image_data[3, :, 5, :]
     )
     assert np.all(
-        viewer.layers[labels_name]._slice.image.raw == labels_data[4, :, 5, :]
+        viewer.layers[labels_name]._slice.image.raw == labels_data[3, :, 5, :]
     )