@@ -324,6 +324,7 @@ def update_viewfinder(relayout_data, annotation_store):
324
324
{"type" : "annotation-class-store" , "index" : ALL }, "data" , allow_duplicate = True
325
325
),
326
326
Output ("annotation-store" , "data" , allow_duplicate = True ),
327
+ Output ("image-viewer" , "figure" , allow_duplicate = True ),
327
328
Input ("image-viewer" , "relayoutData" ),
328
329
State ("image-selection-slider" , "value" ),
329
330
State ("annotation-store" , "data" ),
@@ -347,24 +348,23 @@ def locally_store_annotations(
347
348
annotation_store ["view" ]["xaxis_range_1" ] = relayout_data ["xaxis.range[1]" ]
348
349
annotation_store ["view" ]["yaxis_range_0" ] = relayout_data ["yaxis.range[0]" ]
349
350
annotation_store ["view" ]["yaxis_range_1" ] = relayout_data ["yaxis.range[1]" ]
350
- return all_annotation_class_store , annotation_store
351
- # Case 2: a shape is modified, the relayoutData will have the format "shape[_].path", with the new path (not very useful)
352
- # we can instead take all the shapes from the fig layout directly and reset them in the store
351
+ return all_annotation_class_store , annotation_store , dash . no_update
352
+ # Case 2: A shape is modified, drawn or deleted. Save all the current shapes on the fig layout, which includes new
353
+ # modified, and deleted shapes.
353
354
if (
354
355
any (["shapes" in key for key in relayout_data ])
355
356
and "shapes" in fig ["layout" ].keys ()
356
357
):
357
358
shapes = fig ["layout" ]["shapes" ]
358
- # Case 3: a new shape is drawn, we have access to all this data directly from the relayoutData under the 'shapes' key
359
- elif "shapes" in relayout_data :
360
- shapes = relayout_data ["shapes" ]
361
- # Clear all annotation from the stores at the current slice, except for the hidden shapes
359
+
360
+ # Clear all annotation from the stores at the current slice,
361
+ # except for the hidden shapes (hidden shapes cannot be modified or deleted)
362
362
for a_class in all_annotation_class_store :
363
363
if not a_class ["is_visible" ]:
364
364
continue
365
365
if img_idx in a_class ["annotations" ]:
366
366
del a_class ["annotations" ][img_idx ]
367
- # Add back each annotation on the current slice in each respective store
367
+ # Add back each annotation on the current slice in each respective store.
368
368
for shape in shapes :
369
369
for a_class in all_annotation_class_store :
370
370
if a_class ["color" ] == shape ["line" ]["color" ]:
@@ -373,8 +373,16 @@ def locally_store_annotations(
373
373
else :
374
374
a_class ["annotations" ][img_idx ] = [shape ]
375
375
break
376
-
377
- return all_annotation_class_store , annotation_store
376
+ # redraw all annotations on the fig so the store is aligned with whats on the app
377
+ # ie: drawing with a hidden class hides the shape immediately
378
+ # ie: drawing with the first class pushes the shape to the back of the image imdediately
379
+ fig = Patch ()
380
+ all_annotations = []
381
+ for a in all_annotation_class_store :
382
+ if a ["is_visible" ] and "annotations" in a and img_idx in a ["annotations" ]:
383
+ all_annotations += a ["annotations" ][img_idx ]
384
+ fig ["layout" ]["shapes" ] = all_annotations
385
+ return all_annotation_class_store , annotation_store , fig
378
386
379
387
380
388
@callback (
0 commit comments