toaster — n_pbt_toaster #
← Component reference · Guide contents
"Toast" notifications in a screen corner: a message that appears, informs and disappears without blocking the user or interrupting their typing.
▶ See it live — Demo application, Toaster tile: the preview, the code behind it and this page, side by side.
At a glance #
| Object | n_pbt_toaster — non-visual: nothing to place on the window |
| Used for | Confirming a successful action, reporting a warning or an error, without stopping the work in progress |
| Return | Non-blocking: of_show() returns immediately; user reactions come back through events |
The toast is a detached window: it floats above your application (or above the whole screen) and closes on its own.
// Local variables
n_pbt_toaster lnv_toast
// Create the notifier
lnv_toast = create n_pbt_toaster
// ... configuration ...
// Destroy it when done
destroy lnv_toast
Quick start #
// Local variables
n_pbt_toaster lnv_toast
// Create the notifier
lnv_toast = create n_pbt_toaster
// Configure, then show
lnv_toast.ipo_owner = this // window the toast attaches to
lnv_toast.is_kind = lnv_toast.KIND_SUCCESS // green icon + success stripe
lnv_toast.is_text = "Your changes have been [b]saved[/b]."
lnv_toast.of_show()
// Destroy it when done
destroy lnv_toast
Everything is configured through properties, then of_show() — which takes no argument — makes the notification appear.
Properties #
To be set before of_show.
| Property | Type | Default | Purpose |
|---|---|---|---|
is_text | string | "" | Body of the message. Accepts rich text markup |
is_kind | string | KIND_INFO | Level: drives the icon and the color of the stripe. KIND_* constants |
is_position | string | POSITION_BOTTOM_RIGHT | Anchor corner. POSITION_* constants |
ib_screen | boolean | false | false = anchored to the corner of the window; true = anchored to the corner of the screen, floating above everything. Toasts anchored to the screen stack by monitor: two windows showing one each no longer cover each other |
il_timeout | long | TIMEOUT_AUTO | Display time in milliseconds before the toast closes on its own. TIMEOUT_AUTO (-1, the default) means 4 s for an information but until it is clicked for an error — an error that vanishes after four seconds is an error lost. TIMEOUT_UNTIL_CLICKED (0) makes any toast persistent; an explicit duration is honoured as-is. While the pointer rests on a toast its countdown is suspended, and a bar shows the time left |
is_title | string | "" | Bold title line above the message (rich toast) |
is_image | string | "" | Illustration image on the left, in place of the level icon (accepted forms: path, mono:, DLL resource) |
is_key | string | "" | Key of the toast: showing the same key again updates the toast already on screen instead of opening a second one. That is what a progress notification needs ("Export 3/10" then "4/10"): closing and reopening would restart the animation and shuffle the stack. Leave it empty for an ordinary toast. The key belongs to the toaster: another toaster showing the same key opens its own toast. An update also takes the new corner, screen anchoring and anchor window. The key comes back as as_key in the ue_toast_* events |
is_sound | string | SOUND_AUTO | System sound of the toast, played when it is asked for. SOUND_AUTO (the default): an error or a warning sounds, an information or a success stays quiet; SOUND_ALWAYS: every kind; SOUND_NEVER: silent |
il_max_visible | long | 0 | Maximum number of toasts on screen at the same corner (1 to 20). Past that, the next ones wait and appear as room frees up: a batch loop firing one toast per row used to stack windows straight off the screen. This cap is shared by every toaster of the application: the last value set wins; 0 (the default) leaves it as it is — 5 until someone sets it. A stack is the same corner of the same window — or, for a toast anchored to the screen or without ipo_owner, the same corner of the same monitor, whatever window showed it |
ipo_owner | powerobject | — | The visual object the toast is attached to (its window corner serves as the reference point). It is the only wiring to do: the events of the toast are raised on the toaster itself. While that window is minimized, the toast waits: it is not shown and its countdown does not run until the window comes back |
ipo_receiver | powerobject | — | Optional, legacy: when set, its window gets its pbm_custom02 rung at each toast event (for older code that had mapped it). Leave it empty — the toaster delivers its events on its own, on itself |
Constants #
| Constant | Value | Use |
|---|---|---|
KIND_INFO | "info" | Neutral information |
KIND_SUCCESS | "success" | Successful operation |
KIND_WARNING | "warning" | Warning |
KIND_ERROR | "error" | Failure |
POSITION_TOP_LEFT | "top-left" | Top left corner |
POSITION_TOP_CENTER | "top-center" | Top, centered |
POSITION_TOP_RIGHT | "top-right" | Top right corner |
POSITION_BOTTOM_LEFT | "bottom-left" | Bottom left corner |
POSITION_BOTTOM_CENTER | "bottom-center" | Bottom, centered |
POSITION_BOTTOM_RIGHT | "bottom-right" | Bottom right corner (default) |
SOUND_AUTO | "auto" | Sound for an error or a warning only (default) |
SOUND_ALWAYS | "always" | Sound for every kind |
SOUND_NEVER | "never" | Never a sound |
Why
LEFT/RIGHThere, andSTART/ENDelsewhere? The toast is a system window placed in screen pixels, not content that follows a reading direction: a screen corner has no "beginning". These constants therefore deliberately remain physical, and do not switch sides when the application moves to right-to-left writing. See Language and RTL.
Methods #
| Method | Purpose |
|---|---|
of_show ( ) → long | Displays the notification built from the properties. Returns the identifier of the toast (> 0) — a toast that waits for room (il_max_visible) gets its own at once too — or a negative value on error. Does not block. -5 (and nothing is shown) for a setting out of its range: an is_kind, is_position or is_sound that is none of its constants, il_max_visible outside 0 to 20, il_timeout below TIMEOUT_AUTO |
of_close ( long al_id ) → long | Closes a toast still on screen — or still waiting for room —, designated by the identifier returned by of_show. A toast ON SCREEN closed this way raises ue_toast_dismissed, like its cross; one still waiting was never seen and raises nothing. Returns 0, or -5 if the id is empty or names a toast that has already disappeared |
of_reset ( ) | Resets every content property to its default and clears the buttons (ipo_owner and ipo_receiver are kept: they are wiring, not content) |
of_process_events ( ) | Empties the queue of toast feedback and raises the matching ue_toast_* events. The component calls it itself while a toast is on screen: you normally do not have to — see below |
of_add_button (string as_key, string as_label {, string as_image }) → long | Adds an action button (up to 3). A click on it raises ue_toast_action(id, key, action); of_reset clears the buttons. A label may contain any character — a comma, an equals sign — without being cut. Returns 0, or -5 (nothing added) for an empty key, a key already taken, a key holding / or a vertical bar, or a fourth button |
of_count ( ) → long | Returns how many action buttons the notification holds |
of_keys_at ( long al_index ) → string | The key of the button at rank al_index (1 based), or "" past either end |
of_has ( string as_key ) → boolean | Was a button added under this key? of_add_button refuses (-5) a key already taken: asking first tells why |
Several toasts displayed in the same corner stack automatically. Each one carries a close cross; the identifier returned by of_show lets you tell them apart in the events and close them from your code.
The countdown pauses while the pointer is over the toast: a notification must not vanish under the eyes of whoever is reading it. A thin bar at the bottom of the toast shows the time left — and therefore explains its disappearance. A click on the body answers and closes, in both hosting modes.
A notification set with il_timeout = 0 stays on screen as long as nobody closes it: keep its identifier so you can remove it once the task it announces is finished.
// Local variables
long ll_toast
// Persistent notification : it will stay on screen until of_close.
inv_toaster.is_text = "Export in progress..."
inv_toaster.il_timeout = /*ms, 0 = no auto close*/ 0
ll_toast = inv_toaster.of_show()
// ... long processing ...
// Close the toast once the work is done
inv_toaster.of_close(/*id*/ ll_toast)
Events — the toast talks back #
A notification is not a plain "show and forget": it can tell you that it was clicked, that an action button was chosen, or that it closed.
You have nothing to wire for it: set ipo_owner (the window the toast is anchored to) and handle the events. The component drains them itself while a toast is on screen and raises them on the object — no receiver, no timer.
1. Set ipo_owner to the window the toast is anchored to:
// Anchor the toasts to this window
inv_toaster.ipo_owner = this // the window the toast is anchored to
2. Handle the events raised on the toaster:
| Event | Raised when |
|---|---|
ue_toast_clicked (long al_id, string as_key) | The body of the toast is clicked (not a button). al_id is the identifier of_show returned, as_key the is_key of the toast (empty without one) |
ue_toast_action (long al_id, string as_key, string as_action) | An action button is clicked; as_action holds the key passed to of_add_button. al_id is the identifier of_show returned, as_key the is_key of the toast (empty without one) |
ue_toast_dismissed (long al_id, string as_key) | The toast closes: timeout elapsed, close cross, or of_close while it is on screen (a toast still waiting raises nothing). A click on the body raises ue_toast_clicked, a button ue_toast_action. al_id is the identifier of_show returned, as_key the is_key of the toast (empty without one) |
If you expect nothing back — no action button, no click on the body — you have none of these events to handle: the notification appears and disappears on its own. That is the simplest mode, perfect for a plain confirmation.
Examples #
The four levels #
// Info : a neutral message
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_INFO
inv_toaster.is_text = "Operation complete."
inv_toaster.of_show()
// Success : it went through
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_SUCCESS
inv_toaster.is_text = "Your changes have been [b]saved[/b]."
inv_toaster.of_show()
// Warning : worth a look
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_WARNING
inv_toaster.il_timeout = 5000 // a little longer
inv_toaster.is_text = "Low disk space on drive C:."
inv_toaster.of_show()
// Error : it failed
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_ERROR
inv_toaster.il_timeout = 6000
inv_toaster.is_text = "Unable to reach the server."
inv_toaster.of_show()
Choosing the corner, in the window or on the screen #
// Anchored to the top right corner of the WINDOW (default : follows the application)
inv_toaster.is_position = inv_toaster.POSITION_TOP_RIGHT
inv_toaster.ib_screen = false
inv_toaster.is_text = "Anchored to the window corner."
inv_toaster.of_show()
// Detached : anchored to the SCREEN corner, visible even if the window is minimized
inv_toaster.is_position = inv_toaster.POSITION_TOP_RIGHT
inv_toaster.ib_screen = true
inv_toaster.is_text = "Overnight processing complete."
inv_toaster.of_show()
Rich toast: title, image and duration #
// Start again from the default settings
inv_toaster.of_reset()
// A title, a text and an image
inv_toaster.is_title = "Backup complete"
inv_toaster.is_text = "1,240 files copied to [b]\\server\backup[/b]."
inv_toaster.is_image = "mono:img\backup.svg"
inv_toaster.il_timeout = 8000 // stays 8 seconds
inv_toaster.of_show()
Notification with action buttons #
// open event : anchor the toaster once and for all ; the feedback arrives on its own
inv_toaster.ipo_owner = this
// Offer two actions ; timeout 0 = the toast waits for the user decision
inv_toaster.of_reset()
// Title, text and two buttons, then show
inv_toaster.is_title = "Update available"
inv_toaster.is_text = "Version 2.0 is ready to install."
inv_toaster.il_timeout = 0
inv_toaster.of_add_button(/*key*/ "installer", /*label*/ "Install")
inv_toaster.of_add_button(/*key*/ "later", /*label*/ "Later")
inv_toaster.of_show()
// ue_toast_action event of inv_toaster : (long al_id, string as_key, string as_action)
choose case as_action
case "installer" ; of_start_update()
case "later" ; of_reporter(1)
end choose
Reacting to a click on the message #
// ue_toast_clicked event of inv_toaster : (long al_id, string as_key)
// The user clicked the body of the toast : open the relevant screen
Open(w_journal_import)
Notifying from a long process #
// End of an import : inform without blocking the data entry screen
inv_toaster.of_reset()
// The kind and the text follow the outcome
if ll_errors = 0 then
inv_toaster.is_kind = inv_toaster.KIND_SUCCESS
inv_toaster.is_text = "Import complete : [b]" + String(ll_rows) + " rows[/b] loaded."
else
inv_toaster.is_kind = inv_toaster.KIND_ERROR
inv_toaster.il_timeout = 0 // an error must be read
inv_toaster.is_text = "Import interrupted : " + String(ll_errors) + " errors."
end if
// Show the toast
inv_toaster.of_show()
Best practices #
- One persistent instance per window (an instance variable created on opening) rather than creating and destroying one for each message: the
ipo_owneranchor stays in place and the feedback arrives. A destroyed toaster receives nothing more: its toasts stay on screen, silent. - Call
of_reset()before each notification: without it, the title, the image or the buttons of the previous one stay in place. - Reserve
il_timeout = 0for messages that demand a decision (blocking error, offered action): a toast that never leaves on its own ends up being annoying. - Use
ib_screen = trueonly for what must stay visible when the application is in the background (end of a long process, overnight job). - A toast is a transient message: if you absolutely need an answer before continuing, use messagebox, which blocks and returns the choice.
- For a permanent status rather than a notification, prefer statusbar.