diff --git a/Mage.Client/src/main/java/mage/client/util/gui/ArrowBuilder.java b/Mage.Client/src/main/java/mage/client/util/gui/ArrowBuilder.java index be0d4329f2..4a2b66979e 100644 --- a/Mage.Client/src/main/java/mage/client/util/gui/ArrowBuilder.java +++ b/Mage.Client/src/main/java/mage/client/util/gui/ArrowBuilder.java @@ -1,7 +1,5 @@ package mage.client.util.gui; -import com.google.common.collect.MapMaker; - import javax.swing.*; import java.awt.*; import java.util.*; @@ -14,31 +12,37 @@ import java.util.List; */ public class ArrowBuilder { - private static final ArrowBuilder instance; + private static ArrowBuilder instance; static { instance = new ArrowBuilder(); } - /** - * Stores arrow panels per game - */ - private final Map arrowPanels = new HashMap<>(); - private final Map>> map = new MapMaker().weakKeys().weakValues().makeMap(); - /** - * The top panel where arrow panels are added to. - */ - private JPanel arrowsManagerPanel; - private int currentWidth; - private int currentHeight; - public static ArrowBuilder getBuilder() { return instance; } + /** + * The top panel where arrow panels are added to. + */ + private JPanel arrowsManagerPanel; + + /** + * Stores arrow panels per game + */ + private final Map arrowPanels = new HashMap(); + + private final Map>> map = new HashMap>>(); + + private int currentWidth; + private int currentHeight; + + public enum Type { + PAIRED, SOURCE, TARGET, COMBAT, ENCHANT_PLAYERS; + } + /** * Get the panel where all arrows are being drawn. - * * @return */ public JPanel getArrowsManagerPanel() { @@ -69,6 +73,17 @@ public class ArrowBuilder { return arrowPanels.get(gameId); } + /** + * Not synchronized method for arrows panel. + * Doesn't create JPanel in case the panel doesn't exist. + * Works faster. + * + * @return + */ + /*public JPanel getPanelRef() { + return arrowsManagerPanel; + }*/ + /** * Adds new arrow. * @@ -85,25 +100,26 @@ public class ArrowBuilder { arrow.setColor(color); arrow.setArrowLocation(startX, startY, endX, endY); arrow.setBounds(0, 0, Math.max(startX, endX) + 40, Math.max(startY, endY) + 30); // 30 is offset for arrow heads (being cut otherwise) - p.add(arrow); - Map> innerMap = map.computeIfAbsent(gameId, k -> new HashMap<>()); - List arrows = innerMap.computeIfAbsent(type, k -> new ArrayList<>()); - arrows.add(arrow); + + synchronized (map) { + p.add(arrow); + Map> innerMap = map.get(gameId); + if (innerMap == null) { + innerMap = new HashMap>(); + map.put(gameId, innerMap); + } + java.util.List arrows = innerMap.get(type); + if (arrows == null) { + arrows = new ArrayList(); + innerMap.put(type, arrows); + } + arrows.add(arrow); + } + p.revalidate(); p.repaint(); } - /** - * Not synchronized method for arrows panel. - * Doesn't create JPanel in case the panel doesn't exist. - * Works faster. - * - * @return - */ - /*public JPanel getPanelRef() { - return arrowsManagerPanel; - }*/ - /** * Removes all arrows from the screen. */ @@ -111,13 +127,15 @@ public class ArrowBuilder { if (map.containsKey(gameId)) { Map> innerMap = map.get(gameId); JPanel p = getArrowsPanel(gameId); - if (p != null && p.getComponentCount() > 0) { - p.removeAll(); - p.revalidate(); - p.repaint(); + synchronized (map) { + if (p != null && p.getComponentCount() > 0) { + p.removeAll(); + p.revalidate(); + p.repaint(); + } + innerMap.clear(); + map.remove(gameId); } - innerMap.clear(); - map.remove(gameId); } } @@ -125,12 +143,14 @@ public class ArrowBuilder { if (map.containsKey(gameId)) { Map> innerMap = map.get(gameId); java.util.List arrows = innerMap.get(type); - if (arrows != null && !arrows.isEmpty()) { + if (arrows != null && arrows.size() > 0) { JPanel p = getArrowsPanel(gameId); - for (Arrow arrow : arrows) { - p.remove(arrow); + synchronized (map) { + for (Arrow arrow : arrows) { + p.remove(arrow); + } + innerMap.put(type, new ArrayList()); } - innerMap.put(type, new ArrayList<>()); p.revalidate(); p.repaint(); } @@ -161,8 +181,4 @@ public class ArrowBuilder { } } - public enum Type { - PAIRED, SOURCE, TARGET, COMBAT, ENCHANT_PLAYERS - } - }