*******************************************************************************/
package org.simantics.diagram.profile;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
import org.simantics.databoard.Bindings;
import org.simantics.db.ReadGraph;
import org.simantics.db.procedure.Listener;
import org.simantics.db.request.Read;
import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.g2d.canvas.Hints;
import org.simantics.g2d.canvas.ICanvasContext;
import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.g2d.diagram.handler.DataElementMap;
import org.simantics.g2d.element.IElement;
import org.simantics.scenegraph.INode;
import org.simantics.scenegraph.profile.DataNodeMap;
import org.simantics.scenegraph.profile.common.ObserverGroupListener;
import org.simantics.scenegraph.profile.common.ObserverGroupValueListener;
import org.simantics.scenegraph.profile.impl.DebugPolicy;
-import org.simantics.scl.runtime.tuple.Tuple;
-import org.simantics.scl.runtime.tuple.Tuple2;
+import org.simantics.scl.runtime.tuple.Tuple3;
import org.simantics.utils.datastructures.Pair;
-import org.simantics.utils.threads.AWTThread;
/**
* For most style implementations it should be enough to override the following
*/
public abstract class StyleBase<Result> implements Style {
- protected final Map<Tuple, Result> values = new ConcurrentHashMap<Tuple, Result>();
+ private Object identity;
+ private double priority;
-// private Map<Resource,ObserverGroupListener> listeners = new ConcurrentHashMap<Resource, ObserverGroupListener>();
+ public StyleBase(Object identity) {
+ this.identity = identity;
+ }
+
+ public StyleBase() {
+ this.identity = getClass();
+ }
+
+ @SuppressWarnings("unchecked")
+ protected <T> T getIdentity() {
+ return (T)identity;
+ }
- private Map<Pair<Resource, Group>, ObserverGroupListener> listeners = new HashMap<Pair<Resource, Group>, ObserverGroupListener>();
+ public void setPriority(double priority) {
+ this.priority = priority;
+ }
+
+ public double getPriority() {
+ return priority;
+ }
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((identity == null) ? 0 : identity.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ StyleBase<?> other = (StyleBase<?>) obj;
+ if (identity == null) {
+ if (other.identity != null)
+ return false;
+ } else if (!identity.equals(other.identity))
+ return false;
+ return true;
+ }
- private final List<Resource> removals = new ArrayList<Resource>();
+ protected Resource getResource() {
+ return getIdentity();
+ }
/**
* For caching this simple base request that is done in every
*/
public void styleResultChanged(Observer observer, Resource runtimeDiagram, Resource object, Result result) {
if (result == null)
- values.remove(new Tuple2(runtimeDiagram, object));
+ StyleBaseData.getInstance().removeValue(new Tuple3(this, runtimeDiagram, object));
else
- values.put(new Tuple2(runtimeDiagram, object), result);
- observer.update();
+ StyleBaseData.getInstance().putValue(new Tuple3(this, runtimeDiagram, object), result);
+ observer.update(this, object);
}
/**
final INode node = map.getNode(item);
if (node == null) {
- evaluationContext.update();
+ evaluationContext.update(this, item);
// TODO: continue or return?
return;
}
System.out.println(StyleBase.this + ": applying style for item " + item + " and element " + node + " with result " + value);
applyStyleForNode(evaluationContext, node, value);
-
}
/**
if (DebugPolicy.DEBUG_PROFILE_STYLE_GROUP_TRACKING)
System.out.println(style + ": removed from group " + group + ": " + item);
- synchronized (style.removals) {
- style.removals.add(item);
- }
+ StyleBaseData.getInstance().removeItem(style, item);
// TODO: do something here to dispose of ObserverGroupValueListeners?
super.remove(item);
* @see org.simantics.diagram.profile.Style#activate(org.simantics.db.RequestProcessor, org.simantics.db.Resource, org.simantics.db.layer0.variable.Variable, org.simantics.diagram.profile.Group, org.simantics.diagram.profile.Observer)
*/
@Override
- public final void activate(RequestProcessor backend, final Resource runtimeDiagram, final Resource entry, final Group group, final EvaluationContext observer) {
+ public final void activate(RequestProcessor backend, final Resource runtimeDiagram, final Resource entry, final Group group, final EvaluationContext observer) throws DatabaseException {
ObserverGroupListener listener = getListener(runtimeDiagram, group);
listener = new GroupListener<Result>(backend.getSession(), runtimeDiagram, entry, this, group, observer);
- listeners.put(Pair.make(runtimeDiagram, group), listener);
+ StyleBaseData.getInstance().putListener(new Tuple3(this, runtimeDiagram, group), listener);
group.trackItems(backend, runtimeDiagram, listener);
listener.removeEntry(entry);
if (!listener.hasEntries()) {
listener.dispose();
- listeners.remove(Pair.make(runtimeDiagram, group));
+ StyleBaseData.getInstance().removeListener(new Tuple3(this, runtimeDiagram, group));
}
// This was too eager when multiple groups were tracked!
cleanupItems(observer, diagram, listener.getItems().toArray());
diagram = null;
}
- observer.update();
+
+ //observer.update(); TODO: Check if this is required!
}
}
*/
@Override
public final void apply(Resource entry, Group group, final EvaluationContext evaluationContext) {
-
ICanvasContext context = evaluationContext.getConstant(ProfileKeys.CANVAS);
assert context.getThreadAccess().currentThreadAccess();
if (DebugPolicy.DEBUG_PROFILE_STYLE_APPLICATION)
System.out.println(StyleBase.this + ": applying style for items: " + listener.getItems());
- if (!removals.isEmpty()) {
- Resource[] removed;
- synchronized (removals) {
- removed = removals.toArray(Resource.NONE);
- removals.clear();
- }
- for (Resource item : removed) {
- cleanupStyleForItem(evaluationContext, map, item);
- }
- }
+ StyleBaseData data = StyleBaseData.getInstance();
+
+ data.applyRemovals(evaluationContext, this);
+
+ IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM);
+ assert diagram != null;
+ DataElementMap emap = diagram.getDiagramClass().getSingleItem(DataElementMap.class);
+
for (Object item : listener.getItems()) {
- Result value = values.get(new Tuple2(evaluationContext.getResource(), item));
+ Result value = data.getValue(new Tuple3(this, evaluationContext.getResource(), item));
applyStyleForItem(evaluationContext, map, item, value);
+
+ IElement element = emap.getElement(diagram, item);
+ if (element != null)
+ element.setHint(Hints.KEY_DIRTY, Hints.VALUE_SG_DIRTY);
}
}
+ @Override
+ public final void apply2(Object item, final EvaluationContext evaluationContext) {
+ final DataNodeMap map = evaluationContext.getConstant(ProfileKeys.NODE_MAP);
+
+ StyleBaseData data = StyleBaseData.getInstance();
+
+ data.applyRemovals(evaluationContext, this);
+
+ Result value = data.getValue(new Tuple3(this, evaluationContext.getResource(), item));
+ applyStyleForItem(evaluationContext, map, item, value);
+
+ IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM);
+ assert diagram != null;
+ DataElementMap emap = diagram.getDiagramClass().getSingleItem(DataElementMap.class);
+ IElement element = emap.getElement(diagram, item);
+ if (element != null)
+ element.setHint(Hints.KEY_DIRTY, Hints.VALUE_SG_DIRTY);
+ }
+
/**
* This is ran when this profile entry gets deactivated after being first
* active. It allows cleaning up scene graph left-overs for the listened set
if (DebugPolicy.DEBUG_PROFILE_STYLE_ACTIVATION)
System.out.println(this + ".cleanupItems(" + evaluationContext + ", " + diagram + ", " + Arrays.toString(items));
+ IDiagram diagram = evaluationContext.getConstant(ProfileKeys.DIAGRAM);
+ assert diagram != null;
+ DataElementMap emap = diagram.getDiagramClass().getSingleItem(DataElementMap.class);
+
for (Object item : items) {
cleanupStyleForItem(evaluationContext, map, item);
+
+ IElement element = emap.getElement(diagram, item);
+ if (element != null)
+ element.setHint(Hints.KEY_DIRTY, Hints.VALUE_SG_DIRTY);
}
}
});
}
private ObserverGroupListener getListener(Resource runtime, Group group) {
- return listeners.get(Pair.make(runtime, group));
+ return StyleBaseData.getInstance().getListener(new Tuple3(this, runtime, group));
}
}