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

Cleanup of code. Implemented cloning of widgets, required by feature

allowing mutliple widgets with identical IDs.
parent 5e2bc616
...@@ -171,6 +171,7 @@ STYLESHEET_NODE=styleSheet ...@@ -171,6 +171,7 @@ STYLESHEET_NODE=styleSheet
STYLERULE_NODE=rule STYLERULE_NODE=rule
PATH_NODE=path PATH_NODE=path
PAGE_NODE=page
MEDIA_NODE=media MEDIA_NODE=media
LOCATION_NODE=location LOCATION_NODE=location
......
/**
* Copyright Luxembourg Institute of Science and Technology, 2016.
*
* This file is part of TULIP.
*
* TULIP is licensed under a dual-licensing scheme. For non-commercial purposes, the LGPL version 3,
* as stated below, is applicable. For all commercial purposes TULIP is licensed under a LIST
* proprietary license. Please contact LIST at tto@list.lu to obtain a commercial license.
*
* For all non-commercial purposes, 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.content;
import lu.list.itis.dkd.dbc.annotation.NonNullByDefault;
import lu.list.itis.dkd.dbc.annotation.Nullable;
import lu.list.itis.dkd.tui.utility.Point;
import lu.list.itis.dkd.tui.widget.ZoomWidget;
/**
* Interface imposing functionality in order to be used with the {@link ZoomWidget}.
*
* @author Eric Tobias [eric.tobias@list.lu]
* @since 1.0
* @version 2.3.0
*/
@NonNullByDefault
public interface Zoomable {
/**
* Method used to specify the initial position of the zoom.
*
* @param position
*/
public void centre(Point position);
/**
* Method used to request all zooms be translate to the specified position.
*
* @param position
* The position to centre on.
*/
public void translate(Point position);
/**
* Method used to zoom by a factor given as parameter The direction of the zoom depends whether
* the parameter is positive or negative.
*
* @param position
* Zoom factor contained in a {@link Point}.
*/
public void zoom(@Nullable Point position);
/**
* Method called by the manager handling the {@link Zoomable} instance when the state changed to
* where it is no longer considered zooming. This method provides the opportunity to run code
* only executable when the zooming stopped.
*/
public void stoppedZooming();
/**
* Method called by the manager handling the {@link Zoomable} instance when the state changed to
* where it is no longer considered moving. This method provides the opportunity to run code
* only executable when the moving stopped.
*/
public void stoppedMoving();
}
\ No newline at end of file
...@@ -215,6 +215,7 @@ public class Externalization extends NLS { ...@@ -215,6 +215,7 @@ public class Externalization extends NLS {
public static String POINTING_OFFSET_NODE; public static String POINTING_OFFSET_NODE;
public static String PATH_NODE; public static String PATH_NODE;
public static String PAGE_NODE;
public static String MEDIA_NODE; public static String MEDIA_NODE;
public static String LOCATION_NODE; public static String LOCATION_NODE;
......
...@@ -441,22 +441,6 @@ public class Point extends Float implements KdComparator<Point> { ...@@ -441,22 +441,6 @@ public class Point extends Float implements KdComparator<Point> {
return clone(); return clone();
} }
// switch (state.getClass().getSimpleName()) {
// case "TableCoordinates": //$NON-NLS-1$
// point.toTableCoordinates();
// break;
// case "ScreenCoordinates": //$NON-NLS-1$
// point.toScreenCoordinates();
// break;
// case "CameraCoordinates": //$NON-NLS-1$
// point.toCameraCoordinates();
// break;
// default:
// logger.error("This should never happen! State: {}!", state.toString()); //$NON-NLS-1$
// break;
// }
point.getState().toCoordinates(point, this.state.getClass()); point.getState().toCoordinates(point, this.state.getClass());
Point clone = clone(); Point clone = clone();
......
...@@ -36,36 +36,53 @@ import java.util.ArrayList; ...@@ -36,36 +36,53 @@ import java.util.ArrayList;
* @since 1.0 * @since 1.0
* @version 2.3.0 * @version 2.3.0
*/ */
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
@NonNullByDefault @NonNullByDefault
public class ContentWidget extends BaseWidget { public class ContentWidget extends BaseWidget {
/** List of {@link ContentEventListener} instances listening to updates to content. */ /** List of {@link ContentEventListener} instances listening to updates to content. */
protected ArrayList<ContentEventListener> listeners = new ArrayList<>(); protected ArrayList<ContentEventListener> listeners = new ArrayList<>();
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s)
// ***************************************************************************
// ---------------------------------------------------------------------------
/** /**
* Constructor making use of the super constructor to initialise all fields. * Constructor making use of the super constructor to initialise all fields.
* *
* @param builder * @param builder
* The builder instance defining all parameters. * The builder instance defining all parameters.
*/ */
// ---------------------------------------------------------------------------
public ContentWidget(BaseContentBuilder<?> builder) { public ContentWidget(BaseContentBuilder<?> builder) {
super(builder); super(builder);
listeners = builder.listeners; listeners = builder.listeners;
} }
// ---------------------------------------------------------------------------
/** /**
* Method invoked when the tangible is detected on the table surface for the first time. The * Copy constructor to clone widget.
* {@link BaseWidget} instance is set to be active.
* *
* @param tangibleObject * @param original
* The {@link TangibleObject} that triggered the drop action. * specifies the original widget to create an exact copy from.
*/ */
@Override // ---------------------------------------------------------------------------
public void actionDrop(TangibleObject tangibleObject) {
super.actionDrop(tangibleObject);
notify(this, tangibleObject.getObjectId(), ContentEventType.DROP);
}
public ContentWidget(ContentWidget original) {
super(original);
listeners = new ArrayList<>(original.listeners);
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Primitive(s)
// ***************************************************************************
// ---------------------------------------------------------------------------
/** /**
* Method used to notify all listeners to a specific event. * Method used to notify all listeners to a specific event.
* *
...@@ -76,26 +93,35 @@ public class ContentWidget extends BaseWidget { ...@@ -76,26 +93,35 @@ public class ContentWidget extends BaseWidget {
* @param type * @param type
* The type of the triggered event. * The type of the triggered event.
*/ */
// ---------------------------------------------------------------------------
private void notify(ContentWidget widget, int handleID, ContentEventType type) { private void notify(ContentWidget widget, int handleID, ContentEventType type) {
for (ContentEventListener listener : listeners) { for (ContentEventListener listener : listeners) {
listener.contentUpdated(new ContentEvent(widget, handleID, type)); listener.contentUpdated(new ContentEvent(widget, handleID, type));
} }
} }
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body
// ***************************************************************************
// ---------------------------------------------------------------------------
/** /**
* Method invoked when the tangible is removed from the table surface. The {@link BaseWidget} * Method invoked when the tangible is detected on the table surface for the first time. The
* instance will be set to no longer be active. * {@link BaseWidget} instance is set to be active.
* *
* @param tangibleObject * @param tangibleObject
* The {@link TangibleObject} that was triggering the lift action. * The {@link TangibleObject} that triggered the drop action.
*/ */
// ---------------------------------------------------------------------------
@Override @Override
public void actionLift(TangibleObject tangibleObject) { public void actionDrop(TangibleObject tangibleObject) {
super.actionLift(tangibleObject); super.actionDrop(tangibleObject);
notify(this, tangibleObject.getObjectId(), ContentEventType.LIFT); notify(this, tangibleObject.getObjectId(), ContentEventType.DROP);
} }
// ---------------------------------------------------------------------------
/** /**
* Method invoked when a handle associated with the widget was moved. This default * Method invoked when a handle associated with the widget was moved. This default
* implementation will set the base and angle fields to the corresponding values and update the * implementation will set the base and angle fields to the corresponding values and update the
...@@ -104,13 +130,31 @@ public class ContentWidget extends BaseWidget { ...@@ -104,13 +130,31 @@ public class ContentWidget extends BaseWidget {
* @param tangibleObject * @param tangibleObject
* The {@link TangibleObject} that was triggering the move. * The {@link TangibleObject} that was triggering the move.
*/ */
// ---------------------------------------------------------------------------
@Override @Override
public void actionMove(TangibleObject tangibleObject) { public void actionMove(TangibleObject tangibleObject) {
super.actionMove(tangibleObject); super.actionMove(tangibleObject);
notify(this, tangibleObject.getObjectId(), ContentEventType.MANIPULATION); notify(this, tangibleObject.getObjectId(), ContentEventType.MANIPULATION);
} }
// ---------------------------------------------------------------------------
/**
* Method invoked when the tangible is removed from the table surface. The {@link BaseWidget}
* instance will be set to no longer be active.
*
* @param tangibleObject
* The {@link TangibleObject} that was triggering the lift action.
*/
// ---------------------------------------------------------------------------
@Override
public void actionLift(TangibleObject tangibleObject) {
super.actionLift(tangibleObject);
notify(this, tangibleObject.getObjectId(), ContentEventType.LIFT);
}
// ---------------------------------------------------------------------------
/** /**
* Method used to determine which segment the rotation of a handle is in given the number of * Method used to determine which segment the rotation of a handle is in given the number of
* segments to cover by one rotation. * segments to cover by one rotation.
...@@ -120,13 +164,25 @@ public class ContentWidget extends BaseWidget { ...@@ -120,13 +164,25 @@ public class ContentWidget extends BaseWidget {
* @param handleID * @param handleID
* The ID of the handle to check the rotation for. * The ID of the handle to check the rotation for.
* @return The segment the rotation is currently in given:<br> * @return The segment the rotation is currently in given:<br>
* <code>rotation / (PI / totalSegments)</code>. * <code>rotation / (2*PI / totalSegments)</code>.
*/ */
public int getSegment(int totalSegments, int handleID) { // ---------------------------------------------------------------------------
// float rotation = Math.abs(positions.get(handleID).getAngle());
float rotation = Math.abs(getPosition(handleID).getAngle()); // public int getSegment(int totalSegments, int handleID) {
float segmentSize = (float) (2 * Math.PI / totalSegments); // Preconditions.checkArgument(totalSegments > 0, "Number of segments MUST be greater than 0!");
// //$NON-NLS-1$
//
// double rotation = Math.abs(getPosition(handleID).getAngle() % TWO_PI);
// double segmentSize = (float) (TWO_PI / totalSegments);
//
// return (int) Math.floor(rotation / segmentSize);
// }
// ---------------------------------------------------------------------------
return (int) Math.floor(rotation / segmentSize); @Override
public ContentWidget clone() {
return new ContentWidget(this);
} }
} }
\ No newline at end of file
...@@ -29,15 +29,15 @@ import lu.list.itis.dkd.tui.exception.UnsupportedInformationException; ...@@ -29,15 +29,15 @@ import lu.list.itis.dkd.tui.exception.UnsupportedInformationException;
import lu.list.itis.dkd.tui.utility.Point; import lu.list.itis.dkd.tui.utility.Point;
import lu.list.itis.dkd.tui.widget.builder.BaseContextAwareBuilder; import lu.list.itis.dkd.tui.widget.builder.BaseContextAwareBuilder;
import lu.list.itis.dkd.tui.widget.corona.ContextAwareCorona; import lu.list.itis.dkd.tui.widget.corona.ContextAwareCorona;
import lu.list.itis.dkd.tui.widget.corona.Corona;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Vector; import java.util.List;
import TUIO.TuioCursor; import TUIO.TuioCursor;
...@@ -47,11 +47,16 @@ import TUIO.TuioCursor; ...@@ -47,11 +47,16 @@ import TUIO.TuioCursor;
* set of listeners of any changes in its state in regard to placement. This is done to give * set of listeners of any changes in its state in regard to placement. This is done to give
* listeners as much context information as possible.<br> * listeners as much context information as possible.<br>
* *
* @author Nico Mack [nico.mack@list.lu]
* @author Valérie Maquil [valerie.maquil@list.lu] * @author Valérie Maquil [valerie.maquil@list.lu]
* @author Eric Tobias [eric.tobias@list.lu] * @author Eric Tobias [eric.tobias@list.lu]
* @since 1.0 * @since 1.0
* @version 2.3.0 * @version 2.5.0
*/ */
// ***************************************************************************
// * Class Definition and Members *
// ***************************************************************************
@NonNullByDefault @NonNullByDefault
public abstract class ContextAwareWidget extends BaseWidget { public abstract class ContextAwareWidget extends BaseWidget {
/** /**
...@@ -60,10 +65,19 @@ public abstract class ContextAwareWidget extends BaseWidget { ...@@ -60,10 +65,19 @@ public abstract class ContextAwareWidget extends BaseWidget {
*/ */
protected volatile HashMultimap<ContextAwareCorona, ContextEventListener> contextEventListeners = HashMultimap.create(); protected volatile HashMultimap<ContextAwareCorona, ContextEventListener> contextEventListeners = HashMultimap.create();
/** Field holding all listeners to be notified on events changing the global state. */ /** Field holding all listeners to be notified on events changing the global state. */
protected volatile Vector<ContextEventListener> globalStateListeners = new Vector<>(); protected volatile List<ContextEventListener> globalStateListeners = new ArrayList<>();
// ***************************************************************************
// * Constants *
// ***************************************************************************
private static final Logger logger = LoggerFactory.getLogger(ContextAwareWidget.class.getSimpleName()); private static final Logger LOGGER = LoggerFactory.getLogger(ContextAwareWidget.class.getSimpleName());
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s)
// ***************************************************************************
// ---------------------------------------------------------------------------
/** /**
* Constructor making use of the super constructor to initialise all fields. * Constructor making use of the super constructor to initialise all fields.
* *
...@@ -76,67 +90,122 @@ public abstract class ContextAwareWidget extends BaseWidget { ...@@ -76,67 +90,122 @@ public abstract class ContextAwareWidget extends BaseWidget {
globalStateListeners = builder.globalStateListeners; globalStateListeners = builder.globalStateListeners;
} }
// ---------------------------------------------------------------------------
/**
* Copy constructor to clone widget.
*
* @param original
* specifies the original widget to create an exact copy from.
*/
// ---------------------------------------------------------------------------
public ContextAwareWidget(ContextAwareWidget original) {
super(original);
contextEventListeners = HashMultimap.create(original.contextEventListeners);
globalStateListeners = new ArrayList<>(original.globalStateListeners);
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Primitive(s)
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* Method used to notify all listeners of a context event.
*
* @param event
* The {@link ContextEvent} instance to notify the listeners of.
*/
// ---------------------------------------------------------------------------
private void notifyStateListeners(ContextEvent event) {
for (ContextEventListener listener : globalStateListeners) {
try {
listener.contextUpdated(event);
} catch (UnsupportedInformationException e) {
LOGGER.warn("The listener could not process the provided information!", e); //$NON-NLS-1$
}
}
}
// ---------------------------------------------------------------------------
/** /**
* Method invoked when a cursor is placed. * Method invoked when a cursor is placed.
* *
* @param tangibleCursor * @param tangibleCursor
* The cursor that was placed. * The cursor that was placed.
*/ */
// ---------------------------------------------------------------------------
public abstract void cursorPlaced(TuioCursor tangibleCursor); public abstract void cursorPlaced(TuioCursor tangibleCursor);
// ---------------------------------------------------------------------------
/** /**
* Method invoked when a cursor is moved. * Method invoked when a cursor is moved.
* *
* @param tangibleCursor * @param tangibleCursor
* The cursor that has moved. * The cursor that has moved.
*/ */
// ---------------------------------------------------------------------------
public abstract void cursorMoved(TuioCursor tangibleCursor); public abstract void cursorMoved(TuioCursor tangibleCursor);
// ---------------------------------------------------------------------------
/** /**
* Method invoked when a cursor is removed. * Method invoked when a cursor is removed.
* *
* @param tangibleCursor * @param tangibleCursor
* The cursor that was removed. * The cursor that was removed.
*/ */
// ---------------------------------------------------------------------------
public abstract void cursorRemoved(TuioCursor tangibleCursor); public abstract void cursorRemoved(TuioCursor tangibleCursor);
// ---------------------------------------------------------------------------
/** /**
* {@inheritDoc}<br> * {@inheritDoc}<br>
* <br> * <br>
* *
* The method notifies all global state listeners of the lifting. * The method notifies all global state listeners of the lifting.
*/ */
// ---------------------------------------------------------------------------
@Override @Override
public void actionLift(TangibleObject tangibleObject) { public void actionLift(TangibleObject tangibleObject) {
notifyStateListeners(new ContextEvent(this, ContextType.OBJECT_LIFT, null)); notifyStateListeners(new ContextEvent(this, ContextType.OBJECT_LIFT, null));
super.actionLift(tangibleObject); super.actionLift(tangibleObject);
} }
// ---------------------------------------------------------------------------
/** /**
* {@inheritDoc}<br> * {@inheritDoc}<br>
* <br> * <br>
* *
* The method notifies all global state listeners of the dropping. * The method notifies all global state listeners of the dropping.
*/ */
// ---------------------------------------------------------------------------
@Override @Override
public void actionDrop(TangibleObject tangibleObject) { public void actionDrop(TangibleObject tangibleObject) {
notifyStateListeners(new ContextEvent(this, ContextType.OBJECT_DROP, null)); notifyStateListeners(new ContextEvent(this, ContextType.OBJECT_DROP, null));
super.actionDrop(tangibleObject); super.actionDrop(tangibleObject);
} }
// ---------------------------------------------------------------------------
/** /**
* {@inheritDoc}<br> * {@inheritDoc}<br>
* <br> * <br>
* *
* The method notifies all global state listeners of the moving. * The method notifies all global state listeners of the moving.
*/ */
// ---------------------------------------------------------------------------
@Override @Override
public void actionMove(TangibleObject tangibleObject) { public void actionMove(TangibleObject tangibleObject) {
notifyStateListeners(new ContextEvent(this, ContextType.OBJECT_MOVE, null)); notifyStateListeners(new ContextEvent(this, ContextType.OBJECT_MOVE, null));
super.actionMove(tangibleObject); super.actionMove(