docs: Flutter-app directive can now also show the listings of code (#1500)

This commit is contained in:
Pasha Stetsenko
2022-03-29 12:43:06 -07:00
committed by GitHub
parent 167396142e
commit 0e91f5ca4d
5 changed files with 107 additions and 25 deletions

View File

@ -10,6 +10,7 @@ button.flutter-app-button {
font-size: 1.1em; font-size: 1.1em;
font-weight: bold; font-weight: bold;
line-height: 1em; line-height: 1em;
margin-right: 1em;
min-height: 26pt; min-height: 26pt;
min-width: 120pt; min-width: 120pt;
} }
@ -33,8 +34,45 @@ button.flutter-app-button:after {
top: 1px; top: 1px;
} }
.flutter-app-code {
display: none;
}
.flutter-app-code.active {
background: #282828;
box-shadow: 0 0 30px 0 #000;
box-sizing: border-box;
display: initial;
height: 80vh;
left: 50%;
overflow-y: scroll;
padding: 1em 2em;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 80vw;
}
.flutter-app-code .filename {
font-family: var(--font-mono);
font-size: 1.3em;
font-weight: bold;
margin: 1.5em 0 -0.5em 0;
}
.flutter-app-code div.highlight span.linenos {
color: #444;
margin-right: 8pt;
}
#flutter-app-overlay { #flutter-app-overlay {
background: #00000050; background: repeating-linear-gradient(
-45deg,
#000000bb 0px,
#000000bb 5px,
#000000aa 5px,
#000000aa 10px
);
display: none; display: none;
height: 100vh; height: 100vh;
left: 0; left: 0;
@ -49,8 +87,8 @@ button.flutter-app-button:after {
} }
#flutter-app-overlay.active iframe { #flutter-app-overlay.active iframe {
border: none; border: 1px solid #333;
box-shadow: 0px 0px 30px 0px #ffffff26; box-shadow: 0px 0px 30px 0px #000;
display: none; display: none;
height: 80vh; height: 80vh;
left: 50%; left: 50%;

View File

