# ISelectionProvider und eigene Selections



## Clip (25. Aug 2006)

Hallo,

ich habe eine RCP Applikation.
In dieser benutze ich einen eigenen Editor. In diesem Editor stelle ich in einer 10 x 10 Matrix 100 Composites dar. Jedes Composite hat ein Label mit einem Bild. Zudem repäsentiert jedes Composite ein Object aus meinem Model.
Dafür habe ich eine Klasse geschriben, die Composite erbt. Als Interface habe ich ISelectionProvider angegeben. Bei einem Mausklick auf ein Bild führe ich folgendes aus:

```
public void mouseDown(MouseEvent e) {
  selection = new StructuredSelection(sample);
  setSelection(selection);
}
```
Ein sample Object wird hier der Auswahl übergeben.

In setSelection wird 

```
firePostSelectionChanged(new SelectionChangedEvent(this, selection));
```
 ausgeführt.

Hier die Klasse.

```
protected void firePostSelectionChanged(final SelectionChangedEvent event) {
		Object[] listeners = postSelectionChangedListeners.getListeners();
		for (int i = 0; i < listeners.length; ++i) {
			final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i];
			SafeRunnable.run(new SafeRunnable() {
				public void run() {
					l.selectionChanged(event);
				}
			});
		}
	}
```

In meinem Editor hate ich einen Listener angemeldet :

```
entry.addPostSelectionChangedListener(new ISelectionChangedListener(){
  public void selectionChanged(SelectionChangedEvent event) {
    // ???						
  }					
});
```

entry ist dabei ein Composite. Es gibt also genau 100 listener, für jedes Composite einen. 

Soweit funktioniert auch alles. Im Event wird als selection das sample Objekt mitgeliefert.

Jetzt ist es ja so, dass z.B. bei einem TableViewer mittels der Methode 
	
	
	
	





```
getSite().setSelectionProvider(tableViewer);
```
 der Viewer zu einem Auswahlbereitsteler wird. 
Eclipse kann dann , z.B. in seinen Actions global auf solch ein Event zugreifen und Aktionen ausführen.

Klicke ich beispielsweise in einem TableViewer einen Eintrag an, der ebenfalls ein sample Objekt repräsentiert, so wird die SampleAction durch diesen Code in der Sample Action sichtbar.:

```
public void selectionChanged(IWorkbenchPart part, ISelection incoming) {
	if (incoming instanceof IStructuredSelection) {
		selection = (IStructuredSelection) incoming;
		setEnabled(selection.getFirstElement() instanceof Sample);
	} else {
		setEnabled(false);
	}
}
```

Wobei die Aktion in der Toolbar "liegt" und in ApplicationActionBarAdvisor deklariert wurde.

ZUrück zu meinen 100 Composites 
Bei einem Mausklick auf ein Bild, werden zwar alle Events geworfen und abgehört, inklusieve werde die richtigen Objekte in den events verschickt. Nur leider wird die selectionChanged() Methode der Action nicht angesprungen. 
Ich vermute, dass man Eclipse irgentwie mitteilen muss, dass eine Auswahl getroffen wurde. Nur wie?

```
getSite().setSelectionProvider(entry);
```
 zur Erstellung eines Compoiste entry führt leider zu Fehlern.

weiß das jemend was ich machen muss?

Danke & Gruß

Ps: sorry für den Roman


----------



## Clip (26. Aug 2006)

Hallo,

ich habe es inzwischen herausbekommen.
Erstmal, der Schlüssel ist folgender Artikel.

Lösung:
1. Das Composite (VisualSample) welches als SelectionProvider dienen soll muss meinen RackEditor sagen können, dass es ausgewählt wurde. Dazu hab eich zunächste ein IVisualSampleListener geschrieben:

```
public interface IVisualSampleListener {
	public void visualSampleSelected(VisualSample visualSample);
}
```

2. In meinem VisualSample gibt es nur ein Label mit einem Bild. Durch einen Mausklick soll das Objekt welches repräsentiert wird ausgewählt werden. Daher muss ein Mauslistener auf das Label definiert werden:

```
private class VisualSampleMouseListener implements MouseListener{		
		public void mouseDoubleClick(MouseEvent e) {
		}

		public void mouseDown(MouseEvent e) {
			fireVisualSampleSelected(VisualSample.this);
		}

		public void mouseUp(MouseEvent e) {			
		}	
	}
```
Dieser muss natürlich auch zugewiesen werden:

```
label.addMouseListener(new VisualSampleMouseListener());
```

