From ce17c956368789d6add77c57bba5e0a8bb63942a Mon Sep 17 00:00:00 2001 From: regulus79 <117475203+regulus79@users.noreply.github.com> Date: Sun, 4 Aug 2024 04:30:42 -0400 Subject: [PATCH] Add Continuous Auto-Scrolling (#7396) * Initial Commit * Refactor code and add new icons * Fix logical error * Add smooth scrolling to Song Editor * Remove unused variable * Fix scrolling speed and scrollbar width * Remove QDebug and re-add a newline I deleted in an unrelated file * Forgot to add files to commit * Remove unused variable * Fix Styling * Fix Styling Again * Fix Styling Again * Fix Styling Again * Add icons for classic theme * Accidentally committed varying scroll speed with zoom -- removing * Change abs to std::abs Co-authored-by: saker * Change qMax to std::max and use static_cast Co-authored-by: saker * Simplify stepped auto scrolling Co-authored-by: saker * Remove unnecessary parentheses * Remove return statement causing the play head line to stop * Add specific tooltips to auto scrolling button states * Remove `== true` from SongEditor.cpp Co-authored-by: saker * Make tooltips translatable Co-authored-by: Dominic Clark * Fix zooming position calculation * Rename bars to ticks * Fix rubberband rect size --------- Co-authored-by: saker Co-authored-by: Dominic Clark --- .../classic/autoscroll_continuous_on.png | Bin 0 -> 9733 bytes data/themes/classic/autoscroll_stepped_on.png | Bin 0 -> 11905 bytes .../default/autoscroll_continuous_on.png | Bin 0 -> 7966 bytes data/themes/default/autoscroll_stepped_on.png | Bin 0 -> 8791 bytes include/TimeLineWidget.h | 5 +- src/gui/editors/PianoRoll.cpp | 32 ++++++---- src/gui/editors/SongEditor.cpp | 57 +++++++++--------- src/gui/editors/TimeLineWidget.cpp | 7 ++- src/gui/tracks/TrackContentWidget.cpp | 5 +- 9 files changed, 59 insertions(+), 47 deletions(-) create mode 100644 data/themes/classic/autoscroll_continuous_on.png create mode 100644 data/themes/classic/autoscroll_stepped_on.png create mode 100644 data/themes/default/autoscroll_continuous_on.png create mode 100644 data/themes/default/autoscroll_stepped_on.png diff --git a/data/themes/classic/autoscroll_continuous_on.png b/data/themes/classic/autoscroll_continuous_on.png new file mode 100644 index 0000000000000000000000000000000000000000..0140d5cc51733dd1475c2b9d3cb7b8f4b32ba4db GIT binary patch literal 9733 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 U&Y);L+HjjuHgC)}+eZ1d;&3q7iU_s6|wq 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 L1phd7e)iu1QwSX@ literal 0 HcmV?d00001 diff --git a/data/themes/default/autoscroll_stepped_on.png b/data/themes/default/autoscroll_stepped_on.png new file mode 100644 index 0000000000000000000000000000000000000000..c58fa97b2cfe6eb6a0b582b80b7c1d04f45f80c8 GIT binary patch literal 8791 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 H|4jd1D+9KA literal 0 HcmV?d00001 diff --git a/include/TimeLineWidget.h b/include/TimeLineWidget.h index 5c683cfd9..0eb33bad9 100644 --- a/include/TimeLineWidget.h +++ b/include/TimeLineWidget.h @@ -73,7 +73,8 @@ public: enum class AutoScrollState { - Enabled, + Stepped, + Continuous, Disabled }; @@ -212,7 +213,7 @@ private: QCursor m_cursorSelectLeft = QCursor{embed::getIconPixmap("cursor_select_left"), 0, 16}; QCursor m_cursorSelectRight = QCursor{embed::getIconPixmap("cursor_select_right"), 32, 16}; - AutoScrollState m_autoScroll = AutoScrollState::Enabled; + AutoScrollState m_autoScroll = AutoScrollState::Stepped; // Width of the unused region on the widget's left (above track labels or piano) int m_xOffset; diff --git a/src/gui/editors/PianoRoll.cpp b/src/gui/editors/PianoRoll.cpp index bda6894f3..1c89f6a0b 100644 --- a/src/gui/editors/PianoRoll.cpp +++ b/src/gui/editors/PianoRoll.cpp @@ -4062,7 +4062,7 @@ void PianoRoll::stop() { Engine::getSong()->stop(); m_recording = false; - m_scrollBack = ( m_timeLine->autoScroll() == TimeLineWidget::AutoScrollState::Enabled ); + m_scrollBack = m_timeLine->autoScroll() != TimeLineWidget::AutoScrollState::Disabled; } @@ -4463,30 +4463,36 @@ bool PianoRoll::deleteSelectedNotes() void PianoRoll::autoScroll( const TimePos & t ) { const int w = width() - m_whiteKeyWidth; - if( t > m_currentPosition + w * TimePos::ticksPerBar() / m_ppb ) + if (m_timeLine->autoScroll() == TimeLineWidget::AutoScrollState::Stepped) { - m_leftRightScroll->setValue( t.getBar() * TimePos::ticksPerBar() ); + if (t > m_currentPosition + w * TimePos::ticksPerBar() / m_ppb) + { + m_leftRightScroll->setValue(t.getBar() * TimePos::ticksPerBar()); + } + else if (t < m_currentPosition) + { + TimePos t2 = std::max(t - w * TimePos::ticksPerBar() * + TimePos::ticksPerBar() / m_ppb, static_cast(0)); + m_leftRightScroll->setValue(t2.getBar() * TimePos::ticksPerBar()); + } } - else if( t < m_currentPosition ) + else if (m_timeLine->autoScroll() == TimeLineWidget::AutoScrollState::Continuous) { - TimePos t2 = qMax( t - w * TimePos::ticksPerBar() * - TimePos::ticksPerBar() / m_ppb, (tick_t) 0 ); - m_leftRightScroll->setValue( t2.getBar() * TimePos::ticksPerBar() ); + m_leftRightScroll->setValue(std::max(t.getTicks() - w * TimePos::ticksPerBar() / m_ppb / 2, 0)); } m_scrollBack = false; } - -void PianoRoll::updatePosition( const TimePos & t ) +void PianoRoll::updatePosition(const TimePos & t) { - if( ( Engine::getSong()->isPlaying() + if ((Engine::getSong()->isPlaying() && Engine::getSong()->playMode() == Song::PlayMode::MidiClip - && m_timeLine->autoScroll() == TimeLineWidget::AutoScrollState::Enabled - ) || m_scrollBack ) + && m_timeLine->autoScroll() != TimeLineWidget::AutoScrollState::Disabled + ) || m_scrollBack) { - autoScroll( t ); + autoScroll(t); } // ticks relative to m_currentPosition // < 0 = outside viewport left diff --git a/src/gui/editors/SongEditor.cpp b/src/gui/editors/SongEditor.cpp index 9ba9ac083..f043e715a 100644 --- a/src/gui/editors/SongEditor.cpp +++ b/src/gui/editors/SongEditor.cpp @@ -231,10 +231,10 @@ SongEditor::SongEditor( Song * song ) : static_cast( layout() )->insertWidget( 0, m_timeLine ); m_leftRightScroll = new QScrollBar( Qt::Horizontal, this ); - m_leftRightScroll->setMinimum( 0 ); - m_leftRightScroll->setMaximum( 0 ); - m_leftRightScroll->setSingleStep( 1 ); - m_leftRightScroll->setPageStep( 20 ); + m_leftRightScroll->setMinimum(0); + m_leftRightScroll->setMaximum(0); + m_leftRightScroll->setSingleStep(1); + m_leftRightScroll->setPageStep(20 * TimePos::ticksPerBar()); static_cast( layout() )->addWidget( m_leftRightScroll ); connect( m_leftRightScroll, SIGNAL(valueChanged(int)), this, SLOT(scrolled(int))); @@ -325,7 +325,7 @@ QString SongEditor::getSnapSizeString() const void SongEditor::scrolled( int new_pos ) { update(); - emit positionChanged( m_currentPosition = TimePos( new_pos, 0 ) ); + emit positionChanged(m_currentPosition = TimePos(new_pos)); } @@ -384,7 +384,7 @@ void SongEditor::updateRubberband() } //take care of the scrollbar position - int hs = (m_leftRightScroll->value() - m_scrollPos.x()) * pixelsPerBar(); + int hs = (m_leftRightScroll->value() - m_scrollPos.x()) * pixelsPerBar() / TimePos::ticksPerBar(); int vs = contentWidget()->verticalScrollBar()->value() - m_scrollPos.y(); //the adjusted origin point @@ -522,8 +522,8 @@ void SongEditor::wheelEvent( QWheelEvent * we ) if ((we->modifiers() & Qt::ControlModifier) && (position(we).x() > m_trackHeadWidth)) { int x = position(we).x() - m_trackHeadWidth; - // bar based on the mouse x-position where the scroll wheel was used - int bar = x / pixelsPerBar(); + // tick based on the mouse x-position where the scroll wheel was used + int tick = x / pixelsPerBar() * TimePos::ticksPerBar(); // move zoom slider (pixelsPerBar will change automatically) int step = we->modifiers() & Qt::ShiftModifier ? 1 : 5; @@ -531,9 +531,9 @@ void SongEditor::wheelEvent( QWheelEvent * we ) int direction = (we->angleDelta().y() + we->angleDelta().x()) > 0 ? 1 : -1; m_zoomingModel->incValue(step * direction); - // scroll to zooming around cursor's bar - int newBar = static_cast(x / pixelsPerBar()); - m_leftRightScroll->setValue(m_leftRightScroll->value() + bar - newBar); + // scroll to zooming around cursor's tick + int newTick = static_cast(x / pixelsPerBar() * TimePos::ticksPerBar()); + m_leftRightScroll->setValue(m_leftRightScroll->value() + tick - newTick); // update timeline m_timeLine->setPixelsPerBar(pixelsPerBar()); @@ -542,15 +542,15 @@ void SongEditor::wheelEvent( QWheelEvent * we ) } // FIXME: Reconsider if determining orientation is necessary in Qt6. - else if(abs(we->angleDelta().x()) > abs(we->angleDelta().y())) // scrolling is horizontal + else if (std::abs(we->angleDelta().x()) > std::abs(we->angleDelta().y())) // scrolling is horizontal { - m_leftRightScroll->setValue(m_leftRightScroll->value() - - we->angleDelta().x() /30); + m_leftRightScroll->setValue(m_leftRightScroll->value() + - we->angleDelta().x()); } - else if(we->modifiers() & Qt::ShiftModifier) + else if (we->modifiers() & Qt::ShiftModifier) { - m_leftRightScroll->setValue(m_leftRightScroll->value() - - we->angleDelta().y() / 30); + m_leftRightScroll->setValue(m_leftRightScroll->value() + - we->angleDelta().y()); } else { @@ -711,9 +711,9 @@ void SongEditor::hideMasterPitchFloat( void ) -void SongEditor::updateScrollBar( int len ) +void SongEditor::updateScrollBar(int len) { - m_leftRightScroll->setMaximum( len ); + m_leftRightScroll->setMaximum(len * TimePos::ticksPerBar()); } @@ -756,22 +756,25 @@ void SongEditor::updatePosition( const TimePos & t ) const auto widgetWidth = compactTrackButtons ? DEFAULT_SETTINGS_WIDGET_WIDTH_COMPACT : DEFAULT_SETTINGS_WIDGET_WIDTH; const auto trackOpWidth = compactTrackButtons ? TRACK_OP_WIDTH_COMPACT : TRACK_OP_WIDTH; - if( ( m_song->isPlaying() && m_song->m_playMode == Song::PlayMode::Song - && m_timeLine->autoScroll() == TimeLineWidget::AutoScrollState::Enabled) || - m_scrollBack == true ) + if ((m_song->isPlaying() && m_song->m_playMode == Song::PlayMode::Song) + || m_scrollBack) { m_smoothScroll = ConfigManager::inst()->value( "ui", "smoothscroll" ).toInt(); const int w = width() - widgetWidth - trackOpWidth - contentWidget()->verticalScrollBar()->width(); // width of right scrollbar - if( t > m_currentPosition + w * TimePos::ticksPerBar() / - pixelsPerBar() ) + + if (m_timeLine->autoScroll() == TimeLineWidget::AutoScrollState::Stepped) { - animateScroll( m_leftRightScroll, t.getBar(), m_smoothScroll ); + const auto nextPosition = m_currentPosition + w * TimePos::ticksPerBar() / pixelsPerBar(); + if (t > nextPosition || t < m_currentPosition) + { + animateScroll(m_leftRightScroll, t.getTicks(), m_smoothScroll); + } } - else if( t < m_currentPosition ) + else if (m_timeLine->autoScroll() == TimeLineWidget::AutoScrollState::Continuous) { - animateScroll( m_leftRightScroll, t.getBar(), m_smoothScroll ); + animateScroll(m_leftRightScroll, std::max(t.getTicks() - w * TimePos::ticksPerBar() / pixelsPerBar() / 2, 0.0f), m_smoothScroll); } m_scrollBack = false; } diff --git a/src/gui/editors/TimeLineWidget.cpp b/src/gui/editors/TimeLineWidget.cpp index 7657e2916..f75b1cabf 100644 --- a/src/gui/editors/TimeLineWidget.cpp +++ b/src/gui/editors/TimeLineWidget.cpp @@ -88,9 +88,10 @@ void TimeLineWidget::setXOffset(const int x) void TimeLineWidget::addToolButtons( QToolBar * _tool_bar ) { auto autoScroll = new NStateButton(_tool_bar); - autoScroll->setGeneralToolTip( tr( "Auto scrolling" ) ); - autoScroll->addState( embed::getIconPixmap( "autoscroll_on" ) ); - autoScroll->addState( embed::getIconPixmap( "autoscroll_off" ) ); + autoScroll->setGeneralToolTip(tr("Auto scrolling")); + autoScroll->addState(embed::getIconPixmap("autoscroll_stepped_on"), tr("Stepped auto scrolling")); + autoScroll->addState(embed::getIconPixmap("autoscroll_continuous_on"), tr("Continuous auto scrolling")); + autoScroll->addState(embed::getIconPixmap("autoscroll_off"), tr("Auto scrolling disabled")); connect( autoScroll, SIGNAL(changedState(int)), this, SLOT(toggleAutoScroll(int))); diff --git a/src/gui/tracks/TrackContentWidget.cpp b/src/gui/tracks/TrackContentWidget.cpp index afea82ea4..1926ffeef 100644 --- a/src/gui/tracks/TrackContentWidget.cpp +++ b/src/gui/tracks/TrackContentWidget.cpp @@ -292,6 +292,7 @@ void TrackContentWidget::changePosition( const TimePos & newPos ) setUpdatesEnabled( true ); // redraw background + updateBackground(); // update(); } @@ -628,8 +629,8 @@ void TrackContentWidget::paintEvent( QPaintEvent * pe ) // Don't draw background on Pattern Editor if (m_trackView->trackContainerView() != getGUI()->patternEditor()->m_editor) { - p.drawTiledPixmap( rect(), m_background, QPoint( - tcv->currentPosition().getBar() * ppb, 0 ) ); + p.drawTiledPixmap(rect(), m_background, QPoint( + tcv->currentPosition().getTicks() * ppb / TimePos::ticksPerBar(), 0)); } }