diff --git a/src/app/configs/data/shortcuts.xml b/src/app/configs/data/shortcuts.xml index 7107e705508ac..184dfd0ff2061 100644 --- a/src/app/configs/data/shortcuts.xml +++ b/src/app/configs/data/shortcuts.xml @@ -797,6 +797,11 @@ Ctrl+Return Ctrl+Enter + + apply-system-lock + Alt+Return + Alt+Enter + move-measure-to-prev-system Alt+Up diff --git a/src/app/configs/data/shortcuts_azerty.xml b/src/app/configs/data/shortcuts_azerty.xml index 7dc7ccc57fcb7..eaf65a8fbc06b 100644 --- a/src/app/configs/data/shortcuts_azerty.xml +++ b/src/app/configs/data/shortcuts_azerty.xml @@ -823,6 +823,11 @@ Ctrl+Return Ctrl+Enter + + apply-system-lock + Alt+Return + Alt+Enter + move-measure-to-prev-system Alt+Up diff --git a/src/app/configs/data/shortcuts_mac.xml b/src/app/configs/data/shortcuts_mac.xml index 1cf9ae5fbbd7f..a0cf1bc90ae79 100644 --- a/src/app/configs/data/shortcuts_mac.xml +++ b/src/app/configs/data/shortcuts_mac.xml @@ -797,6 +797,11 @@ Ctrl+Return Ctrl+Enter + + apply-system-lock + Alt+Return + Alt+Enter + move-measure-to-prev-system Alt+Up diff --git a/src/engraving/dom/cmd.cpp b/src/engraving/dom/cmd.cpp index eb2b30b16a695..b06124d5dcd3a 100644 --- a/src/engraving/dom/cmd.cpp +++ b/src/engraving/dom/cmd.cpp @@ -4777,6 +4777,40 @@ void Score::cmdToggleSystemLock() toggleSystemLock(m_selection.selectedSystems()); } +void Score::cmdApplyLockToSelection() +{ + MeasureBase* first = nullptr; + MeasureBase* last = nullptr; + + if (selection().isRange()) { + first = selection().startMeasureBase(); + last = selection().endMeasureBase(); + } else { + for (EngravingItem* el : selection().elements()) { + MeasureBase* mb = el->findMeasureBase(); + if (!mb) { + continue; + } + if (!first || mb->isBefore(first)) { + first = mb; + } + if (!last || mb->isAfter(last)) { + last = mb; + } + } + } + + if (!first || !last) { + return; + } + + if (first != last) { + makeIntoSystem(first, last); + } else { + makeIntoSystem(first->system()->first(), last); + } +} + void Score::cmdToggleScoreLock() { bool unlockAll = true; @@ -4815,40 +4849,7 @@ void Score::cmdMakeIntoSystem() return; } - bool mmrests = style().styleB(Sid::createMultiMeasureRests); - - const SystemLock* lockContainingFirstSelected = m_systemLocks.lockContaining(firstSelected); - const SystemLock* lockContainingLastSelected = m_systemLocks.lockContaining(lastSelected); - - if (lockContainingFirstSelected) { - undoRemoveSystemLock(lockContainingFirstSelected); - if (lockContainingFirstSelected->startMB()->isBefore(firstSelected)) { - MeasureBase* oneBeforeFirst = mmrests ? firstSelected->prevMM() : firstSelected->prev(); - SystemLock* newLockBefore = new SystemLock(lockContainingFirstSelected->startMB(), oneBeforeFirst); - undoAddSystemLock(newLockBefore); - } - } - - if (lockContainingLastSelected) { - if (lockContainingLastSelected != lockContainingFirstSelected) { - undoRemoveSystemLock(lockContainingLastSelected); - } - if (lastSelected->isBefore(lockContainingLastSelected->endMB())) { - MeasureBase* oneAfterLast = mmrests ? lastSelected->nextMM() : lastSelected->next(); - SystemLock* newLockAfter = new SystemLock(oneAfterLast, lockContainingLastSelected->endMB()); - undoAddSystemLock(newLockAfter); - } - } - - std::vector locksContainedInRange = m_systemLocks.locksContainedInRange(firstSelected, lastSelected); - for (const SystemLock* lock : locksContainedInRange) { - if (lock != lockContainingFirstSelected && lock != lockContainingLastSelected) { - undoRemoveSystemLock(lock); - } - } - - SystemLock* newLock = new SystemLock(firstSelected, lastSelected); - undoAddSystemLock(newLock); + makeIntoSystem(firstSelected, lastSelected); } void Score::cmdAddStaffTypeChange(Measure* measure, staff_idx_t staffIdx, StaffTypeChange* stc) diff --git a/src/engraving/dom/edit.cpp b/src/engraving/dom/edit.cpp index b57e1b00aca48..3cd5cdc45c0c1 100644 --- a/src/engraving/dom/edit.cpp +++ b/src/engraving/dom/edit.cpp @@ -6555,6 +6555,44 @@ void Score::toggleSystemLock(const std::vector& systems) } } +void Score::makeIntoSystem(MeasureBase* first, MeasureBase* last) +{ + bool mmrests = style().styleB(Sid::createMultiMeasureRests); + + const SystemLock* lockContainingfirst = m_systemLocks.lockContaining(first); + const SystemLock* lockContaininglast = m_systemLocks.lockContaining(last); + + if (lockContainingfirst) { + undoRemoveSystemLock(lockContainingfirst); + if (lockContainingfirst->startMB()->isBefore(first)) { + MeasureBase* oneBeforeFirst = mmrests ? first->prevMM() : first->prev(); + SystemLock* newLockBefore = new SystemLock(lockContainingfirst->startMB(), oneBeforeFirst); + undoAddSystemLock(newLockBefore); + } + } + + if (lockContaininglast) { + if (lockContaininglast != lockContainingfirst) { + undoRemoveSystemLock(lockContaininglast); + } + if (last->isBefore(lockContaininglast->endMB())) { + MeasureBase* oneAfterLast = mmrests ? last->nextMM() : last->next(); + SystemLock* newLockAfter = new SystemLock(oneAfterLast, lockContaininglast->endMB()); + undoAddSystemLock(newLockAfter); + } + } + + std::vector locksContainedInRange = m_systemLocks.locksContainedInRange(first, last); + for (const SystemLock* lock : locksContainedInRange) { + if (lock != lockContainingfirst && lock != lockContaininglast) { + undoRemoveSystemLock(lock); + } + } + + SystemLock* newLock = new SystemLock(first, last); + undoAddSystemLock(newLock); +} + void Score::removeSystemLocksOnAddLayoutBreak(LayoutBreakType breakType, const MeasureBase* measure) { IF_ASSERT_FAILED(breakType != LayoutBreakType::NOBREAK) { diff --git a/src/engraving/dom/measure.cpp b/src/engraving/dom/measure.cpp index 106a360200612..a6eafb70a9de3 100644 --- a/src/engraving/dom/measure.cpp +++ b/src/engraving/dom/measure.cpp @@ -1383,8 +1383,7 @@ bool Measure::acceptDrop(EditData& data) const { LayoutMode layoutMode = score()->layoutMode(); if (layoutMode == LayoutMode::PAGE || layoutMode == LayoutMode::SYSTEM) { - const System* sys = system(); - viewer->setDropRectangle(sys->canvasBoundingRect().adjusted(sys->leftMargin(), 0.0, 0.0, 0.0)); + viewer->setDropRectangle(canvasBoundingRect().adjusted(-x(), 0.0, 0.0, 0.0)); return true; } return false; @@ -1726,7 +1725,7 @@ EngravingItem* Measure::drop(EditData& data) break; } case ActionIconType::SYSTEM_LOCK: - score()->toggleSystemLock({ system() }); + score()->makeIntoSystem(system()->first(), this); break; default: break; diff --git a/src/engraving/dom/score.h b/src/engraving/dom/score.h index c62160725ddf9..695289dbe3259 100644 --- a/src/engraving/dom/score.h +++ b/src/engraving/dom/score.h @@ -361,6 +361,7 @@ class Score : public EngravingObject, public muse::Injectable void cmdMoveMeasureToPrevSystem(); void cmdMoveMeasureToNextSystem(); void cmdToggleSystemLock(); + void cmdApplyLockToSelection(); void cmdToggleScoreLock(); void cmdMakeIntoSystem(); void cmdAddStaffTypeChange(Measure* measure, staff_idx_t staffIdx, StaffTypeChange* stc); @@ -1018,6 +1019,7 @@ class Score : public EngravingObject, public muse::Injectable void undoRemoveSystemLock(const SystemLock* lock); void undoRemoveAllLocks(); void toggleSystemLock(const std::vector& systems); + void makeIntoSystem(MeasureBase* first, MeasureBase* last); void removeSystemLocksOnAddLayoutBreak(LayoutBreakType breakType, const MeasureBase* measure); void removeLayoutBreaksOnAddSystemLock(const SystemLock* lock); diff --git a/src/notation/inotationinteraction.h b/src/notation/inotationinteraction.h index a3295246f6a4a..77407c1a3f38f 100644 --- a/src/notation/inotationinteraction.h +++ b/src/notation/inotationinteraction.h @@ -205,6 +205,7 @@ class INotationInteraction virtual void toggleSystemLock() = 0; virtual void toggleScoreLock() = 0; virtual void makeIntoSystem() = 0; + virtual void applySystemLock() = 0; virtual void addRemoveSystemLocks(AddRemoveSystemLockType intervalType, int interval = 0) = 0; virtual bool transpose(const TransposeOptions& options) = 0; diff --git a/src/notation/internal/notationactioncontroller.cpp b/src/notation/internal/notationactioncontroller.cpp index 1c6ccc6cd3d76..3475f7fee77fa 100644 --- a/src/notation/internal/notationactioncontroller.cpp +++ b/src/notation/internal/notationactioncontroller.cpp @@ -256,6 +256,7 @@ void NotationActionController::init() registerAction("section-break", &Interaction::toggleLayoutBreak, LayoutBreakType::SECTION, PlayMode::NoPlay, &Controller::toggleLayoutBreakAvailable); + registerAction("apply-system-lock", &Interaction::applySystemLock); registerAction("move-measure-to-prev-system", &Interaction::moveMeasureToPrevSystem); registerAction("move-measure-to-next-system", &Interaction::moveMeasureToNextSystem); registerAction("toggle-system-lock", &Interaction::toggleSystemLock); diff --git a/src/notation/internal/notationinteraction.cpp b/src/notation/internal/notationinteraction.cpp index 095735af6108f..e6b68d77f0471 100644 --- a/src/notation/internal/notationinteraction.cpp +++ b/src/notation/internal/notationinteraction.cpp @@ -1763,7 +1763,7 @@ bool NotationInteraction::applyPaletteElement(mu::engraving::EngravingItem* elem mu::engraving::LayoutBreak* breakElement = toLayoutBreak(element); score->cmdToggleLayoutBreak(breakElement->layoutBreakType()); } else if (element->isActionIcon() && toActionIcon(element)->actionType() == ActionIconType::SYSTEM_LOCK) { - score->cmdToggleSystemLock(); + score->cmdApplyLockToSelection(); } else if (element->isSlur() && addSingle) { doAddSlur(toSlur(element)); } else if (element->isSLine() && !element->isGlissando() && !element->isGuitarBend() && addSingle) { @@ -2022,9 +2022,7 @@ bool NotationInteraction::applyPaletteElement(mu::engraving::EngravingItem* elem } } } else if (element->isActionIcon() && toActionIcon(element)->actionType() == ActionIconType::SYSTEM_LOCK) { - if (sel.isRange()) { - score->toggleSystemLock(sel.selectedSystems()); - } + score->cmdApplyLockToSelection(); } else { track_idx_t track1 = sel.staffStart() * mu::engraving::VOICES; track_idx_t track2 = sel.staffEnd() * mu::engraving::VOICES; @@ -4529,6 +4527,13 @@ void NotationInteraction::makeIntoSystem() apply(); } +void NotationInteraction::applySystemLock() +{ + startEdit(TranslatableString("undoableAction", "Apply system lock to selection")); + score()->cmdApplyLockToSelection(); + apply(); +} + void NotationInteraction::addRemoveSystemLocks(AddRemoveSystemLockType intervalType, int interval) { interval = intervalType == AddRemoveSystemLockType::MeasuresInterval ? interval : 0; diff --git a/src/notation/internal/notationinteraction.h b/src/notation/internal/notationinteraction.h index 688e5f95aeee9..8d88caeb014b6 100644 --- a/src/notation/internal/notationinteraction.h +++ b/src/notation/internal/notationinteraction.h @@ -208,6 +208,7 @@ class NotationInteraction : public INotationInteraction, public muse::Injectable void toggleSystemLock() override; void toggleScoreLock() override; void makeIntoSystem() override; + void applySystemLock() override; void addRemoveSystemLocks(AddRemoveSystemLockType intervalType, int interval = 0) override; bool transpose(const TransposeOptions& options) override; diff --git a/src/notation/internal/notationuiactions.cpp b/src/notation/internal/notationuiactions.cpp index 083c97e70d587..400eef56ca81a 100644 --- a/src/notation/internal/notationuiactions.cpp +++ b/src/notation/internal/notationuiactions.cpp @@ -631,6 +631,12 @@ const UiActionList NotationUiActions::m_actions = { TranslatableString("action", "Add/remove page break"), TranslatableString("action", "Add/remove page break") ), + UiAction("apply-system-lock", + mu::context::UiCtxProjectOpened, + mu::context::CTX_NOTATION_FOCUSED, + TranslatableString("action", "Add/remove system lock"), + TranslatableString("action", "Add/remove system lock") + ), UiAction("move-measure-to-prev-system", mu::context::UiCtxProjectOpened, mu::context::CTX_NOTATION_FOCUSED, diff --git a/src/notation/tests/mocks/notationinteractionmock.h b/src/notation/tests/mocks/notationinteractionmock.h index 91f37f276d721..1b61735efa7b6 100644 --- a/src/notation/tests/mocks/notationinteractionmock.h +++ b/src/notation/tests/mocks/notationinteractionmock.h @@ -167,6 +167,7 @@ class NotationInteractionMock : public INotationInteraction MOCK_METHOD(void, toggleSystemLock, (), (override)); MOCK_METHOD(void, toggleScoreLock, (), (override)); MOCK_METHOD(void, makeIntoSystem, (), (override)); + MOCK_METHOD(void, applySystemLock, (), (override)); MOCK_METHOD(void, addRemoveSystemLocks, (AddRemoveSystemLockType, int), (override)); MOCK_METHOD(bool, transpose, (const TransposeOptions&), (override));