contentProvider für versch. tabellen

schuetzejanett

Erfahrenes Mitglied
Hallo,

habe mehrer Tabellen in meiner rcp anwendung und generiere mir für jeden tableviewer einen eigenen contend und labelprovieder. Jetzt benötige ich allerdings eine tabelle die ich eigentlich schon mal habe nur ändert sich der inhalt einer spalte. Wie kann ich meine provider anpassen, so dass je nach aufrufender Klasse die richtige spalte angepasst wird.

Code:
public class PrintJobLabelProvider extends LabelProvider implements ITableLabelProvider {

	String[] titles = { "PrintJobID", "ProzessID","Papierart","EntaxRefNr" ,"Status", "JobTyp", "VP",
	        "GenerierungsDatum", "Anhang", "Inland" ,  "Seitenzahl"};
	
	public Image getColumnImage(Object element, int columnIndex) 
	{		
		return null;
	}

	public String getColumnText(Object element, int columnIndex) 
	{
		String result = "";
		switch (columnIndex)
		{
		case 0: 
			result = ""+ ((PrintJob)element).getPrintJobID();
			break;
		case 1:
			result = ""+ ((PrintJob)element).getProzessID();
			break;
		case 2: 
			result = ""+ ((PrintJob)element).getPaperKind().getName();
			break;
		case 3: 
			result = ""+ ((PrintJob)element).getEntaxRefNr();
			break;
		case 4: 
			result = ""+ ((PrintJob)element).getState();
			break;
		case 5: 
			result = ""+ ((PrintJob)element).getJobType().getName();
			break;
		case 6: 
			result = ""+ ((PrintJob)element).getContractPartner().getName();
			break;
		case 7: 			
			SimpleDateFormat df = new SimpleDateFormat( "dd-MM-yyyy HH:mm:ss" );
			result = df.format(((PrintJob)element).getDatePJ());
			break;
		case 8: 
			result = (((PrintJob)element).isAttach()) ?   "J" : "N";			
			break;	
		case 9: 
			result = (((PrintJob)element).isInland()) ?   "J" : "N";			
			break;	
		case 10 :
			result = ""+ ((PrintJob)element).getNumberOfPages();			
			break;
		default: 
			break;
		}		
		return result;
	}
	
	 public  void createColumns( Table table ) 
	 { 		
	      for( int i = 0; i < titles.length; i++ ) { 
	    	  TableColumn column = new TableColumn(table, SWT.CENTER, i); 
	    	  column.setText(titles[i]); 
	    	  column.setWidth(100); 
	    	  column.setResizable(false);  	    	  
	      } 	  
	      
	   } 


public class PrintJobContentProvider implements IStructuredContentProvider {

