feat: implemented select all notes feature.

This commit is contained in:
Xiaohan-Tian
2025-08-28 19:23:21 -07:00
parent 131b99aeb5
commit 6445325f3a
4 changed files with 68 additions and 0 deletions
+1
View File
@@ -35,6 +35,7 @@
"play": "space", "play": "space",
"undo": "ctrl+z", "undo": "ctrl+z",
"redo": "ctrl+shift+z", "redo": "ctrl+shift+z",
"select_all": "ctrl+a",
"copy": "ctrl+c", "copy": "ctrl+c",
"cut": "ctrl+x", "cut": "ctrl+x",
"paste": "ctrl+v", "paste": "ctrl+v",
+2
View File
@@ -41,6 +41,7 @@ interface AppConfig {
play: string; play: string;
undo: string; undo: string;
redo: string; redo: string;
select_all: string;
copy: string; copy: string;
cut: string; cut: string;
paste: string; paste: string;
@@ -195,6 +196,7 @@ export class ConfigManager {
play: 'space', play: 'space',
undo: 'ctrl+z', undo: 'ctrl+z',
redo: 'ctrl+shift+z', redo: 'ctrl+shift+z',
select_all: 'ctrl+a',
copy: 'ctrl+c', copy: 'ctrl+c',
cut: 'ctrl+x', cut: 'ctrl+x',
paste: 'ctrl+v', paste: 'ctrl+v',
+9
View File
@@ -4,6 +4,7 @@ import { handleCopyOperation, handlePasteOperation } from '../util/copyPasteUtil
import { saveProject } from '../util/saveUtil'; import { saveProject } from '../util/saveUtil';
import { ConfigManager } from '../core/config/ConfigManager'; import { ConfigManager } from '../core/config/ConfigManager';
import { useProjectStore } from '../stores/projectStore'; import { useProjectStore } from '../stores/projectStore';
import { selectAllNotesInActiveRegion } from '../util/selectionUtil';
/** /**
* Global keyboard handler for copy/paste, undo/redo, play/pause, and save operations * Global keyboard handler for copy/paste, undo/redo, play/pause, and save operations
@@ -56,6 +57,7 @@ export const useGlobalKeyboardHandler = () => {
const redoShortcut = configManager.get('hotkeys.main.redo') as string; const redoShortcut = configManager.get('hotkeys.main.redo') as string;
const copyShortcut = configManager.get('hotkeys.main.copy') as string; const copyShortcut = configManager.get('hotkeys.main.copy') as string;
const pasteShortcut = configManager.get('hotkeys.main.paste') as string; const pasteShortcut = configManager.get('hotkeys.main.paste') as string;
const selectAllShortcut = configManager.get('hotkeys.main.select_all') as string;
const playShortcut = configManager.get('hotkeys.main.play') as string; const playShortcut = configManager.get('hotkeys.main.play') as string;
const saveShortcut = configManager.get('hotkeys.main.save') as string; const saveShortcut = configManager.get('hotkeys.main.save') as string;
@@ -109,6 +111,13 @@ export const useGlobalKeyboardHandler = () => {
return; return;
} }
// Check for select-all-notes shortcut (only when piano roll is open)
if (selectAllShortcut && matchesKeyboardShortcut(event, selectAllShortcut)) {
event.preventDefault();
selectAllNotesInActiveRegion();
return;
}
// Check for play/pause shortcut // Check for play/pause shortcut
if (playShortcut && matchesKeyboardShortcut(event, playShortcut)) { if (playShortcut && matchesKeyboardShortcut(event, playShortcut)) {
event.preventDefault(); event.preventDefault();
+56
View File
@@ -0,0 +1,56 @@
import { KGCore } from '../core/KGCore';
import { useProjectStore } from '../stores/projectStore';
import { KGMidiRegion } from '../core/region/KGMidiRegion';
import { KGTrack } from '../core/track/KGTrack';
import { KGMidiNote } from '../core/midi/KGMidiNote';
/**
* Select all notes in the active region if the piano roll is visible.
* Logs the count and region id on success.
* Returns true if selection was performed; false otherwise.
*/
export const selectAllNotesInActiveRegion = (): boolean => {
const { showPianoRoll, activeRegionId, updateTrack } = useProjectStore.getState();
if (!showPianoRoll || !activeRegionId) {
return false;
}
try {
const core = KGCore.instance();
const project = core.getCurrentProject();
const tracks = project.getTracks();
let parentTrack: KGTrack | null = null;
let activeRegion: KGMidiRegion | null = null;
for (const track of tracks) {
const region = track.getRegions().find(r => r.getId() === activeRegionId);
if (region && region instanceof KGMidiRegion) {
parentTrack = track as KGTrack;
activeRegion = region as KGMidiRegion;
break;
}
}
if (!activeRegion || !parentTrack) {
return false;
}
// Clear previous selection and select all notes in the region
core.clearSelectedItems();
const notes: KGMidiNote[] = activeRegion.getNotes();
notes.forEach((n: KGMidiNote) => n.select());
core.addSelectedItems(notes);
// Update track to persist selection state in model/UI
updateTrack(parentTrack);
console.log(`Selected all notes: count=${notes.length}, regionId=${activeRegionId}`);
return true;
} catch (error) {
console.error('Select all notes failed:', error);
return false;
}
};