Widget personalizzati

A volte può accadere che i controlli forniti in SWT non siano appropriati alle esigenze dell'applicazione. In tal caso, è possibile estendere SWT implementando un proprio widget personalizzato. SWT è infatti dotato di un pacchetto org.eclipse.swt.custom, in cui sono contenuti i controlli personalizzati che non fanno parte dell'insieme principale di controlli SWT, ma che sono necessari per implementare il workbench della piattaforma.

Controllo
Scopo
Stili
Eventi

CCombo

Simile al controllo Combo, ma è personalizzato per consentire l'utilizzo del controllo senza bordi. Questa classe è stata sviluppata per utilizzare controlli Combo all'interno di celle di tabella.

BORDER, FLAT, READ_ONLY

Dispose, Control*, Selection

CLabel

Simile al controllo Label, ma supporta la sostituzione di testo con puntini di sospensione. Supporta, inoltre, un effetto a gradiente per il colore di sfondo nella vista del workbench attiva. Non supporta la disposizione del testo.

CENTER, LEFT, RIGHT, SHADOW_IN, SHADOW_OUT, SHADOW_NONE

Dispose, Control*

CTabFolder

Simile al controllo TabFolder, ma supporta un'ulteriore configurazione dell'aspetto visivo di schede (superiore o inferiore) e bordi.

BORDER, FLAT, BOTTOM, TOP

Dispose, Control*, Selection

CTabItem

Oggetto selezionabile dell'interfaccia utente corrispondente a una scheda di una pagina in una CTabFolder.

 
Dispose, Control*

SashForm

Controllo composito che dispone gli elementi secondari in righe o colonne e li separa mediante un controllo Sash per permettere all'utente di ridimensionarli.

BORDER, HORIZONTAL, VERTICAL

Dispose, Control*

ScrolledComposite

Controllo composito che consente di riempire lo spazio disponibile mediante scorrimento e, opzionalmente, allungamento del relativo contenuto.

BORDER, H_SCROLL, V_SCROLL

Dispose, Control*

StyledText

Controllo modificabile mediante il quale è possibile digitare un testo. Gli intervalli di testo all'interno del controllo possono avere tipi di carattere e colori differenti (primo piano e sfondo).

BORDER, FULL_SELECTION, MULTI, SINGLE, WRAP, READ_ONLY

Dispose, Control*, ExtendedModify, LineGetBackground, LineGetSegments, LineGetStyle, Modify, Selection, Verify, VerifyKey

TableTree

Controllo selezionabile che visualizza un elenco gerarchico di voci selezionabili dall'utente. L'elenco viene presentato in righe che visualizzano più colonne in cui sono rappresentati aspetti differenti delle voci.

BORDER, SINGLE, MULTI, CHECK, FULL_SELECTION

Dispose, Control*, Selection, DefaultSelection, Collapse, Expand

TableTreeItem

Oggetto selezionabile dell'interfaccia utente che rappresenta una gerarchia di voci di una struttura in un TableTree.

 
 

ViewForm

Controllo composito che dispone tre elementi secondari in orizzontale e consente il controllo programmatico dei parametri relativi a layout e bordi. Utilizzato nel workbench per implementare un'etichetta/barra degli strumenti/barra locale dei menu della vista.

BORDER, FLAT

Dispose, Control*

Control* = eventi ereditati da Control:  FocusIn, FocusOut, Help, KeyDown, KeyUp, MouseDoubleClick, MouseDown, MouseEnter, MouseExit, MouseHover, MouseUp, MouseMove, Move, Paint, Resize

Prima di implementare un widget personalizzato, è necessario tenere presente molti aspetti importanti:

Una volta stabilito che è necessario utilizzare un widget personalizzato e si è deciso quali piattaforme deve supportare, è possibile considerare diverse tecniche di implementazione dello stesso. Tali tecniche possono essere mescolate e armonizzate a seconda delle disponibilità nella sottostante piattaforma del sistema operativo.

Implementazione nativa

Quando l'applicazione richiede un widget nativo che non è fornito da SWT, è necessario implementare un widget in modo nativo. Si può utilizzare un widget della piattaforma, un widget di terzi o qualsiasi altro widget di una libreria condivisa della piattaforma.

Ciascuna piattaforma SWT è fornita sia di una libreria condivisa (ad esempio, una DLL su Windows) sia di un JAR (per i file di classe Java). La libreria condivisa contiene la funzionalità nativa completa richiesta per SWT, ma non costituisce un insieme completo delle funzioni disponibili sulla piattaforma. Per esporre la funzione nativa o i widget nativi non esposti da SWT, è necessario scrivere la propria libreria condivisa. In caso di utilizzo di un codice nativo su una piattaforma in combinazione con un codice trasferibile su un'altra piattaforma, assicurarsi di richiamare la libreria condivisa sulla piattaforma che contiene il widget nativo e il JAR su quella con il widget trasferibile.

