Interacting with users in Bliss¶
Programming interactions with users can be simplified by using Bliss dialogs
or getval_XXX
functions.
To know more about dialogs API, see: Dialogs
To know more about the menu
command, see: Show
The following document will define the recomended way to integrate dialogs inside Bliss.
Bliss dialogs¶
User Interface to dialogs¶
The users will access dialogs using the menu
function available in the Bliss shell
exported from bliss.shell.standard
.
Programmer interface to dialogs¶
This paragraph is about how to add your own dialogs to bliss or beamline repository
interacting with the menu()
function.
What you have to do is simply define your function that takes as first argument
the object instance itself (on which you will operate) and decorate it with
@dialog("MyClassName", "dialog_type")
.
This will register the dialog as available for this specific object or class of objects.
If you try to register the same Class twice you wil get an exception, but you
can force this with @dialog("MyClassName", "dialog_type", overwrite=True)
.
This is to avoid unexpected behavior when you register twice the same name.
Full Example:
from bliss.shell.dialog.helpers import dialog
from bliss.shell.cli.user_dialog import UserCheckBox
from bliss.shell.cli.pt_widgets import BlissDialog
from bliss.common.utils import grouped_with_tail
@dialog("Transfocator", "selection")
def transfocator_menu(obj, *args, **kwargs):
"""Transfocator Pinhole/Lens selection"""
dialogs = []
positions_list = obj.status_dict()
for label, position in positions_list.items():
type_ = "Pinhole" if label.startswith("P") else "Lens"
num = label[1:]
dialogs.append(UserCheckBox(label=f"{type_} n.{num}", defval=position))
layout = []
for gr in grouped_with_tail(dialogs, 6):
layout.append(gr)
choices = BlissDialog(
layout,
title="Transfocator selection (checked is IN, unchecked is OUT)",
paddings=(3, 0),
).show()
if choices:
for n, position in enumerate(choices.values()):
obj[n] = position
return obj
-
@dialog("Transfocator", "selection")
: import this decorator frombliss.shell.dialog.helpers
and decorate your function with the Class Name and dialog type. -
obj
: this is the first argument received frommenu
. -
*args, **kwargs
: further args received frommenu(obj, dialog_type, *args, **kwargs)
-
return obj
: is not compulsory to return something. In some case is good to return obj because many bliss objects has implemented the__info__
method that will display a status on Bliss shell. In some other cases could be too verbose or simply not necessary. The idea is to return something that will display the result of your dialog operation. If you want to return and print something on the shell is recomended to simply useShellStr
frombliss.common.utils
.
Plenty of examples can be found inside the bliss/shell/dialogs
folder.
Note
Be aware that the dialog code should be imported to work.
For the bliss package this is normally done inside bliss/shell/dialog/__init__.py
.
getval functions¶
getval_yes_no
:getval_name
:getval_int_range
:getval_idx_list
:getval_char_list
:
getval_
functions are a set of functions to prompt user to enter interactively
various types of inputs: int, float, string, yes/no answer to a question etc.
getval_yes_no¶
getval_yes_no(message, default=True)
from bliss.shell.getval import getval_yes_no
if getval_yes_no("Do you want to open shutter ?", default="no"):
print("ok, openning...")
else:
print("abort...")
User is prevented to type other input than yes
or no
or y
or n
.
Executions example:
Do you want to open shutter ? [y/N]: bof
The input have to be on of [y]es or [n]o
On Enter:
Do you want to open shutter ? [y/N]:
abort...
On Ctrl-C:
Do you want to open shutter ? [y/N]:
!!! === KeyboardInterrupt: === !!! ( for more details type cmd 'last_error()' )
Do you want to open shutter ? [y/N]: y
ok, openning...
getval_name¶
getval_name
prompt for a string without special char or spaces.
DEMO [8]: getval.getval_name("Enter a valid name")
Enter a valid name : fdsf
getval_int_range¶
getval_int_range(message, minimum, maximum, default)
:
Prompt user for an int number in interval [min, max]
from bliss.shell.getval import getval_int_range
getval_int_range("Please enter beamline number", minimum=1, maximum=32, default=1)
Please enter beamline number [1]: f
Error: f is not a valid integer
Please enter beamline number [1]: 99
Error: 99 is not in the valid range of 1 to 32.
Please enter beamline number [1]: 5
Out[2]: 5
getval_idx_list¶
getval_idx_list()
: Return the index and string chosen by user in list of N strings.
Selection is done by index in [1..N].
Example:
from bliss.shell.getval import getval_idx_list
dspacing_list = ["111", "311", "642"]
print(getval_idx_list(dspacing_list,"Choose the index of dspacing you want to use"))
Execution of previous example:
1 - 111
2 - 311
3 - 642
Choose the index of dspacing you want to use [1]: 2
311
getval_char_list¶
from bliss.shell.getval import getval_char_list
actions_list= [("a", "add a roi"), ("r", "remove a roi"), ("m", "modify a roi")]
getval_char_list(actions_list, "Action to do")
Execution of previous example:
a - add a roi
r - remove a roi
m - modify a roi
Action to do (a, r, m):a
Out [11]: ('a', 'add a roi')