Moved search popup to the bottom not to override the editor, added wrap around, other enhancements

pull/1341/head
Alspb 2 years ago
parent 3a69551191
commit ac3eda3686
  1. 186
      lib/src/widgets/toolbar/search_dialog.dart

@ -23,6 +23,8 @@ class _SearchDialogState extends State<SearchDialog> {
late TextEditingController _controller; late TextEditingController _controller;
late List<int>? _offsets; late List<int>? _offsets;
late int _index; late int _index;
bool _case_sensitive = false;
bool _whole_word = false;
@override @override
void initState() { void initState() {
@ -35,87 +37,113 @@ class _SearchDialogState extends State<SearchDialog> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return StatefulBuilder(builder: (context, setState) { var matchShown = '';
var label = '';
if (_offsets != null) { if (_offsets != null) {
label = '${_offsets!.length} ${'matches'.i18n}'; if (_offsets!.isEmpty) {
if (_offsets!.isNotEmpty) { matchShown = '0/0';
label += ', ${'showing match'.i18n} ${_index + 1}'; } else {
matchShown = '${_index + 1}/${_offsets!.length}';
} }
} }
return AlertDialog(
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
backgroundColor: widget.dialogTheme?.dialogBackgroundColor, backgroundColor: widget.dialogTheme?.dialogBackgroundColor,
content: Container( alignment: Alignment.bottomCenter,
height: 100, insetPadding: EdgeInsets.zero,
child: Column( child: SizedBox(
height: 45,
child: Row(
children: [ children: [
TextField( Tooltip(
keyboardType: TextInputType.multiline, message: 'Case sensitivity and whole word search',
child: ToggleButtons(
onPressed: (int index) {
if (index == 0) {
_changeCaseSensitivity();
} else if (index == 1) {
_changeWholeWord();
}
},
borderRadius: const BorderRadius.all(Radius.circular(2)),
isSelected: [_case_sensitive, _whole_word],
children: const [
Text(
'\u0391\u03b1',
style: TextStyle(
fontFamily: 'MaterialIcons',
fontSize: 24,
),
),
Text(
'\u201c\u2026\u201d',
style: TextStyle(
fontFamily: 'MaterialIcons',
fontSize: 24,
),
),
],
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(bottom: 12, left: 5),
child: TextField(
style: widget.dialogTheme?.inputTextStyle, style: widget.dialogTheme?.inputTextStyle,
decoration: InputDecoration( decoration: InputDecoration(
labelText: 'Search'.i18n, isDense: true,
labelStyle: widget.dialogTheme?.labelTextStyle, suffixText: (_offsets != null) ? matchShown : '',
floatingLabelStyle: widget.dialogTheme?.labelTextStyle), suffixStyle: widget.dialogTheme?.labelTextStyle,
),
autofocus: true, autofocus: true,
onChanged: _textChanged, onChanged: _textChanged,
textInputAction: TextInputAction.done,
onEditingComplete: _findText,
controller: _controller, controller: _controller,
), ),
if (_offsets != null)
Padding(
padding: const EdgeInsets.all(8),
child: Text(label, textAlign: TextAlign.left),
), ),
],
), ),
if (_offsets == null)
IconButton(
icon: const Icon(Icons.search),
tooltip: 'Find text',
onPressed: _findText,
), ),
actions: [ if (_offsets != null)
if (_offsets != null && _offsets!.isNotEmpty && _index > 0) IconButton(
TextButton( icon: const Icon(Icons.keyboard_arrow_up),
onPressed: () { tooltip: 'Move to previous occurrence',
setState(() { onPressed: (_offsets!.isNotEmpty) ? _moveToPrevious : null,
_index -= 1;
});
_moveToPosition();
},
child: Text(
'Prev'.i18n,
style: widget.dialogTheme?.labelTextStyle,
), ),
if (_offsets != null)
IconButton(
icon: const Icon(Icons.keyboard_arrow_down),
tooltip: 'Move to next occurrence',
onPressed: (_offsets!.isNotEmpty) ? _moveToNext : null,
), ),
if (_offsets != null && ],
_offsets!.isNotEmpty &&
_index < _offsets!.length - 1)
TextButton(
onPressed: () {
setState(() {
_index += 1;
});
_moveToPosition();
},
child: Text(
'Next'.i18n,
style: widget.dialogTheme?.labelTextStyle,
), ),
), ),
if (_offsets == null && _text.isNotEmpty) );
TextButton( }
onPressed: () {
void _findText() {
if (_text.isEmpty) {
return;
}
setState(() { setState(() {
_offsets = widget.controller.document.search(_text); _offsets = widget.controller.document.search(
_text,
caseSensitive: _case_sensitive,
wholeWord: _whole_word,
);
_index = 0; _index = 0;
}); });
if (_offsets!.isNotEmpty) { if (_offsets!.isNotEmpty) {
_moveToPosition(); _moveToPosition();
} }
},
child: Text(
'Ok'.i18n,
style: widget.dialogTheme?.labelTextStyle,
),
),
],
);
});
} }
void _moveToPosition() { void _moveToPosition() {
@ -126,6 +154,34 @@ class _SearchDialogState extends State<SearchDialog> {
ChangeSource.LOCAL); ChangeSource.LOCAL);
} }
void _moveToPrevious() {
if (_offsets!.isEmpty) {
return;
}
setState(() {
if (_index > 0) {
_index -= 1;
} else {
_index = _offsets!.length - 1;
}
});
_moveToPosition();
}
void _moveToNext() {
if (_offsets!.isEmpty) {
return;
}
setState(() {
if (_index < _offsets!.length - 1) {
_index += 1;
} else {
_index = 0;
}
});
_moveToPosition();
}
void _textChanged(String value) { void _textChanged(String value) {
setState(() { setState(() {
_text = value; _text = value;
@ -133,4 +189,20 @@ class _SearchDialogState extends State<SearchDialog> {
_index = 0; _index = 0;
}); });
} }
void _changeCaseSensitivity() {
setState(() {
_case_sensitive = !_case_sensitive;
_offsets = null;
_index = 0;
});
}
void _changeWholeWord() {
setState(() {
_whole_word = !_whole_word;
_offsets = null;
_index = 0;
});
}
} }

Loading…
Cancel
Save