@@ -11,111 +11,106 @@ class TerminalLevelFilterMenu extends StatelessWidget {
1111 final Set <TerminalLevel > selected;
1212 final ValueChanged <Set <TerminalLevel >> onChanged;
1313
14- void _toggleLevel (TerminalLevel level) {
15- final next = selected.contains (level)
16- ? (selected.toSet ()..remove (level))
17- : (selected.toSet ()..add (level));
18- onChanged (next);
14+ void _showFilterDialog (BuildContext context) {
15+ showDialog <Set <TerminalLevel >>(
16+ context: context,
17+ builder: (context) => _FilterDialog (selected: selected),
18+ ).then ((result) {
19+ if (result != null ) {
20+ onChanged (result);
21+ }
22+ });
1923 }
2024
2125 @override
2226 Widget build (BuildContext context) {
23- final all = TerminalLevel .values.toSet ();
24- return PopupMenuButton <_MenuAction >(
27+ return IconButton (
2528 tooltip: 'Filter' ,
2629 icon: const Icon (Icons .filter_alt),
27- onSelected : (action) {
28- switch (action) {
29- case _MenuAction .toggleDebug :
30- _toggleLevel ( TerminalLevel .debug);
31- break ;
32- case _MenuAction .toggleInfo :
33- _toggleLevel ( TerminalLevel .info);
34- break ;
35- case _MenuAction .toggleWarn :
36- _toggleLevel ( TerminalLevel .warn);
37- break ;
38- case _MenuAction .toggleError :
39- _toggleLevel ( TerminalLevel .error);
40- break ;
41- case _MenuAction .selectAll :
42- onChanged (all) ;
43- break ;
44- case _MenuAction .clearAll :
45- onChanged ( < TerminalLevel > {} );
46- break ;
47- }
48- },
49- itemBuilder : (context) => [
50- CheckedPopupMenuItem < _MenuAction >(
51- value : _MenuAction .toggleError,
52- checked : selected. contains ( TerminalLevel .error),
53- child : const ListTile (
54- dense : true ,
55- contentPadding : EdgeInsets .zero,
56- leading : Icon ( Icons .error_outline_rounded, color : Colors .red),
57- title : Text ( 'Errors' ),
58- ),
59- ),
60- CheckedPopupMenuItem < _MenuAction >(
61- value : _MenuAction .toggleWarn,
62- checked : selected. contains ( TerminalLevel .warn),
63- child : const ListTile (
64- dense : true ,
65- contentPadding : EdgeInsets .zero,
66- leading : Icon ( Icons .warning_amber_outlined, color : Colors .amber),
67- title : Text ( 'Warnings' ),
68- ),
69- ),
70- CheckedPopupMenuItem < _MenuAction >(
71- value : _MenuAction .toggleInfo,
72- checked : selected. contains ( TerminalLevel .info) ,
73- child : const ListTile (
74- dense : true ,
75- contentPadding : EdgeInsets .zero,
76- leading : Icon ( Icons .info_outline, color : Colors .blue ),
77- title : Text ( 'Info' ),
78- ),
79- ),
80- CheckedPopupMenuItem < _MenuAction >(
81- value : _MenuAction .toggleDebug ,
82- checked : selected. contains ( TerminalLevel .debug),
83- child : const ListTile (
84- dense : true ,
85- contentPadding : EdgeInsets .zero,
86- leading : Icon ( Icons .bug_report_outlined),
87- title : Text ( 'Debug' ),
88- ),
89- ),
90- const PopupMenuDivider ( ),
91- PopupMenuItem < _MenuAction > (
92- value : _MenuAction .selectAll,
93- child : const ListTile (
94- dense : true ,
95- contentPadding : EdgeInsets .zero ,
96- leading : Icon ( Icons .select_all ),
97- title : Text ( 'Select all' ) ,
30+ onPressed : () => _showFilterDialog (context),
31+ );
32+ }
33+ }
34+
35+ const _levelMeta = < TerminalLevel , ({ IconData icon, Color ? color, String label}) > {
36+ TerminalLevel .error : (icon : Icons .error_outline_rounded, color : Colors .red, label : 'Errors' ),
37+ TerminalLevel .warn : (icon : Icons .warning_amber_outlined, color : Colors .amber, label : 'Warnings' ),
38+ TerminalLevel .info : (icon : Icons .info_outline, color : Colors .blue, label : 'Info' ),
39+ TerminalLevel .debug : (icon : Icons .bug_report_outlined, color : null , label : 'Debug' ),
40+ } ;
41+
42+ class _FilterDialog extends StatefulWidget {
43+ const _FilterDialog ({ required this .selected}) ;
44+
45+ final Set < TerminalLevel > selected ;
46+
47+ @override
48+ State < _FilterDialog > createState () => _FilterDialogState ( );
49+ }
50+
51+ class _FilterDialogState extends State < _FilterDialog > {
52+ late Set < TerminalLevel > _selected;
53+
54+ @override
55+ void initState () {
56+ super . initState ();
57+ _selected = widget.selected. toSet ();
58+ }
59+
60+ void _toggle ( TerminalLevel level) {
61+ setState (() {
62+ if (_selected. contains (level)) {
63+ _selected. remove (level);
64+ } else {
65+ _selected. add (level);
66+ }
67+ });
68+ }
69+
70+ @override
71+ Widget build ( BuildContext context) {
72+ return AlertDialog (
73+ title : const Text ( 'Filter Levels' ),
74+ content : Column (
75+ mainAxisSize : MainAxisSize .min ,
76+ children : [
77+ for ( final entry in _levelMeta.entries)
78+ CheckboxListTile (
79+ value : _selected. contains (entry.key ),
80+ onChanged : (_) => _toggle (entry.key ),
81+ secondary : Icon (entry.value.icon, color : entry.value.color ),
82+ title : Text (entry.value.label ),
83+ ),
84+ const Divider () ,
85+ Row (
86+ mainAxisAlignment : MainAxisAlignment .spaceEvenly,
87+ children : [
88+ TextButton (
89+ onPressed : () => setState (() {
90+ _selected = TerminalLevel .values. toSet ();
91+ } ),
92+ child : const Text ( 'Select all' ),
93+ ),
94+ TextButton (
95+ onPressed : () => setState (() {
96+ _selected. clear ();
97+ }) ,
98+ child : const Text ( 'Clear selection' ) ,
99+ ),
100+ ] ,
98101 ),
102+ ],
103+ ),
104+ actions: [
105+ TextButton (
106+ onPressed: () => Navigator .of (context).pop (),
107+ child: const Text ('Cancel' ),
99108 ),
100- PopupMenuItem <_MenuAction >(
101- value: _MenuAction .clearAll,
102- child: const ListTile (
103- dense: true ,
104- contentPadding: EdgeInsets .zero,
105- leading: Icon (Icons .clear_all),
106- title: Text ('Clear selection' ),
107- ),
109+ FilledButton (
110+ onPressed: () => Navigator .of (context).pop (_selected),
111+ child: const Text ('Apply' ),
108112 ),
109113 ],
110114 );
111115 }
112116}
113-
114- enum _MenuAction {
115- toggleDebug,
116- toggleInfo,
117- toggleWarn,
118- toggleError,
119- selectAll,
120- clearAll,
121- }
0 commit comments