EMF und Notification Framework

G

Gast2

Gast
Hallo zusammen,

ich hätte ein paar Fragen zum Notification Framework von EMF. Ich nöchte einen ContentProvider für einen TableViewer machen.

1. Gibt es auch einen Adapter der nur auf ein Attribut reagiert oder muss immer überpüft werden, ob das richtige Attribut ankommt?

2. Ich verteh nicht für was die AdapterFactory genau da ist? Und was daran besser sein soll und wie man diese verwendet.

EMF generiert mir ja eine AdapterFactoryImpl aber die einzelenen createMyObjectAdapter sind alle mit null implementiertl.

Mit dem adapt kriert die Factory den richtigen Adapter und fügt diesen meinem eObject zu.
Aber wie bekomme ich den Adapter wieder aus der Liste raus? Bin ich dafür selber verantwortlich oder gehe ich dafür auch über den Adapter?

Wie gesagt seh den Vorteil der Factory noch nicht?!?


Java:
public class FahrtContentProvider implements IStructuredContentProvider{

	private MyEObject eObject;
	private Viewer viewer;
	private Adapter adapter;
	
	public FahrtContentProvider(){
		adapter = new EContentAdapter(){
			@Override
			public void notifyChanged(Notification notification) {
                                   //1. geht das auch leichter?
				   switch (notification.getFeatureID(MyEObject.class))
				    {
				      case KindergeldPackage.MYEOBJECT__PERSONLIST:
				      viewer.refresh();
				       break;
				    }
			}
		};
	eObject.eAdapters().add(adapter);
		
                 //2.
		 AdapterFactory someAdapterFactory = .;
		  Object requiredType = ...;
		  if(someAdapterFactory.isFactoryForType(requiredType))
		  {
		    Adapter theAdapter = someAdapterFactory.adapt(someObject, requiredType);
		    ...
		  }
		

	
	}
	
	@Override
	public void dispose() {
		eObject.eAdapters().remove(adapter);
		
	}

	@Override
	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		this.viewer = viewer;
		
	}

	@Override
	public Object[] getElements(Object inputElement) {
		return eObject.getPersonList().toArray();
	}

}
 

Wildcard

Top Contributor
Die generierte Factory ist primär zum extenden Gedacht um bestimmte Adaptertype zu erstellen.
Adapter sind nicht nur Listener, sie können auch verwendet werden um zusätzliche Funktionalität an ein Objekt anzuklinken.
Wenn es dir nur um einen Content Provider geht der automatisch den Tree aktualisiert, dann kannst du dir die Arbeit sparen:
Java:
treeViewer.setContentProvider(new AdapterFactoryContentProvider(new YourModelItemProviderAdapterFactory));
//beachte das 'Item' Provider Adapter Factory
Gleiches gibt es auch für den Label Provider, AdapterFactoryLabelProvider.
Wenn du dir die YourModelItemProviderAdapterFactory Klasse ansiehst, dann verstehst du vielleicht auch wie die generierte leere AdapterFactory zu verstehen ist.
 
G

Gast2

Gast
Okay das schau ich mir mal an...

Aber ich beschreib mein Problem nochmal genauer vielleicht kennst du dazu auch ne coole Variante ;)...

Also ich hab Object1 das hat eine 1:n beziehung zu Object2...

Das heißt Object1 hat eine EList<Object2>...

So nun stell ich von Object1 alle Object 2 in einem TableViewer dar.

Dafür hab ich dem oberen ContentProvider geschrieben. Es gibt einen Add/Remove Dialog für Object2.
Das heißt wenn ich Object1 ein Object2 hinzufüge muss ich ich den tableviewer refresehen. Aber ja nur auf das attribut von wenn sich die Liste änder darum der switch case.

Verständlich?:)
 
G

Gast2

Gast
Nein, musst du nicht, der AdapterFactoryContentProvider und AdapterFactoryLabelProvider macht das automatisch, auch bei strukturellen Änderungen.

Mhm also irgendwie kapier ich es nicht... hab mit jetzt den edit code generieren lassen

Hab nur ein Object1ItemProvider und ein Object2ItemProvider

und eine ItemProviderAdapterFactory dann hab ich folgendes gemacht aber es passiert gar nichts...

