GUI Frameworks - part 3/3: Operazioni Tipiche
August 3rd, 2006 di Aaron Brancottiin c, gui, oop, widget | Letture: 2543
Dopo la puntata introduttiva e quella su modalità e ambienti, è il tempo di parlare delle operazioni tipiche che vengono compiute in una GUI.
Intersection Test
Un test di intersezione è un test a livello molto basso, che permette di capire se una certa coordinata (x,y) si trovi “dentro” o “fuori” un dato widget. Viene solitamente usato per capire se abbiamo o meno selezionato un widget col mouse.
Focus
Il concetto di focus è molto semplice: quale è il widget “attivo”, ovvero quello al quale devono essere girati gli eventi di input? Solitamente le GUI risolvono il problema con il concetto di “selezione”: cliccando su qualcosa una volta, questo qualcosa diventa attivo e prende il focus. Ogni successivo input viene girato a lui.
Questo ci permette di selezionare una icona con un singolo click e azionarla con un Enter, oltre che azionarla con un doppio click, ad esempio. Si noti che la GUI chiamata “X” fa eccezione, essendo usato continuamente un intersection test: l’oggetto sopra al quale viene posizionato il mouse guadagna automaticamente e istantaneamente il focus senza necessità di alcun click. Questo è anche il comportamento dei link HTML: basta un click per navigarli.
Picking
Anche se può non essere spontaneo da capire, il fatto di avere cento icone, di cliccare in un punto e di determinare quale icona è stata selezionata non è gratuito ed immediato. È spesso necessario un test di picking, dove sono note le coordinate di ogni oggetto, quelle del puntatore del mouse ed è quindi necessario un test di intersezione su ognuno degli oggetti per capire quale sia stata la selezione dell’utente.
Molti widgets compositi come Liste e Alberi hanno già implementati test di picking e sono in grado di restituire direttamente l’ultimo o gli ultimi item selezionati; in altri casi è necessario implementare esplicitamente queste procedure.
Acceleratori
Molte GUI permettono di associare determinati comandi a ben precise sequenze di pressione dei tasti della tastiera, rendendo anche personalizzabile questa possibilità. Questa capacità viene definita keystroke acceleration o più brevemente accelerazione, anche se la seconda definizione tende a confondere le idee.
Problemi Tipici
Quali sono i problemi tipici che un programmatore si trova ad affrontare quando sviluppa la parte visuale di una applicazione?
Coerenza dell’Interfaccia
Un problema che può diventare enormemente complesso se non approcciato in maniera corretta fin dalle prime righe di codice è il mantenimento della coerenza dell’interfaccia.
Una GUI può aumentare la propria complessità in maniera indefinita, con possibilità di relazioni tra i vari widget, dialogs, viste e documenti. Far si che quando l’utente seleziona un certo pulsante si disabilitino dei menu, si riempiano automaticamente delle textbox, vengano invocate delle procedure di determinati oggetti, venga aggiornato il documento e tutte le viste ad esso associate e chissà cos’altro diventa rapidamente un lavoro titanico, proprio a causa di questa relazione molti-a-molti tra un numero potenzialmente molto alto di oggetti della più disparata natura.
Abbiamo già visto che il pattern noto come Observer è proprio dedicato a risolvere questo tipo di problema; in effetti è un approccio utilizzato da molti toolkit come Qt, che utilizza il concetto di “slot”, ovvero di un Observer a livello di ogni singolo widget. Ogni oggetto, quando cambia il suo stato, può emettere una “segnalazione”; ogni altro oggetto interessato si può registrare presso di lui in modo da riceverla. In questo modo si spera che la GUI non vada “fuori sync” e, nel caso questo accada, si sa dove guardare: negli slot del widget che ha provocato la perdita di coerenza.
MVC o non MVC?
Una questione filosofica da sempre dibattuta verte sul livello al quale operare una separazione netta tra Vista, Documento e Controller. Se per i widget che implementano degli ADT è molto comoda – poiché possiamo avere tutti i dati che popolano una lista da una parte e il codice che la crea dall’altra, perfettamente disaccoppiati, per altri widget molto più semplici come un bottone questa distinzione ha poco senso o non ne ha del tutto.
Non è quindi raro trovare detrattori del paradigma MVC e d’altro canto molti framework implementano questa distinzione in maniera mista, fornendo degli oggetti TreeDocument e ListDocument ma non ButtonDocument o TextBoxDocument, ritenuti troppo elementari per giustificare questo aumento di complessità.
Descrizione e Disegno
Un grande problema davanti al quale si trova chi sviluppa la parte visuale di una interfaccia è relativo a come disegnare questa interfaccia.
Ovviamente ci sono vari approcci, il più diretto dei quali è… sviluppare la parte grafica e scrivere direttamente il codice che la controlla. A sua volta, “sviluppare la parte grafica” può voler dire tracciare direttamente da codice linee e punti, oppure disegnare delle maschere con un programma quale Photoshop.
Il primo metodo è da evitare per interfacce che siano almeno minimamente complesse, poiché specificare coordinate, colori, spessori di bordi etc. agendo direttamente sul codice è un approccio decisamente complesso e lento e quindi costoso. Vediamo quindi qualche alternativa.
Tools Grafici
Il metodo più comodo per creare una GUI è sicuramente quello di utilizzare un editor grafico, che ci permetta di posizionare direttamente widget e pagine laddove desideriamo ed eventualmente caricare immagini create esternamente. Questi editor sono solitamente chiamati WYSIWYG (pronuncia: uaisiuaigh), che sta per “What You See Is What You Get”, Quello Che Vedi è Quello Che Ottieni.
L’output di un simile editor può essere dei più disparati: può generare direttamente del codice in un linguaggio di programmazione che, una volta eseguito, crei la GUI così come noi l’abbiamo disegnata, oppure può creare del codice descrittivo che possa successivamente essere utilizzato da librerie o preprocessori in grado di creare dinamicamente la GUI.
Linguaggi di Descrizione
In effetti la seconda possibilità precedentemente descritta, che ha peraltro avuto un notevole successo grazie anche alla standardizzazione imposta dal successo universale di XML, è la possibilità di descrivere una interfaccia mediante un linguaggio analogo all’HTML. In effetti quest’ultimo ci mette a disposizione una serie (minima) di widget quali bottoni e liste, ed alcuni metodi per lo scambio di dati con un server.
È abbastanza logico aspettarsi che, mediante un opportuno schema XML, interfacce composte da widget di complessità arbitraria possano essere descritte, anche se poi sviluppare un editor grafico è tutt’altro discorso. In verità vedremo che questo è un concetto addirittura antico, quando parleremo di X. Questa è peraltro la strada seguita da Mozilla con XUL.
Alcuni Esempi
Esaminiamo ora alcuni GUI Framework esistenti, cercando di ritrovare quanto discusso finora e analizzando vantaggi e svantaggi di vari approcci.
Microsoft MFC
Le Microsoft Foundation Classes sono un framework storico, nativo dell’ambiente Microsoft Visual C++, nato per incapsulare l’estrema complessità della programmazione Windows, ovvero delle cosiddette API Win32. Le MFC risentono pesantemente di un design spalmato nel tempo, che ha cercato di incapsulare Windows mano a mano che questo evolveva e che le rende estremamente poco lineari e difficili da imparare.
Le numerose mani che hanno architettato questo framework si vedono tutte; l’impressione che si ha è quella di una galleria d’arte dove, di fianco a un Picasso, possiamo trovare un Tintoretto, un Dalì e un Ligabue. Le MFC si basano sulla separazione vista-documento, ma le procedure di serializzazione dei dati sono oscure e si basano pesantemente su comandi del preprocessore C++, che sarebbero da evitare come la peste.
Sono disponibili decine di widget con centinaia di varianti, a volte incompatibili tra loro; le MFC si basano su una classe “stringa” nativa, chiamata CString, che rende il codice MFC praticamente intrasportabile. Del pacchetto fanno parte un editor visuale di dialogs/risorse/handlers in grado di generare codice C++ e svariati Wizard in grado di generare delle applicazioni neutre, dalle numerose opzioni che spesso non funzionano come dovrebbero. D’altra parte, creare a mano una applicazione Win32 complessa, ad esempio un server OLE autoregistrante che supporta drag&drop etc etc sarebbe ancora più complesso, quindi grazie lo stesso.
Sun (Java) Swing
Swing è il successore di AWT, entrambi ambienti enormi nativi del linguaggio Java. Il set di widgets è estremamente completo; il paradigma MVC è supportato per i widget più complessi, quali liste e alberi.
Grazie ad alcune caratteristiche del linguaggio, molte operazioni quali la serializzazione di una classe sono banali. Gli handlers degli eventi vengono specificati mediante Listeners, che ancora una volta sono degli observers che dichiarano, all’interno di ogni classe, di essere interessati alla ricezione di determinati eventi e specificano direttamente il codice che deve essere eseguito in risposta.
Un concetto interessante di Swing è che oltre alla possibilità di costruire una GUI posizionando i widgets esplicitamente, si può lasciare il compito di ridisporre gli stessi nella maniera migliore possibile a svariati algoritmi geometrici chiamati layouts.
Questo approccio è particolarmente potente quando non si sa a priori quali dimensioni avranno le pagine invocate da un utente (ovvero quando non si conosce, ad esempio, la risoluzione del suo monitor), poiché si specifica la pagina di una GUI a livello logico senza preoccuparsi dei singoli pixel. Se Swing ha un punto debole, è certamente la sua corposità e un certo “gusto per il prolisso” dei progettisti – peraltro pienamente riscontrabile anche in Java3D.
X
X è una GUI non molto ricca ma molto antica, ed anzi è quella dalla quale il termine “widget” ha avuto origine. Tra le sue particolarità cc’è sicuramente il fatto che, essendo nata in ambiente Unix, ha una struttura di tipo client-server e distribuito.
X si basa su una serie di comandi che vengono interpretati in tempo reale da un sistema di rendering chiamato X-Terminal, che può essere un dispositivo hardware (un terminale intelligente) o un programma di emulazione.
X è quindi una specifica per l’utilizzo di una GUI a livello di network, basata su un linguaggio di descrizione. Tra le caratteristiche tipiche di X c’è il suo tipo di focus, per cui una finestra acquista il focus non appena il mouse viene posizionato sopra la stessa. Non c’è quindi il concetto di singolo click per “selezionare” un oggetto visuale.
Autodesk CyberSpace Developement Kit
Il CDK di Autodesk è sconosciuto ai non addetti ai lavori, essendo uno dei pochi framework dedicati alla creazione di ambienti tridimensionali interattivi in tempo reale, ovvero di Realtà Virtuali (VR).
Se la programmazione di detti ambienti continua a rispettare molti dei concetti base fin qui visti (event driven programming, MVC, rendering independence), altri vengono violati o perdono completamente di senso (SDI/MDI) e gli stessi widgets, così come le interfacce fisiche come mouse e joystick devono essere completamente ripensati.
Alcuni concetti trovano una naturale generalizzazione, come i test di intersezione mouse-widget che diventano picking e collision detection. Nuovi pattern emergono: il concetto di navigazione diventa letterale e il terrain following è una necessità per non perdersi nell’universo virtuale.
Conclusioni
Siamo al termine di questo viaggio in tre puntate alla scoperta della “logica” aldilà del pixel. Abbiamo “smontato” una GUI e l’abbiamo “ridotta” a codici, ambienti e linguaggi che sono molto più nelle corde dei software engineer che che in quelle dei designer. Ma forse, proprio dopo aver fatto lo sforzo di percorrere questo ponte culturale, saremo in grado di progettare ancora meglio. In modo ancora più consapevole degli impatti di processo e di coding che ha ogni piccolo interattore. …e speriamo che anche gli “utenti finali”, se non la qualità, apprezzino almeno il sudore.





