Visualizzatori

Perché utilizzare un visualizzatore quando è stato visto che contributi dell'interfaccia utente del workbench quali viste, editor, procedure guidate e finestre di dialogo possono essere implementati direttamente con i widget SWT?  

I visualizzatori consentono di creare widget utilizzando comunque i propri oggetti modello.  Se si utilizza direttamente un widget SWT, è necessario convertire i propri oggetti in stringhe e immagini previste da SWT.  I visualizzatori fungono da adattatori sui widget SWT, gestendo il codice comune per gli eventi widget che, diversamente, dovrebbero essere implementati dall'utente. 

Per prima cosa è stato descritto un visualizzatore nel contributo vista dello strumento readme, all'interno di ReadmeSectionsView.

   public void createPartControl(Composite parent) {
      viewer = new ListViewer(parent);
      ...
   }
Nota:  i visualizzatori possono essere utilizzati per fornire l'implementazione a viste ed editor del workbench. Il termine visualizzatore non implica l'utilizzo per la sola implementazione di viste. Ad esempio, TextViewer viene utilizzato per l'implementazione in molti degli editor di plugin e del workbench.

Visualizzatori standard

JFace fornisce visualizzatori per la maggior parte dei widget non comuni in SWT. L'utilizzo più comune che si fa dei visualizzatori è per i widget di elenco, struttura ad albero, tabella e testo. 

Ogni visualizzatore dispone di un widget SWT associato. Questo widget può essere creato implicitamente fornendo il Composite principale in un costruttore di visualizzatore, oppure esplicitamente creando prima il widget, quindi fornendolo al visualizzatore nel rispettivo costruttore.

Visualizzatori orientati all'elenco

Elenchi, strutture ad albero e tabelle condividono molte funzioni comuni dal punto di vista dell'utente, ad esempio l'inserimento di oggetti, la selezione, l'ordinamento e il filtro. 

Questi visualizzatori conservano un elenco di oggetti di dominio (denominati elementi) e li visualizzano nel corrispondente widget SWT. Un visualizzatore di elenco è in grado di ottenere un etichetta di testo da un elemento dell'elenco.  Ottiene tale etichetta da un ILabelProvider che può essere impostato nel visualizzatore. I visualizzatori di elenco sono in grado di eseguire l'associazione dai callback dei widget agli elementi riconosciuti dal client del visualizzatore.

I client che utilizzano un widget SWT semplice devono operare sul livello di SWT, dove le voci sono rappresentate da stringhe ed eventi spesso in relazione con un indice all'interno dell'elenco delle stringhe. I visualizzatori forniscono una semantica di livello superiore. I client ricevono la notifica delle selezioni e delle modifiche effettuate nell'elenco attraverso gli elementi da essi forniti al visualizzatore. Il visualizzatore gestisce tutto il lavoro per l'associazione degli indici agli elementi, la regolazione per una vista filtrata degli oggetti e, quando necessario, il riordinamento.

Le funzioni di ordinamento e di filtro vengono gestite attraverso la designazione di un ordinatore di visualizzatore (ViewerSorter) e/o di un filtro di visualizzatore (ViewerFilter). Questi possono essere specificati per visualizzatori di struttura ad albero o di tabella in aggiunta ai visualizzatori di elenco. Il client deve solo fornire una classe in grado di confrontare o filtrare gli oggetti compresi nell'elenco. Il visualizzatore gestisce i dettagli di inserimento di dati nell'elenco in base all'ordine e al filtro specificato e mantiene l'ordine e il filtro durante l'aggiunta e la rimozione degli elementi.

I visualizzatori non sono concepiti per essere estesi dai client.  Per personalizzare un visualizzatore, è possibile configurarlo con i fornitori di contenuti e di etichette personali.

Un ListViewer associa gli elementi di un elenco a un controllo List di SWT.

