Skip to content

Commit 79c478b

Browse files
committed
Tests: Where a pan may start, and what stays a click
- from the background, and from a button of a node: the view pans; - from a widget that uses the navigate button: it keeps the button, no pan; - from outside the editor: no pan (thedmd#238); - a right click on a button of a node: its context menu and the node's, as before; - a pan that ends on the button it started from: no context menu.
1 parent 9489164 commit 79c478b

2 files changed

Lines changed: 134 additions & 0 deletions

File tree

‎tests/CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ set(_TestSources
8686
lifetime_tests.cpp
8787
link_tests.cpp
8888
math_tests.cpp
89+
pan_tests.cpp
8990
popup_callback_tests.cpp
9091
protocol_tests.cpp
9192
settings_tests.cpp

‎tests/pan_tests.cpp‎

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//------------------------------------------------------------------------------
2+
// Where a pan with the navigate button may start: the background, a node, a
3+
// widget of a node which does not use that button. Not a widget which uses it,
4+
// nor a press outside the editor (#238). A click stays a click; the release that
5+
// ends a pan is not one.
6+
//------------------------------------------------------------------------------
7+
# include "harness.h"
8+
9+
namespace {
10+
11+
struct PanScene
12+
{
13+
ImVec2 ButtonCenter, RightButtonCenter, OriginOnScreen;
14+
bool RightButtonHeld = false;
15+
int ButtonContextMenus = 0; // the condition of BeginPopupContextItem() on the button
16+
int NodeContextMenus = 0; // ed::ShowNodeContextMenu() for the node
17+
18+
void operator()(int frame)
19+
{
20+
if (frame == 0)
21+
ed::SetNodePosition(1, ImVec2(100.0f, 100.0f));
22+
ed::BeginNode(1);
23+
ImGui::Text("Node");
24+
ImGui::Button("A button", ImVec2(150.0f, 40.0f));
25+
ButtonCenter = ed::CanvasToScreen((ImGui::GetItemRectMin() + ImGui::GetItemRectMax()) * 0.5f);
26+
if (ImGui::IsMouseReleased(ImGuiMouseButton_Right) && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup))
27+
++ButtonContextMenus;
28+
ImGui::InvisibleButton("uses the navigate button", ImVec2(150.0f, 40.0f), ImGuiButtonFlags_MouseButtonRight);
29+
RightButtonCenter = ed::CanvasToScreen((ImGui::GetItemRectMin() + ImGui::GetItemRectMax()) * 0.5f);
30+
RightButtonHeld = RightButtonHeld || ImGui::IsItemActive();
31+
ed::EndNode();
32+
OriginOnScreen = ed::CanvasToScreen(ImVec2(0.0f, 0.0f));
33+
ed::Suspend();
34+
ed::NodeId nodeId;
35+
if (ed::ShowNodeContextMenu(&nodeId) && nodeId == ed::NodeId(1))
36+
++NodeContextMenus;
37+
ed::Resume();
38+
}
39+
};
40+
41+
// Drags with the navigate button from 'from', and returns how far the view moved.
42+
ImVec2 DragAndMeasure(test::Session& session, PanScene& scene, ImVec2 from, ImVec2 delta)
43+
{
44+
const ImVec2 before = scene.OriginOnScreen;
45+
session.Drag(from, from + delta, ed::Config().NavigateButtonIndex);
46+
return scene.OriginOnScreen - before;
47+
}
48+
49+
bool Equal(ImVec2 a, ImVec2 b) { return ImFabs(a.x - b.x) < 1.0f && ImFabs(a.y - b.y) < 1.0f; }
50+
51+
} // namespace
52+
53+
TEST_CASE(PanFromBackground, "interaction.pan_from_the_background", "#238", test::TestFlags_None)
54+
{
55+
test::Storage storage;
56+
test::Session session(&storage);
57+
PanScene scene;
58+
session.DefaultContent = std::ref(scene);
59+
session.Run(3);
60+
61+
const ImVec2 delta(80.0f, 50.0f);
62+
const ImVec2 moved = DragAndMeasure(session, scene, session.HostPos + ImVec2(700.0f, 500.0f), delta);
63+
test::Check(Equal(moved, delta), "a drag from the background pans the view: moved by (%g, %g), the mouse by (%g, %g)", moved.x, moved.y, delta.x, delta.y);
64+
}
65+
66+
TEST_CASE(PanFromWidget, "interaction.pan_from_a_widget_in_a_node", "#238", test::TestFlags_None)
67+
{
68+
test::Storage storage;
69+
test::Session session(&storage);
70+
PanScene scene;
71+
session.DefaultContent = std::ref(scene);
72+
session.Run(3);
73+
74+
const ImVec2 delta(80.0f, 50.0f);
75+
const ImVec2 moved = DragAndMeasure(session, scene, scene.ButtonCenter, delta);
76+
test::Check(Equal(moved, delta), "a drag from a button of a node (which uses another mouse button) pans the view: moved by (%g, %g), the mouse by (%g, %g)", moved.x, moved.y, delta.x, delta.y);
77+
}
78+
79+
TEST_CASE(NoPanFromWidgetUsingTheButton, "interaction.no_pan_from_a_widget_using_the_navigate_button", "#238", test::TestFlags_None)
80+
{
81+
test::Storage storage;
82+
test::Session session(&storage);
83+
PanScene scene;
84+
session.DefaultContent = std::ref(scene);
85+
session.Run(3);
86+
87+
const ImVec2 moved = DragAndMeasure(session, scene, scene.RightButtonCenter, ImVec2(80.0f, 50.0f));
88+
test::Check(Equal(moved, ImVec2(0.0f, 0.0f)), "a drag from a widget which uses the navigate button does not pan: moved by (%g, %g)", moved.x, moved.y);
89+
test::Check(scene.RightButtonHeld, "the widget keeps the navigate button: it was held");
90+
}
91+
92+
TEST_CASE(NoPanFromOutside, "interaction.no_pan_from_outside_the_editor", "#238", test::TestFlags_None)
93+
{
94+
test::Storage storage;
95+
test::Session session(&storage);
96+
PanScene scene;
97+
session.DefaultContent = std::ref(scene);
98+
session.Run(3);
99+
100+
// Pressed right of the host window, where no window is, then dragged over the editor.
101+
const ImVec2 from = session.HostPos + ImVec2(session.HostSize.x + 100.0f, 300.0f);
102+
const ImVec2 moved = DragAndMeasure(session, scene, from, ImVec2(-500.0f, 0.0f));
103+
test::Check(Equal(moved, ImVec2(0.0f, 0.0f)), "a drag pressed outside the editor does not pan when it enters it: moved by (%g, %g)", moved.x, moved.y);
104+
}
105+
106+
TEST_CASE(RightClickOnWidget, "interaction.right_click_on_a_widget_in_a_node", "#238", test::TestFlags_None)
107+
{
108+
test::Storage storage;
109+
test::Session session(&storage);
110+
PanScene scene;
111+
session.DefaultContent = std::ref(scene);
112+
session.Run(3);
113+
114+
session.Click(scene.ButtonCenter, ed::Config().ContextMenuButtonIndex);
115+
test::Check(scene.ButtonContextMenus == 1, "a right click on a button of a node opens its context menu: %d times", scene.ButtonContextMenus);
116+
test::Check(scene.NodeContextMenus == 1, "and the context menu of the node, as before: %d times", scene.NodeContextMenus);
117+
}
118+
119+
TEST_CASE(NoClickAtTheEndOfAPan, "interaction.no_click_at_the_end_of_a_pan", "#238", test::TestFlags_None)
120+
{
121+
test::Storage storage;
122+
test::Session session(&storage);
123+
PanScene scene;
124+
session.DefaultContent = std::ref(scene);
125+
session.Run(3);
126+
127+
// The view follows the mouse: the drag ends on the button it started from
128+
const ImVec2 delta(80.0f, 50.0f);
129+
const ImVec2 moved = DragAndMeasure(session, scene, scene.ButtonCenter, delta);
130+
test::Check(Equal(moved, delta), "the drag pans the view: moved by (%g, %g)", moved.x, moved.y);
131+
test::Check(scene.ButtonContextMenus == 0, "the release that ends the pan opens no context menu of the button: %d times", scene.ButtonContextMenus);
132+
test::Check(scene.NodeContextMenus == 0, "nor of the node: %d times", scene.NodeContextMenus);
133+
}

0 commit comments

Comments
 (0)