# toaster — `n_pbt_toaster` #

← Komponentenreferenz · Inhalt des Handbuchs

> „Toast“-Benachrichtigungen in einer Bildschirmecke: eine Meldung, die erscheint, informiert und wieder verschwindet, ohne den Benutzer zu blockieren oder seine Eingabe zu unterbrechen.

> ▶ Live ansehen — Demoanwendung, Kachel Toaster: die Vorschau, der zugehörige Code und diese Seite, nebeneinander.

## Auf einen Blick #

Objekt | `n_pbt_toaster` — nicht visuell: nichts, was im Fenster platziert werden müsste
Wofür | Eine erfolgreiche Aktion bestätigen, eine Warnung oder einen Fehler melden, ohne die laufende Arbeit anzuhalten
Rückgabe | Nicht blockierend: `of_show()` gibt sofort die Kontrolle zurück; die Reaktionen des Benutzers kommen über Events zurück

Der Toast ist ein losgelöstes Fenster: Er schwebt über Ihrer Anwendung (oder über dem gesamten Bildschirm) und schließt sich von selbst.

    n_pbt_toaster lnv_toast

    lnv_toast = create n_pbt_toaster
    // ... Konfiguration ...
    destroy lnv_toast

## Schnellstart #

    n_pbt_toaster lnv_toast

    lnv_toast = create n_pbt_toaster

    lnv_toast.ipo_owner = this                       // Fenster, an dem sich der Toast festmacht
    lnv_toast.is_kind   = lnv_toast.KIND_SUCCESS     // gruenes Symbol + Erfolgsstreifen
    lnv_toast.is_text   = "Ihre Änderungen wurden [b]gespeichert[/b]."
    lnv_toast.of_show()

    destroy lnv_toast

Alles wird über Eigenschaften konfiguriert, danach lässt `of_show()` — das kein Argument entgegennimmt — die Benachrichtigung erscheinen.

## Eigenschaften #

Vor `of_show` zu setzen.

Eigenschaft | Typ | Standard | Zweck
--- | --- | --- | ---
`is_text` | string | `""` | Rumpf der Meldung. Akzeptiert die Rich-Text-Auszeichnung
`is_kind` | string | `KIND_INFO` | Stufe: steuert das Symbol und die Farbe des Streifens. Konstanten `KIND_*`
`is_position` | string | `POSITION_BOTTOM_RIGHT` | Verankerungsecke. Konstanten `POSITION_*`
`ib_screen` | boolean | `false` | `false` = an der Ecke des Fensters verankert; `true` = an der Ecke des Bildschirms verankert, über allem schwebend
`il_timeout` | long | `TIMEOUT_AUTO` | Anzeigedauer in Millisekunden bis zum automatischen Schließen. `TIMEOUT_AUTO` (`-1`, die Vorgabe) bedeutet 4 s für eine Information, aber bis zum Klick für einen Fehler — ein Fehler, der nach vier Sekunden verschwindet, ist ein verlorener Fehler. `TIMEOUT_UNTIL_CLICKED` (`0`) macht jeden Toast dauerhaft; eine ausdrückliche Dauer wird unverändert übernommen. Solange der Zeiger auf einem Toast ruht, ist sein Countdown angehalten, und ein Balken zeigt die verbleibende Zeit
`is_title` | string | `""` | Fett gesetzte Titelzeile über der Meldung (erweiterter Toast)
`is_image` | string | `""` | Illustrationsbild links, anstelle des Stufensymbols (akzeptierte Formen: Pfad, `mono:`, DLL-Ressource)
`is_key` | string | `""` | Schlüssel des Toasts: Denselben Schlüssel erneut anzuzeigen aktualisiert den bereits sichtbaren Toast, statt einen zweiten zu öffnen. Genau das braucht eine Fortschrittsmeldung („Export 3/10“ dann „4/10“): Schließen und neu öffnen würde die Animation neu starten und den Stapel durcheinanderbringen. Für einen gewöhnlichen Toast leer lassen
`il_max_visible` | long | `5` | Höchstzahl gleichzeitig sichtbarer Toasts in derselben Ecke (1 bis 20). Darüber hinaus warten die nächsten und erscheinen, sobald Platz frei wird: eine Verarbeitungsschleife mit einem Toast je Zeile stapelte die Fenster sonst aus dem Bildschirm hinaus
`ipo_owner` | powerobject | — | Das visuelle Objekt, an dem der Toast festgemacht ist (seine Fensterecke dient als Bezugspunkt)
`ipo_receiver` | powerobject | — | Das visuelle Objekt, das die Events des Toasts empfängt. Lassen Sie es leer für eine Benachrichtigung ohne Rückmeldung

