import 'package:flutter/material.dart'; import 'package:my_app/appeditor/custom/AppEditorWidgetContext.dart'; Widget buildCustomWidget(BuildContext context, AppEditorWidgetContext app) { return CalculatorWidget(app: app); } class CalculatorWidget extends StatefulWidget { const CalculatorWidget({super.key, required this.app}); final AppEditorWidgetContext app; @override State createState() => _CalculatorWidgetState(); } class _CalculatorWidgetState extends State { final _first = TextEditingController(); final _second = TextEditingController(); String _operation = '+'; double? _result; bool _busy = false; @override void dispose() { _first.dispose(); _second.dispose(); super.dispose(); } Future _calculate() async { final a = double.tryParse(_first.text.trim()); final b = double.tryParse(_second.text.trim()); if (a == null || b == null || !a.isFinite || !b.isFinite) { widget.app.showMessage('دو عدد معتبر با رقم انگلیسی وارد کنید.'); return; } if (_operation == '/' && b == 0) { widget.app.showMessage('تقسیم بر صفر ممکن نیست.'); return; } final result = switch (_operation) { '+' => a + b, '-' => a - b, '*' => a * b, _ => a / b, }; if (!result.isFinite) { widget.app.showMessage('نتیجه خارج از محدوده عددی است.'); return; } final app = widget.app; final variable = app.params['resultVariable'] as String? ?? 'calculator_result'; setState(() { _busy = true; _result = result; }); try { await app.addVar( name: variable, value: result, storeOnDevice: app.params['storeResult'] == true, overwrite: true, ); if (mounted && app.hasAction('onResult')) await app.runAction('onResult'); } catch (error) { app.showMessage('ذخیره نتیجه یا اجرای عملکرد ممکن نشد: $error'); } finally { if (mounted) setState(() => _busy = false); } } @override Widget build(BuildContext context) { final args = widget.app.params; final decimals = ((args['decimals'] as num?)?.toInt() ?? 2).clamp(0, 8); return Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( args['title'] as String? ?? 'ماشین حساب', style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 16), Wrap( spacing: 12, runSpacing: 12, crossAxisAlignment: WrapCrossAlignment.center, children: [ SizedBox( width: 130, child: TextField( controller: _first, textDirection: TextDirection.ltr, keyboardType: const TextInputType.numberWithOptions( decimal: true, signed: true, ), decoration: const InputDecoration(labelText: 'عدد اول'), ), ), DropdownButton( value: _operation, items: ['+', '-', '*', '/'].map((value) { return DropdownMenuItem(value: value, child: Text(value)); }).toList(), onChanged: _busy ? null : (value) { if (value != null) setState(() => _operation = value); }, ), SizedBox( width: 130, child: TextField( controller: _second, textDirection: TextDirection.ltr, keyboardType: const TextInputType.numberWithOptions( decimal: true, signed: true, ), decoration: const InputDecoration(labelText: 'عدد دوم'), ), ), ], ), const SizedBox(height: 16), FilledButton( onPressed: _busy ? null : _calculate, child: Text(_busy ? 'در حال انجام…' : 'محاسبه'), ), if (_result != null) ...[ const SizedBox(height: 16), Text( _result!.toStringAsFixed(decimals), textDirection: TextDirection.ltr, style: Theme.of(context).textTheme.headlineMedium, ), ], ], ), ), ); } }