Perché utilizzare un visualizzatore quando è stato visto che contributi dell'interfaccia utente del workbench quali visualizzazioni, editor, procedure guidate e finestra di dialogo possono essere implementati direttamente con i widget SWT?
I visualizzatori consentono di creare widget mentre si utilizzano ancora 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 agiscono come adattatori sui widget SWT, gestendo il codice comune per gli eventi dei widget che, diversamente, dovrebbe essere implementato.
Per prima cosa è stato descritto un visualizzatore nel contributo di visualizzazione 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 visualizzazioni ed editor del workbench. Il termine visualizzatore non implica l'utilizzo per la sola implementazione di visualizzazioni. Ad esempio, TextViewer viene utilizzato per l'implementazione in molti degli editor di plug-in e del workbench.
JFace fornisce visualizzatori per la maggior parte dei widget non comuni in SWT. I visualizzatori sono più comunemente utilizzati per widget di elenco, struttura, 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 lo stesso widget e fornendolo al visualizzatore nel rispettivo costruttore.
Elenchi, strutture e tabelle condividono molte capacità comuni dal punto di vista dell'utente, ad esempio il riempimento con oggetti, la selezione, l'ordinamento e il filtro.
Questi visualizzatori conservano un elenco di oggetti di dominio (denominati elementi) e li visualizzano nel loro corrispondente widget SWT. Un visualizzatore di elenco è in grado di ottenere un'etichetta di testo da uno qualsiasi degli elementi dell'elenco. L'etichetta viene richiamata da un ILabelProvider che può essere impostato sul visualizzatore. I visualizzatori di elenco sono in grado di eseguire il mapping 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 sull'elenco attraverso gli elementi da essi forniti al visualizzatore. Il visualizzatore gestisce tutto il lavoro per il mapping degli indici agli elementi, la regolazione per una visualizzazione filtrata degli oggetti e, quando necessario, il riordinamento.
Le capacità 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 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 riempimento dell'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 da client. Per personalizzare un visualizzatore, è possibile configurarlo con i provider di contenuto 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 il restringimento di voci. Esistono diversi tipi di visualizzatori di struttura per controlli di struttura SWT differenti (struttura semplice, struttura di tabelle, struttura di caselle di controllo).
Un TableViewer è molto simile a un visualizzatore di elenco, ma aggiunge la capacità di visualizzare colonne multiple di informazioni per ciascun elemento della tabella. I visualizzatori di tabelle estendono in modo significativo 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 avvengono mediante le classi di CellEditor, ad esempio TextCellEditor e CheckboxCellEditor.
I widget di testo dispongono di molta semantica comune, ad esempio la funzionalità di doppio clic, l'annullamento dell'ultima modifica, la colorazione e l'esplorazione per indice o 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.
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.
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 provider di contenuto).
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 nuovamente effettuare il riempimento del 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 il riempimento del widget in base all'elemento è diversa per ciascun tipo di visualizzatore.
Un visualizzatore di contenuto è un visualizzatore che dispone 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 riempire il rispettivo widget e visualizzare informazioni sull'elemento di input.
IContentProvider fornisce il protocollo di base del ciclo di vita per l'associazione di un provider di contenuto a un elemento di input e per la gestione di una modifica all'elemento di input. Provider di contenuto più specializzati vengono implementati per diversi tipi di visualizzatori. Il provider di contenuto 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. In generale, il provider di contenuto è in grado di associare l'elemento di input al contenuto del visualizzatore previsto.
ILabelProvider fa un passo in più. Dato il contenuto di un visualizzatore (derivato dall'elemento di input e dal provider di contenuto), è in grado di produrre gli elementi specifici dell'interfaccia utente, quali nomi e icone, necessari per visualizzare il contenuto nel visualizzatore. I provider di etichette possono aiutare l'utente durante il salvataggio di risorse di icona dato che assicurano che la stessa istanza dell'icona viene utilizzata per tutti i tipi simili in un visualizzatore.
Nota: le istanze di particolari provider di etichette o di contenuto non sono concepite per la condivisione tra più visualizzatori. Anche se tutti i visualizzatori dell'utente utilizzano lo stesso tipo di provider di etichette o di contenuto, ognuno di essi dovrebbe essere inizializzato con la propria istanza della classe di provider. Il protocollo del ciclo di vita del provider è progettato per un rapporto 1 a 1 tra un provider e il relativo visualizzatore.
Gli elementi di input, i provider di contenuto e i provider di etichette consentono ai visualizzatori di nascondere la maggior parte dei dettagli di implementazione per il riempimento dei widget. I client di un visualizzatore devono solo interessarsi del riempimento del visualizzatore con il tipo corretto di input e di provider di contenuto. Il provider di etichette deve essere in grado di risalire alle informazioni dell'interfaccia utente dal contenuto del visualizzatore.
La flessibilità offerta dai visualizzatori, dai provider di contenuto e dai provider di etichette, può essere illustrata dal modo in cui questi vengono utilizzati dal workbench.
WorkbenchContentProvider è un provider di contenuto 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 un elemento di input, il provider di contenuto può determinare con certezza che è possibile eseguire una query dell'elemento per individuare gli elementi secondari. WorkbenchContentProvider svolge anche le attività per mantenere aggiornato il visualizzatore quando l'area di lavoro viene modificata.
WorkbenchLabelProvider è un provider di etichette che riceve un IWorkbenchAdapter da un oggetto per poterne individuare il testo e l'immagine. Il concetto di provider di etichette è particolarmente utile per gli oggetti del workbench poiché consente a un singolo provider 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 della piattaforma, sarà possibile rappresentare correttamente tali tipi in molti dei visualizzatori comuni e delle visualizzazioni del workbench che li contengono.