Files
trombon_ip_browser/lib/widgets/scenario_simulation_widget.dart
2026-05-10 02:54:27 +03:00

157 lines
5.2 KiB
Dart

import 'package:flutter/material.dart';
class ScenarioSimulationItem {
const ScenarioSimulationItem({
required this.id,
required this.title,
required this.available,
required this.isActive,
required this.reason,
required this.help,
required this.onHelp,
required this.onActivate,
required this.onStop,
});
final String id;
final String title;
final bool available;
final bool isActive;
final String reason;
final String help;
final VoidCallback onHelp;
final VoidCallback onActivate;
final VoidCallback onStop;
}
class ScenarioSimulationWidget extends StatelessWidget {
const ScenarioSimulationWidget({
super.key,
required this.visible,
required this.panelWidth,
required this.panelHeight,
required this.scenarios,
required this.onHide,
required this.onShow,
});
final bool visible;
final double panelWidth;
final double panelHeight;
final List<ScenarioSimulationItem> scenarios;
final VoidCallback onHide;
final VoidCallback onShow;
@override
Widget build(BuildContext context) {
final cs = Theme.of(context).colorScheme;
if (!visible) {
return Positioned(
right: 8,
bottom: 8,
child: FilledButton.icon(
onPressed: onShow,
icon: const Icon(Icons.playlist_add_check),
label: const Text('Сценарии'),
),
);
}
return Positioned(
right: 8,
bottom: 8,
child: Container(
width: panelWidth,
height: panelHeight,
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: cs.surface.withValues(alpha: 0.92),
borderRadius: BorderRadius.circular(12),
border: Border.all(color: cs.outlineVariant),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
const Expanded(
child: Text(
'Сценарии',
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w700),
),
),
IconButton(
tooltip: 'Скрыть панель',
onPressed: onHide,
icon: const Icon(Icons.visibility_off_outlined),
),
],
),
const SizedBox(height: 8),
Expanded(
child: ListView(
children: scenarios
.map(
(scenario) => Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
scenario.title,
style: const TextStyle(fontWeight: FontWeight.w600),
),
const SizedBox(height: 2),
Text(
scenario.reason,
style: TextStyle(
fontSize: 12,
color: scenario.isActive
? cs.primary
: scenario.available
? Colors.green.shade700
: cs.error,
),
),
const SizedBox(height: 6),
Wrap(
spacing: 8,
runSpacing: 6,
children: [
OutlinedButton.icon(
onPressed: scenario.onHelp,
icon: const Icon(Icons.help_outline, size: 18),
label: const Text('Help'),
),
if (scenario.isActive)
FilledButton.icon(
style: FilledButton.styleFrom(
backgroundColor: cs.error,
),
onPressed: scenario.onStop,
icon: const Icon(Icons.stop_circle_outlined),
label: const Text('Остановить'),
)
else
FilledButton(
onPressed: scenario.available
? scenario.onActivate
: null,
child: const Text('Активировать'),
),
],
),
],
),
),
)
.toList(),
),
),
],
),
),
);
}
}