improved resizable scrollbar functionality
This commit is contained in:
@@ -48,53 +48,23 @@ void ResizableScrollBar::mousePressEvent(QMouseEvent *event)
|
||||
if (mouse_handle_state_ == kNotInHandle) {
|
||||
QScrollBar::mousePressEvent(event);
|
||||
} else {
|
||||
mouse_dragging_ = true;
|
||||
dragging_ = true;
|
||||
|
||||
mouse_drag_start_ = GetActiveMousePos(event);
|
||||
drag_start_point_ = GetActiveMousePos(event);
|
||||
|
||||
emit ResizeBegan(GetActiveBarSize(), (mouse_handle_state_ == kInTopHandle));
|
||||
}
|
||||
}
|
||||
|
||||
void ResizableScrollBar::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
QStyleOptionSlider opt;
|
||||
initStyleOption(&opt);
|
||||
QRect sr = GetScrollBarRect();
|
||||
|
||||
QRect sr = style()->subControlRect(QStyle::CC_ScrollBar, &opt,
|
||||
QStyle::SC_ScrollBarSlider, this);
|
||||
if (dragging_) {
|
||||
// Determine how much the cursor has moved
|
||||
int mouse_movement = GetActiveMousePos(event) - drag_start_point_;
|
||||
|
||||
if (mouse_dragging_) {
|
||||
int new_drag_pos = GetActiveMousePos(event);
|
||||
int mouse_movement = new_drag_pos - mouse_drag_start_;
|
||||
mouse_drag_start_ = new_drag_pos;
|
||||
|
||||
if (mouse_handle_state_ == kInTopHandle) {
|
||||
mouse_movement = -mouse_movement;
|
||||
}
|
||||
|
||||
double width_adjustment = static_cast<double>(sr.width() + mouse_movement);
|
||||
|
||||
// Prevent dividing by zero or emitting a negative scale
|
||||
if (width_adjustment > 0) {
|
||||
double scale_multiplier = static_cast<double>(sr.width()) / width_adjustment;
|
||||
emit RequestScale(scale_multiplier);
|
||||
|
||||
if (mouse_handle_state_ == kInTopHandle) {
|
||||
QRect gr = style()->subControlRect(QStyle::CC_ScrollBar, &opt,
|
||||
QStyle::SC_ScrollBarGroove, this);
|
||||
|
||||
int slider_min = gr.x();
|
||||
int slider_max = gr.right() - (sr.width() + mouse_movement);
|
||||
int val = QStyle::sliderValueFromPosition(minimum(),
|
||||
maximum(),
|
||||
event->pos().x() - slider_min,
|
||||
slider_max - slider_min,
|
||||
opt.upsideDown);
|
||||
|
||||
setValue(val);
|
||||
} else {
|
||||
setValue(qRound(static_cast<double>(value()) * scale_multiplier));
|
||||
}
|
||||
}
|
||||
emit ResizeMoved(mouse_movement);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -133,13 +103,27 @@ void ResizableScrollBar::mouseMoveEvent(QMouseEvent *event)
|
||||
|
||||
void ResizableScrollBar::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (mouse_dragging_) {
|
||||
mouse_dragging_ = false;
|
||||
if (dragging_) {
|
||||
dragging_ = false;
|
||||
|
||||
emit ResizeEnded();
|
||||
} else {
|
||||
QScrollBar::mouseReleaseEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
QRect ResizableScrollBar::GetScrollBarRect()
|
||||
{
|
||||
// Initialize "style option". I don't know what this does, I just ripped it straight from
|
||||
// Qt source code
|
||||
QStyleOptionSlider opt;
|
||||
initStyleOption(&opt);
|
||||
|
||||
// Determine rect of slider bar
|
||||
return style()->subControlRect(QStyle::CC_ScrollBar, &opt,
|
||||
QStyle::SC_ScrollBarSlider, this);
|
||||
}
|
||||
|
||||
void ResizableScrollBar::Init()
|
||||
{
|
||||
setSingleStep(20);
|
||||
@@ -147,7 +131,7 @@ void ResizableScrollBar::Init()
|
||||
setMouseTracking(true);
|
||||
|
||||
mouse_handle_state_= kNotInHandle;
|
||||
mouse_dragging_ = false;
|
||||
dragging_ = false;
|
||||
}
|
||||
|
||||
int ResizableScrollBar::GetActiveMousePos(QMouseEvent *event)
|
||||
@@ -159,4 +143,15 @@ int ResizableScrollBar::GetActiveMousePos(QMouseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
int ResizableScrollBar::GetActiveBarSize()
|
||||
{
|
||||
QRect sr = GetScrollBarRect();
|
||||
|
||||
if (orientation() == Qt::Horizontal) {
|
||||
return sr.width();
|
||||
} else {
|
||||
return sr.height();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,7 +35,11 @@ public:
|
||||
ResizableScrollBar(Qt::Orientation orientation, QWidget* parent = nullptr);
|
||||
|
||||
signals:
|
||||
void RequestScale(const double& multiplier);
|
||||
void ResizeBegan(int old_bar_width, bool top_handle);
|
||||
|
||||
void ResizeMoved(int movement);
|
||||
|
||||
void ResizeEnded();
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||
@@ -45,6 +49,8 @@ protected:
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
|
||||
private:
|
||||
QRect GetScrollBarRect();
|
||||
|
||||
static const int kHandleWidth;
|
||||
|
||||
enum MouseHandleState {
|
||||
@@ -57,11 +63,13 @@ private:
|
||||
|
||||
int GetActiveMousePos(QMouseEvent* event);
|
||||
|
||||
int GetActiveBarSize();
|
||||
|
||||
MouseHandleState mouse_handle_state_;
|
||||
|
||||
bool mouse_dragging_;
|
||||
bool dragging_;
|
||||
|
||||
int mouse_drag_start_;
|
||||
int drag_start_point_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -44,7 +44,8 @@ TimeBasedWidget::TimeBasedWidget(bool ruler_text_visible, bool ruler_cache_statu
|
||||
connect(ruler_, &TimeRuler::TimeChanged, this, &TimeBasedWidget::SetTimeAndSignal);
|
||||
|
||||
scrollbar_ = new ResizableTimelineScrollBar(Qt::Horizontal, this);
|
||||
connect(scrollbar_, &ResizableScrollBar::RequestScale, this, &TimeBasedWidget::ScrollBarResized);
|
||||
connect(scrollbar_, &ResizableScrollBar::ResizeBegan, this, &TimeBasedWidget::ScrollBarResizeBegan);
|
||||
connect(scrollbar_, &ResizableScrollBar::ResizeMoved, this, &TimeBasedWidget::ScrollBarResizeMoved);
|
||||
|
||||
PassWheelEventsToScrollBar(ruler_);
|
||||
}
|
||||
@@ -126,7 +127,7 @@ void TimeBasedWidget::ConnectViewerNode(ViewerOutput *node)
|
||||
|
||||
void TimeBasedWidget::UpdateMaximumScroll()
|
||||
{
|
||||
rational length = (viewer_node_) ? viewer_node_->GetLength() : rational();
|
||||
rational length = (viewer_node_) ? viewer_node_->GetLength() : 0;
|
||||
|
||||
if (auto_max_scrollbar_) {
|
||||
scrollbar_->setMaximum(qMax(0, qCeil(TimeToScene(length)) - width()));
|
||||
@@ -137,27 +138,47 @@ void TimeBasedWidget::UpdateMaximumScroll()
|
||||
}
|
||||
}
|
||||
|
||||
void TimeBasedWidget::ScrollBarResized(const double &multiplier)
|
||||
void TimeBasedWidget::ScrollBarResizeBegan(int current_bar_width, bool top_handle)
|
||||
{
|
||||
QScrollBar* bar = static_cast<QScrollBar*>(sender());
|
||||
|
||||
// Our extension area (represented by a TimelineViewEndItem) is NOT scaled, but the ResizableScrollBar doesn't know
|
||||
// this. Here we re-calculate the requested scale knowing that the end item is not affected by scale.
|
||||
scrollbar_start_width_ = current_bar_width;
|
||||
scrollbar_start_value_ = bar->value();
|
||||
scrollbar_start_scale_ = GetScale();
|
||||
scrollbar_top_handle_ = top_handle;
|
||||
}
|
||||
|
||||
int current_max = bar->maximum();
|
||||
double proposed_max = static_cast<double>(current_max) * multiplier;
|
||||
void TimeBasedWidget::ScrollBarResizeMoved(int movement)
|
||||
{
|
||||
ResizableScrollBar* bar = static_cast<ResizableScrollBar*>(sender());
|
||||
|
||||
proposed_max = proposed_max - (bar->width() * 0.5 / multiplier) + (bar->width() * 0.5);
|
||||
|
||||
double corrected_scale;
|
||||
|
||||
if (current_max == 0) {
|
||||
corrected_scale = multiplier;
|
||||
} else {
|
||||
corrected_scale = (proposed_max / static_cast<double>(current_max));
|
||||
// Negate movement for the top handle
|
||||
if (scrollbar_top_handle_) {
|
||||
movement = -movement;
|
||||
}
|
||||
|
||||
SetScale(GetScale() * corrected_scale);
|
||||
// The user wants the bar to be this size
|
||||
int proposed_size = scrollbar_start_width_ + movement;
|
||||
|
||||
double ratio = double(scrollbar_start_width_) / double(proposed_size);
|
||||
|
||||
if (ratio > 0) {
|
||||
SetScale(scrollbar_start_scale_ * ratio);
|
||||
|
||||
if (scrollbar_top_handle_) {
|
||||
int viewable_area;
|
||||
|
||||
if (timeline_views_.isEmpty()) {
|
||||
viewable_area = width();
|
||||
} else {
|
||||
viewable_area = timeline_views_.first()->width();
|
||||
}
|
||||
|
||||
bar->setValue((scrollbar_start_value_ + viewable_area) * ratio - viewable_area);
|
||||
} else {
|
||||
bar->setValue(scrollbar_start_value_ * ratio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimeBasedWidget::PageScrollToPlayhead()
|
||||
@@ -492,7 +513,7 @@ void TimeBasedWidget::SetMarker()
|
||||
bool ok;
|
||||
QString marker_name;
|
||||
|
||||
if (Config::Current()["SetNameWithMarker"].toBool()) {
|
||||
if (Config::Current()[QStringLiteral("SetNameWithMarker")].toBool()) {
|
||||
marker_name = QInputDialog::getText(this, tr("Set Marker"), tr("Marker name:"), QLineEdit::Normal, QString(), &ok);
|
||||
} else {
|
||||
ok = true;
|
||||
|
||||
@@ -205,10 +205,17 @@ private:
|
||||
|
||||
QVector<QObject*> wheel_passthrough_objects_;
|
||||
|
||||
int scrollbar_start_width_;
|
||||
double scrollbar_start_value_;
|
||||
double scrollbar_start_scale_;
|
||||
bool scrollbar_top_handle_;
|
||||
|
||||
private slots:
|
||||
void UpdateMaximumScroll();
|
||||
|
||||
void ScrollBarResized(const double& multiplier);
|
||||
void ScrollBarResizeBegan(int current_bar_width, bool top_handle);
|
||||
|
||||
void ScrollBarResizeMoved(int new_bar_width);
|
||||
|
||||
/**
|
||||
* @brief Slot to handle page scrolling of the playhead
|
||||
|
||||
Reference in New Issue
Block a user