Java:
		tableViewer.setContentProvider(new AdapterFactoryContentProvider(new ItemProviderAdapterFactory()));
		tableViewer.setLabelProvider(new AdapterFactoryLabelProvider (new ItemProviderAdapterFactory()));


muss ich noch was bestimmtes aufrufen? Oder geht die Variante nur für TreeViewer?
Hier wird immer Null zurück gegegen da, das 2te if nicht gegeben ist. Was muss ich den in das setInput den reinmachen? Ich dachte die Liste die der tableviewer anzeigen soll ...
Java:
	@Override
	public Object adapt(Object object, Object type) {
		if (isFactoryForType(type)) {
			Object adapter = super.adapt(object, type);
			if (!(type instanceof Class<?>) || (((Class<?>)type).isInstance(adapter))) {
				return adapter;
			}
		}

		return null;
	}

Will eigentlich jetzt sowas machen object1.getObjects2().add(object2) und die Table soll ein refresh erhalten...
 
Zuletzt bearbeitet von einem Moderator:
G

Gast2

Gast
Lass deine generierten ItemProvider zusätzlich ITableItemContentProvider implementieren.
Siehe dazu hier im Kapitel Tables:
Using EMF
Der Labelprovider funktioniert einwandfrei =)...


Mhm was muss ich für den ContentProvider noch machen? DDie Tabelle wird nicht gerefreshed...
Was muss ich den als Input mitgeben? Object 1 oder die Liste von Object2?
 
Zuletzt bearbeitet von einem Moderator:
G

Gast2

Gast
Änderst du auch die gleiche Instanz die auch in der Tabelle enthalten ist?
Es kommt ersteinmal gar nichts in die Tabelle rein. Also ich hab ein AddCommand
und dann mach ich sowas object1.getObjects2().add(object)


Änderst du auch die gleiche Instanz die auch in der Tabelle enthalten ist?

Normal den Parent der Objekte die du anzeigen möchtest, du kannst aber auch eine Liste verwenden.

Hab beides versucht... Wenn ich den parent übergebe verstehe ich halt nicht woher er wissen soll dass er die Objekte 2 von objekt1 anzeigen lassen soll.
Muss ich den ItemProvider vom parent(Object1) auch händisch überarbeiten?
 

Wildcard

Top Contributor
Hab beides versucht... Wenn ich den parent übergebe verstehe ich halt nicht woher er wissen soll dass er die Objekte 2 von objekt1 anzeigen lassen soll.
Muss ich den ItemProvider vom parent(Object1) auch händisch überarbeiten?
Im Genmodel kann man in der Properties View für jedes Feature eintragen ob es ein 'children' Feature ist. Standardmäßig passiert das bei Containment References. Aus dieser Information wird dann pro ItemProvider die getChildrenFeatures Methode generiert die dem ItemProvider sagt was er bei getChildren liefern soll.
 
G

Gast2

Gast
Im Genmodel kann man in der Properties View für jedes Feature eintragen ob es ein 'children' Feature ist. Standardmäßig passiert das bei Containment References. Aus dieser Information wird dann pro ItemProvider die getChildrenFeatures Methode generiert die dem ItemProvider sagt was er bei getChildren liefern soll.

Okay in dem part wo feature steht ist containment true

in dem part wo edit steht ist bei children false.


EDIT:

Also wenn ich edit children auf true setze und notify auf true dann klappts.

aber mein labelprovider wird noch nicht benachrichtigt wenn ich ein object aus der tabelle heraus veränder. das heißt bei den sturktur änderungen passt was noch nicht.
denkeder labelprovider bekommt keine struktur änderungen.
 
Zuletzt bearbeitet von einem Moderator:

Wildcard

Top Contributor
Okay in dem part wo feature steht ist containment true

in dem part wo edit steht ist bei children false.
Wenn du das Feature erst anlegst nachdem das genmodel erstellt wurde auf, oder du es erst später auf Containment setzt, dann musst du das genmodel selbst anpassen (oder neu erstellen).
aber mein labelprovider wird noch nicht benachrichtigt wenn ich ein object aus der tabelle heraus veränder. das heißt bei den sturktur änderungen passt was noch nicht.
denkeder labelprovider bekommt keine struktur änderungen.
Gab mal ein Beispiel was und wie du es tust und was anschließend in der Tabelle passieren soll.
 
G