3. Im Rack Editor muss die Schnittstelle ISelectionProvider eingebunden werden.
Die durch das Interface vorgeschriebenen Methoden sehen in meinem Fall so aus:

```
public void addSelectionChangedListener(ISelectionChangedListener listener) {
		selectionChangedListeners.add(listener);		
	}

	public ISelection getSelection() {
		return selection;
	}

	public void removeSelectionChangedListener(ISelectionChangedListener listener) {
		selectionChangedListeners.remove(listener);
	}

	public void setSelection(ISelection selection) {
		fireSelectionChanged(new SelectionChangedEvent(this, selection));			
	}
```

selectionChangedListeners wurde als private Instanz der Klasse deklariert:

```
private ListenerList selectionChangedListeners = new ListenerList();
```

selection wurde als private Instanz der Klasse deklariert:

```
private StructuredSelection selection = new StructuredSelection(new Object[0]);
```
Dies muss mit new Object[0] erfolgen. Geschieht dies nicht, kann es fürchterliche Fehler geben da in getSelection() eben dieses selection Objekt zurückgegeben wird. Dies passiert u.a. schon direkt nach der Erzeugung des Editors...

Dann müssen noch alle Listeners benachrichtigt werden. Dies erfolgt durch die Methode fireSelectionChanged.

```
protected void fireSelectionChanged(final SelectionChangedEvent event) {		
		Object[] listeners = selectionChangedListeners.getListeners();
		for (int i = 0; i < listeners.length; ++i) {
			final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i];
			SafeRunnable.run(new SafeRunnable() {
				public void run() {
					l.selectionChanged(event);
				}
			});
		}
	}
```

Bleibt noch den Editor als SelectionProvider im System anzumelden. Dies geschieht in der Methode createPartControl

```
getSite().setSelectionProvider(this);
```


4. Im RackEditor in dem die VisualSamples ja dargestellt werden, muss der IVisualSampleListener eingebunden werden:

```
VisualSample entry = new VisualSample(composite,sample, this, i, j,SWT.NONE );	
				entry.addVisualSampleListener(new IVisualSampleListener(){
					public void visualSampleSelected(VisualSample visualSample) {		
						Sample sample = visualSample.getSample();
						if (sample != null)
							selection = new StructuredSelection(sample);
						else
							selection = new StructuredSelection(new Object[0]);
						setSelection(selection);						
					}					
				});
```
"entry " ist dabei ein Composite (das ganze liegt bei mir in einer Schleife, das ist aber hier egal...).


5.
Die eigene Selection ist somit fertig. Z.B. kann in einer entsprechenden SampleAction darauf eingegangen werden:

```
public class SampleAction extends Action implements ISelectionListener{

	private final IWorkbenchWindow window;

	public final static String ID = "sample";
	
	private IStructuredSelection selection;	

	
	public SampleAction(IWorkbenchWindow window) {
		this.window = window;
		setId(ID);
		setActionDefinitionId(ID);
		setText("&Edit Sample");
		setImageDescriptor(AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, IImageKeys.SAMPLE));
		window.getSelectionService().addSelectionListener(this);
	}

	
	// Hier wird die Selection verarbeitet! Ist sie vom Typ Sample wird die Aktion aktiviert.

	public void selectionChanged(IWorkbenchPart part, ISelection incoming) {
		if (incoming instanceof IStructuredSelection) {
			selection = (IStructuredSelection) incoming;
			setEnabled(selection.getFirstElement() instanceof Sample);
		} else {
			setEnabled(false);
		}
	}
	
	public void run() {
		Object[] items = selection.toArray();
		Sample[] samples = new Sample[items.length];
		for (int i = 0; i < items.length; i++){
			samples[i] = (Sample)items[i];
		}
		SampleDialog sampleDialog = new SampleDialog(window.getShell(), samples);;
		int code = sampleDialog.open();
		if (code == Window.OK){			
		}	
	}	
}
```

Das hat jetzt verdammt viel Zeit gekostet..... Obwohls im Nachhinein betrachtet alles so logisch und einfach aussieht...  :autsch:


----------



## Wildcard (27. Aug 2006)

Clip hat gesagt.:
			
		

> Das hat jetzt verdammt viel Zeit gekostet..... Obwohls im Nachhinein betrachtet alles so logisch und einfach aussieht...  :autsch:


Das ist leider immer so bei der Eclipse API  :? 
Aber schön das du die Lösung so ausführlich gepostet hast, jetzt haben auch noch andere was davon  :toll:


----------

