Skip to content

Commit a883d0f

Browse files
gpotter2jonathanslenders
authored andcommitted
CheckboxList & more Dialogs documentation
Squashed the following commits: * Implement CheckboxList out of Checkbox * Add styling reference sheet * Document radiolist_dialog & checkboxlist_dialog * Add standalone styled-checkboxlist example * Add example on how to use the style sheet * Fix typo: frame-label instead of frame.label, resulting in the style not beeing applied * Prompt toolkit 3.0: update pages/dialogs.rst * Apply suggestions
1 parent 72c8327 commit a883d0f

File tree

6 files changed

+317
-65
lines changed

6 files changed

+317
-65
lines changed

docs/pages/dialogs.rst

Lines changed: 159 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ simple message box. For instance:
1919
2020
message_dialog(
2121
title='Example dialog window',
22-
text='Do you want to continue?\nPress ENTER to quit.')
22+
text='Do you want to continue?\nPress ENTER to quit.').run()
2323
2424
.. image:: ../images/dialogs/messagebox.png
2525

@@ -36,7 +36,7 @@ input box. It will return the user input as a string.
3636
3737
text = input_dialog(
3838
title='Input dialog example',
39-
text='Please type your name:')
39+
text='Please type your name:').run()
4040
4141
.. image:: ../images/dialogs/inputbox.png
4242

@@ -58,13 +58,13 @@ confirmation dialog. It will return a boolean according to the selection.
5858
5959
result = yes_no_dialog(
6060
title='Yes/No dialog example',
61-
text='Do you want to confirm?')
61+
text='Do you want to confirm?').run()
6262
6363
.. image:: ../images/dialogs/confirm.png
6464

6565

6666
Button dialog
67-
--------------------------
67+
-------------
6868

6969
The :func:`~prompt_toolkit.shortcuts.button_dialog` function displays a dialog
7070
with choices offered as buttons. Buttons are indicated as a list of tuples,
@@ -82,11 +82,54 @@ each providing the label (first) and return value if clicked (second).
8282
('No', False),
8383
('Maybe...', None)
8484
],
85-
)
85+
).run()
8686
8787
.. image:: ../images/dialogs/button.png
8888

8989

90+
Radio list dialog
91+
-----------------
92+
93+
The :func:`~prompt_toolkit.shortcuts.radiolist_dialog` functiom displays a dialog
94+
with choices offered as a radio list. The values are provided as a list of tuples,
95+
each providing the return value (first element) and the displayed value (second element).
96+
97+
.. code:: python
98+
99+
from prompt_toolkit.shortcuts import radiolist_dialog
100+
101+
result = radiolist_dialog(
102+
title="RadioList dialog",
103+
text="Which breakfast would you like ?",
104+
values=[
105+
("breakfast1", "Eggs and beacon"),
106+
("breakfast2", "French breakfast"),
107+
("breakfast3", "Equestrian breakfast")
108+
]
109+
).run()
110+
111+
112+
Checkbox list dialog
113+
--------------------
114+
115+
The :func:`~prompt_toolkit.shortcuts.checkboxlist_dialog` has the same usage and purpose than the Radiolist dialog, but allows several values to be selected and therefore returned.
116+
117+
.. code:: python
118+
119+
from prompt_toolkit.shortcuts import checkboxlist_dialog
120+
121+
results_array = checkboxlist_dialog(
122+
title="CheckboxList dialog",
123+
text="What would you like in your breakfast ?",
124+
values=[
125+
("eggs", "Eggs"),
126+
("bacon", "Bacon"),
127+
("croissants", "20 Croissants"),
128+
("daily", "The breakfast of the day")
129+
]
130+
).run()
131+
132+
90133
Styling of dialogs
91134
------------------
92135

@@ -103,7 +146,7 @@ dialogs to override the default style. Also, text can be styled by passing an
103146
104147
example_style = Style.from_dict({
105148
'dialog': 'bg:#88ff88',
106-
'dialog frame-label': 'bg:#ffffff #000000',
149+
'dialog frame.label': 'bg:#ffffff #000000',
107150
'dialog.body': 'bg:#000000 #00ff00',
108151
'dialog shadow': 'bg:#00aa00',
109152
})
@@ -112,7 +155,116 @@ dialogs to override the default style. Also, text can be styled by passing an
112155
title=HTML('<style bg="blue" fg="white">Styled</style> '
113156
'<style fg="ansired">dialog</style> window'),
114157
text='Do you want to continue?\nPress ENTER to quit.',
115-
style=example_style)
158+
style=example_style).run()
116159
117160
.. image:: ../images/dialogs/styled.png
118161