Gast2

Gast

Wildcard

Top Contributor
Hier mal ein Beispiel für ein einfaches Ecore (nur eine Node die wieder Nodes enthalten kann).
[XML]<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="providermodel"
nsURI="http://example.org/provider" nsPrefix="pr">
<eClassifiers xsi:type="ecore:EClass" name="Node">
<eStructuralFeatures xsi:type="ecore:EReference" name="children" upperBound="-1"
eType="#//Node" containment="true"/>
</eClassifiers>
</ecore:EPackage>[/XML]

Dann eine View um das ganze zu testen:
Java:
public class ViewPart1 extends ViewPart {

	private TreeViewer viewer;


	@Override
	public void createPartControl(final Composite parent) {
		viewer = new TreeViewer(parent);
		AdapterFactory factory = new ProvidermodelItemProviderAdapterFactory();
		viewer.setLabelProvider(new AdapterFactoryLabelProvider(factory));
		viewer.setContentProvider(new AdapterFactoryContentProvider(factory));
		final Node root = ProvidermodelFactory.eINSTANCE.createNode();
		Node child = ProvidermodelFactory.eINSTANCE.createNode();
		root.getChildren().add(child);
		viewer.setInput(root);
		parent.getDisplay().timerExec(1000, new Runnable() {
		
			@Override
			public void run() {
				root.getChildren().add(ProvidermodelFactory.eINSTANCE.createNode());
				parent.getDisplay().timerExec(1000, this);
			}
		});
		
	}

	@Override
	public void setFocus() {
		viewer.getControl().setFocus();

	}

}

Wie du siehst wird jede Sekunde eine neue Node hinzugefügt und die View aktualisiert sich vollautomatisch. Ob Tree, Table, Liste, oder sonstwas ist dabei egal. Wenn das bei dir nicht funktioniert, dann weil du irgendetwas anders machst als in diesem Beispiel und ohne zu wissen was du anders machst kann ich dir nicht helfen.
 
G

Gast2

Gast
Hier mal ein Beispiel für ein einfaches Ecore (nur eine Node die wieder Nodes enthalten kann).
[XML]<?xml version="1.0" encoding="UTF-8"?>
<ecore:EPackage xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ecore="http://www.eclipse.org/emf/2002/Ecore" name="providermodel"
nsURI="http://example.org/provider" nsPrefix="pr">
<eClassifiers xsi:type="ecore:EClass" name="Node">
<eStructuralFeatures xsi:type="ecore:EReference" name="children" upperBound="-1"
eType="#//Node" containment="true"/>
</eClassifiers>
</ecore:EPackage>[/XML]

Dann eine View um das ganze zu testen:
Java:
public class ViewPart1 extends ViewPart {

	private TreeViewer viewer;


	@Override
	public void createPartControl(final Composite parent) {
		viewer = new TreeViewer(parent);
		AdapterFactory factory = new ProvidermodelItemProviderAdapterFactory();
		viewer.setLabelProvider(new AdapterFactoryLabelProvider(factory));
		viewer.setContentProvider(new AdapterFactoryContentProvider(factory));
		final Node root = ProvidermodelFactory.eINSTANCE.createNode();
		Node child = ProvidermodelFactory.eINSTANCE.createNode();
		root.getChildren().add(child);
		viewer.setInput(root);
		parent.getDisplay().timerExec(1000, new Runnable() {
		
			@Override
			public void run() {
				root.getChildren().add(ProvidermodelFactory.eINSTANCE.createNode());
				parent.getDisplay().timerExec(1000, this);
			}
		});
		
	}

	@Override
	public void setFocus() {
		viewer.getControl().setFocus();

	}

}

Wie du siehst wird jede Sekunde eine neue Node hinzugefügt und die View aktualisiert sich vollautomatisch. Ob Tree, Table, Liste, oder sonstwas ist dabei egal. Wenn das bei dir nicht funktioniert, dann weil du irgendetwas anders machst als in diesem Beispiel und ohne zu wissen was du anders machst kann ich dir nicht helfen.

Ja das klappt bei mir auch, aber jetzt will von einem Node ein Attribut ändern. z.B. den Namen.
Dann wird die Instanz geändert aber der LabelProvider macht nichts. Weißt wie ich mein?
Ich mach morgen auch mal ein KSKB...
 

