ViewPart dynamisch (Install/Deinstall Plugin) anzeigen in Perspektive?

Status
Nicht offen für weitere Antworten.

Perpetuum82

Mitglied
Hallo Zusammen!

Ich versuche gerade auf Eclipse Galileo einen ViewPart der aus Plug-in/Bundle A kommt dynamisch in eine Plug-in B, was eine RCP Anwendung ist, in dessen Perspektive anzeigen zu lassen.

Es ist so, dass Bundle A einen ViewPart implementiert und eine Contribution zu org.eclipse.ui.views macht.

Meine Default Perspektive in der RCP Anwendung implementiert den IExtensionChangeHandler. Sobald also eine Contribution zum ExtensionPoint org.eclipse.ui.views mit der entsprechenden ID von View aus Bundle A installiert und gestartet wird, wird die addExtension Methode aufgerufen und die View hinzugefügt. Leider passeirt aber rein gar nichts sobald ich das Bundle über die OSGI console installiere. Die addExtension Methode wird aufgerufen und auch layout.addView. Doch die View wird nicht angezeigt.

Wenn ich aber die beiden Bundles gemeinsahm per Eclipse Launch-Config starte kalppt es. Die View ist drinn!

So sieht meine addExtension Methode in meiner Default Perspektiven Klasse aus:

Java:
public void addExtension(IExtensionTracker tracker, IExtension extension) {
		
		if(extension.getConfigurationElements()[0].getAttribute("id").equals("org.wt.test.im.extension.im")){
			System.out.println("add " + extension.getConfigurationElements()[0].getAttribute("id"));
			
			layout.addView(extension.getConfigurationElements()[0].getAttribute("id"), SWT.RIGHT, 0.5f, layout.getEditorArea());
			}

	}

Ich verstehe nicht warum das nicht klappt. Ist das ein Bug?
Wenn ich das Bundle A deinstalliere verschwindet die View auch (sofern per Launcher gestartet). Installiere ich Bundle A aber wieder, kommt die VIew nicht zurück, obwohl die addExtension Methode aufgerufen wird.

Weis jemand einen Rat? :?:

Viele Grüße
Eduard
 

Wildcard

Top Contributor
Das Layout einer Perspektive wird in genau 2 Situationen angezeigt:
1. Die perspektive wird zum aller ersten mal geöffnet
2. Der User macht ein reset auf der Perspektive um sie in den Auslieferungszustand zurückzuversetzen

Mit anderen Worten:
Sobald die Perspektive mal verwendet wurde merkt sie sich die User Einstellungen und baut sich nicht neu anhand des Layouts auf.
 

Perpetuum82

Mitglied
Ok, das erklärt es dann natürlich.

Ich habe jetzt einen Folder in die Perspektive gepackt. In diesen Folder habe ich einen Placeholder hinzugefügt mit der ID der Extension, die dynamisch installiert und deinstalliert wird. Sobald die Extension installiert wird, mache ich folgendes in der addextension Methode:

