X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fcanvas%2Fimpl%2FAbstractCanvasParticipant.java;h=cc298f3aa20e1f7ad05d6d47ab213a63a0e9183d;hb=48df6974c83f3f42497712b35e8531377a4178c8;hp=4de85481281222fc2646c8960bd452f51dffb6f6;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/AbstractCanvasParticipant.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/AbstractCanvasParticipant.java index 4de854812..cc298f3aa 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/AbstractCanvasParticipant.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/canvas/impl/AbstractCanvasParticipant.java @@ -1,554 +1,563 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * 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: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.g2d.canvas.impl; - -import java.lang.reflect.Field; - -import org.simantics.g2d.canvas.ICanvasContext; -import org.simantics.g2d.canvas.ICanvasParticipant; -import org.simantics.g2d.canvas.IContentContext; -import org.simantics.g2d.canvas.impl.DependencyReflection.ReferenceDefinition; -import org.simantics.g2d.canvas.impl.DependencyReflection.ReferenceType; -import org.simantics.g2d.canvas.impl.HintReflection.HintListenerDefinition; -import org.simantics.g2d.canvas.impl.SGNodeReflection.CanvasSGNodeDefinition; -import org.simantics.scenegraph.g2d.events.EventHandlerReflection; -import org.simantics.scenegraph.g2d.events.IEventHandler; -import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandlerDefinition; -import org.simantics.utils.datastructures.context.IContext; -import org.simantics.utils.datastructures.context.IContextListener; -import org.simantics.utils.datastructures.hints.HintContext; -import org.simantics.utils.datastructures.hints.IHintContext; -import org.simantics.utils.datastructures.hints.IHintStack; -import org.simantics.utils.datastructures.hints.IHintContext.Key; -import org.simantics.utils.datastructures.prioritystack.IPriorityStack; -import org.simantics.utils.threads.IThreadWorkQueue; -import org.simantics.utils.threads.ThreadUtils; - - -/** - * AbstractCanvasParticipant is base implementation for canvas participants. - * There is an assertion that states AbstractCanvasParticipant can be added - * only once to a canvas. - * - *
- * There is convenience mechanism for adding painter and event handler - * listeners. Subclasses create listeners with usage of Painter and - * EventHandler annotations. Listeners are automatically added and - * removed to/from canvas context. - *
- * - *- * Example: - *
- *- * - *- * @EventHandler(priority=200) - * public boolean handleEvent(Event e) { - * return false; - * } - * - * @EventHandler(priority=400) - * public boolean handleMousePressEvent(MouseButtonPressedEvent e) { - * return false; - * } - * - * IG2DNode node; - * - * @SGInit - * public void initSG(G2DParentNode parent) { - * // Insert a node into the scene graph rendered by the canvas - * // this participant is attached to and initialize it to render - * // something. Later on, to modify what the node will render, just - * // update the node's attributes. - * node = parent.addNode("myNode", MyNode.class); - * node.setZIndex(Integer.MIN_VALUE); - * } - * - * @SGCleanup - * public void cleanup() { - * // Remove our node from the scene graph where it belonged. - * // The node must not be used after this anymore. - * if (node != null) { - * node.remove(); - * node = null; - * } - * } - *
- * Local fields are automatically assigned with ICanvasParticipant instances if they
- * are annotated with either @Dependency
or @Reference
annotation tag.
- * @Depedency
is a requirement, @Reference
is optional.
- *
- * assertDependencies() verifies that dependencies are satisfied.
- * Local depsSatisfied field is true when dependencies are satisfied.
- *
- *
- * Example: - *
- *- * - *- * class MyParticipant implements ICanvasParticipant { - * @Reference MouseMonitor mouseMonitor; - * @Dependency TimeParticipant timeParticipant; - * - * @Painter(priority=100) - * public void paint(GraphicsContext gc) { - * assertDependencies(); // timeParticipant != null - * - * timeParticipant.doSomething(); - * - * if (mouseMonitor!=null) doSomethingElse(); - * } - * }
- * Hint listener annotation. - *
- * - *- * Example: - *
- *- * - * @author Toni Kalajainen - */ -public abstract class AbstractCanvasParticipant implements ICanvasParticipant { - - /** The interactor/canvas context */ - private ICanvasContext context; - - /** The thread used in the context */ - private IThreadWorkQueue thread; - - /** the local hint context */ - protected IHintContext localHintCtx = null; - protected int localPriority = 0; - - /** wrapped local hint context. reads from hint stack */ - protected IHintContext hintCtx = null; - - /** Cached hint stack value */ - protected IHintStack hintStack; - - /** Painters found with reflection */ - protected CanvasSGNodeDefinition[] sghandlers; - - /** Painters found with reflection */ - protected EventHandlerDefinition[] eventHandlers; - - protected HintListenerDefinition[] hintListeners; - - /** Reference definitions */ - protected ReferenceDefinition[] refDefs; - protected boolean depsSatisfied = false; - private final IContextListener- * @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM") - * public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { - * ... - * } - * @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM") - * public void hintRemoved(IHintObservable sender, Key key, Object oldValue) { - * ... - * } - *
- * Local context must be created with createLocalHintContext() method. - * constructor has defualt value Integer.MIN_VALUE. - *
- * Reading from this context returns only the local hint and not - * from the shared hint stack of the canvas context. - *
- * To read from the shared hint stack, use getHint() or getHintStack() instead.
- *
- * @return the local hint context
- */
- public synchronized IHintContext getLocalHintContext()
- {
- return localHintCtx;
- }
-
- /**
- * Get hint context. Read operations are to hint stack, writes to local stack.
- *
- * @return
- */
- public synchronized IHintContext getWriteableHintStack()
- {
- if (hintCtx==null)
- hintCtx = getHintStack().createStackRead(getLocalHintContext());
- return hintCtx;
- }
-
- /**
- * Get hint context; local if exists, otherwise stack's default context.
- *
- * @return
- */
- public IHintContext getWriteableHintContext()
- {
- ICanvasContext ctx = context;
- assert(ctx!=null);
- if (localHintCtx!=null) return localHintCtx;
- return ctx.getDefaultHintContext();
- }
-
- /**
- * Read hint from the hint stack.
- *
- * @param key
- * @return
- */
- public
- * Local hint context overrides default context in the following convenience methods:
- * getHint(), setHint(), setHintAsync()
- *
- * Q: What is the purpose of local hint stack?
- * A: To override hints for the lifetime of the participant.
- * For example, Special editing mode overrides viewport and toolmode.
- *
- * @param priority
- */
- public void createLocalHintContext(int priority)
- {
- localHintCtx = new HintContext();
- }
-
- /**
- * Set hint to the local hint stack if one exists otherwise to the default context.
- * Switches thread to the appropriate context thread.
- *
- * @param key the key
- * @param value the value
- */
- public void setHintAsync(final Key key, final Object value)
- {
- assert(context!=null);
- asyncExec(new Runnable() {
- @Override
- public void run() {
- if (isRemoved())
- return;
- if (localHintCtx!=null)
- localHintCtx.setHint(key, value);
- else
- context.getDefaultHintContext().setHint(key, value);
- }});
- }
-
- /**
- * Get the interactor context.
- * @return the context
- */
- public ICanvasContext getContext()
- {
- return context;
- }
-
- public IThreadWorkQueue getThread()
- {
- return thread;
- }
-
-
- /**
- * Asserts that dependencies of participants are satisfied.
- */
- public void assertDependencies()
- {
- assert(depsSatisfied);
- }
-
- private boolean checkDependencies() {
- synchronized ( ctxListener ) {
- try {
- for (ReferenceDefinition rd : refDefs) {
- if (!rd.dependency)
- continue;
- Field f = rd.field;
- Object o = f.get(this);
- if (o == null)
- return false;
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return true;
- }
- }
-
- public void setDirty()
- {
- ICanvasContext ctx = getContext();
- if ( ctx==null ) return;
- IContentContext cctx = ctx.getContentContext();
- if ( cctx==null ) return;
- cctx.setDirty();
- }
-
-}
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * 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:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.g2d.canvas.impl;
+
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.canvas.ICanvasParticipant;
+import org.simantics.g2d.canvas.IContentContext;
+import org.simantics.g2d.canvas.impl.DependencyReflection.ReferenceDefinition;
+import org.simantics.g2d.canvas.impl.DependencyReflection.ReferenceType;
+import org.simantics.g2d.canvas.impl.HintReflection.HintListenerDefinition;
+import org.simantics.g2d.canvas.impl.SGNodeReflection.CanvasSGNodeDefinition;
+import org.simantics.scenegraph.g2d.events.EventHandlerReflection;
+import org.simantics.scenegraph.g2d.events.IEventHandler;
+import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandlerDefinition;
+import org.simantics.utils.datastructures.context.IContext;
+import org.simantics.utils.datastructures.context.IContextListener;
+import org.simantics.utils.datastructures.hints.HintContext;
+import org.simantics.utils.datastructures.hints.IHintContext;
+import org.simantics.utils.datastructures.hints.IHintStack;
+import org.simantics.utils.datastructures.hints.IHintContext.Key;
+import org.simantics.utils.datastructures.prioritystack.IPriorityStack;
+import org.simantics.utils.threads.IThreadWorkQueue;
+import org.simantics.utils.threads.ThreadUtils;
+
+
+/**
+ * AbstractCanvasParticipant is base implementation for canvas participants.
+ * There is an assertion that states AbstractCanvasParticipant can be added
+ * only once to a canvas.
+ *
+ *
+ * There is convenience mechanism for adding painter and event handler
+ * listeners. Subclasses create listeners with usage of Painter and
+ * EventHandler annotations. Listeners are automatically added and
+ * removed to/from canvas context.
+ *
+ * Example:
+ *
+ * Local fields are automatically assigned with ICanvasParticipant instances if they
+ * are annotated with either
+ * Example:
+ *
+ * Hint listener annotation.
+ *
+ * Example:
+ *
+ * Local context must be created with createLocalHintContext() method.
+ * constructor has defualt value Integer.MIN_VALUE.
+ *
+ * Reading from this context returns only the local hint and not
+ * from the shared hint stack of the canvas context.
+ *
+ * To read from the shared hint stack, use getHint() or getHintStack() instead.
+ *
+ * @return the local hint context
+ */
+ public synchronized IHintContext getLocalHintContext()
+ {
+ return localHintCtx;
+ }
+
+ /**
+ * Get hint context. Read operations are to hint stack, writes to local stack.
+ *
+ * @return
+ */
+ public synchronized IHintContext getWriteableHintStack()
+ {
+ if (hintCtx==null)
+ hintCtx = getHintStack().createStackRead(getLocalHintContext());
+ return hintCtx;
+ }
+
+ /**
+ * Get hint context; local if exists, otherwise stack's default context.
+ *
+ * @return
+ */
+ public IHintContext getWriteableHintContext()
+ {
+ ICanvasContext ctx = context;
+ assert(ctx!=null);
+ if (localHintCtx!=null) return localHintCtx;
+ return ctx.getDefaultHintContext();
+ }
+
+ /**
+ * Read hint from the hint stack.
+ *
+ * @param key
+ * @return
+ */
+ public
+ * Local hint context overrides default context in the following convenience methods:
+ * getHint(), setHint(), setHintAsync()
+ *
+ * Q: What is the purpose of local hint stack?
+ * A: To override hints for the lifetime of the participant.
+ * For example, Special editing mode overrides viewport and toolmode.
+ *
+ * @param priority
+ */
+ public void createLocalHintContext(int priority)
+ {
+ localHintCtx = new HintContext();
+ }
+
+ /**
+ * Set hint to the local hint stack if one exists otherwise to the default context.
+ * Switches thread to the appropriate context thread.
+ *
+ * @param key the key
+ * @param value the value
+ */
+ public void setHintAsync(final Key key, final Object value)
+ {
+ assert(context!=null);
+ asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (isRemoved())
+ return;
+ if (localHintCtx!=null)
+ localHintCtx.setHint(key, value);
+ else
+ context.getDefaultHintContext().setHint(key, value);
+ }});
+ }
+
+ /**
+ * Get the interactor context.
+ * @return the context
+ */
+ public ICanvasContext getContext()
+ {
+ return context;
+ }
+
+ public IThreadWorkQueue getThread()
+ {
+ return thread;
+ }
+
+
+ /**
+ * Asserts that dependencies of participants are satisfied.
+ */
+ public void assertDependencies()
+ {
+ assert(depsSatisfied);
+ }
+
+ private boolean checkDependencies() {
+ synchronized ( ctxListener ) {
+ try {
+ for (ReferenceDefinition rd : refDefs) {
+ if (!rd.dependency)
+ continue;
+ Field f = rd.field;
+ Object o = f.get(this);
+ if (o == null) {
+ missingDependencies.add(f);
+ return false;
+ } else {
+ missingDependencies.remove(f);
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return true;
+ }
+ }
+
+ public void setDirty()
+ {
+ ICanvasContext ctx = getContext();
+ if ( ctx==null ) return;
+ IContentContext cctx = ctx.getContentContext();
+ if ( cctx==null ) return;
+ cctx.setDirty();
+ }
+
+}
+ *
+ *
+ * @EventHandler(priority=200)
+ * public boolean handleEvent(Event e) {
+ * return false;
+ * }
+ *
+ * @EventHandler(priority=400)
+ * public boolean handleMousePressEvent(MouseButtonPressedEvent e) {
+ * return false;
+ * }
+ *
+ * IG2DNode node;
+ *
+ * @SGInit
+ * public void initSG(G2DParentNode parent) {
+ * // Insert a node into the scene graph rendered by the canvas
+ * // this participant is attached to and initialize it to render
+ * // something. Later on, to modify what the node will render, just
+ * // update the node's attributes.
+ * node = parent.addNode("myNode", MyNode.class);
+ * node.setZIndex(Integer.MIN_VALUE);
+ * }
+ *
+ * @SGCleanup
+ * public void cleanup() {
+ * // Remove our node from the scene graph where it belonged.
+ * // The node must not be used after this anymore.
+ * if (node != null) {
+ * node.remove();
+ * node = null;
+ * }
+ * }
+ *
@Dependency
or @Reference
annotation tag.
+ * @Depedency
is a requirement, @Reference
is optional.
+ *
+ * assertDependencies() verifies that dependencies are satisfied.
+ * Local depsSatisfied field is true when dependencies are satisfied.
+ *
+ *
+ *
+ *
+ * class MyParticipant implements ICanvasParticipant {
+ * @Reference MouseMonitor mouseMonitor;
+ * @Dependency TimeParticipant timeParticipant;
+ *
+ * @Painter(priority=100)
+ * public void paint(GraphicsContext gc) {
+ * assertDependencies(); // timeParticipant != null
+ *
+ * timeParticipant.doSomething();
+ *
+ * if (mouseMonitor!=null) doSomethingElse();
+ * }
+ * }
+ *
+ * @author Toni Kalajainen
+ */
+public abstract class AbstractCanvasParticipant implements ICanvasParticipant {
+
+ /** The interactor/canvas context */
+ private ICanvasContext context;
+
+ /** The thread used in the context */
+ private IThreadWorkQueue thread;
+
+ /** the local hint context */
+ protected IHintContext localHintCtx = null;
+ protected int localPriority = 0;
+
+ /** wrapped local hint context. reads from hint stack */
+ protected IHintContext hintCtx = null;
+
+ /** Cached hint stack value */
+ protected IHintStack hintStack;
+
+ /** Painters found with reflection */
+ protected CanvasSGNodeDefinition[] sghandlers;
+
+ /** Painters found with reflection */
+ protected EventHandlerDefinition[] eventHandlers;
+
+ protected HintListenerDefinition[] hintListeners;
+
+ /** Reference definitions */
+ protected ReferenceDefinition[] refDefs;
+ protected boolean depsSatisfied = false;
+ private final IContextListener
+ * @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")
+ * public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
+ * ...
+ * }
+ * @HintListener(Class=Hints.class, Field="KEY_CANVAS_TRANSFORM")
+ * public void hintRemoved(IHintObservable sender, Key key, Object oldValue) {
+ * ...
+ * }
+ *