Changed icons and other minor changes

This commit is contained in:
Álvaro González 2026-03-19 12:05:10 +01:00
parent 12d755d810
commit daebfeb385
4 changed files with 63 additions and 167 deletions

View file

@ -81,23 +81,6 @@ class _FormulaListState extends State<FormulaList> {
} }
} }
void _editFormula(Formula formula) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FormulaEditor(
formula: formula,
corpus: widget.corpus,
onSave: (updatedFormula){
setState((){
// THIS UPDATES THE FORMULA LIST
});
}
),
),
);
}
void _copyFormula(Formula formula) async { void _copyFormula(Formula formula) async {
try { try {
final exportString = _formulaAndDependenciesToExportStringLiteral(formula); final exportString = _formulaAndDependenciesToExportStringLiteral(formula);
@ -137,22 +120,6 @@ class _FormulaListState extends State<FormulaList> {
); );
} }
void _importFromText() {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ImportFromTextScreen(
corpus: widget.corpus,
),
),
).then((result) {
if (result == true) {
setState(() {
// Refresh the list when returning from import
});
}
});
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -183,13 +150,9 @@ class _FormulaListState extends State<FormulaList> {
trailing: Row( trailing: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
IconButton(
icon: const Icon(Icons.edit),
onPressed: () => _editFormula(formula),
tooltip: 'Edit Formula',
),
PopupMenuButton( PopupMenuButton(
icon: const Icon(Icons.share), icon: const Icon(Icons.share),
tooltip: 'Share or copy to clipboard',
onSelected: (value) { onSelected: (value) {
if (value == 'share') { if (value == 'share') {
_shareFormula(formula); _shareFormula(formula);

View file

@ -121,14 +121,13 @@ class _FormulaScreenState extends State<FormulaScreen> {
} }
late final dynamic result; late final dynamic result;
//if( formula is DerivedFormula) { if( formula is DerivedFormula) {
result = formulaSolver(formula, formula.output.name, inputValues,); result = formulaSolver(formula, formula.output.name, inputValues,);
//} }
//else { else {
// TODO: MAYBE ONLY FORMULASOLVER IS NECCESSARY" final evaluator = FormulaEvaluator();
//final evaluator = FormulaEvaluator(); result = evaluator.evaluate(formula as Formula, inputValues);
//result = evaluator.evaluate(formula as Formula, inputValues); }
//}
// Convert output to selected unit if needed // Convert output to selected unit if needed
String? unit = formula.output.unit; String? unit = formula.output.unit;
@ -342,7 +341,7 @@ class _FormulaScreenState extends State<FormulaScreen> {
children: [ children: [
// Fixed width for field name // Fixed width for field name
SizedBox( SizedBox(
width: 150, width: 50,
child: Text( child: Text(
formula.output.name, formula.output.name,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,

View file

@ -5,7 +5,6 @@ import 'package:d4rt_formulas/corpus.dart';
import 'package:d4rt_formulas/ai/formula_editor.dart'; import 'package:d4rt_formulas/ai/formula_editor.dart';
import 'package:d4rt_formulas/services/import_service.dart'; import 'package:d4rt_formulas/services/import_service.dart';
import 'package:flutter_code_editor/flutter_code_editor.dart'; import 'package:flutter_code_editor/flutter_code_editor.dart';
import 'package:flutter_highlight/themes/monokai-sublime.dart'; import 'package:flutter_highlight/themes/monokai-sublime.dart';
import 'package:highlight/languages/dart.dart'; import 'package:highlight/languages/dart.dart';
@ -15,11 +14,7 @@ class ImportPreviewScreen extends StatefulWidget {
final List<FormulaElement> elements; final List<FormulaElement> elements;
final Corpus corpus; final Corpus corpus;
const ImportPreviewScreen({ const ImportPreviewScreen({super.key, required this.elements, required this.corpus});
super.key,
required this.elements,
required this.corpus,
});
@override @override
State<ImportPreviewScreen> createState() => _ImportPreviewScreenState(); State<ImportPreviewScreen> createState() => _ImportPreviewScreenState();
@ -52,9 +47,7 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
onSave: (updatedFormula) { onSave: (updatedFormula) {
// Update the element in the list // Update the element in the list
setState(() { setState(() {
final index = widget.elements.indexWhere( final index = widget.elements.indexWhere((e) => e is Formula && e.uuid == updatedFormula.uuid);
(e) => e is Formula && e.uuid == updatedFormula.uuid,
);
if (index != -1) { if (index != -1) {
widget.elements[index] = updatedFormula; widget.elements[index] = updatedFormula;
} }
@ -77,33 +70,27 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
}).toList(); }).toList();
if (selectedElements.isEmpty) { if (selectedElements.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(
const SnackBar( context,
content: Text('No elements selected to import'), ).showSnackBar(const SnackBar(content: Text('No elements selected to import'), backgroundColor: Colors.orange));
backgroundColor: Colors.orange,
),
);
return; return;
} }
try { try {
widget.corpus.loadFormulaElements(selectedElements, true); widget.corpus.loadFormulaElements(selectedElements, true);
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text('Imported ${selectedElements.length} element(s) successfully'), content: Text('Imported ${selectedElements.length} element(s) successfully'),
backgroundColor: Colors.green, backgroundColor: Colors.green,
), ),
); );
Navigator.pop(context, true); Navigator.pop(context, true);
} catch (e) { } catch (e) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(
SnackBar( context,
content: Text('Error importing: $e'), ).showSnackBar(SnackBar(content: Text('Error importing: $e'), backgroundColor: Colors.red));
backgroundColor: Colors.red,
),
);
} }
} }
@ -115,23 +102,14 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('Import Preview'), title: const Text('Import Preview'),
actions: [ actions: [IconButton(icon: const Icon(Icons.check), tooltip: 'Import Selected', onPressed: _importSelected)],
IconButton(
icon: const Icon(Icons.check),
tooltip: 'Import Selected',
onPressed: _importSelected,
),
],
), ),
body: Column( body: Column(
children: [ children: [
if (formulas.isEmpty && units.isEmpty) if (formulas.isEmpty && units.isEmpty)
const Padding( const Padding(
padding: EdgeInsets.all(16.0), padding: EdgeInsets.all(16.0),
child: Text( child: Text('No formula elements found in the shared content', style: TextStyle(fontSize: 16)),
'No formula elements found in the shared content',
style: TextStyle(fontSize: 16),
),
) )
else else
Expanded( Expanded(
@ -139,25 +117,13 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
children: [ children: [
if (formulas.isNotEmpty) ...[ if (formulas.isNotEmpty) ...[
const ListTile( const ListTile(
title: Text( title: Text('Formulas', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
'Formulas',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
), ),
...formulas.map((formula) => _buildFormulaTile(formula)), ...formulas.map((formula) => _buildFormulaTile(formula)),
], ],
if (units.isNotEmpty) ...[ if (units.isNotEmpty) ...[
const ListTile( const ListTile(
title: Text( title: Text('Units', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
'Units',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
), ),
...units.map((unit) => _buildUnitTile(unit)), ...units.map((unit) => _buildUnitTile(unit)),
], ],
@ -171,7 +137,7 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
Widget _buildFormulaTile(Formula formula) { Widget _buildFormulaTile(Formula formula) {
final isSelected = _selectedUuids.contains(formula.uuid); final isSelected = _selectedUuids.contains(formula.uuid);
return Card( return Card(
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: ListTile( child: ListTile(
@ -189,9 +155,7 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
), ),
title: Text(formula.name), title: Text(formula.name),
subtitle: Text( subtitle: Text(
formula.description?.isNotEmpty == true formula.description?.isNotEmpty == true ? formula.description!.split('\n').first : 'No description',
? formula.description!.split('\n').first
: 'No description',
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
@ -199,21 +163,22 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (formula.tags.isNotEmpty) if (formula.tags.isNotEmpty)
Wrap( SingleChildScrollView(
spacing: 4, child: SizedBox(
children: formula.tags.take(3).map((tag) { width: 150,
return Chip( child: Wrap(
label: Text(tag, style: const TextStyle(fontSize: 10)), spacing: 4,
padding: EdgeInsets.zero, children: formula.tags.take(10).map((tag) {
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, return Chip(
); label: Text(tag, style: const TextStyle(fontSize: 10)),
}).toList(), padding: EdgeInsets.zero,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
);
}).toList(),
),
),
), ),
IconButton( IconButton(icon: const Icon(Icons.edit), tooltip: 'Edit', onPressed: () => _editFormulaElement(formula)),
icon: const Icon(Icons.edit),
tooltip: 'Edit',
onPressed: () => _editFormulaElement(formula),
),
], ],
), ),
), ),
@ -222,7 +187,7 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
Widget _buildUnitTile(UnitSpec unit) { Widget _buildUnitTile(UnitSpec unit) {
final isSelected = _selectedUuids.contains(unit.name); final isSelected = _selectedUuids.contains(unit.name);
return Card( return Card(
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: ListTile( child: ListTile(
@ -249,20 +214,14 @@ class _ImportPreviewScreenState extends State<ImportPreviewScreen> {
class ImportFromTextScreen extends StatefulWidget { class ImportFromTextScreen extends StatefulWidget {
final Corpus corpus; final Corpus corpus;
const ImportFromTextScreen({ const ImportFromTextScreen({super.key, required this.corpus});
super.key,
required this.corpus,
});
@override @override
State<ImportFromTextScreen> createState() => _ImportFromTextScreenState(); State<ImportFromTextScreen> createState() => _ImportFromTextScreenState();
} }
class _ImportFromTextScreenState extends State<ImportFromTextScreen> { class _ImportFromTextScreenState extends State<ImportFromTextScreen> {
final CodeController _codeController = CodeController( final CodeController _codeController = CodeController(language: dart, text: "// Insert code here...");
language: dart,
text: "// Insert code here...",
);
bool _isLoading = false; bool _isLoading = false;
@override @override
@ -273,26 +232,20 @@ class _ImportFromTextScreenState extends State<ImportFromTextScreen> {
Future<void> _pasteFromClipboard() async { Future<void> _pasteFromClipboard() async {
setState(() => _isLoading = true); setState(() => _isLoading = true);
try { try {
final clipboardData = await Clipboard.getData('text/plain'); final clipboardData = await Clipboard.getData('text/plain');
if (clipboardData?.text != null) { if (clipboardData?.text != null) {
_codeController.text = clipboardData!.text!; _codeController.text = clipboardData!.text!;
} else { } else {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(
const SnackBar( context,
content: Text('Clipboard is empty'), ).showSnackBar(const SnackBar(content: Text('Clipboard is empty'), backgroundColor: Colors.orange));
backgroundColor: Colors.orange,
),
);
} }
} catch (e) { } catch (e) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(
SnackBar( context,
content: Text('Error pasting from clipboard: $e'), ).showSnackBar(SnackBar(content: Text('Error pasting from clipboard: $e'), backgroundColor: Colors.red));
backgroundColor: Colors.red,
),
);
} finally { } finally {
setState(() => _isLoading = false); setState(() => _isLoading = false);
} }
@ -302,42 +255,33 @@ class _ImportFromTextScreenState extends State<ImportFromTextScreen> {
final text = _codeController.fullText; final text = _codeController.fullText;
if (text.isEmpty) { if (text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar( const SnackBar(content: Text('Please enter or paste formula text'), backgroundColor: Colors.orange),
content: Text('Please enter or paste formula text'),
backgroundColor: Colors.orange,
),
); );
return; return;
} }
setState(() => _isLoading = true); setState(() => _isLoading = true);
try { try {
final importService = ImportService(); final importService = ImportService();
final elements = importService.parseSharedText(text); final elements = importService.parseSharedText(text);
if (!mounted) return; if (!mounted) return;
final result = await Navigator.push( final result = await Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => ImportPreviewScreen( builder: (context) => ImportPreviewScreen(elements: elements, corpus: widget.corpus),
elements: elements,
corpus: widget.corpus,
),
), ),
); );
if (result == true) { if (result == true) {
Navigator.pop(context, true); Navigator.pop(context, true);
} }
} catch (e) { } catch (e) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(
SnackBar( context,
content: Text('Error parsing text: $e'), ).showSnackBar(SnackBar(content: Text('Error parsing text: $e'), backgroundColor: Colors.red));
backgroundColor: Colors.red,
),
);
} finally { } finally {
setState(() => _isLoading = false); setState(() => _isLoading = false);
} }
@ -346,9 +290,7 @@ class _ImportFromTextScreenState extends State<ImportFromTextScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(title: const Text('Import from Text')),
title: const Text('Import from Text'),
),
body: Column( body: Column(
children: [ children: [
Expanded( Expanded(
@ -356,11 +298,7 @@ class _ImportFromTextScreenState extends State<ImportFromTextScreen> {
data: CodeThemeData(styles: monokaiSublimeTheme), data: CodeThemeData(styles: monokaiSublimeTheme),
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: SingleChildScrollView( child: SingleChildScrollView(child: CodeField(controller: _codeController)),
child: CodeField(
controller: _codeController,
),
),
), ),
), ),
), ),
@ -372,11 +310,7 @@ class _ImportFromTextScreenState extends State<ImportFromTextScreen> {
child: ElevatedButton.icon( child: ElevatedButton.icon(
onPressed: _isLoading ? null : _pasteFromClipboard, onPressed: _isLoading ? null : _pasteFromClipboard,
icon: _isLoading icon: _isLoading
? const SizedBox( ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2))
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.content_paste), : const Icon(Icons.content_paste),
label: const Text('Paste'), label: const Text('Paste'),
), ),
@ -385,7 +319,7 @@ class _ImportFromTextScreenState extends State<ImportFromTextScreen> {
Expanded( Expanded(
child: ElevatedButton.icon( child: ElevatedButton.icon(
onPressed: _isLoading ? null : _import, onPressed: _isLoading ? null : _import,
icon: const Icon(Icons.import_export), icon: const Icon(Icons.library_add),
label: const Text('Import'), label: const Text('Import'),
), ),
), ),

View file

@ -83,7 +83,7 @@ class _CorpusLoaderState extends State<CorpusLoader> {
title: const Text('Formulas'), title: const Text('Formulas'),
actions: [ actions: [
IconButton( IconButton(
icon: const Icon(Icons.import_export), icon: const Icon(Icons.library_add),
tooltip: 'Import formulas', tooltip: 'Import formulas',
onPressed: _handleImport, onPressed: _handleImport,
), ),