December 11th, 2006 at 11:34 pm
Davvero ottimo articolo, ho letto con grande interesse questo tutorial visto che sono in procinto di creare una GUI per il mio piccolo engine 3D ( almeno ci provo ), ho anche capito finamente cosa si intende per WYSIWYG e Event Driven Programming.
Ancora complimenti per l’articolo.
January 28th, 2007 at 2:22 am
Complimenti!
Bellissimi articoli, chiari, precisi e lineari nell’esposizone.
Sarebbe bello poter leggere ulteriori approndimenti sule GUI
March 19th, 2007 at 6:41 am
Interessantissimo.
é possibile aver dei consigli, o dei suggerimenti per delle risorse, che approfondiscano il tema SDI vs MDI?
March 28th, 2007 at 10:23 am
Ciao a tutti,
grazie per i feedback così positivi…
Luca: sta iniziando a farsi strada un nuovo mondo di interfacce multimodali e devices incredibili anche fuori dai laboratori e direi che Idearium è uno dei luoghi di elezione per queste cose. Sicuramente parleremo ancora di GUI dal punto di vista della programmazione. Questo era il “dove siamo”, il “dove stiamo andando” è tutt’altra cosa…
Xander: certamente si, contattami al mio sito http://www.babeledunnit.org oppure aaron@icona.it. C’e’ una quantita’ incredibile di roba la’ fuori; magari posso farti risparmiare un po’ di tempo dandoti qualche link mirato..
Aaron