	public Object[] getElements(Object inputElement) 
	{			
		return  ((PrintJobViewResponse) inputElement).getAPJ().toArray();
	}
Kann ich das mit is instanceOf Klasse prüfen und dann Spalte ändern hinkriegen?
 
Was heisst Du "generierst" Deine Provider?

Also den ContentProvider kann man sehr generisch halten. Alle Tabellen und Listen, die auf einen Datenbestand zeigen können natürlich den selben ContentProvider benutzen. Mit etwas Geschick, lässt sich auch ein ContentProvider entwickeln, der eine ganze Gruppe von Klassen versorgt. Der ArrayContentProvider ist z.B. so eine generische Klasse, die für alle Arrays funktioniert.

Problematisch ist der Labelprovider, weil der ja spezifisches Wissen über das Object, die Spaltenanzahl etc. haben muss. Das einfachste ist, nur den immer anzupassen. Wegen des relativ geringen Codes ist das nicht sehr viel Arbeit und irgendwo muss die Metainformation ja herkommen.

Eine pfiffige Alternative wäre es das Object, welches an getElement übergeben wird per Reflection auszulesen. Lass Dir einfach alle Getter-Methoden des Objects geben, erzeuge daraus die Überschiften und rufe den i-ten Getter für die Spalten auf.

Codebeispiel folgt. Habe gerade wenig Zeit

Link zu Reflection

http://www.galileocomputing.de/openbook/javainsel6/javainsel_21_002.htm
 
danke für deine schnelle Antwort. Mit generieren meinte ich eigentlich nur programmieren, halt das ich nicht den standart nehme sondern mit meinen eienen angaben(spaltennamen, inhalt) überschreibe. War ein bischen blöd asgedrückt. Das mit dem nur noch einen contendprovider ist ne gute idee werde das mal ausprobieren.
freu mich schon auf dein codebsp zu den reflections.
 
Hi,

der ContentProvider reagiert auf Ereignisse in der Datenklasse uns zeichnet den View neu. Ich hatten in ursprünglich für einen Listview geschrieben, deswegen die Doppelclickereignisse. Bei Tabellen funktionieren die (so) nicht.

der LabelProvider mit Reflection. Leider kann man die Reihenfolge der Spalten nicht festlegen, da musst Du Dir was einfallen lassen..

Zum Laufen lassen musst Du folgende Jars aus Eclipse einbinden

Die beiden org.eclipse.swt jars, org.eclipse.jface und org.eclipse.jface.text, sowie org.eclipse.core.command

Java:
package de.tutorials.provider;

import java.lang.reflect.Method;
import java.util.ArrayList;

import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;

public class GenericLabelProvider extends LabelProvider implements ITableLabelProvider {

	
	
	private ArrayList<Method> list = new ArrayList<Method>();

	public GenericLabelProvider(Class clazz){
		
		
		Method [] methods = clazz.getDeclaredMethods();
		for (int i =0 ; i < methods.length; i++){
			if (methods[i].getName().startsWith("get") && methods[i].getParameterTypes().length == 0){
				list.add(methods[i]);
			}
		}
		
	}
	
	
	public String [] getNames() {
		String [] retval = new String[list.size()];
		int i =0 ;
		for(Method m: list){
			retval[i++] = m.getName().substring(3); 
		}
		return retval;
	}

	public int getColumnCount() {
		return list.size();
	}


	public Image getColumnImage(Object element, int columnIndex) {
		
		return null;
	}


	public String getColumnText(Object element, int columnIndex) {
		
		try {
			return list.get(columnIndex).invoke(element, new Object[]{}).toString();
		} catch (Exception e) {
			return "Fehler: " + e.getMessage();
		} 
	}

}

Der ContentProvider funktioniert bei Tabellen und Listen. Er ist nicht sehr generisch und ist auf SchweineModelle spezialisiert.

Java:
package de.tutorials.tiere.provider;

import java.util.Observable;
import java.util.Observer;

import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.Viewer;

import de.tutorials.tiere.Schwein;
import de.tutorials.tiere.SchweineModel;

public class SchweineContentProvider implements IStructuredContentProvider, Observer, IDoubleClickListener {

	private Viewer viewer;

	public Object[] getElements(Object inputElement) {
		SchweineModel model = (SchweineModel) inputElement;
		return model.toArray();
	}

	public void dispose() {
		

	}

	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
		this.viewer =  viewer;
		if (viewer instanceof ListViewer) {
			((ListViewer)this.viewer).removeDoubleClickListener(this);
			((ListViewer)this.viewer).addDoubleClickListener(this);
		}
		if (oldInput == null)
			((SchweineModel) newInput).addObserver(this); 
	}

	public void update(Observable o, Object arg) {
		//plumpes Neuzeichnen durch neusetzten der Quelle. (geht auch besser ;-))
		SchweineModel model = (SchweineModel) o;
		viewer.setInput(model);
	}

	public void doubleClick(DoubleClickEvent event) {
		IStructuredSelection selection = (IStructuredSelection) event.getSelection();
		Schwein schwein = (Schwein) selection.getFirstElement();
		schwein.fressen();
		
	}

}

Der Viewer übergibt dem GenericProvider nur das Classobject der auszuwertenden Klasse. Die bekommst du entweder mit Class.forName("package.Klasse"), oder per Klasse.class, oder referenz.getClass().

Java:
package de.tutorials.gui;



import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;

import de.tutorials.provider.GenericLabelProvider;
import de.tutorials.tiere.Schwein;
import de.tutorials.tiere.SchweineModel;
import de.tutorials.tiere.provider.SchweineContentProvider;

public class SchweineViewer {
	
