/*******************************************************************************
* Copyright (c) 2007, 2014 compeople AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* compeople AG - initial API and implementation
*******************************************************************************/
package org.eclipse.riena.navigation.ui.swt.lnf.renderer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.riena.core.marker.IMarker;
import org.eclipse.riena.ui.core.marker.IIconizableMarker;
import org.eclipse.riena.ui.core.marker.IIconizableMarker.MarkerPosition;
import org.eclipse.riena.ui.core.marker.UIProcessFinishedMarker;
import org.eclipse.riena.ui.swt.lnf.AbstractLnfRenderer;
import org.eclipse.riena.ui.swt.lnf.FlasherSupportForRenderer;
import org.eclipse.riena.ui.swt.lnf.LnfKeyConstants;
import org.eclipse.riena.ui.swt.lnf.LnfManager;
import org.eclipse.riena.ui.swt.utils.SwtUtilities;
/**
* Renderer of the markers (e.g. error or mandatory marker) of a item in the navigation tree.
*/
public class SubModuleTreeItemMarkerRenderer extends AbstractLnfRenderer {
private static final MarkerComperator MARKER_COMPERATOR = new MarkerComperator();
private TreeItem item;
private FlasherSupportForRenderer flasherSupport;
private final static int IMAGE_MARGIN = 2;
/**
* Creates a new instance of the renderer for the markers of sub-modules in a tree.
*/
public SubModuleTreeItemMarkerRenderer() {
super();
flasherSupport = new FlasherSupportForRenderer(this, new MarkerUpdater());
}
@Override
public void paint(final GC gc, final Object value) {
super.paint(gc, value);
Assert.isNotNull(value);
Assert.isTrue(value instanceof TreeItem);
item = (TreeItem) value;
flasherSupport.startFlasher();
final Collection<IIconizableMarker> markers = getMarkersOfType(IIconizableMarker.class);
if (!markers.isEmpty()) {
paintMarkers(gc, markers, item);
}
}
/**
* Paints all the given markers (icons).
*
* @param gc
* graphics context
* @param item
* tree item
*/
protected void paintMarkers(final GC gc, final Collection<IIconizableMarker> markers, final TreeItem item) {
final List<IIconizableMarker> sortedMarkers = new ArrayList<IIconizableMarker>(markers);
Collections.sort(sortedMarkers, MARKER_COMPERATOR);
if (isPaintMarkersHierarchically() && sortedMarkers.size() > 0) {
final MarkerPosition position = (MarkerPosition) LnfManager.getLnf().getSetting(LnfKeyConstants.SUB_MODULE_TREE_MARKER_HIERARCHIC_ORDER_POSITION);
paintMarkerImage(gc, sortedMarkers.get(sortedMarkers.size() - 1), position, item);
} else {
for (final IIconizableMarker iconizableMarker : sortedMarkers) {
paintMarkerImage(gc, iconizableMarker, iconizableMarker.getPositionOfMarker(), item);
}
}
}
private boolean isPaintMarkersHierarchically() {
return LnfManager.getLnf().getSetting(LnfKeyConstants.SUB_MODULE_TREE_MARKER_HIERARCHIC_ORDER_POSITION) instanceof MarkerPosition;
}
private void paintMarkerImage(final GC gc, final IIconizableMarker iconizableMarker, final MarkerPosition markerPosition, final TreeItem item) {
if (!iconizableMarker.isVisible()) {
return;
}
if (iconizableMarker instanceof UIProcessFinishedMarker) {
if (!flasherSupport.isProcessMarkerVisible()) {
return;
}
}
if (item != null) {
final Image itemImage = item.getImage();
final String key = iconizableMarker.getIconConfigurationKey();
final Image markerImage = LnfManager.getLnf().getImage(key);
if (markerImage != null) {
final Point pos = calcMarkerCoordinates(itemImage, markerImage, markerPosition);
gc.drawImage(markerImage, pos.x, pos.y);
}
}
}
/**
* Calculates the x- and y-coordinates of the marker image.
*
* @param itemImage
* image of the item
* @param markerImage
* image of the marker
* @param position
* position of the marker
* @return x- and y-coordinates
*/
private Point calcMarkerCoordinates(final Image itemImage, final Image markerImage, final IIconizableMarker.MarkerPosition position) {
Rectangle itemImageBounds = new Rectangle(0, 0, 0, 0);
if (itemImage != null) {
final Rectangle imageBounds = itemImage.getBounds();
itemImageBounds = new Rectangle(imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height);
}
Rectangle itemMarkerBounds = new Rectangle(0, 0, 0, 0);
if (markerImage != null) {
final Rectangle imageBounds = markerImage.getBounds();
itemMarkerBounds = new Rectangle(imageBounds.x, imageBounds.y, imageBounds.width, imageBounds.height);
}
int x = SwtUtilities.convertXToDpi(IMAGE_MARGIN);
x += getBounds().x;
x += itemImageBounds.x;
int y = getBounds().y;
y += itemImageBounds.y;
switch (position) {
case TOP_RIGHT:
x += itemImageBounds.width - itemMarkerBounds.width;
break;
case BOTTOM_LEFT:
y += itemImageBounds.height - itemMarkerBounds.height;
break;
case BOTTOM_RIGHT:
x += itemImageBounds.width - itemMarkerBounds.width;
y += itemImageBounds.height - itemMarkerBounds.height;
break;
default:
break;
}
return new Point(x, y);
}
public void dispose() {
item = null;
flasherSupport = null;
}
/**
* This class updates (redraws) the tree, so that the marker are also updated (redrawn).
*/
private class MarkerUpdater implements Runnable {
public void run() {
if (!SwtUtilities.isDisposed(item)) {
item.getParent().redraw();
}
}
}
private static class MarkerComperator implements Comparator<IMarker> {
public int compare(final IMarker m1, final IMarker m2) {
return m1.getPriority().compareTo(m2.getPriority());
}
}
}