UIScreen¶
The base class for creating a new screen. UIScreen
is used for any user interaction.
UIScreen
uses containers and widgets
to present information to a user, and the UIScreen.input()
method to get input from a user
to an application. Screens are pushed to the screen stack, which are then used to
communicate with a user. See the screen handling section to find
out more.
The methods UIScreen.redraw()
, UIScreen.close()
, UIScreen.emit()
and
UIScreen.create_and_emit()
are asynchronous. These methods will create a signal which
is passed to the event loop for later processing.
Beware, methods UIScreen.redraw()
and UIScreen.close()
can lead to unexpected
behavior when multiple instances of these signals are emitted (methods are called multiple times).
This can even crash your application.
Lifecycle¶
Every UIScreen
has a distinct lifecycle: uninitialized, initialized, draw,
process input and closed. If the screen has already been initialized
(it was drawn to a monitor) and will be shown again, then the screen skips
the uninitialized stage. The screen can cycle between draw and process input stages by
calling the UIScreen.redraw()
method after processing user input.
In case UIScreen.redraw()
won’t be called and no new screen is pushed, or this screen
wasn’t closed, then an application will stay in an infinite loop waiting for something to happen.
This is correct behavior because there could be something in an event loop which will
call UIScreen.redraw()
later.
Rendering widgets¶
The UIScreen.refresh()
method is the most important part of the UIScreen
.
It contains preparations for rendering (creating widgets and adding them to containers).
The UIScreen.refresh()
method will be called before anything is drawn on a monitor.
The UIScreen.window
attribute, which is the
WindowContainer
instance, contains
all items (widgets, containers) which are to be rendered by the screen.
A new WindowContainer
is created in the
UIScreen.refresh()
method for every screen redraw. The UIScreen.title
attribute is
passed to the WindowContainer.title
property, and a developer can add widgets and other
containers to present items to a user by calling
WindowContainer.add()
or
WindowContainer.add_with_separator()
.
Multiple items can be added by calling these methods repeatedly.
When everything is prepared properly in the UIScreen.refresh()
method, it needs to be drawn
on the monitor for a user. This is handled by the UIScreen.show_all()
method. This method
works automatically, but it could also be useful for a developer, especially when the screen will
not process input. In this case, the UIScreen.input()
method is not called at all.
Developers can override this method and call the parent class’s UIScreen.show_all()
,
which will handle drawing the screen and any additional processing.
Redrawing the screen can be invoked by the UIScreen.redraw()
method. However, this is
not processed immediately. Instead it will be added to the event loop and processed later, when the
loop is idle. Beware, after every redraw
call the input is processed
if not disabled, so if multiple redraw signals are emitted, than the application will
crash.
The UIScreen.redraw()
method is also invoked when a screen is
pushed to the stack.
User input processing¶
If the screen shouldn’t process user input, the UIScreen.input_required
property needs
to be set to False. True is the default value for this property.
After everything is printed to a monitor, the UIScreen
will wait for user input.
For this purpose there is UIScreen.input()
, which is called when a user passes string input
to a screen. The screen needs to react upon user input and return one of the options from the
InputState
enum or the user input string.
To accept the user input, InputState.PROCESSED
, InputState.PROCESSED_AND_REDRAW
or
InputState.PROCESSED_AND_CLOSE
should be returned. Addition to accepting user input the
InputState.PROCESSED_AND_REDRAW
value will also redraw active screen and
InputState.PROCESSED_AND_CLOSE
will close active screen. However, if
InputState.PROCESSED
is used then the developer is responsible for not ending in frozen
application. The UIScreen.refresh()
or the UIScreen.close()
methods must be called
manually.
In case the user input is invalid, the InputState.DISCARDED
value should be returned.
This will reject the user input and wait for another attempt. The UIScreen.refresh
method will be called after 5 rejections and show the screen output again.
If the user input string is returned it will be checked for
options of the Prompt
instance which can either
close the screen, refresh the screen (this will call UIScreen.refresh()
)
or quit the application.
Closing screens¶
There are several ways to close a screen. One is by calling UIScreen.close()
or
by pressing c to continue (with the default
Prompt
class). When the screen is closed
the next screen on the stack will be shown. A screen can also be
replaced. Then the original screen is removed from the stack
without closing a screen. If a reaction on closing a screen is required then the
UIScreen.closed()
callback should be overridden.
Beware, when calling UIScreen.close()
multiple times it will close multiple screens.
This is because the close signal will always close the top screen on the screen stack.
UIScreen class¶
-
class
simpleline.render.screen.
UIScreen
(title=None, screen_height=30)¶ Base class representing one TUI Screen.
Shares some API with anaconda’s GUI to make it easy for devs to create similar UI with the familiar API.
-
close
()¶ Emit signal to close this screen.
Add CloseScreenSignal to the event loop.
-
closed
()¶ Callback when this screen is closed.
-
connect
(signal, callback, data=None)¶ Connect this class method with given signal.
Parameters: - signal (class based on simpleline.event_loop.AbstractSignal) – signal class which you want to connect
- callback (func(event_message, data)) – the callback function
- data (Anything) – Data you want to pass to the callback
-
create_and_emit
(signal)¶ Create the signal and emit it.
This is basically shortcut for calling self.create_signal and self.emit.
-
create_signal
(signal_class, priority=0)¶ Create signal instance usable in the emit method.
Parameters: - signal_class (class based on simpleline.event_loop.AbstractSignal) – signal you want to use
- priority (int) – priority of the signal; please look on the simpleline.event_loop.AbstractSignal.priority for further info
-
emit
(signal)¶ Emit the signal.
This will add signal to the event loop.
Parameters: signal (instance of class based on simpleline.event_loop.AbstractSignal) – signal to emit
-
get_input_with_error_check
(args)¶ Get user input and redraw if user add too many invalid inputs.
This method should be used only by ScreenScheduler.
Parameters: args (Anything.) – Arguments passed in when scheduling this screen.
-
get_user_input
(message, hidden=False)¶ Get immediately input from the user.
Use this with cautious. Never call this in middle of rendering or when other input is already waiting. It is recommended to use self.input_required instead.
Parameters:
-
hide_user_input
¶ Hide typed user input.
This is main solution how to ask for password.
Returns: True if user input should be hidden. False otherwise (default).
-
input
(args, key)¶ Method called to process input. If the input is not handled here, return it.
Parameters: - key (str) – input string to process
- args (anything) – optional argument passed from switch_screen calls
Returns: return simpleline.render.InputState.PROCESSED if key was handled, simpleline.render.InputState.DISCARDED if the screen should not process input on the scheduler and key if you want it to.
Return type: simpleline.render.InputState enum | str
-
input_required
¶ Return if the screen requires input.
-
no_separator
¶ Should we print separator for this screen?
Returns: True to print separator before this screen (default). False do not print separator.
-
password_func
¶ Get password function.
This is function with one argument to get password from command line.
-
prompt
(args=None)¶ Return the text to be shown as prompt or handle the prompt and return None.
Parameters: args (anything) – optional argument passed from switch_screen calls Returns: returns an instance of Prompt with text to be shown next to the prompt for input or None to skip further input processing Return type: Prompt instance|None
-
redraw
()¶ Emit signal to initiate draw.
Add RenderScreenSignal to the event loop.
-
refresh
(args=None)¶ Method which prepares the content desired on the screen to self.window.
Parameters: args (anything) – optional argument passed from switch_screen calls
-
screen_ready
¶ This screen is ready for use.
-
setup
(args)¶ Do additional setup right before this screen is used.
It is mandatory to call this ancestor method in the child class to set ready status.
Parameters: args (array of values) – arguments for the setup Returns: whether this screen should be scheduled or not Return type: bool
-
show_all
()¶ Print WindowContainer in self.window with all its content.
-
title
¶ Screen title.
-
window
¶ Return WindowContainer instance.
-