Un TreeViewer visualizza oggetti gerarchici in un widget Tree SWT. Gestisce i dettagli per l'espansione e la compressione di voci. Esistono diversi tipi di visualizzatori di struttura ad albero per controlli di struttura SWT differenti (struttura ad albero semplice, struttura ad albero di tabelle, struttura ad albero di caselle di controllo).

Un TableViewer è molto simile a un visualizzatore di elenco, ma in più è dotato della funzione di visualizzazione di più colonne di informazioni per ciascun elemento della tabella. I visualizzatori di tabelle estendono in maniera significativa la funzione del widget di tabelle SWT introducendo il concetto di modifica di una cella. Editor di celle speciali possono essere utilizzati per consentire all'utente di modificare una cella di tabella mediante un widget di testo, di finestra di dialogo o di casella combinata. Il visualizzatore di tabella gestisce la creazione e il posizionamento di questi widget quando è necessario per le modifiche dell'utente.  Queste operazioni vengono eseguite mediante le classi CellEditor, ad esempio TextCellEditor e CheckboxCellEditor. Una tabella virtuale, in cui i dati vengono inseriti solo quando visualizzata, il visualizzatore tabelle esegue solo un numero di risultati a prescindere da quelli realmente creati. Il database richiede JIT in modalità "lazy" e non richiede solo un determinato numero alla volta.

Visualizzatore di testo

I widget di testo sono dotati di molta semantica comune, ad esempio la funzionalità di doppio clic, l'annullamento dell'ultima modifica, la colorazione e l'esplorazione in base all'indice o alla riga.  Un TextViewer è un adattatore per un widget StyledText SWT. I visualizzatori di testo forniscono un modello di documento al client e gestiscono la conversione del documento nelle informazioni di stile del testo fornite attraverso il widget di testo.

I visualizzatori di testo vengono trattati dettagliatamente in Editor del workbench.

Architettura dei visualizzatori

Per comprendere un visualizzatore, è necessario capire la relazione esistente tra l'elemento di input di un visualizzatore, il suo contenuto, la sua selezione e le informazioni al momento visualizzate nel widget che il visualizzatore sta utilizzando.

Elementi di input

Un elemento di input è l'oggetto principale visualizzato (o modificato) dal visualizzatore. Dal punto di vista del visualizzatore, un elemento di input può essere un qualsiasi oggetto. Il visualizzatore non presuppone l'implementazione, da parte dell'elemento di input, di alcuna interfaccia particolare (ne verrà illustrato il motivo in seguito, quando verranno illustrati i fornitori di contenuti).

Un visualizzatore deve essere in grado di gestire un cambiamento dell'elemento di input. Se un nuovo elemento di input viene impostato in un visualizzatore, questo deve inserire nuovamente i dati nel proprio widget in base al nuovo elemento e dissociarsi dal precedente elemento di input. La semantica per la registrazione come listener su un elemento di input e per l'inserimento di dati nel widget in base all'elemento è diversa per ciascun tipo di visualizzatore.

Visualizzatori di contenuto

Un visualizzatore di contenuto è un visualizzatore dotato di un protocollo definito per il richiamo di informazioni dal proprio elemento di input. I visualizzatori di contenuto utilizzano due classi helper specializzate, IContentProvider e ILabelProvider, per inserire dati nel rispettivo widget e visualizzare informazioni sull'elemento di input.

IContentProvider fornisce il protocollo di base del ciclo di vita per l'associazione di un fornitore di contenuti a un elemento di input e per la gestione di una modifica all'elemento di input. Fornitori di contenuti più specializzati vengono implementati per diversi tipi di visualizzatori. Il fornitore di contenuti più comune è IStructuredContentProvider, che può fornire un elenco di oggetti a partire da un elemento di input. Viene utilizzato in visualizzatori del tipo a elenco, come elenchi, tabelle o strutture ad albero. In generale, il fornitore di contenuti è in grado di associare l'elemento di input al contenuto del visualizzatore previsto.