Wildcard

Top Contributor
Ja das klappt bei mir auch, aber jetzt will von einem Node ein Attribut ändern. z.B. den Namen.
Dann wird die Instanz geändert aber der LabelProvider macht nichts. Weißt wie ich mein?
Ich mach morgen auch mal ein KSKB...

Nein, das stimmt nicht, siehe hier (ich habe im Ecore ein zusätliches Attribut 'name' eingefügt:
Java:
public class ViewPart1 extends ViewPart {

	private TreeViewer viewer;


	@Override
	public void createPartControl(final Composite parent) {
		viewer = new TreeViewer(parent);
		AdapterFactory factory = new ProvidermodelItemProviderAdapterFactory();
		viewer.setLabelProvider(new AdapterFactoryLabelProvider(factory));
		viewer.setContentProvider(new AdapterFactoryContentProvider(factory));
		final Node root = ProvidermodelFactory.eINSTANCE.createNode();
		Node child = ProvidermodelFactory.eINSTANCE.createNode();
		root.getChildren().add(child);
		viewer.setInput(root);
		parent.getDisplay().timerExec(1000, new Runnable() {
		
			@Override
			public void run() {
				root.getChildren().add(ProvidermodelFactory.eINSTANCE.createNode());
				parent.getDisplay().timerExec(1000, this);
				for (Node node : root.getChildren()) {
					node.setName(SimpleDateFormat.getTimeInstance().format(new Date()));
				}
			}
		});
		
	}

	@Override
	public void setFocus() {
		viewer.getControl().setFocus();

	}

}
 
G

Gast2

Gast
Mhm versuch ich morgen mal und mach es mit 2 verschiedene Klassen velleicht kannst mir dann mein fehler sagen wenn ich ein KSKB hab ;)...
 
G

Gast2

Gast
Danke jetzt klappts.

Ich hab 2 Unterschiede festgestellt:

1. In meinem genModel createChild false. Hab das genModel wegeschmissen und nochmal neu erzeugt.

2. Habe ich meinen beiden Provider (Label und Content) jeweils eine neue Factory mitgegeben anstatt die gleiche jetzt tuts =)...

Erspart echt viel Arbeit Danke für den Tip..
 
G

Gast2

Gast
Vielleicht nochmal eine kleine Frage.

Gibt es auch was wo EMF einen Eingabe Editoren (Masken) erstellt?
Also das nicht alles in einem Baum dargestellt wird sondern, alle Attribute mit Label und Textfeldern wie in der PropertView?
z.B. Person(name,vorname)

Editor

label textfeld(name)
label textfeld(vorname)
 

Wildcard

Top Contributor
Du meinst aber explizit in nicht in der Properties View, sondern in zB einem Dialog oder einer Eclipse Forms Section?
Jein. Es gibt EEF das die default Properties View durch eine Forms basierte ersetzt und dabei auch gleich Wizards/Dialoge mit der gleichen Funktionalität produziert.
Dann gibt es noch den Generic EMF Editor der ebenfalls die Properties View durch eine Forms basierte Tabbed Properties View ersetzt, allerdings ohne dabei Code zu generieren.
EEF ist IMO noch zu sehr incubation und der Generic EMF Editor verwendet wie gesagt die Properties View.
Aber: du kannst dir die Technik des Generic EMF Editors zu nutze machen um automatisch aus den EClasses Forms ausserhalb der Properties View zu instanzieren. Wenn du bereit bist selbst etwas Arbeit zu investieren ist es mit EMF auch sehr einfach dir ein solches Framework selbst zu schreiben.
Du kannst problemlos alle Features einer EClass und deren Typ auslesen und aus dieser Information Widgets erstellen und mit Databinding Verknüpfen. Wenn du zusätzliche Informationen wie Labels oder Gruppierungsinformationen haben möchtest, kannst du EAnnotations in dein Ecore einfügen.
Dadurch das dein Modell explizit im Ecore bekannt ist lässt sich soetwas sehr leicht programmieren.

Auf die Schnelle habe ich zB dieses Beispiel gefunden:
http://www.conceptualprocessengineering.com/library/
 
G

Gast2

