package org.marketcetera.photon.strategy.engine.ui; import java.util.List; import org.eclipse.core.databinding.observable.set.IObservableSet; import org.eclipse.core.databinding.property.value.IValueProperty; import org.eclipse.emf.databinding.EMFProperties; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.BaseLabelProvider; import org.eclipse.jface.viewers.DecoratingLabelProvider; import org.eclipse.jface.viewers.DecorationContext; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ILabelDecorator; import org.eclipse.jface.viewers.ILightweightLabelDecorator; import org.eclipse.jface.viewers.LabelProviderChangedEvent; import org.marketcetera.photon.commons.ui.SWTUtils; import org.marketcetera.photon.commons.ui.databinding.PropertyWatcher; import org.marketcetera.photon.commons.ui.databinding.PropertyWatcher.IPropertiesChangedListener; import org.marketcetera.photon.strategy.engine.model.core.ConnectionState; import org.marketcetera.photon.strategy.engine.model.core.DeployedStrategy; import org.marketcetera.photon.strategy.engine.model.core.StrategyEngine; import org.marketcetera.photon.strategy.engine.model.core.StrategyEngineCorePackage; import org.marketcetera.photon.strategy.engine.model.core.StrategyState; import org.marketcetera.photon.strategy.engine.model.core.util.StrategyEngineCoreSwitch; import org.marketcetera.photon.strategy.engine.ui.StrategyEngineColors.StrategyEngineColor; import org.marketcetera.util.misc.ClassVersion; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; /* $License$ */ /** * Decorates Strategy Engine objects based on their status. This is a * {@link ILightweightLabelDecorator} which is primarily intended to be used * declaratively with the Eclipse Workbench's DecorationManager for efficient * background decoration. However, it doesn't have any direct dependencies on * the workbench and could be used outside the workbench by creating a * {@link DecoratingLabelProvider} with an {@link ILabelDecorator} that * delegates to it. * <p> * {@link StrategyEngineColors} must be initialized for this class to function * properly. * * @author <a href="mailto:will@marketcetera.com">Will Horn</a> * @version $Id: StrategyEngineStatusDecorator.java 16154 2012-07-14 16:34:05Z colin $ * @since 2.0.0 */ @ClassVersion("$Id: StrategyEngineStatusDecorator.java 16154 2012-07-14 16:34:05Z colin $") public class StrategyEngineStatusDecorator extends BaseLabelProvider implements ILightweightLabelDecorator { /** * Creates a StrategyEngineStatusDecorator that tracks the given set of * elements, updating their labels when related properties change. Tracking * will not stop until the returned object is {@link #dispose() disposed}. * * @param elements * the observable set of elements to track, must be on the realm * of the current display * @throws IllegalStateException * if called from a non UI thread, i.e. a thread where * Display.getCurrent() is null * @throws IllegalArgumentException * if the provided elements set is not on the realm of the * current display */ public static StrategyEngineStatusDecorator createAndTrack( IObservableSet elements) { SWTUtils.checkThread(); StrategyEngineStatusDecorator decorator = new StrategyEngineStatusDecorator(); decorator.track(elements); return decorator; } /** * Properties this decorator cares about. */ public final static List<IValueProperty> PROPERTIES = ImmutableList .<IValueProperty> of( EMFProperties .value(StrategyEngineCorePackage.Literals.STRATEGY_ENGINE__CONNECTION_STATE), EMFProperties .value(StrategyEngineCorePackage.Literals.DEPLOYED_STRATEGY__STATE)); private final PropertyWatcher mPropertyWatcher = new PropertyWatcher( PROPERTIES, new IPropertiesChangedListener() { @Override public void propertiesChanged(ImmutableSet<?> affectedElements) { LabelProviderChangedEvent newEvent = new LabelProviderChangedEvent( StrategyEngineStatusDecorator.this, affectedElements.toArray()); fireLabelProviderChanged(newEvent); } }); /** * Causes this object to track the given set of elements, updating their * labels when related properties change. Tracking will not stop until this * object is {@link #dispose() disposed}. * * @param elements * the observable set of elements to track, must be on the realm * of the current display * @throws IllegalStateException * if called from a non UI thread, i.e. a thread where * Display.getCurrent() is null * @throws IllegalArgumentException * if the provided elements set is not on the realm of the * current display */ public final void track(IObservableSet elements) { SWTUtils.checkThread(); mPropertyWatcher.watch(elements); } @Override public final void decorate(Object element, final IDecoration decoration) { /* * Warning: this method may not be called from the UI thread if using * the workbench decoration manager. In that case the decoration manager * is responsible for synchronization to ensure the thread confined * model is visible. */ if (element instanceof EObject) { new StrategyEngineCoreSwitch<Boolean>() { @Override public Boolean caseStrategyEngine(StrategyEngine object) { if (isConnected(object)) { replaceImage(decoration, StrategyEngineImage.ENGINE_CONNECTED_OBJ .getImageDescriptor()); // use default color for foreground } else { replaceImage(decoration, StrategyEngineImage.ENGINE_DISCONNECTED_OBJ .getImageDescriptor()); decoration .setForegroundColor(StrategyEngineColor.ENGINE_DISCONNECTED .getColor()); } return Boolean.TRUE; } @Override public Boolean caseDeployedStrategy(DeployedStrategy object) { if (isRunning(object)) { replaceImage(decoration, StrategyEngineImage.STRATEGY_RUNNING_OBJ .getImageDescriptor()); // use default color for foreground } else { replaceImage(decoration, StrategyEngineImage.STRATEGY_STOPPED_OBJ .getImageDescriptor()); decoration .setForegroundColor(StrategyEngineColor.STRATEGY_STOPPED .getColor()); } return Boolean.TRUE; }; }.doSwitch((EObject) element); } } private boolean isRunning(DeployedStrategy strategy) { return strategy.getState() == StrategyState.RUNNING; } private boolean isConnected(StrategyEngine engine) { return engine.getConnectionState() == ConnectionState.CONNECTED; } private void replaceImage(final IDecoration decoration, ImageDescriptor imageDescriptor) { /* * Without setting IDecoration.ENABLE_REPLACE, IDecoration.REPLACE will * not be respected */ ((DecorationContext) decoration.getDecorationContext()).putProperty( IDecoration.ENABLE_REPLACE, Boolean.TRUE); decoration.addOverlay(imageDescriptor, IDecoration.REPLACE); } @Override public final void dispose() { mPropertyWatcher.dispose(); super.dispose(); } }