summaryrefslogtreecommitdiffstats
path: root/docs/source/layout.rst
blob: 9c998295eb79ac7041267da03bf1be1d7e4f06c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
Layout
======

Rich offers a :class:`~rich.layout.Layout` class which can be used to divide the screen area in to parts, where each part may contain independent content. It can be used with :ref:`Live` to create full-screen "applications" but may be used standalone.

To see an example of a Layout, run the following from the command line::

    python -m rich.layout

Creating layouts
----------------

To define a layout, construct a Layout object and print it::

    from rich import print
    from rich.layout import Layout

    layout = Layout()
    print(layout)

This will draw a box the size of the terminal with some information regarding the layout. The box is a "placeholder" because we have yet to add any content to it. Before we do that, let's create a more interesting layout by calling the :meth:`~rich.layout.Layout.split` method to divide the layout in to two sub-layouts::

    layout.split(
        Layout(name="upper"),
        Layout(name="lower")
    )    
    print(layout)

This will divide the terminal screen in to two equal sized portions, one on top of the other. The ``name`` attribute is an internal identifier we can use to look up the sub-layout later. Let's use that to create another split::

    layout["lower"].split(
        Layout(name="left"),
        Layout(name="right"),
        direction="horizontal"
    )    
    print(layout)

The addition of the ``direction="horizontal"`` tells the Layout class to split left-to-right, rather than the default of top-to-bottom.

You should now see the screen area divided in to 3 portions; an upper half and a lower half that is split in to two quarters.

.. raw:: html
    
    <pre style="font-size:90%;font-family:Menlo,'DejaVu Sans Mono',consolas,'Courier New',monospace"><span style="color: #000080">╭─────────────────────────────── </span><span style="color: #008000">'upper'</span><span style="color: #000080"> </span><span style="color: #000080; font-weight: bold">(</span><span style="color: #000080; font-weight: bold">84</span><span style="color: #000080"> x </span><span style="color: #000080; font-weight: bold">13</span><span style="color: #000080; font-weight: bold">)</span><span style="color: #000080"> ────────────────────────────────╮</span>
    <span style="color: #000080">│</span>                                                                                  <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                                                                  <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                                                                  <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                                                                  <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                                                                  <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>          <span style="font-weight: bold">{</span><span style="color: #008000">'size'</span>: <span style="color: #800080; font-style: italic">None</span>, <span style="color: #008000">'minimum_size'</span>: <span style="color: #000080; font-weight: bold">1</span>, <span style="color: #008000">'ratio'</span>: <span style="color: #000080; font-weight: bold">1</span>, <span style="color: #008000">'name'</span>: <span style="color: #008000">'upper'</span><span style="font-weight: bold">}</span>          <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                                                                  <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                                                                  <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                                                                  <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                                                                  <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                                                                  <span style="color: #000080">│</span>
    <span style="color: #000080">╰──────────────────────────────────────────────────────────────────────────────────╯</span>
    <span style="color: #000080">╭─────────── </span><span style="color: #008000">'left'</span><span style="color: #000080"> </span><span style="color: #000080; font-weight: bold">(</span><span style="color: #000080; font-weight: bold">42</span><span style="color: #000080"> x </span><span style="color: #000080; font-weight: bold">14</span><span style="color: #000080; font-weight: bold">)</span><span style="color: #000080"> ───────────╮╭────────── </span><span style="color: #008000">'right'</span><span style="color: #000080"> </span><span style="color: #000080; font-weight: bold">(</span><span style="color: #000080; font-weight: bold">42</span><span style="color: #000080"> x </span><span style="color: #000080; font-weight: bold">14</span><span style="color: #000080; font-weight: bold">)</span><span style="color: #000080"> ───────────╮</span>
    <span style="color: #000080">│</span>                                        <span style="color: #000080">││</span>                                        <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                        <span style="color: #000080">││</span>                                        <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                        <span style="color: #000080">││</span>                                        <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>         <span style="font-weight: bold">{</span>                              <span style="color: #000080">││</span>         <span style="font-weight: bold">{</span>                              <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>             <span style="color: #008000">'size'</span>: <span style="color: #800080; font-style: italic">None</span>,              <span style="color: #000080">││</span>             <span style="color: #008000">'size'</span>: <span style="color: #800080; font-style: italic">None</span>,              <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>             <span style="color: #008000">'minimum_size'</span>: <span style="color: #000080; font-weight: bold">1</span>,         <span style="color: #000080">││</span>             <span style="color: #008000">'minimum_size'</span>: <span style="color: #000080; font-weight: bold">1</span>,         <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>             <span style="color: #008000">'ratio'</span>: <span style="color: #000080; font-weight: bold">1</span>,                <span style="color: #000080">││</span>             <span style="color: #008000">'ratio'</span>: <span style="color: #000080; font-weight: bold">1</span>,                <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>             <span style="color: #008000">'name'</span>: <span style="color: #008000">'left'</span>             <span style="color: #000080">││</span>             <span style="color: #008000">'name'</span>: <span style="color: #008000">'right'</span>            <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>         <span style="font-weight: bold">}</span>                              <span style="color: #000080">││</span>         <span style="font-weight: bold">}</span>                              <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                        <span style="color: #000080">││</span>                                        <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                        <span style="color: #000080">││</span>                                        <span style="color: #000080">│</span>
    <span style="color: #000080">│</span>                                        <span style="color: #000080">││</span>                                        <span style="color: #000080">│</span>
    <span style="color: #000080">╰────────────────────────────────────────╯╰────────────────────────────────────────╯</span>
    </pre>

