package org.nightlabs.jfire.personrelation.ui.tree; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.eclipse.jface.viewers.CellLabelProvider; import org.eclipse.jface.viewers.ColumnViewer; import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.nightlabs.base.ui.labelprovider.ColumnSpanLabelProvider; import org.nightlabs.eclipse.compatibility.Compatibility; import org.nightlabs.jdo.ObjectID; /** * This should give us more control when we need to access the Graphics Control in the super class's {@link ColumnSpanLabelProvider}. * Notice also that this particular Label Provider handles any further registered delegates. * * Externalised from the original {@link PersonRelationTree}. * * See example with org.nightlabs.jfire.personrelation.trade.ui.tucked.TuckedPersonRelationTreeLabelProvider. * * @author Marco Schulze * @author khaireel */ public class PersonRelationTreeLabelProvider<N extends PersonRelationTreeNode> //extends ColumnSpanLabelProvider extends CellLabelProvider implements IColorProvider, ITableLabelProvider { private final Logger logger = Logger.getLogger(PersonRelationTreeLabelProvider.class); private ColumnViewer columnViewer; private Map<Class<?>, IPersonRelationTreeLabelProviderDelegate> jdoObjectIDClass2PersonRelationTreeLabelProviderDelegate = new HashMap<Class<?>, IPersonRelationTreeLabelProviderDelegate>(); private Map<Class<?>, IPersonRelationTreeLabelProviderDelegate> jdoObjectClass2PersonRelationTreeLabelProviderDelegate = new HashMap<Class<?>, IPersonRelationTreeLabelProviderDelegate>(); private Map<Class<?>, IPersonRelationTreeLabelProviderDelegate> jdoObjectClass2DelegateCache = new HashMap<Class<?>, IPersonRelationTreeLabelProviderDelegate>(); public PersonRelationTreeLabelProvider(ColumnViewer columnViewer, boolean addDefaultDelegates) { // super(columnViewer); this.columnViewer = columnViewer; if (addDefaultDelegates) { addPersonRelationTreeLabelProviderDelegate(new DefaultPersonRelationTreeLabelProviderDelegatePerson()); addPersonRelationTreeLabelProviderDelegate(new DefaultPersonRelationTreeLabelProviderDelegatePersonRelation()); } } public void addPersonRelationTreeLabelProviderDelegate(IPersonRelationTreeLabelProviderDelegate delegate) { Class<? extends ObjectID> objectIDClass = delegate.getJDOObjectIDClass(); Class<?> objectClass = delegate.getJDOObjectClass(); jdoObjectIDClass2PersonRelationTreeLabelProviderDelegate.put(objectIDClass, delegate); jdoObjectClass2PersonRelationTreeLabelProviderDelegate.put(objectClass, delegate); jdoObjectClass2DelegateCache.clear(); if (logger.isTraceEnabled()) logger.trace("addPersonRelationTreeLabelProviderDelegate: added " + delegate + " for objectClass " + (objectClass == null ? null : objectClass.getName()) + " and objectIDClass " + (objectIDClass == null ? null : objectIDClass.getName())); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } protected Set<IPersonRelationTreeLabelProviderDelegate> getAllPersonRelationTreeLabelProviderDelegates() { Set<IPersonRelationTreeLabelProviderDelegate> result = new HashSet<IPersonRelationTreeLabelProviderDelegate>(); result.addAll(jdoObjectIDClass2PersonRelationTreeLabelProviderDelegate.values()); result.addAll(jdoObjectClass2PersonRelationTreeLabelProviderDelegate.values()); return result; } protected String getJDOObjectText(ObjectID jdoObjectID, Object jdoObject, int spanColIndex) { if (jdoObject == null) { IPersonRelationTreeLabelProviderDelegate delegate = getDelegate(jdoObjectID); if (delegate != null) { String result = delegate.getJDOObjectText(jdoObjectID, jdoObject, spanColIndex); if (result != null) return result; } else { switch (spanColIndex) { case 0: return String.valueOf(jdoObjectID); default: break; } } } else { // We check for the delegate first in order to allow overriding the defaults following below. Marco. IPersonRelationTreeLabelProviderDelegate delegate = getDelegate(jdoObject); if (delegate != null) { String result = delegate.getJDOObjectText(jdoObjectID, jdoObject, spanColIndex); if (result != null) return result; } else { switch (spanColIndex) { case 0: return String.valueOf(jdoObject); default: break; } } } return null; } @SuppressWarnings("unchecked") protected int[][] getColumnSpan(Object element) { if (!(element instanceof PersonRelationTreeNode)) return null; // null means each real column assigned to one visible column // return new int[][] { {0}, {1}, {2}, {3}, {4}, {5} }; N node = (N) element; ObjectID jdoObjectID = node.getJdoObjectID(); Object jdoObject = node.getJdoObject(); if (jdoObject == null) { IPersonRelationTreeLabelProviderDelegate delegate = getDelegate(jdoObjectID); if (delegate != null) { int[][] result = delegate.getJDOObjectColumnSpan(jdoObjectID, jdoObject); if (result != null) return result; } return new int[][] { {0, 1} }; } else { IPersonRelationTreeLabelProviderDelegate delegate = getDelegate(jdoObject); if (delegate != null) { int[][] result = delegate.getJDOObjectColumnSpan(jdoObjectID, jdoObject); if (result != null) return result; } return null; // null means each real column assigned to one visible column } } /** * Gets the delegate for the class of the given ID-object without taking its * type-hierarchy into account as ObjectIDs should not have a type hierarchy * * @param jdoObject The object to find the delegate for. * @return The delegate for the object, or <code>null</code> if none could * be found. */ private IPersonRelationTreeLabelProviderDelegate getDelegate(ObjectID jdoObjectID) { return jdoObjectIDClass2PersonRelationTreeLabelProviderDelegate.get(jdoObjectID.getClass()); } /** * Gets the delegate for the class of the given objec with respect to its * type-hierarchy, so a delegate registered for a super-class will be found * to. * * @param jdoObject The object to find the delegate for. * @return The delegate for the object, or <code>null</code> if none could * be found. */ public IPersonRelationTreeLabelProviderDelegate getDelegate(Object jdoObject) { Class<? extends Object> clazz = jdoObject.getClass(); if (!jdoObjectClass2DelegateCache.containsKey(clazz)) { IPersonRelationTreeLabelProviderDelegate delegate = jdoObjectClass2PersonRelationTreeLabelProviderDelegate.get(clazz); jdoObjectClass2DelegateCache.put(clazz, delegate); if (delegate == null) { // no direct delegate found for the class, search type hierarchy for (Class<?> delegateClazz : jdoObjectClass2PersonRelationTreeLabelProviderDelegate.keySet()) { if (delegateClazz.isAssignableFrom(clazz)) { jdoObjectClass2DelegateCache.put(clazz, jdoObjectClass2PersonRelationTreeLabelProviderDelegate.get(delegateClazz)); } } } } return jdoObjectClass2DelegateCache.get(clazz); } @SuppressWarnings("unchecked") @Override public String getColumnText(Object element, int spanColIndex) { if (element == null) { if (logger.isDebugEnabled()) logger.debug("getColumnText: element is null => returning null."); //$NON-NLS-1$ return null; } if (!(element instanceof PersonRelationTreeNode)) { if (logger.isDebugEnabled()) logger.debug("getColumnText: element is not a PersonRelationTreeNode (but a " + element.getClass().getName() + ") => returning element.toString()."); //$NON-NLS-1$ //$NON-NLS-2$ return String.valueOf(element); } N node = (N) element; ObjectID jdoObjectID = node.getJdoObjectID(); Object jdoObject = node.getJdoObject(); String result = getJDOObjectText(jdoObjectID, jdoObject, spanColIndex); if (logger.isDebugEnabled()) logger.debug("getColumnText: oid=" + jdoObjectID + " o=" +jdoObject+ " => returning: " + result); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ return result; } @SuppressWarnings("unchecked") @Override public Image getColumnImage(Object element, int spanColIndex) { if (element == null) return null; if (!(element instanceof PersonRelationTreeNode)) return null; N node = (N) element; ObjectID jdoObjectID = node.getJdoObjectID(); Object jdoObject = node.getJdoObject(); return getJDOObjectImage(jdoObjectID, jdoObject, spanColIndex); } protected Image getJDOObjectImage(ObjectID jdoObjectID, Object jdoObject, int spanColIndex) { if (jdoObject == null) { IPersonRelationTreeLabelProviderDelegate delegate = getDelegate(jdoObjectID); if (delegate != null) { Image result = delegate.getJDOObjectImage(jdoObjectID, jdoObject, spanColIndex); if (result != null) return result; } } else { IPersonRelationTreeLabelProviderDelegate delegate = getDelegate(jdoObject); if (delegate != null) { Image result = delegate.getJDOObjectImage(jdoObjectID, jdoObject, spanColIndex); if (result != null) return result; } } return null; } @Override public void update(ViewerCell cell) { // TODO Auto-generated method stub } @Override public Color getForeground(Object element) { if (element == null) return null; if (!(element instanceof PersonRelationTreeNode)) return null; @SuppressWarnings("unchecked") N node = (N) element; Object jdoObject = node.getJdoObject(); if (jdoObject != null) { IPersonRelationTreeLabelProviderDelegate delegate = getDelegate(jdoObject); if (delegate != null && (delegate instanceof IColorProvider)) { return ((IColorProvider) delegate).getForeground(jdoObject); } } return null; } @Override public Color getBackground(Object element) { return null; } private static class ColumnSpanLabelProviderDelegate extends ColumnSpanLabelProvider implements IColorProvider { private PersonRelationTreeLabelProvider<?> delegate; public ColumnSpanLabelProviderDelegate(PersonRelationTreeLabelProvider<?> delegate, ColumnViewer columnViewer) { super(columnViewer); this.delegate = delegate; } @Override protected int[][] getColumnSpan(Object element) { return delegate.getColumnSpan(element); } @Override public String getColumnText(Object element, int spanColIndex) { return delegate.getColumnText(element, spanColIndex); } @Override public Image getColumnImage(Object element, int spanColIndex) { return delegate.getColumnImage(element, spanColIndex); } @Override public Color getBackground(Object element) { return delegate.getBackground(element); } @Override public Color getForeground(Object element) { return delegate.getForeground(element); } } CellLabelProvider getLabelProviderToUseForTree() { if (Compatibility.isRCP) { // ColumnSpanLabelProvider works for RCP so we use that here... return new ColumnSpanLabelProviderDelegate(this, columnViewer); } else { // In all other cases we return 'this', a non-spanning CellLabelProvider. return this; } } }