### Konstanten #

Konstante | Wert | Verwendung
--- | --- | ---
`KIND_INFO` | `"info"` | Neutrale Information
`KIND_SUCCESS` | `"success"` | Erfolgreiche Operation
`KIND_WARNING` | `"warning"` | Warnung
`KIND_ERROR` | `"error"` | Fehlschlag
`POSITION_TOP_LEFT` | `"top-left"` | Obere linke Ecke
`POSITION_TOP_CENTER` | `"top-center"` | Oben, zentriert
`POSITION_TOP_RIGHT` | `"top-right"` | Obere rechte Ecke
`POSITION_BOTTOM_LEFT` | `"bottom-left"` | Untere linke Ecke
`POSITION_BOTTOM_CENTER` | `"bottom-center"` | Unten, zentriert
`POSITION_BOTTOM_RIGHT` | `"bottom-right"` | Untere rechte Ecke (Standard)

> Warum hier `LEFT`/`RIGHT` und anderswo `START`/`END`? Der Toast ist ein Systemfenster, das in Bildschirmpixeln platziert wird, kein Inhalt, der einer Leserichtung folgt: Eine Bildschirmecke hat keinen „Anfang“. Diese Konstanten bleiben daher bewusst physisch und wechseln nicht die Seite, wenn die Anwendung auf Schreibrichtung von rechts nach links umschaltet. Siehe Sprache und RTL.

## Methoden #

Methode | Zweck
--- | ---
`of_show ( )` → long | Zeigt die aus den Eigenschaften aufgebaute Benachrichtigung an. Gibt den Bezeichner des Toasts zurück (`> 0`) oder einen negativen Wert im Fehlerfall. Blockiert nicht
`of_close ( long al_id )` → long | Schließt einen noch angezeigten Toast, bestimmt durch den von `of_show` gelieferten Bezeichner. Gibt `0` zurück oder `-5`, wenn die Kennung leer ist oder einen bereits verschwundenen Toast bezeichnet
`of_reset ( )` | Setzt alle Inhaltseigenschaften auf ihren Standard zurück und löscht die Schaltflächen (`ipo_owner` und `ipo_receiver` bleiben erhalten: Sie sind Verdrahtung, kein Inhalt)
`of_process_events ( )` | Leert die Warteschlange der Rückmeldungen des Toasts und löst die entsprechenden `ue_toast_*`-Events aus — siehe unten
`of_add_button (string as_key, string as_label {, string as_image })` → long | Fügt eine Aktionsschaltfläche hinzu (höchstens 3) und liefert deren Anzahl. Ein Klick darauf löst `ue_toast_action(id, key)` aus; `of_reset` leert die Schaltflächen. Eine Beschriftung darf jedes Zeichen enthalten — ein Komma, ein Gleichheitszeichen — ohne zerschnitten zu werden

Mehrere in derselben Ecke angezeigte Toasts stapeln sich automatisch. Jeder trägt ein Schließkreuz; der von `of_show` gelieferte Bezeichner erlaubt es, sie in den Events zu unterscheiden und sie aus Ihrem Code heraus zu schließen.

Der Countdown pausiert, solange der Zeiger über dem Toast steht: eine Meldung darf nicht unter den Augen dessen verschwinden, der sie liest. Ein schmaler Balken am unteren Rand zeigt die verbleibende Zeit — und erklärt damit ihr Verschwinden. Ein Klick auf den Rumpf antwortet und schließt, in beiden Hosting-Modi.