162+
Styling reference sheet
163+
-----------------------
164+
165+
In reality, the shortcut commands presented above build a full-screen frame by using a list of components. The two tables below allow you to get the classnames available for each shortcut, therefore you will be able to provide a custom style for every element that is displayed, using the method provided above.
166+
167+
.. note:: All the shortcuts use the ``Dialog`` component, therefore it isn't specified explicitely below.
168+
169+
+--------------------------+-------------------------+
170+
| Shortcut | Components used |
171+
+==========================+=========================+
172+
| ``yes_no_dialog`` | - ``Label`` |
173+
| | - ``Button`` (x2) |
174+
+--------------------------+-------------------------+
175+
| ``button_dialog`` | - ``Label`` |
176+
| | - ``Button`` |
177+
+--------------------------+-------------------------+
178+
| ``input_dialog`` | - ``TextArea`` |
179+
| | - ``Button`` (x2) |
180+
+--------------------------+-------------------------+
181+
| ``message_dialog`` | - ``Label`` |
182+
| | - ``Button`` |
183+
+--------------------------+-------------------------+
184+
| ``radiolist_dialog`` | - ``Label`` |
185+
| | - ``RadioList`` |
186+
| | - ``Button`` (x2) |
187+
+--------------------------+-------------------------+
188+
| ``checkboxlist_dialog`` | - ``Label`` |
189+
| | - ``CheckboxList`` |
190+
| | - ``Button`` (x2) |
191+
+--------------------------+-------------------------+
192+
| ``progress_dialog`` | - ``Label`` |
193+
| | - ``TextArea`` (locked) |
194+
| | - ``ProgressBar`` |
195+
+--------------------------+-------------------------+
196+
197+
+----------------+-----------------------------+
198+
| Components | Available classnames |
199+
+================+=============================+
200+
| Dialog | - ``dialog`` |
201+
| | - ``dialog.body`` |
202+
+----------------+-----------------------------+
203+
| TextArea | - ``text-area`` |
204+
| | - ``text-area.prompt`` |
205+
+----------------+-----------------------------+
206+
| Label | - ``label`` |
207+
+----------------+-----------------------------+
208+
| Button | - ``button`` |
209+
| | - ``button.focused`` |
210+
| | - ``button.arrow`` |
211+
| | - ``button.text`` |
212+
+----------------+-----------------------------+
213+
| Frame | - ``frame`` |
214+
| | - ``frame.border`` |
215+
| | - ``frame.label`` |
216+
+----------------+-----------------------------+
217+
| Shadow | - ``shadow`` |
218+
+----------------+-----------------------------+
219+
| RadioList | - ``radio-list`` |
220+
| | - ``radio`` |
221+
| | - ``radio-checked`` |
222+
| | - ``radio-selected`` |
223+
+----------------+-----------------------------+
224+
| CheckboxList | - ``checkbox-list`` |
225+
| | - ``checkbox`` |
226+
| | - ``checkbox-checked`` |
227+
| | - ``checkbox-selected`` |
228+
+----------------+-----------------------------+
229+
| VerticalLine | - ``line`` |
230+
| | - ``vertical-line`` |
231+
+----------------+-----------------------------+
232+
| HorizontalLine | - ``line`` |
233+
| | - ``horizontal-line`` |
234+
+----------------+-----------------------------+
235+
| ProgressBar | - ``progress-bar`` |
236+
| | - ``progress-bar.used`` |
237+
+----------------+-----------------------------+
238+
239+
Example
240+
_______
241+
242+
Let's customize the example of the ``checkboxlist_dialog``.
243+
244+
It uses 2 ``Button``, a ``CheckboxList`` and a ``Label``, packed inside a ``Dialog``.
245+
Threfore we can customize each of these elements separately, using for instance:
246+
247+
.. code:: python
248+
249+
from prompt_toolkit.shortcuts import checkboxlist_dialog
250+
from prompt_toolkit.styles import Style
251+
252+
results = checkboxlist_dialog(
253+
title="CheckboxList dialog",
254+
text="What would you like in your breakfast ?",
255+
values=[
256+
("eggs", "Eggs"),
257+
("bacon", "Bacon"),
258+
("croissants", "20 Croissants"),
259+
("daily", "The breakfast of the day")
260+
],
261+
style=Style.from_dict({
262+
'dialog': 'bg:#cdbbb3',
263+
'button': 'bg:#bf99a4',
264+
'checkbox': '#e8612c',
265+
'dialog.body': 'bg:#a9cfd0',
266+
'dialog shadow': 'bg:#c98982',
267+
'frame.label': '#fcaca3',
268+
'dialog.body label': '#fd8bb6',
269+
})
270+
).run()

