Skip to content

Commit

Permalink
Merge pull request #25518 from mathesoncalum/percussions_keyboard_nav…
Browse files Browse the repository at this point in the history
…igation

Percussion panel - implement keyboard navigation for toolbar and pad grid
  • Loading branch information
mathesoncalum authored Dec 5, 2024
2 parents 091ac0d + 15c1561 commit 8fa1eaa
Show file tree
Hide file tree
Showing 6 changed files with 382 additions and 79 deletions.
158 changes: 133 additions & 25 deletions src/notation/qml/MuseScore/NotationScene/PercussionPanel.qml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ Item {
Component.onCompleted: {
percModel.init()
}

onCurrentPanelModeChanged: {
// Cancel any active keyboard swaps when the panel mode changes
if (padGrid.isKeyboardSwapActive) {
padGrid.swapOriginPad = null
padGrid.isKeyboardSwapActive = false
padGrid.model.endPadSwap(-1)
}
}
}

// TODO: Will live inside percussion panel until #22050 is implemented
Expand All @@ -69,8 +78,8 @@ Item {
width: parent.width
height: 36

navigation.section: root.navigationSection
navigation.order: root.contentNavigationPanelOrderStart
navigationSection: root.navigationSection
navigationOrderStart: root.contentNavigationPanelOrderStart

model: percModel

Expand Down Expand Up @@ -105,6 +114,16 @@ Item {
height: padGrid.cellHeight * padGrid.numRows
spacing: padGrid.spacing / 2

NavigationPanel {
id: deleteButtonsPanel

name: "PercussionPanelDeleteRowButtons"
section: root.navigationSection
order: toolbar.navigationOrderEnd + 3

enabled: deleteButtonsColumn.visible
}

Column {
id: deleteButtonsColumn

Expand All @@ -114,6 +133,7 @@ Item {
width: rowLayout.sideColumnsWidth

visible: percModel.currentPanelMode === PanelMode.EDIT_LAYOUT
enabled: !padGrid.isKeyboardSwapActive

Repeater {
id: deleteRepeater
Expand All @@ -137,6 +157,9 @@ Item {
icon: IconCode.DELETE_TANK
backgroundRadius: deleteButton.width / 2

navigation.panel: deleteButtonsPanel
navigation.row: model.index

onClicked: {
padGrid.model.deleteRow(model.index)
}
Expand All @@ -163,7 +186,16 @@ Item {
readonly property int numColumns: model.numColumns
readonly property int spacing: 12

property Item draggedPad: null
property Item swapOriginPad: null
property bool isKeyboardSwapActive: false

QtObject {
id: gridPrv

// This variable ensures we stay within a given pad when tabbing back-and-forth between
// "main" and "footer" controls
property var currentPadNavigationIndex: [0, 0]
}

Layout.alignment: Qt.AlignTop
Layout.fillHeight: true
Expand All @@ -177,6 +209,36 @@ Item {

model: percModel.padListModel

NavigationPanel {
id: padsNavPanel

name: "PercussionPanelPads"
section: root.navigationSection
order: toolbar.navigationOrderEnd + 1

onNavigationEvent: function(event) {
if (event.type === NavigationEvent.AboutActive) {
event.setData("controlIndex", gridPrv.currentPadNavigationIndex)
}
}
}

NavigationPanel {
id: padFootersNavPanel

name: "PercussionPanelFooters"
section: root.navigationSection
order: toolbar.navigationOrderEnd + 2

enabled: percModel.currentPanelMode !== PanelMode.EDIT_LAYOUT

onNavigationEvent: function(event) {
if (event.type === NavigationEvent.AboutActive) {
event.setData("controlIndex", gridPrv.currentPadNavigationIndex)
}
}
}

delegate: Item {
id: padArea

Expand All @@ -196,54 +258,96 @@ Item {
panelMode: percModel.currentPanelMode
useNotationPreview: percModel.useNotationPreview

// When dragging, only show the outline for the dragged pad and the drag target...
// When swapping, only show the outline for the swap origin and the swap target...
showEditOutline: percModel.currentPanelMode === PanelMode.EDIT_LAYOUT
&& (!Boolean(padGrid.draggedPad) || padGrid.draggedPad === pad || pad.containsDrag)
showOriginBackground: pad.containsDrag || pad === padGrid.draggedPad
&& (!Boolean(padGrid.swapOriginPad) || padGrid.swapOriginPad === pad)
showOriginBackground: pad.containsDrag || (pad === padGrid.swapOriginPad && !padGrid.isKeyboardSwapActive)

panelHasActiveKeyboardSwap: padGrid.isKeyboardSwapActive
dragParent: root

onDragStarted: {
padGrid.draggedPad = pad
padGrid.model.startDrag(index)
navigationRow: index / padGrid.numColumns
navigationColumn: index % padGrid.numColumns
padNavigation.panel: padsNavPanel
footerNavigation.panel: padFootersNavPanel

onStartPadSwapRequested: function(isKeyboardSwap) {
padGrid.swapOriginPad = pad
padGrid.isKeyboardSwapActive = isKeyboardSwap
padGrid.model.startPadSwap(index)
}

onDropped: function(dropEvent) {
padGrid.draggedPad = null
padGrid.model.endDrag(index)
dropEvent.accepted = true
onEndPadSwapRequested: {
padGrid.swapOriginPad = null
padGrid.isKeyboardSwapActive = false
padGrid.model.endPadSwap(index)
}

onDragCancelled: {
padGrid.draggedPad = null
padGrid.model.endDrag(-1)
onCancelPadSwapRequested: {
padGrid.swapOriginPad = null
padGrid.isKeyboardSwapActive = false
padGrid.model.endPadSwap(-1)
}

onHasActiveControlChanged: {
if (!pad.hasActiveControl) {
return;
}
gridPrv.currentPadNavigationIndex = [pad.navigationRow, pad.navigationColumn]
}
}

states: [
// If this is the drop target - move the draggable area to the origin of the dragged pad (preview the drop)
// If this is the swap target - move the swappable area to the swap origin (preview the swap)
State {
name: "DROP_TARGET"
when: Boolean(padGrid.draggedPad) && pad.containsDrag && padGrid.draggedPad !== pad
name: "SWAP_TARGET"
when: Boolean(padGrid.swapOriginPad) && (pad.containsDrag || pad.padNavigationCtrl.active) && padGrid.swapOriginPad !== pad

ParentChange {
target: pad.draggableArea
parent: padGrid.draggedPad
target: pad.swappableArea
parent: padGrid.swapOriginPad
}
AnchorChanges {
target: pad.draggableArea
anchors.verticalCenter: padGrid.draggedPad.verticalCenter
anchors.horizontalCenter: padGrid.draggedPad.horizontalCenter
target: pad.swappableArea
anchors.verticalCenter: padGrid.swapOriginPad.verticalCenter
anchors.horizontalCenter: padGrid.swapOriginPad.horizontalCenter
}
PropertyChanges {
target: pad
showEditOutline: true
}

// Origin background not needed for the dragged pad when a preview is taking place...
PropertyChanges {
target: padGrid.draggedPad
target: padGrid.swapOriginPad
showOriginBackground: false
}

// In the case of a keyboard swap, we also need to move the origin pad
ParentChange {
target: padGrid.isKeyboardSwapActive && Boolean(padGrid.swapOriginPad) ? padGrid.swapOriginPad.swappableArea : null
parent: pad
}
AnchorChanges {
target: padGrid.isKeyboardSwapActive && Boolean(padGrid.swapOriginPad) ? padGrid.swapOriginPad.swappableArea : null
anchors.verticalCenter: pad.verticalCenter
anchors.horizontalCenter: pad.horizontalCenter
}
}
]
}
}

NavigationPanel {
id: addRowButtonPanel

name: "PercussionPanelAddRowButton"
section: root.navigationSection
order: toolbar.navigationOrderEnd + 4

enabled: addRowButton.visible
}

FlatButton {
id: addRowButton

Expand All @@ -252,10 +356,14 @@ Item {
Layout.bottomMargin: (padGrid.cellHeight / 2) - (height / 2)

visible: percModel.currentPanelMode === PanelMode.EDIT_LAYOUT
enabled: !padGrid.isKeyboardSwapActive

icon: IconCode.PLUS
text: qsTrc("notation", "Add row")
orientation: Qt.Horizontal

navigation.panel: addRowButtonPanel

onClicked: {
padGrid.model.addEmptyRow()
flickable.goToBottom()
Expand Down
Loading

0 comments on commit 8fa1eaa

Please sign in to comment.