Gast
Du meinst aber explizit in nicht in der Properties View, sondern in zB einem Dialog oder einer Eclipse Forms Section?
Jein. Es gibt EEF das die default Properties View durch eine Forms basierte ersetzt und dabei auch gleich Wizards/Dialoge mit der gleichen Funktionalität produziert.
Dann gibt es noch den Generic EMF Editor der ebenfalls die Properties View durch eine Forms basierte Tabbed Properties View ersetzt, allerdings ohne dabei Code zu generieren.
EEF ist IMO noch zu sehr incubation und der Generic EMF Editor verwendet wie gesagt die Properties View.
Aber: du kannst dir die Technik des Generic EMF Editors zu nutze machen um automatisch aus den EClasses Forms ausserhalb der Properties View zu instanzieren. Wenn du bereit bist selbst etwas Arbeit zu investieren ist es mit EMF auch sehr einfach dir ein solches Framework selbst zu schreiben.
Du kannst problemlos alle Features einer EClass und deren Typ auslesen und aus dieser Information Widgets erstellen und mit Databinding Verknüpfen. Wenn du zusätzliche Informationen wie Labels oder Gruppierungsinformationen haben möchtest, kannst du EAnnotations in dein Ecore einfügen.
Dadurch das dein Modell explizit im Ecore bekannt ist lässt sich soetwas sehr leicht programmieren.

Auf die Schnelle habe ich zB dieses Beispiel gefunden:
http://www.conceptualprocessengineering.com/library/

Ja ich sollte erst einmal genauer EMF lernen ;), bevor ich an sowas denke.
Aber war neugierig ob es sowas schon gibt. Aber des EEF wäre ja schon mal ein Ansatz ein paar Sachen verwenden zu können.
Besser wie grad alles mit händisch + databinding zu machen ;). Aber da ich nur am versuchen und lernen bin ist es nicht schlimm.
Muss auch sagen dass es mit ein paar eigenen Klasse und Factory methoden nicht viel Code ist einen Editor + Databinding zu machen. Undo/Redo sind ja auch gleich dabei.
Aber danke für die infos.
 

Wildcard

Top Contributor
Wie gesagt, es ist sehr einfach Code zu schreiben der aus den Definitionen in EClasses automatisch Widgets instanziert und diese Widgets dann per Databinding an passende EObjects bindet. Primär Fleißarbeit, eine Fingerübung... ich würde davon ausgehen das entweder EEF bald entsprechend mature wird, oder jemand anders ein entsprechendes Projekt vorantreibt. Wenn du selbst so etwas haben willst und dich dabei auf die für dich relevanten Use-Cases beschränkst schafft man das an einem Abend, inklusive Validierung und Field Decorations.
Wenn du dann noch das WidgetToolkit für Forms subclassed kannst du sogar den 'Style' der erzeugten Widgets on-the-fly ändern, also zB wahlweise Eclipse Forms oder Plain Widgets mit grauem Hintergrund erzeugen.
 
G

Gast2

Gast
Wie gesagt, es ist sehr einfach Code zu schreiben der aus den Definitionen in EClasses automatisch Widgets instanziert und diese Widgets dann per Databinding an passende EObjects bindet. Primär Fleißarbeit, eine Fingerübung... ich würde davon ausgehen das entweder EEF bald entsprechend mature wird, oder jemand anders ein entsprechendes Projekt vorantreibt. Wenn du selbst so etwas haben willst und dich dabei auf die für dich relevanten Use-Cases beschränkst schafft man das an einem Abend, inklusive Validierung und Field Decorations.
Wenn du dann noch das WidgetToolkit für Forms subclassed kannst du sogar den 'Style' der erzeugten Widgets on-the-fly ändern, also zB wahlweise Eclipse Forms oder Plain Widgets mit grauem Hintergrund erzeugen.

Joa klingt interessant, aber zuerst einmal sollte ich mich noch mit EMF beschäftigen, um alle Möglichkeiten zu kennen ;)
 
G

Gast2

Gast
Weißt du wie man das Databinding bei einem TableViewer mit EMF Undo/Redo gescheit macht?
Ich versteh es noch nicht so richtig bei einem Viewer...

Also ich denke ich benötige die Liste von Nodes: Diesen ContentProvider...
Aber weiter fehlt es mir jetzt...

Java:
		ObservableListContentProvider cp =new ObservableListContentProvider();
	IEMFEditListProperty list = EMFEditProperties.list(editingDomain, Package.Literals.NODE__NODES);
		list.
 
