Skip to content

Commit

Permalink
Merge pull request #26075 from mathesoncalum/percussion_refinements_5
Browse files Browse the repository at this point in the history
Percussion panel - refinements round 5
  • Loading branch information
mathesoncalum authored Jan 15, 2025
2 parents fcdafac + 9dcbfac commit a0e3c29
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 101 deletions.
4 changes: 4 additions & 0 deletions src/appshell/qml/NotationPage/NotationPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,10 @@ DockPage {
Component.onDestruction: {
percussionPanel.toolbarComponent = null
}

onResizeRequested: function(newWidth, newHeight) {
percussionPanel.resize(newWidth, newHeight)
}
}
}
]
Expand Down
160 changes: 95 additions & 65 deletions src/appshell/qml/Preferences/PercussionPreferencesPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,14 @@ PreferencesPage {
id: percussionPanelPreferences

title: qsTrc("appshell/preferences", "Percussion")
rowSpacing: 20

navigation.section: root.navigationSection

CheckBox {
id: unpitchedSelectedCheckbox

visible: percussionPreferencesModel.useNewPercussionPanel
enabled: percussionPreferencesModel.useNewPercussionPanel
width: parent.width

text: qsTrc("appshell/preferences", "Open the percussion panel when an unpitched staff is selected")
Expand All @@ -65,109 +66,138 @@ PreferencesPage {
}
}

StyledTextLabel {
id: padSwapInfo
Column {
id: swappingOptionsColumn

visible: percussionPreferencesModel.useNewPercussionPanel
width: parent.width
spacing: 12

horizontalAlignment: Text.AlignLeft
wrapMode: Text.Wrap
text: qsTrc("notation/percussion", "When swapping the positions of two drum pads:")
}

RadioButtonGroup {
id: radioButtons
StyledTextLabel {
id: padSwapInfo

property int navigationRowStart: unpitchedSelectedCheckbox.navigation.row + 1
property int navigationRowEnd: radioButtons.navigationRowStart + model.length
enabled: percussionPreferencesModel.useNewPercussionPanel
width: parent.width

visible: percussionPreferencesModel.useNewPercussionPanel
horizontalAlignment: Text.AlignLeft
wrapMode: Text.Wrap
text: qsTrc("notation/percussion", "When swapping the positions of two drum pads:")
}

width: parent.width
spacing: percussionPanelPreferences.spacing
RadioButtonGroup {
id: radioButtons

orientation: ListView.Vertical
property int navigationRowStart: unpitchedSelectedCheckbox.navigation.row + 1
property int navigationRowEnd: radioButtons.navigationRowStart + model.length

model: [
{ text: qsTrc("notation/percussion", "Move MIDI notes and keyboard shortcuts with their sounds"), value: true },
{ text: qsTrc("notation/percussion", "Leave MIDI notes and keyboard shortcuts fixed to original pad positions"), value: false }
]
enabled: percussionPreferencesModel.useNewPercussionPanel

delegate: Row {
width: parent.width
spacing: 6
spacing: swappingOptionsColumn.spacing

orientation: ListView.Vertical

model: [
{ text: qsTrc("notation/percussion", "Move MIDI notes and keyboard shortcuts with their sounds"), value: true },
{ text: qsTrc("notation/percussion", "Leave MIDI notes and keyboard shortcuts fixed to original pad positions"), value: false }
]

delegate: Row {
width: parent.width
spacing: 6

RoundedRadioButton {
id: radioButton
RoundedRadioButton {
id: radioButton

anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenter: parent.verticalCenter

navigation.name: modelData.text
navigation.panel: percussionPanelPreferences.navigation
navigation.row: radioButtons.navigationRowStart + model.index
navigation.name: modelData.text
navigation.panel: percussionPanelPreferences.navigation
navigation.row: radioButtons.navigationRowStart + model.index

checked: modelData.value === percussionPreferencesModel.percussionPanelMoveMidiNotesAndShortcuts
checked: modelData.value === percussionPreferencesModel.percussionPanelMoveMidiNotesAndShortcuts

onToggled: {
percussionPreferencesModel.percussionPanelMoveMidiNotesAndShortcuts = modelData.value
onToggled: {
percussionPreferencesModel.percussionPanelMoveMidiNotesAndShortcuts = modelData.value
}
}
}

//! NOTE: Can't use radioButton.text because it won't wrap
StyledTextLabel {
width: parent.width - parent.spacing - radioButton.width
//! NOTE: Can't use radioButton.text because it won't wrap
StyledTextLabel {
width: parent.width - parent.spacing - radioButton.width

anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenter: parent.verticalCenter

horizontalAlignment: Text.AlignLeft
wrapMode: Text.Wrap
text: modelData.text
horizontalAlignment: Text.AlignLeft
wrapMode: Text.Wrap
text: modelData.text

MouseArea {
id: mouseArea
MouseArea {
id: mouseArea

anchors.fill: parent
anchors.fill: parent

onClicked: {
percussionPreferencesModel.percussionPanelMoveMidiNotesAndShortcuts = modelData.value
onClicked: {
percussionPreferencesModel.percussionPanelMoveMidiNotesAndShortcuts = modelData.value
}
}
}
}
}

CheckBox {
id: alwaysAsk

enabled: percussionPreferencesModel.useNewPercussionPanel
width: parent.width

text: qsTrc("global", "Always ask")

navigation.name: "AlwaysAskCheckBox"
navigation.panel: percussionPanelPreferences.navigation
navigation.row: radioButtons.navigationRowEnd

checked: percussionPreferencesModel.showPercussionPanelPadSwapDialog

onClicked: {
percussionPreferencesModel.showPercussionPanelPadSwapDialog = !alwaysAsk.checked
}
}
}

CheckBox {
id: alwaysAsk
Row {
id: useLegacyToggleRow

visible: percussionPreferencesModel.useNewPercussionPanel
height: useLegacyToggle.height
width: parent.width

text: qsTrc("global", "Always ask")
spacing: 6

navigation.name: "AlwaysAskCheckBox"
navigation.panel: percussionPanelPreferences.navigation
navigation.row: radioButtons.navigationRowEnd
ToggleButton {
id: useLegacyToggle

checked: percussionPreferencesModel.showPercussionPanelPadSwapDialog
checked: !percussionPreferencesModel.useNewPercussionPanel

onClicked: {
percussionPreferencesModel.showPercussionPanelPadSwapDialog = !alwaysAsk.checked
navigation.name: "UseLegacyPercussionPanel"
navigation.panel: percussionPanelPreferences.navigation
navigation.row: alwaysAsk.navigation.row + 1

onToggled: {
percussionPreferencesModel.useNewPercussionPanel = !percussionPreferencesModel.useNewPercussionPanel
}
}
}

FlatButton {
id: useNewPercussionPanel
StyledTextLabel {
id: legacyToggleInfo

text: percussionPreferencesModel.useNewPercussionPanel ? qsTrc("notation/percussion", "Switch to old percussion panel")
: qsTrc("notation/percussion", "Switch to new percussion panel")
enabled: percussionPreferencesModel.useNewPercussionPanel

navigation.name: "SwitchPercussionPanels"
navigation.panel: percussionPanelPreferences.navigation
navigation.row: alwaysAsk.navigation.row + 1
height: parent.height

horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter

onClicked: {
percussionPreferencesModel.useNewPercussionPanel = !percussionPreferencesModel.useNewPercussionPanel
wrapMode: Text.Wrap
text: qsTrc("notation/percussion", "Use legacy percussion panel")
}
}
}
Expand Down
54 changes: 30 additions & 24 deletions src/engraving/dom/noteentry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,9 @@ Note* Score::addPitch(NoteVal& nval, bool addFlag, InputState* externalInputStat
}

if (!is.cr()) {
return 0;
handleOverlappingChordRest(is);
}

Measure* measure = is.segment()->measure();
if (measure->isMeasureRepeatGroup(track2staff(track))) {
MeasureRepeat* mr = measure->measureRepeatElement(track2staff(track));
Expand Down Expand Up @@ -456,29 +457,7 @@ Ret Score::putNote(const Position& p, bool replace)

// If there's an overlapping ChordRest at the current input position, shorten it...
if (!cr) {
MasterScore* ms = masterScore();
ChordRest* prevCr = m_is.segment()->nextChordRest(m_is.track(), /*backwards*/ true, /*stopAtMeasureBoundary*/ true);
if (prevCr && prevCr->endTick() > m_is.tick()) {
const Fraction overlapDuration = prevCr->endTick() - m_is.tick();
const Fraction desiredDuration = prevCr->ticks() - overlapDuration;

const InputState inputStateToRestore = m_is; // because changeCRlen will alter the input state
ms->changeCRlen(prevCr, desiredDuration, /*fillWithRest*/ false);

// Fill the difference with tied notes if necessary...
const Fraction difference = desiredDuration - prevCr->ticks();
if (prevCr->isChord() && difference.isNotZero()) {
Fraction startTick = prevCr->endTick();
Chord* prevChord = toChord(prevCr);
const std::vector<TDuration> durationList = toDurationList(difference, true);
for (const TDuration& dur : durationList) {
prevChord = ms->addChord(startTick, dur, prevChord, /*genTie*/ bool(prevChord), prevChord->tuplet());
startTick += dur.fraction();
}
}

m_is = inputStateToRestore;
}
handleOverlappingChordRest(m_is);
}

auto checkTied = [&](){
Expand Down Expand Up @@ -587,6 +566,33 @@ Ret Score::putNote(const Position& p, bool replace)
return ret;
}

void Score::handleOverlappingChordRest(InputState& inputState)
{
MasterScore* ms = masterScore();
ChordRest* prevCr = inputState.segment()->nextChordRest(inputState.track(), /*backwards*/ true, /*stopAtMeasureBoundary*/ true);
if (prevCr && prevCr->endTick() > inputState.tick()) {
const Fraction overlapDuration = prevCr->endTick() - inputState.tick();
const Fraction desiredDuration = prevCr->ticks() - overlapDuration;

const InputState inputStateToRestore = inputState; // because changeCRlen will alter the input state
ms->changeCRlen(prevCr, desiredDuration, /*fillWithRest*/ true);

// Fill the difference with tied notes if necessary...
const Fraction difference = desiredDuration - prevCr->ticks();
if (prevCr->isChord() && difference.isNotZero()) {
Fraction startTick = prevCr->endTick();
Chord* prevChord = toChord(prevCr);
const std::vector<TDuration> durationList = toDurationList(difference, true);
for (const TDuration& dur : durationList) {
prevChord = ms->addChord(startTick, dur, prevChord, /*genTie*/ bool(prevChord), prevChord->tuplet());
startTick += dur.fraction();
}
}

inputState = inputStateToRestore;
}
}

//---------------------------------------------------------
// repitchNote
//---------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions src/engraving/dom/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,7 @@ class Score : public EngravingObject, public muse::Injectable
void selectRange(EngravingItem* e, staff_idx_t staffIdx);

muse::Ret putNote(const Position&, bool replace);
void handleOverlappingChordRest(InputState& inputState);

void resetTempo();
void resetTempoRange(const Fraction& tick1, const Fraction& tick2);
Expand Down
12 changes: 7 additions & 5 deletions src/engraving/dom/select.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -817,10 +817,11 @@ void Selection::setRange(Segment* startSegment, Segment* endSegment, staff_idx_t
assert(!(endSegment && !startSegment));

m_startSegment = startSegment;
m_endSegment = endSegment;
m_endSegment = endSegment;
m_activeSegment = endSegment;
m_staffStart = staffStart;
m_staffEnd = staffEnd;
m_staffStart = staffStart;
m_staffEnd = staffEnd;
m_activeTrack = staff2track(staffStart);

if (m_state == SelState::RANGE) {
m_score->setSelectionChanged(true);
Expand All @@ -844,8 +845,9 @@ void Selection::setRangeTicks(const Fraction& tick1, const Fraction& tick2, staf
m_plannedTick1 = tick1;
m_plannedTick2 = tick2;
m_startSegment = m_endSegment = m_activeSegment = nullptr;
m_staffStart = staffStart;
m_staffEnd = staffEnd;
m_staffStart = staffStart;
m_staffEnd = staffEnd;
m_activeTrack = staff2track(staffStart);

if (m_state == SelState::RANGE) {
m_score->setSelectionChanged(true);
Expand Down
2 changes: 1 addition & 1 deletion src/notation/internal/notationinteraction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,11 @@ NotationInteraction::NotationInteraction(Notation* notation, INotationUndoStackP

m_undoStack->undoRedoNotification().onNotify(this, [this]() {
endEditElement();
notifyAboutNoteInputStateChanged();
});

m_undoStack->stackChanged().onNotify(this, [this]() {
notifyAboutSelectionChangedIfNeed();
notifyAboutNoteInputStateChanged();
});

m_dragData.ed = mu::engraving::EditData(&m_scoreCallbacks);
Expand Down
9 changes: 9 additions & 0 deletions src/notation/qml/MuseScore/NotationScene/PercussionPanel.qml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Item {
property NavigationSection navigationSection: null
property int contentNavigationPanelOrderStart: 1

signal resizeRequested(var newWidth, var newHeight)

anchors.fill: parent

property Component toolbarComponent: PercussionPanelToolBar {
Expand All @@ -47,6 +49,8 @@ Item {

Component.onCompleted: {
padGrid.model.init()
var newHeight = (padGrid.numRows * padGrid.cellHeight) + (soundTitleLabel.height * 2)
root.resizeRequested(root.width, newHeight)
}

PercussionPanelModel {
Expand Down Expand Up @@ -325,6 +329,11 @@ Item {
}
pad.padNavigation.requestActive()
}

function onNumPadsChanged() {
var newHeight = (padGrid.numRows * padGrid.cellHeight) + (soundTitleLabel.height * 2)
root.resizeRequested(root.width, newHeight)
}
}
}

Expand Down
Loading

0 comments on commit a0e3c29

Please sign in to comment.