viewersizer: use float for all calculations, center manual zoom

This commit is contained in:
itsmattkc
2023-02-22 10:41:17 -08:00
parent e44a3d221d
commit 060c3b0883
3 changed files with 62 additions and 35 deletions
+5 -4
View File
@@ -1376,10 +1376,10 @@ void ViewerWidget::ShowContextMenu(const QPoint &pos)
Menu* zoom_menu = new Menu(tr("Zoom"), &menu);
menu.addMenu(zoom_menu);
zoom_menu->addAction(tr("Fit"))->setData(0);
zoom_menu->addAction(tr("Fit"))->setData(-1);
for (int i=0;i<ViewerSizer::kZoomLevelCount;i++) {
int z = ViewerSizer::kZoomLevels[i];
zoom_menu->addAction(tr("%1%").arg(z))->setData(z);
double z = ViewerSizer::kZoomLevels[i];
zoom_menu->addAction(tr("%1%").arg(z * 100.0))->setData(z);
}
connect(zoom_menu, &QMenu::triggered, this, &ViewerWidget::SetZoomFromMenu);
@@ -1822,7 +1822,8 @@ void ViewerWidget::UpdateRendererAudioParameters()
void ViewerWidget::SetZoomFromMenu(QAction *action)
{
sizer_->SetZoom(action->data().toInt());
auto s = sizer_->GetContainerSize();
sizer_->SetZoomAnchored(action->data().toDouble(), s.width()/2, s.height()/2);
}
void ViewerWidget::ViewerInvalidatedVideoRange(const TimeRange &range)
+47 -26
View File
@@ -35,7 +35,7 @@ ViewerSizer::ViewerSizer(QWidget *parent) :
width_(0),
height_(0),
pixel_aspect_(1),
zoom_(0),
zoom_(-1),
current_widget_scale_(0)
{
horiz_scrollbar_ = new QScrollBar(Qt::Horizontal, this);
@@ -64,6 +64,12 @@ void ViewerSizer::SetWidget(QWidget *widget)
}
}
QSize ViewerSizer::GetContainerSize() const
{
double s = GetRealCurrentZoom();
return QSize(std::min(this->width(), int(width_ * s)) - vert_scrollbar_->width(), std::min(int(height_ * s), this->height()) - horiz_scrollbar_->height());
}
void ViewerSizer::SetChildSize(int width, int height)
{
width_ = width;
@@ -79,13 +85,36 @@ void ViewerSizer::SetPixelAspectRatio(const rational &pixel_aspect)
UpdateSize();
}
void ViewerSizer::SetZoom(int percent)
void ViewerSizer::SetZoom(double percent)
{
zoom_ = percent;
UpdateSize();
}
void ViewerSizer::SetZoomAnchored(double next_scale, double cursor_x, double cursor_y)
{
if (next_scale > 0) {
double cur_scale = GetRealCurrentZoom();
// Clamp scale within safe values
next_scale = std::clamp(next_scale, kZoomLevels[0], kZoomLevels[kZoomLevelCount-1]);
int anchor_x = qRound(double(cursor_x + horiz_scrollbar_->value()) / cur_scale * next_scale - cursor_x);
int anchor_y = qRound(double(cursor_y + vert_scrollbar_->value()) / cur_scale * next_scale - cursor_y);
SetZoom(next_scale);
horiz_scrollbar_->setValue(anchor_x);
vert_scrollbar_->setValue(anchor_y);
} else {
SetZoom(-1);
horiz_scrollbar_->setValue(0);
vert_scrollbar_->setValue(0);
}
}
void ViewerSizer::HandDragMove(int x, int y)
{
if (horiz_scrollbar_->isVisible()) {
@@ -104,28 +133,9 @@ bool ViewerSizer::eventFilter(QObject *watched, QEvent *event)
QWheelEvent *w = static_cast<QWheelEvent*>(event);
if (HandMovableView::WheelEventIsAZoomEvent(w)) {
int current_percent = zoom_;
if (current_percent == 0) {
// Currently set to "fit"
current_percent = current_widget_scale_;
}
double cur_scale = current_percent * 0.01;
current_percent *= HandMovableView::GetScrollZoomMultiplier(w);
current_percent = std::clamp(current_percent, kZoomLevels[0], kZoomLevels[kZoomLevelCount-1]);
double next_scale = current_percent * 0.01;
double next_scale = GetRealCurrentZoom() * HandMovableView::GetScrollZoomMultiplier(w);
QPointF cursor_pos = w->position();
int anchor_x = qRound(double(cursor_pos.x() + horiz_scrollbar_->value()) / cur_scale * next_scale - cursor_pos.x());
int anchor_y = qRound(double(cursor_pos.y() + vert_scrollbar_->value()) / cur_scale * next_scale - cursor_pos.y());
SetZoom(current_percent);
horiz_scrollbar_->setValue(anchor_x);
vert_scrollbar_->setValue(anchor_y);
SetZoomAnchored(next_scale, cursor_pos.x(), cursor_pos.y());
} else {
// Pass scroll values to scrollbars
QPoint p = w->pixelDelta();
@@ -218,12 +228,12 @@ void ViewerSizer::UpdateSize()
}
current_widget_scale_ = current_scale * 100;
current_widget_scale_ = current_scale;
if (zoom_ > 0) {
// Scale to get to the requested zoom
double zoom_diff = (zoom_ * 0.01) / current_scale;
double zoom_diff = zoom_ / current_scale;
child_matrix.scale(zoom_diff, zoom_diff, 1.0);
}
@@ -235,7 +245,18 @@ void ViewerSizer::UpdateSize()
int ViewerSizer::GetZoomedValue(int value)
{
return qRound(value * static_cast<double>(zoom_) * 0.01);
return qRound(value * zoom_);
}
double ViewerSizer::GetRealCurrentZoom() const
{
if (zoom_ < 0) {
// Currently set to "fit"
return current_widget_scale_;
} else {
// Explicit zoom set
return zoom_;
}
}
void ViewerSizer::ScrollBarMoved()
+10 -5
View File
@@ -51,8 +51,10 @@ public:
*/
void SetWidget(QWidget* widget);
static constexpr int kZoomLevelCount = 8;
static constexpr int kZoomLevels[kZoomLevelCount] = {10, 25, 50, 75, 100, 150, 200, 400};
QSize GetContainerSize() const;
static constexpr int kZoomLevelCount = 10;
static constexpr double kZoomLevels[kZoomLevelCount] = {0.05, 0.1, 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 4.0, 8.0};
public slots:
/**
@@ -72,7 +74,8 @@ public slots:
*
* The number is an integer percentage (100 = 100%). Set to 0 to auto-fit.
*/
void SetZoom(int percent);
void SetZoom(double percent);
void SetZoomAnchored(double percent, double cursor_x, double cursor_y);
void HandDragMove(int x, int y);
@@ -97,6 +100,8 @@ private:
int GetZoomedValue(int value);
double GetRealCurrentZoom() const;
/**
* @brief Reference to widget
*
@@ -115,8 +120,8 @@ private:
/**
* @brief Internal zoom value
*/
int zoom_;
int current_widget_scale_;
double zoom_;
double current_widget_scale_;
QScrollBar* horiz_scrollbar_;
QScrollBar* vert_scrollbar_;