ILabelProvider fa qualcosa di più. Dato il contenuto di un visualizzatore (derivato dall'elemento di input e dal fornitore di contenuti), è in grado di produrre gli elementi specifici dell'interfaccia utente, quali nomi e icone, necessari per visualizzare il contenuto nel visualizzatore. I fornitori di etichette possono agevolare l'utente durante il salvataggio di risorse di icona in quanto sono in grado di garantire che, per tutti i tipi simili presenti in un visualizzatore, venga utilizzata la stessa istanza dell'icona.

Nota:  le istanze di particolari fornitori di etichette o di contenuti non sono concepite per la condivisione tra più visualizzatori. Anche se tutti i visualizzatori dell'utente utilizzano lo stesso tipo di fornitori di etichette o di contenuti, ognuno di essi dovrebbe essere inizializzato con la propria istanza della classe di fornitori. Il protocollo del ciclo di vita del fornitore è progettato per un rapporto 1 a 1 tra un fornitore e il relativo visualizzatore.

Gli elementi di input, i fornitori di contenuti e i fornitori di etichette consentono ai visualizzatori di nascondere la maggior parte dei dettagli di implementazione per l'inserimento di dati nei widget. I client di un visualizzatore devono solo interessarsi dell'inserimento di dati nel visualizzatore con il tipo corretto di input e di fornitore di contenuti. Il fornitore di etichette deve essere in grado di risalire alle informazioni dell'interfaccia utente dal contenuto del visualizzatore.

Un fornitore di etichette può mostrare non solo il testo e un'immagine. JFace fornisce diverse classi e interfacce per supportare le più diffuse funzionalità aggiuntive. Le seguenti classi sono supportate da TableViewer, AbstractTreeViewer e TableTreeViewer.

A partire da Eclipse 3.1 ci sono due modi per impostare i colori di una vista: con il fornitore di etichette o con un decoratore che imposta colori e tipi di caratteri. In generale, è meglio utilizzare il supporto del colore e del tipo di carattere nei fornitori di etichette, in quanto i decoratori hanno effetti su tutte le viste che mostrano un tipo particolare. Se si utilizza un decoratore di colori o tipi di caratteri, assicurarsi che i suoi valori siano impostati nella pagina delle preferenze Colori e tipi di caratteri.

Visualizzatori e workbench

La flessibilità offerta dai visualizzatori, dai fornitori di contenuti e dai fornitori di etichette, può essere dimostrata dal modo in cui questi vengono utilizzati dal workbench.

WorkbenchContentProvider è un fornitore di contenuti strutturato che ottiene il contenuto da un elemento di input effettuando la richiesta dei rispettivi elementi secondari. Il concetto di adattatori viene nuovamente utilizzato per implementare la funzione generica. Quando viene richiesto l'elenco degli elementi dall'elemento di input, WorkbenchContentProvider ottiene un IWorkbenchAdapter per l'elemento di input. Se un IWorkbenchAdapter è stato registrato per l'elemento di input, il fornitore di contenuti può determinare con certezza che è possibile eseguire una query dell'elemento per individuare gli elementi secondari.  WorkbenchContentProvider svolge anche le attività necessarie per mantenere aggiornato il visualizzatore quando lo spazio di lavoro viene modificato. 

WorkbenchLabelProvider è un fornitore di etichette che riceve un IWorkbenchAdapter da un oggetto per poterne individuare il testo e l'immagine. Il concetto di fornitore di etichette è particolarmente utile per gli oggetti del workbench poiché consente a un singolo fornitore di etichette la memorizzazione nella cache delle immagini comunemente utilizzate in un visualizzatore. Ad esempio, quando WorkbenchLabelProvider ottiene un'immagine da utilizzare per un IProject, può memorizzare questa immagine nella cache e utilizzarla per tutti gli oggetti di IProject presenti nel visualizzatore.

Definendo un adattatore comune, IWorkbenchAdapter, e registrandolo per molti dei tipi di piattaforma, sarà possibile rappresentare correttamente tali tipi in molti dei visualizzatori comuni e delle viste del workbench che li contengono.