Eine mit `il_timeout = 0` gesetzte Benachrichtigung bleibt auf dem Bildschirm, solange niemand sie schließt: Bewahren Sie ihren Bezeichner auf, um sie entfernen zu können, sobald die angekündigte Aufgabe beendet ist.

    long ll_toast

    // Dauerhafte Benachrichtigung : sie bleibt bis of_close sichtbar.
    inv_toaster.is_text = "Export läuft..."
    inv_toaster.il_timeout = /*ms, 0 = kein automatisches Schliessen*/ 0
    ll_toast = inv_toaster.of_show()

    // ... lange Verarbeitung ...

    inv_toaster.of_close(/*id*/ ll_toast)

## Events — der Toast antwortet Ihnen #

Eine Benachrichtigung ist kein bloßes „anzeigen und vergessen“: Sie kann Ihnen mitteilen, dass sie angeklickt wurde, dass eine Aktionsschaltfläche gewählt wurde oder dass sie sich geschlossen hat.

Da der Toast in einem losgelösten Fenster lebt, erfolgt die Verdrahtung in drei Schritten.

1. Das visuelle Zielobjekt bestimmen:

    inv_toaster.ipo_owner    = this
    inv_toaster.ipo_receiver = this      // dieses Userobject / dieses Fenster erhaelt die Rueckmeldungen

> `ipo_receiver` muss ein visuelles Objekt sein (Fenster oder Userobject). Ein nicht visuelles Objekt kann keine Systembenachrichtigung empfangen.

2. Auf diesem visuellen Objekt ein auf `pbm_custom02` gemapptes Event deklarieren, das die Warteschlange leert:

    // Event ue_toast_notified, auf pbm_custom02 gemappt
    if IsValid(inv_toaster) then inv_toaster.of_process_events()

3. Die auf dem Toaster ausgelösten Events behandeln:

Event | Ausgelöst wenn
--- | ---
`ue_toast_clicked (string as_id)` | Der Rumpf des Toasts wird angeklickt (keine Schaltfläche)
`ue_toast_action (string as_id, string as_action)` | Eine Aktionsschaltfläche wird angeklickt; `as_action` enthält den an `of_add_button` übergebenen Schlüssel
`ue_toast_dismissed (string as_id)` | Der Toast schließt sich: Zeit abgelaufen, Schließkreuz oder nach einer Aktion

Ohne `ipo_receiver` erscheint die Benachrichtigung und verschwindet wieder, ohne jemals etwas zurückzumelden — das ist der einfachste Modus, ideal für eine schlichte Bestätigung.

## Beispiele #

### Die vier Stufen #

    inv_toaster.of_reset()
    inv_toaster.is_kind = inv_toaster.KIND_INFO
    inv_toaster.is_text = "Vorgang abgeschlossen."
    inv_toaster.of_show()

    inv_toaster.of_reset()
    inv_toaster.is_kind = inv_toaster.KIND_SUCCESS
    inv_toaster.is_text = "Ihre Änderungen wurden [b]gespeichert[/b]."
    inv_toaster.of_show()

    inv_toaster.of_reset()
    inv_toaster.is_kind    = inv_toaster.KIND_WARNING
    inv_toaster.il_timeout = 5000                        // etwas laenger
    inv_toaster.is_text    = "Wenig Speicherplatz auf Laufwerk C:."
    inv_toaster.of_show()

    inv_toaster.of_reset()
    inv_toaster.is_kind    = inv_toaster.KIND_ERROR
    inv_toaster.il_timeout = 6000
    inv_toaster.is_text    = "Der Server ist nicht erreichbar."
    inv_toaster.of_show()

### Die Ecke wählen, im Fenster oder auf dem Bildschirm #

    // Verankert an der oberen rechten Ecke des FENSTERS (Standard : folgt der Anwendung)
    inv_toaster.is_position = inv_toaster.POSITION_TOP_RIGHT
    inv_toaster.ib_screen   = false
    inv_toaster.is_text     = "An der Fensterecke verankert."
    inv_toaster.of_show()

    // Losgeloest : an der BILDSCHIRM-Ecke verankert, sichtbar auch wenn das Fenster minimiert ist
    inv_toaster.is_position = inv_toaster.POSITION_TOP_RIGHT
    inv_toaster.ib_screen   = true
    inv_toaster.is_text     = "Nachtverarbeitung abgeschlossen."
    inv_toaster.of_show()

