mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
compositor refactor and transparent screens (#2139)
* compositor refactor and trasparent screens * multuple layers * catch screen stack error * refinement * error messages * capture screen stack * new border type * Background screen * borders and bindings * snapshot * screen docs * fix for missing screens * screens docs * fix for non updating transparent screens * fix background resize * changelog * copy * superfluous function * update diagram * inline code * Update CHANGELOG.md Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com> * Update docs/guide/screens.md Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com> * superfluous file * Explicit None * Apply suggestions from code review Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com> * docstring * update docstring * docstring make property private * Apply suggestions from code review Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com> * docstring * update docstring * Apply suggestions from code review Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com> * docstrings * remove comment, add docstring * Apply suggestions from code review Co-authored-by: Dave Pearson <davep@davep.org> --------- Co-authored-by: Rodrigo Girão Serrão <5621605+rodrigogiraoserrao@users.noreply.github.com> Co-authored-by: Dave Pearson <davep@davep.org>
This commit is contained in:
@@ -4,14 +4,10 @@ This chapter covers Textual's screen API. We will discuss how to create screens
|
||||
|
||||
## What is a screen?
|
||||
|
||||
Screens are containers for widgets that occupy the dimensions of your terminal. There can be many screens in a given app, but only one screen is visible at a time.
|
||||
Screens are containers for widgets that occupy the dimensions of your terminal. There can be many screens in a given app, but only one screen is active at a time.
|
||||
|
||||
Textual requires that there be at least one screen object and will create one implicitly in the App class. If you don't change the screen, any widgets you [mount][textual.widget.Widget.mount] or [compose][textual.widget.Widget.compose] will be added to this default screen.
|
||||
|
||||
!!! tip
|
||||
|
||||
Try printing `widget.parent` to see what object your widget is connected to.
|
||||
|
||||
<div class="excalidraw">
|
||||
--8<-- "docs/images/dom1.excalidraw.svg"
|
||||
</div>
|
||||
@@ -78,7 +74,11 @@ If you have installed a screen, but you later want it to be removed and cleaned
|
||||
|
||||
## Screen stack
|
||||
|
||||
Textual keeps track of a _stack_ of screens. You can think of the screen stack as a stack of paper, where only the very top sheet is visible. If you remove the top sheet the paper underneath becomes visible. Screens work in a similar way.
|
||||
Textual apps keep a _stack_ of screens. You can think of this screen stack as a stack of paper, where only the very top sheet is visible. If you remove the top sheet, the paper underneath becomes visible. Screens work in a similar way.
|
||||
|
||||
!!! note
|
||||
|
||||
You can also make parts of the top screen translucent, so that deeper screens show through. See [Screen opacity](#screen-opacity).
|
||||
|
||||
The active screen (top of the stack) will render the screen and receive input events. The following API methods on the App class can manipulate this stack, and let you decide which screen the user can interact with.
|
||||
|
||||
@@ -127,13 +127,45 @@ Like [pop_screen](#pop-screen), if the screen being replaced is not installed it
|
||||
|
||||
You can also switch screens with the `"app.switch_screen"` action which accepts the name of the screen to switch to.
|
||||
|
||||
|
||||
## Screen opacity
|
||||
|
||||
If a screen has a background color with an *alpha* component, then the background color will be blended with the screen beneath it.
|
||||
For example, if the top-most screen has a background set to `rgba(0,0,255,0.5)` then anywhere in the screen not occupied with a widget will display the *second* screen from the top, tinted with 50% blue.
|
||||
|
||||
|
||||
<div class="excalidraw">
|
||||
--8<-- "docs/images/screens/screen_alpha.excalidraw.svg"
|
||||
</div>
|
||||
|
||||
|
||||
!!! note
|
||||
|
||||
Although parts of other screens may be made visible with background alpha, only the top-most is *active* (can respond to mouse and keyboard).
|
||||
|
||||
One use of background alpha is to style *modal dialogs* (see below).
|
||||
|
||||
|
||||
## Modal screens
|
||||
|
||||
Screens can be used to implement modal dialogs. The following example pushes a screen when you hit the ++q++ key to ask you if you really want to quit.
|
||||
Screens may be used to create modal dialogs, where the main interface is temporarily disabled (but still visible) while the user is entering information.
|
||||
|
||||
The following example pushes a screen when you hit the ++q++ key to ask you if you really want to quit.
|
||||
From the quit screen you can click either Quit to exit the app immediately, or Cancel to dismiss the screen and return to the main screen.
|
||||
|
||||
=== "Output"
|
||||
|
||||
```{.textual path="docs/examples/guide/screens/modal01.py"}
|
||||
```
|
||||
|
||||
=== "Output (after pressing ++q++)"
|
||||
|
||||
```{.textual path="docs/examples/guide/screens/modal01.py" press="q"}
|
||||
```
|
||||
|
||||
=== "modal01.py"
|
||||
|
||||
```python title="modal01.py" hl_lines="18 20 32"
|
||||
```python title="modal01.py"
|
||||
--8<-- "docs/examples/guide/screens/modal01.py"
|
||||
```
|
||||
|
||||
@@ -143,9 +175,47 @@ Screens can be used to implement modal dialogs. The following example pushes a s
|
||||
--8<-- "docs/examples/guide/screens/modal01.css"
|
||||
```
|
||||
|
||||
|
||||
Note the `request_quit` action in the app which pushes a new instance of `QuitScreen`.
|
||||
This makes the quit screen active. If you click Cancel, the quit screen calls [pop_screen][textual.app.App.pop_screen] to return the default screen. This also removes and deletes the `QuitScreen` object.
|
||||
|
||||
There are two flaws with this modal screen, which we can fix in the same way.
|
||||
|
||||
The first flaw is that the app adds a new quit screen every time you press ++q++, even when the quit screen is still visible.
|
||||
Consequently if you press ++q++ three times, you will have to click Cancel three times to get back to the main screen.
|
||||
This is because bindings defined on App are always checked, and we call `push_screen` for every press of ++q++.
|
||||
|
||||
The second flaw is that the modal dialog doesn't *look* modal.
|
||||
There is no indication that the main interface is still there, waiting to become active again.
|
||||
|
||||
We can solve both those issues by replacing our use of [Screen][textual.screen.Screen] with [ModalScreen][textual.screen.ModalScreen].
|
||||
This screen sub-class will prevent key bindings on the app from being processed.
|
||||
It also sets a background with a little alpha to allow the previous screen to show through.
|
||||
|
||||
Let's see what happens when we use `ModalScreen`.
|
||||
|
||||
|
||||
=== "Output"
|
||||
|
||||
```{.textual path="docs/examples/guide/screens/modal01.py" press="q"}
|
||||
```{.textual path="docs/examples/guide/screens/modal02.py"}
|
||||
```
|
||||
|
||||
Note the `request_quit` action in the app which pushes a new instance of `QuitScreen`. This makes the quit screen active. if you click cancel, the quit screen calls `pop_screen` to return the default screen. This also removes and deletes the `QuitScreen` object.
|
||||
=== "Output (after pressing ++q++)"
|
||||
|
||||
```{.textual path="docs/examples/guide/screens/modal02.py" press="q"}
|
||||
```
|
||||
|
||||
=== "modal02.py"
|
||||
|
||||
```python title="modal02.py" hl_lines="3 15"
|
||||
--8<-- "docs/examples/guide/screens/modal02.py"
|
||||
```
|
||||
|
||||
=== "modal01.css"
|
||||
|
||||
```sass title="modal01.css"
|
||||
--8<-- "docs/examples/guide/screens/modal01.css"
|
||||
```
|
||||
|
||||
Now when we press ++q++, the dialog is displayed over the main screen.
|
||||
The main screen is darkened to indicate to the user that it is not active, and only the dialog will respond to input.
|
||||
|
||||
Reference in New Issue
Block a user