Zuletzt bearbeitet von einem Moderator:
G

Gast2

Gast
Mhm so hab ich es mal hinbekommen passt zu unserem Beispiel oben wenns mal jemand braucht:

Java:
	final TableViewer viewer = new TableViewer(parent);
	        AdapterFactory factory = new ProvidermodelItemProviderAdapterFactory();
	        viewer.setLabelProvider(new AdapterFactoryLabelProvider(factory));
	        
	        IEMFEditListProperty list = EMFEditProperties.list(editingDomain,ProvidermodelPackage.Literals.NODE__CHILDREN);
			ObservableListContentProvider cp =new ObservableListContentProvider();
			viewer.setContentProvider(cp);
	       
//	        viewer.setContentProvider(new AdapterFactoryContentProvider(factory));
	        final Node root = ProvidermodelFactory.eINSTANCE.createNode();
	        Node child = ProvidermodelFactory.eINSTANCE.createNode();
//	        root.getChildren().add(child);
	        viewer.setInput(list.observe(root));
	        
	        Button button = new Button(parent, SWT.PUSH);
	        button.setText("Add");
	        button.addSelectionListener(new SelectionAdapter() {
	        	@Override
	        	public void widgetSelected(SelectionEvent e) {
	        		
	        		   Command cmd = AddCommand.create(
	 			   	        editingDomain,
	 			   	    root,
	 			   	    ProvidermodelPackage.Literals.NODE__CHILDREN,
	 			   	ProvidermodelFactory.eINSTANCE.createNode());
	        		   System.out.println(cmd.canUndo());
	 			   	      if (cmd.canExecute())
	 			   	      {
	 			   	    	editingDomain.getCommandStack().execute(cmd);
	 			   	      }
//	        		 root.getChildren().add(ProvidermodelFactory.eINSTANCE.createNode());
	        	}
			});
 

Wildcard

Top Contributor
Es gibt übrigens auch ein ChangeCommand. Damit kannst du ganz normal auf dem Domain Modell arbeiten (also ohne Commands) und bleibst trotzdem Undo/Redo fähig.
Den ObservableListContentProvider solltest du eigentlich nicht brauchen, der AdapterFactoryContentProvider müsste genügen.
 
G

Gast2

Gast
Es gibt übrigens auch ein ChangeCommand. Damit kannst du ganz normal auf dem Domain Modell arbeiten (also ohne Commands) und bleibst trotzdem Undo/Redo fähig.
He? Das ChangeCommand ist doch auch ein Command?
Oder wie führe ich das dann aus?
Meinst du so?
Java:
			ChangeCommand changeCommand = new ChangeCommand(node) {
				
				@Override
				protected void doExecute() {
					node.getNodes().add(newNode);
					
				}
			};
			
			EditingDomain editingDomain = ((EditingDomain) HandlerUtil.getActiveEditor(event))
			.getEditingDomain();
			if (changeCommand.canExecute()) {

				editingDomain.getCommandStack().execute(changeCommand);
			}

Den ObservableListContentProvider solltest du eigentlich nicht brauchen, der AdapterFactoryContentProvider müsste genügen.

Tatsache perfekt =)... Ist ja echt cool dann brauch man ja nur noch eine Zeile
Java:
EMFEditProperties.list(editingDomain,MyPackage.Literals.NODE__NODES);
 
Zuletzt bearbeitet von einem Moderator:

Wildcard

Top Contributor
He? Das ChangeCommand ist doch auch ein Command?
Oder wie führe ich das dann aus?
Meinst du so?
Ja, so. Bei einem einfachen Command spielt es keine große Rolle, aber bei komplexeren Operationen ist das Change Command IMO komfortabler als n atomare Commands zu verketten.
 
G

Gast2

Gast
Ja, so. Bei einem einfachen Command spielt es keine große Rolle, aber bei komplexeren Operationen ist das Change Command IMO komfortabler als n atomare Commands zu verketten.

Okay.
Was ich noch nicht verstehe ist das ComposedAdapterFactory die geb ich ja dem AdapterFactoryEditingDomain im Konstruktor mit. Und der ComposedAdapterFactory kann ich noch weitere Factory adden. Ich check net ganz für was das gut ist?
 

