Un menù è uno SCREEN che assiste l'utente nel scegliere una porzione
di un dato insieme di voci. La libreria menù
è una estensione
delle curese che supporta la facile programmazione di gerarchie di menù
con una interfaccia uniforme ma flessibile.
La libreria menù
apparve per prima nel System V di AT&T.
La versione qui documentata è il codice freeware menu
distribuito
con le ncurses
.
I vostri moduli che usano la libreria menù dovranno importare le dichiarazioni della libreria con
#include <menu.h>
e dovranno linkarsi esplicitamente con la libreria menù usando
l'argomento -lmenu
. Notate che dovranno anche linkare la
libreria ncurses
tramite -lncurses
. Molti linker
moderni eseguono due passaggi e accetteranno qualunque ordine,
ma è comunque buona pratica usare -lmenu
per prima e
-lncurses
per seconda.
I menù creati con questa libreria consistono in una collezione di voci (items) composte da una parte nome ed una parte descrizione. Per creare i menù, create gruppi di queste voci e le connettete con il corpo (frame ) del menù.
Il menù può quindi venir pubblicato, cioè scritto in una finestra associata. Attualmente ciascun menù ha due finestre associate: un contenitore in cui il programmatore può scarabocchiare titoli e bordi, ed una sottofinestra in cui le voci del menù vengono visualizzate. Se una sottofinestra è troppo piccola per mostrare tutte le voci, diventerà un'apertura scorrevole sulla collezione di voci.
Un menù può anche venir spubblicato (cioè, cancellato), e finalmente rilasciato per rendere disponibile al riuso lo spazio associato a esso ed alle sue voci.
Il flusso generale del controllo di un programma menù somiglia a questo:
curses
.new_item()
.new_menu()
.menu_post()
.menu_unpost()
.free_menu()
.free_item()
.curses
.I Menù possono essere del tipo a valori multipli (la norma)
oppure a valore singolo (consultate il manuale alla pagina
mitem_opts(3x)
per vedere come impostarlo).
Entrambi i tipi hanno una voce corrente.
È possibile leggere il valore scelto da un menù a valore singolo
semplicemente consultando la voce corrente.
Troverete l'insieme dei valori selezionati da un menù a valori multipli
applicando ciclicamente la funzione predicato item_value()
.
Il codice di gestione del vostro menù può utilizzare la funzione
set_item_value()
per spuntare le voci nell'insieme.
Le voci di menù possono diventare non-selezionabili mediante la
set_item_opts()
oppure la item_opts_off()
con argomento O_SELECTABLE
.
Benchè questa sia l'unica opzione per ora implementata nei menù,
è buona pratica attivarla con questo metodo in quanto altri bit
potrebbero essere settati.
La libreria menù calcola una dimensione minimale della finestra basandosi sui seguenti valori:
La finzione set_menu_format()
vi permette di impostare
la dimensione massima del riquadro o pagina-menù che
sarà usata per visualizzare le voci del menù.
Potete recuperare il formato associato ad un menù usando
menu_format()
. I valori iniziali sono rows=16,
columns=1.
L'attuale pagina-menù può essere più piccola delle dimensioni indicate nel formato. Questo dipende dal numero e dimensioni delle voci e se O_ROWMAJOR è attiva. Questa opzione (inizialmente attiva) porta le voci del menù ad essere visualizzate in una modalità a ''scansione'', cosicchè la prima coppia di voci si dispone fianco-a-fianco sulla riga iniziale, se possibile. L'alternativa è il modello ''incolonnato'', che prova a disporre il maggior numero di voci nella prima colonna.
Come accennato prima, un formato di menù non sufficientemente largo da permettere a tutte le voci di essere visibili sullo schermo, darà origine ad un menù verticalmente scrollabile. Potete scorrerlo mediante richieste al gestore di menù, che verrà descritto nella sezione gestione dell'input.
Ogni menù è dotato di un segnaposto utilizzato
per marcare le voci selezionate;
vedere il manuale alla pagina menu_mark(3x)
per dettagli.
Il segnaposto influisce anche sulla dimensione della pagina-menù.
La funzione scale_menu()
restituisce la dimensione
minima calcolata in base a tutti questi fattori.
Esistono altri attributi di visualizzazione di un menù, incluso
un attributo di selezione, un attributo per voci selezionabili,
uno per voci non-selezionabili e un carattere riempitivo usato
per separare il nome di una voce con il testo della sua descrizione.
Queste hanno ragionevoli valori iniziali che la libreria vi permette
di modificare (vedere il manuale alla pagina menu_attribs(3x)
.
Ogni menù ha, come già menzionato, una coppia di finestre associate. Entrambe queste finestre vengono riempite quando il menù viene pubblicato e cancellate quando viene spubblicato.
La finestra esterna non viene in alcun modo usata dalle routine del menù. Esiste per permettere al programmatore di associare al menù un titolo, un bordo o perfino un testo di ''help'' ed averli correttamente visualizzati o cancellati nel momento della pubblicazione o spubblicazione. La finestra interna o sottofinestra è quella in cui la pagina del menù viene correntemente visualizzata.
Inizialmente entrambe le finestre sono stdscr
.
Potete impostarle mediante le funzioni in menu_win(3x)
.
Quando chiamate la menu_post()
, il menù viene scritto
nella sottofinestra. Chiamando la menu_unpost()
, viene
cancellato dalla sottofinestra. Comunque nessuna di queste funzioni
modifica lo schermo visibile. Per far ciò chiamate la
wrefresh()
o le equivalenti.
Il ciclo principale del vostro codice di gestione del menù dovrà
eseguire menu_driver()
ripetutamente.
Il primo argomento di questa routine è un puntatore ad un menù;
il secondo e un comando al menù.
Dovrete scrivere una routine di cattura dell'input che associ
i caratteri dell'imput ai comandi del menù, e passare il suo
output alla menu_driver()
.
I comandi del menù sono completamente documentati nel manuale
alla pagina menu_driver(3x)
.
Il più semplice gruppo di comandi è
REQ_NEXT_ITEM
,
REQ_PREV_ITEM
, REQ_FIRST_ITEM
,
REQ_LAST_ITEM
, REQ_UP_ITEM
,
REQ_DOWN_ITEM
, REQ_LEFT_ITEM
,
REQ_RIGHT_ITEM
.
Questi spostano la voce correntemente selezionata.
Queste richieste possono causare lo scorrimento della pagina-menù
se questa è solo parzialmente visualizzata.
Ci sono richieste esplicite di scorrimento che cambiano
la voce corrente (perchè la locazione selezionata non cambia,
mentre cambia la voce in essa). Sono le REQ_SCR_DLINE
,
REQ_SCR_ULINE
, REQ_SCR_DPAGE
, e la
REQ_SCR_UPAGE
.
La REQ_TOGGLE_ITEM
seleziona o de-seleziona la voce corrente.
Viene usata nei menù a valori multipli; se la usate con l'opzione
O_ONEVALUE
attiva,
vi verrà ritornato l'errore (E_REQUEST_DENIED
).
Ogni menù è associato ad un buffer di confronto. La logica della
menu_driver()
prova ad accumularvi i caratteri ASCII
stampabili che le vengono passati; quando uguagliano un prefisso o
il nome di una voce, quella voce viene selezionata.
Se aggiungendo un nuovo carattere non fornisce una nuova scelta,
il carattere viene rimosso dal buffer, e la menu_driver()
ritorna E_NO_MATCH
.
Alcune richieste modificano direttamente il buffer di confronto:
REQ_CLEAR_PATTERN
, REQ_BACK_PATTERN
,
REQ_NEXT_MATCH
, REQ_PREV_MATCH
.
Le ultime due sono utili quando l'input nel buffer soddisfa più
di una voce in un menù a valori multipli.
Ogni valida richiesta di scorrimento o di cambio di voce svuota
il buffer di confronto. È anche possibile cambiare esplicitamente
il buffer mediante la set_menu_pattern()
Infine, ogni richiesta al gestore del menù superiore in valore
alla costante MAX_COMMAND
è considerata un comando
specifico dell'applicazione. Il codeice della menu_driver()
li ignora e ritorna E_UNKNOWN_COMMAND
.
Diverse opzioni possono influenzare l'aspetto visivo
e l'elaborazione dell'input dei menù.
Vedi il manuale alla pagina menu_opts(3x)
per dettagli.
È possibile cambiare la voce corrente dal codice dell'applicazione:
è comodo se volete scrivere vostre proprie richieste di navigazione.
È inoltre possibile cambiare esplicitamente la prima riga del menù.
Vedere mitem_current(3x)
.
Se la vostra applicazione ha bisogno di cambiare il cursore della
sottofinestra del menù per qualunque ragione,
la pos_menu_cursor()
lo ripristinerà alla
locazione giusta per continuare la gestione del menù.
È possibile agganciare del codice da far eseguire
all'inizializzazione del menù, al momento della visualizzazione,
ed ogniqualvolta la voce selezionata cambi.
Vedere menu_hook(3x)
.
Ogni voce ed ogni menu è associato ad un puntatore d'utente a cui
si possono agganciare dati dell'applicazione.
Vedere mitem_userptr(3x)
e menu_userptr(3x)
.