This is an automated email from the ASF dual-hosted git repository. pabloem pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/beam.git
The following commit(s) were added to refs/heads/master by this push: new 0702451 Merge pull request #16892 from [BEAM-13755] [Playground] Scroll the opened example to the context line 0702451 is described below commit 07024513d7775a599c9c90768a6903909a0d1656 Author: Alexander Zhuravlev <alexander.zhurav...@akvelon.com> AuthorDate: Mon Feb 28 20:50:51 2022 +0400 Merge pull request #16892 from [BEAM-13755] [Playground] Scroll the opened example to the context line * [BEAM-13755] Added contextLine parameter to examples, reworked text scrolling * [BEAM-13755] Improving text scrolling * [BEAM-13755] Updated text scrolling in the editor textarea * [BEAM-13755] Fixed PR Remarks --- .../modules/editor/components/editor_textarea.dart | 94 +++++++++++++++------- .../lib/modules/examples/models/example_model.dart | 2 + .../example_client/grpc_example_client.dart | 1 + 3 files changed, 67 insertions(+), 30 deletions(-) diff --git a/playground/frontend/lib/modules/editor/components/editor_textarea.dart b/playground/frontend/lib/modules/editor/components/editor_textarea.dart index 42e505d..cef01cf 100644 --- a/playground/frontend/lib/modules/editor/components/editor_textarea.dart +++ b/playground/frontend/lib/modules/editor/components/editor_textarea.dart @@ -31,7 +31,6 @@ import 'package:playground/modules/examples/models/example_model.dart'; import 'package:playground/modules/sdk/models/sdk.dart'; import 'package:provider/provider.dart'; -const kNumberOfStringsToSkip = 16; const kJavaRegExp = r'import\s[A-z.0-9]*\;\n\n[(\/\*\*)|(public)|(class)]'; const kPythonRegExp = r'[^\S\r\n](import|as)[^\S\r\n][A-z]*\n\n'; const kGoRegExp = r'[^\S\r\n]+\' @@ -39,6 +38,7 @@ const kGoRegExp = r'[^\S\r\n]+\' r'.*' r'"' r'\n\)\n\n'; +const kAdditionalLinesForScrolling = 4; class EditorTextArea extends StatefulWidget { final SDK sdk; @@ -65,6 +65,7 @@ class EditorTextArea extends StatefulWidget { class _EditorTextAreaState extends State<EditorTextArea> { CodeController? _codeController; var focusNode = FocusNode(); + final GlobalKey codeFieldKey = LabeledGlobalKey('CodeFieldKey'); @override void initState() { @@ -86,10 +87,6 @@ class _EditorTextAreaState extends State<EditorTextArea> { webSpaceFix: false, ); - if (widget.enableScrolling) { - _setTextScrolling(); - } - super.didChangeDependencies(); } @@ -102,6 +99,8 @@ class _EditorTextAreaState extends State<EditorTextArea> { @override Widget build(BuildContext context) { + WidgetsBinding.instance!.addPostFrameCallback((_) => _setTextScrolling()); + return Semantics( container: true, textField: true, @@ -112,6 +111,7 @@ class _EditorTextAreaState extends State<EditorTextArea> { child: FocusScope( node: FocusScopeNode(canRequestFocus: widget.isEditable), child: CodeField( + key: codeFieldKey, focusNode: focusNode, enabled: widget.enabled, controller: _codeController!, @@ -133,44 +133,78 @@ class _EditorTextAreaState extends State<EditorTextArea> { focusNode.requestFocus(); if (_codeController!.text.isNotEmpty) { _codeController!.selection = TextSelection.fromPosition( - TextPosition(offset: _findOffset()), + TextPosition( + offset: _getOffset(), + ), ); } } - _findOffset() { + int _getOffset() { + int contextLine = _getIndexOfContextLine(); + String pattern = _getPattern(_getQntOfStringsOnScreen()); + + if (pattern == '' || pattern == '}') { + return _codeController!.text.lastIndexOf(pattern); + } + return _codeController!.text.indexOf( - _skipStrings(kNumberOfStringsToSkip), - _getPositionAfterImportsAndLicenses(widget.sdk), + pattern, + contextLine, ); } - String _skipStrings(int qntOfStrings) { - List<String> strings = _codeController!.text - .substring(_getPositionAfterImportsAndLicenses(widget.sdk)) - .split('\n'); + String _getPattern(int qntOfStrings) { + int contextLineIndex = _getIndexOfContextLine(); + List<String> stringsAfterContextLine = + _codeController!.text.substring(contextLineIndex).split('\n'); + String result = - strings.length > qntOfStrings ? strings[qntOfStrings] : strings.last; - if (result == '') { - return _skipStrings(qntOfStrings - 1); - } else { - return result; + stringsAfterContextLine.length + kAdditionalLinesForScrolling > + qntOfStrings + ? _getResultSubstring(stringsAfterContextLine, qntOfStrings) + : stringsAfterContextLine.last; + + return result; + } + + int _getQntOfStringsOnScreen() { + RenderBox rBox = + codeFieldKey.currentContext?.findRenderObject() as RenderBox; + double height = rBox.size.height * .75; + + return height ~/ kCodeFontSize; + } + + int _getIndexOfContextLine() { + int ctxLineNumber = widget.example!.contextLine; + String contextLine = _codeController!.text.split('\n')[ctxLineNumber]; + + while (contextLine == '') { + ctxLineNumber -= 1; + contextLine = _codeController!.text.split('\n')[ctxLineNumber]; } + + return _codeController!.text.indexOf(contextLine); } - int _getPositionAfterImportsAndLicenses(SDK sdk) { - switch (sdk) { - case SDK.java: - return _codeController!.text.lastIndexOf(RegExp(kJavaRegExp)); - case SDK.python: - return _codeController!.text.lastIndexOf(RegExp(kPythonRegExp)); - case SDK.go: - return _codeController!.text.lastIndexOf(RegExp(kGoRegExp)); - case SDK.scio: - return _codeController!.text.indexOf( - _codeController!.text.split('\n')[0], - ); + // This function made for more accuracy in the process of finding an exact line. + String _getResultSubstring( + List<String> stringsAfterContextLine, + int qntOfStrings, + ) { + StringBuffer result = StringBuffer(); + + for (int i = qntOfStrings - kAdditionalLinesForScrolling; + i < qntOfStrings + kAdditionalLinesForScrolling; + i++) { + if (i == stringsAfterContextLine.length - 1) { + return result.toString(); + } + result.write(stringsAfterContextLine[i] + '\n'); } + + return result.toString(); } _getLanguageFromSdk() { diff --git a/playground/frontend/lib/modules/examples/models/example_model.dart b/playground/frontend/lib/modules/examples/models/example_model.dart index e6f850a..cd752c2 100644 --- a/playground/frontend/lib/modules/examples/models/example_model.dart +++ b/playground/frontend/lib/modules/examples/models/example_model.dart @@ -43,6 +43,7 @@ class ExampleModel with Comparable<ExampleModel> { final String name; final String path; final String description; + final int contextLine; bool isMultiFile; String? link; String? source; @@ -56,6 +57,7 @@ class ExampleModel with Comparable<ExampleModel> { required this.path, required this.description, required this.type, + this.contextLine = 1, this.isMultiFile = false, this.link, this.source, diff --git a/playground/frontend/lib/modules/examples/repositories/example_client/grpc_example_client.dart b/playground/frontend/lib/modules/examples/repositories/example_client/grpc_example_client.dart index 672b2e5..8c9f71e 100644 --- a/playground/frontend/lib/modules/examples/repositories/example_client/grpc_example_client.dart +++ b/playground/frontend/lib/modules/examples/repositories/example_client/grpc_example_client.dart @@ -223,6 +223,7 @@ class GrpcExampleClient implements ExampleClient { description: example.description, type: _exampleTypeFromString(example.type), path: example.cloudPath, + contextLine: example.contextLine, pipelineOptions: example.pipelineOptions, isMultiFile: example.multifile, link: example.link,