@ -4,13 +4,7 @@
/// creates an (x) button to hide the overlay. /// creates an (x) button to hide the overlay.
function run_flutter_app(url) { function run_flutter_app(url) {
let id = compute_iframe_id(url); let id = compute_iframe_id(url);
if (!$('#flutter-app-overlay').length) { create_overlay();
$('body').append($(`
<div id="flutter-app-overlay">
<button id="flutter-app-close-button" onclick="close_flutter_app()">✖</button>
</div>`
));
}
if (!$('#' + id).length) { if (!$('#' + id).length) {
$('#flutter-app-overlay').append($( $('#flutter-app-overlay').append($(
`<iframe id="${id}" class="flutter-app" src="${url}"></iframe>` `<iframe id="${id}" class="flutter-app" src="${url}"></iframe>`
@ -20,9 +14,29 @@ function run_flutter_app(url) {
$('#' + id).addClass('active'); $('#' + id).addClass('active');
} }
function open_code_listings(id) {
create_overlay();
if (!$('#flutter-app-overlay #' + id).length) {
$('#' + id).appendTo($('#flutter-app-overlay'));
}
$('#flutter-app-overlay').addClass('active');
$('#' + id).addClass('active');
}
function create_overlay() {
if (!$('#flutter-app-overlay').length) {
$('body').append($(`
<div id="flutter-app-overlay">
<button id="flutter-app-close-button" onclick="close_flutter_app()">✖</button>
</div>`
));
}
}
/// Handler for the (x) close button on an app iframe. /// Handler for the (x) close button on an app iframe.
function close_flutter_app() { function close_flutter_app() {
$('#flutter-app-overlay iframe').removeClass('active'); $('#flutter-app-overlay > iframe').removeClass('active');
$('#flutter-app-overlay > div').removeClass('active');
$('#flutter-app-overlay').removeClass('active'); $('#flutter-app-overlay').removeClass('active');
} }

View File

@ -1,4 +1,5 @@
#!/usr/bin/env python #!/usr/bin/env python
import glob
import os import os
import re import re
import shutil import shutil
@ -46,7 +47,8 @@ class FlutterAppDirective(SphinxDirective):
"popup", and "code". Each of these modes produces a different output: "popup", and "code". Each of these modes produces a different output:
"widget" - an iframe shown directly inside the docs page; "widget" - an iframe shown directly inside the docs page;
"popup" - a [Run] button which opens the app to (almost) fullscreen; "popup" - a [Run] button which opens the app to (almost) fullscreen;
"code" - (NYI) opens a popup showing the code that was compiled. "code" - a [Code] button which opens a popup with the code that was
compiled.
""" """
has_content = False has_content = False
required_arguments = 0 required_arguments = 0
@ -91,7 +93,14 @@ class FlutterAppDirective(SphinxDirective):
onclick=f'run_flutter_app("{iframe_url}")', onclick=f'run_flutter_app("{iframe_url}")',
)) ))
if 'code' in self.modes: if 'code' in self.modes:
pass code_id = self.app_name + "-source"
result.append(self._generate_code_listings(code_id))
result.append(Button(
'',
nodes.Text('Code'),
classes=['flutter-app-button', 'code'],
onclick=f'open_code_listings("{code_id}")',
))
if 'widget' in self.modes: if 'widget' in self.modes:
result.append(IFrame(src=iframe_url)) result.append(IFrame(src=iframe_url))
return result return result
@ -132,7 +141,7 @@ class FlutterAppDirective(SphinxDirective):
self.logger.info('Compiling Flutter app ' + self.app_name) self.logger.info('Compiling Flutter app ' + self.app_name)
self._compile_source() self._compile_source()
self._copy_compiled() self._copy_compiled()
self._create_index() self._create_index_html()
self.logger.info(' + copied into ' + self.target_dir) self.logger.info(' + copied into ' + self.target_dir)
assert os.path.isfile(self.target_dir + '/main.dart.js') assert os.path.isfile(self.target_dir + '/main.dart.js')
assert os.path.isfile(self.target_dir + '/index.html') assert os.path.isfile(self.target_dir + '/index.html')
@ -167,17 +176,38 @@ class FlutterAppDirective(SphinxDirective):
dirs_exist_ok=True, dirs_exist_ok=True,
) )
def _create_index(self): def _create_index_html(self):
target_file = os.path.join(self.target_dir, 'index.html') target_file = os.path.join(self.target_dir, 'index.html')
with open(target_file, 'wt') as out: with open(target_file, 'wt') as out:
out.write('<!DOCTYPE html>\n') out.write('<!DOCTYPE html>\n')
out.write('<html>\n<head>\n') out.write('<html>\n<head>\n')
out.write('<base href="%s%s/">\n' % (_doc_root(), self.html_dir)) out.write('<base href="%s%s/">\n' % (_doc_root(), self.html_dir))
out.write('<title>%s</title>\n' % self.app_name) out.write('<title>%s</title>\n' % self.app_name)
out.write('<style>body { background: black; }</style>\n')
out.write('</head>\n<body>\n') out.write('</head>\n<body>\n')
out.write('<script src="main.dart.js"></script>\n') out.write('<script src="main.dart.js"></script>\n')
out.write('</body>\n</html>\n') out.write('</body>\n</html>\n')
def _generate_code_listings(self, code_id):
code_dir = self.source_dir + '/lib/' + self.options.get('page', '')
if not os.path.isdir(code_dir):
raise self.error('Cannot find source directory ' + code_dir)
files = glob.glob(code_dir + '/**', recursive=True)
result = nodes.container(classes=['flutter-app-code'], ids=[code_id])
for filename in sorted(files):
if os.path.isfile(filename):
simple_filename = os.path.relpath(filename, code_dir)
result += nodes.container(
'', nodes.Text(simple_filename), classes=['filename']
)
with open(filename, 'rt') as f:
self.state.nested_parse(
['``````{code-block} dart\n:lineno-start: 1\n'] +
[line.rstrip() for line in f] +
['``````\n'], 0, result)
return result
def _doc_root(): def _doc_root():
root = os.environ.get('PUBLISH_PATH', '') root = os.environ.get('PUBLISH_PATH', '')

View File

@ -1,7 +1,7 @@
# Bare Flame game # Bare Flame game
This tutorial assumes that you already have [Flutter], [git], and This tutorial assumes that you already have [Flutter], [git], and
[Android Studio] on your computer (all of these programs are free); and that [Android Studio] on your computer (all of these programs are free); and that
you have basic familiarity with using the command line. Android Studio is not you have basic familiarity with using the command line. Android Studio is not
a strict requirement, you can use other IDEs too, such as [Visual Studio Code]. a strict requirement, you can use other IDEs too, such as [Visual Studio Code].
@ -22,7 +22,7 @@ $ flutter doctor
``` ```
Your output will be slightly different, but the important thing is to verify Your output will be slightly different, but the important thing is to verify
that no errors are reported, and that your Flutter version is **2.5.0** or that no errors are reported, and that your Flutter version is **2.5.0** or
above. above.
@ -55,7 +55,7 @@ $ flutter create .
You can verify that the project files were created successfully: You can verify that the project files were created successfully:
```console ```console
$ ls $ ls
README.md android/ lib/ pubspec.yaml test/ README.md android/ lib/ pubspec.yaml test/
analysis_options.yaml ios/ pubspec.lock syzygy.iml web/ analysis_options.yaml ios/ pubspec.lock syzygy.iml web/
``` ```
@ -73,13 +73,13 @@ If you see only the `main.dart` file but not the side panel, then click the
vertical `[Project]` button at the left edge of the window. vertical `[Project]` button at the left edge of the window.
Before we proceed, let's fix the view in the left panel. Locate the button Before we proceed, let's fix the view in the left panel. Locate the button
in the top left corner that says `[Android]` in the screenshot. In this in the top left corner that says `[Android]` in the screenshot. In this
dropdown select the first option "Project". Your project window should now dropdown select the first option "Project". Your project window should now
look like this: look like this:
![](../images/tutorials/android-studio-screenshot-2.webp) ![](../images/tutorials/android-studio-screenshot-2.webp)
The important part is that you should be able to see all files in your The important part is that you should be able to see all files in your
project directory. project directory.
@ -110,7 +110,7 @@ After that, press the `[Pub get]` button at the top of the window; or
alternatively you could run command `flutter pub get` from the terminal. This alternatively you could run command `flutter pub get` from the terminal. This
will "apply" the changes in `pubspec` file to your project, in particular it will "apply" the changes in `pubspec` file to your project, in particular it
will download the Flame library which we have declared as a dependency. In the will download the Flame library which we have declared as a dependency. In the
future, you should run `flutter pub get` whenever you make changes to this future, you should run `flutter pub get` whenever you make changes to this
file. file.
Now, open file `lib/main.dart` and replace its content with the following: Now, open file `lib/main.dart` and replace its content with the following:
@ -138,7 +138,7 @@ selected>`. In that dropdown choose `<Chrome (web)>` instead.
After that open the `main.dart` file and press the green arrow next to the After that open the `main.dart` file and press the green arrow next to the
`void main()` function in line 4. Select `[Run main.dart]` from the menu. `void main()` function in line 4. Select `[Run main.dart]` from the menu.
This should open a new Chrome window (which may take 10-30 seconds) and run This should open a new Chrome window (which may take 10-30 seconds) and run
your project in that window. For now it will simply show a black screen, which your project in that window. For now it will simply show a black screen, which
is expected because we created the game in its simplest blank configuration. is expected because we created the game in its simplest blank configuration.
@ -151,7 +151,7 @@ assumes that you already have a GitHub account.
Log into your GitHub account, select `[Your repositories]` from your profile Log into your GitHub account, select `[Your repositories]` from your profile
dropdown, and press the green `[New]` button. In the form enter repository dropdown, and press the green `[New]` button. In the form enter repository
name the same as your project name; select type "private"; and opt out of name the same as your project name; select type "private"; and opt out of
adding initial files like README, license and gitignore. adding initial files like README, license and gitignore.
Now go to your project's directory in the terminal and execute the following Now go to your project's directory in the terminal and execute the following

View File

@ -258,7 +258,7 @@ the card objects, which are the most important visual objects in this game.
```{flutter-app} ```{flutter-app}
:sources: ../tutorials/klondike/app :sources: ../tutorials/klondike/app
:page: step2 :page: step2
:show: popup :show: popup code
``` ```
[World]: ../../flame/camera_component.md#world [World]: ../../flame/camera_component.md#world