| 434 | } |
| 435 | |
| 436 | void WindowZoomSet(WindowBase& w, ZoomLevel zoomLevel, bool atCursor) |
| 437 | { |
| 438 | Viewport* v = w.viewport; |
| 439 | if (v == nullptr) |
| 440 | return; |
| 441 | |
| 442 | zoomLevel = std::clamp(zoomLevel, ZoomLevel::min(), ZoomLevel::max()); |
| 443 | if (v->zoom == zoomLevel) |
| 444 | return; |
| 445 | |
| 446 | const ZoomLevel previousZoomLevel = v->zoom; |
| 447 | |
| 448 | // Zoom in |
| 449 | while (v->zoom > zoomLevel) |
| 450 | { |
| 451 | v->zoom--; |
| 452 | w.savedViewPos.x += v->ViewWidth() / 2; |
| 453 | w.savedViewPos.y += v->ViewHeight() / 2; |
| 454 | } |
| 455 | |
| 456 | // Zoom out |
| 457 | while (v->zoom < zoomLevel) |
| 458 | { |
| 459 | v->zoom++; |
| 460 | w.savedViewPos.x -= v->ViewWidth() / 4; |
| 461 | w.savedViewPos.y -= v->ViewHeight() / 4; |
| 462 | } |
| 463 | |
| 464 | if (Config::Get().general.zoomToCursor && atCursor) |
| 465 | { |
| 466 | const auto mouseCoords = ContextGetCursorPositionScaled() - v->pos; |
| 467 | const int32_t diffX = (mouseCoords.x - (zoomLevel.ApplyInversedTo(v->ViewWidth()) / 2)); |
| 468 | const int32_t diffY = (mouseCoords.y - (zoomLevel.ApplyInversedTo(v->ViewHeight()) / 2)); |
| 469 | if (previousZoomLevel > zoomLevel) |
| 470 | { |
| 471 | w.savedViewPos.x += zoomLevel.ApplyTo(diffX); |
| 472 | w.savedViewPos.y += zoomLevel.ApplyTo(diffY); |
| 473 | } |
| 474 | else |
| 475 | { |
| 476 | w.savedViewPos.x -= previousZoomLevel.ApplyTo(diffX); |
| 477 | w.savedViewPos.y -= previousZoomLevel.ApplyTo(diffY); |
| 478 | } |
| 479 | } |
| 480 | |
| 481 | v->viewPos.x = w.savedViewPos.x; |
| 482 | v->viewPos.y = w.savedViewPos.y; |
| 483 | |
| 484 | // HACK: Prevents the redraw from failing when there is |
| 485 | // a window on top of the viewport. |
| 486 | auto* windowMgr = Ui::GetWindowManager(); |
| 487 | windowMgr->BringToFront(w); |
| 488 | w.invalidate(); |
| 489 | } |
| 490 | |
| 491 | /** |
| 492 | * Splits a drawing of a window into regions that can be seen and are not hidden |
no test coverage detected