# TableViewer Contentprovider



## Clip (23. Aug 2006)

Hallo,

ich habe einen TableViewer. Diesem teile ich mittels setInput() eine Datenquelle mit. Als ContentProvider habe ich ArrayContentProvider angegeben. Dieser tut leider laut API spezifikation nichts bei inputChanged()
Code:

inputChanged(Viewer viewer, Object oldInput, Object newInput)
          This implementation does nothing.


Was ist ein guter Contentprovider wenn ich Tabellen benutzen will und gleichzeitig den Eclipse Adapter Mechanismus[1] benutzen möchte?
Gleichzeitig soll sich der Inhalt der Tabelle mittels Listener und tabelViewer.refrech() aktualisieren lassen.

[1]
Eclipse Rich Client Platform - Designing, Coding, and Packaging Java Applications
Kapitel 5.4.2
Seite: 73 unten.


----------



## byte (23. Aug 2006)

Wenn Du wirklich nur ein Array im TableViewer darstellen willst, dann kannste ruhig den ArrayContentProvider nehmen. Normalerweise arbeitet man aber mit eigenen Datenstrukturen und implementiert sich demnach auch einen eigenen ContentProvider und LabelProvider.

Aktualisieren kannst Du übrigens immer mittels tableViewer.refresh(). Das hat gar nix damit zu tun, welchen ContentProvider Du nun verwendest. Demnach brauchst Du auch nicht zwingend die inputChanged() zu implementieren, sondern aktualisierst den tableViewer einfach per Refresh in einem Listener.


----------



## Clip (23. Aug 2006)

Hallo und danke für die Antwort!
ich möchte natürlich kein Array darstellen sonder eine Tabelle. Zum Probieren hat ders aber ersteinmal getan.
Mit dem TableViewer.refresh() klappt es aber nicht bei mir 
Ich habe mal :

```
tableViewer.setInput(Session.getInstance().getRack(getRackID()).getSamples());	
		Session.getInstance().getRack(getRackID()).addUpdatableObjectListener(new IUpdatableObjectListener(){
			public void updatableObjectChanged(UpdatableObject parent, UpdatableObject current) {
				tableViewer.refresh();	
				MessageDialog.openInformation(null, "Info!", new Integer(((Rack)current).getSamples().length).toString());
			}			
		});
```

Die Methode "updatableObjectChanged" wird ausgeführt! Der Nachrichtendialog in dessen Rumpf wird immer dann angezeigt wenn es eine Änderung om Model gibt.  Die Methode getSamples() liefert sogar die aktualisierte Länge des Array (der Samples im Rack) zurück. 
Komischerweise wird aber die Tabelle nicht geupdated. 

Gibt es einen Trick oder sowas?


----------



## Clip (23. Aug 2006)

> Normalerweise arbeitet man aber mit eigenen Datenstrukturen und implementiert sich demnach auch einen eigenen ContentProvider und LabelProvider.



Kannst Du mir dafür ein Beispiel geben?
Danke!


----------



## Wildcard (23. Aug 2006)

Da gibts eigentlich gar nicht viel zu erklären, du musst nur die Methoden des Interfaces erfüllen, und die Javadocs dazu sind ja recht klar.
Der ContentProvider ist dazu da Daten aus dem Model zu extrahieren, so das also anders als in Swing keine Anforderungen an das Model selbst gestellt werden. Du kannst auf jedem Model arbeiten solange du einen passenden ContentProvider zur Verfügung stellst.


----------



## Clip (23. Aug 2006)

Das mit dem passenden Content Provider ist ha genau das Problem.

Mein Provider benutzt das Interface IStructuredContentProvider
Dieses stellt die Methode public Object[] getElements(Object parent) zur Verfügung.
In diesem könnte ich z.B. mittels Rack.getSamples() alle Samples als Array zurückgeben.

Im Labelprovider würde das dann in etwa so aussehen:

```
public String getColumnText(Object element, int columnIndex) {
			if (element instanceof Sample)
				return ((Sample)element).getName();
			else
				return null;
		}
```

Das bewirkt aber, dass alle Samples in der ersten Spalte meiner Tabelle dargestellt werden.

Meine Sampleklasse hat je ein X und ein Y Wert. Ich möchte aber, dass ein Sample Object an der Stelle in der Tabelle dargestellt wird, die diesen Werten entspricht.


----------



## byte (23. Aug 2006)

Dafür wird doch die Column als Argument übergeben. Du musst es halt entsprechend auswerten, z.b. so:


```
public String getColumnText(Object element, int columnIndex) {
         if (element instanceof Sample)
            Sample sample = (Sample)element;
            switch(columnIndex) {
            case 0: return ...;
            case 1: return ...;
            case default: return ...;
            }
         else
            return null;
      }
```


----------



## Wildcard (23. Aug 2006)

Der ContentProvider gibt für getElements Objekte zurück die die Rows repräsentieren.
Alles andere muss der LabelProvider erledigen


			
				void org.eclipse.jface.viewers.TableViewer.setLabelProvider(IBaseLabelProvider labelProvider) hat gesagt.:
			
		

> The table viewer implementation of this Viewer framework method ensures that the given label provider is an instance of either ITableLabelProvider or ILabelProvider.
> 
> If the label provider is an ITableLabelProvider, then it provides a separate label text and image for each column. Implementers of ITableLabelProvider may also implement ITableColorProvider and/or ITableFontProvider to provide colors and/or fonts.
> 
> If the label provider is an ILabelProvider, then it provides only the label text and image for the first column, and any remaining columns are blank. Implementers of ILabelProvider may also implement IColorProvider and/or IFontProvider to provide colors and/or fonts.


----------



## Clip (23. Aug 2006)

Also ein Problem habe ich noch.

Mein Labelprovider:

```
private class RackTableLabelProvider extends LabelProvider implements ITableLabelProvider{

		public Image getColumnImage(Object element, int columnIndex) {
			if (element instanceof Sample && columnIndex == ((Sample)element).getX()){
				return AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, IImageKeys.SAMPLE).createImage();
			}
			return null;
		}
	

		public String getColumnText(Object element, int columnIndex) {
			if (element instanceof Sample && columnIndex == ((Sample)element).getX())
				return ((Sample)element).getName();
			else				
				return null;
		}
				
	}
```

Mein ContentProvider:

```
private class RackTableContentProvider extends LabelProvider implements IStructuredContentProvider{

		public Object[] getElements(Object inputElement) {
			return rack.getSamples();
		}
		
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
			
		}	
	}
```

Der Contentprovider erstellt also für jedes Sample eine Tabellenreihe. Innerhalb der Tabellenreihe filter ich dann alle Einträge raus, die nicht in die Spalte passen (sample.x != columnIndex).
Mir fehlt die Möglichkeit Die Y Achse (die Zeilen) bestimmen zu können. 
Oder mache ich grundlegend was falsch?

Ps.: Seit ich meine eigenen Content und Labelprovider benutze geht der Tablerefresh


----------

