182 lines
7.3 KiB
TypeScript
182 lines
7.3 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { useAppDispatch, useAppState } from '../state';
|
|
|
|
export function EventsPanel() {
|
|
const dispatch = useAppDispatch();
|
|
const { design, selectedWidgetId, vscode } = useAppState();
|
|
const [eventType, setEventType] = useState('command');
|
|
const [eventName, setEventName] = useState('on_click');
|
|
|
|
const w = design.widgets.find((x) => x.id === selectedWidgetId);
|
|
const widgetEvents = (id: string | undefined) =>
|
|
(design.events || []).filter((e) => e.widget === id);
|
|
|
|
const add = () => {
|
|
if (!w) {
|
|
vscode.postMessage({
|
|
type: 'showError',
|
|
text: 'Select a widget to add events to',
|
|
});
|
|
return;
|
|
}
|
|
if (!eventName) {
|
|
vscode.postMessage({
|
|
type: 'showError',
|
|
text: 'Please fill in handler name',
|
|
});
|
|
return;
|
|
}
|
|
if (!eventType) {
|
|
vscode.postMessage({
|
|
type: 'showError',
|
|
text: 'Please fill in event type',
|
|
});
|
|
return;
|
|
}
|
|
dispatch({
|
|
type: 'addEvent',
|
|
payload: {
|
|
widget: w.id,
|
|
type: eventType,
|
|
name: eventName,
|
|
code: 'pass', // Default body
|
|
},
|
|
});
|
|
vscode.postMessage({
|
|
type: 'showInfo',
|
|
text: `Event added: ${eventName}`,
|
|
});
|
|
};
|
|
|
|
const remove = (type: string, name: string) => {
|
|
if (!w) return;
|
|
dispatch({
|
|
type: 'removeEvent',
|
|
payload: { widget: w.id, type, name },
|
|
});
|
|
vscode.postMessage({ type: 'showInfo', text: 'Event removed' });
|
|
};
|
|
|
|
const commonEvents = [
|
|
'command',
|
|
'<Button-1>',
|
|
'<Button-2>',
|
|
'<Button-3>',
|
|
'<Double-Button-1>',
|
|
'<Enter>',
|
|
'<Leave>',
|
|
'<FocusIn>',
|
|
'<FocusOut>',
|
|
'<Return>',
|
|
'<Key>',
|
|
'<Configure>',
|
|
];
|
|
|
|
return (
|
|
<div className="events-panel">
|
|
<h3>Events & Commands</h3>
|
|
<div id="eventsContent">
|
|
{!w ? (
|
|
<p>Select a widget to configure events</p>
|
|
) : (
|
|
<div className="event-section">
|
|
<div className="event-controls">
|
|
<label className="property-label">
|
|
Event Type:
|
|
</label>
|
|
<div style={{ marginBottom: '8px' }}>
|
|
<select
|
|
className="event-handler-input"
|
|
value={
|
|
commonEvents.includes(eventType)
|
|
? eventType
|
|
: 'custom'
|
|
}
|
|
onChange={(e) => {
|
|
if (e.target.value !== 'custom') {
|
|
setEventType(e.target.value);
|
|
} else {
|
|
setEventType('');
|
|
}
|
|
}}
|
|
style={{ marginBottom: '4px' }}
|
|
>
|
|
{commonEvents.map((evt) => (
|
|
<option key={evt} value={evt}>
|
|
{evt}
|
|
</option>
|
|
))}
|
|
<option value="custom">Custom...</option>
|
|
</select>
|
|
{!commonEvents.includes(eventType) && (
|
|
<input
|
|
className="event-handler-input"
|
|
type="text"
|
|
placeholder="Enter custom event type"
|
|
value={eventType}
|
|
onChange={(e) =>
|
|
setEventType(e.target.value)
|
|
}
|
|
/>
|
|
)}
|
|
</div>
|
|
<label className="property-label">
|
|
Handler Name:
|
|
</label>
|
|
<input
|
|
className="event-handler-input"
|
|
type="text"
|
|
value={eventName}
|
|
onChange={(e) => setEventName(e.target.value)}
|
|
/>
|
|
</div>
|
|
<div className="event-buttons">
|
|
<button className="event-btn primary" onClick={add}>
|
|
Add Event
|
|
</button>
|
|
</div>
|
|
<div className="event-list">
|
|
<h4>Configured Events</h4>
|
|
{widgetEvents(w.id).length === 0 ? (
|
|
<p>No events added yet.</p>
|
|
) : (
|
|
widgetEvents(w.id).map((ev) => (
|
|
<div
|
|
className="event-item"
|
|
key={`${ev.widget}-${ev.type}-${ev.name}`}
|
|
>
|
|
<div className="event-info">
|
|
<span
|
|
className="event-name"
|
|
style={{ fontWeight: 'bold' }}
|
|
>
|
|
{ev.type}:
|
|
</span>
|
|
<span
|
|
className="event-name"
|
|
style={{ marginLeft: '5px' }}
|
|
>
|
|
{ev.name}
|
|
</span>
|
|
</div>
|
|
<div className="event-actions">
|
|
<button
|
|
className="event-btn secondary"
|
|
onClick={() =>
|
|
remove(ev.type, ev.name)
|
|
}
|
|
>
|
|
Remove
|
|
</button>
|
|
</div>
|
|
</div>
|
|
))
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|