diff --git a/data/themes/classic/autoscroll_continuous_on.png b/data/themes/classic/autoscroll_continuous_on.png new file mode 100644 index 000000000..0140d5cc5 Binary files /dev/null and b/data/themes/classic/autoscroll_continuous_on.png differ diff --git a/data/themes/classic/autoscroll_stepped_on.png b/data/themes/classic/autoscroll_stepped_on.png new file mode 100644 index 000000000..e54489f7a Binary files /dev/null and b/data/themes/classic/autoscroll_stepped_on.png differ diff --git a/data/themes/default/autoscroll_continuous_on.png b/data/themes/default/autoscroll_continuous_on.png new file mode 100644 index 000000000..7f27a7f7d Binary files /dev/null and b/data/themes/default/autoscroll_continuous_on.png differ diff --git a/data/themes/default/autoscroll_stepped_on.png b/data/themes/default/autoscroll_stepped_on.png new file mode 100644 index 000000000..c58fa97b2 Binary files /dev/null and b/data/themes/default/autoscroll_stepped_on.png differ 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)); } }