feat: implemented select all notes feature.
This commit is contained in:
@@ -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",
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user