Commit f4e1739e authored by Eric Tobias's avatar Eric Tobias

2.1.0 - Added SpatialMatrix and removed spatial comparators as the behaviour wasn't consistent.

+ Added methods to retrieve position information to BaseWidget.
+ Updated behaviour to retrieve widgets from the TangibleObjectManager to also include cursors and blobs.
~ BaseBuilder now specifies the network adapter as Nullable.
parent d8ad4b93
...@@ -329,7 +329,7 @@ public class TangibleInterfaceManager extends JComponent { ...@@ -329,7 +329,7 @@ public class TangibleInterfaceManager extends JComponent {
} }
if (tangibleApplication.getObjectManager() != null) { if (tangibleApplication.getObjectManager() != null) {
for (BaseWidget widget : tangibleApplication.getObjectManager().getObjects()) { for (BaseWidget widget : tangibleApplication.getObjectManager().getWidgets()) {
widget.paint(canvas2D); widget.paint(canvas2D);
} }
} }
......
...@@ -29,6 +29,7 @@ import lu.list.itis.dkd.tui.widget.corona.builder.ShadowBuilder; ...@@ -29,6 +29,7 @@ import lu.list.itis.dkd.tui.widget.corona.builder.ShadowBuilder;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Properties; import java.util.Properties;
import java.util.Vector; import java.util.Vector;
...@@ -140,13 +141,17 @@ public abstract class TangibleObjectManager { ...@@ -140,13 +141,17 @@ public abstract class TangibleObjectManager {
} }
/** /**
* Method returning a collection of {@link BaseWidget} instances held by this manager. * 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. * @return The collection of managed {@link BaseWidget} instances.
*/ */
public synchronized Collection<BaseWidget> getObjects() { public static synchronized Collection<BaseWidget> getWidgets() {
Preconditions.checkState(objectList.values() != null, "Critical failure, a values() call to an initialised dictionnary " + "should never return null."); //$NON-NLS-1$ //$NON-NLS-2$ Collection<BaseWidget> widgets = new ArrayList<>();
return objectList.values(); widgets.addAll(objectList.values());
widgets.addAll(cursorList.values());
widgets.addAll(blobList.values());
return widgets;
} }
/** /**
...@@ -158,8 +163,15 @@ public abstract class TangibleObjectManager { ...@@ -158,8 +163,15 @@ public abstract class TangibleObjectManager {
* @return The {@link BaseWidget} or <code>null</code> if no {@link BaseWidget} was keyed to the * @return The {@link BaseWidget} or <code>null</code> if no {@link BaseWidget} was keyed to the
* identifier. * identifier.
*/ */
public static synchronized @Nullable BaseWidget getObject(int identifier) { public static synchronized @Nullable BaseWidget getWidget(int identifier) {
return objectList.get(identifier) != null ? objectList.get(identifier) : cursorList.get(identifier); if (null != objectList.get(identifier)) {
return objectList.get(identifier);
}
if (null != cursorList.get(identifier)) {
return cursorList.get(identifier);
}
return blobList.get(identifier);
} }
/** /**
......
...@@ -306,7 +306,20 @@ public class TangibleObject { ...@@ -306,7 +306,20 @@ public class TangibleObject {
* @return The {@link Point} instance representing this objects location data. * @return The {@link Point} instance representing this objects location data.
*/ */
public Point getPosition() { public Point getPosition() {
return new Point(this.getX(), this.getY(), this.getAngle(), Math.signum(this.rotationSpeed)); return path.get(path.size() - 1);
}
/**
* Method for retrieving one of the former positions of this instance.
*
* @param anteriority
* The number of steps in this instances path to go back. Note that if the anteriority is
* superior to the paths length, the first element will be returned.
* @return The position of this instance at the given "time" or the first position in the path
* if the "time" is greater then the recorded path's length.
*/
public Point getPreviousPosition(int anteriority) {
return path.get((anteriority >= path.size() ? 0 : path.size() - (anteriority + 1)));
} }
/** /**
...@@ -489,4 +502,22 @@ public class TangibleObject { ...@@ -489,4 +502,22 @@ public class TangibleObject {
public void setArea(float area) { public void setArea(float area) {
this.area = area; this.area = area;
} }
@Override
public boolean equals(@Nullable Object that) {
if (this == that) {
return true;
}
if (that instanceof TangibleObject) {
return hashCode() == ((TangibleObject) that).hashCode();
}
return false;
}
@Override
public int hashCode() {
return getObjectId();
}
} }
\ No newline at end of file
...@@ -21,8 +21,6 @@ import lu.list.itis.dkd.tui.adapter.TangibleObject; ...@@ -21,8 +21,6 @@ import lu.list.itis.dkd.tui.adapter.TangibleObject;
import lu.list.itis.dkd.tui.utility.Point; import lu.list.itis.dkd.tui.utility.Point;
import lu.list.itis.dkd.tui.utility.ScreenCoordinates; import lu.list.itis.dkd.tui.utility.ScreenCoordinates;
import com.google.common.base.Preconditions;
import java.util.EventObject; import java.util.EventObject;
/** /**
...@@ -54,17 +52,16 @@ public class SpatialEvent extends EventObject { ...@@ -54,17 +52,16 @@ public class SpatialEvent extends EventObject {
* the event. * the event.
* @param location * @param location
* The location the event was triggered on. Note that the location must be expressed in * The location the event was triggered on. Note that the location must be expressed in
* {@link ScreenCoordinates}. * {@link ScreenCoordinates}. Otherwise the conversion will be done before the location
* is stored.
* @param type * @param type
* The type of the event that is to be triggered. * The type of the event that is to be triggered.
* @ore location.getState().getClass() == ScreenCoordinates.class * @pre location.getState().getClass() == ScreenCoordinates.class
*/ */
public SpatialEvent(TangibleObject source, Point location, SpatialEventType type) { public SpatialEvent(TangibleObject source, Point location, SpatialEventType type) {
super(source); super(source);
Preconditions.checkArgument(location.getState().getClass().equals(ScreenCoordinates.class), "The location must be given in screen coordinates!"); //$NON-NLS-1$ this.location = location.toScreenCoordinates();
this.location = location;
this.type = type; this.type = type;
} }
......
/**
* Copyright Luxembourg Institute of Science and Technology, 2015. All rights reserved.
*
* This file is part of TULIP.
*
* TULIP is free software: you can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation, version 3 of the
* License.
*
* TULIP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.space;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.tui.adapter.TangibleObject;
import lu.list.itis.dkd.tui.utility.ScreenCoordinates;
import java.util.Comparator;
/**
* @author Eric Tobias [eric.tobias@list.lu]
* @since 2.1
* @version 2.1.0
*/
@NonNullByDefault
public class HorizontalPositionComparator implements Comparator<TangibleObject> {
/**
* Method used to compare two {@link TangibleObject} instances. The method will return 0 if both
* instances are equal. None of the provided parameters may be <code>null</code>.
*
* The method will use {@link Double#compare(double, double)} on the x-axis position of the
* provided {@link TangibleObject} instances after retrieving and converting their points to
* {@link ScreenCoordinates}.
*/
@Override
public int compare(TangibleObject thisTangible, TangibleObject thatTangible) {
if (thisTangible.equals(thatTangible)) {
return 0;
}
return Double.compare(thisTangible.getPosition().toScreenCoordinates().getX(), thatTangible.getPosition().toScreenCoordinates().getX());
}
}
\ No newline at end of file
/**
* Copyright Luxembourg Institute of Science and Technology, 2015. All rights reserved.
*
* This file is part of TULIP.
*
* TULIP is free software: you can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation, version 3 of the
* License.
*
* TULIP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.space;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.tui.adapter.TangibleObject;
import java.util.ArrayList;
/**
* @author Eric Tobias [eric.tobias@list.lu]
* @since 2.1
* @version 2.1.1
*/
@NonNullByDefault
public class SpatialMatrix {
private ArrayList<TangibleObject> horizontal = new ArrayList<>();
private ArrayList<TangibleObject> vertical = new ArrayList<>();
/**
* Method used to add an element to the matrix. The method will insert the element into the
* matrix such that all elements horizontally to the left of have a smaller (or equal) x-axis
* coordinate and such that all elements on the vertical axis that are above this element have a
* smaller or equal y-axis coordinate.
*
* @param object
* The object to add.
*/
public void add(TangibleObject object) {
object.getPosition().toScreenCoordinates();
horizontal.add(findHorizontalIndexFor(object), object);
vertical.add(findVerticalIndexFor(object), object);
}
/**
* Method to remove an element from the matrix. The method will remove the object from the
* matrix space.
*
* @param object
* The object to remove.
*/
public void remove(TangibleObject object) {
horizontal.remove(object);
vertical.remove(object);
}
/**
* Method used to update an object that is already present in the matrix. The method will remove
* and reinsert the object in this atomic operation.
*
* @param object
* The object to update.
*/
public synchronized void update(TangibleObject object) {
remove(object);
add(object);
}
/**
* Method used to find the index of the first horizontal object whose x-axis coordinate is
* bigger than this object's. Returns the size of the horizontal list if no such element could
* be found.
*
* @param object
* The object to look up the insertion index for.
* @return The index to add the element or the size of the list if the element should be added
* at the end.
*/
private int findHorizontalIndexFor(TangibleObject object) {
for (int index = 0; index < horizontal.size(); index++) {
if (Double.compare(object.getPosition().getX(), horizontal.get(index).getPosition().getX()) <= 0) {
return index;
}
}
return horizontal.size();
}
/**
* Method used to find the index of the first horizontal object whose x-axis coordinate is
* bigger than this object's. Returns the size of the horizontal list if no such element could
* be found.
*
* @param object
* The object to look up the insertion index for.
* @return The index to add the element or the size of the list if the element should be added
* at the end.
*/
private int findVerticalIndexFor(TangibleObject object) {
for (int index = 0; index < vertical.size(); index++) {
if (Double.compare(object.getPosition().getY(), vertical.get(index).getPosition().getY()) <= 0) {
return index;
}
}
return vertical.size();
}
public void printLists() {
StringBuilder verticalBuilder = new StringBuilder();
StringBuilder horizontalbuilder = new StringBuilder();
vertical.forEach(object -> verticalBuilder.append(object.getObjectId() + ", ")); //$NON-NLS-1$
horizontal.forEach(object -> horizontalbuilder.append(object.getObjectId() + ", ")); //$NON-NLS-1$
System.out.println("Vertical : " + verticalBuilder.toString()); //$NON-NLS-1$
System.out.println("Horizontal : " + horizontalbuilder.toString()); //$NON-NLS-1$
}
}
\ No newline at end of file
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
*/ */
package lu.list.itis.dkd.tui.space; package lu.list.itis.dkd.tui.space;
import lu.list.itis.dkd.tui.adapter.TangibleObject;
import lu.list.itis.dkd.tui.event.SpatialEvent; import lu.list.itis.dkd.tui.event.SpatialEvent;
import lu.list.itis.dkd.tui.event.SpatialEventListener; import lu.list.itis.dkd.tui.event.SpatialEventListener;
import lu.list.itis.dkd.tui.utility.PropertiesFetcher; import lu.list.itis.dkd.tui.utility.PropertiesFetcher;
...@@ -25,7 +24,6 @@ import com.google.common.base.Preconditions; ...@@ -25,7 +24,6 @@ import com.google.common.base.Preconditions;
import java.io.IOException; import java.io.IOException;
import java.util.Properties; import java.util.Properties;
import java.util.TreeSet;
import java.util.logging.FileHandler; import java.util.logging.FileHandler;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
...@@ -48,18 +46,17 @@ import java.util.logging.Logger; ...@@ -48,18 +46,17 @@ import java.util.logging.Logger;
*/ */
public class SpatialPositioningManager implements SpatialEventListener { public class SpatialPositioningManager implements SpatialEventListener {
private static final SpatialPositioningManager INSTANCE = new SpatialPositioningManager();
private static final Logger logger = Logger.getLogger(SpatialPositioningManager.class.getSimpleName()); private static final Logger logger = Logger.getLogger(SpatialPositioningManager.class.getSimpleName());
private static final Properties properties = PropertiesFetcher.fetchProperties(); private static final Properties properties = PropertiesFetcher.fetchProperties();
private static final SpatialPositioningManager INSTANCE = new SpatialPositioningManager();
private TreeSet<TangibleObject> horizontalOrder = new TreeSet<>(new HorizontalPositionComparator()); private SpatialMatrix spatialMatrix = new SpatialMatrix();
private TreeSet<TangibleObject> verticalOrder = new TreeSet<>(new VerticalPositionComparator());
/** /**
* Constructor initializing all fields. * Constructor initializing all fields.
*/ */
private SpatialPositioningManager() { private SpatialPositioningManager() {
// TODO Auto-generated constructor stub configureLogger(logger);
} }
/** /**
...@@ -67,7 +64,7 @@ public class SpatialPositioningManager implements SpatialEventListener { ...@@ -67,7 +64,7 @@ public class SpatialPositioningManager implements SpatialEventListener {
* *
* @return The only valid instance of this {@link SpatialPositioningManager}. * @return The only valid instance of this {@link SpatialPositioningManager}.
*/ */
public SpatialPositioningManager getInstance() { public static SpatialPositioningManager getInstance() {
return INSTANCE; return INSTANCE;
} }
...@@ -79,8 +76,8 @@ public class SpatialPositioningManager implements SpatialEventListener { ...@@ -79,8 +76,8 @@ public class SpatialPositioningManager implements SpatialEventListener {
* The {@link Logger} instance to configure. * The {@link Logger} instance to configure.
* @pre logger != null * @pre logger != null
*/ */
public static void configureLogger(final Logger unconfiguredLogger) { private static void configureLogger(final Logger unconfiguredLogger) {
Preconditions.checkArgument(unconfiguredLogger != null, "The provider logger must not be null!"); //$NON-NLS-1$ Preconditions.checkArgument(unconfiguredLogger != null, "The provided logger must not be null!"); //$NON-NLS-1$
if (Boolean.parseBoolean(properties.getProperty("logger.event.output.enabled"))) { //$NON-NLS-1$ if (Boolean.parseBoolean(properties.getProperty("logger.event.output.enabled"))) { //$NON-NLS-1$
try { try {
...@@ -98,22 +95,18 @@ public class SpatialPositioningManager implements SpatialEventListener { ...@@ -98,22 +95,18 @@ public class SpatialPositioningManager implements SpatialEventListener {
switch (event.getType()) { switch (event.getType()) {
case UPDATE: case UPDATE:
horizontalOrder.remove(event.getSource()); spatialMatrix.update(event.getSource());
verticalOrder.remove(event.getSource()); break;
// The update call would need to remove and then reinsert the objects to trigger a
// rearrangement.
// $FALL-THROUGH$
case INSERT: case INSERT:
horizontalOrder.add(event.getSource()); spatialMatrix.add(event.getSource());
verticalOrder.add(event.getSource());
break; break;
case REMOVE: case REMOVE:
horizontalOrder.remove(event.getSource()); spatialMatrix.remove(event.getSource());
verticalOrder.remove(event.getSource());
break; break;
default: default:
logger.log(Level.SEVERE, "Spatial event type \"" + event.getType() + "\" not recognized!"); //$NON-NLS-1$ //$NON-NLS-2$ logger.log(Level.SEVERE, "Spatial event type \"" + event.getType() + "\" not recognized!"); //$NON-NLS-1$ //$NON-NLS-2$
break; break;
} }
spatialMatrix.printLists();
} }
} }
\ No newline at end of file
/**
* Copyright Luxembourg Institute of Science and Technology, 2015. All rights reserved.
*
* This file is part of TULIP.
*
* TULIP is free software: you can redistribute it and/or modify it under the terms of the GNU
* Lesser General Public License as published by the Free Software Foundation, version 3 of the
* License.
*
* TULIP is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with TULIP. If
* not, see <http://www.gnu.org/licenses/lgpl-3.0.html>.
*/
package lu.list.itis.dkd.tui.space;
import lu.list.itis.dkd.tui.adapter.TangibleObject;
import lu.list.itis.dkd.tui.utility.ScreenCoordinates;
import java.util.Comparator;
/**
* @author Eric Tobias [eric.tobias@list.lu]
* @since 2.1
* @version 2.1.0
*/
public class VerticalPositionComparator implements Comparator<TangibleObject> {
/**
* Method used to compare two {@link TangibleObject} instances. The method will return 0 if both
* instances are equal. None of the provided parameters may be <code>null</code>.
*
* The method will use {@link Double#compare(double, double)} on the y-axis position of the
* provided {@link TangibleObject} instances after retrieving and converting their points to
* {@link ScreenCoordinates}.
*
* <b>Important</b>: the provided coordinate system for the screen uses an inverse y-axis.
*/
@Override
public int compare(TangibleObject thisTangible, TangibleObject thatTangible) {
if (thisTangible.equals(thatTangible)) {
return 0;
}
return Double.compare(thisTangible.getPosition().toScreenCoordinates().getY(), thatTangible.getPosition().toScreenCoordinates().getY());
}
}
\ No newline at end of file
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
package lu.list.itis.dkd.tui.widget; package lu.list.itis.dkd.tui.widget;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault; import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.dbc.annotation.Nullable;
import lu.list.itis.dkd.tui.adapter.TangibleObject; import lu.list.itis.dkd.tui.adapter.TangibleObject;
import lu.list.itis.dkd.tui.logging.EventLogger; import lu.list.itis.dkd.tui.logging.EventLogger;
import lu.list.itis.dkd.tui.network.adapter.NetworkAdapter; import lu.list.itis.dkd.tui.network.adapter.NetworkAdapter;
...@@ -40,7 +41,7 @@ import java.util.List; ...@@ -40,7 +41,7 @@ import java.util.List;
* *
* @author Eric TOBIAS [eric.tobias@list.lu] * @author Eric TOBIAS [eric.tobias@list.lu]
* @since 1.0 * @since 1.0
* @version 1.0.2 * @version 2.1.1
*/ */
@NonNullByDefault @NonNullByDefault
public class BaseWidget { public class BaseWidget {
...@@ -50,7 +51,7 @@ public class BaseWidget { ...@@ -50,7 +51,7 @@ public class BaseWidget {
protected HashMap<Integer, Point> positions; protected HashMap<Integer, Point> positions;
/** The name given to this widget. */ /** The name given to this widget. */
protected String name; protected String name;
@Nullable
protected NetworkAdapter networkAdapter; protected NetworkAdapter networkAdapter;
/** /**
...@@ -76,7 +77,7 @@ public class BaseWidget { ...@@ -76,7 +77,7 @@ public class BaseWidget {
* The {@link TangibleObject} that was triggering the move. * The {@link TangibleObject} that was triggering the move.
*/ */
public void actionMove(TangibleObject tangibleObject) { public void actionMove(TangibleObject tangibleObject) {
EventLogger.getInstance().addObjInfo(tangibleObject.getObjectId(), tangibleObject.getX(), tangibleObject.getY(), tangibleObject.getAngle(), "move", tangibleObject.getTotalMilliseconds()); EventLogger.getInstance().addObjInfo(tangibleObject.getObjectId(), tangibleObject.getX(), tangibleObject.getY(), tangibleObject.getAngle(), "move", tangibleObject.getTotalMilliseconds()); //$NON-NLS-1$
positions.put(tangibleObject.getObjectId(), new Point(tangibleObject.getX(), tangibleObject.getY(), tangibleObject.getAngle(), Math.signum(tangibleObject.getRotationSpeed()))); positions.put(tangibleObject.getObjectId(), new Point(tangibleObject.getX(), tangibleObject.getY(), tangibleObject.getAngle(), Math.signum(tangibleObject.getRotationSpeed())));
updateCoronas(tangibleObject.getObjectId()); updateCoronas(tangibleObject.getObjectId());
} }
...@@ -102,7 +103,7 @@ public class BaseWidget { ...@@ -102,7 +103,7 @@ public class BaseWidget {
* The {@link TangibleObject} that was triggering the drop action. * The {@link TangibleObject} that was triggering the drop action.
*/ */
public void actionDrop(TangibleObject tangibleObject) { public void actionDrop(TangibleObject tangibleObject) {
EventLogger.getInstance().addObjInfo(tangibleObject.getObjectId(), tangibleObject.getX(), tangibleObject.getY(), tangibleObject.getAngle(), "down", tangibleObject.getTotalMilliseconds()); EventLogger.getInstance().addObjInfo(tangibleObject.getObjectId(), tangibleObject.getX(), tangibleObject.getY(), tangibleObject.getAngle(), "down", tangibleObject.getTotalMilliseconds()); //$NON-NLS-1$
actionMove(tangibleObject); actionMove(tangibleObject);
startDrawingIfAppropriate(tangibleObject.getObjectId()); startDrawingIfAppropriate(tangibleObject.getObjectId());
} }
...@@ -128,7 +129,7 @@ public class BaseWidget { ...@@ -128,7 +129,7 @@ public class BaseWidget {
* The TangibleObject that was triggering the drop action. * The TangibleObject that was triggering the drop action.
*/ */
public void actionLift(TangibleObject tangibleObject) { public void actionLift(TangibleObject tangibleObject) {
EventLogger.getInstance().addObjInfo(tangibleObject.getObjectId(), tangibleObject.getX(), tangibleObject.getY(), tangibleObject.getAngle(), "up", tangibleObject.getTotalMilliseconds()); EventLogger.getInstance().addObjInfo(tangibleObject.getObjectId(), tangibleObject.getX(), tangibleObject.getY(), tangibleObject.getAngle(), "up", tangibleObject.getTotalMilliseconds()); //$NON-NLS-1$
actionMove(tangibleObject); actionMove(tangibleObject);
stopDrawing(tangibleObject.getObjectId()); stopDrawing(tangibleObject.getObjectId());
} }
...@@ -199,13 +200,37 @@ public class BaseWidget { ...@@ -199,13 +200,37 @@ public class BaseWidget {
return results; return results;
} }
/**
* Method for returning the {@link Point} that holds the position at which the handle with the
* given ID resides.
*
* @param handleId
* The ID of the handle for which to retrieve the position.
* @return The {@link Point} holding the position of the parameterized (by its ID) handle.
* <code>null</code> if no such handle is managed.
*/
public Point getPosition(int handleId) {
return positions.get(handleId);
}