You can continue to call split() in this way to create as many parts to the screen as you wish.

Setting renderables
-------------------

The first position argument to ``Layout`` can be any Rich renderable, which will be sized to fit within the layout's area. Here's how we might divide the "right" layout in to two panels::

    layout["right"].split(
        Layout(Panel("Hello")),
        Layout(Panel("World!))
    )

You can also call :meth:`~rich.layout.Layout.update` to set or replace the current renderable::

    layout["left"].update(
        "The mystery of life isn't a problem to solve, but a reality to experience."
    )
    print(layout)

Fixed size
----------

You can set a layout to use a fixed size by setting the ``size`` argument on the Layout constructor or by setting the attribute. Here's an example::

    layout["upper"].size = 10
    print(layout)

This will set the upper portion to be exactly 10 rows, no matter the size of the terminal. If the parent layout is horizontal rather than vertical, then the size applies to the number of characters rather that rows.

Ratio
-----

In addition to a fixed size, you can also make a flexible layout setting the ``ratio`` argument on the constructor or by assigning to the attribute. The ratio defines how much of the screen the layout should occupy in relation to other layouts. For example, lets reset the size and set the ratio of the upper layout to 2::

    layout["upper"].size = None
    layout["upper"].ratio = 2
    print(layout)

This makes the top layout take up two thirds of the space. This is because the default ratio is 1, giving the upper and lower layouts a combined total of 3. As the upper layout has a ratio of 2, it takes up two thirds of the space, leaving the remaining third for the lower layout.

A layout with a ratio set may also have a minimum size to prevent it from getting too small. For instance, here's how we could set the minimum size of the lower sub-layout so that it won't shrink beyond 10 rows::

    layout["lower"].minimum_size = 10

Visibility
----------

You can make a layout invisible by setting the ``visible`` attribute to False. Here's an example::

    layout["upper"].visible = False
    print(layout)

The top layout is now invisible, and the "lower" layout will expand to fill the available space. Set ``visible`` to True to bring it back::

    layout["upper"].visible = True
    print(layout)

You could use this to toggle parts of your interface based on your applications configuration.

Tree
----

To help visualize complex layouts you can print the ``tree`` attribute which will display a summary of the layout as a tree::

    print(layout.tree)


Example
-------

See `fullscreen.py <https://github.com/willmcgugan/rich/blob/master/examples/fullscreen.py>`_ for an example that combines :class:`~rich.layout.Layout` and :class:`~rich.live.Live` to create a fullscreen "application".