viewer: extended scrolling/panning functionality
This commit is contained in:
@@ -75,8 +75,9 @@ ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
connect(display_widget_, &ViewerDisplayWidget::CursorColor, this, &ViewerWidget::CursorColor);
|
||||
connect(display_widget_, &ViewerDisplayWidget::ColorProcessorChanged, this, &ViewerWidget::ColorProcessorChanged);
|
||||
connect(display_widget_, &ViewerDisplayWidget::ColorManagerChanged, this, &ViewerWidget::ColorManagerChanged);
|
||||
connect(sizer_, &ViewerSizer::RequestMatrix, display_widget_, &ViewerDisplayWidget::SetMatrixZoom);
|
||||
connect(sizer_, &ViewerSizer::IsZoomed, display_widget_, &ViewerDisplayWidget::IsZoomed);
|
||||
connect(sizer_, &ViewerSizer::RequestScale, display_widget_, &ViewerDisplayWidget::SetMatrixZoom);
|
||||
connect(sizer_, &ViewerSizer::RequestTranslate, display_widget_, &ViewerDisplayWidget::SetMatrixTranslate);
|
||||
connect(display_widget_, &ViewerDisplayWidget::HandDragMoved, sizer_, &ViewerSizer::HandDragMove);
|
||||
sizer_->SetWidget(display_widget_);
|
||||
|
||||
// Create waveform view when audio is connected and video isn't
|
||||
|
||||
+110
-110
@@ -45,13 +45,13 @@ ViewerDisplayWidget::ViewerDisplayWidget(QWidget *parent) :
|
||||
gizmos_(nullptr),
|
||||
gizmo_click_(false),
|
||||
last_loaded_buffer_(nullptr),
|
||||
zoomed_(false),
|
||||
hand_tool_clicked_(false),
|
||||
hand_dragging_(false),
|
||||
deinterlace_(false)
|
||||
{
|
||||
connect(Core::instance(), &Core::ToolChanged, this, &ViewerDisplayWidget::ToolChanged);
|
||||
// Initilises hand_tool_ based on currently selected tool.
|
||||
ToolChanged(Core::instance()->tool());
|
||||
connect(Core::instance(), &Core::ToolChanged, this, &ViewerDisplayWidget::UpdateCursor);
|
||||
|
||||
// Initializes cursor based on tool
|
||||
UpdateCursor();
|
||||
}
|
||||
|
||||
ViewerDisplayWidget::~ViewerDisplayWidget()
|
||||
@@ -62,49 +62,32 @@ ViewerDisplayWidget::~ViewerDisplayWidget()
|
||||
void ViewerDisplayWidget::SetMatrixTranslate(const QMatrix4x4 &mat)
|
||||
{
|
||||
translate_matrix_ = mat;
|
||||
update();
|
||||
|
||||
UpdateMatrix();
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::SetMatrixZoom(const QMatrix4x4 &mat)
|
||||
{
|
||||
scale_matrix_ = mat;
|
||||
update();
|
||||
|
||||
UpdateMatrix();
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::IsZoomed(bool flag)
|
||||
void ViewerDisplayWidget::UpdateCursor()
|
||||
{
|
||||
zoomed_ = flag;
|
||||
// If the image is smaller than the container widget we reset the translation.
|
||||
if (!flag) {
|
||||
QMatrix4x4 mat; // defaults to identity matrix.
|
||||
SetMatrixTranslate(mat);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::ToolChanged(Tool::Item tool)
|
||||
{
|
||||
if (tool == Tool::kHand) {
|
||||
hand_tool_ = true;
|
||||
if (Core::instance()->tool() == Tool::kHand) {
|
||||
setCursor(Qt::OpenHandCursor);
|
||||
} else {
|
||||
hand_tool_ = false;
|
||||
unsetCursor();
|
||||
}
|
||||
}
|
||||
|
||||
QMatrix4x4 ViewerDisplayWidget::GetCompleteMatrix()
|
||||
QMatrix4x4 ViewerDisplayWidget::GetCompleteMatrixFlippedYTranslation()
|
||||
{
|
||||
QMatrix4x4 mat;
|
||||
// Images is scaled, then translated.
|
||||
return translate_matrix_ * scale_matrix_ * mat;
|
||||
}
|
||||
QMatrix4x4 mat = combined_matrix_;
|
||||
|
||||
mat.data()[13] *= -1.0f;
|
||||
|
||||
QMatrix4x4 ViewerDisplayWidget::GetCompleteMatrixFlippedYTranslation() {
|
||||
QMatrix4x4 mat;
|
||||
// Image is scaled, then translated.
|
||||
mat = translate_matrix_ * scale_matrix_ * mat;
|
||||
// Y translation is flipped for OpenGL usage
|
||||
*(mat.data() + 13) = *(mat.data() + 13) * -1.0f;
|
||||
return mat;
|
||||
}
|
||||
|
||||
@@ -188,28 +171,6 @@ FramePtr ViewerDisplayWidget::last_loaded_buffer() const
|
||||
return last_loaded_buffer_;
|
||||
}
|
||||
|
||||
QTransform ViewerDisplayWidget::GenerateWorldTransform()
|
||||
{
|
||||
/*
|
||||
* Get matrix elements (roughly) as below in column major order
|
||||
*
|
||||
* | Sx 0 0 Tx |
|
||||
* | 0 Sy 0 Ty |
|
||||
* | 0 0 Sz Tz |
|
||||
* | 0 0 0 1 |
|
||||
*/
|
||||
float *data = GetCompleteMatrix().data();
|
||||
QTransform world;
|
||||
// Move corner of canvas to correct point
|
||||
world.translate(width() * 0.5 - width() * *(data)*0.5, height() * 0.5 - height() * *(data + 5) * 0.5);
|
||||
// Scale
|
||||
world.scale(*(data), *(data + 5));
|
||||
// Translate for mouse movement
|
||||
world.translate(*(data + 12) * width() * 0.5 / *(data), *(data + 13) * height() * 0.5 / *(data + 5));
|
||||
|
||||
return world;
|
||||
}
|
||||
|
||||
QPoint ViewerDisplayWidget::TransformViewerSpaceToBufferSpace(QPoint pos)
|
||||
{
|
||||
/*
|
||||
@@ -223,62 +184,35 @@ void ViewerDisplayWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton && gizmos_
|
||||
&& gizmos_->GizmoPress(gizmo_db_, TransformViewerSpaceToBufferSpace(event->pos()),
|
||||
QVector2D(GetTexturePosition(size())), size())) {
|
||||
QVector2D(GetTexturePosition(size())), size())) {
|
||||
|
||||
// Handle gizmo click
|
||||
gizmo_click_ = true;
|
||||
gizmo_drag_time_ = GetGizmoTime();
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset translation.
|
||||
if (event->button() == Qt::MiddleButton && event->modifiers() & Qt::ControlModifier) {
|
||||
QMatrix4x4 mat; // Identity matrix
|
||||
SetMatrixTranslate(mat);
|
||||
return;
|
||||
}
|
||||
} else if (IsHandDrag(event)) {
|
||||
|
||||
// If translation is enabled get current position in preperation for move event.
|
||||
if ((event->button() == Qt::MiddleButton || hand_tool_) && zoomed_) {
|
||||
position_ = event->pos();
|
||||
if (hand_tool_) hand_tool_clicked_ = true;
|
||||
return;
|
||||
}
|
||||
// Handle hand drag
|
||||
hand_last_drag_pos_ = event->pos();
|
||||
hand_dragging_ = true;
|
||||
emit HandDragStarted();
|
||||
setCursor(Qt::ClosedHandCursor);
|
||||
|
||||
QOpenGLWidget::mousePressEvent(event);
|
||||
} else {
|
||||
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
// Handle standard drag
|
||||
emit DragStarted();
|
||||
}
|
||||
|
||||
QOpenGLWidget::mousePressEvent(event);
|
||||
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
emit DragStarted();
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
// Only allow translation if the image is larger than the container widget
|
||||
if ((event->buttons() & Qt::MiddleButton || hand_tool_clicked_) && zoomed_) {
|
||||
QPointF delta = event->pos() - position_;
|
||||
// Scale delta to widget size
|
||||
delta.setX(2 * delta.x() / width());
|
||||
delta.setY(2 * delta.y() / height());
|
||||
|
||||
QMatrix4x4 mat;
|
||||
mat = GetMatrixTranslate();
|
||||
|
||||
mat.translate(delta.x(), delta.y());
|
||||
SetMatrixTranslate(mat);
|
||||
|
||||
// Get new start position
|
||||
position_ = event-> pos();
|
||||
return;
|
||||
}
|
||||
|
||||
if (gizmo_click_) {
|
||||
gizmos_->GizmoMove(TransformViewerSpaceToBufferSpace(event->pos()),
|
||||
QVector2D(GetTexturePosition(size())), gizmo_drag_time_);
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
QOpenGLWidget::mouseMoveEvent(event);
|
||||
|
||||
// Do this no matter what, emits signal to any pixel samplers
|
||||
if (signal_cursor_color_) {
|
||||
Color reference, display;
|
||||
|
||||
@@ -287,7 +221,7 @@ void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
static_cast<float>(event->y()) / static_cast<float>(height()) * 2.0f - 1.0f,
|
||||
0);
|
||||
|
||||
pixel_pos = GetCompleteMatrix().inverted() * pixel_pos;
|
||||
pixel_pos = GenerateWorldTransform().inverted() * pixel_pos;
|
||||
|
||||
int frame_x = qRound((pixel_pos.x() + 1.0f) * 0.5f * last_loaded_buffer_->width());
|
||||
int frame_y = qRound((pixel_pos.y() + 1.0f) * 0.5f * last_loaded_buffer_->height());
|
||||
@@ -298,20 +232,52 @@ void ViewerDisplayWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
|
||||
emit CursorColor(reference, display);
|
||||
}
|
||||
|
||||
// Handle hand dragging
|
||||
if (hand_dragging_) {
|
||||
|
||||
// Emit movement
|
||||
emit HandDragMoved(event->x() - hand_last_drag_pos_.x(),
|
||||
event->y() - hand_last_drag_pos_.y());
|
||||
|
||||
hand_last_drag_pos_ = event->pos();
|
||||
|
||||
} else if (gizmo_click_) {
|
||||
|
||||
// Signal movement
|
||||
gizmos_->GizmoMove(TransformViewerSpaceToBufferSpace(event->pos()),
|
||||
QVector2D(GetTexturePosition(size())), gizmo_drag_time_);
|
||||
update();
|
||||
|
||||
} else {
|
||||
|
||||
// Default behavior
|
||||
QOpenGLWidget::mouseMoveEvent(event);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (gizmo_click_) {
|
||||
if (hand_dragging_) {
|
||||
|
||||
// Handle hand drag
|
||||
emit HandDragEnded();
|
||||
hand_dragging_ = false;
|
||||
UpdateCursor();
|
||||
|
||||
} else if (gizmo_click_) {
|
||||
|
||||
// Handle gizmo
|
||||
gizmos_->GizmoRelease();
|
||||
gizmo_click_ = false;
|
||||
|
||||
return;
|
||||
} else {
|
||||
|
||||
// Default behavior
|
||||
QOpenGLWidget::mouseReleaseEvent(event);
|
||||
|
||||
}
|
||||
|
||||
hand_tool_clicked_ = false;
|
||||
|
||||
QOpenGLWidget::mouseReleaseEvent(event);
|
||||
}
|
||||
|
||||
QMatrix4x4 ViewerDisplayWidget::GetMatrixTranslate()
|
||||
@@ -355,7 +321,7 @@ void ViewerDisplayWidget::paintGL()
|
||||
|
||||
}
|
||||
|
||||
QTransform world = GenerateWorldTransform();
|
||||
QTransform world_transform = GenerateWorldTransform();
|
||||
|
||||
// Draw gizmos if we have any
|
||||
if (gizmos_) {
|
||||
@@ -366,14 +332,14 @@ void ViewerDisplayWidget::paintGL()
|
||||
gizmo_db_ = gt.GenerateDatabase(gizmos_, TimeRange(node_time, node_time));
|
||||
|
||||
QPainter p(this);
|
||||
p.setWorldTransform(world);
|
||||
p.setWorldTransform(world_transform);
|
||||
gizmos_->DrawGizmos(gizmo_db_, &p, QVector2D(GetTexturePosition(size())), size());
|
||||
}
|
||||
|
||||
// Draw action/title safe areas
|
||||
if (safe_margin_.is_enabled()) {
|
||||
QPainter p(this);
|
||||
p.setWorldTransform(world);
|
||||
p.setWorldTransform(world_transform);
|
||||
|
||||
p.setPen(Qt::lightGray);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
@@ -399,7 +365,7 @@ void ViewerDisplayWidget::paintGL()
|
||||
int cross = qMin(w, h) / 32;
|
||||
|
||||
QLine lines[] = {QLine(rect().center().x() - cross, rect().center().y(),rect().center().x() + cross, rect().center().y()),
|
||||
QLine(rect().center().x(), rect().center().y() - cross, rect().center().x(), rect().center().y() + cross)};
|
||||
QLine(rect().center().x(), rect().center().y() - cross, rect().center().x(), rect().center().y() + cross)};
|
||||
|
||||
p.drawLines(lines, 2);
|
||||
}
|
||||
@@ -426,6 +392,40 @@ rational ViewerDisplayWidget::GetGizmoTime()
|
||||
return GetAdjustedTime(GetTimeTarget(), gizmos_, time_, NodeParam::kInput);
|
||||
}
|
||||
|
||||
bool ViewerDisplayWidget::IsHandDrag(QMouseEvent *event) const
|
||||
{
|
||||
return event->button() == Qt::MiddleButton || Core::instance()->tool() == Tool::kHand;
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::UpdateMatrix()
|
||||
{
|
||||
combined_matrix_ = scale_matrix_ * translate_matrix_;
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
QTransform ViewerDisplayWidget::GenerateWorldTransform()
|
||||
{
|
||||
/*
|
||||
* Get matrix elements (roughly) as below in column major order
|
||||
*
|
||||
* | Sx 0 0 Tx |
|
||||
* | 0 Sy 0 Ty |
|
||||
* | 0 0 Sz Tz |
|
||||
* | 0 0 0 1 |
|
||||
*/
|
||||
float *data = combined_matrix_.data();
|
||||
QTransform world;
|
||||
// Move corner of canvas to correct point
|
||||
world.translate(width() * 0.5 - width() * *(data)*0.5, height() * 0.5 - height() * *(data + 5) * 0.5);
|
||||
// Scale
|
||||
world.scale(*(data), *(data + 5));
|
||||
// Translate for mouse movement
|
||||
world.translate(*(data + 12) * width() * 0.5 / *(data), *(data + 13) * height() * 0.5 / *(data + 5));
|
||||
|
||||
return world;
|
||||
}
|
||||
|
||||
void ViewerDisplayWidget::ContextCleanup()
|
||||
{
|
||||
makeCurrent();
|
||||
|
||||
@@ -72,12 +72,6 @@ public:
|
||||
*/
|
||||
QMatrix4x4 GetMatrixTranslate();
|
||||
|
||||
/**
|
||||
* @brief Return the complete translation and scale matrix
|
||||
* This must be used if you want the entire transformation pipeline (scale and translate).
|
||||
*/
|
||||
QMatrix4x4 GetCompleteMatrix();
|
||||
|
||||
/**
|
||||
* @brief Return the complete translation and scale matrix but with the Y translation flipped
|
||||
* as OpenGL stores textures "upside down".
|
||||
@@ -93,12 +87,6 @@ public:
|
||||
|
||||
FramePtr last_loaded_buffer() const;
|
||||
|
||||
/**
|
||||
* @brief Return a QTransform that contains all the scale and translation data (inc. mouse drags)
|
||||
* that can be used to set the world transform for a QPainter.
|
||||
*/
|
||||
QTransform GenerateWorldTransform();
|
||||
|
||||
/**
|
||||
* @brief Transform a point from viewer space to the buffer space.
|
||||
* Multiplies by the inverted transform matrix to undo the scaling and translation.
|
||||
@@ -117,7 +105,7 @@ public slots:
|
||||
* Set this if you want the drawing to pass through some sort of transform (most of the time you won't want this).
|
||||
*/
|
||||
void SetMatrixTranslate(const QMatrix4x4& mat);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the scale matrix.
|
||||
*/
|
||||
@@ -140,18 +128,11 @@ public slots:
|
||||
*/
|
||||
void SetImage(FramePtr in_buffer);
|
||||
|
||||
/**
|
||||
* @brief Set zoomed_ flag if the viewersizer has zoomed the image to be larger than the widget.
|
||||
*
|
||||
* If the image is smaller than the widget the translation is reset so the image is centered.
|
||||
*/
|
||||
void IsZoomed(bool flag);
|
||||
|
||||
/**
|
||||
* @brief Changes the pointer type if the tool is changed to the hand tool. Otherwise resets the pointer to it's
|
||||
* normal type.
|
||||
*/
|
||||
void ToolChanged(Tool::Item tool);
|
||||
void UpdateCursor();
|
||||
|
||||
/**
|
||||
* @brief Enables/disables a basic deinterlace on the viewer
|
||||
@@ -164,6 +145,21 @@ signals:
|
||||
*/
|
||||
void DragStarted();
|
||||
|
||||
/**
|
||||
* @brief Signal emitted when a hand drag starts
|
||||
*/
|
||||
void HandDragStarted();
|
||||
|
||||
/**
|
||||
* @brief Signal emitted when a hand drag moves
|
||||
*/
|
||||
void HandDragMoved(int x, int y);
|
||||
|
||||
/**
|
||||
* @brief Signal emitted when a hand drag ends
|
||||
*/
|
||||
void HandDragEnded();
|
||||
|
||||
/**
|
||||
* @brief Signal emitted when cursor color is enabled and the user's mouse position changes
|
||||
*/
|
||||
@@ -206,6 +202,12 @@ private:
|
||||
|
||||
rational GetGizmoTime();
|
||||
|
||||
bool IsHandDrag(QMouseEvent* event) const;
|
||||
|
||||
void UpdateMatrix();
|
||||
|
||||
QTransform GenerateWorldTransform();
|
||||
|
||||
/**
|
||||
* @brief Internal reference to the OpenGL texture to draw. Set in SetTexture() and used in paintGL().
|
||||
*/
|
||||
@@ -221,7 +223,10 @@ private:
|
||||
*/
|
||||
QMatrix4x4 scale_matrix_;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Cached result of translate_matrix_ and scale_matrix_ multiplied
|
||||
*/
|
||||
QMatrix4x4 combined_matrix_;
|
||||
|
||||
bool signal_cursor_color_;
|
||||
|
||||
@@ -237,25 +242,11 @@ private:
|
||||
|
||||
FramePtr last_loaded_buffer_;
|
||||
|
||||
/**
|
||||
* @brief Tells us if the image is zoomed in to be larger than the container widget.
|
||||
*/
|
||||
bool zoomed_;
|
||||
|
||||
/**
|
||||
* @brief Position of mouse to calculate delta from.
|
||||
*/
|
||||
QPoint position_;
|
||||
|
||||
/**
|
||||
* @brief Set if the hand tool is selected.
|
||||
*/
|
||||
bool hand_tool_;
|
||||
|
||||
/**
|
||||
* @brief Set if the hand tool is selected and viewer is clicked.
|
||||
*/
|
||||
bool hand_tool_clicked_;
|
||||
QPoint hand_last_drag_pos_;
|
||||
bool hand_dragging_;
|
||||
|
||||
bool deinterlace_;
|
||||
|
||||
|
||||
@@ -32,6 +32,13 @@ ViewerSizer::ViewerSizer(QWidget *parent) :
|
||||
pixel_aspect_(1),
|
||||
zoom_(0)
|
||||
{
|
||||
horiz_scrollbar_ = new QScrollBar(Qt::Horizontal, this);
|
||||
horiz_scrollbar_->setVisible(false);
|
||||
connect(horiz_scrollbar_, &QScrollBar::valueChanged, this, &ViewerSizer::ScrollBarMoved);
|
||||
|
||||
vert_scrollbar_ = new QScrollBar(Qt::Vertical, this);
|
||||
vert_scrollbar_->setVisible(false);
|
||||
connect(vert_scrollbar_, &QScrollBar::valueChanged, this, &ViewerSizer::ScrollBarMoved);
|
||||
}
|
||||
|
||||
void ViewerSizer::SetWidget(QWidget *widget)
|
||||
@@ -70,6 +77,17 @@ void ViewerSizer::SetZoom(int percent)
|
||||
UpdateSize();
|
||||
}
|
||||
|
||||
void ViewerSizer::HandDragMove(int x, int y)
|
||||
{
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
horiz_scrollbar_->setValue(horiz_scrollbar_->value() - x);
|
||||
}
|
||||
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
vert_scrollbar_->setValue(vert_scrollbar_->value() - y);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerSizer::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
QWidget::resizeEvent(event);
|
||||
@@ -94,58 +112,147 @@ void ViewerSizer::UpdateSize()
|
||||
QSize child_size;
|
||||
QMatrix4x4 child_matrix;
|
||||
|
||||
double sequence_aspect_ratio = static_cast<double>(width_) / static_cast<double>(height_) * pixel_aspect_.toDouble();
|
||||
int available_width = width();
|
||||
int available_height = height();
|
||||
double sequence_aspect_ratio = static_cast<double>(width_) / static_cast<double>(height_)
|
||||
* pixel_aspect_.toDouble();
|
||||
|
||||
if (zoom_ <= 0) {
|
||||
|
||||
// If zoom is 0, we auto-fit
|
||||
double our_aspect_ratio = static_cast<double>(width()) / static_cast<double>(height());
|
||||
// If zoom is zero or negative, we auto-fit
|
||||
double our_aspect_ratio = static_cast<double>(available_width) / static_cast<double>(available_height);
|
||||
|
||||
child_size = size();
|
||||
|
||||
if (our_aspect_ratio > sequence_aspect_ratio) {
|
||||
// This container is wider than the image, scale by height
|
||||
child_size = QSize(qRound(child_size.height() * sequence_aspect_ratio), height());
|
||||
child_size = QSize(qRound(child_size.height() * sequence_aspect_ratio), available_height);
|
||||
} else {
|
||||
// This container is taller than the image, scale by width
|
||||
child_size = QSize(width(), qRound(child_size.width() / sequence_aspect_ratio));
|
||||
child_size = QSize(available_width, qRound(child_size.width() / sequence_aspect_ratio));
|
||||
}
|
||||
emit IsZoomed(false);
|
||||
|
||||
// No scrollbars necessary for auto-fit
|
||||
horiz_scrollbar_->setVisible(false);
|
||||
vert_scrollbar_->setVisible(false);
|
||||
|
||||
} else {
|
||||
|
||||
float x_scale = 1.0f;
|
||||
float y_scale = 1.0f;
|
||||
// Translation is only active if the image is bigger then the widget
|
||||
// See ViewerDisplayWidget::SetZoomData
|
||||
bool zoomed_in = false;
|
||||
|
||||
int zoomed_width = qRound(width_ * static_cast<double>(zoom_) * 0.01);
|
||||
int zoomed_height = qRound(height_ * static_cast<double>(zoom_) * 0.01);
|
||||
int zoomed_width = GetZoomedValue(width_);
|
||||
int zoomed_height = GetZoomedValue(height_);
|
||||
|
||||
if (zoomed_width > width()) {
|
||||
x_scale = static_cast<double>(zoomed_width) / static_cast<double>(width());
|
||||
zoomed_width = width();
|
||||
zoomed_in = true;
|
||||
bool child_exceeds_parent_width = (zoomed_width > available_width);
|
||||
bool child_exceeds_parent_height = (zoomed_height > available_height);
|
||||
|
||||
if (child_exceeds_parent_width != child_exceeds_parent_height) {
|
||||
// One scrollbar definitely needs to be shown, so it's a matter of determining if the other
|
||||
// does too since adding one scrollbar necessary limits the total area
|
||||
|
||||
if (child_exceeds_parent_height) {
|
||||
// A vertical scrollbar will need to be shown, which limits the width
|
||||
child_exceeds_parent_width = (zoomed_width > available_width - vert_scrollbar_->sizeHint().width());
|
||||
} else {
|
||||
// A horizontal scrollbar will need to be shown, which limits the height
|
||||
child_exceeds_parent_height = (zoomed_height > available_height - horiz_scrollbar_->sizeHint().height());
|
||||
}
|
||||
}
|
||||
|
||||
if (zoomed_height > height()) {
|
||||
y_scale = static_cast<double>(zoomed_height) / static_cast<double>(height());
|
||||
zoomed_height = height();
|
||||
zoomed_in = true;
|
||||
horiz_scrollbar_->setVisible(child_exceeds_parent_width);
|
||||
vert_scrollbar_->setVisible(child_exceeds_parent_height);
|
||||
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
// Limit available width for further calculations
|
||||
available_width -= vert_scrollbar_->sizeHint().width();
|
||||
}
|
||||
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
// Limit available height for further calculations
|
||||
available_height -= horiz_scrollbar_->sizeHint().height();
|
||||
}
|
||||
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
x_scale = static_cast<double>(zoomed_width) / static_cast<double>(available_width);
|
||||
|
||||
// Update scrollbar sizes
|
||||
int horiz_width = this->width();
|
||||
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
horiz_width -= vert_scrollbar_->sizeHint().width();
|
||||
}
|
||||
|
||||
horiz_scrollbar_->resize(horiz_width, horiz_scrollbar_->sizeHint().height());
|
||||
horiz_scrollbar_->move(0, this->height() - horiz_scrollbar_->height() - 1);
|
||||
horiz_scrollbar_->setMaximum(zoomed_width - available_width);
|
||||
horiz_scrollbar_->setPageStep(available_width);
|
||||
|
||||
zoomed_width = available_width;
|
||||
}
|
||||
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
y_scale = static_cast<double>(zoomed_height) / static_cast<double>(available_height);
|
||||
|
||||
// Update scrollbar sizes
|
||||
int vert_height = this->height();
|
||||
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
vert_height -= horiz_scrollbar_->sizeHint().height();
|
||||
}
|
||||
|
||||
vert_scrollbar_->resize(vert_scrollbar_->sizeHint().width(), vert_height);
|
||||
vert_scrollbar_->move(this->width() - vert_scrollbar_->width() - 1, 0);
|
||||
vert_scrollbar_->setMaximum(zoomed_height - available_height);
|
||||
vert_scrollbar_->setPageStep(available_height);
|
||||
|
||||
zoomed_height = available_height;
|
||||
}
|
||||
|
||||
// Rather than make a huge surface, we still crop at our width/height and then signal a matrix
|
||||
child_matrix.scale(x_scale, y_scale, 1.0F);
|
||||
|
||||
child_size = QSize(zoomed_width, zoomed_height);
|
||||
emit IsZoomed(zoomed_in);
|
||||
}
|
||||
|
||||
widget_->resize(child_size);
|
||||
widget_->move(width() / 2 - child_size.width() / 2, height() / 2 - child_size.height() / 2);
|
||||
widget_->move(available_width / 2 - child_size.width() / 2,
|
||||
available_height / 2 - child_size.height() / 2);
|
||||
|
||||
emit RequestMatrix(child_matrix);
|
||||
emit RequestScale(child_matrix);
|
||||
|
||||
ScrollBarMoved();
|
||||
}
|
||||
|
||||
int ViewerSizer::GetZoomedValue(int value)
|
||||
{
|
||||
return qRound(value * static_cast<double>(zoom_) * 0.01);
|
||||
}
|
||||
|
||||
void ViewerSizer::ScrollBarMoved()
|
||||
{
|
||||
QMatrix4x4 mat;
|
||||
|
||||
float x_scroll, y_scroll;
|
||||
|
||||
if (horiz_scrollbar_->isVisible()) {
|
||||
int zoomed_width = GetZoomedValue(width_);
|
||||
x_scroll = (zoomed_width/2 - horiz_scrollbar_->value() - widget_->width() / 2) * (2.0 / zoomed_width);
|
||||
} else {
|
||||
x_scroll = 0;
|
||||
}
|
||||
|
||||
if (vert_scrollbar_->isVisible()) {
|
||||
int zoomed_height = GetZoomedValue(height_);
|
||||
y_scroll = (zoomed_height/2 - vert_scrollbar_->value() - widget_->height() / 2) * (2.0 / zoomed_height);
|
||||
} else {
|
||||
y_scroll = 0;
|
||||
}
|
||||
|
||||
// Zero translate is centered, so we need to determine how much "off center" we are
|
||||
mat.translate(x_scroll, y_scroll);
|
||||
|
||||
emit RequestTranslate(mat);
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#ifndef VIEWERSIZER_H
|
||||
#define VIEWERSIZER_H
|
||||
|
||||
#include <QScrollBar>
|
||||
#include <QWidget>
|
||||
|
||||
#include "common/define.h"
|
||||
@@ -69,13 +70,13 @@ public:
|
||||
*/
|
||||
void SetZoom(int percent);
|
||||
|
||||
signals:
|
||||
void RequestMatrix(const QMatrix4x4& matrix);
|
||||
public slots:
|
||||
void HandDragMove(int x, int y);
|
||||
|
||||
/**
|
||||
* @brief Tells the viewerdisplay widget if the image is enlarged to be bigger than the widget or not.
|
||||
*/
|
||||
void IsZoomed(bool flag);
|
||||
signals:
|
||||
void RequestScale(const QMatrix4x4& matrix);
|
||||
|
||||
void RequestTranslate(const QMatrix4x4& matrix);
|
||||
|
||||
protected:
|
||||
/**
|
||||
@@ -89,6 +90,8 @@ private:
|
||||
*/
|
||||
void UpdateSize();
|
||||
|
||||
int GetZoomedValue(int value);
|
||||
|
||||
/**
|
||||
* @brief Reference to widget
|
||||
*
|
||||
@@ -109,6 +112,12 @@ private:
|
||||
*/
|
||||
int zoom_;
|
||||
|
||||
QScrollBar* horiz_scrollbar_;
|
||||
QScrollBar* vert_scrollbar_;
|
||||
|
||||
private slots:
|
||||
void ScrollBarMoved();
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
Reference in New Issue
Block a user