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. 216
      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) { if (_offsets!.isEmpty) {
label = '${_offsets!.length} ${'matches'.i18n}'; matchShown = '0/0';
if (_offsets!.isNotEmpty) { } else {
label += ', ${'showing match'.i18n} ${_index + 1}'; matchShown = '${_index + 1}/${_offsets!.length}';
}
} }
return AlertDialog( }
backgroundColor: widget.dialogTheme?.dialogBackgroundColor,
content: Container( return Dialog(
height: 100, shape: RoundedRectangleBorder(
child: Column( borderRadius: BorderRadius.circular(5),
children: [ ),
TextField( backgroundColor: widget.dialogTheme?.dialogBackgroundColor,
keyboardType: TextInputType.multiline, alignment: Alignment.bottomCenter,
style: widget.dialogTheme?.inputTextStyle, insetPadding: EdgeInsets.zero,
decoration: InputDecoration( child: SizedBox(
labelText: 'Search'.i18n, height: 45,
labelStyle: widget.dialogTheme?.labelTextStyle, child: Row(
floatingLabelStyle: widget.dialogTheme?.labelTextStyle), children: [
autofocus: true, Tooltip(
onChanged: _textChanged, message: 'Case sensitivity and whole word search',
controller: _controller, 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,
),
),
],
), ),
if (_offsets != null) ),
Padding( Expanded(
padding: const EdgeInsets.all(8), child: Padding(
child: Text(label, textAlign: TextAlign.left), padding: const EdgeInsets.only(bottom: 12, left: 5),
child: TextField(
style: widget.dialogTheme?.inputTextStyle,
decoration: InputDecoration(
isDense: true,
suffixText: (_offsets != null) ? matchShown : '',
suffixStyle: widget.dialogTheme?.labelTextStyle,
),
autofocus: true,
onChanged: _textChanged,
textInputAction: TextInputAction.done,
onEditingComplete: _findText,
controller: _controller,
), ),
],
),
),
actions: [
if (_offsets != null && _offsets!.isNotEmpty && _index > 0)
TextButton(
onPressed: () {
setState(() {
_index -= 1;
});
_moveToPosition();
},
child: Text(
'Prev'.i18n,
style: widget.dialogTheme?.labelTextStyle,
), ),
), ),
if (_offsets != null && if (_offsets == null)
_offsets!.isNotEmpty && IconButton(
_index < _offsets!.length - 1) icon: const Icon(Icons.search),
TextButton( tooltip: 'Find text',
onPressed: () { onPressed: _findText,
setState(() {
_index += 1;
});
_moveToPosition();
},
child: Text(
'Next'.i18n,
style: widget.dialogTheme?.labelTextStyle,
), ),
), if (_offsets != null)
if (_offsets == null && _text.isNotEmpty) IconButton(
TextButton( icon: const Icon(Icons.keyboard_arrow_up),
onPressed: () { tooltip: 'Move to previous occurrence',
setState(() { onPressed: (_offsets!.isNotEmpty) ? _moveToPrevious : null,
_offsets = widget.controller.document.search(_text);
_index = 0;
});
if (_offsets!.isNotEmpty) {
_moveToPosition();
}
},
child: Text(
'Ok'.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,
),
],
),
),
);
}
void _findText() {
if (_text.isEmpty) {
return;
}
setState(() {
_offsets = widget.controller.document.search(
_text,
caseSensitive: _case_sensitive,
wholeWord: _whole_word,
); );
_index = 0;
}); });
if (_offsets!.isNotEmpty) {
_moveToPosition();
}
} }
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