11# guitest: show
2+ from __future__ import annotations
23
3- from typing import TYPE_CHECKING , TypeVar
4+ from typing import TYPE_CHECKING , TypeVar , Union
45
56import numpy as np
67import qtpy .QtCore as QC
78import qtpy .QtGui as QG
89import qtpy .QtWidgets as QW
910from guidata .qthelpers import exec_dialog , qt_app_context
10- from numpy import linspace , sin
1111
12- from plotpy .builder import make
13- from plotpy .interfaces . items import ICurveItemType
12+ from plotpy .interfaces . items import ICurveItemType , IItemType
13+ from plotpy .panels . base import PanelWidget
1414from plotpy .plot .plotwidget import PlotDialog , PlotWindow
1515from plotpy .tests import vistools as ptv
16+ from plotpy .tests .features .test_auto_curve_image import make_curve_image_legend
1617from plotpy .tools import (
18+ CommandTool ,
1719 EditPointTool ,
1820 InteractiveTool ,
1921 SelectPointsTool ,
2022 SelectPointTool ,
2123)
24+ from plotpy .tools .curve import DownSamplingTool
2225
2326if TYPE_CHECKING :
27+
2428 from plotpy .items .curve .base import CurveItem
29+ from plotpy .items .image .base import BaseImageItem
2530
2631CLICK = (QC .QEvent .Type .MouseButtonPress , QC .QEvent .Type .MouseButtonRelease )
27- ToolT = TypeVar ("ToolT" , bound = InteractiveTool )
32+ ToolT = TypeVar ("ToolT" , bound = Union [ InteractiveTool , CommandTool ] )
2833
2934
3035def keyboard_event (
@@ -77,7 +82,7 @@ def mouse_event_at_relative_plot_pos(
7782 size = canva .size ()
7883 pos_x , pos_y = (
7984 relative_xy [0 ] * size .width (),
80- size . height () - relative_xy [1 ] * size .height (),
85+ relative_xy [1 ] * size .height (),
8186 )
8287 # pos_x, pos_y = axes_to_canvas(plot.get_active_item(), x, y)
8388 canva_pos = QC .QPointF (pos_x , pos_y ).toPoint ()
@@ -97,37 +102,44 @@ def mouse_event_at_relative_plot_pos(
97102
98103
99104def drag_mouse (
100- win : PlotDialog ,
105+ win : PlotWindow ,
101106 qapp : QW .QApplication ,
102107 x_path : np .ndarray ,
103108 y_path : np .ndarray ,
104109 mod = QC .Qt .KeyboardModifier .NoModifier ,
110+ click = True ,
105111) -> None :
106112 x0 , y0 = x_path [0 ], y_path [0 ]
107113 xn , yn = x_path [- 1 ], y_path [- 1 ]
108114 press = (QC .QEvent .Type .MouseButtonPress ,)
109115 move = (QC .QEvent .Type .MouseMove ,)
110116 release = (QC .QEvent .Type .MouseButtonRelease ,)
111117
112- mouse_event_at_relative_plot_pos (win , qapp , (x0 , y0 ), press , mod )
118+ if click :
119+ mouse_event_at_relative_plot_pos (win , qapp , (x0 , y0 ), press , mod )
113120 for x , y in zip (x_path , y_path ):
114121 mouse_event_at_relative_plot_pos (win , qapp , (x , y ), move , mod )
115- mouse_event_at_relative_plot_pos (win , qapp , (xn , yn ), release , mod )
122+ if click :
123+ mouse_event_at_relative_plot_pos (win , qapp , (xn , yn ), release , mod )
116124
117125
118- def create_window (tool_class : type [ToolT ]) -> tuple [PlotWindow , ToolT ]:
119- n = 100
120- x = linspace (
121- 0 ,
122- n ,
123- )
124- y = (sin (sin (sin (x / (n / 10 )))) - 1 ) * - n
125- curve = make .curve (x , y , color = "b" )
126- win = ptv .show_items (
127- [curve ], wintitle = "Unit tests for Point tools" , auto_tools = False
128- )
126+ def create_window (
127+ tool_class : type [ToolT ],
128+ active_item_type : type [IItemType ] = ICurveItemType ,
129+ panels : list [type [PanelWidget ]] | None = None ,
130+ ) -> tuple [PlotWindow , ToolT ]:
131+
132+ items : list [CurveItem | BaseImageItem ] = make_curve_image_legend ()
133+ win = ptv .show_items (items , wintitle = "Unit test plot" , auto_tools = False )
129134 plot = win .manager .get_plot ()
130- plot .set_active_item (curve ) # type: ignore
135+ for item in win .manager .get_plot ().get_items ()[::- 1 ]:
136+ plot .set_active_item (item )
137+ last_active_item = plot .get_last_active_item (active_item_type )
138+ plot .set_active_item (last_active_item )
139+
140+ if panels is not None :
141+ for panel in panels :
142+ win .manager .add_panel (panel ())
131143
132144 tool = win .manager .add_tool (tool_class )
133145 tool .activate ()
@@ -137,7 +149,6 @@ def create_window(tool_class: type[ToolT]) -> tuple[PlotWindow, ToolT]:
137149def test_free_select_point_tool ():
138150 with qt_app_context (exec_loop = False ) as qapp :
139151 win , tool = create_window (SelectPointTool )
140-
141152 mouse_event_at_relative_plot_pos (
142153 win ,
143154 qapp ,
@@ -189,15 +200,22 @@ def test_select_points_tool():
189200def test_edit_point_tool ():
190201 with qt_app_context (exec_loop = False ) as qapp :
191202 win , tool = create_window (EditPointTool )
192- curve_item : CurveItem = win .manager .get_plot ().get_last_active_item ( ICurveItemType ) # type: ignore
203+ curve_item : CurveItem = win .manager .get_plot ().get_active_item ( ) # type: ignore
193204 orig_x , orig_y = curve_item .get_data ()
194205
195206 assert orig_x is not None and orig_y is not None
196207 orig_x , orig_y = orig_x .copy (), orig_y .copy ()
197208
198209 assert tool is not None
199210
200- n = 100
211+ # must activate downsampling because the curve is too dense so the selection
212+ # distance threshold is too small for the programmed drag to select the first
213+ # point
214+ curve_item .param .dsamp_factor = 20
215+ win .manager .add_tool (DownSamplingTool ).activate ()
216+ # The steps must be very small to ensure the mouse passes close
217+ # enough to the first point of the curve to move it (distance < threshold)
218+ n = 1000
201219 min_v , max_v = 0 , 1
202220 x_path = np .full (n , min_v )
203221 y_path = np .linspace (max_v , min_v , n )
@@ -206,7 +224,6 @@ def test_edit_point_tool():
206224 x_path = np .full (n , max_v )
207225
208226 drag_mouse (win , qapp , x_path , y_path )
209-
210227 curve_changes = tool .get_changes ()[curve_item ]
211228 for i , (x , y ) in curve_changes .items ():
212229 x_arr , y_arr = curve_item .get_data ()
0 commit comments