# tab — `u_pbt_tab` #

← Riferimento dei componenti · Sommario della guida

> Schede moderne che ospitano veri controlli PowerBuilder: banda riposizionabile, icone per scheda, schede chiudibili, riordino con il mouse.

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

## In breve #

Userobject | `u_pbt_tab`
Classe degli item | `n_pbt_tab_page` (una pagina = una scheda)
Serve per | Sostituire un `tab` PowerBuilder con una banda a tema, conservando le Sue schermate esistenti come pagine
Opzioni opt-in | `ib_reorderable`

L'argomento chiave: una pagina non è un mockup HTML, è un `dragobject` PowerBuilder — un userobject, una DataWindow, un gruppo di controlli o persino un altro componente PBToolboxAI. Il componente si occupa del posizionamento, del ridimensionamento e della visualizzazione/nascondimento al cambio di scheda. Vedere Ospitare veri controlli PowerBuilder.

## Avvio rapido #

    // event open della finestra : ogni pagina e un controllo PB gia posto sulla finestra
    uo_onglets.of_add_page("clients",  "Clienti",  uo_page_clients)
    uo_onglets.of_add_page("factures", "Fatture", uo_page_factures, /*chiudibile*/ true)

    // Un'icona per scheda, posta sull'handle della pagina
    uo_onglets.of_item("clients").is_icon  = "mono:img\clients.svg"
    uo_onglets.of_item("factures").is_icon = "mono:img\invoice.svg"

    uo_onglets.of_select_page("clients")

    // event ue_selection_changed di uo_onglets : (string as_from_id, string as_id)
    of_charger_page(as_id)

## Proprietà #

