Contribuire ad una applicazione Eclipse e4

Introduzione

Con Eclipse 3.x abbiamo imparato ad apprezzare il vantaggio di suddividere un’applicazione RCP in moduli (plug-in). Ciascun plug-in può contribuire aggiungendo nuove funzionalità, ad es. form, voci di menu, servizi di business, ecc…
L’inclusione di tutti o di un sottoinsieme di tali plug-in permette di comporre in maniera modulare l’applicazione rilasciata (ovvero il prodotto).

Il modo con cui in precedenza (3.x) si effettuava questa operazione era attraverso l’uso degli Extension Point (tab “Extensions” dell’editor del file plugin.xml). Con e4 questa operazione viene fatta in un modo diverso, anzi due (ed è in arrivo il terzo…).

Il primo modo, oggetto di questo tutorial, è attraverso l’uso dei Model Fragment; si tratta di un approccio dichiarativo, molto simile a quanto si faceva in 3.x col file plugin.xml. Esiste poi anche un approccio programmatico (definendo un Processor) dove, via codice, si contribuisce o si modifica un’applicazione. In più è in fase di sviluppo un nuovo approccio basato su XPath.

Un nuovo plug-in con un e4 Model Fragment

In questo tutorial vediamo come contribuire ad una applicazione e4 utilizzando un Model Fragment. Lo scopo che ci prefiggiamo è quello di aggiungere un plug-in capace di contribuire all’applicazione realizzata nel tutorial precedente, con una nuova voce di menu e una view (tecnicamente una “part”, ma oramai il termine “view” rende meglio l’idea!). In particolare vogliamo aggiungere un plug-in per la gestione dei clienti (ci limiteremo ad una voce di menu ed una view).

Creiamo quindi un nuovo plug-in con File → New → Plug-in Project, indichiamo un nome, ad es. it.rcpvision.e4training.customers), poi Next. Nella seconda pagina dello wizard possiamo deselezionare sia l’opzione di creazione dell’Activator, sia quella relativa alle UI contributions. Naturalmente poi rispondiamo No alla richiesta di creare un’applicazione rich client, dato che stiamo creando un plug-in che contribuirà ad una applicazione esistente. A questo punto saltiamo la pagina successiva (non ci interessa usare un template) premendo subito Finish.

Ora, invece di agire sul plug-in manifest (aprendo i file plugin.xml/MANIFEST.MF, come si faceva in passato con la piattaforma 3.x) creiamo, al top level di questo plug-in, un Model Fragment con File → New → Other… (oppure premiamo Ctrl-N), selezioniamo la categoria e4 → Model e poi selezionando New Model Fragment e premendo Next. La seconda pagina di questo wizard non dovrebbe richiedere nessuna modifica (come Container dovrebbe indicare il plug-in corrente e come file namefragment.e4xmi”, che possiamo lasciare inalterato), poi Finish. Tale file è analogo a quello visto nel precedente tutorial che descriveva il modello EMF dell’applicazione (Application.e4xmi): stavoltà però il contenuto di questo file lo definiremo noi indicando i nuovi contributi. In pratica si tratta di un modello EMF che estende quello dell’applicazione.

Al fine di registrare tale file tuttavia dobbiamo utilizzare il plug-in manifest: apriamo quindi il file MANIFEST.MF nel modo classico, andiamo nel tab “Extensions”, aggiungiamo (bottone Add…) l’extension “org.eclipse.e4.workbench.model” (Attenzione: assicuratevi che il flag “Show only extension points from the required plug-ins” sia disabilitato!). Premendo poi Finish vi verrà chiesto se devono essere aggiunte le dipendenze necessarie: rispondete Yes. A questo punto sulla nuova extension creata eseguiamo tasto destro New → fragment e modifichiamo l’attributo uri premendo il vicino tasto Browse… e selezionando il file fragment.e4xmi, poi OK e salviamo.

Ora passiamo invece al tab Dependencies e aggiungiamo i seguenti plug-in:

  • org.eclipse.e4.ui.di

  • org.eclipse.e4.core.di

  • org.eclipse.ui

  • javax.inject

Quindi al termine di questa operazione dovremmo vedere la seguente situazione:

Finalmente siamo pronti per aggiungere elementi al Fragment Model; aggiungeremo un Command, un Handler e una voce di Menu. Apriamo perciò il file fragment.e4xmi, selezioniamo il nodo Model Fragments


e sul pannello di dettaglio a destra premiamo il tasto Add…


per tre volte (riselezionando ogni volta il nodo Model Fragments) arrivando quindi ad avere

Aggiunta di un Command

Posizionamoci sul primo elemento Model Fragment e, nel pannello di dettaglio, inseriamo i seguenti valori:

Element Id = org.eclipse.e4.ide.application
Featurename = commands


In pratica stiamo dicendo che questo fragment andrà ad aggiungere un contributo all’elemento del modello dell’applicazione avente id = org.eclipse.e4.ide.application (potete infatti notare che, aprendo il file Application.e4xmi del plug-in contenente l’applicazione, la root di tale modello è appunto un nodo di tipo Application il cui id è proprio org.eclipse.e4.ide.application)


inoltre stiamo indicando che il contributo agirà sulla feature commands (cioè l’attributo EMF che è la lista dei commands dell’Application stessa), come è chiaro dalla seguente figura:

Potreste chiedervi a questo punto perchè digitare questi valori esplicitamente invece di selezionarli da una lista. Ebbene questo è in effetti possibile, attraverso i tasti Find…; se preferite questa modalità dovrete selezionare nella popup dialog relativa al primo tasto Find… il Container-Type (nel nostro caso Application)

mentre nel caso della dialog del secondo tasto Find… dovrete selezionare la feature commands dell’entità Application


In ogni caso queste azioni porteranno comunque i suddetti valori nei campi Element Id e Featurename.

Ora occorre aggiungere il Command vero e proprio: selezioniamo quindi il primo Model Fragment, nella sezione di dettaglio selezioniamo nella combo il valore Command e premiamo Add…

sul dettaglio inseriamo i campi

id = it.rcpvision.e4training.customers.command.show.customers
name = Show Customers


In pratica abbiamo appena definito un Command. Se avete sviluppato in tecnologia 3.x riconoscerete certamente un parallelo con quanto si faceva prima (si definiva l’Extension Point org.eclipse.ui.commands, si creava un nodo figlio di tipo command e se ne indicavano gli attributi id e name, del tutto simile quindi)

Aggiunta di un Handler

Passiamo al secondo Model Fragment e alla definizione dell’Handler. Selezionamo perciò il secondo fragment e indichiamo nel dettaglio (analogamente a quanto fatto per il Command)

Element Id = org.eclipse.e4.ide.application
Featurename = handlers


Poi creiamo, su questo fragment, un Handler


impostando un Id per l’Handler, un riferimento al Command definito prima

Id = it.rcpvision.e4training.customers.handler.show.customers
Command = Show Customers – it.rcpvision.e4training.customers.command.show.customers

(scegliendo col tasto Find…)

e infine indicando una classe per l’implementazione dell’Handler stesso. Per questo possiamo scrivere il nome di una classe, es. ShowCustomerHandlers


e poi selezionare l’hyperlink Class URI, scegliere Package (es. it.rcpvision.e4training.customers.handlers), Name (es. ShowCustomersHandler) e premere Finish.

Otterremo una implementazione iniziale dell’Handler, che dovremo popolare con azioni. Ad esempio, per il momento possiamo semplicemente far stampare, nel metodo execute() una stringa in console, giusto per verificare l’esecuzione del metodo.

package it.rcpvision.e4training.customers.handlers;

import org.eclipse.e4.core.di.annotations.Execute;

public class ShowCustomersHandler {
	@Execute
	public void execute() {
		System.out.println("Called ShowCustomersHandler!");
	}
}

Aggiunta di un Menu item

Manca solamente la voce di menu per l’invocazione del Command. Selezioniamo il terzo Model Fragment e indichiamo stavolta, come Element Id quello del Main Menu dell’applicazione (infatti è questo il parent a cui vogliamo contribuire), come si vede dalla figura

Element Id = menu:org.eclipse.ui.main.menu

mentre come Featurename, aiutati anche dal tasto Find… indicheremo children


Aggiungiamo quindi un contributo di tipo HandledMenuItem


indicando, un Id (es. it.rcpvision.e4training.customers.handledmenuitem.show.customers), una Label (che verrà mostrata effettivamente nel Menu) ad es. Customers e un riferimento al Command.

Aggiunta del plug-in realizzato al Product

Se ora modifichiamo il product definito nel plug-in precedente (it.rcpvision.e4training.application.product) indicando che deve comprendere anche questo secondo plug-in (più tutte le dipendenze necessarie)

salviamo, torniamo sul tab Overview del Product e premiamo Launch an Eclipse Application


Eseguiamo ora il lancio del product (eventualmente aggiungendo al lancio le dipendenze necessarie) e verifichiamo l’effetto del plug-in realizzato.

Aggiunta di una Part

Per contribuire con una Part al PartStack dell’applicazione originaria occorre innanzitutto che a quest’ultimo sia stato attribuito un Element Id. Apriamo quindi il file Application.e4xmi e attribuiamo al PartStack ad es. l’id org.eclipse.e4.ide.partstack

Ora torniamo al file fragment.e4xmi aggiungiamo un altro Model Fragment indicando nel dettaglio

Element Id = org.eclipse.e4.ide.partstack
Featurename = children

In pratica, analogamente a quanto fatto per la voce di Menu, stiamo agendo sulla lista di children del PartStack individuato da quel particolare id. Allo stesso modo infatti aggiungiamo una Part

e a questo punto, come abbiamo fatto nel tutorial precedente quando abbiamo aggiunto la part Orders, impostiamo una Label (es. Customers) e un ClassURI (con un click sull’hyperlink)

e popoliamo la nuova view con un contenuto di esempio.

	private Label label;
	private TableViewer tableViewer;

	@PostConstruct
	public void createPartControl(Composite parent) {
		parent.setLayout(new GridLayout());

		label = new Label(parent, SWT.NONE);
		label.setText("Customers");

		tableViewer = new TableViewer(parent);
		tableViewer.add("ABC");
		tableViewer.add("DEF");
		tableViewer.getTable().setLayoutData(new GridData(GridData.FILL_BOTH));
	}

A questo punto lanciando l’applicazione vedremo

Opzioni di Part ed interazione col Command

Come ultimo esercizio rendiamo la Part appena creata chiudibile ed utilizziamo il Command legato alla voce di Menu per poter riaprire la Part stessa.
Il primo step si ottiene attraverso il corrispndente flag Closeable