Per implementare un widget nativo, è necessario conoscere JNI (Java Native Interface), l'API del widget nella libreria condivisa e le API della sottostante piattaforma del sistema operativo in C.

Il processo base di implementazione consiste nel determinare quale parte dell'API del widget nativo esporre nell'API Java e nello scrivere il codice Java che richiama i nativi per implementare il comportamento. Per richiamare la libreria condivisa, è necessario scrivere il codice JNI in C.

Una buona idea è quella di seguire i criteri di progettazione utilizzati per implementare SWT durante la creazione dell'implementazione del proprio widget nativo. Ad esempio, i nativi JNI devono essere abbinati singolarmente alle chiamate API effettuate nella libreria condivisa.

Un esempio completo di implementazione di un widget nativo personalizzato è reperibile in Creazione di widget personali mediante SWT.

Estensione di un widget esistente

Se il nuovo widget è simile nelle caratteristiche o nell'implementazione a un widget esistente, si potrebbe effettuare il ritorno a capo di un widget SWT esistente. Questa tecnica viene utilizzata per l'implementazione di TableTree.

Per effettuare il ritorno a capo di un widget, è necessario creare una sottoclasse del widget Composite o Canvas (a seconda che il controllo abbia o meno elementi secondari). Creare il widget con ritorno a capo nel costruttore per il widget personalizzato. Il widget risultante sarà completamente trasferibile in Java perché per l'implementazione viene richiamata l'API del widget con ritorno a capo.

L'inclusione di un widget spesso consente di implementare widget personalizzati in maniera più semplice che partendo da zero. Tuttavia, occorre progettare attentamente l'API del nuovo widget. Suggerimenti importanti:

Considerare se il proprio widget è un "tipo di" widget con ritorno a capo o se ne utilizza giusto uno per l'implementazione. Ad esempio, una struttura di tabella non è un tipo di tabella. Non fa riferimento alle voci mediante un indice di numero di riga. Il controllo TableTree utilizza semplicemente una tabella per implementare la presentazione e aggiunge il comportamento di struttura. Se si sta effettuando il ritorno a capo di un widget a solo scopo di implementazione, l'API potrebbe apparire differente da quella del widget sottostante.

Inoltrare il minor numero di metodi ed eventi possibile. Non implementare nuovamente l'intera API del widget incluso, se non si vuole essere costretti a effettuare aggiornamenti a causa delle modifiche subite dall'API inclusa in una futura versione. È necessario inoltrare i metodi comuni alla maggioranza dei widget, come setFont, setForeground e setBackground.

Se viene implementata la maggior parte delle API del widget con ritorno a capo, si prenda in considerazione la possibilità di esporre tale widget al livello API in modo da farlo utilizzare direttamente dal codice applicativo. In questo caso, si potrebbe anche riconsiderare la scelta di fornire un nuovo widget. Potrebbe risultare conveniente implementare la funzione come un "adattatore" che aggiunge funzionalità a un widget senza tuttavia fingere di esserlo (i visualizzatori JFace seguono questo modello).

Nota: la discussione è incentrata soltanto sull'estensione del comportamento di un widget mediante il processo di ritorno a capo. Si sconsiglia fortemente di estendere un widget mediante una sua collocazione in sottoclassi, perché lo si renderebbe dipendente dall'implementazione della superclasse.

Implementazione personalizzata

A volte non esiste alcun codice nativo o widget che possa essere di supporto nell'implementazione del nuovo widget. In questo caso, è necessario progettare un widget personalizzato mediante le chiamate grafiche di SWT. Sebbene questa tecnica sia diventata abbastanza complicata, ha il pregio di produrre un'implementazione completamente trasferibile.

I controlli personalizzati sono implementati posizionando la classe Canvas o Composite in sottoclassi mediante le seguenti regole:

In un controllo personalizzato, lo stato interno viene mantenuto in variabili di istanza Java. API e stili vengono definiti in base alle esigenze del widget

L'implementazione interna di un widget personalizzato generalmente implica le seguenti attività principali:

Molti dei widget implementati in org.eclipse.swt.custom si avvalgono di questo approccio. Un esempio semplice può essere trovato in CLabel.

Ulteriori informazioni sui widget personalizzati sono disponibili in Creazione di widget mediante SWT.

Copyright IBM Corporation e altri 2000, 2003.