Commit c6df8cd0 authored by Nico Mack's avatar Nico Mack

Fixed cause for ConcurrentModificationException introduced by

ModalWidget
parent 5687b8cc
......@@ -38,6 +38,7 @@ import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Area;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
......@@ -156,6 +157,8 @@ public class BaseWidget implements Touchable {
/**
* Method used to keep the conona's positions aligned with the base of the widget.
*
* @param handleID
*
* @pre <code>positions.contains(handleID);</code>
* @post <code>forAll coronas.get(handleID) as corona : corona.getCentre().equals(positions.get(handleID);</code>
*/
......@@ -299,8 +302,6 @@ public class BaseWidget implements Touchable {
}
}
// ---------------------------------------------------------------------------
/**
* Draws a the visual feedback for any widget. The method will iterate through all coronas and call
......@@ -315,15 +316,15 @@ public class BaseWidget implements Touchable {
public void paint(Graphics2D canvas) {
clippingRegion.reset();
// Create a snapshot of the corona multimap in order to avoid potential
// ConcurrentModificationExceptions caused by modifications to the corona
// multimap in other threads
Corona[] snapshot = coronas.values().toArray(new Corona[0]);
for (Corona corona : snapshot) {
if ((corona != null) && corona.isInvalidated()) {
corona.paint(canvas);
clippingRegion.add(new Area(corona.getClippingRegion().getBounds()));
corona.validate();
Collection<Corona> snapshot = coronas.values();
synchronized (coronas) {
for (Corona corona : snapshot) {
if ((corona != null) && corona.isInvalidated()) {
corona.paint(canvas);
clippingRegion.add(new Area(corona.getClippingRegion().getBounds()));
corona.validate();
}
}
}
}
......@@ -518,7 +519,6 @@ public class BaseWidget implements Touchable {
}
this.isTouchable = Boolean.valueOf(touchableCoronaFound);
}
return isTouchable;
}
......
......@@ -25,7 +25,6 @@ import com.google.common.collect.Multimap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
......@@ -142,7 +141,7 @@ public class ModalWidget extends TetherableWidget {
*/
// ---------------------------------------------------------------------------
private boolean activateBundle(String nameOfBundle) {
private synchronized boolean activateBundle(String nameOfBundle) {
boolean activated = this.addToActiveBundles(nameOfBundle);
if (activated) {
Collection<CoronaBundle> bundles = coronaBundles.get(nameOfBundle);
......@@ -153,7 +152,9 @@ public class ModalWidget extends TetherableWidget {
}
Multimap<Integer, Corona> bundledCoronas = bundle.getCoronas();
this.coronas.putAll(bundledCoronas);
synchronized (this.coronas) {
this.coronas.putAll(bundledCoronas);
}
if (this.onStage) {
bundledCoronas.values().forEach(corona -> corona.setActive(true));
}
......@@ -173,13 +174,15 @@ public class ModalWidget extends TetherableWidget {
*/
// ---------------------------------------------------------------------------
private boolean deactivateBundle(String nameOfBundle) {
private synchronized boolean deactivateBundle(String nameOfBundle) {
boolean deactivated = this.removeFromActiveBundles(nameOfBundle);
if (deactivated) {
Collection<CoronaBundle> bundles = coronaBundles.get(nameOfBundle);
for (CoronaBundle bundle : bundles) {
Multimap<Integer, Corona> bundledCoronas = bundle.getCoronas();
this.coronas.removeAll(bundledCoronas);
synchronized (this.coronas) {
this.coronas.removeAll(bundledCoronas);
}
bundledCoronas.values().forEach(corona -> corona.setActive(false));
}
}
......@@ -222,45 +225,8 @@ public class ModalWidget extends TetherableWidget {
boolean stateChanged = false;
stateChanged = (activateIt) ? this.activateBundle(bundle) : this.deactivateBundle(bundle);
return stateChanged;
}
// ---------------------------------------------------------------------------
/**
* Draws a the visual feedback for any widget. The method will iterate through all coronas and call
* their <code>paint()</code> method. The consistency of their position is ensured due to the
* <code>actionMove(TUIObject)</code> method issuing a call to <code>
* updateCoronas(long)</code>.
*
* @param canvas
* The Graphics2D instance to draw on.
*/
// ---------------------------------------------------------------------------
@Override
public void paint(Graphics2D canvas) {
super.paint(canvas);
boolean isTethered = this.isTethered();
this.activateBundle("Yes/No", isTethered);
// for (String activeBundle : activeBundles) {
// Collection<CoronaBundle> bundles = coronaBundles.get(activeBundle);
// for (CoronaBundle bundle : bundles) {
// List<Corona> bundledCoronas = bundle.getCoronas();
// for (Corona corona : bundledCoronas) {
// if ((corona != null) && corona.isInvalidated()) {
// corona.paint(canvas);
// clippingRegion.add(new Area(corona.getClippingRegion().getBounds()));
// corona.validate();
// }
// }
// }
// }
}
// ---------------------------------------------------------------------------
// ***************************************************************************
// * End of Class *
......
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