feat: added mode list dropdown
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"modes": [
|
||||
{
|
||||
"id": "ionian",
|
||||
"name": "Ionian",
|
||||
"steps": [2, 2, 1, 2, 2, 2, 1]
|
||||
},
|
||||
{
|
||||
"id": "aeolian",
|
||||
"name": "Aeolian",
|
||||
"steps": [2, 1, 2, 2, 1, 2, 2]
|
||||
},
|
||||
{
|
||||
"id": "harmonic_minor",
|
||||
"name": "Harmonic Minor",
|
||||
"steps": [2, 1, 2, 2, 1, 3, 1]
|
||||
},
|
||||
{
|
||||
"id": "melodic_minor",
|
||||
"name": "Melodic Minor",
|
||||
"steps": [2, 1, 2, 2, 2, 2, 1]
|
||||
},
|
||||
{
|
||||
"id": "dorian",
|
||||
"name": "Dorian",
|
||||
"steps": [2, 1, 2, 2, 2, 1, 2]
|
||||
},
|
||||
{
|
||||
"id": "phrygian",
|
||||
"name": "Phrygian",
|
||||
"steps": [1, 2, 2, 2, 1, 2, 2]
|
||||
},
|
||||
{
|
||||
"id": "lydian",
|
||||
"name": "Lydian",
|
||||
"steps": [2, 2, 2, 1, 2, 2, 1]
|
||||
},
|
||||
{
|
||||
"id": "mixolydian",
|
||||
"name": "Mixolydian",
|
||||
"steps": [2, 2, 1, 2, 2, 1, 2]
|
||||
},
|
||||
{
|
||||
"id": "locrian",
|
||||
"name": "Locrian",
|
||||
"steps": [1, 2, 2, 1, 2, 2, 2]
|
||||
},
|
||||
{
|
||||
"id": "phrygian_dominant",
|
||||
"name": "Phrygian Dominant",
|
||||
"steps": [1, 3, 1, 2, 1, 2, 2]
|
||||
},
|
||||
{
|
||||
"id": "harmonic_major",
|
||||
"name": "Harmonic Major",
|
||||
"steps": [2, 2, 1, 2, 1, 3, 1]
|
||||
}
|
||||
]
|
||||
}
|
||||
+10
@@ -597,6 +597,7 @@ body {
|
||||
padding: 0 10px;
|
||||
user-select: none;
|
||||
position: relative;
|
||||
z-index: 100; /* Ensure toolbar and its dropdowns appear above piano roll content */
|
||||
}
|
||||
|
||||
/* Override pointer-events for piano roll toolbar sections */
|
||||
@@ -609,6 +610,15 @@ body {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.piano-roll-toolbar .toolbar-left .quant-button {
|
||||
margin-left: 0px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.piano-roll-toolbar .toolbar-left .quant-dropdown {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Generic button blink effect */
|
||||
.quant-button.button-blink {
|
||||
animation: buttonBlink 0.2s ease-in-out;
|
||||
|
||||
+14
@@ -12,6 +12,7 @@ import { SettingsPanel } from './components/settings';
|
||||
import LoadingOverlay from './components/common/LoadingOverlay';
|
||||
import { useEffect as useEffectReact, useState, useRef } from 'react';
|
||||
import { KGToneBuffersPool } from './core/audio-interface/KGToneBuffersPool';
|
||||
import { KGPianoRollState } from './core/state/KGPianoRollState';
|
||||
|
||||
function App() {
|
||||
// Enable global keyboard handler for copy/paste and undo/redo
|
||||
@@ -33,6 +34,19 @@ function App() {
|
||||
// Initialize store from config after ConfigManager is ready
|
||||
await initializeFromConfig();
|
||||
|
||||
// Load mode list from JSON
|
||||
try {
|
||||
const response = await fetch(`${import.meta.env.BASE_URL}resources/modes/mode_list.json`);
|
||||
const data = await response.json();
|
||||
const modeNames = data.modes.map((mode: { name: string; steps: number[] }) => mode.name);
|
||||
KGPianoRollState.MODE_OPTIONS = modeNames;
|
||||
console.log(`Loaded ${modeNames.length} modes:`, modeNames);
|
||||
} catch (error) {
|
||||
console.error('Failed to load mode list:', error);
|
||||
// Fallback to default mode
|
||||
KGPianoRollState.MODE_OPTIONS = ['ionian'];
|
||||
}
|
||||
|
||||
// Log maxBars to console
|
||||
console.log(`Project max bars: ${maxBars}`);
|
||||
};
|
||||
|
||||
@@ -39,6 +39,9 @@ const PianoRoll: React.FC<PianoRollProps> = ({
|
||||
// Snapping state
|
||||
const [snapping, setSnapping] = useState<string>('NO SNAP');
|
||||
|
||||
// Mode state
|
||||
const [selectedMode, setSelectedMode] = useState<string>('ionian');
|
||||
|
||||
// Piano roll state with temporary initial values
|
||||
const [position, setPosition] = useState(initialPosition || { x: 0, y: 0 });
|
||||
|
||||
@@ -296,6 +299,15 @@ const PianoRoll: React.FC<PianoRollProps> = ({
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Handle mode selection
|
||||
const handleModeSelect = useCallback((value: string) => {
|
||||
setSelectedMode(value);
|
||||
KGPianoRollState.instance().setCurrentMode(value);
|
||||
if (DEBUG_MODE.PIANO_ROLL) {
|
||||
console.log(`Selected mode: ${value}`);
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Handler for receiving the setNoteUpdateCounter function from PianoRollContent
|
||||
const handleSetNoteUpdateTrigger = (setNoteFn: React.Dispatch<React.SetStateAction<number>>) => {
|
||||
triggerNoteUpdateRef.current = setNoteFn;
|
||||
@@ -765,6 +777,8 @@ const PianoRoll: React.FC<PianoRollProps> = ({
|
||||
onQuantSelect={handleQuantSelect}
|
||||
snapping={snapping}
|
||||
onSnappingSelect={handleSnappingSelect}
|
||||
selectedMode={selectedMode}
|
||||
onModeChange={handleModeSelect}
|
||||
blinkButton={blinkButton}
|
||||
/>
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ interface PianoRollToolbarProps {
|
||||
onQuantSelect: (type: 'position' | 'length', value: string) => void;
|
||||
snapping: string;
|
||||
onSnappingSelect: (value: string) => void;
|
||||
selectedMode: string;
|
||||
onModeChange: (value: string) => void;
|
||||
blinkButton?: string | null;
|
||||
}
|
||||
|
||||
@@ -22,12 +24,21 @@ const PianoRollToolbar: React.FC<PianoRollToolbarProps> = ({
|
||||
onQuantSelect,
|
||||
snapping,
|
||||
onSnappingSelect,
|
||||
selectedMode,
|
||||
onModeChange,
|
||||
blinkButton = null
|
||||
}) => {
|
||||
return (
|
||||
<div className="piano-roll-toolbar">
|
||||
<div className="toolbar-left">
|
||||
{/* Left section - can add more tools later */}
|
||||
{/* Left section with mode dropdown */}
|
||||
<KGDropdown
|
||||
options={KGPianoRollState.MODE_OPTIONS}
|
||||
value={selectedMode}
|
||||
onChange={(value) => onModeChange(value)}
|
||||
label="Mode"
|
||||
buttonClassName="mode-dropdown"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="toolbar-center">
|
||||
|
||||
@@ -8,10 +8,12 @@ export class KGPianoRollState {
|
||||
public static SNAP_OPTIONS: string[] = ['NO SNAP', '1/3', '1/4', '1/6', '1/8', '1/12', '1/16', '1/24', '1/32'];
|
||||
public static QUANT_POS_OPTIONS: string[] = ['1/3', '1/4', '1/6', '1/8', '1/12', '1/16', '1/24', '1/32'];
|
||||
public static QUANT_LEN_OPTIONS: string[] = ['1/1', '1/2', '1/3', '1/4', '1/6', '1/8', '1/12', '1/16', '1/24', '1/32'];
|
||||
public static MODE_OPTIONS: string[] = []; // Will be populated from mode_list.json
|
||||
|
||||
private activeTool: string = "pointer";
|
||||
private currentSnap: string = "NO SNAP";
|
||||
private lastEditedNoteLength: number = 1; // Default to 1 beat
|
||||
private currentMode: string = "ionian"; // Default mode
|
||||
|
||||
private constructor() {
|
||||
console.log("KGPianoRollState initialized");
|
||||
@@ -48,4 +50,12 @@ export class KGPianoRollState {
|
||||
public setLastEditedNoteLength(length: number): void {
|
||||
this.lastEditedNoteLength = length;
|
||||
}
|
||||
|
||||
public getCurrentMode(): string {
|
||||
return this.currentMode;
|
||||
}
|
||||
|
||||
public setCurrentMode(mode: string): void {
|
||||
this.currentMode = mode;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user