	private static final Display display = new Display();
	private Shell shell = null;
	private TableViewer viewer = null;
	private SchweineModel model = null;
	private Button button = null;
	
	
	SchweineViewer() {
		getViewer();
		getButton();
		dispatch();
	}

	
	private void dispatch() {
		
		getShell().open();
		while(! getShell().isDisposed()) {
			if(! getDisplay().readAndDispatch()) 
				getDisplay().sleep();
		}
	}

	

	private static Display getDisplay() {
		return display;
	}


	private Shell getShell() {
		if(shell == null){
			shell = new Shell(getDisplay());
			shell.setLayout(new FillLayout());
		}
		return shell;
	}


	private TableViewer getViewer() {
		if(viewer == null){
			viewer = new TableViewer(getShell(), SWT.SINGLE | SWT.FULL_SELECTION);
			GenericLabelProvider labelProvider = new GenericLabelProvider(Schwein.class);
			Table table = viewer.getTable();
			table.setHeaderVisible(true);
			for (int i = 0; i < labelProvider.getColumnCount(); i++){
				TableColumn column = new TableColumn(table, SWT.LEFT);
				column.setText(labelProvider.getNames()[i]);
				column.setWidth(200);
			}
			
			
			viewer.setContentProvider(new SchweineContentProvider());
			viewer.setLabelProvider(labelProvider);
			viewer.setInput(getModel());
		}
		return viewer;
	}


	private SchweineModel getModel() {
		if(model == null) {
			model = new SchweineModel();
			model.add(new Schwein("Piggy"));
			model.add(new Schwein("Babe"));
		}
		return model;
	}
	
	


	private Button getButton() {
		if(button == null) {
			button = new Button(getShell(), SWT.PUSH);
			button.setText("Neues Schwein!");
			button.addSelectionListener(new SelectionAdapter(){

				@Override
				public void widgetSelected(SelectionEvent e) {
					getModel().add(new Schwein());
				}}) ;
		}
		return button;
	}


	public static void main(String[] args) {
		new SchweineViewer();

	}

}


und sie Tiere

Java:
package de.tutorials.tiere;

import java.util.Observable;

public class Schwein extends Observable{
	
	private String name;
	private int gewicht;
	
	public Schwein() {
		this("nobody");
	}
	
	public Schwein(String name) {
		setName(name);
		setGewicht(10);
	}

	public int getGewicht() {
		return gewicht;
	}

	private void setGewicht(int gewicht) {
		this.gewicht = gewicht;
		fireEvent();
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
		fireEvent();
	}
	
	public void fressen() {
		setGewicht(getGewicht() + 1);
	}

	@Override
	public String toString() {
		
		return "Schwein [Name="+getName()+", Gewicht=" + getGewicht() + "]";
	}
	
	private void fireEvent() {
		setChanged();
		notifyObservers();
	}
	
	
	

}


Java:
package de.tutorials.tiere;

import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

public class SchweineModel extends Observable implements Observer{

	private List<Schwein> schweine = new ArrayList<Schwein>();
	
	public void add(Schwein e) {
		e.addObserver(this);
		schweine.add(e);
		fireEvent();
	}

	public void clear() {
		for(Schwein schwein: schweine)
			schwein.deleteObserver(this);
		schweine.clear();
		fireEvent();
	}

	public void remove(Schwein o) {
		o.deleteObserver(this);
		schweine.remove(o);
		fireEvent();
	}

	public Object[] toArray() {
		return schweine.toArray();
	}

	public void update(Observable o, Object arg) {
		fireEvent();
		
	}
 
	private void fireEvent() {
		setChanged();
		notifyObservers();
	}
	

}
 
Zurück