Commit 5d7a291d authored by Nico Mack's avatar Nico Mack

Changes to both AngleUtils and PolarCoordinateHelper classes

Extension of BootstrapCallback interface
parent 471d6930
......@@ -118,9 +118,9 @@
<version>4.1</version>
</dependency>
<dependency>
<groupId>com.metsci.ext.com.kitfox.svg</groupId>
<groupId>com.kitfox.svg</groupId>
<artifactId>svg-salamander</artifactId>
<version>0.1.19</version>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
......@@ -140,7 +140,7 @@
<id>LIST</id>
<name>Artifacts</name>
<url>https://artefacts.list.lu/libs-release-local</url>
</repository>
</repository>
</repositories>
......
......@@ -88,8 +88,8 @@ public abstract class TangibleObjectManager {
protected Boolean cursorsEnabled = true;
/**
* Specifies whether the object manager shall manage blobs or not. Can be changed with
* blobsEnabled property in property file
* Specifies whether the object manager shall manage blobs or not. Can be changed with blobsEnabled
* property in property file
*/
protected Boolean blobsEnabled = true;
......@@ -160,6 +160,8 @@ public abstract class TangibleObjectManager {
for (BaseWidget widget : objectMap.values()) {
if (widget.isTouchable()) {
takenCareOf |= widget.touched(event);
if (takenCareOf)
break;
}
}
}
......@@ -179,6 +181,8 @@ public abstract class TangibleObjectManager {
for (BaseWidget widget : objectMap.values()) {
if (widget.isTouchable()) {
takenCareOf |= widget.dragged(event);
if (takenCareOf)
break;
}
}
}
......@@ -270,8 +274,8 @@ public abstract class TangibleObjectManager {
// ---------------------------------------------------------------------------
/**
* Method ensuring that all mapped widgets are present on the table by querying the global state
* of the application.
* Method ensuring that all mapped widgets are present on the table by querying the global state of
* the application.
*/
// ---------------------------------------------------------------------------
......@@ -305,28 +309,26 @@ public abstract class TangibleObjectManager {
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* Method used to define all widgets. In this method, all handles need to be assigned to
* instances of {@link BaseWidget} or a child thereof. Implementing classes should define what
* widgets to use by implementing this method. <b>By default, no widgets are instantiated</b>.
* <br>
* Method used to define all widgets. In this method, all handles need to be assigned to instances
* of {@link BaseWidget} or a child thereof. Implementing classes should define what widgets to use
* by implementing this method. <b>By default, no widgets are instantiated</b>. <br>
* <br>
*
* When adding Widgets to map to cursors, refer to {@link IdMapper#remapCursorId(int)}. Cursor
* IDs are remapped as not to clash with any symbol ID assigned by reacTIVision. A good practice
* is to reason with regular cursor IDs and add them to the map by calling for example:
* <code>objectMap.put(remapCursorID(0), W extends BaseWidget);</code> to the first cursor that
* is placed to the widget in the put statement.<br>
* When adding Widgets to map to cursors, refer to {@link IdMapper#remapCursorId(int)}. Cursor IDs
* are remapped as not to clash with any symbol ID assigned by reacTIVision. A good practice is to
* reason with regular cursor IDs and add them to the map by calling for example:
* <code>objectMap.put(remapCursorID(0), W extends BaseWidget);</code> to the first cursor that is
* placed to the widget in the put statement.<br>
* <br>
*
* To dynamically allocate widgets to cursors, the <code>addTuioCursor()</code> method should be
* overridden or reimplimented to dynamically instantiate the desired widget and add it to the
* dictionary of objects. This would require manual removal of the dynamically created widget in
* the <code>removeTuioCursor()</code> method.
* dictionary of objects. This would require manual removal of the dynamically created widget in the
* <code>removeTuioCursor()</code> method.
*
* @throws BuildException
* Exception raised when the building on a widget or corona instance cannot complete
* successfully due to the violation of one or more contracts associated with the
* instance.
* successfully due to the violation of one or more contracts associated with the instance.
*/
// ---------------------------------------------------------------------------
......@@ -354,8 +356,8 @@ public abstract class TangibleObjectManager {
// ---------------------------------------------------------------------------
/**
* Method returning a collection of {@link BaseWidget} instances held by this manager. The
* method will return objects, cursors, and blobs.
* Method returning a collection of {@link BaseWidget} instances held by this manager. The method
* will return objects, cursors, and blobs.
*
* @return The collection of managed {@link BaseWidget} instances.
*/
......@@ -371,8 +373,8 @@ public abstract class TangibleObjectManager {
// ---------------------------------------------------------------------------
/**
* Static method for retrieving a {@link BaseWidget} by its identifier. The method will first
* check the list of objects before it checks the list of cursors.
* Static method for retrieving a {@link BaseWidget} by its identifier. The method will first check
* the list of objects before it checks the list of cursors.
*
* @param identifier
* The identifier the {@link BaseWidget} is keyed with.
......
......@@ -24,6 +24,15 @@ import org.jdom2.Element;
* @version [major].[minor].[micro]
*/
public interface BootstrapCallback {
/**
* @param node
* @param context
* @return
*/
public BootstrapContext initialize(Element node, BootstrapContext context);
/**
* @param node
* @param context
......@@ -51,4 +60,10 @@ public interface BootstrapCallback {
*/
public BootstrapContext reset(BootstrapContext context);
/**
* @param context
* @return
*/
public BootstrapContext finalize(BootstrapContext context);
}
......@@ -58,9 +58,8 @@ public class BootstrappingUtils {
private static ScriptEngine script = new ScriptEngineManager().getEngineByName("js"); //$NON-NLS-1$
// private static final Pattern INDEXED_PATTERN =
// Pattern.compile("\\$\\{([a-z0-9\\-_]+)(\\[(\\$\\{([a-z0-9\\-_]+)\\}|[0-9]+)\\])?\\}",
// Pattern.compile("\\$\\{([a-z0-9\\-_]+)(\\[\\$\\{([a-z0-9\\-_]+)\\}\\])?\\}",
// Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
private static final Pattern BOOTSTRAP_VAR_PATTERN = Pattern.compile("\\$\\{([a-z0-9\\-_]+)\\}", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
private static final Pattern ANGLE_PATTERN = Pattern.compile("([+-]?\\d+.?\\d*)\\s*(deg|rad)??", Pattern.CASE_INSENSITIVE); //$NON-NLS-1$
......
......@@ -32,27 +32,40 @@ import org.jdom2.Element;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
/**
* @author Eric Tobias [eric.tobias@list.lu]
* @since 2.2
* @version 2.3.0
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class CoronaBootstrapper {
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
private CoronaBootstrapper() {}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* Method used to determine the appropriate builder for a given object and then issue a build
* call.
* Method used to determine the appropriate builder for a given object and then issue a build call.
*
* @param bootstrapContext
* @param callback
*
* @param coronaNode
* The node from a larger document that contains, as children, all the necessary
* information to resolve the correct builder and build the final widget.
* The node from a larger document that contains, as children, all the necessary information
* to resolve the correct builder and build the final widget.
* @return The final widget as defined by the children of the element node.
* @throws ClassNotFoundException
* Thrown when the class of the builder for the widget or those of the nested corona
......@@ -90,14 +103,13 @@ public class CoronaBootstrapper {
Constructor<CoronaBuilder<?>> constructor = (Constructor<CoronaBuilder<?>>) builder.getConstructor(new Class[] {Element.class, BootstrapContext.class, BootstrapCallback.class});
instance = constructor.newInstance(new Object[] {coronaNode, bootstrapContext, callback}).build();
}
return instance;
}
// ---------------------------------------------------------------------------
/**
* Method used for bootstrapping all coronas found as child nodes of a root node. The method
* will look for child nodes names <code>corona</code>.
* Method used for bootstrapping all coronas found as child nodes of a root node. The method will
* look for child nodes names <code>corona</code>.
*
* @param coronaRootNode
* The root node that holds all <code>corona</code> child nodes.
......@@ -121,22 +133,21 @@ public class CoronaBootstrapper {
throw new BuildException("One or more operations failed while issuing a reflective call!", roe); //$NON-NLS-1$
}
}
return coronas;
}
// ---------------------------------------------------------------------------
/**
* Method used for bootstrapping all coronas found as child nodes of a root node. The method
* will look for child nodes names <code>corona</code>. The method returns a map, using the
* coronas' <code>handleId</code> property as the key and the corona itself as the value.
* Method used for bootstrapping all coronas found as child nodes of a root node. The method will
* look for child nodes names <code>corona</code>. The method returns a map, using the coronas'
* <code>handleId</code> property as the key and the corona itself as the value.
*
* @param coronaRootNode
* The root node that holds all <code>corona</code> child nodes.
* @param context
* @param callback
* @return A map containing all concrete {@link Corona} instances that could be build from the
* provided root node keyed to the handle ID to which they are associated. *
* provided root node keyed to the handle ID to which they are associated.
* @throws BuildException
* Thrown when a corona was not associated to any handle.
*/
......@@ -153,40 +164,47 @@ public class CoronaBootstrapper {
coronas.put(handleId, newInstance);
}
}
return coronas;
}
// ---------------------------------------------------------------------------
/**
* Method used for bootstrapping all coronas found as child nodes of a root node. The method
* will look for child nodes names <code>corona</code>. The method returns a list of corona
* instances build from the definitions found under the coronaRootNode.
* Method used for bootstrapping all coronas found as child nodes of a root node. The method will
* look for child nodes names <code>corona</code>. The method returns a map, using the coronas'
* <code>handleId</code> property as the key and the corona itself as the value.
*
* @param coronaRootNode
* The root node that holds all <code>corona</code> child nodes.
* @param context
* @param callback
* @return A list containing all concrete {@link Corona} instances that could be build from the
* provided root node.
* @param callbacks
* @return A map containing all concrete {@link Corona} instances that could be build from the
* provided root node keyed to the handle ID to which they are associated. *
* @throws BuildException
* Thrown when a corona couldn't be build.
* Thrown when a corona was not associated to any handle.
*/
// ---------------------------------------------------------------------------
public static List<Corona> getListOfCoronas(Element coronaRootNode, BootstrapContext context, BootstrapCallback callback) throws BuildException {
List<Corona> coronas = new ArrayList<>();
for (Element coronaNode : coronaRootNode.getChildren(Externalization.CORONA_NODE)) {
CoronaFactory<Corona> factory = new CoronaFactory<>(coronaNode, context, callback);
while (factory.hasNext()) {
Corona newInstance = factory.next();
coronas.add(newInstance);
}
}
return coronas;
}
// public static Multimap<Integer, Corona> getCoronas(Element coronaRootNode, BootstrapContext
// context, Map<String, BootstrapCallback> callbacks) throws BuildException {
// Multimap<Integer, Corona> coronas = ArrayListMultimap.create();
//
// for (Element coronaNode : coronaRootNode.getChildren(Externalization.CORONA_NODE)) {
// int handleId = BootstrappingUtils.getContentAsInteger(coronaNode, Externalization.HANDLE_NODE,
// BootstrappingUtils.MANDATORY, 0, context);
// CoronaFactory<Corona> factory = new CoronaFactory<>(coronaNode, context, callbacks);
// while (factory.hasNext()) {
// Corona newInstance = factory.next();
// coronas.put(handleId, newInstance);
// }
// }
// return coronas;
// }
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of Class *
// ***************************************************************************
// ---------------------------------------------------------------------------
}
\ No newline at end of file
......@@ -18,6 +18,7 @@ package lu.list.itis.dkd.tui.bootstrapping;
import lu.list.itis.dkd.tui.exception.BuildException;
import lu.list.itis.dkd.tui.utility.Externalization;
import lu.list.itis.dkd.tui.utility.StringUtils;
import lu.list.itis.dkd.tui.widget.corona.Corona;
import org.jdom2.Element;
......@@ -26,13 +27,18 @@ import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* @author mack
* @since [major].[minor]
* @version [major].[minor].[micro]
* @author Nico Mack [nico.mack@list.lu]
* @since 1.5
* @version 1.5.0
* @param <C>
*/
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
public class CoronaFactory<C extends Corona> implements Iterator<C> {
private boolean repeating;
......@@ -43,52 +49,100 @@ public class CoronaFactory<C extends Corona> implements Iterator<C> {
private String indexVariable;
private BootstrapCallback callback;
private static final Logger logger = LoggerFactory.getLogger(CoronaFactory.class.getSimpleName());
// ***************************************************************************
// * Constants
// ***************************************************************************
private static final Logger LOGGER = LoggerFactory.getLogger(CoronaFactory.class.getSimpleName());
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* @param coronaNode
* @param context
* @param callback
* @throws BuildException
*/
// ---------------------------------------------------------------------------
public CoronaFactory(Element coronaNode, BootstrapContext context, BootstrapCallback callback) throws BuildException {
this.buildFromBootstrap(coronaNode, context, callback);
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Primitive(s) *
// ***************************************************************************
// ---------------------------------------------------------------------------
@SuppressWarnings("hiding")
private void buildFromBootstrap(Element coronaNode, BootstrapContext context, BootstrapCallback callback) throws BuildException {
this.coronaNode = coronaNode;
this.callback = callback;
this.context = context;
this.index = 0;
this.repeating = BootstrappingUtils.getAttributeAsBoolean(coronaNode, Externalization.REPEAT_ATTRIBUTE, BootstrappingUtils.OPTIONAL, false);
if (this.repeating) {
if (callback != null)
this.context = callback.reset(this.context);
// if (callback == null) {
// String callbackAttribute = BootstrappingUtils.getAttributeAsString(coronaNode,
// Externalization.CALLBACK_ATTRIBUTE, BootstrappingUtils.MANDATORY, null);
// if (context.hasProperty(callbackAttribute)) {
// this.callback = (BootstrapCallback) context.getProperty(callbackAttribute);
// } else {
// throw new BuildException(StringUtils.build("Required callback {} was not found in available
// callbacks!", callbackAttribute)); //$NON-NLS-1$
// }
// }
if (this.callback != null) {
this.context = this.callback.reset(this.context);
this.context = this.callback.initialize(coronaNode, this.context);
}
this.indexVariable = BootstrappingUtils.getAttributeAsString(coronaNode, Externalization.INDEX_ATTRIBUTE, BootstrappingUtils.MANDATORY, null);
String countVariable = BootstrappingUtils.getAttributeAsString(coronaNode, Externalization.COUNT_ATTRIBUTE, BootstrappingUtils.MANDATORY, null);
context.setProperty(this.indexVariable, this.index);
Object countProperty = context.getProperty(countVariable);
if (countProperty == null) {
throw new BuildException("Specified count property " + countVariable + " has not been set in context!"); //$NON-NLS-1$ //$NON-NLS-2$
throw new BuildException(StringUtils.build("Specified count property {} has not been set in context!", countVariable)); //$NON-NLS-1$
}
this.count = Integer.parseInt(countProperty.toString());
} else
{
} else {
this.count = 1;
}
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
/** {@inheritDoc} */
// ---------------------------------------------------------------------------
@Override
public boolean hasNext() {
return (index < count);
}
// ---------------------------------------------------------------------------
/** {@inheritDoc} */
// ---------------------------------------------------------------------------
@SuppressWarnings("unchecked")
@Override
public C next() {
C next = null;
if (!hasNext()) {
throw new NoSuchElementException();
}
try {
if (callback != null)
this.context = callback.preInstantiation(this.coronaNode, this.context);
......@@ -97,7 +151,7 @@ public class CoronaFactory<C extends Corona> implements Iterator<C> {
if (callback != null)
this.context = callback.postInstantiation(this.coronaNode, this.context);
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException | BuildException exception) {
logger.error("Failed to instantiate a corona from template!", exception); //$NON-NLS-1$
LOGGER.error("Failed to instantiate a corona from template!", exception); //$NON-NLS-1$
}
this.index++;
if (this.repeating) {
......@@ -106,7 +160,17 @@ public class CoronaFactory<C extends Corona> implements Iterator<C> {
this.context = callback.next(context);
}
if ((callback != null) && !hasNext()) {
this.context = this.callback.finalize(context);
}
return next;
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of Class *
// ***************************************************************************
// ---------------------------------------------------------------------------
}
......@@ -30,6 +30,7 @@ public class AngleUtils {
protected static final double PI_HALF = Math.PI / 2;
protected static final double THREE_PI_HALF = 1.5 * Math.PI;
protected static final double TWO_PI = 2 * Math.PI;
protected static final double THREE_PI = 3 * Math.PI;
protected static final double THREE_SIXTY = 360d;
protected static final double ONE_EIGHTY = 180d;
......@@ -87,8 +88,43 @@ public class AngleUtils {
*/
// ---------------------------------------------------------------------------
public static double wrap(double rawAngle) {
public static double wrapThreeSixty(double rawAngle) {
return ((rawAngle + 540) % THREE_SIXTY) - ONE_EIGHTY;
}
// ---------------------------------------------------------------------------
/**
* Brings the specified raw angle in the range between -π and + π degrees. This operation is useful
* for checking angular ranges crossing the 2π/0 line.
*
* @param rawAngle
* specifies the raw angle to wrap.
* @return the transformed rawAngle alpha so that the condition -π <= alpha < π is met.
*
*/
// ---------------------------------------------------------------------------
public static double wrapTwoPi(double rawAngle) {
return ((rawAngle + THREE_PI) % TWO_PI) - Math.PI;
}
// ---------------------------------------------------------------------------
/**
* @param angle
* @return
*/
// ---------------------------------------------------------------------------
public static final int getQuadrant(double angle) {
double modulo = moduloTwoPi(angle);
int cosSign = (Math.cos(modulo) < 0) ? 1 : 0;
int sinSign = (Math.sin(modulo) < 0) ? 1 : 0;
int quadrant = (cosSign ^ sinSign) + sinSign + sinSign;
return quadrant;
}
}
......@@ -51,6 +51,7 @@ public class Externalization extends NLS {
public static String BUILDER_CLASS_POSTFIX;
public static String BUNDLES_NODE;
public static String BUNDLE_NODE;
public static String CALLBACK_ATTRIBUTE;
public static String CENTER_ON_ZOOM_NODE;
public static String CENTRE_NODE;
public static String CENTRED_NODE;
......@@ -105,6 +106,7 @@ public class Externalization extends NLS {
public static String INITIAL_ROTATION_NODE;
public static String INITIAL_TRANSLATION_NODE;
public static String INNER_RADIUS_NODE;
public static String INSET_BORDER_NODE;
public static String JAVA_AWT_COLOR_NAMESPACE;
public static String LABEL_COLOUR_ELEMENT;
public static String LABEL_FORMAT_NODE;
......
......@@ -54,28 +54,6 @@ public class PolarCoordinateHelper {
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* @param angle
* @return
*/
public static final int getQuadrant(double angle) {
angle = angle % TWO_PI;
// Nudge angle into next quadrant for angles π/2, π, 3π/2 and 2π
// angle += ((angle == PI_HALF) || (angle == Math.PI) || (angle == THREE_PI_HALF) || (angle
// == TWO_PI)) ? 1e-10 : 0;
int cosSign = (Math.cos(angle) < 0) ? 1 : 0;
int sinSign = (Math.sin(angle) < 0) ? 1 : 0;
int quadrant = (cosSign ^ sinSign) + sinSign + sinSign;
return quadrant;
}
// ---------------------------------------------------------------------------
/**
* @param pole
* @param coordinate
......
......@@ -88,8 +88,7 @@ public class Vector2D {
// ---------------------------------------------------------------------------
/**
* @param operand
* @return a new Dimension object representing the sum of this dimension and the specified
* operand.
* @return a new Dimension object representing the sum of this dimension and the specified operand.
*/
// ---------------------------------------------------------------------------
......@@ -128,6 +127,18 @@ public class Vector2D {
*/
// ---------------------------------------------------------------------------
public Vector2D atAngle(double angle) {
return new Vector2D((this.x * Math.cos(angle)), (this.y * Math.sin(angle)));
}
// ---------------------------------------------------------------------------
/**
* @param factor
* specifies the factor to multiply this dimension with.
* @return a new Dimension object representing this instance scaled by the specified factor.
*/
// ---------------------------------------------------------------------------
public Vector2D divideBy(double factor) {
if (factor != 0) {
return new Vector2D((this.x / factor), (this.y / factor));
......
......@@ -19,6 +19,7 @@ package lu.list.itis.dkd.tui.utility.graph;
import com.jgoodies.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -122,6 +123,7 @@ public class Graph {
if (!this.nodesLookup.containsKey(nodeToAdd.getId())) {
this.nodes.add(nodeToAdd);
Collections.sort(this.nodes);
}
this.nodesLookup.put(nodeToAdd.getId(), nodeToAdd);
......@@ -174,6 +176,7 @@ public class Graph {
if (!alreadyKnown) {
this.edges.add(edgeToAdd);
Collections.sort(this.edges);
}
if (!this.neighbours.containsKey(edgeToAdd.getSource().getId())) {
......
......@@ -16,8 +16,12 @@
*/
package lu.list.itis.dkd.tui.utility.graph;
import lu.list.itis.dkd.dbc.annotation.Nullable;
import com.jgoodies.common.base.Preconditions;
import java.util.Objects;
/**
* @author mack
* @since 2.5
......@@ -27,7 +31,7 @@ import com.jgoodies.common.base.Preconditions;
// * Class Definition and Members *
// ***************************************************************************
public class Node {
public class Node implements Comparable<Node> {
private Integer id;
private double mass;
......@@ -117,6 +121,37 @@ public class Node {
this.mass = mass;
}
// ---------------------------------------------------------------------------
/** {@inheritDoc} */
@Override
public int compareTo(Node o) {
return Integer.compare(this.id, o.id);
}
// ---------------------------------------------------------------------------
@Override
public boolean equals(@Nullable Object object) {
if (object == null)
return false;
if (object == this)
return true;
if (object instanceof Node) {
Node node = (Node) object;
return id == node.id;
}
return false;
}
// ---------------------------------------------------------------------------
@Override
public int hashCode() {
return Objects.hashCode(id);
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of Class
......
......@@ -185,7 +185,7 @@ public class Body {
// ---------------------------------------------------------------------------