Skip to content

Commit 5b97dc7

Browse files
Malargalexeyinkin
andauthored
Issue207 popup display bug (akvelon#209)
* suggestions popup changed to overlayentry * fix vertical overflow * fixed popup overflow bug * pr fixes * fix pr * Update lib/src/wip/autocomplete/popup.dart Co-authored-by: alexeyinkin <[email protected]> * Update lib/src/wip/autocomplete/popup.dart Co-authored-by: alexeyinkin <[email protected]> * Update lib/src/wip/autocomplete/popup.dart Co-authored-by: alexeyinkin <[email protected]> * Update lib/src/code_field/code_field.dart Co-authored-by: alexeyinkin <[email protected]> --------- Co-authored-by: alexeyinkin <[email protected]>
1 parent 079e111 commit 5b97dc7

File tree

5 files changed

+181
-103
lines changed

5 files changed

+181
-103
lines changed

analysis_options.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@ include: package:total_lints/app.yaml
33
analyzer:
44
exclude:
55
- lib/src/wip
6+
7+
linter:
8+
rules:
9+
prefer_if_elements_to_conditional_expressions: false

lib/src/code_field/code_controller.dart

+1-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ class CodeController extends TextEditingController {
8686

8787
final _styleList = <TextStyle>[];
8888
final _modifierMap = <String, CodeModifier>{};
89-
bool isPopupShown = false;
9089
RegExp? _styleRegExp;
9190
late PopupController popupController;
9291
final autocompleter = Autocompleter();
@@ -269,7 +268,7 @@ class CodeController extends TextEditingController {
269268
}
270269

271270
KeyEventResult _onKeyDownRepeat(KeyEvent event) {
272-
if (popupController.isPopupShown) {
271+
if (popupController.shouldShow) {
273272
if (event.logicalKey == LogicalKeyboardKey.arrowUp) {
274273
popupController.scrollByArrow(ScrollDirection.up);
275274
return KeyEventResult.handled;

lib/src/code_field/code_field.dart

+100-57
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import 'dart:async';
21
import 'dart:math';
32

43
import 'package:flutter/material.dart';
@@ -181,17 +180,21 @@ class _CodeFieldState extends State<CodeField> {
181180
ScrollController? _horizontalCodeScroll;
182181
final _codeFieldKey = GlobalKey();
183182

183+
OverlayEntry? _suggestionsPopup;
184184
Offset _normalPopupOffset = Offset.zero;
185185
Offset _flippedPopupOffset = Offset.zero;
186186
double painterWidth = 0;
187187
double painterHeight = 0;
188188

189-
StreamSubscription<bool>? _keyboardVisibilitySubscription;
190189
FocusNode? _focusNode;
191190
String? lines;
192191
String longestLine = '';
193192
Size? windowSize;
194193
late TextStyle textStyle;
194+
Color? _backgroundCol;
195+
196+
final _editorKey = GlobalKey();
197+
Offset? _editorOffset;
195198

196199
@override
197200
void initState() {
@@ -202,6 +205,7 @@ class _CodeFieldState extends State<CodeField> {
202205

203206
widget.controller.addListener(_onTextChanged);
204207
widget.controller.addListener(_updatePopupOffset);
208+
widget.controller.popupController.addListener(_onPopupStateChanged);
205209
_horizontalCodeScroll = ScrollController();
206210
_focusNode = widget.focusNode ?? FocusNode();
207211
_focusNode!.attach(context, onKeyEvent: _onKeyEvent);
@@ -226,13 +230,25 @@ class _CodeFieldState extends State<CodeField> {
226230
void dispose() {
227231
widget.controller.removeListener(_onTextChanged);
228232
widget.controller.removeListener(_updatePopupOffset);
233+
widget.controller.popupController.removeListener(_onPopupStateChanged);
229234
_numberScroll?.dispose();
230235
_codeScroll?.dispose();
231236
_horizontalCodeScroll?.dispose();
232-
unawaited(_keyboardVisibilitySubscription?.cancel());
233237
super.dispose();
234238
}
235239

240+
@override
241+
void didUpdateWidget(covariant CodeField oldWidget) {
242+
super.didUpdateWidget(oldWidget);
243+
widget.controller.removeListener(_onTextChanged);
244+
widget.controller.removeListener(_updatePopupOffset);
245+
widget.controller.popupController.removeListener(_onPopupStateChanged);
246+
247+
widget.controller.addListener(_onTextChanged);
248+
widget.controller.addListener(_updatePopupOffset);
249+
widget.controller.popupController.addListener(_onPopupStateChanged);
250+
}
251+
236252
void rebuild() {
237253
setState(() {
238254
WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -263,6 +279,16 @@ class _CodeFieldState extends State<CodeField> {
263279
if (line.length > longestLine.length) longestLine = line;
264280
});
265281

282+
if (_codeScroll != null && _editorKey.currentContext != null) {
283+
final box = _editorKey.currentContext!.findRenderObject() as RenderBox?;
284+
_editorOffset = box?.localToGlobal(Offset.zero);
285+
if (_editorOffset != null) {
286+
var fixedOffset = _editorOffset!;
287+
fixedOffset += Offset(0, _codeScroll!.offset);
288+
_editorOffset = fixedOffset;
289+
}
290+
}
291+
266292
rebuild();
267293
}
268294

@@ -287,7 +313,6 @@ class _CodeFieldState extends State<CodeField> {
287313
child: Text(longestLine, style: textStyle),
288314
), // Add extra padding
289315
),
290-
// ignore: prefer_if_elements_to_conditional_expressions
291316
widget.expands ? Expanded(child: codeField) : codeField,
292317
],
293318
),
@@ -310,12 +335,12 @@ class _CodeFieldState extends State<CodeField> {
310335

311336
final themeData = Theme.of(context);
312337
final styles = CodeTheme.of(context)?.styles;
313-
Color? backgroundCol = widget.background ??
338+
_backgroundCol = widget.background ??
314339
styles?[rootKey]?.backgroundColor ??
315340
DefaultStyles.backgroundColor;
316341

317342
if (widget.decoration != null) {
318-
backgroundCol = null;
343+
_backgroundCol = null;
319344
}
320345

321346
final defaultTextStyle = TextStyle(
@@ -325,35 +350,6 @@ class _CodeFieldState extends State<CodeField> {
325350

326351
textStyle = defaultTextStyle.merge(widget.textStyle);
327352

328-
final lineNumberSize = textStyle.fontSize;
329-
final lineNumberColor =
330-
widget.gutterStyle.textStyle?.color ?? textStyle.color?.withOpacity(.5);
331-
332-
final lineNumberTextStyle =
333-
(widget.gutterStyle.textStyle ?? textStyle).copyWith(
334-
color: lineNumberColor,
335-
fontFamily: textStyle.fontFamily,
336-
fontSize: lineNumberSize,
337-
);
338-
339-
final gutterStyle = widget.gutterStyle.copyWith(
340-
textStyle: lineNumberTextStyle,
341-
errorPopupTextStyle: widget.gutterStyle.errorPopupTextStyle ??
342-
textStyle.copyWith(
343-
fontSize: DefaultStyles.errorPopupTextSize,
344-
backgroundColor: DefaultStyles.backgroundColor,
345-
fontStyle: DefaultStyles.fontStyle,
346-
),
347-
);
348-
349-
Widget? gutter;
350-
if (gutterStyle.showGutter) {
351-
gutter = GutterWidget(
352-
codeController: widget.controller,
353-
style: gutterStyle,
354-
);
355-
}
356-
357353
final codeField = TextField(
358354
focusNode: _focusNode,
359355
scrollPadding: widget.padding,
@@ -395,37 +391,48 @@ class _CodeFieldState extends State<CodeField> {
395391
shortcuts: _shortcuts,
396392
child: Container(
397393
decoration: widget.decoration,
398-
color: backgroundCol,
394+
color: _backgroundCol,
399395
key: _codeFieldKey,
400396
padding: const EdgeInsets.only(left: 8),
401397
child: Row(
402398
crossAxisAlignment: CrossAxisAlignment.start,
403399
children: [
404-
if (gutter != null) gutter,
405-
Expanded(
406-
child: Stack(
407-
children: [
408-
editingField,
409-
if (widget.controller.popupController.isPopupShown &&
410-
windowSize != null)
411-
Popup(
412-
normalOffset: _normalPopupOffset,
413-
flippedOffset: _flippedPopupOffset,
414-
controller: widget.controller.popupController,
415-
editingWindowSize: windowSize!,
416-
style: textStyle,
417-
backgroundColor: backgroundCol,
418-
parentFocusNode: _focusNode!,
419-
),
420-
],
421-
),
422-
),
400+
if (widget.gutterStyle.showGutter) _buildGutter(),
401+
Expanded(key: _editorKey, child: editingField),
423402
],
424403
),
425404
),
426405
);
427406
}
428407

408+
Widget _buildGutter() {
409+
final lineNumberSize = textStyle.fontSize;
410+
final lineNumberColor =
411+
widget.gutterStyle.textStyle?.color ?? textStyle.color?.withOpacity(.5);
412+
413+
final lineNumberTextStyle =
414+
(widget.gutterStyle.textStyle ?? textStyle).copyWith(
415+
color: lineNumberColor,
416+
fontFamily: textStyle.fontFamily,
417+
fontSize: lineNumberSize,
418+
);
419+
420+
final gutterStyle = widget.gutterStyle.copyWith(
421+
textStyle: lineNumberTextStyle,
422+
errorPopupTextStyle: widget.gutterStyle.errorPopupTextStyle ??
423+
textStyle.copyWith(
424+
fontSize: DefaultStyles.errorPopupTextSize,
425+
backgroundColor: DefaultStyles.backgroundColor,
426+
fontStyle: DefaultStyles.fontStyle,
427+
),
428+
);
429+
430+
return GutterWidget(
431+
codeController: widget.controller,
432+
style: gutterStyle,
433+
);
434+
}
435+
429436
void _updatePopupOffset() {
430437
final textPainter = _getTextPainter(widget.controller.text);
431438
final caretHeight = _getCaretHeight(textPainter);
@@ -467,7 +474,8 @@ class _CodeFieldState extends State<CodeField> {
467474
return max(
468475
_getCaretOffset(textPainter).dx +
469476
widget.padding.left -
470-
_horizontalCodeScroll!.offset,
477+
_horizontalCodeScroll!.offset +
478+
(_editorOffset?.dx ?? 0),
471479
0,
472480
);
473481
}
@@ -478,8 +486,43 @@ class _CodeFieldState extends State<CodeField> {
478486
caretHeight +
479487
16 +
480488
widget.padding.top -
481-
_codeScroll!.offset,
489+
_codeScroll!.offset +
490+
(_editorOffset?.dy ?? 0),
482491
0,
483492
);
484493
}
494+
495+
void _onPopupStateChanged() {
496+
final shouldShow =
497+
widget.controller.popupController.shouldShow && windowSize != null;
498+
if (!shouldShow) {
499+
_suggestionsPopup?.remove();
500+
_suggestionsPopup = null;
501+
return;
502+
}
503+
504+
if (_suggestionsPopup == null) {
505+
_suggestionsPopup = _buildSuggestionOverlay();
506+
Overlay.of(context).insert(_suggestionsPopup!);
507+
}
508+
509+
_suggestionsPopup!.markNeedsBuild();
510+
}
511+
512+
OverlayEntry _buildSuggestionOverlay() {
513+
return OverlayEntry(
514+
builder: (context) {
515+
return Popup(
516+
normalOffset: _normalPopupOffset,
517+
flippedOffset: _flippedPopupOffset,
518+
controller: widget.controller.popupController,
519+
editingWindowSize: windowSize!,
520+
style: textStyle,
521+
backgroundColor: _backgroundCol,
522+
parentFocusNode: _focusNode!,
523+
editorOffset: _editorOffset,
524+
);
525+
},
526+
);
527+
}
485528
}

0 commit comments

Comments
 (0)