Java:
public void addExtension(IExtensionTracker tracker, IExtension extension) {
		
		if(extension.getConfigurationElements()[0].getAttribute("id").equals(ID_IM)){

			try {
				window.getActivePage().showView(ID_IM);
			} catch (PartInitException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

Trotzdem tut sich nichts. Im Prinzip mache ich das selbe wie in diesem RCP Mail Template. Allerdings klappt es nicht? Jemand eine Idee?

Gruß
Eduard
 
Zuletzt bearbeitet:

Perpetuum82

Mitglied
Breakpoint gesetzt und geschaut was passiert?

Ich habe bei ...

Java:
window.getActivePage().showView(ID_IM);

... einen Breakpoint gesetzt und im Debugmode ewig durch die einzelnen Schritte durchgeklickt. Zunächst holt er sich die Page. Dann versucht er die Klasse zu laden und das Bundle (das sind sehr viele Schritte) und dann fängt er irgendwie von vorne an. Hohlt sich wieder die Active Page usw. Das ist das was ich grob erkennen konnte. Diese ganzen Schritte sagen mir nicht viel.

Das komische ist, sobald "window.getActivePage().showView(ID_IM);" aufgerufen wurde, wird keine Exception geworfen, aber in ein System.out.println(), nach diesem Befehl kommt er auch nicht. Es verhällt sich so, als ob dort eine Endlosschleife läuft.

Ich habe jetzt absolut keine Idee wie ich ViewParts aus externen Bundles im meine RCP Application bekomme. Hat sowas schon jemand gemacht? Wie würde man dort vorgehen? Vielleicht mache ich das nur falsch oder denke falsch.

Hier noch der Code der kompletten Perspective Klasse.

Java:
package org.wt.test;

import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.RegistryFactory;
import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker;
import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler;
import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker;
import org.eclipse.ui.IFolderLayout;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;

public class Perspective implements IPerspectiveFactory, IExtensionChangeHandler{
	
	public static final String IM_ID = "org.wt.test.im.extension";
	
	private IFolderLayout folder;
	private IPageLayout layout;
	private IWorkbenchWindow window;
	
	public void createInitialLayout(IPageLayout layout) {

		window = PlatformUI.getWorkbench().getWorkbenchWindows()[0];
		
		this.layout = layout;
		layout.setEditorAreaVisible(false);
		layout.addPlaceholder(IM_ID, IPageLayout.TOP, 0.5f, IPageLayout.ID_EDITOR_AREA);
		//layout.addView("org.wt.test.SampleView",IPageLayout.RIGHT, 0.2f, IPageLayout.ID_EDITOR_AREA);
		//folder = layout.createFolder("views", IPageLayout.LEFT, 0.5f, IPageLayout.ID_EDITOR_AREA);
		//folder.addPlaceholder(IM_ID);
		//folder.addView(IM_ID);
		
		IExtensionRegistry registry = RegistryFactory.getRegistry();

		IExtensionPoint extensionPoint = registry
		    .getExtensionPoint("org.eclipse.ui.views");
		IExtensionTracker tracker = new ExtensionTracker(registry);

		for (IExtension extension : extensionPoint.getExtensions()) {
			System.out.println("for (extensions)");
			//addExtension(tracker, extension);
		}

		// Kuenftige Installation/De-Installation von Extensions fuer unseren
		// Extension Point verfolgen
		tracker.registerHandler(this, ExtensionTracker
		    .createExtensionPointFilter(extensionPoint));
	}

	@Override
	public void addExtension(IExtensionTracker tracker, IExtension extension) {

            System.out.println("addExtension "  + extension.getConfigurationElements()[0].getAttribute("id"));

            try {

            	
            	window.getActivePage().showView(IM_ID);

			} catch (PartInitException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
            System.out.println("aha");
		
	}

	@Override
	public void removeExtension(IExtension extension, Object[] objects) {
		// TODO Auto-generated method stub
		
	}
	

}

Damit das betreffende Bundle installiert bzw. neuinstalliert wird, mache ich in der OSGi Consoloe einfach refresh BundleID.

Viele Grüße
Perpetuum
 

Wildcard

Top Contributor
Damit das betreffende Bundle installiert bzw. neuinstalliert wird, mache ich in der OSGi Consoloe einfach refresh BundleID.
So geht das nicht.
OSGi kann das zwar wunderbar, Eclipse aber nicht, Views werden per Extension registriert und Extensions werden nur beim Start von Eclipse geparst. Bundles die du danach lädst funktionieren zwar, sind aber der Extension Registry nicht bekannt.
 

Perpetuum82

Mitglied
Ahhhhhhhhhhh...

Das erklärt auch das Verhalten. Sprich ich muss mich um die Registrierung der Extensions irgendwie selbst kümmern.

Na mal sehen was möglich ist.

Vielen Dank schon mal für den hilfreichen Tipp! :toll:


EDIT --------------------------------------------------------------------------------------

Ich habe nochmal versucht das Verhalten der Extensionregistry nachzuvollziehen.

Dazu habe ich eine View mit einem Button (der Button führt nur den Befehl
Java:
PlatformUI.getWorkbench().getWorkbenchWindows()[0].getActivePage().showView("org.wt.test.im.extension.ViewIM");
). Diese View wird direkt aus meiner RCP Application contributed und ist immer da. Ich starte die RCP Appl. ohne das Plugin mit der zusätzlichen ViewContribution mitzustarten. Soweit so gut.

Dann installiere ich das Bundle über die Console und starte es. Es ist im Zustand ACTIVE. Ich drücke den Button und siehe da in der ExtensionRegistry ist diese Contribution registriert und die View wird tatsächlich in dem Placeholder angezeigt. Nun deinstalliere ich das Package und die View verschwindet auch. So wie gewollt.

Versuche ich das ganze nochmal. Wird die View aber nicht mehr angezeigt. Das Hinzufügen der View läuft aber sauber durch ohne Fehler oder anzuhalten. Wenn ich jetzt einpaar mal die Page maximiere und minimiere, kommt irgendwann die View zum Vorschein. Deinstalliere ich nun das Package verschwindet die View aber nicht mehr.

Ich schließe draus, dass das ganze doch sehr instabil und verbugt ist und nicht richtig dynamisch funktioniert.

Ist das der Grund warum nach einer Plug-in Installation eclipse neugestartet werden muss, damit all die neuen Contributions zu Beginn mitgestartet und registriert werden und alles sauber über die Bühne läuft?

Echte Dynamic on the fly die Oberfläche via Plug-ins veränder kann man dann mit RCP nicht machen.



Theoretisch könnte ich den ViewPart auch selber als ExecutableExtension laden. Nur kann ich das Objekt niergendwo in der Page darstellen. Weil ich nur die ID des ViewParts übergeben kann und alles andere läuft verdeckt über die Registry.

Ebenfalls kann ich keine Controls oder Widgets dynamisch aus externen Bundles nachladen oder deinstallieren, weil ich ein Parent-Objekt übergeben muss.

Die Frage ist also, gibt es irgendeinen Weg dynalisch zur Laufzeit meiner RCP Anwendung Bundles zu installieren und zu deinstallieren welche das UI meiner RCP Anwendung anpassen?

Viele Grüße
Eduard
 
Zuletzt bearbeitet:

Wildcard

Top Contributor
Das die Extension Registry nur beim Start geparst wird ist kein Bug, sondern eine Limitierung im aktuellen Design. Du kannst natürlich die Oberfläche dynamisch manipulieren wie du lustig bist und auch dynamisch Bundles installieren/entfernen wie du magst, aber du kannst dafür nicht die Extension Registry verwenden.
Anders gesagt: du kannst zB eine View per Extension Point registrieren die selbst keinen Inhalt hat. Gleichzeitig definierst du eine neue Capability (Capabilities sind so eine Art Filter für die Extension Registry) die dafür sorgt das deine View initial nicht zugänglich ist für den Anwender. Diese Placeholder-View versucht nun einen OSGi-Service zu konsumieren der die 'echte' View bereitstellen soll. Sobald der Service verfügbar ist, wird die Capability aktiviert (die View also per Menü sichtbar), der Service aufgefordert das Widget für die View zu erstellen und dann kannst du von mir aus noch automatisch die View anzeigen.

Eine einfachere Lösung (falls das zu deinem Use-Case passt): diese dynamische View ist von anfang an installiert, aber wird durch eine Capability ausgeblendet. Du installiert dynamisch ein neues Bundle und das aktiviert automatisch die Capability und die View ist scheinbar neu hinzugekommen (auch wenn sie eigentlich schon immer da war).
 
Zuletzt bearbeitet:

Perpetuum82

Mitglied
Hmm, also soweit ich das verstanden habe, platziere ich eine View schonmal vorab als Placeholder. Zeige sie aber nicht an. Kommt ein Bundle dazu mit dem Inhalt der View lade ich das ganze, platziere das in der View und zeige die View an.

Problem hier ist nur, wenn ich den Inhalt in einem Composite oder Control oder las Widget Klasse erstelle (davon ableite), dann habe ich das Problem der 'Parent'-Übergabe. Beim erzeugen von Composite usw. wird ein parent Composite bei Contruktor gefordert. Diesen habe ich beim Laden leider nicht und übergeben kann ich das ganze auch nicht sofern ich eine ExecutableExtension lade.

Das mit dem konsumieren des Inhalts des OSGi-Bundles verstehe ich ebend nicht ganz. Wie soll das ablaufen, wenn nicht über eine ExecutablaeExtension, sprich ich lade die Klasse dynamisch?

Gruß
Eduard
 

Wildcard

Top Contributor
Ist dir nicht aufgefallen das Eclipse niemals als Klasse ein Control erwartet? Das ist immer ein EditorPart, oder ein ViewPart, oder ähnliches die eine createControl(Composite parent) Methode haben... ;)
Das mit dem konsumieren des Inhalts des OSGi-Bundles verstehe ich ebend nicht ganz. Wie soll das ablaufen, wenn nicht über eine ExecutablaeExtension, sprich ich lade die Klasse dynamisch?
Na über einen OSGi Service. Entweder direkt im Code oder per Declarative Service.
 

Perpetuum82

Mitglied
Ist dir nicht aufgefallen das Eclipse niemals als Klasse ein Control erwartet? Das ist immer ein EditorPart, oder ein ViewPart, oder ähnliches die eine createControl(Composite parent) Methode haben... ;)

Na über einen OSGi Service. Entweder direkt im Code oder per Declarative Service.

OK, nur wenn ich einen ViewPart implementiere, den dann dynamisch lade, bekomme ich den nicht in eine Perspektive rein. Dort wird ja nicht ein Objekt erwartet, sonder eine ID einer Externsion.

Wie bekomme ich einen ViewPart in meine Oberfläche rein? ViewPart ist auch kein Control oder Composite, so dass man es in die Shell einfach packen kann. Ich steht da grad wohl irgendwie auf dem Schlauch... ???:L
Grüße
Eduard
 

Wildcard

Top Contributor
Deine View musst du statisch registrieren. Deren Inhalt kann aber dynamisch sein. Nichts spricht gegenen einen OSGi Service mit eigens definiertem Interface das so etwas wie eine
Code:
createControl(Composite parent)
Methode hat. Drücke ich mich wirklich so unklar aus? :noe:
 

Perpetuum82

Mitglied
Deine View musst du statisch registrieren. Deren Inhalt kann aber dynamisch sein. Nichts spricht gegenen einen OSGi Service mit eigens definiertem Interface das so etwas wie eine
Code:
createControl(Composite parent)
Methode hat. Drücke ich mich wirklich so unklar aus? :noe:

Ja, das muss gehen.

Habe aber eine andere Möglichkeit gefunden um meine Perspektive um Views zu erweitern. Und zwar übder den Extension Pint perspectiveExtensions (wie hier beschrieben).

Leider klappt das auch nicht. Irgendwie habe ich nicht das Händchen dafür :noe:.
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben