Skip to content

Commit cc4905c

Browse files
Feat: Implement graph panning (closes #6)
1 parent fdb7539 commit cc4905c

1 file changed

Lines changed: 52 additions & 11 deletions

File tree

src/core/Core/Application.cpp

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,40 @@ ExitStatus App::Application::run() {
135135
const ImVec2 canvas_p0 = ImGui::GetCursorScreenPos();
136136
const ImVec2 canvas_sz = ImGui::GetContentRegionAvail();
137137
const auto canvas_p1 = ImVec2(canvas_p0.x + canvas_sz.x, canvas_p0.y + canvas_sz.y);
138-
const ImVec2 origin(canvas_p0.x + canvas_sz.x * 0.5f, canvas_p0.y + canvas_sz.y * 0.5f);
138+
// --- PANNING IMPLEMENTATION BEGIN ---
139+
static bool isPanning = false;
140+
static ImVec2 lastMousePos = {0.0f, 0.0f};
141+
static ImVec2 originOffset = {0.0f, 0.0f};
142+
143+
// Get mouse position
144+
ImVec2 mousePos = ImGui::GetMousePos();
145+
146+
// Detect click start only when cursor is inside the graphing area
147+
if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
148+
isPanning = true;
149+
lastMousePos = mousePos;
150+
}
151+
152+
// Stop panning when mouse released
153+
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
154+
isPanning = false;
155+
}
156+
157+
// While dragging, update origin offset
158+
if (isPanning && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
159+
ImVec2 delta = ImVec2(mousePos.x - lastMousePos.x, mousePos.y - lastMousePos.y);
160+
originOffset.x += delta.x;
161+
originOffset.y += delta.y;
162+
lastMousePos = mousePos;
163+
}
164+
165+
// Apply offset to origin
166+
const ImVec2 origin(
167+
canvas_p0.x + canvas_sz.x * 0.5f + originOffset.x,
168+
canvas_p0.y + canvas_sz.y * 0.5f + originOffset.y
169+
);
170+
// --- PANNING IMPLEMENTATION END ---
171+
139172
float lineThickness = 6.0f;
140173
draw_list->AddLine(ImVec2(canvas_p0.x, origin.y), ImVec2(canvas_p1.x, origin.y), IM_COL32(0, 0, 0, 255), lineThickness);
141174
draw_list->AddLine(ImVec2(origin.x, canvas_p0.y), ImVec2(origin.x, canvas_p1.y), IM_COL32(0, 0, 0, 255), lineThickness);
@@ -191,12 +224,13 @@ ExitStatus App::Application::run() {
191224
const double t_step = 0.02;
192225

193226
for (t = t_min; t <= t_max; t += t_step) {
194-
const double vx = expr_fx.value();
195-
const double vy = expr_gx.value();
196-
197-
198-
ImVec2 screen_pos(origin.x + static_cast<float>(vx * zoom),
199-
origin.y - static_cast<float>(vy * zoom));
227+
const double vx = expr_fx.value();
228+
const double vy = expr_gx.value();
229+
// The 'origin' variable already includes the pan offset.
230+
ImVec2 screen_pos(
231+
origin.x + static_cast<float>(vx * zoom),
232+
origin.y - static_cast<float>(vy * zoom)
233+
);
200234
points.push_back(screen_pos);
201235
}
202236

@@ -226,11 +260,18 @@ ExitStatus App::Application::run() {
226260
exprtk::parser<double> parser;
227261
parser.compile(function, expression);
228262

229-
for (x = -canvas_sz.x / (2 * zoom); x < canvas_sz.x / (2 * zoom); x += 0.05) {
230-
const double y = expression.value();
263+
// Calculate the visible x-range in world-space, accounting for the pan
264+
const float world_x_min = (-canvas_sz.x * 0.5f - originOffset.x) / zoom;
265+
const float world_x_max = ( canvas_sz.x * 0.5f - originOffset.x) / zoom;
231266

232-
233-
ImVec2 screen_pos(origin.x + x * zoom, origin.y - y * zoom);
267+
// Evaluate the function across the correct visible world-range
268+
for (x = world_x_min; x <= world_x_max; x += 0.05) {
269+
const double y = expression.value();
270+
// The 'origin' variable already includes the pan offset.
271+
ImVec2 screen_pos(
272+
origin.x + static_cast<float>(x * zoom),
273+
origin.y - static_cast<float>(y * zoom)
274+
);
234275
points.push_back(screen_pos);
235276
}
236277

0 commit comments

Comments
 (0)