# listbar — `u_pbt_listbar` #

← Riferimento dei componenti · Sommario della guida

> Barra di navigazione laterale: sezioni comprimibili a fisarmonica che contengono voci con icona, con banda d'accento sulla voce corrente e compressione in una barra di sole icone.

> ▶ Vederlo dal vivo — Applicazione dimostrativa, riquadro Listbar: l'anteprima, il codice che lo produce e questa pagina, affiancati.

## In breve #

Userobject | `u_pbt_listbar`
Classi degli item | `n_pbt_listbar_section` (sezione) → `n_pbt_listbar_item` (voce)
Serve per | Sostituire un menu laterale improvvisato a colpi di pulsanti con una navigazione strutturata, a tema e comprimibile
Opzioni opt-in | `ib_auto_width`, `ib_reorderable`

È l'unico componente della libreria a pubblicare `ib_auto_width`: la sua larghezza naturale ha un senso, poiché la barra compressa è nettamente più stretta di quella espansa. Del resto il caso più comune è già coperto senza attivare nulla: `ib_collapsed = true` restringe la barra alla sola striscia di icone, e le restituisce la larghezza quando viene espansa.

## Avvio rapido #

    // event open della finestra
    n_pbt_listbar_section lnv_section

    lnv_section = uo_nav.of_add_header(/*id*/ "nav", /*titolo*/ "Navigazione")
    lnv_section.of_add_item(/*id*/ "accueil",   /*etichetta*/ "Home",   /*icona*/ "mono:img\home.svg")
    lnv_section.of_add_item(/*id*/ "documents", /*etichetta*/ "Documenti", /*icona*/ "mono:img\doc.svg")
    lnv_section.of_add_item(/*id*/ "recherche", /*etichetta*/ "Ricerca", /*icona*/ "mono:img\find.svg")

    uo_nav.of_add_header(/*id*/ "config", /*titolo*/ "Impostazioni") &
          .of_add_item(/*id*/ "preferences", /*etichetta*/ "Preferenze", /*icona*/ "mono:img\gear.svg")

    // La selezione si imposta sulla VOCE, tramite il suo percorso completo
    uo_nav.of_select_item("nav", "accueil")

    // event ue_selection_changed di uo_nav : (string as_from_section, string as_from_id,
    //                                         string as_section, string as_id)
    choose case as_section + "/" + as_id
        case "nav/accueil"       ; of_ouvrir_accueil()
        case "nav/documents"     ; of_ouvrir_documents()
        case "config/preferences"; of_ouvrir_preferences()
    end choose

## Due livelli, un percorso obbligatorio #

Un identificatore di voce è univoco solo all'interno della sua sezione: non esiste quindi alcuna scorciatoia verso la voce. Ogni accesso passa dalla sezione, il che rende la scrittura non ambigua — vedere Gerarchie.

    // Componente  ->  sezione        ->  voce        ->  proprieta
    uo_nav        .of_section("nav") .of_item("docs") .is_text = "Documents"

Anche gli event portano il percorso completo, e con esso la voce lasciata: `ue_selection_changed(as_from_section, as_from_id, as_section, as_id)`.

## Proprietà #