Proprietà | Tipo | Predefinito | Ruolo
--- | --- | --- | ---
`is_position` | string | `"top"` | Collocazione della banda: `top`, `bottom` (banda orizzontale), `start`, `end` (banda verticale). Costanti `POSITION_TOP`, `POSITION_BOTTOM`, `POSITION_START`, `POSITION_END`. `START`/`END` sono logiche e seguono il senso di scrittura
`is_overflow_mode` | string | `"menu"` | Ciò che fa una banda troppo piccola per le sue schede. `menu` (predefinito) mantiene ogni scheda leggibile: quelle che non entrano più escono dalla banda e il pulsante `···` le elenca tutte, con la scheda attiva sempre a schermo. `compact` le tiene tutte nella banda e le lascia ridurre, fino allo spazio che richiede un testo troncato. Costanti `OVERFLOW_MENU`, `OVERFLOW_COMPACT`
`ib_reorderable` | boolean | `false` | Opt-in: l'utente può riordinare le schede trascinandone l'intestazione con il mouse (attiva `ue_tab_reordered`)
`ib_veto_selection` | boolean | `true` | Chiedere prima di cambiare scheda attiva (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
`ib_veto_close` | boolean | `true` | Chiedere prima di chiudere una scheda chiudibile (attiva `ue_tab_closing`, che può rifiutare). Attivo per impostazione predefinita, stessa regola
`ib_context_menu` | boolean | `true` | Menu contestuale integrato sull'intestazione di una scheda: Chiudi, Chiudi le altre, Chiudi a destra, Chiudi tutte, disattivati quando non hanno bersaglio. Attivo per impostazione predefinita. Il clic destro seleziona prima la scheda: se l'applicazione rifiuta il cambio, non si apre alcun menu. Ogni chiusura passa da `ue_tab_closing`, una domanda per pagina: quella che detiene lavoro non salvato rifiuta da sola e resta aperta mentre le sue vicine se ne vanno. A `false` per mostrare il suo menu da `ue_rclicked`
`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 pagina — `n_pbt_tab_page` #

Ottenute con `of_item(id)`, si modificano a caldo, senza ricostruire la banda.

Proprietà | Tipo | Predefinito | Ruolo
--- | --- | --- | ---
`is_title` | string | `""` | Etichetta della scheda. Accetta il testo formattato con tag
`is_icon` | string | `""` | Icona della scheda (forme accettate: percorso, `mono:`, `tint:`, risorsa di DLL). Vuoto = nessuna icona
`ib_enabled` | boolean | `true` | `false` disattiva la scheda e ne impedisce la selezione da parte dell'utente
`ib_visible` | boolean | `true` | `false` nasconde la scheda senza eliminare la pagina; nascondere la scheda attiva ne attiva una vicina
`ib_closable` | boolean | `false` | Croce di chiusura su questa scheda. Raramente nota al momento dell aggiunta: diventa `true` non appena il documento contenuto viene salvato, `false` mentre vi gira un elaborazione
`is_shortcut` | string | `""` | Combinazione di tasti che attiva questa scheda: `"Ctrl+2"`, `"Alt+F"`, `"F6"`… Risponde ovunque si trovi l'utente nella finestra, pagina ospitata compresa — la combinazione è tenuta dalla DLL, non dalla barra delle schede. Selezionare così è un clic: `ue_selection_changing` viene chiesto, `ue_selection_changed` segue. `""` la rimuove
`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 #

Metodo | Ruolo
--- | ---
`of_add_page (string as_id, string as_title, dragobject ado_page)` | Aggiunge una scheda non chiudibile, senza icona, e ospita il controllo
`of_add_page (string as_id, string as_title, dragobject ado_page, boolean ab_closable)` | Idem, con crocetta di chiusura se `ab_closable`
`of_add_page (string as_id, string as_title, dragobject ado_page, boolean ab_closable, string as_icon)` | Idem, con l'icona posta nella stessa chiamata (la scheda appare subito completa)
`of_insert_page (string as_id, string as_title, dragobject ado_page, integer ai_index)` | Aggiunge la pagina e poi la sposta alla posizione `ai_index`
`of_insert_page (string as_id, string as_title, dragobject ado_page, boolean ab_closable, string as_icon, integer ai_index)` | Idem, dicendo ciò che dice `of_add_page` : se la scheda si chiude, e la sua icona
`of_move_page (string as_id, integer ai_index)` | Sposta una scheda esistente; la pagina ospitata e la selezione vengono conservate
`of_select_page (string as_id)` | Attiva una scheda — rigorosamente equivalente a un clic dell'utente (passa da `ue_selection_changing` poi `ue_selection_changed`)
`of_remove_page (string as_id)` | Rimuove la scheda e restituisce il controllo alla sua finestra di origine, nascosto. Il controllo resta utilizzabile e può essere ospitato altrove
`of_selected_key ( )` | Identificatore della scheda attiva, `""` se nessuna
`of_get_layout ( )` | Rilegge la disposizione corrente in JSON: l'ordine delle schede e la visibilità di ciascuna. 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_item (string as_id)` | Handle `n_pbt_tab_page` della pagina (creato al primo accesso)
`of_refresh_page (string as_id)` | Aggiorna il rendering di una pagina costruita fuori schermo, senza sfarfallio
`of_relayout ( )` | Ripubblica l'area di pagina affinché il controllo ospitato venga riposizionato (utile dopo una visualizzazione differita)
`of_preload_icons (string as_icons[])` | Preriscalda un lotto di icone all'avvio: una scheda aperta più tardi mostra la propria icona istantaneamente
`of_reset ( )` | Svuota la banda: ogni pagina ospitata viene restituita alla sua finestra di origine, poi il componente torna 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

> `of_add_page` restituisce un codice negativo se l'identificatore è vuoto, già utilizzato, oppure se il controllo passato non è valido.

Quando le schede sono troppe — si riducono per stare nella banda, ma mai sotto una larghezza leggibile: l'icona e la croce di chiusura occupano il loro spazio in aggiunta al titolo, mai al suo posto. Quelle che non entrano più escono dalla banda, e alla sua estremità compare un pulsante `···`: apre l'elenco di tutte le schede visibili, con l'attiva spuntata, e la scelta vi passa. La scheda attiva resta sempre a schermo. La banda non scorre — quel pulsante è la via verso le schede fuori dal riquadro. Nulla da programmare, il comportamento è automatico.

## Event #

Event | Attivato quando
--- | ---
`ue_selection_changed (string as_from_id, string as_id)` | La scheda attiva è cambiata — con un clic oppure tramite `of_select_page`. Stessi argomenti di `ue_selection_changing`: la domanda e il suo esito si leggono allo stesso modo, e `as_from_id` è la pagina lasciata
`ue_tab_closed (string as_id)` | L'utente fa clic sulla crocetta di una scheda chiudibile. La scheda è già stata rimossa e la pagina restituita alla sua finestra
`ue_tab_reordered (string as_id, integer ai_index)` | L'utente ha terminato di trascinare un'intestazione. `ai_index` è la nuova posizione, a partire da 1
`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_id, string as_id)` → boolean | Annullabile, posto prima che la scheda attiva cambi. Sollevato per impostazione predefinita; `ib_veto_selection = false` lo elimina. Restituisca `false` per mantenere l'utente sulla sua pagina
`ue_tab_closing (string as_id)` → boolean | Annullabile, posto prima della chiusura di una scheda chiudibile. Sollevato per impostazione predefinita; `ib_veto_close = false` lo elimina. Chiamato per fare coppia con `ue_tab_closed`: closing / closed. Restituisca `false` per mantenere aperta la scheda (e la sua pagina ospitata)
`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 #

### Un raccoglitore di pagine gestionali #

    // event open : gli userobject di pagina sono gia posti sulla finestra
    uo_onglets.of_set_redraw(false)

    uo_onglets.of_add_page(/*id*/ "identite", /*titolo*/ "Identita",  /*pagina*/ uo_identite)
    uo_onglets.of_add_page(/*id*/ "adresses", /*titolo*/ "Indirizzi",  /*pagina*/ uo_adresses)
    uo_onglets.of_add_page(/*id*/ "compta",   /*titolo*/ "Contabilita", /*pagina*/ uo_compta)

    uo_onglets.of_item("identite").is_icon = "mono:img\user.svg"
    uo_onglets.of_item("adresses").is_icon = "mono:img\map.svg"
    uo_onglets.of_item("compta").is_icon   = "mono:img\euro.svg"

    uo_onglets.of_set_redraw(true)
    uo_onglets.of_select_page("identite")

### Documenti chiudibili, aperti su richiesta #

    // Aprire un documento in una nuova scheda chiudibile
    uo_onglets.of_add_page(/*id*/ ls_cle, /*titolo*/ ls_libelle, /*pagina*/ uo_editeur, &
                           /*chiudibile*/ true, /*icona*/ "mono:img\doc.svg")
    uo_onglets.of_select_page(ls_cle)

    // event ue_tab_closed di uo_onglets : (string as_id)
    // La scheda e gia stata rimossa ; resta solo da liberare i Suoi dati gestionali.
    of_liberer_document(as_id)

### Riordino con il mouse #

    uo_onglets.ib_reorderable = true

    // event ue_tab_reordered di uo_onglets : (string as_id, integer ai_index)
    // ai_index = nuova posizione, a partire da 1 : si memorizza l'ordine scelto.
    of_enregistrer_ordre(as_id, ai_index)

### Banda verticale #

    // Banda di schede sul lato sinistro, utile quando le etichette sono lunghe
    uo_onglets.is_position = uo_onglets.POSITION_START

### Disattivare o nascondere una scheda in base ai diritti #

    // Il percorso passa sempre dall'handle della pagina
    uo_onglets.of_item("compta").ib_enabled = of_a_le_droit("compta")
    uo_onglets.of_item("audit").ib_visible  = gb_mode_expert

### Reagire alla selezione #

    // event ue_selection_changed di uo_onglets : (string as_from_id, string as_id)
    choose case as_id
        case "identite" ; uo_identite.of_rafraichir()
        case "adresses" ; uo_adresses.of_rafraichir()
        case "compta"   ; uo_compta.of_rafraichir()
    end choose

### Rifiutare un cambio di scheda o una chiusura #

    // Entrambe le domande sono poste per IMPOSTAZIONE PREDEFINITA: niente da
    // attivare. Queste righe fanno il contrario, le tolgono dove arbitrare non serve.
    uo_onglets.ib_veto_selection = false
    uo_onglets.ib_veto_close     = false

    // event ue_selection_changing di uo_onglets : (string as_from_id, string as_id)
    // Restituire FALSE mantiene l'utente sulla pagina che sta lasciando.
    if of_page_modifiee(as_from_id) then
        if MessageBox("Modifiche", "Uscire senza salvare ?", Question!, YesNo!) = 2 then
            return false
        end if
    end if
    return true

    // event ue_tab_closing di uo_onglets : (string as_id)
    // Restituire FALSE mantiene aperti la scheda e la sua pagina ospitata.
    return not of_page_modifiee(as_id)

### Ripartire da una banda vuota #

    // of_reset restituisce OGNI pagina ospitata alla sua finestra di origine prima di svuotare
    uo_onglets.of_reset()
    uo_onglets.of_add_page("accueil", "Home", uo_accueil)

## Buone pratiche #

- I controlli ospitati devono esistere prima della chiamata: li ponga sulla finestra in fase di progettazione, il componente si occupa di nasconderli e riposizionarli.
- Carichi le pagine una sola volta nell'`open`, poi piloti unicamente la selezione: è più rapido che aggiungere e rimuovere pagine di continuo.
- Chiami `of_preload_icons` all'avvio se le Sue schede portano icone: in caso contrario, la prima apertura di una scheda nascosta mostra un breve ritardo prima dell'icona.
- Entrambe le domande sono poste per impostazione predefinita: un event lasciato vuoto autorizza sempre l'azione, non deve fare nulla. Le disattivi con `ib_veto_selection` / `ib_veto_close` a `false` se arbitrare non le serve, perché ogni domanda costa un andata e ritorno verso PowerBuilder.
- Un controllo ospitato è una finestra nativa: si disegna al di sopra dello strato web. Nessun effetto visivo del componente può passargli sopra.
- Non dimentichi `of_reset()` prima di ricostruire una banda: senza di esso, riutilizzare un identificatore di pagina fallisce e i controlli precedenti restano visualizzati.
- Per aree ridimensionabili e sganciabili anziché pagine esclusive, preferisca dockcontainer.

← Riferimento dei componenti · Sommario della guida