• Non ci sono risultati.

2.2 Introduzione al framework

2.2.4 Stati e modalità di interazione

Consideriamo una applicazione che consente di visitare un museo virtuale, in cui è pos- sibile selezionare le opere esposte per ottenere informazioni su di esse. In una possibile implementazione possiamo individuare almeno tre stati significativi:

• Lo stato principale, nel quale l’utente naviga all’interno del museo e può selezionare le opere esposte.

• Uno stato nel quale viene visualizzata la sola opera selezionata ed in cui l’utente ha la possibilità di esaminarla da vicino attraverso una apposita metafora (es. l’Orbiting). Viene inoltre mostrata una descrizione dettagliata dell’opera e della sua storia. • Una schermata iniziale, comprensiva di un pannello di configurazione.

Ad ognuno di questi stati corrisponderà un diverso insieme di oggetti da disegnare a schermo, di controller, ed eventualmente di dispositivi di input. Da quanto detto tali oggetti sono tutti listener dell’oggetto “applicazione”, quindi uno stato dell’applicazione può essere definito come un insieme di listener registrati presso IFApplication5.

Ad ogni stato è associato un identificatore unico, che può essere di tipo stringa o intero. L’identificatore dello stato di default deve essere dichiarato esplicitamente, definendo la costante IFC_APP_DEFAULT_STATE_ID all’inizio del programma (come mo- strato nel listato 2.1, riga 5). Ovviamente definendo questo identificatore se ne dichiara

implicitamente anche il tipo (stringa o intero), quindi gli identificatori degli altri stati dovranno essere coerenti con questa scelta.

I principali metodi che la classe IFApplication definisce per la gestione degli stati sono i seguenti:

CreateState - Crea un nuovo stato (senza modificare lo stato corrente).

RemoveState - Elimina lo stato specificato (se si cerca di eliminare lo stato corrente, la rimozione non ha effetto).

ChangeState - Effettua un cambiamento di stato.

Una volta richiesto un cambiamento di stato, ma prima che questo venga portato a termi- ne, viene generato l’evento StateWillChange. Tale evento ha il fine di dare la possibilità agli oggetti interessati di prepararsi all’imminente cambio di stato, ad esempio effettuando operazioni di “cleanup” e resettando il proprio stato interno.

La creazione e l’inizializzazione degli stati avviene tipicamente nella OnInit, seguendo la seguente procedura:

1. Si crea un nuovo stato per mezzo del metodo CreateState.

2. Si passa allo stato appena creato invocando il metodo ChangeState.

3. Si aggiungono al nuovo stato corrente tutti gli elementi che lo compongono6.

4. Si ripete questa procedura per ognuno degli stati rimanenti.

5. Infine si ripristina lo stato di default come stato corrente per mezzo della seguente chiamata:

ChangeState(IFC_APP_DEFAULT_STATE_ID) Il listato seguente illustra questa la procedura:

/* Nome della main class */

#d e f i n e IFAPPNAME E s e m p i o S t a t i

// ID degli stati dell’applicazione

// In questo esempio si è scelto di usare identificatori interi

#d e f i n e IFC_APP_DEFAULT_STATE_ID 0

#d e f i n e IFC_APP_STATE1_ID 1

#d e f i n e IFC_APP_STATE2_ID 1

[ . . . ]

c l a s s IFAPPNAME : I F A p p l i c a t i o n { I n i t ( userParam ) ;

[ . . . ] } ;

function IFAPPNAME : : I n i t ( userParam ) {

[ . . . ]

// Creazione dello stato 1

t h i s. C r e a t e S t a t e (IFC_APP_STATE1_ID) ;

t h i s. ChangeState (IFC_APP_STATE1_ID , f a l s e) ;

// Aggiunta degli elementi dello stato 1

[ . . . ]

// Creazione dello stato 2

t h i s. C r e a t e S t a t e (IFC_APP_STATE2_ID) ;

t h i s. ChangeState (IFC_APP_STATE2_ID , f a l s e) ;

// Aggiunta degli elementi dello stato 2

[ . . . ]

// Ripristino e inizializzo lo stato iniziale

t h i s. ChangeState (IFC_APP_DEFAULT_STATE_ID, f a l s e) ;

// Aggiunta degli elementi dello stato 0

[ . . . ] }

Si noti il secondo parametro del metodo ChangeState. Esso specifica se deve essere inviato l’evento StateWillChange prima dell’effettivo cambiamento di stato. In fase di inizializza- zione questo parametro deve essere sempre settato a false (oppure omesso, è un parametro opzionale). Al contrario, ad ogni successiva invocazione questo parametro dovrebbe essere sempre settato a true, al fine di dare la possibilità agli oggetti interessati di prepararsi all’imminente cambiamento di stato.

All’interno di uno stato è possibile definire più sotto-stati, detti “modalità di intera- zione”. Il nome deriva dal fatto che, passando da una modalità all’altra, l’utente può interagire in maniera differente con l’ambiente virtuale. Modalità di interazione differenti si distinguono tra loro in funzione di:

• La metafora di interazione in uso (per eseguire task differenti o per eseguire uno stesso task in modi diversi).

• L’impiego di un differente insieme di dispositivi. • Ecc...

In termini implementativi questo si traduce nella realizzazione delle modalità di intera- zione come stati degli oggetti controller (anziché stati della classe IFApplication). In altri termini, gli oggetti controller modificano il loro comportamento (cioè le azioni da essi intraprese in risposta agli eventi) al variare della modalità di interazione corrente. Ovviamente, a seconda della propria funzione, un controller può ignorare completamen- te questo meccanismo, oppure supportare soltanto un sottoinsieme delle modalità usate dall’applicazione: quando ad un controller viene notificata l’attivazione di una modalità da lui non supportata, esso si limita ad ignorare la notifica, mantenendo il proprio stato corrente. Da quanto detto segue che i metodi per la gestione delle modalità di intera- zione sono forniti dalle classi controller, anziché da IFApplication. Esamineremo questi metodi nel paragrafo 3.4. La classe IFApplication si limita a fornire i meccanismi per richiedere un cambio di modalità e per inoltrare tale richiesta agli oggetti interessati: il metodo preposto a questo è ChangeInteractionModality, la cui implementazione consiste nella generazione di due eventi:

InteractionModalityWillChange - Ha lo scopo di preparare gli oggetti interessati all’im- minente cambio di modalità.

InteractionModalityChange - Rappresenta la vera e propria richiesta di cambiamento di modalità di interazione. Alla ricezione di tale evento i controller modifiche- ranno il loro stato interno di conseguenza.

Così come per gli stati dell’applicazione, esiste una modalità di interazione predefinita, il cui identificatore (di tipo intero o stringa) deve essere definito per mezzo della costante IFC_CTRL_DEFAULT_INTERMOD_ID(come mostrato nel listato2.1, riga7).

Nota

Una volta conclusa la fase di inizializzazione (OnInit), i comandi relativi alla creazio- ne, alla rimozione e il cambio di stati e modalità di interazione devono essere eseguiti sfruttando il meccanismo di esecuzione differita, come descritto nel paragrafo2.2.6.

Documenti correlati