examples/dialogs/checkbox_dialog.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env python
2+
"""
3+
Example of a checkbox-list-based dialog.
4+
"""
5+
from __future__ import unicode_literals
6+
7+
from prompt_toolkit.shortcuts import checkboxlist_dialog, message_dialog
8+
from prompt_toolkit.styles import Style
9+
10+
results = checkboxlist_dialog(
11+
title="CheckboxList dialog",
12+
text="What would you like in your breakfast ?",
13+
values=[
14+
("eggs", "Eggs"),
15+
("bacon", "Bacon"),
16+
("croissants", "20 Croissants"),
17+
("daily", "The breakfast of the day")
18+
],
19+
style=Style.from_dict({
20+
'dialog': 'bg:#cdbbb3',
21+
'button': 'bg:#bf99a4',
22+
'checkbox': '#e8612c',
23+
'dialog.body': 'bg:#a9cfd0',
24+
'dialog shadow': 'bg:#c98982',
25+
'frame.label': '#fcaca3',
26+
'dialog.body label': '#fd8bb6',
27+
})
28+
).run()
29+
if results:
30+
message_dialog(
31+
title="Room service",
32+
text="You selected: %s\nGreat choice sir !" % ",".join(results)
33+
).run()
34+
else:
35+
message_dialog("*starves*").run()

prompt_toolkit/shortcuts/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from .dialogs import (
22
button_dialog,
3+
checkboxlist_dialog,
34
input_dialog,
45
message_dialog,
56
progress_dialog,
@@ -27,6 +28,7 @@
2728
'input_dialog',
2829
'message_dialog',
2930
'progress_dialog',
31+
'checkboxlist_dialog',
3032
'radiolist_dialog',
3133
'yes_no_dialog',
3234
'button_dialog',

prompt_toolkit/shortcuts/dialogs.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from prompt_toolkit.widgets import (
2626
Box,
2727
Button,
28+
CheckboxList,
2829
Dialog,
2930
Label,
3031
ProgressBar,
@@ -38,6 +39,7 @@
3839
'input_dialog',
3940
'message_dialog',
4041
'radiolist_dialog',
42+
'checkboxlist_dialog',
4143
'progress_dialog',
4244
]
4345

@@ -189,6 +191,42 @@ def ok_handler() -> None:
189191
return _create_app(dialog, style)
190192

191193

194+
def checkboxlist_dialog(
195+
title: AnyFormattedText = '',
196+
text: AnyFormattedText = '',
197+
ok_text: str = 'Ok',
198+
cancel_text: str = 'Cancel',
199+
values: Optional[List[Tuple[_T, AnyFormattedText]]] = None,
200+
style: Optional[BaseStyle] = None) -> Application[_T]:
201+
"""
202+
Display a simple list of element the user can choose multiple values amongst.
203+
204+
Several elements can be selected at a time using Arrow keys and Enter.
205+
The focus can be moved between the list and the Ok/Cancel button with tab.
206+
"""
207+
if values is None:
208+
values = []
209+
210+
def ok_handler() -> None:
211+
get_app().exit(result=cb_list.current_values)
212+
213+
cb_list = CheckboxList(values)
214+
215+
dialog = Dialog(
216+
title=title,
217+
body=HSplit([
218+
Label(text=text, dont_extend_height=True),
219+
cb_list,
220+
], padding=1),
221+
buttons=[
222+
Button(text=ok_text, handler=ok_handler),
223+
Button(text=cancel_text, handler=_return_none),
224+
],
225+
with_background=True)
226+
227+
return _create_app(dialog, style)
228+
229+
192230
def progress_dialog(
193231
title: AnyFormattedText = '',
194232
text: AnyFormattedText = '',

prompt_toolkit/widgets/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
Box,
1111
Button,
1212
Checkbox,
13+
CheckboxList,
1314
Frame,
1415
HorizontalLine,
1516
Label,
@@ -40,6 +41,7 @@
4041
'Box',
4142
'VerticalLine',
4243
'HorizontalLine',
44+
'CheckboxList',
4345
'RadioList',
4446
'Checkbox',
4547
'ProgressBar',

0 commit comments

Comments
 (0)