Wildcard

Top Contributor
2 wichtige Gründe:
1. Eine Adapter Factory kann nicht nur die Edit Adapter erstellen, sondern auch Adapter die deinem Modell zB neue Funktionalität verleiht, ähnlich wie IAdaptable in Eclipse. Anstatt nun alle denkbaren Adapter Typen in einer einzigen Factory Bündeln zu müssen kannst du dank der Composed Adapter Factory mehrere verschiedene Adapter Factories implementieren und sie dann alle einer Composed Adapter Factory hinzufügen. Die Composed Adapter Factory unterstützt dann alle Adapter Typen der einzelnen Factories

2. Wenn man sich mit EMF vertraut gemacht hat will man es nicht mehr missen. Man verwendet EMF nun für so ziemlich jede Art Modell in der eigenen Anwendung. Manche dieser Modelle referenzieren wieder andere Modell. Willst du nun zB ein Modell in einem TreeViewer darstellen dessen Kinder wieder aus anderen Modellen kommen dann erlaubt dir die Composed Adapter Factory das du alle benötigten Item Provider in einer einzigen Factory bündelst. Der TreeViewer kann jetzt Objekte aus den unterschiedlichsten Domainen (Ecore Modellen) korrekt rendern ohne die anderen Modelle überhaupt zu 'kennen'.
 
G

Gast2

Gast
Okay soweit bin ich wohl noch nicht :)...

2 wichtige Gründe:
1. Eine Adapter Factory kann nicht nur die Edit Adapter erstellen, sondern auch Adapter die deinem Modell zB neue Funktionalität verleiht, ähnlich wie IAdaptable in Eclipse. Anstatt nun alle denkbaren Adapter Typen in einer einzigen Factory Bündeln zu müssen kannst du dank der Composed Adapter Factory mehrere verschiedene Adapter Factories implementieren und sie dann alle einer Composed Adapter Factory hinzufügen. Die Composed Adapter Factory unterstützt dann alle Adapter Typen der einzelnen Factories
Gibt es dazu ne gut Seite ? Wie man durch einen Adapater neue Funktioniltät einem Model gibt?


Aber das hat jetzt nichts mit dem undo/Redo support zu tun oder? Weil ich hab der ComposedAdapterFactory keine weitere Factory hinzugefügt und es klappt trotzdem

Java:
		ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
		BasicCommandStack commandStack = new BasicCommandStack();
		
		editingDomain = new AdapterFactoryEditingDomain(adapterFactory, commandStack, new HashMap<Resource, Boolean>());
 
Zuletzt bearbeitet von einem Moderator:

Wildcard

Top Contributor
Aber das hat jetzt nichts mit dem undo/Redo support zu tun oder? Weil ich hab der ComposedAdapterFactory keine weitere Factory hinzugefügt und es klappt trotzdem
Indirekt schon. Du übergibst die globale Registry an die ComposedAdapterFactory. In der Registry sind alle ItemProviderAdapterFactories bekannt die sich per ExtensionPoint anmelden (der per default generierte Edit Code enthält auch eine plugin.xml mit einer solchen Extension).
Wenn nun ein Objekt deines Modells auf einen Item Provider adaptiert werden soll findet die Composed Adapter Factory die passende ItemProviderAdapterFactory über den Extension Point und instanziert sie. Damit werden deine Item Provider verwendet um die Labels, Kinder usw berechnen.
Beim Databinding werden dann die gleichen Item Provider verwendet um Commands zu erzeugen. Diese Commands werden über die Edit Domain ausgeführt und damit funktioniert Undo und Redo.
 
G

Gast2

Gast
Indirekt schon. Du übergibst die globale Registry an die ComposedAdapterFactory. In der Registry sind alle ItemProviderAdapterFactories bekannt die sich per ExtensionPoint anmelden (der per default generierte Edit Code enthält auch eine plugin.xml mit einer solchen Extension).
Wenn nun ein Objekt deines Modells auf einen Item Provider adaptiert werden soll findet die Composed Adapter Factory die passende ItemProviderAdapterFactory über den Extension Point und instanziert sie. Damit werden deine Item Provider verwendet um die Labels, Kinder usw berechnen.
Beim Databinding werden dann die gleichen Item Provider verwendet um Commands zu erzeugen. Diese Commands werden über die Edit Domain ausgeführt und damit funktioniert Undo und Redo.