Proprietà | Tipo | Predefinito | Ruolo
--- | --- | --- | ---
`ib_collapsed` | boolean | `false` | `true` comprime la barra in una barra di sole icone: le etichette scompaiono, le icone restano cliccabili
`ib_auto_width` | boolean | `false` | Opt-in: idem per la larghezza, anche da espansa (la barra si allinea all'etichetta più lunga). La compressione in striscia di icone, invece, si restringe già da sola; `ue_auto_width` segue in entrambi i casi
`ib_reorderable` | boolean | `false` | Opt-in: l'utente può spostare una voce con il mouse. Lo spostamento resta nella sua sezione — un identificatore di voce è unico solo lì, quindi attraversare rischierebbe due chiavi identiche (attiva `ue_item_reordered`)
`ib_veto_selection` | boolean | `true` | Chiedere prima che la selezione si sposti (attiva `ue_selection_changing`, che può rifiutare). Attivo per impostazione predefinita: non scrivere nulla lascia sempre passare. Lo metta a `false` per togliere l'andata e ritorno verso PowerBuilder (~35 ms) dove si noterebbe — navigazione da tastiera, selezione spostata in un ciclo
`is_theme_style` | string | `fluent` | Stile visivo del componente (costanti `THEME_STYLE_*`)
`is_theme_mode` | string | `light` | Variante chiara o scura (costanti `THEME_MODE_*`)
`il_theme_accent` | long | `-1` | Colore d'accento di questo componente (`-1` = accento del tema)
`is_tooltip` | string | `""` | Tooltip semplice mostrato al passaggio del mouse sul componente
`is_super_tooltip_title` | string | `""` | Titolo del tooltip avanzato (prevale su `is_tooltip`)
`is_super_tooltip_text` | string | `""` | Testo del tooltip avanzato (markup avanzato accettato)
`is_super_tooltip_image` | string | `""` | Immagine del tooltip avanzato

### Proprietà di una sezione — `n_pbt_listbar_section` #

Proprietà | Tipo | Predefinito | Ruolo
--- | --- | --- | ---
`is_title` | string | `""` | Titolo della sezione. Accetta il testo formattato con tag. Un titolo vuoto non mostra alcuna riga di intestazione: la sezione diventa un semplice raggruppamento invisibile
`ib_collapsed` | boolean | `false` | Fisarmonica: `true` comprime le voci di questa sezione. L'intestazione resta visibile e il suo chevron ruota

### Proprietà di una voce — `n_pbt_listbar_item` #

Proprietà | Tipo | Predefinito | Ruolo
--- | --- | --- | ---
`is_text` | string | `""` | Etichetta della voce, modificabile a caldo senza ricostruire la barra. Accetta il testo formattato con tag
`is_image` | string | `""` | Icona, modificabile a caldo (forme accettate: percorso, `mono:`, `tint:`, risorsa di DLL)
`ib_enabled` | boolean | `true` | `false` disattiva la voce e ne blocca il clic
`ib_visible` | boolean | `true` | `false` nasconde la voce senza rimuoverla dalla barra
`is_tooltip` | string | `""` | Tooltip semplice mostrato al passaggio del mouse sull'item
`is_super_tooltip_title` | string | `""` | Titolo del tooltip avanzato dell'item (prevale su `is_tooltip`)
`is_super_tooltip_text` | string | `""` | Testo del tooltip avanzato dell'item (markup avanzato accettato)
`is_super_tooltip_image` | string | `""` | Immagine del tooltip avanzato dell'item

## Metodi #

### Sul componente #

Metodo | Ruolo
--- | ---
`of_add_header (string as_id, string as_text)` | Aggiunge una sezione e restituisce il suo handle `n_pbt_listbar_section`, sul quale si concatenano le aggiunte di voci
`of_section (string as_id)` | Handle di una sezione esistente (creato al primo accesso)
`of_insert_item (string as_section, string as_id, string as_text, integer ai_index)` | Inserisce una voce nella posizione `ai_index` all'interno della sua sezione
`of_insert_item (string as_section, string as_id, string as_text, string as_image, integer ai_index)` | Idem, con l’icona della voce: `of_add_item` ne accetta una, quindi anche l’inserimento deve poterla accettare
`of_move_item (string as_section, string as_id, integer ai_index)` | Sposta una voce esistente all'interno della sua sezione, conservandone lo stato
`of_remove_item (string as_section, string as_id)` | Rimuove una voce indicata dalla coppia sezione / identificatore
`of_clear ( )` | Svuota la barra: tutte le sezioni e tutte le voci
`of_select_item (string as_section, string as_id)` | Seleziona una voce — rigorosamente equivalente a un clic dell'utente: `ue_selection_changing` viene chiesto prima, poi `ue_selection_changed` annuncia lo spostamento
`of_get_layout ( )` | Rilegge la disposizione corrente in JSON: le sezioni nell'ordine, ciascuna con le sue voci in ordine e il suo stato compresso. Da memorizzare (file, database, registro) e da restituire con `of_set_layout` all'avvio successivo. La stessa coppia porta gli stessi nomi su ogni componente riorganizzabile
`of_set_layout (string as_layout_json)` | Ripristina una disposizione letta con `of_get_layout` o ricevuta con `ue_layout_changed`. Ciò che la disposizione non nomina conserva il suo posto in fondo: una disposizione di ieri non deve far sparire ciò che è stato aggiunto da allora. Applicarla non genera alcun event — l'avete fornita voi
`of_clear_selection ( )` | Non lascia selezionata alcuna voce. Annunciato come qualsiasi altro spostamento
`of_selected_key ( )` | Identificatore della voce selezionata, `""` se non ve n'è alcuna. Sempre quella corrente: un clic e `of_select_item` ripassano entrambi da `ue_selection_changed`
`of_selected_section ( )` | Sezione che contiene la voce selezionata — un id di voce è unico solo dentro la sua sezione, quindi è la coppia a designare la selezione. `""` se non ve n'è alcuna
`of_reset ( )` | Svuota la barra e riporta il componente allo stato iniziale
`of_set_redraw (boolean)` | Raggruppa una raffica di modifiche in un unico rendering
`of_save_as_png (string)` · `of_save_as_jpg (string)` | Esporta il rendering come immagine

### Su una sezione — `n_pbt_listbar_section` #

Metodo | Ruolo
--- | ---
`of_add_item (string as_id, string as_label, string as_icon_file)` | Aggiunge una voce normale a questa sezione e ne restituisce l'handle
`of_item (string as_id)` | Handle di una voce di questa sezione (creato al primo accesso)

## Event #

Event | Attivato quando
--- | ---
`ue_selection_changed (string as_from_section, string as_from_id, string as_section, string as_id)` | La selezione si è spostata — con un clic oppure tramite `of_select_item`. Stessi argomenti di `ue_selection_changing`: la domanda e il suo esito si leggono allo stesso modo, e la coppia `as_from_*` indica la voce lasciata (vuota se nessuna)
`ue_section_toggled (string as_section, boolean ab_collapsed)` | L'utente comprime o espande una sezione dalla sua intestazione
`ue_item_reordered (string as_section, string as_id, integer ai_index)` | L'utente ha finito di trascinare una voce. `ai_index` è il suo nuovo rango nella sua sezione, a partire da 1. Conservi quest'ordine per restituire all'utente la barra come l'ha lasciata
`ue_layout_changed (string as_layout_json)` | La disposizione è cambiata — l'utente ha riorganizzato qualcosa, o il vostro codice. Porta la disposizione intera, non solo ciò che si è mosso: conservarla è una sola assegnazione
`ue_selection_changing (string as_from_section, string as_from_id, string as_section, string as_id)` → boolean | Annullabile, posto prima che la selezione si sposti. Sollevato per impostazione predefinita; `ib_veto_selection = false` lo elimina. Restituisca `false` per mantenere l'utente dove si trova
`ue_auto_width (long al_width)` | Il componente ha ricalcolato la propria larghezza ideale — richiede `ib_auto_width = true`
`ue_ready ( )` | Il componente ha terminato il caricamento; tutto ciò che è stato inviato prima è stato riprodotto
`ue_runtime_missing ( )` | Il runtime WebView2 è assente: il componente resta vuoto
`ue_bg_color (long al_color)` | Il componente ha calcolato il colore di sfondo del proprio tema; l'userobject lo ha già adottato (`backcolor`)

## Esempi #

### Menu laterale completo #

    n_pbt_listbar_section lnv_dossiers, lnv_outils

    uo_nav.of_set_redraw(false)

    lnv_dossiers = uo_nav.of_add_header("dossiers", "Cartelle")
    lnv_dossiers.of_add_item("recents",  "Recenti",  "mono:img\clock.svg")
    lnv_dossiers.of_add_item("clients",  "Clienti",  "mono:img\user.svg")
    lnv_dossiers.of_add_item("archives", "Archivi", "mono:img\box.svg")

    lnv_outils = uo_nav.of_add_header("outils", "Strumenti")
    lnv_outils.of_add_item("import", "Importa", "mono:img\import.svg")
    lnv_outils.of_add_item("export", "Esporta", "mono:img\export.svg")

    uo_nav.of_set_redraw(true)
    uo_nav.of_select_item("dossiers", "recents")

### Barra comprimibile che libera spazio #

    // Comprimere in una barra di sole icone : la barra si restringe da sola (e riprende la
    // sua larghezza quando la si espande).
    uo_nav.ib_collapsed = true

    // event ue_auto_width di uo_nav : (long al_width)
    // La barra ha appena adottato la sua larghezza ideale : riallineare cio che si trova a destra.
    uo_contenu.x     = uo_nav.x + al_width
    uo_contenu.width = parent.width - uo_contenu.x

### Fisarmonica: comprimere una sezione #

    // Comprimere la sezione degli archivi, usata di rado
    uo_nav.of_section("archives").ib_collapsed = true

    // event ue_section_toggled di uo_nav : (string as_section, boolean ab_collapsed)
    of_enregistrer_preference("section_" + as_section, String(ab_collapsed))

### Reagire alla navigazione #

    // event ue_selection_changed di uo_nav : (string as_from_section, string as_from_id,
    //                                         string as_section, string as_id)
    // La sezione fa parte della chiave : due sezioni possono avere una voce "liste".
    choose case as_section
        case "dossiers" ; of_ouvrir_dossier(as_id)
        case "outils"   ; of_lancer_outil(as_id)
    end choose

### Rifiutare un cambio di selezione #

    // La domanda e posta per IMPOSTAZIONE PREDEFINITA: niente da attivare. Questa
    // riga fa il contrario, la toglie dove arbitrare non serve e il costo si vedrebbe.
    uo_nav.ib_veto_selection = false

    // event ue_selection_changing di uo_nav :
    //   (string as_from_section, string as_from_id, string as_section, string as_id)
    // Restituire FALSE mantiene l'utente sulla voce che sta lasciando.
    if of_saisie_en_cours(as_from_section, as_from_id) then
        MessageBox("Inserimento", "Completi la scheda in corso prima di navigare.")
        return false
    end if
    return true

### Aggiornare una voce a caldo #

    n_pbt_listbar_item lnv_entree

    // Il percorso completo e obbligatorio : componente -> sezione -> voce
    lnv_entree = uo_nav.of_section("dossiers").of_item("recents")
    lnv_entree.is_text  = "Recenti (12)"
    lnv_entree.is_image = "mono:img\clock_full.svg"

    // Disattivare o nascondere in base ai diritti, senza ricostruire la barra
    uo_nav.of_section("outils").of_item("import").ib_enabled = of_a_le_droit("import")
    uo_nav.of_section("outils").of_item("export").ib_visible = gb_mode_expert

### Selezione pilotata dal codice #

    // Spostare la selezione altrove : la banda d'accento segue
    uo_nav.of_select_item("dossiers", "clients")

    // Oppure cancellarla completamente
    uo_nav.of_clear_selection()

### Ricostruire la barra #

    // of_clear svuota sezioni e voci ; of_reset vi aggiunge i valori predefiniti del componente
    uo_nav.of_clear()
    of_construire_menu_selon_profil()

## Buone pratiche #

- Conservi l'handle di sezione restituito da `of_add_header` in una variabile locale: è più leggibile che richiamare `of_section(...)` per ogni voce.
- Usi `mono:` per le icone: si ricolorano con il tema, sia chiaro sia scuro, e restano leggibili una volta che la barra è compressa in barra di sole icone.
- Un titolo di sezione vuoto funge da raggruppamento discreto: le voci sono distanziate senza che appaia alcuna riga di intestazione.
- `ib_collapsed` restringe l'userobject alla striscia di icone, ma non sposta i suoi altri controlli: gestisca `ue_auto_width` per occupare lo spazio liberato, altrimenti resta vuoto.
- In modalità barra di sole icone restano solo le icone: imposti un tooltip su ogni voce affinché le etichette restino accessibili.
- La domanda è posta per impostazione predefinita: un `ue_selection_changing` lasciato vuoto autorizza sempre lo spostamento, non deve fare nulla. La disattivi con `ib_veto_selection = false` dove il clic è ripetuto — navigazione da tastiera, selezione pilotata in un ciclo — perché ogni domanda costa un andata e ritorno verso PowerBuilder.
- `ib_enabled = false` è preferibile a `ib_visible = false` quando la voce tornerà disponibile: il menu non cambia forma sotto gli occhi dell'utente.

← Riferimento dei componenti · Sommario della guida