Commit a644e451 authored by Nico Mack's avatar Nico Mack

Added baseUrl property for HtmlBox corona

Added lower and upper range properties to ForceGenerator interface
Implement rotateWithTether functionality
parent 5a0a99db
......@@ -7,6 +7,7 @@ ASSET_ELEMENT=asset
ASSIGNABLE_NODE=assignable
BACKGROUND_COLOUR_NODE=backgroundColour
BASE_VALUE_NODE=baseValue
BASE_URL_NODE=baseUrl
BEGIN_NODE=begin
BEZEL_COLOUR_ELEMENT=bezelColour
BLOBS_NODE=blobs
......
......@@ -79,9 +79,6 @@ public class Stage extends JComponent {
protected volatile ConcurrentHashMap<Integer, BaseWidget> objects = new ConcurrentHashMap<>();
// protected transient volatile Multimap<String, Content> contents = HashMultimap.create();
// ***************************************************************************
// * Constants *
// ***************************************************************************
......@@ -240,13 +237,15 @@ public class Stage extends JComponent {
timeline.playLoop(RepeatBehavior.LOOP);
}
/**
* @param contentManager
*/
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Class Body *
// ***************************************************************************
// ---------------------------------------------------------------------------
/**
* @param contentManager
*/
// ---------------------------------------------------------------------------
public void setContentManager(TangibleContentManager contentManager) {
this.contentManager = contentManager;
......
......@@ -174,7 +174,12 @@ public abstract class Marker implements Positionable {
* @param isActive
*/
public void setActive(boolean isActive) {
coronas.values().forEach(corona -> corona.setActive(isActive));
if (isActive) {
coronas.values().forEach(corona -> corona.onTable());
} else {
coronas.values().forEach(corona -> corona.setActive(false));
}
this.active = isActive;
}
......
......@@ -42,6 +42,7 @@ public class Externalization extends NLS {
public static String ASSIGNABLE_NODE;
public static String BACKGROUND_COLOUR_NODE;
public static String BASE_VALUE_NODE;
public static String BASE_URL_NODE;
public static String BEGIN_NODE;
public static String BEZEL_COLOUR_ELEMENT;
public static String BLOBS_NODE;
......
......@@ -35,6 +35,14 @@ public class Body {
private volatile Vector2D acceleration;
private volatile boolean immobile;
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constants *
// ***************************************************************************
// ---------------------------------------------------------------------------
private static final Vector2D ZERO = new Vector2D(0, 0);
// ---------------------------------------------------------------------------
// ***************************************************************************
// * Constructor(s) *
......@@ -65,7 +73,7 @@ public class Body {
// ---------------------------------------------------------------------------
public void applyForce(Vector2D force) {
this.acceleration = this.acceleration.add(force.divideBy(this.mass));
this.acceleration = (this.isImmobile()) ? ZERO : this.acceleration.add(force.divideBy(this.mass));
}
// ---------------------------------------------------------------------------
......@@ -170,12 +178,12 @@ public class Body {
// ---------------------------------------------------------------------------
/**
* @param immobilizeIt
* @return
*/
// ---------------------------------------------------------------------------
public boolean isImmobile() {
return false; // this.immobile;
return this.immobile;
}
// ---------------------------------------------------------------------------
......
......@@ -163,7 +163,7 @@ public class BaseWidget implements Positionable, Touchable {
Point centre = this.getPosition(entry.getKey());
if (this.isActive())
entry.getValue().setHandleCentre(centre);
entry.getValue().setActive(true);
entry.getValue().onTable();
added |= this.coronas.put(entry.getKey(), entry.getValue());
}
}
......@@ -480,6 +480,22 @@ public class BaseWidget implements Positionable, Touchable {
return position;
}
// ---------------------------------------------------------------------------
/**
* Method for explicitely setting 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 set the position.
* @param position
* The {@link Point} holding the new position
*/
// ---------------------------------------------------------------------------
public void setPosition(int handleId, Point position) {
positions.put(handleId, position);
}
// ---------------------------------------------------------------------------
/**
* Method used for returning the main handle, i.e. the handle with the lowest ID.
......
......@@ -22,6 +22,7 @@
package lu.list.itis.dkd.tui.widget;
import lu.list.itis.dkd.tui.adapter.TangibleObject;
import lu.list.itis.dkd.tui.utility.CameraCoordinates;
import lu.list.itis.dkd.tui.utility.Point;
import lu.list.itis.dkd.tui.utility.ScreenCoordinates;
import lu.list.itis.dkd.tui.widget.builder.BaseTetherableBuilder;
......@@ -52,6 +53,7 @@ public abstract class TetherableWidget extends PointingWidget implements Tethera
private double tetheringDistance;
private boolean draggable;
private boolean rotatesWithTether;
private float angleOffset;
private TetherManager tetherManager;
......@@ -307,7 +309,14 @@ public abstract class TetherableWidget extends PointingWidget implements Tethera
@Override
public void actionMove(TangibleObject tangibleObject) {
super.actionMove(tangibleObject);
TangibleObject clone = tangibleObject;
if (this.isTethered() && this.rotatesWithTether) {
clone = tangibleObject.constrainedClone(new Point(tangibleObject.getX(), tangibleObject.getY(), tangibleObject.getAngle() + angleOffset, CameraCoordinates.class));
}
super.actionMove(clone);
StateManager manager = objectStates.get(tangibleObject.getObjectId());
if (manager.isMoving() || manager.isRotating()) {
......@@ -316,6 +325,8 @@ public abstract class TetherableWidget extends PointingWidget implements Tethera
Point origin = this.getPointingLocation(position);
this.tetherManager.move(origin);
angleOffset = this.getTetherOrigin().getAngle();
}
}
......
......@@ -37,6 +37,7 @@ import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.net.URL;
import java.util.List;
import javax.swing.JEditorPane;
......@@ -56,8 +57,9 @@ import javax.swing.text.html.StyleSheet;
// ***************************************************************************
@NonNullByDefault
public class HtmlBox extends FadingCorona implements InformationReceiver<String> {
public class HtmlBox extends SelectableCorona implements InformationReceiver<String> {
protected String htmlContent;
protected URL baseUrl;
protected Color fillColour;
protected Color strokeColour;
protected int strokeWidth;
......@@ -96,6 +98,7 @@ public class HtmlBox extends FadingCorona implements InformationReceiver<String>
super(builder);
htmlContent = builder.htmlContent;
baseUrl = builder.baseUrl;
shape = builder.shape;
fillColour = builder.fillColour;
strokeColour = builder.strokeColour;
......@@ -120,6 +123,7 @@ public class HtmlBox extends FadingCorona implements InformationReceiver<String>
super(original);
htmlContent = original.htmlContent;
baseUrl = original.baseUrl;
shape = original.shape;
fillColour = original.fillColour;
strokeColour = original.strokeColour;
......@@ -207,6 +211,10 @@ public class HtmlBox extends FadingCorona implements InformationReceiver<String>
@Override
public void setInformation(String information) {
HTMLDocument html = (HTMLDocument) htmlEditor.createDefaultDocument();
if (baseUrl != null) {
html.setBase(baseUrl);
}
editor.setDocument(html);
editor.setText(information);
......
......@@ -40,6 +40,7 @@ import java.awt.Color;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
......@@ -57,9 +58,10 @@ import java.util.List;
// * Class Definition and Members *
// ***************************************************************************
public abstract class BaseHtmlBoxBuilder<B extends BaseHtmlBoxBuilder<B>> extends BaseFadingCoronaBuilder<B> {
public abstract class BaseHtmlBoxBuilder<B extends BaseHtmlBoxBuilder<B>> extends BaseSelectableCoronaBuilder<B> {
public String htmlContent;
public URL baseUrl;
public Color fillColour;
public Color strokeColour;
public int strokeWidth;
......@@ -150,6 +152,16 @@ public abstract class BaseHtmlBoxBuilder<B extends BaseHtmlBoxBuilder<B>> extend
}
}
String url = BootstrappingUtils.getContentAsString(rootElement, Externalization.BASE_URL_NODE, BootstrappingUtils.OPTIONAL, Externalization.EMPTY_STRING, context);
if (!Strings.isNullOrEmpty(url)) {
try {
File urlFile = new File(url);
this.baseUrl = urlFile.toURI().toURL();
} catch (IOException e) {
throw new BuildException(StringUtils.build("Failed to set base URL to {}", url)); //$NON-NLS-1$
}
}
fillColour = BootstrappingUtils.getContentAsColour(rootElement, Externalization.FILL_COLOUR_ELEMENT, BootstrappingUtils.OPTIONAL, Color.WHITE, context);
strokeColour = BootstrappingUtils.getContentAsColour(rootElement, Externalization.STROKE_COLOUR_ELEMENT, BootstrappingUtils.OPTIONAL, null, context);
strokeWidth = BootstrappingUtils.getContentAsInteger(rootElement, Externalization.STROKE_WIDTH_NODE, BootstrappingUtils.OPTIONAL, 1, context);
......
......@@ -31,7 +31,9 @@ public interface ForceGenerator {
public boolean isRepelling(ForceReactive potential);
public double getRange();
public double getShortRange();
public double getLongRange();
public double getMagnitude();
......
......@@ -50,6 +50,8 @@ public class ForceManager {
// * Constants *
// ***************************************************************************
private static final double HYSTERESIS = 5;
private static final Logger logger = LoggerFactory.getLogger(ForceManager.class.getSimpleName());
// ---------------------------------------------------------------------------
......@@ -73,14 +75,26 @@ public class ForceManager {
// ***************************************************************************
// ---------------------------------------------------------------------------
private Vector2D impart(Point distance, double magnitude, double range, boolean isRepelling) {
private Vector2D repell(Point distance, double magnitude, double longRange) {
Vector2D force;
double radius = distance.magnitude();
radius = (longRange - radius) / longRange;
Vector2D direction = new Vector2D(distance.x, distance.y).normalize();
double exertedForce = -magnitude * (radius * radius);
force = direction.multiplyBy(exertedForce);
return force;
}
// ---------------------------------------------------------------------------
private Vector2D attract(Point distance, double magnitude, double shortRange, double longRange) {
Vector2D force;
double effective = (isRepelling) ? -magnitude : magnitude;
double radius = distance.magnitude();
radius = (range - radius) / range;
radius = (radius - shortRange) / (longRange - shortRange);
Vector2D direction = new Vector2D(distance.x, distance.y).normalize();
double exertedForce = effective * (radius * radius);
double exertedForce = magnitude * (radius * radius);
force = direction.multiplyBy(exertedForce);
return force;
}
......@@ -138,7 +152,8 @@ public class ForceManager {
// ---------------------------------------------------------------------------
public void move(Point newPosition) {
double range = this.generator.getRange();
double shortRange = this.generator.getShortRange();
double longRange = this.generator.getLongRange();
double magnitude = this.generator.getMagnitude();
Point origin = newPosition.toCoordinates(ScreenCoordinates.class);
......@@ -146,11 +161,15 @@ public class ForceManager {
if (subject.getPosition() == null)
continue;
boolean isRepelling = this.generator.isRepelling(subject);
Point target = subject.getPosition().clone().toCoordinates(ScreenCoordinates.class);
Point distance = origin.clone().subtract(target, false);
double radius = distance.magnitude();
if (distance.magnitude() < range) {
subject.applyForce(this.impart(distance, magnitude, range, this.generator.isRepelling(subject)));
if (isRepelling && (radius < longRange)) {
subject.applyForce(this.repell(distance, magnitude, longRange));
} else if (!isRepelling && (radius > shortRange) && (radius < longRange)) {
subject.applyForce(this.attract(distance, magnitude, shortRange, longRange));
}
}
}
......
......@@ -21,7 +21,9 @@
package lu.list.itis.dkd.tui.widget.tether;
import lu.list.itis.dkd.tui.utility.AngleUtils;
import lu.list.itis.dkd.tui.utility.Point;
import lu.list.itis.dkd.tui.utility.PolarCoordinateHelper;
import lu.list.itis.dkd.tui.utility.ScreenCoordinates;
import lu.list.itis.dkd.tui.widget.tether.listener.TetherEvent;
import lu.list.itis.dkd.tui.widget.tether.listener.TetherEventSource;
......@@ -35,6 +37,7 @@ import org.slf4j.LoggerFactory;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
......@@ -68,7 +71,7 @@ public class TetherManager {
// * Constants *
// ***************************************************************************
private static final Logger logger = LoggerFactory.getLogger(TetherManager.class.getSimpleName());
private static final Logger LOGGER = LoggerFactory.getLogger(TetherManager.class.getSimpleName());
private static final int HYSTERESIS = 5;
......@@ -483,7 +486,7 @@ public class TetherManager {
if (propagate)
potential.addPotentialTether(this.tetherable, tether, false);
} else {
logger.warn("Attempt to add an already known tetherable as potential tether!"); //$NON-NLS-1$
LOGGER.warn("Attempt to add an already known tetherable as potential tether!"); //$NON-NLS-1$
}
}
......@@ -520,10 +523,10 @@ public class TetherManager {
candidate.tetherWith(this.tetherable);
}
} else {
logger.warn("Attempt to tether with an already tethered object!"); //$NON-NLS-1$
LOGGER.warn("Attempt to tether with an already tethered object!"); //$NON-NLS-1$
}
} else {
logger.warn("Specified tetherable is not a potential tether! Won't tether!"); //$NON-NLS-1$
LOGGER.warn("Specified tetherable is not a potential tether! Won't tether!"); //$NON-NLS-1$
}
}
......@@ -546,7 +549,7 @@ public class TetherManager {
tethered.separateFrom(this.tetherable);
}
} else {
logger.warn("Not tethered to specified tetherable!"); //$NON-NLS-1$
LOGGER.warn("Not tethered to specified tetherable!"); //$NON-NLS-1$
}
}
......@@ -615,9 +618,9 @@ public class TetherManager {
public void updateTethers(Graphics2D canvas) {
Tether tether;
for (Tetherable tethered : currentlyTethered) {
tether = this.potentialTethers.get(tethered);
Iterator<Tetherable> tetherIterator = currentlyTethered.iterator();
while (tetherIterator.hasNext()) {
tether = this.potentialTethers.get(tetherIterator.next());
tether.paint(canvas);
}
}
......@@ -637,15 +640,18 @@ public class TetherManager {
public List<Tether> move(Point newPosition) {
List<Tether> draggedTethers = null;
// Point beforeMove = this.tetherable.getTetherOrigin().toScreenCoordinates();
Point tetherOrigin = newPosition.toScreenCoordinates();
this.tetherable.setTetherOrigin(newPosition);
double shortestTether = this.shortestTether();
double tetheringDistance = this.tetherable.getTetheringDistance();
double angle = 0;
int tetherCount = 0;
boolean isTethered;
for (Entry<Tetherable, Tether> entry : potentialTethers.entrySet()) {
isTethered = false;
Tetherable potential = entry.getKey();
if (!potential.isActive())
......@@ -661,16 +667,25 @@ public class TetherManager {
if (!alreadyTetheredWith) {
if ((distance <= tetheringDistance - HYSTERESIS) && (distance < shortestTether)) {
this.tetherable.tetherWith(potential);
isTethered = true;
}
} else if (distance >= tetheringDistance + HYSTERESIS) {
if (!potential.isDraggable()) {
this.tetherable.separateFrom(potential);
} else {
// this.drag (beforeMove, tetherOrigin, tetherEnding, potential,
// tetheringDistance);
// TODO implement dragging
}
} else {
isTethered = true;
}
if (isTethered && this.tetherable.rotatesWithTether()) {
Point lineOfSight = PolarCoordinateHelper.carthesianToPolar(tetherOrigin, tetherEnding);
angle += lineOfSight.getAngle();
tetherCount++;
}
if (alreadyTetheredWith) {
Tether tether = entry.getValue();
tether.setOrigin(tetherOrigin);
......@@ -679,6 +694,11 @@ public class TetherManager {
}
if (this.tetherable.rotatesWithTether() && tetherCount > 0) {
double averageAngle = (angle / tetherCount);
this.tetherable.getTetherOrigin().setAngle((float) AngleUtils.moduloTwoPi(averageAngle));
}
return draggedTethers;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment