11. Migrare dalla 3.0 alla 4.0 #
← Migrare dalla 2.0 alla 3.0 · Sommario · Note di versione →
La 4.0 rimuove due metodi dei trentadue componenti della 3.0 — of_set_data della tabella incrociata, rinominato of_from_datastore (11.33), e of_transform di n_pbt_xml, che se ne va con XSLT (11.31) — e cambia firme che il compilatore le mostra riga per riga: tre proprietà rinominate (id_minimum e id_maximum della barra di avanzamento, 11.6; il_doc_line dell'editor di codice, 11.28), argomenti di evento aggiunti o rinominati (ue_tile_moved, 11.6; ue_failed del client REST, 11.6, e del video, 11.26; ue_error dell'immagine, 11.25; ue_cell_double_clicked, 11.33; ue_closed della palette dei comandi, 11.36; ue_toast_clicked, ue_toast_action e ue_toast_dismissed del toaster, 11.38), of_count e of_keys_at in long (11.34) e metodi che ora restituiscono un codice (of_refresh, of_select, of_show, of_scroll_to_end, of_set_header…). L'11.6 allinea inoltre due conteggi, un evento e il percorso dell'albero JSON al resto della libreria: è lì, con le sezioni citate, che va ritoccato codice che compilava. Ciò che cambia riguarda soprattutto la barra multifunzione (ribbon), che è stata rivista per intero. Due cambiamenti chiedono di rileggere il codice: la domanda posta prima di una piastrella di galleria (11.1) e gli handle liberati da una rimozione (11.2). Gli altri correggono comportamenti che può aver aggirato (11.3) — tra cui il clic destro su un elemento, che ora produce un solo evento in tutti i componenti, e il filo di Arianna (breadcrumb), i cui indirizzi e rifiuti sono stati rivisti. Seguono il generatore n_pbt_menu2ribbon (11.4) e ciò che è stato aggiunto (11.5). Anche la barra laterale (listbar) segue la regola dell'11.1: la sua domanda prima di una selezione è ora facoltativa. Le schede (tab) seguono la stessa regola: le loro due domande, prima di un cambio di scheda e prima di una chiusura, sono ora facoltative (11.1). Infine, i temi seguono l'applicazione (11.7): l'accento dell'applicazione sopravvive a un cambio di tema, e un asse di tema lasciato vuoto segue quello dell'applicazione. La revisione di sicurezza di crypto (11.8) chiude una confusione di algoritmo dei token JWT, sostituisce diversi silenzi con un rifiuto che dice la sua ragione e fissa la regola dei percorsi relativi dei file.
La revisione completa del 28/09/2026 ha riletto ogni componente consegnato; ciò che cambia ha una sezione per componente: restclient (11.9), speechout (11.10), statictext e il testo formattato (11.11), breadcrumb (11.12), buttonbar e la tastiera di finestra (11.13), button (11.14), menubar (11.15), ribbon (11.16), toolbar (11.17), statusbar (11.18), dockcontainer (11.19), tab (11.20), listbar (11.21), tilesbox (11.22), stepbar (11.23), progressbar (11.24), picture (11.25), video (11.26), pdfviewer (11.27), codeeditor (11.28), jsontree e xmltree (11.29, 11.30), xml (11.31), json (11.32), crosstab (11.33), shellexplorer (11.35), commandpalette (11.36), radialmenu (11.37), toaster (11.38) e messagebox (11.39); la base comune ha due sezioni, 11.34 e 11.40. Una regola le attraversa, quella di PowerBuilder (SelectTab solleva SelectionChanged): un cambiamento chiesto dal vostro codice solleva lo stesso evento di un gesto dell'utente, e pone la domanda del veto se l'avete attivato; il metodo restituisce -4 se rifiutate. Vale per una selezione (of_select_*), un'apertura o una chiusura (of_expand, of_collapse, of_open), uno zoom, uno schermo intero, un capitolo; nulla viene sollevato quando nulla cambia, e of_reset resta silenzioso. Impostare un VALORE (un segno di spunta, un testo, un volume, un filtro) resta silenzioso, come SetItem. ue_layout_changed è sollevato in entrambi i casi: dice che una disposizione da salvare è cambiata.
11.1 Le domande prima di un cambiamento sono ora facoltative #
Nella 3.0 la barra multifunzione poneva d'ufficio la domanda ue_gallery_selection_changing prima di scegliere una piastrella: ib_veto_gallery valeva true. Nella 4.0 vale false, come ogni evento annullabile della libreria: ogni domanda costa un andata e ritorno verso PowerBuilder, e solo un'applicazione che risponde deve pagarlo. Un'applicazione che non scriveva l'evento non vede alcuna differenza. Novità: of_select_gallery_item solleva ue_gallery_selection_changed come un clic e, con la domanda attivata, la pone anch'esso; un rifiuto gli fa restituire -4, la piastrella non cambia.
// 4.0 : the question is only asked on request. If your ue_gallery_selection_changing
// returns false for some tiles, switch it on where the ribbon is built.
uo_ribbon.ib_veto_gallery = true
La ricetta: cerchi ue_gallery_selection_changing nei discendenti della barra multifunzione; dove è scritto, aggiunga ib_veto_gallery = true alla costruzione. Dove scriveva ib_veto_gallery = false per disattivare la domanda, la riga non serve più e può essere tolta.
La barra laterale (listbar): ib_veto_selection #
Stessa regola: nella 3.0 la listbar poneva d'ufficio ue_selection_changing prima di ogni cambio di selezione (ib_veto_selection valeva true). Nella 4.0 vale false. Se scriveva ue_selection_changing per rifiutare uno spostamento, imposti ib_veto_selection = true: senza, l'evento non viene più sollevato e la selezione passa senza chiederle nulla. Attivata, la domanda viene posta anche per una selezione chiesta dal suo codice (of_select_item, of_clear_selection), come nella 3.0; un rifiuto fa ora restituire loro -4, e la selezione non si sposta. ue_selection_changed parte come prima.
// 4.0 : the listbar only asks on request. If your ue_selection_changing
// returns false (unsaved changes), switch the question on where the bar is built.
uo_nav.ib_veto_selection = true
La ricetta: cerchi ue_selection_changing nei discendenti di u_pbt_listbar; dove restituisce false, aggiunga ib_veto_selection = true alla costruzione. Dove scriveva ib_veto_selection = false per disattivare la domanda, la riga non serve più e può essere tolta.
Le schede (tab): ib_veto_selection e ib_veto_close #
Stessa regola, due domande: nella 3.0 il componente tab poneva d'ufficio ue_selection_changing prima di ogni cambio di scheda e ue_tab_closing prima di ogni chiusura (ib_veto_selection e ib_veto_close valevano true). Nella 4.0 valgono entrambi false. Se scriveva ue_selection_changing o ue_tab_closing per rifiutare, imposti ib_veto_selection = true o ib_veto_close = true: senza, l'evento non viene più sollevato e la scheda cambia o si chiude senza chiederle nulla. Attivata, la domanda viene posta anche per of_select_page, come nella 3.0, ma prima che la scheda cambi: un rifiuto gli fa restituire -4 e nulla si muove; un consenso cambia la scheda subito, ue_selection_changed parte come prima, e of_selected_key() riletto subito dopo restituisce già la nuova chiave.
// 4.0 : the tab only asks on request. If your ue_selection_changing or
// ue_tab_closing returns false (unsaved changes), switch the questions on.
uo_tabs.ib_veto_selection = true
uo_tabs.ib_veto_close = true
La ricetta: cerchi ue_selection_changing e ue_tab_closing nei discendenti di u_pbt_tab; dove uno restituisce false, aggiunga la riga corrispondente alla costruzione. Dove scriveva = false per spegnere una domanda, la riga non serve più e può sparire.
11.2 Le aggiunte dicono cosa rifiutano, le rimozioni liberano i loro handle #
Nella 3.0 un'aggiunta ignorata dalla barra multifunzione — una chiave già presa, una voce di menu sotto un semplice pulsante — restituiva comunque 0, e non compariva nulla. Nella 4.0 restituisce -5, e il codice dell'invio (-2 se il componente non è creato) invece di uno 0 fisso. E una rimozione libera gli handle di ciò che se ne va: una variabile che teneva l'handle di un controllo rimosso non è più valida.
| Cosa | 3.0 | 4.0 |
|---|---|---|
| Aggiunta di una chiave già presa (scheda, gruppo, controllo) | 0, ignorata | -5 |
| Voce di menu, scelta di combo o piastrella sotto un controllo di altra natura | 0, ignorata | -5 |
of_add_tab, of_insert_tab, of_add_group, of_add_contextual_*, of_add_qat su un componente non creato | 0 | -2 |
Un handle tenuto dopo of_remove_tab, of_remove_group, of_remove_item o of_clear | restava in memoria fino alla distruzione della barra | liberato: IsValid() restituisce false |
// 4.0 : after a removal or of_clear, ask the component for the handle again
uo_ribbon.of_clear()
uo_ribbon.of_add_tab(/*key*/ "home", /*title*/ "Home")
uo_ribbon.of_add_group(/*keys*/ "home/clip", /*title*/ "Clipboard")
uo_ribbon.of_add_button(/*keys*/ "home/clip/paste", /*label*/ "Paste", /*image*/ "")
uo_ribbon.of_item(/*keys*/ "home/clip/paste").ib_enabled = false
La ricetta: non conservi un handle oltre una rimozione o un of_clear — lo richieda con of_tab, of_group, of_item o of_menu_item, il che non costa nulla. Dove un errore di costruzione le importa, verifichi il codice restituito dall'aggiunta.
11.3 Altri comportamenti che può notare #
Quando la finestra è stretta, la barra multifunzione ripiega i gruppi in un pulsante che apre un pannello. È da questo pannello che vengono le differenze più visibili:
| Cosa | 3.0 | 4.0 | |
|---|---|---|---|
| Pulsante, o parte principale di uno split, cliccato nel pannello di un gruppo ripiegato | ue_menu_selected("", false) | ue_clicked(indirizzo) | |
| Voce di menu scelta in quel pannello | indirizzo incompleto | indirizzo completo, cascata compresa | |
| Controllo disattivato, o voce nascosta, in quel pannello | rispondeva / era mostrata | non risponde / non è mostrata | |
| Split grande ridotto per mancanza di spazio | un clic apriva solo il menu | due parti: il comando e la freccia del menu | |
Voce di menu con la chiave del suo controllo (home/clip/paste/paste) | ue_clicked("home/clip/paste") | ue_menu_selected("home/clip/paste/paste", …) | |
of_menu_item("…/exp/pdf") quando una cascata contiene anch'essa pdf | poteva puntare a …/exp/more/pdf | punta alla voce che l'indirizzo nomina | |
as_from_keys di ue_gallery_selection_changed senza piastrella precedente | l'indirizzo della galleria | "" | |
Rileggere un handle della barra di accesso rapido, il_color di un selettore di colore, ii_visible_items, is_keytip di una scheda, il_color di un gruppo contestuale, of_count() di una galleria | vuoto, -1 o 0 | il valore sullo schermo | |
of_keys_at di una combo | "home/font/cb/cb:Arial" | "home/font/cb/Arial": la chiave di una scelta è la sua etichetta | |
of_ctx_group(k).il_color quando una scheda porta anch'essa la chiave k | colorava la scheda | colora solo il banner | |
Colori di elemento (il_back_color…) e is_tooltip di una scheda o di un gruppo | senza effetto | applicati; il suggerimento di un gruppo appare sul suo titolo | |
of_remove_item("save") su un pulsante della barra di accesso rapido | -5 | il pulsante è rimosso | |
of_add_app_menu_separator("saveas/s1") | una riga alla radice del menu | la riga nel sottomenu di saveas; una chiave senza / non cambia | |
of_clear() mentre una scheda era attiva | nessun evento | ue_selection_changed("") | |
Spinner a passo decimale (0.1) | 0.30000000000000004 | 0.3 | |
| Scorciatoia Alt (keytip) su un controllo disattivato, barra ridotta | la barra restava aperta | si richiude, nulla viene eseguito | |
| toolbar: combo, spinner o galleria disattivati nel pannello del chevron | rispondevano | non rispondono | |
Tutti: clic destro su un elemento (ue_item_rclicked, ue_panel_rclicked, ue_row_rclicked…) | la pagina inviava anche l'evento del componente, che nessun componente con elementi trasmetteva a PowerBuilder | un solo evento, quello dell'elemento; un ue_rclicked di componente, dove esiste, parte solo fuori dagli elementi | |
Tutti: un rilascio di file (ib_allow_drop) | ue_drag_leave poi ue_drop_files; percorsi tagliati a 260 caratteri | solo ue_drop_files, percorsi interi; of_reset toglie la destinazione di rilascio | |
breadcrumb: of_path() con un segmento nascosto, o nella versione dimostrativa | le chiavi mostrate: quello nascosto saltato, i primi segmenti tagliati | l'indirizzo completo del luogo corrente: of_truncate(of_path()) va a segno; il campo di digitazione parte dallo stesso | |
breadcrumb: of_keys_at(n); of_has("computer/C:") | la chiave semplice; cercava tra i rami del menu | l'indirizzo del segmento; cerca tra i segmenti | |
breadcrumb: leggere un handle di indirizzo profondo, of_item("a/b/c").is_text | leggeva solo l'ultimo livello: vuoto su una chiave ripetuta | il segmento di quell'indirizzo | |
breadcrumb: of_truncate, of_remove_item, of_clear_children, of_remove_child su un indirizzo sconosciuto o una chiave semplice ripetuta; of_add_child sotto un segmento assente o su un ramo già preso; of_add_item di un indirizzo che finirebbe altrove | 0, ignorato (o solo l'ultima chiave tenuta) | -5 | |
breadcrumb: un handle tenuto dopo of_clear, of_remove_item, of_truncate, of_clear_children o of_remove_child | restava in memoria | liberato: IsValid() restituisce false | |
| breadcrumb: campo di digitazione lasciato invariato, o finestra cambiata (Alt+Tab) durante la digitazione | ue_path_entered sollevato | nulla; la digitazione resta cambiando finestra | |
breadcrumb: segmento disattivato; Invio su un segmento | il suo chevron si apriva e riceveva un rilascio; Invio premeva anche il pulsante predefinito della finestra | interamente inerte; Invio clicca solo il segmento | |
buttonbar: Invio mentre un altro pulsante della barra ha il focus della tastiera | attivava il pulsante predefinito (is_default) | attiva il pulsante con il focus, come Windows; il predefinito parte quando nessun pulsante della barra ha il focus | |
buttonbar: pulsante predefinito o annulla disattivato o nascosto; is_shortcut di un pulsante disattivato o nascosto | Invio, Esc o Alt+lettera inghiottiti senza effetto, anche in un controllo PowerBuilder della finestra | il tasto resta alla finestra | |
buttonbar: is_shortcut di più lettere ("Save") | Alt+S funzionava solo se la barra aveva il focus | Alt+S funziona da qualsiasi punto della finestra (la prima lettera, come documentato) | |
buttonbar: of_add_button / of_insert_button su una chiave già presa o che contiene / o una barra verticale; of_remove_button / of_move_button su una chiave sconosciuta | 0, ignorato | -5 | |
buttonbar: of_remove_button, of_clear_buttons | la scorciatoia Alt+lettera, i colori e il tooltip del pulsante restavano (un pulsante ricreato con la stessa chiave li riprendeva); l'handle restava in memoria | se ne vanno con il pulsante; l'handle è liberato: IsValid() restituisce false | |
codeeditor: rileggere is_text di un testo in CRLF | in LF (in CRLF solo se l'editor era ripiegato): is_text = ls_original era falso | con i fine riga ricevuti, ripiegato o no | |
codeeditor: rileggere is_syntax dopo SYNTAX_CSHARP, SYNTAX_CPP, SYNTAX_JAVA, SYNTAX_XML | la grammatica usata ("c", "html") | il valore scritto | |
codeeditor: of_insert_text in sola lettura o ripiegato | inserito in sola lettura; rifiutato ripiegato, ma 0 | -4, non viene inserito nulla | |
codeeditor: ii_doc_line | solo una fascia, spesso fuori vista, assente con l'a capo; un integer | la riga arriva al centro della vista (una regione ripiegata che la nasconde si apre), fascia anche con l'a capo; cursore e selezione intatti; un long — rinominato il_doc_line nella 4.0 (sezione 11.28) | |
codeeditor: #regionopen con ib_folding | riscritto #region nel testo (is_text, e dopo il ripiegamento) | mai toccato; solo la visualizzazione ripiegata mostra #region | |
codeeditor: ue_find_result | due volte per of_find, a ogni tasto e (0, 0) alla chiusura della barra; sollevato anche con ib_search_enabled = false | una volta per ricerca o per passo; durante la digitazione se il conteggio cambia; mai alla chiusura; of_find senza effetto con la ricerca disattivata | |
codeeditor: ue_caret_changed | muto durante la digitazione; ripiegato, la riga VISUALIZZATA | sollevato anche durante la digitazione; ripiegato, la riga del margine | |
codeeditor: Ctrl+Z dopo Invio o Tab; Invio / Tab in modalità ripiegata | la cronologia di annullamento veniva svuotata; ripiegato, il tasto modificava la visualizzazione e poi si perdeva | ogni tasto si annulla; ripiegato, il tasto non ha effetto | |
codeeditor: ib_folding = true con ib_line_numbers = false | le regioni restavano chiuse, senza indicatore per aprirle | un margine stretto mantiene gli indicatori | |
commandpalette: of_add_command su una chiave già presa o che contiene / o una barra verticale; of_remove_command su una chiave sconosciuta | 0 (una chiave presa dava due comandi gemelli) | -5 | |
commandpalette: of_open / of_register_shortcut senza ipo_owner né ipo_receiver | 0, e nessun evento arrivava mai | -5 | |
| commandpalette: la combinazione premuta mentre la palette è aperta | senza effetto | richiude la palette | |
| commandpalette: un oggetto palette distrutto (pagina o finestra chiusa) | la sua combinazione restava registrata e inghiottiva il tasto nella finestra, senza alcun evento | la combinazione se ne va con l'oggetto, e una palette che aveva aperto si richiude | |
commandpalette: scorciatoia mostrata su una riga, su una tastiera non latina, con una cifra e Maiusc, Ctrl+Space, Ctrl+Up, Ctrl+Del, o un tasto F da solo | non rispondeva; Win + la lettera lanciava il comando con quella sola lettera come scorciatoia | risponde: il tasto fisico, letto come lo legge la DLL; Win non è mai un modificatore | |
commandpalette: un comando la cui scorciatoia è Ctrl+C, Ctrl+V, Ctrl+Z o Ctrl+A, durante la digitazione | partiva il comando al posto della copia, dell'incolla… | la casella di ricerca tiene questi quattro tasti | |
commandpalette: of_reset | conservava is_recent, una palette aperta e la combinazione già registrata | li svuota, la richiude e riporta la combinazione registrata a SHORTCUT_DEFAULT | |
commandpalette: pbm_custom02 della finestra ipo_owner | scatenato a ogni evento della palette | mai: solo un ipo_receiver impostato lo riceve ancora | |
Tutti: rileggere un valore di testo lungo (is_text di uno script grande) | sempre più lento con la dimensione (diversi secondi); tagliato senza avviso oltre un milione di caratteri | proporzionale alla dimensione; intero | |
n_pbt_utils.of_dir_has_subfolders | contava le cartelle nascoste, di sistema e le giunzioni; illeggibile oltre 260 caratteri | le ignora, come l'Esplora risorse (l'overload ab_include_hidden le conta); legge i percorsi lunghi | |
crosstab: separatore delle migliaia di of_set_value_format | valeva per TUTTE le misure; "," non riconosciuto ($1 234 in francese) | impostazione di QUESTA misura; ",", ".", " " riconosciuti; "" = predefinito del menu Opzioni | |
crosstab: of_set_member_filter(campo, "") | nessun membro tenuto: tabella vuota | rimuove il filtro, come of_set_member_order("") | |
crosstab: is_show, is_conditional_formatting, of_set_value_format prima di of_add_value_field | persi senza avviso | conservati, riletti così come posti, applicati quando il campo entra in Valori | |
| crosstab: ordinamento di una colonna o compressione di un gruppo con il mouse | nessun evento | ue_layout_changed, come tutto ciò che of_get_layout salva | |
crosstab: date di un DataStore su una postazione non francese (3/15/2025, 15.03.2025) | raggruppate in un mese sbagliato o vuoto; date ordinate sul solo anno | il mese giusto; la colonna riletta come aaaa-mm-gg, ordinata nel tempo | |
| crosstab: numeri mostrati in tedesco, italiano, spagnolo, portoghese | all'americana (1,234.5) | nella lingua di visualizzazione (1.234,5 in tedesco) | |
crosstab: of_export_csv | numeri con punto (1436.5), letti come testo da un Excel francese; un'etichetta =… si eseguiva all'apertura | separatore decimale della lingua di visualizzazione; un apostrofo davanti a = + - @ | |
crosstab: of_export_xlsx | totali e subtotali nascosti esportati comunque; totale in cima ignorato; simbolo « prima » spostato dopo | la tabella come sullo schermo | |
| crosstab: « Aggiungi ai valori » dal menu di un campo già in Valori | sostituiva i suoi valori | aggiunge un valore, come il trascinamento | |
| crosstab: « Rimuovi » dal menu di un campo filtrato | il filtro restava attivo, invisibile | il filtro se ne va con il campo | |
crosstab: AGG_DISTINCT_COUNT su una colonna con celle vuote | il vuoto contava come un valore | ignorato, come in Excel | |
| crosstab: formula che cita una misura calcolata | accettata, valeva 0 | rifiutata tramite ue_calc_field_error; i suoi messaggi sono in inglese | |
crosstab: ue_layout_changed con una graffa in un membro; ad_value di ue_cell_double_clicked | disposizione troncata; valore 0 se un campo in righe si chiama value, esponente perso | lette per intero | |
crosstab: ib_enabled = false, da tastiera | Invio apriva il menu di un chip, Ctrl+C copiava | muto | |
| crosstab: tastiera | il focus tornava in cima alla pagina dopo ogni azione; nessun modo di spostare un campo | il focus resta sull'elemento usato; il menu di un chip lo sposta (altra zona, a sinistra, a destra) | |
| crosstab: tema scuro | negativi e frecce delle icone poco leggibili; cella della scala di colori selezionata illeggibile | una tavolozza propria in modalità scura | |
crypto: of_jwt_sign con JWT_EDDSA | l'intestazione diceva "alg":"EDDSA", che le altre librerie (jose, PyJWT, jjwt) rifiutano | "alg":"EdDSA", il nome registrato; un token 3.0 si verifica ancora | |
crypto: of_generate_keypair di un tipo o di una dimensione sconosciuti ("ec_p256", 1024) | 0 e una coppia RSA 2048, senza una parola | -5, entrambi i PEM vuoti, is_last_error nomina le KEY_* ammesse | |
crypto: of_hash_file("SHA-256", …); algoritmo sconosciuto | vuoto, e is_last_error diceva « file illeggibile » di un file perfetto | il nome si legge come lo legge of_hash (SHA-256 = HASH_SHA256); un algoritmo sconosciuto è detto tale, distinto da un file illeggibile | |
crypto: of_base64_encode_file di un file troppo grande (oltre 64 MB a 32 bit, 512 MB a 64 bit); di un file assente in demo | « file illeggibile »; « limite della demo » | « troppo grande per questo processo »; « file illeggibile » — is_last_error dice la vera ragione | |
crypto: is_last_error dopo una chiamata nativa riuscita (of_crc32, of_hash in MD5, of_hash_file…) | conservava l'errore della chiamata precedente | vuoto | |
crypto: chiave HMAC vuota; exp/nbf non numerico di un JWT; of_password_verify di un valore oltre 10 000 000 round; of_random_password di un insieme sconosciuto | errore oscuro del motore; token valido per sempre; minuti di calcolo; CHARSET_ALL preso senza una parola | rifiutati subito, is_last_error dice perché | |
crypto: of_base64_decode_to_file("", percorso) | -5 | 0, un file vuoto | |
dockcontainer: of_add_panel con un as_relative_to sconosciuto, un controllo già ospitato, una chiave con / o una barra verticale, o POSITION_STACK sul pannello principale | 0: il pannello si ancorava alla radice, il controllo veniva ospitato due volte, o il pannello impilato sul principale restava invisibile | -5, e il controllo non viene toccato | |
dockcontainer: of_move_panel verso una destinazione sconosciuta, o POSITION_STACK sul pannello principale | 0: il pannello finiva contro la radice, o nulla si muoveva | -5 | |
dockcontainer: of_remove_panel, of_reset | il controllo tornava nella sua finestra nascosto, alla posizione e alla dimensione del dock | torna al suo posto, alla sua dimensione e con la visibilità che aveva prima di of_add_panel | |
dockcontainer: is_main impostato prima di of_add_panel; is_main = ""; is_main di un pannello impilato | ignorato in silenzio; nulla veniva trasmesso; i vicini di pila diventavano invisibili | conservato e applicato all'aggiunta del pannello; il pannello principale viene rimosso; esce dalla sua pila, gli altri restano visibili | |
dockcontainer: of_set_layout di una disposizione che non conosce nessuno dei pannelli, o di un testo che non è una disposizione | il dock si svuotava, o l'intero messaggio veniva rifiutato; 0 | i pannelli restano, sistemati accanto agli altri (mai sul principale); -5 per un testo che non è una disposizione | |
dockcontainer: ue_layout_changed | sollevato solo al trascinamento, al ridimensionamento e all'ancoraggio: una disposizione salvata a questo evento dimenticava un pannello chiuso o la scheda attiva | sollevato anche quando un pannello viene chiuso, nascosto, selezionato o rinominato, e quando cambia il pannello principale | |
| dockcontainer: clic sulla scheda (o intestazione) del pannello già attivo | ue_panel_selected a ogni clic | nulla: l'evento segnala un CAMBIO di pannello attivo | |
dockcontainer: pannello sbloccato (ib_pinned = false) | la sua linguetta si apriva solo al clic (la doc diceva « al passaggio del mouse ») | si apre al passaggio (400 ms) o al clic; aperta al passaggio, si richiude quando il mouse la lascia | |
| dockcontainer: controllo PB standard (MultiLineEdit, pulsante…) in un pannello mobile | le sue notifiche (modified, clicked, colori) non arrivavano più | arrivano come quando è ancorato | |
dockcontainer: nascondere un pannello mobile (ib_visible = false) | la sua finestra restava aperta | si chiude; mostrato di nuovo, il pannello torna ancorato al suo posto | |
| dockcontainer: finestra mobile | la sua area utile era più piccola del pannello (barra del titolo sottratta), poteva uscire dallo schermo, e un titolo con marcatori li mostrava | l'area utile ha la dimensione del pannello, la finestra resta nello schermo, il titolo è testo semplice | |
| dockcontainer: separatore da tastiera | la prima freccia lo faceva saltare al 50 % | parte dalla sua posizione visualizzata | |
json: valore null passato a of_set_number, of_add_number, of_set_boolean, of_add_boolean, o valore null o vuoto passato a of_set_raw / of_add_raw | l'intero documento diventava null (of_text rendeva null) o smetteva di essere JSON; un booleano null si scriveva false | si scrive null, il resto del documento è intatto | |
json: scrivere in un documento CARICATO la cui chiave è scritta "k" : v o con un carattere con escape, seguito da un a capo, o la cui radice è un array; of_set_members su un tale documento | la chiave veniva aggiunta due volte (la rilettura dava il vecchio valore), la scrittura rendeva -4 a torto, o il documento veniva sostituito dal frammento | il valore viene sostituito o aggiunto come in un documento costruito; of_set_members rende -4 se la radice non è un oggetto | |
json: of_set_*("items/1/qty", …) — una chiave NUOVA in un oggetto contenuto in un array | -4 | 0: la chiave viene aggiunta al primo elemento; un array si attraversa con un indice esistente, si crea solo una chiave di oggetto | |
json: percorso con un segmento vuoto (/name, a//b, a/) | venivano create chiavi chiamate ""; of_remove poteva togliere un altro valore | -5, non si scrive nulla; un lettore risponde "assente" | |
json: of_load di un numero scritto male (-, 01, +1, .5, 1., 1e) | 0, e of_is_valid vero | -4, come ogni JSON non valido | |
json: of_get_number di un numero con esponente (1e-7, 2.5E+3) o con più di 9 decimali | esponente ignorato (2.5E+3 letto 2,5), decimali tagliati a 9 | esponente risolto, 17 cifre significative conservate | |
| json: leggere o modificare un documento grande (una risposta API di 80 KB, 2000 righe) | secondi per chiamata (20 s per of_count), l'applicazione sembrava bloccata | un tempo proporzionale alla dimensione; leggere le righe una a una (rows/1, rows/2…) o scorrere le chiavi con of_name non riparte più dall'inizio | |
listbar: of_add_section / of_insert_section su una chiave presa o che contiene / o una barra verticale; of_add_item / of_insert_item su un indirizzo preso o sotto una sezione che la barra non ha aggiunto; of_remove_item, of_move_item, of_select_item, of_remove_section, of_move_section su un indirizzo sconosciuto | 0, ignorato; una voce sotto una sezione sconosciuta appariva sotto l'ultima sezione | -5; of_add_section restituisce anche -2 quando il componente non è creato | |
listbar: un handle tenuto dopo of_remove_item, of_remove_section o of_clear | restava in memoria | liberato: IsValid() restituisce false | |
listbar: rimuovere o svuotare ciò che porta la selezione (of_remove_item, of_remove_section, of_clear) | la selezione spariva senza evento; dopo of_clear, of_selected_key restituiva ancora la vecchia | ue_selection_changed(vecchia, "") | |
listbar: ue_layout_changed | muto alla compressione di una sezione e alla rimozione di una voce; sollevato all'ingresso nella barra di icone | sollevato alla compressione (clic o ib_collapsed di una sezione) e alla rimozione; non più per la barra di icone, che non fa parte della disposizione | |
listbar: barra di icone (ib_collapsed = true) | le voci di una sezione compressa sparivano; una voce senza icona mostrava un riquadro vuoto; of_reset lasciava la barra stretta | tutte le voci, un filetto tra le sezioni, l'iniziale di una voce senza icona, l'etichetta al passaggio del mouse; of_reset restituisce alla barra la sua larghezza | |
listbar: is_image di una sezione; un colore posto sulla sezione k quando anche una voce ha la chiave k | senza effetto; anche la voce prendeva il colore | l'icona è disegnata davanti al titolo; solo la sezione prende il colore | |
| listbar: tastiera | dopo un cambio di etichetta o una selezione, le frecce non rispondevano più; senza selezione la barra era fuori dalla tabulazione; i titoli di sezione si comprimevano solo con il mouse | il focus resta sulla voce; una fermata di tabulazione; i titoli si raggiungono con le frecce e si comprimono con Invio o Spazio | |
listbar: voce disattivata (ib_enabled = false); ib_auto_width su una barra espansa | etichetta sbiadita, poco leggibile nei temi chiari; riportava la larghezza già data | il colore « disattivato » del tema; la larghezza che chiede la riga più lunga | |
listbar: trascinare una voce (ib_reorderable) | pulsante rilasciato fuori dalla finestra: la voce seguiva ancora il mouse; il clic finale poteva selezionare la voce rilasciata | il gesto si ferma al ritorno del mouse; la fine di un trascinamento non seleziona nulla | |
menubar: ue_menu_opening | sollevato accanto all'elenco: ciò che cambiava (ingrigire Incolla…) si vedeva solo all'apertura successiva | l'elenco attende che l'evento torni: la modifica si vede a questa apertura | |
menubar: of_item, of_remove_item su una voce la cui chiave esiste anche in un'altra cascata (file/export/pdf, file/print/pdf) | potevano colpire l'altra voce (la prima trovata); la scorciatoia mostrata su una attivava l'altra | colpiscono la voce che l'indirizzo nomina; una chiave sola non scende più nelle cascate | |
menubar: of_add_menu, of_add_item, of_add_separator su una chiave già presa, con / o una barra verticale, o sotto un menu o un genitore sconosciuti; of_remove_item / of_remove_menu di un indirizzo sconosciuto | 0; una voce con il genitore scritto male finiva alla radice del menu, una chiave già presa dava voci gemelle | -5 | |
menubar: un handle o una scorciatoia dopo of_remove_item, of_remove_menu o of_clear | l'handle restava in memoria; la scorciatoia restava armata e inghiottiva il tasto, che non arrivava più all'applicazione | handle liberato: IsValid() restituisce false; scorciatoia disarmata | |
| menubar: voce ingrigita, nascosta o rimossa mentre il suo elenco è aperto; scorciatoia di una voce sotto una cascata ingrigita | il clic o il tasto sollevava ancora ue_item_selected | nulla | |
menubar: colori di item (il_back_color…) di un menu o di una voce; is_tooltip di un menu | senza effetto; un colore si rileggeva -1 | applicati: sul titolo del menu, sulla voce nell'elenco; il tooltip di un menu appare sul suo titolo, una voce dell'elenco non ne mostra | |
| menubar: tastiera | le frecce restavano bloccate su un menu ingrigito; in RTL, sinistra e destra erano invertite; Alt+lettera di un menu nascosto nascondeva la stessa lettera di un altro menu; dopo Alt+lettera e una scelta, l'Alt successivo spegneva | i menu ingrigiti sono saltati; le frecce seguono il senso di scrittura; solo un menu visibile risponde alla sua lettera; l'Alt successivo riaccende la barra | |
menubar: una cascata le cui voci sono tutte nascoste; of_count("file"), of_keys_at | si sceglieva come un comando (file/export); i separatori erano contati (__sep0) | ingrigita; solo le voci sono contate | |
menubar: of_item("file") — un indirizzo di un livello | rileggeva il menu, e scriveva su una voce «file» inesistente | non designa nulla: usate of_menu("file") | |
Ogni testo letto da un componente o da un JSON: escape \b e \f | restavano scritti così | decodificati (backspace, avanzamento pagina) | |
| messagebox: una finestra che non ha potuto aprirsi (runtime WebView2 assente, motore non pronto) | of_show e le scorciatoie (of_info…) restituivano 0, come una chiusura: of_info lasciava credere che una finestra fosse apparsa | -4 (-6 se manca il runtime), il motivo con of_get_last_error(); of_choose e of_prompt restituiscono "" e of_get_last_error lo dice. Un test = 1 per «confermato» resta giusto | |
messagebox: Esc o Alt+F4 mentre un pulsante di annullamento conta ancora alla rovescia (of_add_button_timed) | chiudevano la finestra (0) | non fanno nulla fino alla fine dell'attesa: serve a far leggere | |
| messagebox: il testo del messaggio e dell'istruzione | non si selezionava; premerci sopra spostava la finestra | si seleziona e si copia (Ctrl+C copia la selezione, o tutta la finestra senza selezione); la finestra si sposta dal titolo, dall'icona, dai margini | |
messagebox: un input di più di circa 900 caratteri (of_prompt, ib_input) | tornava vuoto, come un annullamento | torna intero | |
messagebox: al_hwnd = 0, una finestra aperta da un'altra, una finestra spostata e poi ingrandita | l'intero desktop veniva disattivato; la finestra si riattivava mentre la prima finestra attendeva ancora; la finestra tornava al centro | senza proprietario non si disattiva nulla; la finestra resta disattivata finché una finestra la attende; la finestra mantiene il suo posto | |
progressbar: intervallo vuoto o invertito (id_maximum = 0 poi id_value = 0) | 0 % qualunque sia il valore | 100 % non appena il valore raggiunge il massimo (un lotto vuoto è terminato), 0 % prima | |
| progressbar: la percentuale mostrata, l'anello | arrotondata al più vicino (99,5 % mostrava «100%»); anello fisso a 128 px; in attesa, l'anello ruotava con l'arco del valore (vuoto a 0: non si muoveva nulla) | arrotondata per difetto: 100 % significa terminato; l'anello segue la dimensione del controllo; in attesa ruota un arco fisso; se Windows chiede meno animazioni, l'attesa pulsa | |
Qualsiasi proprietà double riletta (id_value…) su un computer con virgola decimale | la parte decimale veniva letta male (0,5 non si rileggeva 0,5) | riletta esattamente, qualunque sia il separatore del computer | |
speechout: un nuovo of_speak (o of_close) durante una lettura | la lettura interrotta non sollevava alcun ue_stopped | ogni lettura iniziata finisce con un ue_stopped | |
speechout: il_timeout_ms = 0 | interrompeva la lettura sincrona dopo 5 s | nessun limite (24 ore al massimo) | |
| speechout: una voce che non ha potuto essere creata (runtime WebView2 assente, pagina rifiutata) | of_speak, of_speak_from, of_pause, of_resume, of_enqueue, of_clear_queue rendevano -1, of_open il codice grezzo della DLL | -2 (componente non creato, come ovunque), is_last_error dice perché; -4 se la pagina non ha risposto | |
speechout: of_speak_sync chiamato da un evento sollevato durante un altro of_speak_sync | interrompeva la lettura della chiamata esterna, che rendeva comunque 0 | rifiutato: -4, is_last_error = "already speaking synchronously" | |
speechout: of_speak_from oltre l'ultima frase | 0, non veniva letto nulla | -5 | |
speechout: of_is_speaking() subito dopo of_speak | false finché l'elenco delle voci non era arrivato | true fin da of_speak | |
speechout: of_pick_voice("", genere), o elenco delle voci illeggibile | sceglieva nella lingua della pagina; un errore svuotava is_voice | "" = is_lang; un errore mantiene is_voice e riempie is_last_error | |
speechout: of_voice_used, of_duration, of_spoken_text subito dopo aver cambiato is_lang o il dizionario | potevano rispondere con le impostazioni precedenti | rispondono con le impostazioni appena poste | |
| speechout: errore di script nella pagina della voce | silenzioso | ue_error("script error: …") | |
statictext: il_back_color con ii_corner_radius | lo sfondo riempiva tutto il rettangolo, solo il bordo era arrotondato | lo sfondo segue l'arrotondamento; fuori dagli angoli, il colore dell'oggetto su cui è posato il blocco, che prende anche lo userobject | |
statictext: is_marquee_direction con lettura da destra a sinistra | invertito: MARQUEE_START scorreva verso la fine, "left" verso destra | MARQUEE_START scorre verso l'inizio della lettura; "left" / "right" restano fisici | |
statictext: rilettura di il_back_color, ii_marquee_speed, is_marquee_direction, ib_marquee_overflow_only, ib_marquee_pause_on_hover, is_font_family | -1, 0, "", false qualunque cosa fosse impostata; una famiglia con spazio tra virgolette | il valore impostato | |
statictext: ii_marquee_speed = 0 | manteneva la velocità precedente | velocità predefinita (60) | |
statictext: of_reset dopo un bordo | colore e spessore mantenuti: il bordo successivo li ereditava | cancellati | |
statictext: ib_track_mouse, componente disattivato durante il passaggio del mouse | ue_mouse_leave mai sollevato | ue_mouse_leave sollevato all'uscita | |
statictext: scorrimento (ib_marquee) | un [foldarea] non si ripiegava più dopo; con ib_marquee_overflow_only, un cambio di ALTEZZA ripartiva dall'inizio; con ib_wrap = false, un ue_text_overflow(true) errato | corretto: il testo non viene più copiato, solo una vera nuova LARGHEZZA viene rimisurata, e lo scorrimento mostra tutto il testo | |
statictext: ib_hover_effect e link al passaggio del mouse su un tema scuro | scuriti (contrasto ridotto) | schiariti | |
Testo ricco: [symbol=clock] | mostrato così com'è | un glifo monocromo; un nome sconosciuto resta testo | |
statusbar: of_add_panel / of_insert_panel su una chiave presa o che contiene / o una barra verticale; of_move_panel, of_remove_panel, of_clear_menu, of_add_menu_separator su un pannello sconosciuto; of_add_menu_item / of_insert_menu_item sotto un pannello sconosciuto o su una voce presa; of_remove_menu_item, of_move_menu_item su un indirizzo sconosciuto | 0, ignorato | -5 | |
statusbar: of_insert_panel(…, 0) | aggiunto in fondo alla barra | per primo, come ogni posizione (0 o meno = per primo) | |
statusbar: un separatore (of_add_sep) in of_count, of_keys_at e nelle posizioni di of_insert_panel / of_move_panel | contato come un pannello a chiave vuota | ignorato: una posizione conta i pannelli | |
statusbar: un separatore tra due pannelli ALIGN_END | disegnato alla fine del gruppo di inizio | tra i due: apre il gruppo del pannello che lo segue | |
| statusbar: clic destro su un pannello non cliccabile | nessun evento | ue_panel_rclicked (un pannello disattivato resta muto) | |
statusbar: of_panel(k).ii_progress riletto su un pannello senza barra | 0, come una barra a 0 % | -1 | |
statusbar: of_menu_item("k"), un indirizzo di un solo livello | scriveva sul pannello k (ib_enabled lo disattivava) | non designa nulla: non scrive da nessuna parte, si rilegge vuoto | |
statusbar: colori e suggerimento di un pannello dopo of_clear, poi un pannello aggiunto con la stessa chiave | ripresi dal nuovo pannello | dimenticati: il pannello parte pulito | |
statusbar: is_state in un tema scuro; pannello disattivato | colori del tema chiaro, poco leggibili; disattivato per trasparenza, sfondo perso al passaggio | una tavolozza scura leggibile; disattivato con il colore del tema, sfondo mantenuto | |
| statusbar: un pannello le cui voci di elenco sono tutte nascoste | mano e freccia, clic senza effetto | un pannello normale, cliccabile o no secondo ib_clickable | |
| statusbar, toolbar: frecce Sinistra / Destra in lettura da destra a sinistra (RTL) | al contrario: Destra andava verso la sinistra dello schermo | nel verso dello schermo, come la scheda e la barra multifunzione | |
stepbar: impostare ii_current | non veniva sollevato nulla | ue_step_changed quando la barra si sposta, come la documentazione prometteva | |
| stepbar: togliere, inserire o spostare un passaggio prima di quello in corso | il passaggio in corso cambiava in silenzio (era un rango) | lo stesso passaggio resta in corso; se è lui a essere tolto, la barra passa al successivo raggiungibile e solleva ue_step_changed | |
stepbar: ii_current impostato prima dei passaggi; of_clear_steps | riportato al primo passaggio; il passaggio in corso sopravviveva allo svuotamento | conservato e applicato non appena il passaggio esiste; lo svuotamento riparte dal primo passaggio | |
stepbar: of_add_step / of_insert_step su una chiave presa o che contiene / o una barra verticale; of_move_step, of_remove_step su una chiave sconosciuta | 0, ignorato | -5 | |
stepbar: of_insert_step(…, 0) | aggiunto in fondo alla barra | inserito in testa, come ogni posizione della libreria (of_add_step aggiunge in fondo) | |
| stepbar: frecce sinistra / destra in una lingua da destra a sinistra | la freccia destra andava al passaggio successivo, disegnato a sinistra | invertite: la freccia sinistra va al passaggio successivo | |
tab: of_add_page / of_insert_page con una chiave che contiene / o una barra verticale; un invio fallito | 0; la pagina restava ospitata e la sua chiave presa | -5; un invio fallito restituisce il suo codice, la pagina torna alla sua finestra e la chiave resta libera | |
tab: of_select_page di una pagina nascosta, disattivata o oltre il limite della demo | 0, e la pagina appariva sotto una barra senza scheda attiva | -5, non si muove nulla | |
tab: croce, scorciatoia (is_shortcut), «Chiudi tutte / le altre / a destra» su una scheda disattivata o nascosta | la scheda si attivava o si chiudeva, e PB liberava la sua pagina | nessun effetto: una scheda che non si può né vedere né raggiungere non si attiva né si chiude | |
| tab: la scheda attiva viene chiusa, rimossa o nascosta | subentrava la successiva o la prima, anche nascosta o disattivata; as_from_key di ue_selection_changed era vuoto | subentra la vicina selezionabile (destra, altrimenti sinistra); as_from_key nomina la scheda davvero lasciata, anche se sparita | |
| tab: nessuna scheda visibile (tutte nascoste, o una disposizione che le nasconde) | la pagina della vecchia scheda restava visibile, senza evento | la pagina viene nascosta e viene sollevato ue_selection_changed(vecchia, ""); mostrare di nuovo una scheda la seleziona | |
tab: un handle tenuto dopo of_remove_page o una chiusura; la sua scorciatoia | restavano; una pagina riaperta con la stessa chiave riprendeva colore, tooltip e vecchia scorciatoia | liberati: IsValid() restituisce false, la pagina torna nuova | |
tab: of_set_layout con un testo che non è JSON | 0, e il messaggio partiva rotto | -5, non viene inviato nulla | |
| tab: tastiera nella barra delle schede | Invio perdeva il focus; le frecce si fermavano sulle schede disattivate o in eccesso; né Su/Giù su barra verticale né inversione nelle lingue da destra a sinistra | il focus resta sulla scheda; le frecce seguono l'asse della barra e saltano ciò che non risponde; Canc chiude una scheda chiudibile | |
| tab: testo di una scheda disattivata; tooltip di una scheda dal titolo troncato | sbiadito in blocco (illeggibile al passaggio in office2007 scuro); il nome completo nativo nascondeva il suo tooltip | testo nel colore disattivato del tema, leggibile; il suo tooltip ha la precedenza | |
tilesbox: of_get_layout | restituiva sempre "": una disposizione salvata non si ripristinava mai | la disposizione intera, lo stesso testo di ue_layout_changed; conserva anche la dimensione e la visibilità di ogni riquadro e la visibilità di ogni gruppo | |
tilesbox: of_set_layout che nomina un riquadro sotto un gruppo diverso dal suo; un testo che non è JSON | il primo riquadro con quella chiave, in qualsiasi gruppo, vi veniva spostato; 0 | un riquadro si ritrova tramite il suo gruppo e la sua chiave: la voce è ignorata; -5 su un testo che non è JSON | |
tilesbox: of_add_group su una chiave già presa; of_add_tile / of_insert_tile su una chiave presa o sotto un gruppo mai aggiunto; una chiave vuota, o con / o ` | ` | 0; un gruppo aggiunto di nuovo veniva rinominato, un riquadro sotto un gruppo sconosciuto lo creava con la sua chiave | -5, non viene aggiunto nulla: aggiungete prima il gruppo con of_add_group |
tilesbox: of_move_tile, of_remove_tile, of_add_live_item, of_clear_live_items su un riquadro inesistente; of_remove_group su un gruppo inesistente | 0 | -5 | |
tilesbox: un handle tenuto dopo of_remove_tile, of_remove_group, of_clear, o un riquadro trascinato in un altro gruppo | restava in memoria; un riquadro ricreato allo stesso indirizzo riprendeva colori e tooltip del vecchio, un riquadro trascinato li perdeva | l'handle è liberato (richiedetelo con of_tile / of_group); colori e tooltip seguono il riquadro trascinato e se ne vanno con ciò che è rimosso | |
statusbar, stepbar, crosstab: un handle tenuto dopo of_remove_panel, of_remove_menu_item, of_clear_menu, of_clear (statusbar), of_remove_step, of_clear_steps (stepbar), of_remove_calc_field o of_remove_calc_measure (crosstab) | restava in memoria fino alla distruzione del componente | liberato: IsValid() restituisce false; lo richieda con of_panel, of_menu_item, of_step o of_field | |
Tutti i componenti con elementi: rileggere il_back_color_hover / il_text_color_hover di un elemento mai colorato | 0, il nero | -1, «il colore del tema», come gli altri tre colori dell'elemento | |
tilesbox: rileggere ib_enabled / ib_visible di un gruppo, o ii_badge_size | false, false, 0 qualunque cosa fosse impostata | il valore in vigore | |
tilesbox: gruppo disattivato (ib_enabled = false) | la sua intestazione lo comprimeva ancora (clic, Invio) e sollevava ue_group_toggled; un riquadro trascinato poteva finirci | inerte: nessuna compressione, nessun evento, nessun rilascio | |
tilesbox: colori degli item (il_back_color, il_text_color, il_accent…) impostati su un gruppo | senza effetto; il colore di un gruppo a poteva colorare un riquadro a di un altro gruppo | colorano l'intestazione del gruppo (sfondo, titolo, passaggio del mouse, linea d'accento), mai i suoi riquadri | |
tilesbox: of_tile(""), o un indirizzo a uno o tre livelli | impostare una proprietà arrestava l'applicazione («Array boundary exceeded») o scriveva sul gruppo | un handle inerte: non scrive nulla e si legge vuoto | |
| tilesbox: tastiera e lettore di schermo | il focus si perdeva a ogni aggiornamento proveniente da PB (un badge) e il menu delle dimensioni si chiudeva; menu delle dimensioni solo col mouse; in RTL, frecce al contrario; etichette lette con i loro tag | focus e menu mantenuti; menu delle dimensioni da tastiera (frecce, Invio, Esc); frecce nel senso di lettura; testo semplice | |
toaster: il_max_visible | predefinito 5, inviato da OGNI toaster: un toaster che aveva impostato 10 tornava a 5 appena un altro mostrava un toast | predefinito 0 = non si invia nulla; il limite è COMUNE all'applicazione e vale l'ultimo valore impostato (5 finché nessuno lo imposta) | |
toaster: of_show di un toast in attesa di posto | restituiva 0: il toast non si poteva chiudere con of_close, e i suoi eventi portavano un id mai ricevuto; coda piena (200): 0 anche lì, toast perso senza una parola | un vero identificatore, subito; of_close lo toglie dalla coda; coda piena: -4 | |
toaster: due toast senza is_key con un pulsante della stessa chiave | il secondo SOSTITUIVA il primo (la chiave del pulsante era presa per quella del toast) e of_show restituiva l'id del primo | due toast, due identificatori; solo is_key aggiorna sul posto | |
| toaster: eventi di più toaster | archiviati per FINESTRA: due toaster ancorati alla stessa finestra si rubavano gli eventi, e quelli di un toaster distrutto andavano al successivo | ogni toaster riceve quelli dei SUOI toast; un toaster distrutto non riceve più nulla, i suoi toast restano a schermo, muti | |
toaster: pbm_custom02 della finestra ipo_owner | la finestra d'ancoraggio riceveva un pbm_custom02 a ogni evento di toast, anche senza ipo_receiver | solo una finestra impostata in ipo_receiver lo riceve; se aveva mappato pbm_custom02 della Sua finestra per i toast, imposti ipo_receiver, o meglio, tolga quel codice: gli eventi arrivano da soli | |
| toaster: visualizzazione | un toast restava fermo quando la sua finestra si spostava; un toast di oltre 800 px (una lunga traccia d'errore) non compariva MAI; larghezza non scalata (180 px al 200 %); aggiornare un toast sorvolato faceva ripartire tutta la pila | segue la sua finestra; il testo scorre nel toast limitato; larghezza in scala con lo schermo; la pila resta in pausa sotto il puntatore | |
toolbar: aggiunte, of_add_separator, of_move_item, of_remove_* su una chiave occupata, con / o ` | `, una barra sconosciuta o un indirizzo sconosciuto | 0, ignorato — un errore di battitura nel nome di una barra creava una barra fantasma | -5; solo main non ha bisogno di of_add_bar |
toolbar: of_clear, of_remove_bar, of_remove_item | gli handle restavano, le scorciatoie restavano attive, e uno strumento ricreato con la stessa chiave ritrovava i colori del precedente | handle liberati, scorciatoie disattivate, colori e tooltip dimenticati; richieda un handle dopo una rimozione | |
toolbar: of_item su un indirizzo a tre livelli (una voce di menu) | agiva sullo STRUMENTO della barra che portava il nome della voce | non designa nulla; una voce si pilota con of_menu_item(indirizzo) | |
| toolbar: voce scelta in un menu a discesa ripiegato nella freccia | ue_menu_selected senza il genitore della cascata, sotto un altro menu a discesa, o vuoto | l'indirizzo completo, come nella barra | |
toolbar: ii_index di una barra | non spostava mai una barra verso destra | la barra prende il rango richiesto | |
toolbar: of_add_bar(chiave, banda, rango) su un rango già occupato, o una banda oltre le altre | ordine indefinito; la banda si rileggeva così com'era (5 per la seconda riga) | si inserisce davanti alla barra che occupava il rango; le bande si ricompattano | |
toolbar: of_count, of_keys_at di una barra, rango di of_move_item | contavano i separatori, sotto una chiave vuota | solo gli strumenti: un separatore non ha né chiave né rango | |
| toolbar: Invio in una casella di testo | convalidava il campo E premeva il pulsante predefinito della finestra | convalida solo il campo; Esc gli restituisce il testo convalidato | |
toolbar: is_shortcut riletto; ii_band / ii_index di una barra sconosciuta | ctrl+s (normalizzato); 1 | Ctrl+S, come scritto; 0 | |
toolbar: colore o tooltip impostato su una BARRA (of_bar) | senza effetto, o colorava lo strumento con lo stesso nome | applicato alla barra, e solo a essa | |
| toolbar: scorciatoia di uno strumento nascosto o oltre il limite della demo | ingoiava il tasto | il tasto va allo strumento successivo con la stessa combinazione | |
webbrowser: una pagina che non si carica (host sconosciuto, rete, certificato, of_stop) | sollevava ue_load_completed, come un successo | solleva invece ue_load_failed(as_url, al_status) | |
webbrowser: parole in is_address («fattura 2026») | partivano come https://fattura 2026 e poi non avveniva più alcuna navigazione | rifiutate con ue_error, il seguito si carica; una ricerca se is_search_url è impostato | |
webbrowser: un percorso su disco (C:\temp\x.html) o //host/x in is_address | preceduto da https://, quindi introvabile | file:///C:/temp/x.html; https://host/x; javascript: rifiutato | |
webbrowser: is_address riletto dopo un link seguito o Indietro | l'ultimo indirizzo impostato | la pagina visualizzata | |
webbrowser: of_go_back, of_go_forward, of_stop subito dopo is_address | potevano passare PRIMA dell'indirizzo; of_stop lasciava ripartire le pagine in attesa | vengono eseguiti nell'ordine scritto; of_stop abbandona anche le pagine in attesa | |
webbrowser: of_save_as_png, of_save_as_jpg, of_print_to_pdf, of_print | catturavano o stampavano la barra degli indirizzi | il sito visualizzato | |
webbrowser: link target=_blank, window.open dopo un clic | non succedeva nulla | la pagina si apre nella vista, ue_new_window lo segnala | |
webbrowser: risposta di of_execute_javascript oltre 4.095 caratteri | tagliata senza avvisare | intera | |
| webbrowser: F5, Ctrl+R, Ctrl+rotellina nella barra degli indirizzi | ricaricavano o ingrandivano la barra stessa | senza effetto nella barra; attivi nel sito | |
webbrowser: clic destro in un campo di testo con ib_context_menu | Indietro / Avanti / Aggiorna | Taglia / Copia / Incolla | |
webbrowser: Tab o of_focus_webview senza barra degli indirizzi; file trascinato sul sito con ib_allow_drop | focus perso in una barra di 0 px; file aperto dal browser | il focus va al sito, Tab ne esce verso la Sua finestra; ue_drop_files | |
pdfviewer: is_source riletto, e as_source di ue_load_completed | l'indirizzo interno /_file/?p=… | ciò che ha scritto (doc\notice.pdf) | |
| pdfviewer: file assente, non un PDF, sito irraggiungibile o che rifiuta il riquadro | ue_load_completed su una pagina di errore, o nessun evento | ue_load_failed(as_source, as_reason) (costanti REASON_*), il visualizzatore resta vuoto | |
pdfviewer: http://, data: di un tipo diverso da PDF, pagina web in https:// | visualizzati (o riquadro vuoto per http://) | rifiutati: ue_load_failed con REASON_INSECURE o REASON_NOT_PDF | |
pdfviewer: un # in is_source | tagliava il percorso (Preventivo #12.pdf non trovato); il frammento di un URL si mescolava a ii_page / ii_zoom | un # fa parte del nome del file; il frammento di un URL è ignorato, pagina e zoom passano per le proprietà | |
pdfviewer: ii_page impostato prima di is_source | perso: il documento si apriva a pagina 1 | conservato per quel documento; senza pagina impostata dall'ultimo is_source, un nuovo documento si apre a pagina 1 | |
pdfviewer: PDF rigenerato allo stesso percorso poi of_refresh; PDF da 32 MB in su; percorso di oltre 260 caratteri | la vecchia versione per 5 minuti; niente; non trovato | il file così com'è sul disco; visualizzato (servito a blocchi); visualizzato | |
pdfviewer: link seguito nel documento; of_print | il sito sostituiva il documento, senza ritorno; stampava la pagina che incornicia il documento | il documento resta, ue_link_clicked(as_url) Le fornisce l'indirizzo; of_print stampa il documento (-4 senza documento) | |
picture, button, tilesbox: il_badge_color | 0 = il colore del tema; il nero era irraggiungibile; non impostato, si rileggeva 0 | -1 = non impostato (il colore del tema), come ogni altro colore; 0 è il nero. Sostituisca il_badge_color = 0 con -1 | |
picture: id_zoom impostato prima di ib_zoomable | si rileggeva come impostato, mentre l'immagine restava inquadrata | ignorato: id_zoom resta 1.0 finché ib_zoomable è falso; imposti prima ib_zoomable | |
picture: ib_mirror su un'immagine ruotata di un quarto di giro; is_align / is_valign con una rotazione | ribaltamento verticale sullo schermo; il posizionamento ruotava con l'immagine | specchiatura e posizionamento si leggono sullo schermo, qualunque sia la rotazione | |
| picture: trascinare l'immagine ingrandita; rotellina; immagine disattivata (anche statictext disattivato) | ue_clicked a ogni spostamento; zoom verso il centro, l'immagine poteva uscire dalla cornice; i file rilasciati restavano accettati | nessun clic dopo uno spostamento; zoom verso il puntatore, l'immagine copre sempre la cornice; disattivata, rifiuta ogni rilascio; ue_error nomina la sorgente | |
xml: una lettura (of_get_value, of_count, of_is_valid…) o una modifica dopo una costruzione | agiva sull'ultimo documento CARICATO, o su nulla | il documento costruito viene caricato e diventa IL documento; il of_start_element seguente ne inizia uno nuovo | |
xml: of_load fallito (vuoto, non valido), of_start_element dopo un caricamento | il documento precedente restava leggibile e modificabile (of_is_valid vero); un documento costruito a metà restava in of_xml | non resta nulla | |
xml: of_xml, of_pretty, of_get_values di un documento grande | tagliato senza dirlo oltre qualche MB | intero | |
xml: of_get_value di un XPath di valore (count(//line), sum(//@qty)) | vuoto | il valore come testo (3, true) | |
| xml: un XPath il cui prefisso è dichiarato sotto la radice (risposta SOAP) | vuoto senza of_register_namespace | risolto | |
xml: is_last_error dopo un XPath non valido, una pagina che non risponde, un rifiuto; codici di of_register_namespace / of_clear_namespaces | vuoto, o «no node matched» qualunque fosse la causa; le modifiche rendevano -4 quando mancava la pagina; sempre 0; una pagina senza risposta rendeva il testo null | la vera ragione; -2 quando la pagina non risponde; un URI vuoto è rifiutato (-5); vuoto anziché null | |
xml: of_pretty | perdeva CDATA, commenti, istruzioni di elaborazione e dichiarazione XML, e rimaneggiava il testo misto | tutto è conservato; un elemento che contiene testo resta su una riga | |
| xml: costruzione — a capo o tabulazione in un attributo, CR in un testo, carattere di controllo, nome non valido | riletti alterati; documento non valido; nome scritto tale e quale | riletti identici; carattere di controllo rimosso; nome rifiutato (is_last_error), elemento escluso | |
xml: un documento che contiene un elemento <parsererror>; messaggio di un XML non valido | rifiutato come non valido; messaggio incorniciato da «This page contains the following errors» | caricato; la sola riga d'errore | |
xml: of_remove di nodi annidati, della radice, di un attributo; of_set_value("/"); of_add_child sotto un attributo | contava due volte; svuotava il documento; l'attributo restava; 0 senza effetto; «parent not found» | il conteggio reale; la radice resta (0 e is_last_error); l'attributo è rimosso; -4; «the node cannot have children» | |
xml: of_close poi una lettura; ipo_owner impostato dopo la prima lettura | il documento caricato era perso; ignorato fino a of_close | il documento è conservato e ricaricato; trasmesso alla lettura seguente | |
temi metro-light e metro-dark: testo sul colore d'accento | bianco sul blu #25a0da in entrambi i temi (intestazioni dei pannelli, scheda attiva, pulsante applicazione della barra multifunzione, riquadri): poco leggibile | metro-light: l'accento diventa il blu più profondo #1b76a1, testo sempre bianco; metro-dark: l'accento resta #25a0da, il testo sopra diventa quasi nero (#1b1b1b) | |
temi office-dark, office2003-dark, office2003-light, office2007-light: colori d'accento e delle intestazioni | in modalità scura l'accento si leggeva male sulla pagina (punto del passo, badge), come il testo bianco sull'accento al passaggio del mouse e sulle intestazioni di colonna del crosstab; in modalità chiara la parte alta delle sfumature del pulsante applicazione e delle intestazioni dei pannelli era troppo pallida per il testo bianco | office-dark: accento #1178d1, passaggio del mouse #0f6cbd; office2003-dark: accento #4574cb, passaggio del mouse #2f5aa8; intestazioni del crosstab più scure al passaggio del mouse e sui totali; office2003-light e office2007-light: inizio della sfumatura più profondo (#3e73cf, #4275c5), intestazioni dei pannelli di office2007-light più opache. Testo sempre bianco, almeno 4,5:1 | |
testo su un colore scelto dall'applicazione (il_accent, colore di un elemento, intestazione di pannello, badge) | bianco fino a un colore piuttosto chiaro: un blu medio come #25a0da riceveva testo bianco a 2,95:1 | bianco o quasi nero (#1b1b1b), quello dei due che si legge meglio (rapporto di contrasto WCAG): #25a0da riceve ora testo scuro | |
jsontree: of_clear | svuotava l'albero E rimetteva ib_wrap e ib_search_enabled ai loro valori predefiniti | svuota solo l'albero; le impostazioni restano (è of_reset che rimette tutto) | |
jsontree: is_json = "" | sollevava ue_error «Invalid JSON» | svuota l'albero senza errore, come la documentazione prometteva | |
jsontree: numeri e chiavi mostrati, is_json riletto | riscritti dal motore: 12345678901234567890 mostrato 12345678901234567000, 1.10 → 1.1, la prima di due chiavi identiche persa; is_json si rileggeva compattato, e vuoto dopo un JSON non valido | come ricevuti, entrambe le chiavi comprese; is_json si rilegge esattamente come è stato impostato | |
jsontree: of_match_count, al_count di ue_search_result | contavano le RIGHE; due occorrenze su una riga erano entrambe «correnti» | contano le OCCORRENZE, una sola è corrente e of_search_next passa dall'una all'altra | |
| jsontree: blocchi aperti da una ricerca | TUTTI quelli che contenevano una corrispondenza, per sempre: cercare «e» apriva tutto il documento | solo quelli che nascondono l'occorrenza CORRENTE; of_clear_search rende le pieghe di prima della ricerca | |
jsontree: of_select_path | una riga nascosta in un blocco piegato restava invisibile; un percorso sconosciuto rendeva 0 | i blocchi che la nascondono si aprono; un percorso sconosciuto rende -5 e la selezione non si sposta | |
| jsontree: piegare il blocco che contiene la selezione | la selezione diventava invisibile, e la freccia successiva ripartiva dall'alto | la selezione passa sul blocco piegato; su un gesto dell'utente, ue_selection_changed lo dice | |
xmltree: of_clear | svuotava l'albero E rimetteva ib_wrap e ib_search_enabled ai valori predefiniti | svuota solo l'albero; le impostazioni restano (è of_reset a ripristinare tutto) | |
xmltree: is_xml = "" | sollevava ue_error «Invalid XML» e mostrava un errore rosso | svuota l'albero senza errore, come la documentazione prometteva | |
xmltree: is_xml relu | riserializzato dal motore: virgolette cambiate, a capo persi, vuoto dopo un XML non valido | si rilegge esattamente come è stato impostato, anche un testo non valido | |
| xmltree: ce qui s'affiche | un CDATA era invisibile (l'elemento appariva vuoto), commenti, istruzioni di elaborazione e dichiarazione mancavano, il testo di un contenuto misto era incollato prima dei figli, un testo privato dei suoi spazi, un valore di attributo con virgolette mostrato così com'era | ogni nodo al suo posto, nell'ordine del documento; la riga resta XML (virgoletta scelta o ", , &, <); gli spazi significativi restano | |
xmltree: of_match_count, al_count de ue_search_result | contavano le RIGHE; una corrispondenza a cavallo di due pezzi (id="4152") era contata senza essere evidenziata | contano le OCCORRENZE, ciascuna evidenziata, una sola è corrente | |
| xmltree: éléments ouverts par une recherche | TUTTI quelli che contenevano una corrispondenza, per sempre | solo quelli che nascondono l'occorrenza CORRENTE; of_clear_search rende le pieghe di prima della ricerca | |
xmltree: of_select_path | una riga nascosta in un elemento piegato restava invisibile; un percorso sconosciuto rendeva 0 | gli elementi che la nascondono si aprono; un percorso sconosciuto rende -5 e la selezione non si sposta | |
xmltree: ue_selection_changed | sollevato anche senza cambiamento (Fine sull'ultima riga); piegare l'elemento che conteneva la selezione la rendeva invisibile, in silenzio | sollevato solo quando la selezione cambia; alla piega, la selezione passa sull'elemento piegato e l'evento lo dice | |
xmltree: ue_error | il testo grezzo della pagina di errore del motore; un elemento <parsererror> del documento passava per un errore | la sola riga dell'errore («error on line N at column M: …»); un <parsererror> del documento è un elemento come un altro | |
| restclient: cookie di una richiesta sincrona | nessuno conservato: ogni of_get / of_post apriva la propria sessione; ib_keep_cookies valeva solo per l'asincrono | una sessione per oggetto, comune al sincrono e all'asincrono: un login sincrono vi mantiene connessi per le chiamate successive | |
restclient: ib_keep_cookies cambiato dopo la prima richiesta | senza effetto fino a of_close | applicato subito; a false, i cookie già conservati vengono dimenticati | |
| restclient: reindirizzamento verso un altro host o porta | cadevano solo Authorization, Cookie e l'autenticazione Basic: una chiave API (X-Api-Key…) partiva verso il terzo | nessuna intestazione impostata con of_set_header segue, resta solo Content-Type | |
restclient: of_set_bearer("") dopo of_set_basic; of_set_basic poi of_set_bearer; of_set_basic("", "") | la password Basic continuava a partire; due Authorization insieme; Basic Og== inviato | una sola autenticazione alla volta: ciascuna sostituisce l'altra, un token o un utente vuoto la rimuove | |
restclient: HEAD, o risposta 204 / 304 che annuncia una dimensione | -4 «connection lost», e ripetuta in asincrono | lo stato (200, 304…) | |
restclient: corpo con un byte non valido; charset=iso-8859-1 o utf-16 | tutto il corpo riletto in Windows-1252; charset ignorato | solo il byte non valido diventa un carattere sostitutivo; il charset annunciato viene letto | |
| restclient: corpo di testo di diverse centinaia di MB | tenuto tre volte in memoria: un processo a 32 bit poteva morire | -4 «body too large : use of_download» oltre 64 MB | |
| restclient: cento richieste asincrone lanciate in una volta | cento thread in parallelo | al massimo sei insieme, le successive attendono il loro turno | |
| restclient: una richiesta asincrona inviata più spesso che ogni 50 ms (un timer di telemetria) | nessuna risposta consegnata finché durava il flusso | le risposte arrivano man mano | |
restclient: of_cancel di un id sconosciuto; di una richiesta la cui risposta è arrivata | -1; 0 (ma arrivava ue_response) | -5; -4, troppo tardi | |
restclient: of_response_text() dopo of_download; dopo un of_download(url, "") | il numero di byte scritti; la risposta precedente | vuoto: quel corpo è nel file; vuoto | |
restclient: leggere una risposta asincrona durante ue_progress | una memoria in scrittura: crash possibile | vuoto, of_status(id) = 0 finché la richiesta è in corso | |
video: cambiare film (is_source, of_play(source)) | il segmento, i sottotitoli, i marcatori e i capitoli del vecchio film restavano | se ne vanno con lui (impostati prima di ogni film, aspettano il primo); un film della playlist conserva i suoi sottotitoli. Impostali dopo is_source | |
video: of_go_chapter, of_next_chapter, of_previous_chapter | sollevavano ue_seeked; of_go_chapter oltre il numero di capitoli rendeva 0 senza fare nulla | ue_seeked e ue_chapter_changed, come un clic sulla barra; -5 | |
video: of_add_source mentre un is_source è impostato | la playlist non partiva mai, of_next andava al primo film | la prima voce si carica subito (a meno che il film impostato STIA SUONANDO: la playlist lo segue alla sua fine) | |
video: ue_started dopo of_stop o la fine del film, poi of_play | mai: una volta per sorgente | a ogni nuova riproduzione (non alla ripresa da una pausa) | |
video: of_play su un film in errore; of_reset; ii_rate al film successivo | «in corso» per sempre, senza evento; il vecchio film restava caricato (of_duration, of_capture); ritorno alla velocità normale | di nuovo ue_failed; il film viene scaricato; la velocità resta | |
video: of_capture verso un file non scrivibile; verso «\x» o «C:x» | -4 (la doc diceva -5); scritti secondo la cartella corrente | -4, e non resta alcun file troncato; -5: dai un percorso completo | |
| video: schermo intero poi Alt+Tab verso un'altra applicazione | il film restava sopra tutto | l'altra applicazione passa davanti; tornare alla tua rimette il film sopra tutto | |
| pdfviewer: un clic semplice su un link del PDF | niente: solo Ctrl+clic sollevava ue_link_clicked | ue_link_clicked(url), il documento resta visualizzato | |
webbrowser: una pagina data: (is_address = "data:text/html,…") | visualizzata, ma nessun ue_load_completed | ue_load_completed con l'indirizzo richiesto | |
webbrowser: una nuova finestra chiesta dal sito verso file:, data: o mailto: | aperta nella vista, ue_new_window sollevato | rifiutata: ue_error, nessun ue_new_window; si aprono solo http e https | |
| webbrowser: un sito che chiede la fotocamera, il microfono, la posizione, le notifiche | richiesta del browser all'utente, risposta memorizzata | rifiutato a meno che ue_permission_requested restituisca true; nulla viene memorizzato | |
| webbrowser: cookie, sessioni e archiviazione dei siti | nel profilo condiviso con i componenti | in un profilo di navigazione a parte: una sessione aperta in 3.0 non viene ripresa (riconnettersi una volta); of_clear_browsing_data la cancella | |
webbrowser: is_search_url senza %s, senza http(s):// o in javascript: | accettato: ogni ricerca falliva o perdeva il testo digitato | rifiutato: ue_error, il motore in vigore resta | |
webbrowser: gestion/ o [::1]/x in is_address | «non è un indirizzo» (o una ricerca) | https://gestion/, https://[::1]/x; la parola da sola resta testo | |
webbrowser: clic destro su una selezione, un collegamento, un'immagine con ib_context_menu | solo Indietro / Avanti / Ricarica | in più: Copia, Apri collegamento, Copia indirizzo collegamento, Copia immagine | |
tab: scheda chiudibile disattivata (ib_enabled = false) | la croce spariva ma il suo spazio restava vuoto | né croce né spazio vuoto: la scheda è larga come una non chiudibile | |
video: of_chapters su un titolo che contiene ` | ` o una tabulazione | spezzato in due capitoli | letto così com'è |
video: un .srt in Windows-1252 o UTF-16 | accenti illeggibili; nessun sottotitolo | letto correttamente | |
commandpalette: of_open senza runtime WebView2; toaster: of_show senza runtime | -1 | -6, come la finestra di messaggio | |
crypto, xml, restclient: of_open quando la pagina o il client non può nascere | il codice grezzo della DLL (-1, -3…) | -2, e is_last_error dice perché |
Se aveva aggirato uno di questi difetti — per esempio gestendo ue_menu_selected con un indirizzo vuoto per recuperare i clic di un gruppo ripiegato —, tolga l'aggiramento: l'evento documentato ora arriva.
11.4 Il generatore n_pbt_menu2ribbon #
Nella 3.0 il codice scritto da n_pbt_menu2ribbon usava metodi di handle che non esistevano più: non compilava senza ritocchi. Nella 4.0 scrive l'API attuale — ogni aggiunta tramite il suo indirizzo, dal componente —, riprende i sottomenu a qualsiasi profondità, conserva le voci disattivate e spuntate, e il suo router copre ue_clicked, ue_toggled e ue_menu_selected. Le chiavi cambiano: ognuna è ora il ClassName della voce di menu (m_fichier/g1/m_ouvrir) invece del percorso puntato (m_principal.m_fichier.m_ouvrir).
La ricetta: una barra già costruita a mano, o da un codice generato e poi corretto, non ha nulla da cambiare. Per ripartire dal generatore, lo rilanci e incolli anche il nuovo router: il vecchio leggeva chiavi puntate.
11.5 Ciò che è stato aggiunto #
Nulla di quanto segue chiede di modificare il codice. I nuovi componenti della 4.0 sono presentati nelle note di versione.
| Oggetto | Aggiunto |
|---|---|
| ribbon | of_add_menu_separator accetta l'indirizzo di una voce: la riga va nella cascata sotto di essa |
| ribbon | of_add_menu_item e of_add_menu_check accettano una cascata di qualsiasi profondità, e ogni livello si pilota con of_menu_item(indirizzo) |
| menubar | of_add_separator accetta l'indirizzo di una voce (file/export): la linea va nella sua cascata; of_menu(...) porta i colori (il_accent, il_back_color…) e il tooltip del titolo |
| crosstab | of_set_label_filter(as_field, as_type, as_a, as_b) su testo (LABEL_CONTAINS, LABEL_BEGINS, LABEL_ENDS) e le costanti LABEL_GT, LABEL_LT, LABEL_BETWEEN: la forma con due double poteva passare solo un numero |
| crypto | KEYFORMAT_TEXT, KEYFORMAT_HEX, KEYFORMAT_BASE64 e un sovraccarico di of_hmac, of_jwt_sign e of_jwt_verify che li prende (una chiave in BYTE: segreto fornito codificato, AWS SigV4); un'entropia facoltativa per of_protect e of_unprotect |
| crypto | of_hmac_verify (un HMAC ricevuto — webhook — confrontato in tempo costante); of_jwt_header e un overload di of_jwt_sign che aggiunge membri all'intestazione (kid); of_totp_verify(…, ref al_step), il passo accettato, per rifiutare un codice già usato; il_password_hash_rounds |
| messagebox | of_get_last_error(): perché l'ultima finestra non ha potuto aprirsi (stringa vuota se si è aperta) |
| n_pbt_utils | of_dir_has_subfolders(as_dir, ab_include_hidden): la stessa domanda, contando anche le cartelle nascoste, di sistema e le giunzioni |
| n_pbt_utils | of_dw_date_order(): l'ordine in cui un DataWindow scrive una data su questa postazione (dmy, mdy, ymd) |
| speechout | of_is_paused(): vero finché la lettura è in pausa |
| Testo ricco | il tag [symbol=nome]: diciotto glifi monocromi che seguono il colore del testo (capitolo 4) |
| toolbar | of_menu_item(indirizzo) → n_pbt_toolbar_menu_item: ogni voce di menu a discesa ha il proprio stato (ib_enabled, ib_visible, ib_checked, is_text, is_shortcut), designata dal suo indirizzo completo |
| toolbar | is_date su un selettore di data; of_clear_menu; of_remove_item di una voce di menu; of_add_menu_separator su una voce (cascata); cascate di qualsiasi profondità |
| pdfviewer | ue_load_failed(as_source, as_reason) e le costanti REASON_*; ue_link_clicked(as_url); gli indirizzi file:///; ib_allow_save e ib_allow_print: i comandi Salva e Stampa della barra del lettore |
| picture | is_alt_text (testo alternativo letto da un lettore di schermo); una tastiera per lo zoom: +, -, 0 e le frecce per spostarsi; n_pbt_utils.of_json_get_str_array |
| webbrowser | is_search_url (motore di ricerca per le parole che non sono un indirizzo); ib_veto_new_window e ue_new_window; ib_veto_downloads e ue_download_starting; ue_load_failed; ue_error; of_show_html; of_clear_browsing_data e ib_private; ib_veto_navigation e ue_navigating; is_title e ue_title_changed; ue_permission_requested e le costanti PERMISSION_*; le costanti LOADSTATUS_* di ue_load_failed; F5, Ctrl+R, Alt+frecce ed Esc nella barra degli indirizzi |
| jsontree | of_selected_text rende il valore DECODIFICATO della foglia selezionata (una stringa senza virgolette né escape); of_has_selection distingue la radice, il cui percorso è "", da «niente selezionato»; la tastiera salta le graffe di chiusura (non si selezionano più) |
| xmltree | ogni attributo è un bersaglio: un clic dà il suo percorso (/order/@id), of_select_path lo seleziona, of_selected_value rende il suo valore; un documento grande disegna solo le righe a schermo (8.000 elementi fratelli: 12 s → 0,15 s, una freccia in pochi ms) |
| video | ue_muted_changed(ab_on): l'utente ha tolto o ridato il suono (l'altoparlante della barra, il tasto M), come volume e velocità avevano già il loro evento |
| ribbon | of_remove_menu_item, of_clear_menu, of_remove_combo_item, of_clear_combo, of_remove_gallery_item, of_remove_app_menu_item, of_remove_contextual_group: le rimozioni sotto un controllo — un elenco «File recenti» si aggiorna senza ricreare il controllo |
| ribbon | of_app_menu_item(indirizzo): l'handle di una voce del menu applicativo (is_label, is_image, ib_enabled, ib_checked, ib_visible); of_app_menu_item("") percorre il menu |
| ribbon | tasti di accesso rapido di più lettere (is_keytip = "FP"), digitate una dopo l'altra; nomi accessibili (barra di accesso rapido, tessere) per i lettori di schermo |
| toolbar | of_add_split_button: un pulsante diviso (azione + menu); is_group: interruttori esclusivi (allineamento); is_image su uno strumento e su una voce di menu; ue_item_rclicked(indirizzo): il clic destro su uno strumento |
11.6 Nomi e conteggi allineati al resto della libreria #
Sette punti parlavano diversamente dal resto della libreria. La 4.0 li allinea invece di mantenere lo scarto: due nomi cambiano — il compilatore Le mostra ogni riga da riprendere —, il percorso reso dall'albero JSON diventa quello di n_pbt_json, quello dell'albero XML sotto uno spazio dei nomi predefinito un XPath che funziona, due conteggi partono ora da 1, come ogni posizione del prodotto, e un evento ambientale diventa facoltativo. Sono gli unici cambiamenti della 4.0 che chiedono di ritoccare codice che compilava.
| Cosa | 3.0 | 4.0 |
|---|---|---|
| progressbar: limiti della scala | il_minimum, il_maximum, dei long | id_minimum, id_maximum, dei double: una scala 0..1 o un numero di byte oltre 2 GB è valido; il prefisso dice il tipo |
| json: indice di array in un percorso | da 0: lines/0 è la prima riga | da 1: lines/1 è la prima riga; lines/0 non designa nulla — una lettura lo trova assente, una scrittura rende -5 |
jsontree: percorso di un nodo (ue_node_clicked, ue_selection_changed, of_selected_path, of_select_path) | livelli uniti da un punto, indice di array da 0: lines.0.sku — un dialetto che n_pbt_json non leggeva | il percorso di n_pbt_json: livelli uniti da /, indice da 1 (lines/1/sku), "" per la radice — da passare così com'è a of_get_string sullo stesso testo |
xmltree: percorso di un elemento sotto uno spazio dei nomi PREDEFINITO (xmlns="urn:…") | /Envelope/Body — un XPath che non trova nulla | /*[local-name()='Envelope']/*[local-name()='Body'] — da passare così com'è a n_pbt_xml.of_get_value; un elemento senza spazio dei nomi o con prefisso mantiene il suo percorso |
toolbar: band e index della disposizione (of_get_layout, of_set_layout, ue_layout_changed) | da 0, una stringa detta «opaca» mentre ii_band, ii_index e ue_bar_reordered contavano da 1 | da 1, come ii_band, ii_index e ue_bar_reordered; un'andata e ritorno lettura → ripristino rende la stessa stringa |
statictext: ue_cycle | sollevato a ogni ciclo dello scorrimento, senza sottoscrizione — e anche da un'animazione all'interno del testo | un evento ambientale, quindi facoltativo: sollevato solo quando ib_track_cycle = true, come ue_mouse_enter con ib_track_mouse; solo a ogni passaggio completo del testo |
tilesbox: 2° argomento di ue_tile_moved | as_to_keys, mentre porta UNA chiave: il gruppo di destinazione | as_to_key: il nome dice ciò che porta, come ovunque altrove (as_key = un livello, as_keys = un indirizzo) |
restclient: ue_failed | ue_failed (long al_id, string as_error) | ue_failed (long al_id, long al_code, string as_error): -4 fallimento, -5 URL o file — non serve più analizzare il testo |
restclient: of_json_value | una chiave, prima occorrenza a qualsiasi profondità; solo un valore testo — un numero restituiva il nome della chiave seguente | un percorso n_pbt_json ("json/customer", "items/1/qty"), qualsiasi valore: "4152", "true". Una chiave annidata si nomina con i suoi genitori |
La ricetta: (1) ricompili — il compilatore segnala il_minimum, il_maximum e as_to_keys: li rinomini id_minimum, id_maximum e as_to_key; (2) cerchi i percorsi json che puntano a un array e aggiunga 1 a ogni indice — un ciclo for i = 0 to n - 1 su "lines/" + String(i) diventa for i = 1 to n; (3) una disposizione di toolbar salvata dalla 3.0 conta da 0: aggiunga 1 a band e index di ogni barra prima di passarla a of_set_layout, oppure lasci che l'utente riorganizzi una volta — riletta così com'è, metterebbe insieme le prime due bande; (4) dove ue_cycle è scriptato, imposti ib_track_cycle = true alla costruzione; (5) dove leggeva un percorso dall'albero JSON (ue_node_clicked, of_selected_path) o ne passava uno (of_select_path), sostituisca i punti con / e aggiunga 1 a ogni indice di array — lines.0.sku diventa lines/1/sku, che va così com'è a n_pbt_json.of_get_string.
11.7 I temi seguono l'applicazione #
La revisione dei temi ha fatto rispettare a ogni componente la regola che il capitolo 4 già annunciava: l'applicazione decide tema e accento, un componente se ne discosta solo per ciò che gli si chiede. Nessun metodo è rinominato; ciò che cambia si vede a schermo, rileggendo le proprietà e in due codici di ritorno.
| Cosa | 3.0 | 4.0 |
|---|---|---|
PBT_SetDefaultTheme | cambiare tema cancellava l'accento impostato con PBT_SetDefaultThemeAccent — anche reimpostando lo stesso tema — e appiattiva lo sfondo sfumato di office2007 e office2003 | l'accento dell'applicazione resta da un tema all'altro; ogni tema conserva il suo sfondo |
PBT_GetDefaultThemeAccent | l'accento del tema quando l'applicazione non ne aveva impostato alcuno | -1 finché l'applicazione non ha impostato un accento |
| codici di ritorno nativi | PBT_SetDefaultTheme con un nome sconosciuto restituiva 0 e lasciava i componenti successivi senza tema; PBT_SetDefaultThemeAccent con un colore di sistema PowerBuilder lo dipingeva di nero | -5 in entrambi i casi; il tema o l'accento precedente resta |
| un asse di tema impostato da solo | congelava l'altro asse sul tema dell'applicazione del momento | l'asse vuoto segue il tema dell'applicazione a ogni suo cambio; entrambi gli assi vuoti = interamente il tema dell'applicazione |
is_theme_style · is_theme_mode · il_theme_accent | si rileggevano "", "" e -1, qualunque cosa fosse stata impostata | lo stile e la modalità mostrati, e l'accento proprio del componente (-1 se non ne ha) |
un valore d'asse sconosciuto ("office2010") o scritto male (" Metro ") | il componente perdeva il suo tema e non ascoltava più quello dell'applicazione fino all'of_reset() | spazi e maiuscole ignorati; un valore sconosciuto viene ignorato e l'asse conserva il suo valore |
| accento di un componente con tema locale | conservava l'accento del suo tema, anche quando l'applicazione ne impostava uno | segue l'accento dell'applicazione finché non ne ha uno proprio |
| un accento personalizzato | cambiava solo l'accento: passaggio e pressione dei pulsanti d'accento, selezioni tinte, pulsanti spuntati della barra multifunzione conservavano l'accento del tema | tutto ciò che deriva dall'accento lo segue |
tilesbox : il_badge_color | 0 e -1 = il colore del tema; riletto 0 senza colore impostato; il nero era irraggiungibile | -1 = il colore del tema (riletto -1); 0 è il nero, come per tutti i colori |
un colore di sistema PowerBuilder (ButtonFace…) in il_theme_accent | dipinto di nero | contato come -1: l'accento dell'applicazione |
webbrowser · pdfviewer | il contenuto di terzi seguiva la modalità chiara/scura di Windows, e un rettangolo bianco precedeva la sua prima visualizzazione | segue il tema predefinito dell'applicazione, sullo sfondo del tema (4.11) |
| accento di office-dark e office2003-dark | un blu scuro, leggibile a 3:1 quando colorava un testo (link, [accent]) | un blu più chiaro (#479ef5, #7ea1e8), con un testo scuro sopra |
datagrid: filetti tra le righe | assenti in otto temi su dieci | presenti nei dieci temi, nel colore della griglia del tema |
| contrasto elevato di Windows | le icone monocromatiche e gli anelli disegnati come ombra sparivano | supportato (4.10) |
La ricetta: (1) se reimpostava l'accento dopo ogni PBT_SetDefaultTheme, non serve più — e se contava su un cambio di tema per cancellare l'accento, chiami PBT_SetDefaultThemeAccent(-1); (2) verifichi il codice di ritorno di PBT_SetDefaultTheme quando il nome viene da un input o da un file; (3) dove impostava i due assi su ogni componente per seguire l'applicazione, li lasci vuoti; (4) una casella il cui badge tornava «al tema» con il_badge_color = 0 si scrive ora -1.
11.8 crypto: cosa rifiuta ora la sicurezza, e dove vanno i percorsi relativi #
La revisione di sicurezza di crypto chiude una porta reale — un JWT falsificato con la chiave PUBBLICA passava quando l'algoritmo mancava — e sostituisce diversi silenzi con un rifiuto che dice la sua ragione. Nessun metodo è rimosso; una firma ECDSA cambia forma, e i percorsi relativi dei file seguono una sola regola.
| Cosa | 3.0 | 4.0 |
|---|---|---|
of_jwt_verify, of_jwt_sign | un algoritmo VUOTO valeva JWT_HS256, e una chiave PEM era accettata come segreto HS256: verificato con la chiave PUBBLICA come segreto, un token falsificato passava; l'algoritmo dell'intestazione si confrontava senza maiuscole, un'intestazione crit era ignorata | l'algoritmo è OBBLIGATORIO e confrontato ESATTAMENTE; una chiave PEM non è mai un segreto HMAC (anche of_hmac); crit è rifiutato — stringa vuota e is_last_error |
of_jwt_sign | un exp fornito nei claims era sostituito in silenzio dalla durata al_expires_seconds | entrambi insieme sono rifiutati: tieni l'uno o l'altro |
of_encrypt, of_decrypt | una password VUOTA cifrava — chiunque rileggeva il valore | rifiutata, come già faceva of_encrypt_file; of_password_hash("") resta permesso |
il_pbkdf2_rounds | un valore fuori da 1.000 a 10.000.000 ricadeva in silenzio su 100.000 | la chiamata è RIFIUTATA: stringa vuota per un testo, -5 per un file, e is_last_error dice i limiti |
of_password_hash | il_pbkdf2_rounds (100.000 round) | il_password_hash_rounds, 600.000 per impostazione predefinita (la cifra OWASP); i valori già memorizzati portano i loro round e si verificano ancora |
of_base64_decode, of_base64url_decode, of_hex_decode, of_decrypt… | byte che non sono un testo (un PDF, un'immagine) tornavano come caratteri di sostituzione, senza errore | stringa vuota e is_last_error, che rimanda a of_base64_decode_to_file o of_decrypt_file |
of_sign (chiave EC) | una firma IEEE-P1363 (64 byte), che openssl dgst e Java rifiutano | una firma DER; of_verify legge entrambe le forme, una firma già memorizzata si verifica ancora; il JWT ES256 resta in P1363 |
of_totp_code, of_totp_verify | un carattere non base32 nel segreto (uno 0 digitato per una O) era tolto in silenzio: un ALTRO segreto, codici che non corrispondevano mai | rifiutato (spazi e = tollerati) |
of_encrypt_file | « qualunque sia la dimensione » | fino a 64 GB, il limite di un contenitore AES-GCM: oltre, -7 |
percorsi relativi: n_pbt_crypto, u_pbt_zip, of_capture del lettore video | letti nella cartella CORRENTE (che si sposta dopo un DirList o una finestra di file), scritti accanto all'EXE (nell'IDE: la cartella di PowerBuilder) | LETTI nella cartella corrente, poi nella cartella in cui l'applicazione è partita, poi accanto all'EXE; SCRITTI nella cartella in cui l'applicazione è partita — la stessa nell'IDE e compilata |
La ricetta: (1) passa SEMPRE l'algoritmo di un JWT come costante (n_pbt_crypto.JWT_RS256), mai letto dal token né da un INI a cui può mancare; (2) se un server verificava le tue firme EC in P1363 (.NET VerifyData per impostazione predefinita), convertile o verificale in DER (DSASignatureFormat.Rfc3279DerSequence); (3) un il_pbkdf2_rounds impostato fuori limiti deve tornare tra 1.000 e 10.000.000; (4) un file che un percorso relativo scriveva accanto all'EXE ora si trova nella cartella di avvio dell'applicazione — dai un percorso completo se ne vuoi un altro.
11.9 restclient: intestazioni che dicono il loro rifiuto, reindirizzamenti che conservano la richiesta #
La revisione di restclient sostituisce due perdite silenziose — una modifica mai fatta dietro un reindirizzamento, un'autenticazione mai inviata dietro un'intestazione malformata — con il comportamento giusto o un rifiuto che dice la sua ragione. Nessun metodo è rimosso; tre diventano funzioni, arrivano due proprietà, e l'autenticazione Windows parte solo se la chiedi. Un punto vale per i cinque componenti non visuali che sollevano eventi: un errore nel tuo codice di evento ora si vede.
| Cosa | 3.0 | 4.0 |
|---|---|---|
of_set_header, of_set_bearer, of_set_basic | subroutine: nulla era restituito, un valore malformato era tenuto così com'era | funzioni long: 0, oppure -5 e nulla cambia — nome vuoto, nome con uno spazio, due punti o un carattere di controllo, valore con un a capo; un valore vuoto rimuove l'intestazione |
| una richiesta con un'intestazione malformata | partiva SENZA ALCUNA intestazione — Authorization compresa —, senza errore | -5, e is_last_error = «invalid header: <nome>»; nulla parte |
| reindirizzamento 301 / 302 di un PUT, PATCH o DELETE | ripartiva in GET senza corpo: la modifica non veniva mai fatta, e la chiamata restituiva 200 | metodo e corpo conservati; solo un POST diventa GET; un 303 riparte in GET senza corpo (tranne HEAD) |
| una connessione riutilizzata (quella di un reindirizzamento) che il server chiude nello stesso istante | -4 e «request failed: 12152», di tanto in tanto | la richiesta viene rinviata UNA volta, corpo compreso, su una connessione nuova: il server non vi aveva risposto nulla |
of_response_text ( ), of_response_headers ( ), of_response_header, of_json_value | l'ultima risposta sincrona del PROCESSO: un secondo n_pbt_restclient la sovrascriveva | quella dell'OGGETTO; of_close la dimentica |
| corpo letto come testo, applicazione a 32 bit | limitato a 64 MB | limitato a 16 MB (64 MB a 64 bit): oltre, -4 «body too large» — leggilo con of_download |
of_get_async, of_request_async… su un URL o un'intestazione non validi | un id di richiesta, poi un ue_failed | -5 subito, nessun evento segue; is_last_error dice perché («invalid URL: …») |
| autenticazione Windows (Negotiate / NTLM) | il sistema rispondeva da solo alla sfida di un server dell'intranet con le credenziali della sessione | disattivata per impostazione predefinita: le credenziali non vanno a nessun server senza ib_windows_auth = true (proprietà nuova); is_client_certificate (nuova) imposta un certificato client |
of_cancel (long al_id), of_status (long al_id), of_response_text (long al_id)… | l'id di una richiesta di un ALTRO oggetto raggiungeva quella richiesta | solo le richieste dell'oggetto: of_cancel restituisce -5 e non annulla nulla, i lettori restituiscono 0 / "" |
of_status (long al_id) in ue_failed | poteva restituire 200: lo stato di una risposta ricevuta e poi persa | 0 per ogni richiesta fallita |
ue_failed | -4 fallimento, -5 URL o file | -4 fallimento, -5 file o certificato client, -6 richiesta di intervallo rifiutata in demo |
errore di esecuzione in un evento dell'applicazione — restclient, speechout, soundplayer, toaster, commandpalette | inghiottito senza una parola, e gli eventi successivi non erano più consegnati | risale all'evento SystemError dell'applicazione come ogni errore di script; gli eventi successivi sono consegnati |
il_max_retries | ripeteva anche un fallimento che si ripete identico (troppi reindirizzamenti, reindirizzamento non valido o HTTPS → HTTP, TLS, file impossibile da scrivere) | quei fallimenti non vengono più ripetuti; 429, 503 e un guasto di rete sì |
| URL e percorsi | il frammento #… partiva al server; una Location relativa ?page=2 perdeva l'ultimo segmento; un percorso relativo di of_download seguiva la cartella corrente del momento | il frammento non viene più inviato; Location risolta come fa un browser (RFC 3986); un percorso relativo è risolto alla chiamata, nella cartella corrente dell'applicazione al caricamento della libreria |
La ricetta: (1) verifica il ritorno di of_set_header, of_set_bearer e of_set_basic quando il valore viene da un input, da un INI o da un database — una chiamata che ignora il ritorno compila ancora, ma il -5 è ora l'unica traccia di un'intestazione rifiutata; (2) un'API dell'intranet con autenticazione Windows che rispondeva 200 ora risponde 401: imposta ib_windows_auth = true su QUEL client; (3) un'applicazione a 32 bit che legge come testo un corpo oltre 16 MB passa a of_download; (4) se condividevi un id di richiesta tra due oggetti, leggi la risposta sull'oggetto che l'ha inviata; (5) un errore che ora appare in SystemError da ue_response o ue_failed esisteva già: veniva inghiottito.
11.10 speechout: impostazioni vive, una distruzione silenziosa #
La revisione di speechout mantiene due promesse che la documentazione faceva e il codice no — un'impostazione cambiata durante una lettura vale per la frase successiva, of_speak_from oltre il testo restituisce -5 — e toglie un evento sollevato al momento sbagliato. Nessun metodo è ritirato. Aggiunti: of_add_abbreviation, of_clear_abbreviations, l'evento ue_mark e due tag, [mark=nome] e [rate=150]…[/rate].
| Cosa | 3.0 | 4.0 |
|---|---|---|
of_speak_from (al_index) | oltre il testo, la lettura in corso veniva TAGLIATA, non ripartiva nulla, e il ritorno era 0 | -5, e la lettura in corso continua |
ii_rate, ii_pitch, ii_volume, is_lang, is_voice | cambiati durante una lettura, presi solo alla lettura SUCCESSIVA (la documentazione prometteva la frase successiva) | proprietà vive: la frase successiva le prende |
ue_voice_fallback | muto quando mancava solo la REGIONE (fr-CA richiesto, voce fr-FR) | sollevato; i tag di lingua si confrontano senza maiuscole, e fr_FR vale fr-FR |
destroy (n_pbt_speechout) | durante una lettura, sollevava ue_stopped — su una finestra già mezzo distrutta | nessun evento; of_close() solleva sempre ue_stopped |
of_sentence_count, of_count | il conteggio del testo letto la volta PRECEDENTE (0 prima di ogni lettura) | il conteggio di is_text così com'è |
of_pause, of_resume, of_clear_queue | creavano la voce quando non esisteva; una pausa durante l'attesa delle voci andava persa | 0 senza creare nulla, -4 se la pagina non ha risposto; la pausa tiene fino a of_resume |
ue_sentence (al_index) | un'abbreviazione (Mr., Dr., e.g.), un indirizzo compitato o una versione tagliavano la frase; un testo senza punto era una sola frase | non tagliano più; una frase di oltre 250 caratteri viene tagliata: i numeri di frase possono cambiare |
[pause=ms] | ignorata alla FINE del testo | un silenzio dopo l'ultima frase, prima di ue_stopped |
La ricetta: (1) verifica il -5 di of_speak_from quando l'indice viene da un clic; (2) se il tuo ue_stopped faceva qualcosa alla chiusura della finestra, chiama tu of_close() nel suo close — la distruzione non lo solleva più; (3) non conservare i numeri di frase da una versione all'altra: prendili da ue_sentence, come la documentazione ha sempre detto.
11.11 statictext e testo formattato: una marcatura letta da sinistra a destra #
La revisione di statictext ha corretto soprattutto il testo con tag comune (4.7): queste righe valgono per l'etichetta di ogni componente — titolo di scheda, pannello della barra di stato, toast, finestra di dialogo. Nessun metodo è ritirato. Aggiunto: of_refresh_parent_color(), e le aree [action], [hyperlink] e le intestazioni di [foldarea] di uno statictext si raggiungono da tastiera (Tab, poi Invio o Spazio).
| Cosa | 3.0 | 4.0 |
|---|---|---|
of_escape_markup (une donnée collée à une balise) | un ] protetto subito dopo un tag faceva coppia con il ] del tag: "[b]" + of_escape_markup("] fine") + "[/b]" mostrava [b]] fine senza grassetto | il dato si mostra così com'è, e la formattazione attorno regge |
[/b], [/i]… | un tag di chiusura chiudeva l'ULTIMO tag aperto, qualunque fosse: [b]A[i]B[/b]C lasciava C in grassetto; anche [/br] chiudeva qualcosa | un tag di chiusura chiude solo il proprio tag (gli stili aperti all'interno continuano); un tag di chiusura senza apertura, o quello di un tag autochiudente, viene ignorato |
[picture=…] | tagliata alla prima virgola: un data URI (ciò che restituisce of_icon()) o un nome di file con una virgola non si mostrava | le dimensioni si leggono alla fine del valore: entrambi si mostrano |
[picture=\\server\share\x.png] | l'immagine veniva letta sulla condivisione di rete | rifiutata: un'immagine della marcatura non va mai a cercare una condivisione di rete. Passi per of_icon(), che la incorpora, o per un picture |
[hyperlink=HTTPS://…] | uno schema in maiuscolo non veniva aperto | aperto: lo schema si legge senza distinzione di maiuscole; l'elenco resta http, https, mailto |
ii_padding | 0 = il margine del tema: un'etichetta non poteva mai allinearsi al bordo di un campo vicino | -1 = il margine del tema (nuovo predefinito), 0 = nessun margine |
ue_clicked, ue_double_clicked | sollevati ripiegando un [foldarea] (tre eventi per un doppio clic), e rilasciando il mouse dopo una selezione di testo | non più sollevati: ripiegare è una questione di lettura |
[foldarea:… [action=…]] | sollevava ue_action E ripiegava il blocco | solo ue_action, il blocco resta com'è |
ii_line_spacing, is_marquee_direction | un valore fuori da 50-400 veniva ignorato e riletto 0; un senso sconosciuto ("UP") scorreva verso l'inizio ma si rileggeva così com'era scritto | riportato al limite più vicino, riletto così come applicato; un senso sconosciuto vale e si rilegge MARQUEE_START |
of_scroll_to_end | non restituiva nulla | restituisce 0, o -2 se il componente non è creato |
La ricetta: (1) un ii_padding = 0 scritto per dire «il margine del tema» diventa -1 — o sparisce; (2) un'immagine della marcatura posta su una condivisione di rete passa per of_icon(); (3) un ue_clicked che reagiva al ripiegamento di una sezione non sarà più chiamato: il ripiegamento non si programma.
11.12 breadcrumb: cosa cede quando il percorso non ci sta, e lasciare il campo #
La seconda revisione del filo di Arianna (breadcrumb) ha corretto il ripiegamento per larghezza, la modalità OVERFLOW_SHRINK e ciò che un segmento porta con sé. Nessun metodo è ritirato. Una riga vale per tutti i menu nativi della libreria: la ricerca digitando.
| Cosa | 3.0 | 4.0 |
|---|---|---|
of_edit() sans / without ib_editable | restituisce 0, non si apre nulla | restituisce -4 |
| lasciare il campo del percorso per un altro controllo dell'applicazione | il campo restava aperto, testo digitato a metà, e nulla era riportato | un testo modificato viene convalidato: ue_path_entered; passare a un'altra applicazione conserva sempre la digitazione |
OVERFLOW_SHRINK | ogni etichetta limitata a 12 caratteri, anche con spazio; il luogo corrente tagliato netto al bordo della barra | nulla viene tagliato finché c'è spazio; il centro cede per primo, fino a una lettera e …, il primo segmento e il luogo corrente per ultimi |
OVERFLOW_COLLAPSE | l'etichetta del luogo corrente poteva essere troncata prima che il centro si ripiegasse | il centro si ripiega per primo; il luogo corrente si tronca solo come ultima risorsa |
of_insert_item(…, ai_index) | gli handle dei segmenti spostati designavano un altro segmento, i loro colori e tooltip restavano al vecchio indirizzo | i loro handle vengono rilasciati, i loro colori e tooltip li seguono; un segmento rimosso (of_clear, of_truncate, of_remove_item) porta via i propri |
of_item("b").il_back_color / of_item("a/b").il_back_color | due valori per lo stesso segmento | uno solo: la chiave unica e l'indirizzo designano lo stesso segmento |
OVERFLOW_SCROLL, rotellina | senza effetto | fa scorrere la striscia |
| i menu nativi (rami del filo, barra multifunzione, barra dei menu, barra degli strumenti, menu contestuale): una lettera digitata | non faceva nulla, mnemonici a parte | le lettere digitate entro un secondo saltano alla prima voce che comincia così («Win»), come nell'esplora risorse; un menu di oltre 500 voci disegna solo ciò che si vede |
La ricetta: (1) un of_edit() di cui verificava lo 0 senza aver impostato ib_editable restituisce ora -4; (2) un ue_path_entered può arrivare quando l'utente clicca altrove nella finestra — è lo stesso testo che con Invio; (3) dopo un of_insert_item in mezzo al filo, richieda gli handle dei segmenti che seguono.
11.13 buttonbar e tastiera della finestra: il tasto va al componente del focus #
La seconda revisione della barra di pulsanti (buttonbar) ha toccato la tastiera della finestra, condivisa da tutti i componenti che rispondono a Invio, Esc, una lettera Alt o una scorciatoia registrata (button, buttonbar e le scorciatoie di of_register_shortcut di tutti i componenti). Nessun metodo è ritirato; uno è aggiunto, of_focus_button.
| Cosa | 3.0 | 4.0 |
|---|---|---|
| due componenti della stessa finestra rispondono a Invio, Esc o alla stessa scorciatoia (due fogli MDI, due pannelli) | la riceveva il primo creato, anche nell'altro foglio | il più vicino al focus (stesso foglio, stesso pannello); a parità, nessuno: il tasto resta alla finestra |
Invio su un CommandButton PB che ha il focus, o in una DropDownListBox aperta; Esc in una lista aperta | attivava il pulsante predefinito / annulla del componente | resta al controllo, come in una finestra di dialogo di Windows |
of_register_shortcut(chord, key) su un pulsante della barra, poi il pulsante disabilitato e riabilitato, o la sua lettera is_shortcut cambiata | la scorciatoia veniva cancellata | mantenuta: la lettera Alt e la scorciatoia dell'applicazione non si toccano più |
| la lettera Alt di un pulsante di fronte a una scorciatoia esplicita dello stesso tasto | vinceva il primo registrato | vince la scorciatoia esplicita; le lettere sono consultate solo dopo |
of_clear_shortcuts() | cancellava anche l'is_shortcut di un button | cancella solo le scorciatoie dell'applicazione |
buttonbar: of_register_shortcut(chord) senza chiave, o con una chiave che non nomina alcun pulsante | restituiva 0 e inghiottiva il tasto senza attivare nulla | restituisce -5 |
buttonbar: rimuovere il pulsante di is_default / is_cancel, o svuotare la barra | la proprietà manteneva la chiave; un pulsante riaggiunto con quella chiave tornava predefinito | svuotata: il ruolo se ne va con il suo pulsante |
| buttonbar: un altro pulsante della barra ha il focus | l'accento restava su is_default mentre Invio attivava il pulsante con il focus | il pulsante con il focus prende l'aspetto predefinito; is_default riletto è invariato |
buttonbar: un ii_padding_x negativo | tornava a 12 | il rientro del tema, come ii_padding_y e ii_gap |
| buttonbar: la linea di separazione tra i pulsanti | disegnata a metà dello spazio, anche quando i pulsanti non si toccavano | solo tra pulsanti uniti (ii_gap = 0), e dal lato giusto nella lettura da destra a sinistra |
La ricetta: (1) su una barra, dia una scorciatoia a UN pulsante — of_register_shortcut("Ctrl+S", "save") — la forma senza chiave restituisce -5; (2) dopo aver rimosso e riaggiunto il pulsante predefinito, reimposti is_default; (3) per mettere il focus su un pulsante preciso («No» piuttosto che «Sì»), chiami of_focus_button("no").
11.14 button: un pulsante disattivato lascia la mano, e Alt+lettera risponde #
La revisione del pulsante (button, deprecato a favore di buttonbar ma sempre fornito e corretto) cambia ciò che fa alla tastiera e ciò che rileggono le sue proprietà. Nessun metodo è ritirato né aggiunto.
| Cosa | 3.0 | 4.0 |
|---|---|---|
un pulsante disattivato con ib_default, ib_cancel o is_shortcut (ib_enabled = false) | tratteneva Invio, Esc o la sua scorciatoia in tutta la finestra: il tasto andava perso | restituisce il tasto alla finestra (un CommandButton PB predefinito, un SingleLineEdit lo ricevono); riattivato, lo riprende |
la & di is_text (&Salva) | sottolineava la lettera, niente di più | Alt + la lettera attiva il pulsante ovunque sia il focus nella finestra, dopo le scorciatoie esplicite, mai se disattivato; una barra dei menu PB che usa la stessa lettera la perde |
| Invio o Spazio tenuti premuti sul pulsante con il focus | una raffica di ue_clicked; Spazio partiva alla pressione | un solo ue_clicked; Spazio parte al rilascio, come in Windows |
un is_shortcut che la finestra non sa attivare ("Win+S", "Ctrl+Entrée", "Ctrl+Pause") | si rileggeva tale e quale; "Win+S" attivava il pulsante con una S semplice | rifiutato: si rilegge "". I nomi dei tasti si scrivono in inglese (Enter, Esc, Del) |
is_shortcut con un tooltip | la scorciatoia non compariva da nessuna parte | aggiunta al tooltip (al titolo di uno arricchito): «Salva (Ctrl+S)» |
of_register_shortcut("F5") sul pulsante, poi ib_default, ib_cancel o is_shortcut cambiati | F5 veniva cancellato | F5 e is_shortcut rispondono entrambi |
is_text, is_image, is_style, ii_badge, il_badge_color, ii_badge_size, ii_image_size letti dopo of_reset() | il vecchio valore, mentre lo schermo era azzerato | il loro valore predefinito ("", "standard", 0, -1) |
| un pulsante disattivato e il tasto Tab | riceveva il focus | viene saltato |
un'etichetta fatta di sola immagine ([picture=…]), o una & in un tag | l'etichetta scompariva, o il tag era rotto | mostrati come scritti |
La ricetta: scriva i nomi dei tasti di is_shortcut in inglese ("Ctrl+Enter") e rilegga la proprietà in caso di dubbio: "" significa rifiutato. Se disattivava un pulsante predefinito per «disattivare Invio», nulla da cambiare: è ciò che ora accade.
11.15 menubar: una barra dei menu che restituisce il focus, e Alt+lettera da ovunque #
La revisione della barra dei menu (menubar) cambia ciò che fa del focus e della tastiera, e ciò che fanno tutti i menu nativi in scrittura da destra a sinistra. Nessun metodo è ritirato né cambia firma.
| Cosa | 3.0 | 4.0 |
|---|---|---|
un clic nella barra, poi una scelta (Modifica > Incolla) | la barra teneva il focus: GetFocus() in ue_item_selected non nominava più il campo, l'incolla andava nel vuoto | il focus torna al controllo precedente prima che parta ue_item_selected; lo stesso con Esc e con un clic fuori |
Alt+F tenuto, o F10, con il focus in un campo | niente: solo Alt premuto e poi F apriva File | Alt+F apre File da qualunque controllo, F10 fa come Alt; un Alt+F registrato dalla sua applicazione mantiene la precedenza, e un menu PowerBuilder nativo sulla stessa lettera la perde |
Ctrl++, Ctrl+-, Ctrl+,, Alt+Left, Ctrl+Space, Ctrl+Tab, Ctrl+Backspace (tutti i componenti con scorciatoie) | mostrate, ma nulla partiva da un controllo PB; il button le rifiutava ("") | attivate ovunque sia il focus; questi tasti richiedono Ctrl o Alt (da soli restano navigazione) |
in RTL, i menu a tendina di tutti i menu nativi (barra dei menu, ribbon, barra degli strumenti, breadcrumb, menu contestuale…) | allineati a sinistra, cascate a destra, chevron ›, Sinistra chiudeva | il menu a tendina pende allineato a destra sotto il titolo, una cascata si apre a sinistra (chevron ‹): Sinistra apre, Destra chiude |
| un clic sul titolo di un menu già aperto | lo chiudeva e poi lo riapriva (un secondo ue_menu_opening) | lo chiude, come in Windows |
un is_shortcut posto su una voce che apre una cascata | mostrato, e sollevava ue_item_selected("file/export"), un indirizzo che nessun clic produce | né mostrato né attivato: una scorciatoia va su una foglia |
| una barra i cui menu sono tutti nascosti o ingrigiti, accanto a un ribbon | prendeva Alt per niente: i keytip del ribbon non uscivano più | restituisce Alt al ribbon finché nessun titolo è raggiungibile |
due titoli sulla stessa lettera (&File, &Preferiti con la stessa lettera) | Alt+F apriva sempre il primo | nella barra, la banda passa dall'uno all'altro, Invio apre |
| una voce rimossa e poi riaggiunta allo stesso indirizzo (un elenco di file recenti) | riprendeva i colori e il tooltip di quella scomparsa | nasce senza colore (il_back_color riletto -1); lo stesso dopo of_remove_menu e of_clear |
una lettera accentata o non latina in un menu a tendina (&Édition) | sottolineata, ma nessun tasto la raggiungeva | si digita come sulla tastiera |
| il tasto Tab sulla barra | una fermata per titolo | una sola fermata per tutta la barra; le frecce passano da un titolo all'altro |
| nuovo | — | is_image (l'icona di una voce, cambiata al volo), is_group (voci radio), ue_menu_closed(as_key) (un menu a tendina chiuso senza scelta) |
La ricetta: in ue_item_selected, lavori su GetFocus() o sul DataWindow in modifica come con un menu PowerBuilder; metta una & in ogni titolo; se la sua applicazione usava Alt+lettera per altro, lo registri (of_register_shortcut): mantiene la precedenza.
11.16 ribbon: una scelta che regge, menu che restano aperti, rifiuti che si dichiarano #
La seconda revisione della barra multifunzione (ribbon) corregge ciò che l'utente vedeva — una scelta di carattere annullata, un menu che si chiudeva sotto il puntatore — e applica alla barra la regola della libreria: un'aggiunta o una rimozione impossibile restituisce -5. Nessun metodo è ritirato né cambia firma.
| Cosa | 3.0 | 4.0 |
|---|---|---|
| ribbon: una scelta nell'elenco di una casella combinata, poi l'uscita dal campo | ue_combo_changed due volte — la scelta, poi il testo digitato prima, che la sovrascriveva; is_text rileggeva il testo digitato | un solo ue_combo_changed, la scelta; il campo la mostra subito, anche per una casella non modificabile |
ribbon: Invio o Esc in una casella combinata, un contatore, o su un pulsante della barra con il focus | andavano anche al pulsante predefinito o di annullamento della finestra | restano nella barra; Esc in un campo ripristina il testo di prima della digitazione |
| ribbon: un menu aperto mentre l'applicazione aggiorna la barra (un altro controllo nascosto, una scheda rinominata, una tessera aggiunta) | si chiudeva, e la scelta fatta dentro non attivava alcun evento | resta aperto; si chiude solo se il suo controllo sparisce, è nascosto o disattivato |
ribbon: is_app_button riscritto («File» → «Fichier»); is_app_button = "" | il menu applicativo veniva svuotato; una stringa vuota mostrava «File» | il menu resta; una stringa vuota rimuove il pulsante e il suo menu |
ribbon: of_select_tab di una scheda sconosciuta o nascosta | 0 | -5, nulla cambia |
ribbon: aggiunta di una voce di menu, di una tessera, di una scelta di casella combinata, di un pulsante di accesso rapido, di una voce del menu applicativo o di un gruppo contestuale su una chiave già presa; chiave che contiene una barra verticale o inizia con __; genitore sconosciuto (separatore, intestazione, scelta, voce senza pulsante applicativo, scheda sotto un gruppo contestuale assente) | 0: un doppione, o niente del tutto (una scheda contestuale senza fascia) | -5 |
ribbon: of_remove_tab, of_remove_group, of_remove_item, of_select_gallery_item su un indirizzo sconosciuto; of_open su un pulsante di accesso rapido | 0, senza effetto | -5. of_open("scheda/gruppo") apre il pannello di un gruppo ridotto |
ribbon: un handle of_qat_item tenuto dopo of_remove_item del suo pulsante | restava valido e designava un pulsante scomparso | liberato: IsValid() restituisce false |
| ribbon: tasti di accesso rapido — due controlli con la stessa lettera, uno dei quali nascosto; un controllo di un gruppo ridotto | quello nascosto rubava la lettera, non partiva nulla; la lettera di un gruppo ridotto non faceva nulla; un tasto di due lettere non rispondeva mai | risponde solo un controllo visibile e attivo; la lettera apre il pannello del gruppo ridotto; "FP" si digita lettera dopo lettera |
| ribbon: tasti freccia su un pulsante diviso, un selettore di colore, una casella combinata o una raccolta disattivati | vi si fermavano, senza poter fare nulla | li saltano; Giù su un pulsante a discesa o diviso ne apre il menu |
La ricetta: (1) ue_selection_changed e ue_minimized sono sollevati anche quando il vostro codice chiama of_select_tab o imposta ib_minimized, come per un clic: se chiamavate voi stessi la vostra elaborazione subito dietro, togliete quella chiamata, verrebbe eseguita due volte; (2) verificate il -5 delle aggiunte se la vostra costruzione può ripetere una chiave; (3) un is_app_button = "" che voleva dire «File» si scrive ora is_app_button = "File". Le rimozioni sotto un controllo e l'handle di una voce del menu applicativo sono nella tabella 11.5.
11.17 toolbar: una regola per le scorciatoie, un solo tooltip, rifiuti che si dichiarano #
La seconda revisione della barra degli strumenti (toolbar) allinea le sue scorciatoie a quelle della finestra e rende visibile ciò che era scritto senza effetto. Nessun metodo viene rimosso né cambia firma; compaiono due codici di ritorno (-5).
| Cosa | 3.0 | 4.0 |
|---|---|---|
uno strumento con is_shortcut = "Delete" (un tasto da solo) e un campo nella barra | Canc nel campo attivava lo strumento e non cancellava nulla; fuori dalla barra, nulla | un tasto da solo non è mai una scorciatoia: serve Ctrl o Alt, oppure da F1 a F24 — la regola della finestra |
| un tasto di scorciatoia tenuto premuto (tutti i componenti) | l'azione si ripeteva: un interruttore lampeggiava | un'azione per pressione |
of_register_shortcut(accordo, chiave) ereditato, su una toolbar | non attivava nulla, e il tasto veniva inghiottito | prende l'indirizzo dello strumento o della voce ("main/save"), altrimenti -5; la forma a un argomento restituisce -5; of_clear_shortcuts svuota anche is_shortcut |
| la scorciatoia di un campo, di un selettore di data, di un'etichetta | inghiottiva il tasto senza fare nulla | il campo riceve il cursore (Ctrl+F su una ricerca), il selettore apre il suo calendario; un'etichetta non ne accetta |
il tooltip dato all'aggiunta (of_add_button(…, tooltip)) | tag mostrati alla lettera; due bolle insieme se poi veniva impostato is_tooltip | un solo tooltip a tema, testo ricco, la scorciatoia in coda; is_tooltip lo sostituisce e si rilegge |
of_add_bar(MAIN_BAR) dopo un primo strumento su main | restituiva 0 senza fare nulla | -5: per posizionarla, aggiungete main prima di qualsiasi strumento |
of_set_layout di un testo che non è JSON | restituiva 0 | -5 |
ue_layout_changed | assente quando l'aggiunta di una barra ne spostava un'altra; scatenato mostrando una barra già visibile | scatenato nel primo caso, non più nel secondo |
| separatori, menu a discesa o cascata le cui voci sono tutte nascoste | tratti orfani; il menu a discesa e la cascata restavano attivi e muti | nessun tratto in testa, in coda o doppio; vengono disegnati in grigio |
| un clic destro nella barra | nessun evento, ue_rclicked compreso | ue_item_rclicked(indirizzo) su uno strumento, ue_rclicked fuori da ogni strumento — mai entrambi |
i colori di una voce di menu (of_menu_item(…).il_back_color) | scritti e riletti, mai disegnati | disegnati nel menu |
toolbar: ue_rclicked, ue_mouse_enter, ue_mouse_leave | documentati, ma mai sollevati | sollevati: un clic destro sulla barra fuori da ogni strumento, l'entrata e l'uscita del mouse |
La ricetta: (1) una scorciatoia di strumento su un tasto da solo (tranne F1–F24) prende Ctrl o Alt; (2) su una toolbar, of_register_shortcut riceve l'indirizzo dello strumento o della voce; (3) per posizionare la barra main, chiamate of_add_bar(MAIN_BAR, banda, posizione) prima del suo primo strumento.
11.18 statusbar: una maniglia che ridimensiona, un messaggio che non sostituisce il testo #
La seconda revisione della barra di stato (statusbar) dà alla maniglia di ridimensionamento il suo vero ruolo e fa di ogni chiave vuota o sconosciuta un rifiuto. Nessun metodo è rimosso né cambia firma; of_flash_panel acquisisce un codice di ritorno (-5).
| Cosa | 3.0 | 4.0 |
|---|---|---|
ib_show_resize_grip = true, poi trascinare la maniglia | un disegno: non si muove nulla | la finestra si ridimensiona dal suo angolo (in basso a sinistra in RTL); la maniglia non è disegnata su una finestra ingrandita o senza bordo ridimensionabile |
of_flash_panel su una chiave mai data alla barra, o su un indirizzo | 0, non si vede nulla | -5 |
of_panel(k).is_text riletto durante un of_flash_panel | il messaggio | il testo del pannello (il messaggio passa sopra) |
of_panel(""), of_panel("a/b"): scrittura poi rilettura | scriveva nei pannelli senza chiave e nei separatori | non designa nulla: non scrive da nessuna parte, si rilegge vuoto |
is_state fuori dalle costanti STATE_* ("Error", "very bad") | riletto così com'è, senza colore; un valore con uno spazio sollevava un errore di script | le maiuscole sono ignorate ("Error" = errore); qualsiasi altro valore vale « nessuno stato » e si rilegge vuoto |
ii_progress = 150 poi riletto | 150 (disegnato al 100 %) | 100, ciò che è disegnato |
| un pannello disattivato che porta uno stato | manteneva il colore dello stato: sembrava attivo | in grigio, segno di stato compreso |
un pannello rimosso, svuotato (of_clear, of_clear_menu), disattivato o nascosto mentre il suo elenco è aperto | l'elenco restava aperto, e una scelta sollevava ue_panel_menu_clicked | l'elenco si chiude, non viene sollevato nulla (lo stesso per una voce diventata grigia o nascosta) |
| doppio clic su un pannello con elenco a discesa | ue_panel_double_clicked oltre all'elenco aperto | solo l'elenco |
| Freccia su / giù su un pannello con elenco a discesa che ha il focus | passava al pannello vicino | apre l'elenco (le frecce Sinistra / Destra continuano a spostare) |
| un elenco a discesa fatto di soli separatori | freccia ed elenco vuoto | nessun elenco: il pannello resta ciò che dice ib_clickable |
La ricetta: (1) imposti ib_show_resize_grip su una barra di stato posta in fondo a una finestra ridimensionabile; (2) controlli il ritorno di of_flash_panel come quello degli altri metodi a chiave; (3) dia una chiave a ogni pannello che vuole rileggere o modificare.
11.19 dockcontainer: un of_select_panel che trova il pannello, finestre mobili che ricordano #
La seconda revisione del contenitore di pannelli (dockcontainer) dà a of_select_panel un effetto su un pannello ripiegato o mobile, e fa conservare le finestre mobili dalla disposizione. Nessun metodo è rimosso né cambia firma.
| Cosa | 3.0 | 4.0 |
|---|---|---|
of_select_panel di un pannello ripiegato, mobile o nascosto | 0, non si vede nulla | ripiegato: il suo pannello a scomparsa si apre; mobile: la sua finestra passa davanti; nascosto: -5 |
of_float_panel del pannello principale o di un pannello nascosto | 0, non succede nulla | -5 |
of_move_panel che impila il pannello PRINCIPALE | 0, e il suo vicino sparisce senza scheda | -5, non si muove nulla |
as_position sconosciuta (of_add_panel, of_move_panel) | 0, il pannello si ancora in basso | -5, il controllo non viene toccato |
disposizione (of_get_layout, ue_layout_changed, of_set_layout) e pannelli MOBILI | dimenticati: un pannello staccato tornava ancorato; spostare la sua finestra non sollevava nulla | conservati con il posto della loro finestra, riaperti al ripristino (riportati su uno schermo); spostare o ridimensionare la finestra solleva ue_layout_changed |
of_set_layout di una disposizione senza pannello principale | il pannello principale corrente viene tolto | viene mantenuto |
is_title di un pannello aggiunto senza titolo | la sua chiave; un titolo dato in seguito al pannello principale non faceva apparire la sua intestazione | "" (la scheda mostra sempre la chiave); l'intestazione del principale segue il suo titolo |
La ricetta: (1) ue_panel_selected, ue_panel_floated e ue_panel_pinned sono sollevati anche dopo of_select_panel, of_float_panel e ib_pinned, come per un gesto: se chiamavate voi stessi la vostra elaborazione subito dietro, togliete quella chiamata, verrebbe eseguita due volte; (2) verificate il -5 di of_move_panel, of_float_panel e of_select_panel; (3) una disposizione salvata prima della 4.0 si ripristina così com'è, i suoi pannelli restano ancorati.
11.20 tab: codici di ritorno onesti, un clic destro che torna all'applicazione #
La seconda revisione delle schede (tab) fa dire a of_add_page e of_select_page ciò che rifiutano, annuncia la disposizione quando il suo codice nasconde una scheda, e restituisce il clic destro all'applicazione quando il menu integrato è disattivato. Nessun metodo è rimosso né cambia firma; si aggiunge un evento.
| Cosa | 3.0 | 4.0 |
|---|---|---|
of_add_page di un controllo già ospitato (da questa scheda sotto un'altra chiave, o da un altro componente) | 0, e una scheda senza nulla dietro | -5, non viene aggiunto nulla |
of_select_page di una scheda rifiutata mentre nessuna scheda è attiva (tutte nascoste) | 0 | -5 |
Nascondere o rimostrare una scheda dal suo codice (ib_visible) | nessun ue_layout_changed | ue_layout_changed sollevato con la disposizione intera, come per of_move_page: è l'avviso che la disposizione da salvare è cambiata |
Clic destro su una scheda con ib_context_menu = false | nulla | la scheda viene selezionata poi viene sollevato ue_tab_rclicked(as_key) (nuovo): apra lì il suo menu |
Tornare sulla scheda corrente mentre ue_selection_changing attende la sua risposta | una risposta «sì» attivava comunque l'altra scheda | la domanda è annullata: vince l'ultimo gesto dell'utente |
Una scheda disattivata o nascosta mentre ue_tab_closing attende la sua risposta | si chiudeva comunque | resta aperta |
| Chiudere da tastiera (Canc) la scheda che ha il focus | il focus lasciava la barra, le frecce non rispondevano più | il focus passa alla scheda diventata attiva |
La ricetta: (1) verifichi il -5 di of_add_page (una pagina si ospita una sola volta) e di of_select_page; (2) se salva la disposizione in ue_layout_changed, nulla da fare — ora segue anche i suoi ib_visible; (3) dove ib_context_menu = false lasciava il clic destro senza seguito, scriva ue_tab_rclicked.
11.21 listbar: una voce nascosta mai selezionata, una disposizione verificata #
La seconda revisione della barra di navigazione (listbar) fa rifiutare a of_select_item una voce nascosta e a of_set_layout un testo che non è una disposizione, e aggiunge una pastiglia contatore, i tasti Sinistra / Destra e il clic destro su una voce. Nessun metodo viene rimosso né cambia firma.
| Cosa | 3.0 | 4.0 |
|---|---|---|
of_select_item di una voce nascosta (ib_visible = false) | 0, una selezione invisibile | -5, la selezione non si sposta; nascondere la voce già selezionata la lascia selezionata |
of_set_layout di un testo che non è un oggetto JSON (file troncato) | 0, non viene applicato nulla | -5, non viene inviato nulla |
| Sezione compressa in una disposizione ripristinata, aggiunta più tardi | nasce compressa | nasce espansa: lo stato compresso vale solo per una sezione presente |
| Sezione con titolo vuoto | le sue voci attaccate a quelle sopra; comprimibile, senza più nulla per riaprirla | uno spazio (un filetto nella barra compressa) la separa; non si comprime mai |
Nuovo: is_badge (voce), ue_item_rclicked(as_keys), Sinistra / Destra e salto per lettera | — | una pastiglia contatore, il clic destro su una voce (un solo evento, la voce non viene selezionata), la compressione da tastiera |
La ricetta: (1) ue_selection_changed è sollevato anche dopo un of_select_item del vostro codice (aprire la pagina iniziale all'avvio, per esempio), come per un clic: se aprivate voi stessi la pagina subito dietro, lasciatelo all'evento, altrimenti si aprirebbe due volte; (2) verificate il -5 di of_select_item se nascondete delle voci, e quello di of_set_layout se la disposizione viene da un file; (3) una sezione senza titolo non si comprime più: dategli un titolo se deve comprimersi.
11.22 tilesbox: un titolo che non crea più gruppi, la riorganizzazione dalla tastiera #
La seconda revisione del pannello di riquadri (tilesbox) impedisce al titolo di un gruppo di creare quel gruppo, fa rifiutare a of_add_live_item un testo vuoto, dà una sola fermata di tabulazione per gruppo e aggiunge la riorganizzazione dalla tastiera. Nessun metodo viene rimosso né cambia firma. il_badge_color segue ora la regola di tutti i colori (vedere la riga picture, button, tilesbox più sopra).
| Cosa | 3.0 | 4.0 | |
|---|---|---|---|
of_group(chiave).is_title su un gruppo mai aggiunto | creava un gruppo visibile che non si poteva né riempire né rimuovere (salvo of_clear) | non scrive nulla: solo of_add_group crea un gruppo; una chiave vuota, o con / o ` | `, dà un handle inerte |
of_add_live_item con un testo vuoto | 0, e il testo fisso is_live_text veniva cancellato | -5, non cambia nulla | |
of_tile(indirizzo).of_count() | 0 | il numero di facce poste da of_add_live_item | |
Riorganizzare (ib_reorderable = true) | solo con il mouse | anche dalla tastiera: Ctrl+Sinistra/Destra nel gruppo (senso di lettura), Ctrl+Su/Giù verso il gruppo vicino; stessi ue_tile_moved e ue_layout_changed | |
| Tasto Tab | si fermava su ogni riquadro; una freccia verso un bordo senza vicino saltava al riquadro precedente o successivo del documento | una fermata per gruppo (l'ultimo riquadro con il focus), le frecce percorrono i riquadri; al bordo il focus resta | |
| Riquadro disattivato o nascosto mentre lo si trascina | spostato al rilascio, ue_tile_moved sollevato | il trascinamento viene abbandonato, nulla si muove | |
ib_collapsed di un gruppo impostato dal vostro codice | nessun evento | ue_group_toggled, come un clic sull'intestazione (nulla quando il gruppo è già in quello stato) |
La ricetta: (1) create un gruppo con of_add_group prima di cambiarne il titolo; (2) verificate il -5 di of_add_live_item se il testo di una faccia può essere vuoto; (3) ciò che facevate in ue_tile_moved vale ora anche per uno spostamento dalla tastiera.
11.23 stepbar: «tutto terminato» ancorato all'ultimo passaggio, passaggi rimossi che non lasciano più nulla #
La seconda revisione della barra dei passaggi (stepbar) rende «tutto terminato» coerente con la regola del passaggio in corso (un'identità, non un rango), fa portare via a un passaggio rimosso ciò che gli apparteneva e corregge quattro difetti di visualizzazione. Nessuna firma cambia.
| Cosa | 3.0 | 4.0 |
|---|---|---|
of_add_step mentre la barra è su «tutto terminato» | il passaggio aggiunto appariva terminato (spunta); ii_current passava a n + 2 senza evento | aggiunto dopo l'ultimo passaggio di allora, diventa il passaggio in corso e ue_step_changed viene sollevato; inserito prima, non cambia nulla |
of_step(chiave).is_state su una chiave che non designa alcun passaggio | conservato, poi applicato al passaggio aggiunto più tardi con quel nome | ignorato; un passaggio aggiunto nasce con il suo stato calcolato |
Colori e tooltip di un passaggio rimosso (of_remove_step, of_clear_steps) | tornavano sul prossimo passaggio aggiunto con la stessa chiave | se ne vanno con il passaggio |
Barra compattata (OVERFLOW_AUTO) il cui passaggio in corso è forzato in errore | nessuna etichetta; un passaggio forzato a STATE_CURRENT ne guadagnava una | l'etichetta resta al passaggio in corso (il rango di ii_current), qualunque sia il suo stato |
OVERFLOW_SHRINK | etichette su più righe, parole lunghe tagliate senza «…» | una riga per etichetta, terminata da «…» |
POSITION_BOTTOM con una seconda riga (is_description) | sopra l'etichetta, attaccata ad essa | sotto l'etichetta, sopra il pallino |
Passaggio del mouse su un passaggio disattivato o non raggiungibile (il_back_color_hover, il_text_color_hover) | il colore al passaggio si accendeva | non si accende nulla: il passaggio non risponderà al clic |
La ricetta: se il vostro codice aggiunge un passaggio dopo aver impostato «tutto terminato» (ii_current = of_count() + 1) e vuole che la barra resti così, reimpostate ii_current = of_count() + 1 dopo l'aggiunta. Se ricostruite la barra con le stesse chiavi, reimpostate i colori e i tooltip voluti: non sopravvivono più alla rimozione.
11.24 progressbar: una barra che sta nel suo controllo, un'etichetta che segue la lingua #
La seconda revisione della barra di avanzamento (progressbar) la fa stare dove c'era una HProgressBar, invia al componente solo i valori che cambiano il disegno, scrive la percentuale nella lingua di visualizzazione e aggiunge is_label_format (un'etichetta vostra) e is_state (pausa, errore). Nessuna firma cambia.
| Cosa | 3.0 | 4.0 |
|---|---|---|
| Barra lineare in un controllo basso o largo | margine di 12 px, al massimo 640 px di larghezza: sotto i 24 px di altezza compariva una barra di scorrimento e la barra era tagliata | margine di 2 px, tutta la larghezza; la traccia (14 px) e l'etichetta si riducono con l'altezza |
Etichetta della percentuale (ib_label) | «50%» in tutte le lingue | nella lingua di visualizzazione: «50 %» in francese |
of_set_property("value", "12,5"), o un testo che non è un numero | inviato così com'era: il comando andava perso senza dire nulla; un minimum non valido bloccava la scala fino al prossimo of_reset | «12,5» viene letto 12.5; un testo che non è un numero (né true/false per un booleano) viene ignorato |
id_value riletto | il valore che il componente aveva ricevuto; ogni assegnazione era un andata e ritorno con esso | l'ultimo valore impostato dall'applicazione; il componente riceve solo quelli che cambiano il disegno (un decimo di punto percentuale) |
of_reset() su una barra piena | la barra scendeva a zero scorrendo | torna a zero di colpo |
La ricetta: (1) se calcolavate una percentuale a mano, impostate id_maximum e assegnate il valore grezzo, anche a ogni riga; (2) se un test automatico leggeva l'etichetta, aspettatevi il formato della lingua di visualizzazione; (3) per mostrare una pausa o un errore, preferite is_state a un colore scelto con il_color.
11.25 picture: un'assegnazione rilegge il file, un errore dice il perché #
La seconda revisione dell'immagine (picture) le fa rileggere il disco a ogni assegnazione, come il Picture nativo, dà a ue_error un secondo argomento che dice perché l'immagine manca, rifiuta un indirizzo http:// invece di fallire senza motivo e solleva un solo ue_clicked su un doppio clic. ue_error è l'unica firma che cambia.
| Cosa | 3.0 | 4.0 |
|---|---|---|
| picture: doppio clic sull'immagine | due ue_clicked, poi ue_double_clicked | un solo ue_clicked, poi ue_double_clicked — come il Picture nativo |
picture: ue_error | ue_error (string as_message): solo il messaggio | ue_error (string as_message, string as_reason): as_reason è una delle costanti REASON_* (non trovato, troppo grande, http rifiutato, formato non mostrato, altro). Il Suo script dell'evento riceve l'argomento da sé; una chiamata event ue_error(…) scritta nel Suo codice ora ne passa due |
picture: is_source = "http://…" | tentato in https dal motore; su un server senza TLS, un errore senza motivo | rifiutato subito: glifo di errore e ue_error con REASON_INSECURE. Scarichi prima l'immagine (n_pbt_restclient.of_download) e mostri il file |
picture: lo stesso percorso riassegnato dopo aver riscritto il file; mono: o tint: su is_source; un'immagine .avif | la vecchia immagine; il glifo di errore; non trovata | il file riletto, come il Picture nativo; il glifo ricolorato dal tema; mostrata |
| picture: immagine ingrandita più piccola della cornice (bande); rotellina orizzontale, touchpad; tasto destro tenuto premuto | usciva dalla cornice trascinandola; uno scatto di zoom per evento, riduzione su uno scorrimento orizzontale; l'immagine si spostava | resta dove la collocano is_align e is_valign; zoom proporzionale al gesto, nulla su uno scorrimento orizzontale; solo il tasto sinistro sposta |
La ricetta: (1) se uno script apriva una scheda su ue_clicked e un'altra azione su ue_double_clicked, nulla da fare — il doppio clic non riapre più la scheda; (2) sostituisca ogni analisi del testo di as_message con un test di as_reason; (3) un'immagine di un server intranet in http si scarica prima (n_pbt_restclient.of_download in una cartella temporanea), poi si mostra con il suo percorso; (4) se aggiungeva un ?v= al percorso per forzare la rilettura di un'immagine riscritta, lo tolga: riassegnare basta.
11.26 video: sottotitoli e formati che si riproducono, un errore che dice il perché #
La seconda revisione del lettore (video) dà a ue_failed un secondo argomento che dice perché un film non suona, rifiuta un indirizzo http://, riproduce .mkv e .mov, carica i sottotitoli dati per URL, e mette in pausa il film quando il componente è nascosto. ue_failed è l'unica firma che cambia.
| Cosa | 3.0 | 4.0 | |
|---|---|---|---|
video: ue_failed | ue_failed (string as_message) | ue_failed (string as_message, string as_reason) — as_reason è una costante REASON_* | |
video: una sorgente http:// | falliva come « introvabile » | rifiutata subito, REASON_INSECURE; solo https si riproduce | |
video: un .mkv, un .mov | .mkv « introvabile », .mov rifiutato dal nome | serviti e riprodotti quando il motore li decodifica; .avi, .wmv, .flv restano rifiutati (REASON_FORMAT) | |
| video: un sottotitolo dato per URL | non si mostrava mai, senza dire nulla | scaricato dal componente (il server deve consentire CORS); un rifiuto solleva ue_subtitles_failed | |
video: of_add_subtitles due volte per la stessa lingua | sostituiva la traccia in silenzio, 0 | -5 (anche per una lingua con / o ` | ); prima of_remove_subtitles` |
| video: il componente nascosto durante la riproduzione | il film continuava, con l'audio | in pausa, ue_paused, e attende of_play (ib_pause_when_hidden, vero per default) | |
| video: trascinare il volume sulla barra | un ue_volume_changed per pixel | uno solo, al rilascio | |
video: of_capture verso un .jpg | un PNG con un nome .jpg | un JPEG; l'overload of_capture(as_path, al_max_width) riduce l'immagine | |
video: of_get_last_error dopo un errore di of_capture | l'errore precedente della libreria | il motivo di QUESTO errore (cartella mancante, percorso vuoto…) | |
video: Esc a schermo intero, ib_enabled = false | senza effetto (usciva solo Alt+F4) | esce dallo schermo intero |
La ricetta: (1) aggiungi as_reason allo script di ue_failed e verificalo invece del testo del messaggio; (2) un film o un sottotitolo di un server intranet in http si scarica prima (n_pbt_restclient.of_download verso una cartella temporanea), poi si riproduce dal suo percorso; (3) ue_fullscreen_changed, ue_pip_changed, ue_source_changed e ue_chapter_changed sono sollevati anche dopo le vostre chiamate (of_fullscreen, of_pip, of_next, of_seek…), come per un gesto: se il vostro codice chiamava da sé la sua elaborazione subito dietro, togliete quella chiamata, verrebbe eseguita due volte; (4) una parete di schermi che deve suonare nascosta imposta ib_pause_when_hidden = false; (5) per sostituire la traccia di una lingua, of_remove_subtitles poi of_add_subtitles.
11.27 pdfviewer: of_refresh dice cosa fa, nulla si scarica a Sua insaputa #
La seconda revisione del visualizzatore (pdfviewer) dà un codice di ritorno a of_refresh — e, perché lo stesso nome abbia lo stesso senso, anche a quelli di webbrowser e shellexplorer —, segnala ogni link del documento e rifiuta ciò che non si visualizzerà mai invece di lasciare in attesa. Nessuna firma di evento cambia.
| Cosa | 3.0 | 4.0 |
|---|---|---|
pdfviewer · webbrowser · shellexplorer: of_refresh | subroutine | long: 0 una volta richiesto, -4 senza documento o pagina (pdfviewer, webbrowser), -2 se il componente non è creato |
pdfviewer: of_refresh dopo un rifiuto (http://…) | non faceva nulla, senza evento | il rifiuto viene ripetuto: ue_load_failed |
pdfviewer: un indirizzo data: di oltre 2 MB di caratteri | mai visualizzato, nessun evento | ue_load_failed con REASON_TOO_LARGE, subito |
| pdfviewer: un PDF remoto inviato «come download» | ue_load_failed, ma il file finiva in Download | ue_load_failed con REASON_REFUSED, nulla viene scaricato |
pdfviewer: ue_link_clicked su un link mailto:, file: o relativo | mai sollevato (solo http e https); un link relativo arrivava come indirizzo interno | sollevato per ogni link; as_url è un mailto:… così com'è, o un percorso su disco per un file locale |
pdfviewer: of_print_to_pdf | scriveva la pagina attorno al lettore, non il documento | -4, nulla viene scritto: copi il file di is_source |
pdfviewer: file://localhost/C:/…, file:////server/condivisione/… | un percorso errato, non trovato | C:\… e \\server\condivisione\… |
pdfviewer: il focus dato al componente (Tab, of_focus_webview) | restava sulla pagina: i tasti non facevano scorrere il documento | passa al documento: PagGiù, frecce, Home / Fine lo fanno scorrere |
La ricetta: (1) una chiamata uo_pdf.of_refresh() compila così com'è; ne verifichi il ritorno se vuole sapere che non c'era nulla da rileggere; (2) un documento di oltre 1,5 MB tenuto in memoria si scrive in un file temporaneo, poi si visualizza tramite il suo percorso; (3) in ue_link_clicked, si aspetti anche un mailto: e un percorso su disco, non solo un indirizzo web; (4) per copiare il documento visualizzato, copi il file di is_source piuttosto che usare of_print_to_pdf.
11.28 codeeditor: una ricerca che si vede, un «vai a» che sposta il cursore, sostituire #
La seconda revisione dell'editor di codice (codeeditor) porta sullo schermo ciò che la ricerca trova, mantiene il cursore dell'utente durante una ricerca, rinomina ii_doc_line e aggiunge ciò che ci si aspetta da un editor di script: sostituire, pilotare il cursore, sapere se occorre salvare, mostrare un errore nel margine. Nessuna firma di evento cambia.
| Cosa | 3.0 | 4.0 |
|---|---|---|
codeeditor: ii_doc_line | un long con il prefisso di integer | il_doc_line: lo rinomini; una riga oltre la fine del testo non segna più nulla (si rilegge come è stata scritta) |
codeeditor: of_find con ib_search_enabled = false | 0, senza cercare nulla | -4 |
codeeditor: of_find("") | rilanciava la ricerca precedente | svuota il campo e cancella le evidenziazioni, senza ue_find_result |
codeeditor: of_find, Invio nella barra | l'occorrenza restava spesso fuori vista; il cursore ci andava | l'occorrenza viene portata sullo schermo; la ricerca parte dal cursore, che si sposta solo alla chiusura della barra (Esc) |
codeeditor: of_insert_text con la barra di ricerca aperta | sostituiva l'occorrenza trovata, fuori vista, e svuotava la cronologia di Ctrl+Z | inserisce al cursore dell'utente, portato sullo schermo; Ctrl+Z lo annulla |
codeeditor: un nuovo is_text | conservava lo scorrimento del documento precedente; un testo con solo CR si rileggeva in LF | si visualizza dalla prima riga e cancella gli indicatori; il solo CR si rilegge in CR (una miscela in CRLF) |
codeeditor: ib_current_line con ib_wrap | nessuna fascia | la fascia copre tutta la riga del cursore |
| codeeditor: aggiunte | — | sostituire (of_replace, of_replace_all, Ctrl+H) e opzioni di ricerca (ib_find_match_case, ib_find_whole_word, ib_find_regex, F3); cursore e selezione (il_caret_line, il_caret_column, of_select_range, of_selected_text, of_line_count); ib_modified; indicatori nel margine (of_add_marker, of_remove_marker, of_clear_markers, of_marker_count) |
La ricetta: (1) sostituisca ii_doc_line con il_doc_line; (2) verifichi il -4 di of_find se la ricerca può essere disattivata; (3) per «andare alla riga» di un errore spostando il cursore, imposti il_caret_line (e of_add_marker per mostrarlo) — il_doc_line segna soltanto; (4) se seguiva ue_caret_changed per sapere dove era stato inserito un frammento, legga il_caret_line dopo of_insert_text; (5) un pulsante Salva può seguire ib_modified, che rimette a false dopo il salvataggio.
11.29 jsontree e xmltree: la tastiera resta all'albero, una ricerca che non sposta più la selezione #
La seconda revisione dell'albero JSON (jsontree) ha riguardato il motore che condivide con l'albero XML (xmltree): quanto segue vale per entrambi, salvo indicazione. Nessuna firma cambia; l'albero JSON guadagna of_expand_path, of_collapse_path, of_is_expanded, of_copy e l'evento ue_node_toggled, sollevato da un gesto dell'utente come da of_expand_path e of_collapse_path.
| Cosa | 3.0 | 4.0 |
|---|---|---|
| jsontree, xmltree: Invio su una foglia | passato alla finestra: il suo pulsante predefinito partiva | tenuto dall'albero, solleva ue_node_clicked come un clic; senza selezione, nulla |
| jsontree, xmltree: Esc con la casella di ricerca aperta | partiva il pulsante Annulla della finestra | chiude prima la casella; a casella chiusa, Esc torna alla finestra |
jsontree, xmltree: righe di chiusura (}, ], </x>) | raggiunte dalle frecce (ue_selection_changed di un blocco già annunciato); un clic riportava la vista sull'apertura | saltate dalla tastiera; un clic seleziona il blocco senza spostare la vista |
| jsontree, xmltree: freccia destra su una foglia | scendeva di una riga | non fa nulla, come in un albero |
| jsontree, xmltree: una ricerca durante una selezione | of_search_next o Esc potevano piegare la riga scelta e spostare la selezione senza evento | la riga selezionata resta visibile e selezionata: of_selected_path non cambia |
jsontree: il messaggio di ue_error | metà tradotto, metà inglese («JSON non valido : Unexpected end of JSON (line 1, column 6)») | interamente nella lingua di visualizzazione, riga e colonna comprese: non ne confronti il testo |
| jsontree, xmltree: un documento di più di 1.500.000 righe | mostrato, ma la sua fine irraggiungibile, senza dire nulla | rifiutato: un messaggio nell'albero e ue_error |
| jsontree: Ctrl+C nell'albero | non copiava nulla, e partiva come scorciatoia della finestra | copia la selezione (come of_copy); senza selezione, la scorciatoia resta alla finestra |
La ricetta: (1) se una finestra contava su Invio nell'albero per attivare il suo pulsante predefinito, aggiunga questo passo in ue_node_clicked; (2) non cerchi più una chiave vuota in ue_selection_changed (una riga di chiusura non è più selezionata); (3) non analizzi il testo di ue_error: segue la lingua; (4) per ripristinare le pieghe di un utente, legga of_is_expanded e le reimposti con of_expand_path / of_collapse_path.
11.30 xmltree: ogni riga ha il suo XPath, qualsiasi XPath seleziona #
La seconda revisione dell'albero XML (xmltree) riprende tutto ciò che la sezione precedente dice del motore condiviso. Aggiunge ciò che è proprio dell'XML: un percorso che designa SEMPRE il nodo della riga, leggibile così com'è da n_pbt_xml. Nessuna firma cambia; l'albero XML guadagna of_selected_xml, of_copy, of_expand_path, of_collapse_path, of_is_expanded e l'evento ue_node_toggled.
| Cosa | 3.0 | 4.0 |
|---|---|---|
| xmltree: percorso di una riga di testo, di commento o di istruzione di elaborazione | quello del suo elemento (mentre of_selected_value dava il suo testo); "" prima della radice | il proprio: /r/text()[2], /r/comment()[1], /r/processing-instruction('x')[1], /comment()[1] — n_pbt_xml.of_get_value vi legge lo stesso valore |
| xmltree: elemento il cui prefisso è ridichiarato con un altro URI, o con un fratello dello stesso nome in un altro spazio dei nomi | un percorso che non trovava nulla, o un ALTRO nodo | *[local-name()='x' and namespace-uri()='urn:…'], che designa proprio quel nodo |
xmltree : of_select_path | solo la forma esatta che l'albero scrive, altrimenti -5 | qualsiasi XPath (//line[@sku='A'], /r/a[1]…): viene selezionato il primo nodo trovato, of_selected_path rende poi il percorso dell'albero |
xmltree: il messaggio di ue_error | « XML non valido : error on line 1 at column 11: … »; l'albero restava vuoto | « XML non valido : riga 1, colonna 11 (…) », nella lingua di visualizzazione; l'albero mostra il sorgente, con la riga errata evidenziata |
xmltree: <?xml-stylesheet?> senza dichiarazione XML | mostrato due volte | una sola riga |
n_pbt_xml: un XPath con @xml:lang | rifiutato (prefisso xml sconosciuto), valore vuoto | letto: il prefisso xml è legato d'ufficio, come vuole lo standard |
| xmltree: Freccia destra su un tag con attributi | gli attributi si raggiungevano solo con il mouse | percorre gli attributi uno per uno (Freccia sinistra torna indietro), un ue_selection_changed per passo, poi scende |
| xmltree: Ctrl+C, piegare per percorso | niente; Ctrl+C andava alla finestra come scorciatoia | of_selected_xml, of_copy e Ctrl+C (il XML della selezione), of_expand_path, of_collapse_path, of_is_expanded (qualsiasi XPath), ue_node_toggled (un gesto, o of_expand_path / of_collapse_path) |
La ricetta: (1) se risalivate da una riga di testo o di commento al suo elemento con of_selected_path, prendete il genitore del percorso (ciò che precede l'ultima /); (2) non analizzate il testo di ue_error: segue la lingua; (3) un percorso memorizzato in 3.0 sotto spazi dei nomi misti si ritrova passandolo a of_select_path, che ora accetta qualsiasi XPath, e rileggendo poi of_selected_path.
11.31 xml: rifiuti che si dichiarano, spazi dei nomi che tengono #
La seconda revisione di n_pbt_xml non cambia alcuna firma. Rende of_remove fedele ai codici della libreria, rifiuta una lettura finché un documento costruito ha un elemento aperto, e fa tenere gli spazi dei nomi: ciò che un mutatore scrive si rilegge nello spazio giusto, o è rifiutato dicendolo.
| Cosa | 3.0 | 4.0 |
|---|---|---|
xml: of_remove(""), of_remove senza documento caricato, pagina che non risponde | 0, come «nulla rimosso» | -5; -4; -2 — il conteggio (>= 0) solo quando la rimozione è stata tentata |
xml: una lettura (of_exists, of_count, of_get_value, of_is_valid…) o una modifica mentre un elemento costruito è ancora aperto | il documento era caricato così com'era, e il resto della costruzione iniziava un NUOVO documento: ciò che precedeva era perso senza errore | rifiutata: -4, vuoto o false, e is_last_error = «the document is still being built : close its elements first»; nulla va perso (of_xml e of_pretty restano disponibili) |
xml: of_add_xml sotto un elemento con spazio dei nomi predefinito, o con il prefisso del bersaglio (<s:Item/> sotto s:Body) | il frammento restava fuori dallo spazio dei nomi (xmlns=''), invisibile all'XPath usato per aggiungerlo; il prefisso del bersaglio era rifiutato (-4) | il frammento eredita gli spazi dei nomi in vigore sul suo bersaglio, come of_add_child |
xml: of_set_attr / of_add_child con un nome con prefisso (xsi:type, p:item) | 0, un attributo fuori dallo spazio dei nomi che l'XPath non trovava; con un prefisso non dichiarato, un documento che non si ricaricava più | nello spazio dei nomi del prefisso (dichiarato sul nodo, o legato con of_register_namespace); -4 e «undeclared prefix : xsi» se non è legato da nessuna parte |
xml: of_pretty dopo un of_add_child sotto un genitore con prefisso (s:Body) | <Item> senza prefisso: riletto, fuori dallo spazio dei nomi | <s:Item>, come in of_xml |
xml: of_element_attr due volte con lo stesso nome; un nome :x, x: o a:b:c | due attributi (documento non valido); nome accettato (un documento che non si carica) | un solo attributo, con il secondo valore; nome rifiutato (is_last_error), elemento escluso |
xml: of_transform | applica un foglio XSLT al documento caricato | rimosso: XSLT non esiste più nel motore (Chromium lo rimuove); trasformate lato server o in PowerScript |
La ricetta: (1) un of_remove controllato con = 0 (nulla rimosso) funziona ancora; controllate < 0 (nulla ha potuto essere tentato); (2) se leggevate un documento DURANTE la costruzione (un of_exists per controllare, un of_count per numerare), chiudete prima i suoi elementi, o tenete il conto voi; (3) un frammento di of_add_xml non deve più ridichiarare lo spazio dei nomi del suo bersaglio: chi scriveva xmlns='' per uscirne può ancora farlo; (4) controllate il ritorno di of_set_attr / of_add_child con un nome con prefisso, e dichiarate il prefisso (o legatelo con of_register_namespace).
11.32 json: un array che si costruisce in fretta, numeri che conservano le cifre, un testo vuoto che si dice vuoto #
La seconda revisione di n_pbt_json non rimuove né cambia alcuna firma. Aggiunge gli overload decimal e longlong di of_set_number e of_add_number, e i lettori of_get_decimal e of_get_longlong. Costruire un array con of_add_* non ripercorre più tutto l'array a ogni aggiunta: 2.000 righe si costruiscono in una frazione di secondo invece che in diversi minuti. Due regole sono ora scritte nella documentazione, senza cambiare: una stringa null si scrive "" (per un null JSON, of_set_raw(path, "null")), e una chiave scritta due volte si legge alla sua PRIMA occorrenza.
| Cosa | 3.0 | 4.0 |
|---|---|---|
json: of_load di un testo fatto di spazi (a capo, tabulazione) | -4, come un testo malformato | -5, come un testo vuoto |
json: of_load di un testo preceduto da un BOM (file UTF-8 con BOM) | -4 | 0, il BOM viene ignorato |
json: of_load di un documento annidato su più di 512 livelli | 0 — e un testo molto profondo poteva arrestare l'applicazione | -4, l'applicazione resta viva |
json: of_set_number / of_add_number di un decimal (o di un letterale come 690.50) | convertito in double: una quindicina di cifre, un centesimo poteva perdersi | overload decimal: tutte le cifre, zeri finali tolti (690.5); anche un longlong ha il suo |
json: of_get_number di un esponente con zeri iniziali (1E-0000005) | 0, o un valore enorme | il valore giusto (0.00001) |
tutti i componenti: \u seguito da quattro caratteri non esadecimali, in una stringa letta | i quattro caratteri sparivano | conservati così come sono, come un escape sconosciuto |
La ricetta: (1) se verificavate of_load(...) = -4 per riconoscere un file vuoto, verificate < 0; (2) un importo decimal passato a of_set_number si scrive ora con tutte le cifre, senza cambiare nulla nel vostro codice; (3) un identificativo di più di 15 cifre si rilegge con of_get_longlong, un importo con of_get_decimal, non più con of_get_number.
11.33 crosstab: of_from_datastore, rifiuti che si dicono, il valore visualizzato al doppio clic #
La seconda revisione del crosstab rinomina of_set_data in of_from_datastore, il nome del datagrid e dello scheduler, che leggono un DataStore allo stesso modo (stessi argomenti, stessi codici). Ogni aggiunta, filtro o formato che nomina un campo sconosciuto restituisce ora -5 invece di 0. La tabella disegna solo le colonne visibili: un codice cliente o una data giornaliera posti in Colonne non bloccano più lo schermo. Novità: is_thousands, CF_ICONS, le costanti VALUEFILTER_* e DATE_*.
| Cosa | 3.0 | 4.0 |
|---|---|---|
| crosstab: alimentare da un DataStore | of_set_data(ds) | of_from_datastore(ds), stessi codici |
| crosstab: un campo sconosciuto (refuso) passato a un'aggiunta, un filtro, un formato, un ordine, un raggruppamento di date | 0, non succede nulla | -5 |
crosstab: un tipo di filtro, un'aggregazione, una parte di data fuori elenco; una misura calcolata in Righe; of_set_value_filter a una posizione senza misura | 0; la posizione scivolava sull'ultima misura | -5 |
crosstab: of_set_layout di un testo che non è JSON; of_remove_calc_field / of_remove_calc_measure di un nome sconosciuto | 0 | -5 |
crosstab: ad_value di ue_cell_double_clicked | l'aggregato grezzo (400 sotto « 80,0 % »), 0 per una cella vuota | il valore visualizzato (0.8), NULL per una cella vuota; un membro vuoto vale null nelle tuple |
| crosstab: lo stesso campo in Righe (o Colonne, Filtri) E in Valori | dipendeva dall'ordine delle chiamate: il valore spariva; Rimuovi su una dimensione toglieva tutto | consentito ovunque; aggiungere o spostare una dimensione conserva i valori, Rimuovi toglie solo il chip interessato |
| crosstab: un membro vuoto (NULL, testo vuoto); un testo con tabulazione o a capo nel DataStore | « null » o una riga senza etichetta; righe fantasma, colonne sfasate | un solo membro (vuoto), per ultimo; il testo resta nella sua riga |
crosstab: is_label dopo un nuovo of_from_datastore; is_label = "" | perso; un chip senza testo | conservato; "" ripristina l'intestazione del DataWindow |
| crosstab: Ctrl+C in modalità demo | ue_copy sollevato, appunti scritti | rifiutato come un'esportazione, la griglia lo dice |
crosstab: of_collapse_all; filtro dei membri della griglia; of_export_xlsx oltre 16 384 colonne; esportazioni in VALUES_ROWS | solo le righe; applicato a ogni casella; un file illeggibile; le misure affiancate | righe e colonne; applicato con OK (al massimo 10 000 membri elencati); rifiutato, ue_xlsx_saved dice perché; come a schermo |
La ricetta: (1) sostituite of_set_data con of_from_datastore; (2) se ignoravate il codice restituito da of_add_*_field o da un filtro, verificate < 0 — un refuso finalmente si vede; (3) in ue_cell_double_clicked, verificate IsNull(ad_value) prima di calcolare, e rileggete ad_value come il valore visualizzato (una quota, non una somma, in modalità « % »).
11.34 Base comune: of_count e of_keys_at contano in long #
of_count restituiva un integer e of_keys_at prendeva un rango integer — su tutti i componenti, sui loro handle e sugli oggetti non visivi che li portano (commandpalette, messagebox, speechout, toaster). Oltre 32 767 elementi il conteggio traboccava: un calendario (scheduler) alimentato da un DataStore di 40 000 righe non si contava più, e le sue ultime righe non si percorrevano. Le quattro firme sono ora in long: long of_count ( ), long of_count ( string as_keys ), string of_keys_at ( long al_index ), string of_keys_at ( string as_keys, long al_index ).
La ricetta: una chiamata non cambia. Una variabile integer che riceve of_count() resta giusta fino a 32 767: la dichiari long. Un discendente che ridefiniva of_count o of_keys_at riprende la nuova firma — il compilatore Le mostra la riga.
11.35 shellexplorer: un aggiornamento che conserva lo stato, ogni riga per sé #
La revisione dell'esploratore della shell conserva i suoi eventi: of_select, of_expand e of_collapse li sollevano come un clic, come nella 3.0. of_refresh e ib_show_files non richiudono più l'albero. Novità: is_file_filter (i file mostrati), ib_show_hidden (gli elementi nascosti, per impostazione predefinita l'impostazione di Esplora risorse), ib_enabled e of_refresh(percorso), che rilegge un solo ramo.
| Cosa | 3.0 | 4.0 |
|---|---|---|
shellexplorer: of_refresh(), o ib_show_files cambiato | l'albero si richiudeva, la selezione spariva senza evento | i rami aperti e la selezione ritornano, ritrovati dal loro percorso; una selezione che non esiste più solleva ue_selected("", "") |
shellexplorer: of_expand, of_select, of_collapse di un percorso vuoto | 0 | -5 |
shellexplorer: of_expand di un file o di una cartella senza figli | nulla | ue_path_not_found(…, "expand", "not a branch") |
shellexplorer: of_keys_at(percorso, i) | percorso/figlio, che nulla sapeva rileggere | il percorso del figlio, intero: si reinserisce in of_has, of_select, of_expand |
| shellexplorer: la stessa cartella mostrata su due livelli (la Musica del Desktop e quella della cartella dell'utente) | un clic, un chevron o un doppio clic sull'una agiva sull'altra | ogni riga risponde per sé |
| shellexplorer: file e cartelle nascosti | mai mostrati | mostrati secondo l'impostazione di Esplora risorse della postazione, o ib_show_hidden |
| shellexplorer: un ramo su una condivisione che non risponde | « … » per sempre, anche richiusa e riaperta | ue_error « … : timeout » dopo 30 secondi; il ramo si richiede alla riapertura |
La ricetta: (1) ue_selected e ue_expanded sono sollevati anche dopo un of_select o un of_expand del vostro codice, una volta raggiunta la cartella (un percorso ancora da leggere arriva un po' più tardi): fate il vostro lavoro nell'evento, non subito dietro la chiamata, o rileggete of_selected_key() una volta arrivata la selezione; (2) in ue_selected, trattate as_path = "" (la selezione è scomparsa); (3) verificate -5 su un percorso vuoto; (4) impostate ib_show_hidden = false se i vostri utenti non devono mai vedere gli elementi nascosti, qualunque cosa dica il loro Esplora risorse.
11.36 commandpalette: ogni oggetto tocca solo la propria palette, una chiusura che si annuncia sempre, la lingua dell'applicazione #
C'è una sola palette a schermo alla volta: quando un secondo oggetto palette apre la propria, sostituisce la prima. Un oggetto ora risponde solo della sua palette e della sua combinazione. ue_opened e ue_closed restano sollevati su of_open / of_close: dicono il ciclo di vita della finestra, non un gesto (stessa regola dei lettori audio e video). Novità: of_insert_command (un comando a un rango scelto), of_anchor_under (la palette sotto un controllo, in pixel schermo), e sull'handle is_group, is_hint, is_keywords, is_icon.
| Cosa | 3.0 | 4.0 |
|---|---|---|
commandpalette: ue_closed | senza argomento; nulla del tutto quando la palette moriva prima di apparire (chiusa o sostituita subito, finestra rifiutata) | ue_closed(string as_reason) segue ogni of_open che ha restituito 0: "", cancelled, failed o blocked |
commandpalette: of_is_open, of_close, of_reset, la distruzione di un oggetto la cui palette è stata sostituita da quella di un altro | rispondevano VERO per la palette dell'altro, e la chiudevano | rispondono solo della loro palette: FALSO, e nulla viene chiuso |
| commandpalette: distruggere (o azzerare) un oggetto la cui combinazione è stata ripresa da un altro oggetto palette della stessa finestra | toglieva la combinazione dell'altro: il tasto non rispondeva più da nessuna parte | la combinazione dell'altro resta |
commandpalette: of_register_shortcut di un tasto che l'hook non nomina (ctrl+ù, win+k, space senza modificatore) | 0 (« posata »), e il tasto non faceva mai nulla | -5; la combinazione precedente resta |
commandpalette: of_register_shortcut con is_shortcut vuoto e nessuna combinazione posata | 0 | 2 |
commandpalette: of_add_command di una chiave che contiene una virgola | 0 — e is_recent la rileggeva come due comandi | -5 |
| commandpalette: un gruppo dichiarato in più volte (File, Edit, poi File) | due intestazioni « File » | una sola, al posto della sua prima apparizione; l'ordine dei comandi è conservato nel gruppo |
| commandpalette: la ricerca e gli accenti | preferences non trovava « Préférences » | gli accenti non contano |
| commandpalette: la lingua | la palette parlava inglese qualunque fosse PBT_SetLanguage | la lingua dell'applicazione; un is_placeholder impostato da voi non viene tradotto |
| commandpalette: la scorciatoia mostrata su una riga, tastiera AZERTY; AltGr nella ricerca | Ctrl+A si leggeva Ctrl+Q; digitare € (AltGr+E) lanciava il comando mostrato come Ctrl+Alt+E | il tasto è letto come la DLL lo nomina; un carattere digitato non è mai una combinazione |
commandpalette: una combinazione posata senza ipo_owner (tutta l'applicazione) prima di quella di una finestra, sullo stesso tasto | vinceva anche in quella finestra | la combinazione della finestra passa prima |
commandpalette: POSITION_ABSOLUTE | un comando di chiave x o y riportava la palette al bordo dello schermo; su due schermi andava su quello della finestra | il_x / il_y valgono, sullo schermo del punto richiesto |
commandpalette: inv_pump | variabile interna rimasta pubblica | protetta: non fa parte dell'API, niente da leggere né da scrivere |
commandpalette: un comando il cui testo cita __license | la palette non si apriva (-5) | si apre: solo una parola riservata scritta come chiave resta rifiutata |
La ricetta: (1) se il vostro codice solleva da sé ue_closed(), passategli un motivo (""); uno script che si limita a riceverlo compila così com'è; (2) se attendevate ue_opened dopo of_open, trattate anche ue_closed("cancelled"), "failed", "blocked"; (3) verificate 2 e -5 al ritorno di of_register_shortcut; (4) rinominate una chiave di comando che contiene una virgola.
11.37 radialmenu: una chiave nuda che mira giusto, una ruota aperta che segue l'applicazione, un'etichetta che si legge #
La ruota viene disegnata una volta, e l'applicazione continua a girare mentre è a schermo: ciò che cambiate nel frattempo ora conta. Il mozzo non scrive più nulla (non lo faceva più dalla 3.0, contrariamente a quanto diceva la documentazione): è il ramo puntato a mostrare l'etichetta intera.
| Cosa | 3.0 | 4.0 |
|---|---|---|
radialmenu: of_item con una chiave nuda (of_item("csv")) | cambiava etichetta e stato dell'unico ramo che la portava, ma i suoi colori non venivano disegnati, e la maniglia sopravviveva alla rimozione del padre | viene risolta nell'indirizzo completo (import/csv): stessa maniglia, colori compresi, liberata con il padre. Ambigua o sconosciuta: la maniglia non cambia nulla |
| radialmenu: una maniglia su un indirizzo non ancora aggiunto | un colore impostato tramite essa colorava il ramo aggiunto dopo a quell'indirizzo, anche dopo of_clear | non scrive nulla; of_clear dimentica tutti i colori |
radialmenu: of_show | non restituiva nulla | restituisce un long: 0, o -2 se il componente non è creato |
radialmenu: of_show(-1, -1) | apriva la ruota al cursore | la apre nel punto (-1, -1), come ogni coordinata negativa; al cursore è of_show() |
| radialmenu: un ramo rimosso, svuotato, disattivato o nascosto mentre la ruota è aperta | si sceglieva ancora: ue_item_selected per un ramo scomparso | non si sceglie più: ue_dismissed; of_clear, of_remove_item e of_reset chiudono la ruota aperta |
| radialmenu: clic destro altrove mentre la ruota è aperta | la nuova ruota sostituiva la vecchia senza ue_dismissed | ue_dismissed per la vecchia, poi la nuova ruota |
| radialmenu: etichetta lunga o vuota | tagliata a due righe e leggibile da nessuna parte; vuota, una fetta senza nulla | il ramo puntato la mostra intera; vuota, si mostra la chiave |
| radialmenu: lettura da destra a sinistra | la corona girava in senso orario, ← risaliva | la corona gira nell'altro senso, ← e → si scambiano |
La ricetta: (1) of_show restituisce un long: una chiamata semplice compila così com'è; (2) sostituite of_show(-1, -1) con of_show(); (3) se in ue_dismissed disfacevate ciò che impostavate all'apertura, nulla da fare: ora arriva anche quando una ruota ne sostituisce un'altra; (4) una maniglia ottenuta con una chiave portata da due rami non cambia più nulla: date l'indirizzo.
11.38 toaster: eventi che dicono quale toast, rifiuti che si dichiarano, un toast che aspetta di essere visto #
I tre eventi del toast cambiano firma, of_add_button restituisce un codice, e un toast non si perde più quando l'applicazione è ridotta a icona.
| Cosa | 3.0 | 4.0 |
|---|---|---|
toaster: ue_toast_clicked, ue_toast_action, ue_toast_dismissed | (string as_key …): as_key portava l'identificatore del toast, come testo | (long al_id, string as_key …): al_id è il numero restituito da of_show, as_key il is_key del toast (vuoto senza chiave) |
toaster: of_add_button | restituiva il numero di pulsanti; una chiave già presa, una chiave vuota e un quarto pulsante passavano senza una parola | restituisce 0; -5 senza aggiungere nulla per una chiave vuota, già presa, che contiene / o una barra verticale, o un quarto pulsante. Il numero si legge con of_count() |
toaster: of_show con un'impostazione fuori limite | mostrava comunque: un tipo sconosciuto come informazione, un angolo sconosciuto in alto a sinistra | restituisce -5 e non mostra nulla: is_kind, is_position o is_sound fuori dalle loro costanti, il_max_visible fuori da 0 a 20, il_timeout sotto TIMEOUT_AUTO |
toaster: la stessa is_key mostrata da due toaster | il secondo sostituiva il toast del primo e gli prendeva gli eventi; un aggiornamento conservava l'angolo d'origine | ogni toaster ha il suo; un aggiornamento riprende anche l'angolo, l'ancoraggio allo schermo e la finestra di ancoraggio |
| toaster: il suono | un suono di sistema a ogni toast, informazione e successo compresi; nessuno per un toast uscito dalla coda d'attesa | is_sound: SOUND_AUTO (predefinito) = solo errore e avviso, SOUND_ALWAYS, SOUND_NEVER; riprodotto quando il toast è richiesto, anche se attende il suo posto |
toaster: toast ancorati allo schermo da due finestre, o senza ipo_owner | si posavano esattamente uno sull'altro; il limite si contava per finestra | una sola pila per monitor e per angolo, e il_max_visible conta per monitor |
| toaster: un toast ancorato a una finestra ridotta a icona | finiva a -32 000 px e si spegneva senza essere visto | aspetta: non si mostra e il suo conto alla rovescia non scorre finché la finestra non torna |
| toaster: un toast che arriva mentre la pila è sorvolata | scalava il suo tempo e poteva sparire durante la lettura | nasce in pausa, come gli altri |
toaster: PBT_SetLanguage, PBT_SetDefaultTheme, PBT_SetDefaultThemeAccent, PBT_SetDefaultFont, PBT_SetFlowDirection mentre un toast è visualizzato | non lo raggiungevano; la dimensione del carattere restava 11 pt | lo seguono subito, dimensione del carattere compresa |
| toaster: il testo di un toast | non si selezionava; afferrare la barra di scorrimento di un testo lungo poteva rispondere e chiudere | si seleziona e si copia (clic destro, Copia); la selezione e la barra di scorrimento non chiudono più il toast |
toaster: il_button_count | variabile pubblica | privata: leggete il numero di pulsanti con of_count() |
toaster: un toast il cui testo cita __license | non si mostrava | si mostra: solo una parola riservata scritta come chiave resta rifiutata |
toaster: of_close di un toast visualizzato | nessun evento | ue_toast_dismissed, come la sua croce; un toast ancora in attesa, mai visto, non solleva nulla |
La ricetta: (1) aggiunga long al_id come primo argomento dei Suoi ue_toast_clicked, ue_toast_action e ue_toast_dismissed, e sostituisca Long(as_key) con al_id; as_key è ora la chiave del toast; (2) se leggeva il ritorno di of_add_button come un numero di pulsanti, legga of_count(); (3) per mantenere un suono su un'informazione o un successo, imposti is_sound = SOUND_ALWAYS.
11.39 messagebox: un campo obbligatorio vuoto non viene mai convalidato, scelte con chiavi uniche #
Cambiano cinque comportamenti; nessuna firma.
| Cosa | 3.0 | 4.0 | |
|---|---|---|---|
messagebox: ib_input_required e un pulsante predefinito con conto alla rovescia (of_add_button_timed) | il clic automatico convalidava la finestra con il campo vuoto (of_show restituiva il pulsante, of_input_value una stringa vuota) | il conto alla rovescia si esaurisce senza cliccare; il pulsante aspetta che il campo sia compilato | |
| messagebox: Esc o Alt+F4 su un pulsante insieme predefinito e di annullamento, campo obbligatorio vuoto | restituiva 1, come un clic su quel pulsante | restituisce 0: chiusa senza scelta | |
messagebox: of_add_choice | accettava una chiave già presa, o che contiene / o ` | ` | restituisce -5 e non aggiunge nulla |
messagebox: of_choose senza alcuna scelta | mostrava una finestra con un solo pulsante Annulla | non mostra nulla: stringa vuota, e of_get_last_error dice «no choice to show» | |
messagebox: i pulsanti delle finestre pronte (of_info, of_confirm, of_yes_no, of_prompt…) quando l'applicazione non ha impostato alcuna lingua | «Ok» | «OK», la parola del catalogo inglese («Cancel», «Yes», «No» per gli altri) |
La ricetta: (1) un campo obbligatorio si convalida ora a mano — se contava sul clic automatico per proseguire, dia al campo un valore predefinito (is_input_value); (2) dia a ogni scelta una chiave unica, senza / né |, e verifichi -5 se le chiavi provengono da dati.
11.40 Base comune: la lingua annunciata per impostazione predefinita, i numeri decimali di ogni postazione #
Due correzioni della base comune, valide per tutti i componenti; nessuna firma cambia.
| Cosa | 3.0 | 4.0 |
|---|---|---|
la lingua annunciata da un componente (<html lang>) | il francese, finché l'applicazione non sceglieva una lingua | l'inglese, la lingua predefinita dei componenti; la lingua scelta dall'applicazione la sostituisce sempre |
un numero decimale dato a una proprietà (id_*) | solo la virgola decimale veniva convertita: su una postazione il cui separatore decimale è un altro carattere, il valore non arrivava | il separatore decimale della postazione, qualunque sia, viene convertito |
La ricetta: niente da cambiare. Un'applicazione che sceglie la sua lingua la vede sempre applicata; un lettore di schermo che leggeva in francese un componente di un'applicazione inglese ora lo legge in inglese.
11.41 Tastiera, focus e spazio: ciò che i test della 4.0 hanno raddrizzato #
Comportamenti visti usando i componenti in una vera applicazione; nessuna firma cambia, si aggiunge un metodo.
| Cosa | 3.0 | 4.0 |
|---|---|---|
Invio su un CommandButton PowerBuilder che ha il focus | niente (il tasto andava perso) | il pulsante viene premuto (clicked), come in una finestra di dialogo Windows; il pulsante predefinito di una barra no |
Un componente disattivato (ib_enabled = false) | Tab si fermava su di esso | esce dall'ordine di tabulazione; riattivato (o of_reset), riprende il suo posto |
Una scorciatoia Ctrl su un carattere senza tasto proprio (AZERTY: - sul tasto 6, + con Maiusc) | Ctrl+- non trovava mai la sua scorciatoia | dopo il tasto, il carattere del layout attivo: Ctrl+-, Ctrl++, Ctrl+,, Ctrl+. scattano su ogni tastiera |
| La digitazione in un menu aperto (ricerca, lettere sottolineate) | un tasto della riga superiore dava la sua cifra (AZERTY: - arrivava come 6) | il carattere del layout; una lettera sottolineata &1 risponde sempre al tasto 1 |
Il calendario del selettore di data (toolbar) | solo con il mouse | anche da tastiera: frecce (giorno, settimana), Pag su/giù (mese), Inizio/Fine, Invio sceglie, Esc chiude |
| Alt con due barre multifunzione (o barre dei menu) nella stessa finestra, senza sottofinestra tra loro | il primo creato | il più vicino al focus sullo schermo |
breadcrumb in una barra molto stretta | il primo segmento non cedeva mai: il luogo corrente si riduceva a niente, il percorso debordava | dopo il centro, il luogo corrente cede fino a una lettera e «…», poi il primo segmento; nulla esce dalla barra |
menubar: una scelta fatta con il mouse nel menu a discesa | il focus restava sulla barra (Modifica > Incolla non incollava da nessuna parte) | il focus torna al controllo che lo aveva |
ribbon: digitare in una casella combinata e poi scegliere nel suo elenco | due ue_combo_changed: il testo digitato, poi la scelta | uno solo, la scelta |
toolbar: is_text = "" impostato in ue_text_changed, il focus nel campo | il vecchio testo tornava, con un secondo evento | il campo resta vuoto |
| Il focus restituito a un componente dopo una finestra della libreria (palette dei comandi) | la pagina, senza elemento: il cursore dell'editor di codice era sparito | l'elemento che lo aveva |
Un'etichetta con lettera sottolineata (&File) da destra a sinistra | lettere in disordine («ileF») | la parola si legge in ordine |
n_pbt_utils.of_dir_folders(as_dir, ref as_names[]) | DirList in una ListBox: 4,5 s per 30 000 cartelle, e la cartella corrente dell'applicazione cambiava | nuovo: le sottocartelle come le mostra Esplora risorse, ordinate, in un solo passaggio; -4 illeggibile, -5 percorso vuoto |
breadcrumb: of_add_children(as_keys, as_child_keys[], as_texts[]) | un ramo alla volta (of_add_child): 30 000 sottocartelle aprivano il menu in oltre 20 s | nuovo: un intero livello in una chiamata |
La ricetta: niente da cambiare. Un'applicazione il cui CommandButton con il focus doveva ignorare Invio lo disattiva (Enabled = false) o gli toglie il focus; per una cartella voluminosa, sostituisca il ciclo di of_add_child con un solo of_add_children.
11.42 Dati e tastiera: ciò che il secondo lotto di test della 4.0 ha raddrizzato #
Comportamenti visti usando i componenti di dati in una vera applicazione; nessuna firma cambia.
| Cosa | 3.0 | 4.0 |
|---|---|---|
| Invio o Esc premuti in un componente che non li prende | persi: il CommandButton PowerBuilder Default o Cancel non partiva | il tasto torna alla finestra PowerBuilder, come promette il capitolo 6.4: Esc preme il pulsante Cancel, Invio il pulsante Default |
PBT_SetLanguage seguito subito da un ordine al componente | il testo di un evento sollevato da quell'ordine (ue_error di xmltree) restava nella vecchia lingua | la lingua vale dall'ordine successivo |
jsontree, xmltree: il focus dato al componente (of_focus_webview, il tasto Tab) | restava sulla pagina: le frecce e Invio non andavano da nessuna parte | l'albero lo prende; F3 e Maiusc+F3 passano all'occorrenza successiva o precedente della ricerca |
xmltree: un errore segnalato DOPO l'ultimo carattere della sua riga | nessuna colonna sottolineata | la fine della riga è segnata (↵) |
codeeditor con a capo (ib_wrap) | la banda il_doc_line poteva stare una riga troppo in alto, sulla fine della riga precedente | le bande coprono tutte le righe visive della loro riga e seguono il ridimensionamento |
codeeditor: « Sostituisci tutto » e of_replace_all su un testo lungo | diversi secondi quando il focus era nell'editor; oltre, of_replace_all poteva restituire 0 | istantaneo, e il numero di sostituzioni è restituito; Ctrl+H con una ricerca vuota mette il cursore in « Trova » |
crosstab: « Aggiungi alle colonne » (o righe, filtri) dal menu di un chip, da tastiera | il focus si perdeva; solo Invio apriva il menu di un chip | il focus segue il chip nella sua nuova zona; Maiusc+F10 e il tasto Menu aprono anche il suo menu |
json: migliaia di of_add_* di seguito | quasi un secondo per 2 000 righe | qualche decina di millisecondi; il documento è lo stesso |
La ricetta: niente da cambiare. Un'applicazione che gestiva da sé Esc premuto in un componente (una scorciatoia registrata con of_register_shortcut) la mantiene: una scorciatoia viene prima della finestra.
11.43 Contenuti e media: ciò che il terzo lotto di test della 4.0 ha raddrizzato #
Comportamenti visti usando i componenti di contenuto e media in una vera applicazione; nessuna firma cambia.
| Cosa | 3.0 | 4.0 |
|---|---|---|
speechout: of_speak poi of_pause nello stesso script | ue_started e la prima ue_sentence arrivavano prima di ue_paused: la voce era annunciata come partita | ue_started è sollevato quando la voce inizia davvero a parlare; una pausa posta prima la trattiene: nulla è detto né annunciato fino a of_resume |
speechout: una lingua senza voce esatta sul computer (fr-CA dove c'è solo fr-FR) | ue_started annunciava la lingua richiesta (fr-CA) | ue_started annuncia la lingua realmente letta (fr-FR), dopo ue_voice_fallback |
webbrowser: Tab dopo l'ultimo controllo della barra degli indirizzi | il focus lasciava il componente per la finestra PowerBuilder | il focus entra nel sito, come in un browser; Maiusc+Tab dal sito torna alla barra |
webbrowser: ib_private = true impostato quando la navigazione è già privata | nessun effetto: il sito ritrovava ciò che aveva tenuto nella sessione privata | ogni volta una sessione privata nuova e vuota |
video a schermo intero: una finestra modale dell'applicazione (un MessageBox in ue_ended) | nascosta sotto il film, che le riprendeva la tastiera: l'applicazione sembrava bloccata | il film cede: la finestra passa davanti e riceve la tastiera; alla sua chiusura il film riprende lo schermo ed Esc ne esce |
tilesbox: un tasto freccia al bordo, accanto a una tessera più piccola | Freccia su su una tessera grande della prima fila saltava di lato, sulla piccola vicina | conta solo una tessera interamente oltre il bordo: al bordo, il focus resta dov'è |
dockcontainer: il_back_color / il_text_color di un pannello impilato | perse non appena la sua scheda era attiva (prendeva l'accento del tema) | la scheda attiva mantiene i colori del pannello, come la sua linguetta sulla barra |
progressbar: id_value impostato a ogni giro di un lungo ciclo | circa 2,5 s per 20 000 righe | ben meno di un secondo; la barra avanza sempre durante il ciclo |
La ricetta: niente da cambiare. Un'applicazione che contava su ue_started per sapere che of_speak era stato accettato legge invece il suo codice di ritorno (0); quella che confronta la lingua di ue_started con is_lang apprende ora il ripiego anche da questa differenza, oltre che da ue_voice_fallback.
11.44 Dati: leggere una cella, ordinare e cercare con più precisione (json, jsontree, xmltree, crosstab) #
Queste aggiunte della 4.0 non rimuovono alcuna firma. Due cambiano ciò che vedete senza che abbiate scritto nulla: Ctrl+C del crosstab copia ora le intestazioni, e ue_cell_double_clicked riceve un argomento in più.
| Cosa | 3.0 | 4.0 |
|---|---|---|
crosstab: ue_cell_double_clicked | ( string as_row_tuple_json, string as_col_tuple_json, double ad_value ) | ( string as_row_tuple_json, string as_col_tuple_json, integer ai_measure, double ad_value ): ai_measure è la posizione del valore cliccato due volte in Valori, a partire da 1; con le due tuple, è l'indirizzo che of_get_cell_value rilegge |
crosstab: Ctrl+C sulle celle | solo le cifre | le intestazioni insieme: i nomi delle colonne su una prima riga, il membro di ogni riga (il suo percorso, «North / Boston») in una prima colonna; ib_copy_headers = false restituisce solo le cifre |
crosstab: of_remove_field, of_get_cell_value | — | nuovi: togliere un campo da tutte le zone senza ricostruire il layout; leggere il valore di una cella tramite le sue tuple e la posizione della sua misura |
json: of_get_array, of_pretty (long al_indent) | — | nuovi: tutti gli elementi di un array in una chiamata; un rientro in spazi, o il documento compatto su una riga con 0 |
jsontree, xmltree: la ricerca | sempre senza distinzione di maiuscole, e dentro le parole | ib_find_match_case e ib_find_whole_word, come il codeeditor, con i pulsanti Aa e ab della casella di ricerca; per impostazione predefinita la ricerca resta quella della 3.0 |
La ricetta: uno script di ue_cell_double_clicked non ha nulla da cambiare, l'argomento si aggiunge prima del valore. Un'applicazione che incolla il risultato di Ctrl+C in un'elaborazione che si aspetta solo cifre imposta ib_copy_headers = false.
11.45 Navigazione e contenitori: schede da tastiera, pannelli con un doppio clic (tab, dockcontainer, ribbon, stepbar, listbar) #
Queste aggiunte della 4.0 non rimuovono alcuna firma. Tre gesti cambiano ciò che vede un utente senza che abbiate scritto nulla: il clic centrale e Ctrl+Tab su un tab, e il doppio clic su un pannello di dockcontainer o sulla barra del titolo della sua finestra mobile.
| Cosa | 3.0 | 4.0 |
|---|---|---|
tab: clic centrale su una scheda | nulla | chiude una scheda chiudibile, per la stessa via della sua croce: ue_tab_closing se ib_veto_close = true, poi ue_tab_closed; una scheda non chiudibile o disattivata non fa nulla |
tab: Ctrl+Tab, Ctrl+Maiusc+Tab, Ctrl+Pag giù / Pag su | nulla | la scheda successiva o precedente che può diventare attiva, in ciclo, che la tastiera sia nella banda o in una pagina ospitata (un controllo PowerBuilder, un altro componente); è un gesto: ue_selection_changing se ib_veto_selection = true, poi ue_selection_changed. Da un controllo fuori dal tab, il tasto resta alla finestra |
dockcontainer: doppio clic su un'intestazione o una scheda; sulla barra del titolo di una finestra mobile | nulla; la finestra mobile si ingrandiva | stacca il pannello in una finestra mobile (ue_panel_floated); sulla barra del titolo di quella finestra, lo riaggancia al suo posto (ue_panel_docked), come la sua croce |
dockcontainer: clic destro su un'intestazione o una scheda | nulla | un menu Stacca, Chiudi, Chiudi gli altri (gli altri pannelli chiudibili dello stesso gruppo); ogni chiusura pone la propria domanda |
dockcontainer: ib_veto_close, ue_panel_closing, of_close_panel, n_pbt_dock_panel.ib_closable | — | nuovi: la domanda prima della chiusura di un pannello (facoltativa, false per impostazione predefinita), la chiusura da codice (-4 se la rifiutate, -5 per il pannello principale o un pannello non chiudibile), e la possibilità di chiudere cambiata dal vivo |
ribbon: n_pbt_ribbon_item.is_image, id_min, id_max, id_step | fissati all'aggiunta | l'immagine di un controllo e l'intervallo di un contatore cambiano dal vivo e si rileggono; il valore di un contatore è riportato nel nuovo intervallo senza sollevare ue_value_changed, come id_value |
stepbar: STATE_WARNING, STATE_SKIPPED, NAV_VISITED | — | nuovi: un passo superato con un avviso (pallino ambra), un passo saltato (anello tratteggiato), e una modalità in cui ogni passo già raggiunto resta cliccabile, anche in avanti dopo un ritorno |
listbar: n_pbt_listbar_section.ib_pinned | — | nuovo: una sezione fissata in fondo alla barra (Impostazioni, Guida), che resta visibile quando la barra scorre, anche nella guida laterale; la disposizione salvata conserva l'ordine delle sezioni |
La ricetta: niente da cambiare. In una pagina di tab, Ctrl+Tab cambia ora scheda anche quando il focus è in un controllo della pagina, come in una finestra delle proprietà di Windows. Per ingrandire una finestra mobile del dockcontainer, resta il suo pulsante Ingrandisci.
11.46 Menu: il chevron della barra dei menu, un elenco a discesa nella barra degli strumenti, diecimila comandi (menubar, toolbar, commandpalette) #
Queste aggiunte della 4.0 non rimuovono alcuna firma. Un comportamento predefinito cambia: una barra dei menu troppo stretta non va più a capo, ripiega i suoi ultimi titoli in un chevron. E of_open di una palette di comandi non rifiuta più di aprirsi senza ipo_owner né ipo_receiver.
| Cosa | 3.0 | 4.0 |
|---|---|---|
menubar: una barra troppo stretta per i suoi titoli | andava a capo: la sua altezza seguiva le righe, ue_auto_height a ogni cambio di larghezza | resta su una riga: i titoli che non entrano, a partire dalla fine, passano nel menu di un chevron (le loro voci in cascata, Alt + la loro lettera li apre dal chevron, le frecce vi si fermano come su un titolo, a sinistra in RTL); l'altezza non cambia più. ib_wrap = true ripristina il comportamento precedente |
menubar: ib_track_hover, ue_item_hover, of_add_header, n_pbt_menubar_menu.is_align | — | nuovi: la voce puntata di un menu a discesa, per il testo di aiuto di una barra di stato (facoltativo, false per impostazione predefinita; un indirizzo vuoto alla chiusura), intestazioni di sezione in un menu a discesa, e un menu in fondo alla barra (ALIGN_END, Aiuto) |
toolbar: of_add_combo, of_add_combo_item, of_remove_combo_item, of_clear_combo, ue_combo_changed, n_pbt_toolbar_item.ib_editable | — | nuovi: un elenco a discesa nella barra, modificabile o no, che resta funzionante ripiegato nel chevron; il suo evento ha il nome e il significato di quello della barra multifunzione |
commandpalette: due palette sullo stesso ipo_owner | condividevano la loro coda di eventi (una poteva ricevere il ue_closed dell'altra), e la seconda riprendeva la combinazione della prima | ciascuna i propri eventi e la propria combinazione; la stessa combinazione registrata dalla seconda passa a questa (1). of_open e of_register_shortcut non restituiscono più -5 senza ipo_owner né ipo_receiver: gli eventi arrivano sempre |
commandpalette: migliaia di comandi | ogni riga disegnata: l'apertura e la digitazione rallentavano | sono disegnate solo le righe visibili: 10.000 comandi si aprono e si filtrano senza attesa |
| Scorciatoie di tutta la libreria: AltGr + un tasto che scrive un carattere (l'euro di una tastiera francese) | lanciava la scorciatoia Ctrl+Alt di quel tasto, anche in un campo PowerBuilder | il carattere viene digitato, nessuna scorciatoia parte; AltGr da solo non dà più la tastiera a una barra dei menu o a una barra multifunzione |
La ricetta: una barra dei menu la cui altezza variabile era voluta imposta ib_wrap = true; un'applicazione che riposizionava i suoi controlli in ue_auto_height a ogni ridimensionamento non ha più nulla da fare dopo il primo. Una scorciatoia dell'applicazione su Ctrl+Alt + una lettera che la tastiera dell'utente scrive con AltGr non parte più mentre digita: scegliete un altro tasto.
11.47 Contenuti e media: un registro riga per riga, la dimensione reale di un'immagine, un film che attende (statictext, picture, video) #
Queste aggiunte della 4.0 non rimuovono alcuna firma e non cambiano alcun valore predefinito. Due comportamenti si precisano: lo zoom di un'immagine può superare il suo tetto per raggiungere la dimensione reale, e un film da un URL letto senza rete lo dice.
| Cosa | 3.0 | 4.0 |
|---|---|---|
statictext: of_append_text, ib_follow_end | — | nuovi: un registro scritto riga per riga — solo la riga aggiunta parte verso il componente — e, come opzione, la vista che resta in fondo finché il lettore non risale |
statictext: ib_auto_width, ue_auto_width | — | nuovi: l'userobject prende la larghezza del proprio testo (facoltativo, false per impostazione predefinita), come fa ib_auto_height per l'altezza |
picture: id_max_zoom, il tasto 1 | lo zoom si fermava a 8.0 volte l'inquadratura, comunque: una grande scansione mostrata in piccolo non era mai leggibile pixel per pixel | il tetto si regola (id_max_zoom, 8.0 per impostazione predefinita); il tasto 1 mostra la dimensione reale, e il tetto sale fino a essa quando richiede di più |
video: ue_buffering, of_is_buffering | un film che attendeva i suoi dati restava fermo senza dire nulla | un anello nel colore d'accento del tema gira sull'immagine, e ue_buffering(true) poi ue_buffering(false) incorniciano l'attesa |
video: un film da un URL mentre la postazione non ha rete | «questo file è introvabile o illeggibile», ue_failed con REASON_UNSUPPORTED | «nessuna connessione di rete» sull'immagine, ue_failed con REASON_NETWORK |
La ricetta: niente da cambiare. Un registro che riscriveva is_text a ogni riga passa a of_append_text; un codice che verificava REASON_UNSUPPORTED per un film da un URL senza rete verifica REASON_NETWORK.
11.48 Revisione del 03/10/2026: una disposizione ripristinata viene segnalata, un'esportazione verso un percorso relativo finisce al posto giusto (toolbar, crosstab) #
Nessuna firma cambia. Due comportamenti si allineano alla regola della libreria: ogni cambiamento della disposizione viene segnalato, e un percorso relativo di scrittura si risolve come per le altre esportazioni.
| Cosa | 3.0 | 4.0 |
|---|---|---|
toolbar: of_set_layout | nessun evento | solleva ue_layout_changed, come il dockcontainer e il datagrid: ogni cambiamento della disposizione viene segnalato, che venga dall'utente o dal Suo codice |
crosstab: of_export_csv, of_export_xlsx verso un percorso relativo | scritto nella cartella corrente del momento — che un DirList o una finestra di file potevano aver spostato; ue_csv_saved / ue_xlsx_saved restituivano il percorso così come dato | scritto nella cartella in cui l'applicazione è partita, come le altre esportazioni native; l'evento restituisce il percorso completo; un percorso che dipende dalla cartella corrente di un'unità (\x, C:x) viene rifiutato |
La ricetta: un'applicazione che salva la disposizione in ue_layout_changed salva di nuovo lo stesso valore dopo of_set_layout — senza conseguenze. Un'esportazione che contava sulla cartella corrente del momento indica un percorso completo.
← Migrare dalla 2.0 alla 3.0 · Sommario · Note di versione →