### Erweiterter Toast: Titel, Bild und Dauer #

    inv_toaster.of_reset()

    inv_toaster.is_title    = "Sicherung abgeschlossen"
    inv_toaster.is_text     = "1 240 Dateien kopiert nach [b]\\server\backup[/b]."
    inv_toaster.is_image    = "mono:img\backup.svg"
    inv_toaster.il_timeout  = 8000                    // bleibt 8 Sekunden
    inv_toaster.of_show()

### Benachrichtigung mit Aktionsschaltflächen #

    // open-Event : die Rueckmeldung ein fuer alle Mal verdrahten
    inv_toaster.ipo_owner    = this
    inv_toaster.ipo_receiver = this

    // Zwei Aktionen anbieten ; timeout 0 = der Toast wartet auf die Entscheidung des Benutzers
    inv_toaster.of_reset()

    inv_toaster.is_title   = "Update verfügbar"
    inv_toaster.is_text    = "Version 2.0 ist zur Installation bereit."
    inv_toaster.il_timeout = 0
    inv_toaster.of_add_button(/*key*/ "installer", /*label*/ "Installieren")
    inv_toaster.of_add_button(/*key*/ "plus_tard", /*label*/ "Spaeter")
    inv_toaster.of_show()

    // Event ue_toast_notified des Fensters, auf pbm_custom02 gemappt
    if IsValid(inv_toaster) then inv_toaster.of_process_events()

    // Event ue_toast_action von inv_toaster : (string as_id, string as_action)
    choose case as_action
        case "installer" ; of_lancer_mise_a_jour()
        case "plus_tard" ; of_reporter(1)
    end choose

### Auf den Klick auf die Meldung reagieren #

    // Event ue_toast_clicked von inv_toaster : (string as_id)
    // Der Benutzer hat den Rumpf des Toasts angeklickt : die betreffende Maske oeffnen
    Open(w_journal_import)

### Aus einer langen Verarbeitung heraus benachrichtigen #

    // Ende eines Imports : informieren, ohne die Eingabemaske zu blockieren
    inv_toaster.of_reset()

    if ll_erreurs = 0 then
        inv_toaster.is_kind = inv_toaster.KIND_SUCCESS
        inv_toaster.is_text = "Import abgeschlossen : [b]" + String(ll_lignes) + " Zeilen[/b] übernommen."
    else
        inv_toaster.is_kind    = inv_toaster.KIND_ERROR
        inv_toaster.il_timeout = 0                    // ein Fehler muss gelesen werden
        inv_toaster.is_text    = "Import abgebrochen : " + String(ll_erreurs) + " Fehler."
    end if

    inv_toaster.of_show()

## Best Practices #

- Eine dauerhafte Instanz pro Fenster (eine beim Öffnen erzeugte Instanzvariable) statt einer Erzeugung und Zerstörung bei jeder Meldung: Die `ipo_receiver`-Verdrahtung bleibt bestehen und die Rückmeldungen kommen an.
- Rufen Sie `of_reset()` vor jeder Benachrichtigung auf: Andernfalls bleiben Titel, Bild oder Schaltflächen der vorherigen bestehen.
- Behalten Sie `il_timeout = 0` den Meldungen vor, die eine Entscheidung verlangen (blockierender Fehler, angebotene Aktion): Ein Toast, der nicht von selbst verschwindet, wird auf Dauer lästig.
- Verwenden Sie `ib_screen = true` nur für das, was sichtbar bleiben muss, wenn die Anwendung im Hintergrund ist (Ende einer langen Verarbeitung, Nachtlauf).
- Ein Toast ist eine flüchtige Meldung: Wenn Sie unbedingt eine Antwort brauchen, bevor es weitergeht, verwenden Sie messagebox, das blockiert und die Auswahl zurückgibt.
- Für einen dauerhaften Status statt einer Benachrichtigung bevorzugen Sie statusbar.

← Komponentenreferenz · Inhalt des Handbuchs