The rendering flow¶
Understanding the rendering flow is important for understanding how
Container
and
UIControl
objects interact. We will demonstrate
it by explaining the flow around a
BufferControl
.
Note
A BufferControl
is a
UIControl
for displaying the content of a
Buffer
. A buffer is the object that holds
any editable region of text. Like all controls, it has to be wrapped into a
Window
.
Let’s take the following code:
from prompt_toolkit.enums import DEFAULT_BUFFER
from prompt_toolkit.layout.containers import Window
from prompt_toolkit.layout.controls import BufferControl
from prompt_toolkit.buffer import Buffer
b = Buffer(name=DEFAULT_BUFFER)
Window(content=BufferControl(buffer=b))
What happens when a Renderer
objects wants a
Container
to be rendered on a certain
Screen
?
The visualisation happens in several steps:
The
Renderer
calls thewrite_to_screen()
method of aContainer
. This is a request to paint the layout in a rectangle of a certain size.The
Window
object then requests theUIControl
to create aUIContent
instance (by callingcreate_content()
). The user control receives the dimensions of the window, but can still decide to create more or less content.Inside the
create_content()
method ofUIControl
, there are several steps:First, the buffer’s text is passed to the
lex_document()
method of aLexer
. This returns a function which for a given line number, returns a “formatted text list” for that line (that’s a list of(style_string, text)
tuples).This list is passed through a list of
Processor
objects. Each processor can do a transformation for each line. (For instance, they can insert or replace some text, highlight the selection or search string, etc…)The
UIControl
returns aUIContent
instance which generates such a token lists for each lines.
The Window
receives the
UIContent
and then:
It calculates the horizontal and vertical scrolling, if applicable (if the content would take more space than what is available).
The content is copied to the correct absolute position
Screen
, as requested by theRenderer
. While doing this, theWindow
can possible wrap the lines, if line wrapping was configured.
Note that this process is lazy: if a certain line is not displayed in the
Window
, then it is not requested
from the UIContent
. And from there, the line is
not passed through the processors or even asked from the
Lexer
.