Ah den Extension Point hab ich noch gar nie beachtet, gut dann macht das Sinn =)
 
G

Gast2

Gast
Nein, das stimmt nicht, siehe hier (ich habe im Ecore ein zusätliches Attribut 'name' eingefügt:
Java:
public class ViewPart1 extends ViewPart {

	private TreeViewer viewer;


	@Override
	public void createPartControl(final Composite parent) {
		viewer = new TreeViewer(parent);
		AdapterFactory factory = new ProvidermodelItemProviderAdapterFactory();
		viewer.setLabelProvider(new AdapterFactoryLabelProvider(factory));
		viewer.setContentProvider(new AdapterFactoryContentProvider(factory));
		final Node root = ProvidermodelFactory.eINSTANCE.createNode();
		Node child = ProvidermodelFactory.eINSTANCE.createNode();
		root.getChildren().add(child);
		viewer.setInput(root);
		parent.getDisplay().timerExec(1000, new Runnable() {
		
			@Override
			public void run() {
				root.getChildren().add(ProvidermodelFactory.eINSTANCE.createNode());
				parent.getDisplay().timerExec(1000, this);
				for (Node node : root.getChildren()) {
					node.setName(SimpleDateFormat.getTimeInstance().format(new Date()));
				}
			}
		});
		
	}

	@Override
	public void setFocus() {
		viewer.getControl().setFocus();

	}

}

1.Klappt das eigentlich auch irgendwie wenn als input mehrere roots hat? oder muss man dann extra noch ein Root Object anlegen in EMF?

Also ich hab quasi eine Klasse Root und die kann mehrer Nodes aufnehmen.
Ich habe mehrere Roots die würde ich gerne auch anzeigen lassen.

2. Unterstützt die Factory auch DeferredTrees? Oder muss man hierfür noch etwas anlegen?
Also es wäre schön wenn da auch "Pending" steht wenn das Laden der Kinder etwas länger dauert? Ist das so ohne weiteres möglich?

Also sowas :
Java:
	        AdapterFactory factory = new ProvidermodelItemProviderAdapterFactory();
	        viewer.setLabelProvider(new AdapterFactoryLabelProvider(factory));
	        viewer.setContentProvider(new AdapterFactoryContentProvider(factory));
			List<Root> roots= new ArrayList<Root>();
			for(int i = 0 ;i < 5; i++){
				Root root = ProvidermodelFactory.eINSTANCE.createRoot();
				for(int j = 0; j<5;j++){
					Node node = ProvidermodelFactory.eINSTANCE.createNode();
					root.getChildren().add(node);
				}
				roots.add(root);
			}
	        
	        viewer.setInput(roots);
 
Zuletzt bearbeitet von einem Moderator:

Wildcard

Top Contributor
1.Klappt das eigentlich auch irgendwie wenn als input mehrere roots hat? oder muss man dann extra noch ein Root Object anlegen in EMF?
Wenn etwas nicht funktioniert mach dir einfach einen ContentProvider der an einen AdapterFactoryContentProvider delegiert aber bestimmte Anfragen anders/selbst handelt.

2. Unterstützt die Factory auch DeferredTrees? Oder muss man hierfür noch etwas anlegen?
Also es wäre schön wenn da auch "Pending" steht wenn das Laden der Kinder etwas länger dauert? Ist das so ohne weiteres möglich?
Eclipse bietet dafür schon eine fertige Klasse. AFAIR hieß sie DeferredTreeContentManager
 

Alan4

Mitglied
Hallo zusammen,
ich habe eine Frage bitte bezüglich EMF Forms.

Ich bin bis jetzt dazu bekommen, dass ich aus einer XSD ein Listobjekt nun nur Pull-Down-Menü in EMF Forms bekomme, und das wäre die Fragestellung, wie ich aus einer XSD eine ListBox in EMF Forms bekommen kann?
Ist das möglich? Oder es ist schon so festgelegt?

Außerdem könnte man die UI nach der Erstellung irgendwie als XML Beschreibung (Also XML Datei) abspeichern?

Ich bedanke mich im Voraus für eure Antwort und Unterstützung.

Beste Grüße
Alan Jaff
 

Ähnliche Java Themen


Oben