/* * Copyright (c) 2012 Data Harmonisation Panel * * All rights reserved. This program and the accompanying materials are made * available under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution. If not, see <http://www.gnu.org/licenses/>. * * Contributors: * HUMBOLDT EU Integrated Project #030962 * Data Harmonisation Panel <http://www.dhpanel.eu> */ package eu.esdihumboldt.hale.ui.common.graph.labels; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.annotation.Nullable; import org.eclipse.draw2d.ConnectionRouter; import org.eclipse.draw2d.IFigure; import org.eclipse.jface.resource.FontDescriptor; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.services.IDisposable; import org.eclipse.zest.core.viewers.GraphViewer; import org.eclipse.zest.core.viewers.IEntityConnectionStyleProvider; import org.eclipse.zest.core.viewers.IEntityStyleProvider; import org.eclipse.zest.core.viewers.IFigureProvider; import org.eclipse.zest.core.widgets.ZestStyles; import eu.esdihumboldt.hale.common.align.extension.function.FunctionDefinition; import eu.esdihumboldt.hale.common.align.extension.function.FunctionUtil; import eu.esdihumboldt.hale.common.align.model.AlignmentUtil; import eu.esdihumboldt.hale.common.align.model.Cell; import eu.esdihumboldt.hale.common.align.model.CellExplanation; import eu.esdihumboldt.hale.common.align.model.Entity; import eu.esdihumboldt.hale.common.align.model.EntityDefinition; import eu.esdihumboldt.hale.common.align.model.Type; import eu.esdihumboldt.hale.common.align.model.impl.TypeEntityDefinition; import eu.esdihumboldt.hale.common.core.service.ServiceProvider; import eu.esdihumboldt.hale.common.schema.model.Definition; import eu.esdihumboldt.hale.common.schema.model.TypeDefinition; import eu.esdihumboldt.hale.ui.common.CommonSharedImages; import eu.esdihumboldt.hale.ui.common.definition.viewer.DefinitionLabelProvider; import eu.esdihumboldt.hale.ui.common.function.viewer.FunctionLabelProvider; import eu.esdihumboldt.hale.ui.common.graph.figures.CellFigure; import eu.esdihumboldt.hale.ui.common.graph.figures.EntityFigure; import eu.esdihumboldt.hale.ui.common.graph.figures.FunctionFigure; import eu.esdihumboldt.hale.ui.common.graph.internal.GraphUIPlugin; import eu.esdihumboldt.hale.ui.common.service.compatibility.CompatibilityService; import eu.esdihumboldt.hale.ui.common.service.compatibility.CompatibilityServiceListener; import eu.esdihumboldt.hale.ui.util.graph.CustomShapeFigure; import eu.esdihumboldt.hale.ui.util.graph.WrappedText; import eu.esdihumboldt.hale.ui.util.graph.shapes.FingerPost; /** * Label provider for mapping graphs. * * @author Simon Templer */ public class GraphLabelProvider extends LabelProvider implements IEntityStyleProvider, IEntityConnectionStyleProvider, IFigureProvider { private final int entityBorderWidth = 1; private final Color entityBorderColor; private final Color entityBorderHighlightColor; private final Color typeBackgroundColor; private final Color propertyBackgroundColor; private final Color entityHighlightColor; private final Color entityForegorundColor; private final int cellBorderWidth = 1; private final Color cellBorderColor; private final Color cellBorderHighlightColor; private final Color cellBackgroundColor; private final Color cellHighlightColor; private final Color cellForegroundColor; private final LabelProvider definitionLabels; private final FunctionLabelProvider functionLabels = new FunctionLabelProvider(); private final ServiceProvider serviceProvider; /** * Map with images of cell function images with base alignment overlay */ private final Map<String, Image> baseAlignmentFunctionImages = new HashMap<String, Image>(); private final Image baseAlignmentFunctionOverlay = GraphUIPlugin .getImageDescriptor("icons/base_align_cell_overlay.gif").createImage(); //$NON-NLS-1$ /** * Local resource manager. * * TODO use for other resources than font? */ protected final LocalResourceManager resources = new LocalResourceManager( JFaceResources.getResources()); private final Font customFigureFont; private final CompatibilityServiceListener csl; private final List<Cell> incompatibleCells; private String lastCompatibilityMode; // TODO set colors for function in graph? /** * Default constructor * * @param associatedViewer the associated viewer (needed for style legend) * or <code>null</code> * @param provider the service provider that may be needed to obtain cell * explanations, may be <code>null</code> */ public GraphLabelProvider(@Nullable GraphViewer associatedViewer, @Nullable ServiceProvider provider) { super(); serviceProvider = provider; definitionLabels = createDefinitionLabels(associatedViewer); final Display display = Display.getCurrent(); // XXX keep entity colors in a central place? // XXX colors dependent of mapping context? // entity colors entityBorderColor = null; entityForegorundColor = null; // display.getSystemColor(SWT.COLOR_BLACK); typeBackgroundColor = new Color(display, 190, 230, 160); propertyBackgroundColor = new Color(display, 220, 250, 200); entityHighlightColor = new Color(display, 250, 250, 130); entityBorderHighlightColor = display.getSystemColor(SWT.COLOR_GRAY); // cell colors cellBorderColor = null; cellBorderHighlightColor = display.getSystemColor(SWT.COLOR_GRAY); cellBackgroundColor = null; cellForegroundColor = null; cellHighlightColor = entityHighlightColor; customFigureFont = createFigureFont(); incompatibleCells = new ArrayList<Cell>(); // initiate compatibility mode checkups and changes final CompatibilityService cs = PlatformUI.getWorkbench() .getService(CompatibilityService.class); lastCompatibilityMode = cs.getCurrentDefinition().getDisplayName(); csl = new CompatibilityServiceListener() { @Override public void compatibilityChanged(boolean isCompatible, List<Cell> incompatibleCells) { GraphLabelProvider.this.incompatibleCells.clear(); if (!isCompatible) { GraphLabelProvider.this.incompatibleCells.addAll(incompatibleCells); lastCompatibilityMode = cs.getCurrentDefinition().getDisplayName(); } } }; cs.addCompatibilityListener(csl); } /** * Returns whether the given cell is an inherited cell.<br> * The default implementation returns <code>false</code>, since the label * provider got no information about any selected type cell. * * @param cell the cell to check * @return true, if the cell is inherited, false otherwise. */ protected boolean isInherited(Cell cell) { return false; } /** * @return the cellHighlightColor */ protected Color getCellHighlightColor() { return cellHighlightColor; } /** * Create the label provider for {@link Definition}s and * {@link EntityDefinition}s. * * @param associatedViewer the associated viewer (needed for style legend) * or <code>null</code> * @return the label provider */ protected LabelProvider createDefinitionLabels(@Nullable GraphViewer associatedViewer) { return new DefinitionLabelProvider(associatedViewer, true); } /** * Create the font to use for the figures. * * @return the figure font or <code>null</code> */ protected Font createFigureFont() { FontData[] defFontData = JFaceResources.getDefaultFont().getFontData(); return resources .createFont(FontDescriptor.createFrom(defFontData[0].getName(), 9, SWT.NORMAL)); } /** * @see LabelProvider#getImage(Object) */ @Override public Image getImage(Object element) { if (element instanceof Entity) { element = ((Entity) element).getDefinition(); } if (element instanceof EntityDefinition || element instanceof Definition<?>) { // use definition image return definitionLabels.getImage(element); } if (element instanceof Cell) { // use function image if possible Cell cell = (Cell) element; String functionId = cell.getTransformationIdentifier(); FunctionDefinition<?> function = FunctionUtil.getFunction(functionId, serviceProvider); if (function != null) { Image image = functionLabels.getImage(function); if (image == null) { // use a default image if none is available image = CommonSharedImages.getImageRegistry() .get(CommonSharedImages.IMG_FUNCTION); } if (cell.isBaseCell()) { Image baseAlignmentImage = baseAlignmentFunctionImages.get(functionId); if (baseAlignmentImage == null) { baseAlignmentImage = new Image(image.getDevice(), image.getBounds()); GC gc = new GC(baseAlignmentImage); try { gc.drawImage(image, 0, 0); gc.drawImage(baseAlignmentFunctionOverlay, 0, 0); } finally { gc.dispose(); } baseAlignmentFunctionImages.put(functionId, baseAlignmentImage); } image = baseAlignmentImage; } return image; } return null; } if (element instanceof FunctionDefinition) { return functionLabels.getImage(element); } return super.getImage(element); } /** * @see LabelProvider#getText(Object) */ @Override public String getText(Object element) { if (element instanceof Entity) { element = ((Entity) element).getDefinition(); } if (element instanceof EntityDefinition) { // use definition text return definitionLabels.getText(element); } if (element instanceof Definition<?>) { // use definition text return definitionLabels.getText(element); } if (element instanceof Cell) { // use function name if possible Cell cell = (Cell) element; String functionId = cell.getTransformationIdentifier(); FunctionDefinition<?> function = FunctionUtil.getFunction(functionId, serviceProvider); if (function != null) { return functionLabels.getText(function); } return functionId; } if (element instanceof FunctionDefinition) { return functionLabels.getText(element); } return super.getText(element); } /** * @see IDisposable#dispose() */ @Override public void dispose() { for (Image image : baseAlignmentFunctionImages.values()) image.dispose(); baseAlignmentFunctionOverlay.dispose(); definitionLabels.dispose(); functionLabels.dispose(); // dispose created colors typeBackgroundColor.dispose(); propertyBackgroundColor.dispose(); entityHighlightColor.dispose(); // cellBorderHighlightColor.dispose(); resources.dispose(); PlatformUI.getWorkbench().getService(CompatibilityService.class) .removeCompatibilityListener(csl); super.dispose(); } /** * @see IEntityStyleProvider#getNodeHighlightColor(Object) */ @Override public Color getNodeHighlightColor(Object entity) { if (entity instanceof Entity || entity instanceof EntityDefinition || entity instanceof Definition<?>) { return entityHighlightColor; } if (entity instanceof Cell || entity instanceof FunctionDefinition) { return cellHighlightColor; } return null; } /** * @see IEntityStyleProvider#getBorderColor(Object) */ @Override public Color getBorderColor(Object entity) { if (entity instanceof Entity || entity instanceof EntityDefinition || entity instanceof Definition<?>) { return entityBorderColor; } if (entity instanceof Cell || entity instanceof FunctionDefinition) { return cellBorderColor; } return null; } /** * @see IEntityStyleProvider#getBorderHighlightColor(Object) */ @Override public Color getBorderHighlightColor(Object entity) { if (entity instanceof Entity || entity instanceof EntityDefinition || entity instanceof Definition<?>) { return entityBorderHighlightColor; } if (entity instanceof Cell || entity instanceof FunctionDefinition) { return cellBorderHighlightColor; } return null; } /** * @see IEntityStyleProvider#getBorderWidth(Object) */ @Override public int getBorderWidth(Object entity) { if (entity instanceof Entity || entity instanceof EntityDefinition || entity instanceof Definition<?>) { return entityBorderWidth; } if (entity instanceof Cell || entity instanceof FunctionDefinition) { return cellBorderWidth; } return -1; } /** * @see IEntityStyleProvider#getBackgroundColour(Object) */ @Override public Color getBackgroundColour(Object entity) { if (entity instanceof Entity || entity instanceof EntityDefinition || entity instanceof Definition<?>) { if (entity instanceof Type || entity instanceof TypeEntityDefinition || entity instanceof TypeDefinition) { return typeBackgroundColor; } return propertyBackgroundColor; } if (entity instanceof Cell || entity instanceof FunctionDefinition) { return cellBackgroundColor; } return null; } /** * @see IEntityStyleProvider#getForegroundColour(Object) */ @Override public Color getForegroundColour(Object entity) { if (entity instanceof Entity || entity instanceof EntityDefinition || entity instanceof Definition<?>) { return entityForegorundColor; } if (entity instanceof Cell || entity instanceof FunctionDefinition) { return cellForegroundColor; } return null; } /** * @see IEntityStyleProvider#getTooltip(Object) */ @Override public IFigure getTooltip(Object entity) { if (entity instanceof Cell) { Cell cell = (Cell) entity; FunctionDefinition<?> function = FunctionUtil .getFunction(cell.getTransformationIdentifier(), serviceProvider); if (function != null) { CellExplanation explanation = function.getExplanation(); if (explanation != null) { String text = explanation.getExplanation(cell, serviceProvider); if (text != null) { return new WrappedText(text, 400); } } } } // default return null; } /** * @see IEntityStyleProvider#fisheyeNode(Object) */ @Override public boolean fisheyeNode(Object entity) { // default return false; } /** * @see IEntityConnectionStyleProvider#getConnectionStyle(Object, Object) */ @Override public int getConnectionStyle(Object src, Object dest) { return ZestStyles.CONNECTIONS_SOLID; // | // ZestStyles.CONNECTIONS_DIRECTED; } /** * @see IEntityConnectionStyleProvider#getColor(Object, Object) */ @Override public Color getColor(Object src, Object dest) { // default return null; } /** * @see IEntityConnectionStyleProvider#getHighlightColor(Object, Object) */ @Override public Color getHighlightColor(Object src, Object dest) { // default return null; } /** * @see IEntityConnectionStyleProvider#getLineWidth(Object, Object) */ @Override public int getLineWidth(Object src, Object dest) { // default return -1; } /** * @see IEntityConnectionStyleProvider#getTooltip(Object, Object) */ @Override public IFigure getTooltip(Object src, Object dest) { // default return null; } /** * @see IEntityConnectionStyleProvider#getRouter(Object, Object) */ @Override public ConnectionRouter getRouter(Object src, Object dest) { // default return null; } /** * @see IFigureProvider#getFigure(Object) */ @Override public IFigure getFigure(Object element) { CustomShapeFigure figure = null; if (element instanceof Cell) { Cell cell = (Cell) element; if (incompatibleCells.contains(cell)) { figure = new CellFigure(cell, customFigureFont, false, lastCompatibilityMode, isInherited(cell)); } else { figure = new CellFigure(cell, customFigureFont, true, lastCompatibilityMode, isInherited(cell)); } } if (element instanceof FunctionDefinition) { figure = new FunctionFigure(getCustomFigureFont()); } if (element instanceof Entity) { element = ((Entity) element).getDefinition(); } if (element instanceof EntityDefinition) { String contextText = AlignmentUtil.getContextText((EntityDefinition) element); switch (((EntityDefinition) element).getSchemaSpace()) { case SOURCE: figure = new EntityFigure(new FingerPost(10, SWT.RIGHT), contextText, null, getCustomFigureFont()); break; case TARGET: figure = new EntityFigure(new FingerPost(10, SWT.LEFT), contextText, null, getCustomFigureFont()); break; } } if (figure != null && !figure.getSize().isEmpty()) { figure.setPreferredSize(figure.getSize()); } return figure; } /** * @return the custom figure font */ public Font getCustomFigureFont() { return customFigureFont; } }