9
9
import numpy as np
10
10
import pytest
11
11
12
- from ndv ._types import MouseButton , MouseMoveEvent , MousePressEvent , MouseReleaseEvent
12
+ from ndv ._types import (
13
+ CursorType ,
14
+ MouseButton ,
15
+ MouseMoveEvent ,
16
+ MousePressEvent ,
17
+ MouseReleaseEvent ,
18
+ )
13
19
from ndv .controllers import ArrayViewer
14
20
from ndv .controllers ._channel_controller import ChannelController
15
21
from ndv .models ._array_display_model import ArrayDisplayModel , ChannelMode
@@ -309,18 +315,25 @@ def test_roi_interaction() -> None:
309
315
return
310
316
311
317
ctrl = ArrayViewer ()
318
+ roi = RectangularROIModel ()
319
+ ctrl .roi = roi
320
+ roi_view = ctrl ._roi_view
321
+ assert roi_view is not None
312
322
313
- canvas_roi_start = (0 , 0 )
323
+ # FIXME: We need a large world space on the canvas, but
324
+ # VispyArrayCanvas.set_range is not implemented yet. This workaround
325
+ # sets the range to the extent of the data i.e. the extent of the ROI
326
+ roi .bounding_box = ((0 , 0 ), (500 , 500 ))
327
+ ctrl ._canvas .set_range ()
328
+ # Note that these positions are far apart to satisfy sufficient distance
329
+ # in world space
330
+ canvas_roi_start = (200 , 200 )
314
331
world_roi_start = tuple (ctrl ._canvas .canvas_to_world (canvas_roi_start )[:2 ])
315
- canvas_new_start = (- 100 , - 100 )
332
+ canvas_new_start = (100 , 100 )
316
333
world_new_start = tuple (ctrl ._canvas .canvas_to_world (canvas_new_start )[:2 ])
317
- canvas_roi_end = (100 , 100 )
334
+ canvas_roi_end = (300 , 300 )
318
335
world_roi_end = tuple (ctrl ._canvas .canvas_to_world (canvas_roi_end )[:2 ])
319
-
320
- roi = RectangularROIModel (bounding_box = (world_roi_start , world_roi_end ))
321
- ctrl .roi = roi
322
- roi_view = ctrl ._roi_view
323
- assert roi_view is not None
336
+ roi .bounding_box = (world_roi_start , world_roi_end )
324
337
325
338
# Note - avoid diving into rendering logic here - just identify view
326
339
with patch .object (ctrl ._canvas , "elements_at" , return_value = [ctrl ._roi_view ]):
@@ -339,3 +352,42 @@ def test_roi_interaction() -> None:
339
352
canvas_new_start [0 ], canvas_new_start [1 ], MouseButton .LEFT
340
353
)
341
354
ctrl ._canvas .on_mouse_release (mre )
355
+
356
+ # Test translation
357
+ roi .bounding_box = (world_roi_start , world_roi_end )
358
+ mpe = MousePressEvent (
359
+ (canvas_roi_start [0 ] + canvas_roi_end [0 ] / 2 ),
360
+ (canvas_roi_start [1 ] + canvas_roi_end [1 ] / 2 ),
361
+ MouseButton .LEFT ,
362
+ )
363
+ ctrl ._canvas .on_mouse_press (mpe )
364
+ assert roi_view .selected ()
365
+ mme = MouseMoveEvent (
366
+ (canvas_roi_start [0 ] + canvas_new_start [0 ] / 2 ),
367
+ (canvas_roi_start [1 ] + canvas_new_start [1 ] / 2 ),
368
+ MouseButton .LEFT ,
369
+ )
370
+ ctrl ._canvas .on_mouse_move (mme )
371
+ assert roi .bounding_box [0 ] == pytest .approx (world_new_start , 1e-6 )
372
+ assert roi .bounding_box [1 ] == pytest .approx (world_roi_start , 1e-6 )
373
+ mre = MouseReleaseEvent (
374
+ (canvas_roi_start [0 ] + canvas_new_start [0 ] / 2 ),
375
+ (canvas_roi_start [1 ] + canvas_new_start [1 ] / 2 ),
376
+ MouseButton .LEFT ,
377
+ )
378
+ ctrl ._canvas .on_mouse_release (mre )
379
+
380
+ # Test cursors
381
+ roi .bounding_box = (world_roi_start , world_roi_end )
382
+ # Top-Left corner
383
+ mme = MouseMoveEvent (canvas_roi_start [0 ], canvas_roi_start [1 ])
384
+ assert roi_view .get_cursor (mme ) == CursorType .FDIAG_ARROW
385
+ # Top-Right corner
386
+ mme = MouseMoveEvent (canvas_roi_start [0 ], canvas_roi_end [1 ])
387
+ assert roi_view .get_cursor (mme ) == CursorType .BDIAG_ARROW
388
+ # Middle
389
+ mme = MouseMoveEvent (
390
+ (canvas_roi_start [0 ] + canvas_roi_end [0 ]) / 2 ,
391
+ (canvas_roi_start [1 ] + canvas_roi_end [1 ]) / 2 ,
392
+ )
393
+ assert roi_view .get_cursor (mme ) == CursorType .ALL_ARROW
0 commit comments