p4-vscode_designer_extension/src/webview/react/components/EventsPanel.tsx
2025-12-23 05:43:33 +03:00

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>
);
}