107 lines
3.5 KiB
TypeScript
107 lines
3.5 KiB
TypeScript
import React, { useMemo, useState } from 'react';
|
|
import './EventListPanel.css';
|
|
import { useProjectStore } from '../stores/projectStore';
|
|
import { KGMidiRegion } from '../core/region/KGMidiRegion';
|
|
import { KGMidiTrack } from '../core/track/KGMidiTrack';
|
|
import { KGAudioTrack } from '../core/track/KGAudioTrack';
|
|
import RegionEventListTab from './event-list-panel/RegionEventListTab';
|
|
import TrackEventListTab from './event-list-panel/TrackEventListTab';
|
|
import GlobalEventListTab from './event-list-panel/GlobalEventListTab';
|
|
import { useI18n } from '../i18n/useI18n';
|
|
|
|
interface EventListPanelProps {
|
|
isVisible: boolean;
|
|
}
|
|
|
|
type ScopeTab = 'region' | 'track' | 'global';
|
|
|
|
const EventListPanel: React.FC<EventListPanelProps> = ({ isVisible }) => {
|
|
const { t } = useI18n();
|
|
const {
|
|
tracks,
|
|
globalTracks,
|
|
activeRegionId,
|
|
selectedRegionIds,
|
|
selectedTrackId,
|
|
timeSignature,
|
|
playheadPosition,
|
|
refreshProjectState,
|
|
} = useProjectStore();
|
|
const [scopeTab, setScopeTab] = useState<ScopeTab>('region');
|
|
|
|
const resolvedRegionId = selectedRegionIds.length > 1
|
|
? activeRegionId
|
|
: selectedRegionIds.length === 1
|
|
? selectedRegionIds[0]
|
|
: activeRegionId;
|
|
|
|
const selectedTrack = useMemo(() => {
|
|
const track = tracks.find(candidate => candidate.getId().toString() === selectedTrackId) ?? null;
|
|
return track instanceof KGMidiTrack || track instanceof KGAudioTrack ? track : null;
|
|
}, [tracks, selectedTrackId]);
|
|
|
|
let activeMidiRegion: KGMidiRegion | null = null;
|
|
let parentTrack: KGMidiTrack | null = null;
|
|
|
|
if (resolvedRegionId) {
|
|
for (const track of tracks) {
|
|
const region = track.getRegions().find(candidate => candidate.getId() === resolvedRegionId);
|
|
if (region instanceof KGMidiRegion && track instanceof KGMidiTrack) {
|
|
activeMidiRegion = region;
|
|
parentTrack = track;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (
|
|
<div className={`event-list-panel${isVisible ? '' : ' is-hidden'}`}>
|
|
<div className="event-list-panel-header">
|
|
<h3>{t('eventList.title')}</h3>
|
|
</div>
|
|
|
|
<div className="event-list-scope-tabs" role="tablist" aria-label={t('eventList.scopeTabs')}>
|
|
<button
|
|
className={`event-list-scope-tab${scopeTab === 'region' ? ' active' : ''}`}
|
|
type="button"
|
|
onClick={() => setScopeTab('region')}
|
|
>
|
|
{t('eventList.scope.region')}
|
|
</button>
|
|
<button
|
|
className={`event-list-scope-tab${scopeTab === 'track' ? ' active' : ''}`}
|
|
type="button"
|
|
onClick={() => setScopeTab('track')}
|
|
>
|
|
{t('eventList.scope.track')}
|
|
</button>
|
|
<button
|
|
className={`event-list-scope-tab${scopeTab === 'global' ? ' active' : ''}`}
|
|
type="button"
|
|
onClick={() => setScopeTab('global')}
|
|
>
|
|
{t('eventList.scope.global')}
|
|
</button>
|
|
</div>
|
|
|
|
<div className="event-list-panel-body">
|
|
{scopeTab === 'region' ? (
|
|
<RegionEventListTab activeMidiRegion={activeMidiRegion} parentTrack={parentTrack} />
|
|
) : scopeTab === 'track' ? (
|
|
<TrackEventListTab selectedTrack={selectedTrack} />
|
|
) : (
|
|
<GlobalEventListTab
|
|
globalTracks={globalTracks}
|
|
selectedRegionIds={selectedRegionIds}
|
|
timeSignature={timeSignature}
|
|
playheadPosition={playheadPosition}
|
|
refreshProjectState={refreshProjectState}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default EventListPanel;
|