summaryrefslogtreecommitdiffstats
path: root/src/jrummikub/view/impl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jrummikub/view/impl')
-rw-r--r--src/jrummikub/view/impl/AbstractStonePanel.java234
-rw-r--r--src/jrummikub/view/impl/StoneCollectionPanel.java132
-rw-r--r--src/jrummikub/view/impl/TablePanel.java350
3 files changed, 383 insertions, 333 deletions
diff --git a/src/jrummikub/view/impl/AbstractStonePanel.java b/src/jrummikub/view/impl/AbstractStonePanel.java
index a19ea1f..855b40a 100644
--- a/src/jrummikub/view/impl/AbstractStonePanel.java
+++ b/src/jrummikub/view/impl/AbstractStonePanel.java
@@ -21,117 +21,127 @@ import jrummikub.view.IStonePanel;
*/
@SuppressWarnings("serial")
abstract class AbstractStonePanel extends JPanel implements IStonePanel,
- IClickable {
- private StonePainter stonePainter;
-
- private Event1<Position> clickEvent = new Event1<Position>();
- private Event2<Stone, Boolean> stoneClickEvent = new Event2<Stone, Boolean>();
- private Event2<Stone, Boolean> rangeClickEvent = new Event2<Stone, Boolean>();
- private Event2<Stone, Boolean> setClickEvent = new Event2<Stone, Boolean>();
-
- private Map<Stone, Position> stones = Collections.emptyMap();
-
- /**
- * @return the stone painter
- */
- protected StonePainter getStonePainter() {
- return stonePainter;
- }
-
- /**
- * Create a new StonePanel with default scale factor
- */
- public AbstractStonePanel() {
- this(1);
- }
-
- /**
- * Create a new StonePanel with a given scale factor
- *
- * @param scale
- * the grid scale
- */
- public AbstractStonePanel(float scale) {
- super(true); // Set double buffered
-
- stonePainter = new StonePainter(scale);
-
- addMouseListener(new MouseAdapter() {
- @Override
- public void mouseClicked(MouseEvent e) {
- Insets insets = getInsets();
- Position pos = stonePainter.calculatePosition(e.getX() - insets.left,
- e.getY() - insets.top);
- Stone stone = getStoneAt(pos);
-
- if (stone == null) {
- clickEvent.emit(pos);
- return;
- }
-
- Event2<Stone, Boolean> event = stoneClickEvent;
-
- if (e.isShiftDown())
- event = rangeClickEvent;
- else if (e.getClickCount() >= 2)
- event = setClickEvent;
-
- event.emit(stone, e.isControlDown());
- }
- });
- }
-
- private Stone getStoneAt(Position pos) {
- for (Map.Entry<Stone, Position> entry : stones.entrySet()) {
- Stone stone = entry.getKey();
- Position p = entry.getValue();
- Rectangle2D rect = new Rectangle2D.Float(p.getX(), p.getY(),
- stone.getWidth(), stone.getHeight());
-
- if (rect.contains(pos.getX(), pos.getY()))
- return stone;
- }
-
- return null;
- }
-
- /**
- * Sets the list of stones that can be clicked on
- *
- * @param stones
- * the stones and positions
- */
- protected void setStones(Map<Stone, Position> stones) {
- this.stones = stones;
- }
-
- /**
- * Returns the list of stones and positions currently set
- *
- * @return the stones
- */
- protected Map<Stone, Position> getStones() {
- return stones;
- }
-
- @Override
- public Event1<Position> getClickEvent() {
- return clickEvent;
- }
-
- @Override
- public Event2<Stone, Boolean> getStoneClickEvent() {
- return stoneClickEvent;
- }
-
- @Override
- public Event2<Stone, Boolean> getRangeClickEvent() {
- return rangeClickEvent;
- }
-
- @Override
- public Event2<Stone, Boolean> getSetClickEvent() {
- return setClickEvent;
- }
+ IClickable {
+ private StonePainter stonePainter;
+
+ private Event1<Position> clickEvent = new Event1<Position>();
+ private Event2<Stone, Boolean> stoneClickEvent = new Event2<Stone, Boolean>();
+ private Event2<Stone, Boolean> rangeClickEvent = new Event2<Stone, Boolean>();
+ private Event2<Stone, Boolean> setClickEvent = new Event2<Stone, Boolean>();
+
+ private Map<Stone, Position> stones = Collections.emptyMap();
+
+ /**
+ * @return the stone painter
+ */
+ protected StonePainter getStonePainter() {
+ return stonePainter;
+ }
+
+ /**
+ * Create a new StonePanel with default scale factor
+ */
+ public AbstractStonePanel() {
+ this(1);
+ }
+
+ /**
+ * Create a new StonePanel with a given scale factor
+ *
+ * @param scale
+ * the grid scale
+ */
+ public AbstractStonePanel(float scale) {
+ super(true); // Set double buffered
+
+ stonePainter = new StonePainter(scale);
+
+ addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ Insets insets = getInsets();
+ Position pos = stonePainter.calculatePosition(e.getX() - insets.left,
+ e.getY() - insets.top);
+ Stone stone = getStoneAt(pos);
+
+ if (stone == null) {
+ if (!handleOtherClickEvent(pos))
+ clickEvent.emit(pos);
+
+ return;
+ }
+
+ Event2<Stone, Boolean> event = stoneClickEvent;
+
+ if (e.isShiftDown())
+ event = rangeClickEvent;
+ else if (e.getClickCount() >= 2)
+ event = setClickEvent;
+
+ event.emit(stone, e.isControlDown());
+ }
+ });
+ }
+
+ /*
+ * *Overwrite this method* to signal if special zone was clicked
+ *
+ * @return special zone clicked
+ */
+ protected boolean handleOtherClickEvent(Position pos) {
+ return false;
+ }
+
+ private Stone getStoneAt(Position pos) {
+ for (Map.Entry<Stone, Position> entry : stones.entrySet()) {
+ Stone stone = entry.getKey();
+ Position p = entry.getValue();
+ Rectangle2D rect = new Rectangle2D.Float(p.getX(), p.getY(), 1, 1);
+
+ if (rect.contains(pos.getX(), pos.getY()))
+ return stone;
+ }
+
+ return null;
+ }
+
+ /**
+ * Sets the list of stones that can be clicked on
+ *
+ * @param stones
+ * the stones and positions
+ */
+ protected void setStones(Map<Stone, Position> stones) {
+ this.stones = stones;
+ }
+
+ /**
+ * Returns the list of stones and positions currently set
+ *
+ * @return the stones
+ */
+ protected Map<Stone, Position> getStones() {
+ return stones;
+ }
+
+ @Override
+ public Event1<Position> getClickEvent() {
+ return clickEvent;
+ }
+
+ @Override
+ public Event2<Stone, Boolean> getStoneClickEvent() {
+ return stoneClickEvent;
+ }
+
+ @Override
+ public Event2<Stone, Boolean> getRangeClickEvent() {
+ return rangeClickEvent;
+ }
+
+ @Override
+ public Event2<Stone, Boolean> getSetClickEvent() {
+ return setClickEvent;
+ }
}
diff --git a/src/jrummikub/view/impl/StoneCollectionPanel.java b/src/jrummikub/view/impl/StoneCollectionPanel.java
index 8729170..9548b3b 100644
--- a/src/jrummikub/view/impl/StoneCollectionPanel.java
+++ b/src/jrummikub/view/impl/StoneCollectionPanel.java
@@ -20,70 +20,70 @@ import jrummikub.view.IStoneCollectionPanel;
*/
@SuppressWarnings("serial")
class StoneCollectionPanel extends AbstractStonePanel implements
- IStoneCollectionPanel {
- private final static int INSET = 7;
- private final static float STONE_SCALE = 1.1f;
-
- private Collection<Stone> selectedStones = Collections.emptyList();
-
- /**
- * Creates a new StoneCollection instance
- */
- StoneCollectionPanel() {
- super(STONE_SCALE);
-
- setOpaque(false);
- setVisible(false);
- setBorder(new EmptyBorder(INSET, INSET, INSET, INSET));
- }
-
- /**
- * Sets the stones to be shown in the collection
- *
- * @param selectedStones
- * the selected stones
- */
- void setSelectedStones(Collection<Stone> selectedStones) {
- this.selectedStones = selectedStones;
-
- Map<Stone, Position> stones = new HashMap<Stone, Position>();
- float x = 0;
-
- for (Stone stone : selectedStones) {
- stones.put(stone, new Position(x, 0));
- x += stone.getWidth();
- }
-
- setStones(stones);
-
- if (selectedStones.isEmpty()) {
- setVisible(false);
- } else {
- setSize(getStonePainter().getStoneWidth() * selectedStones.size() + 2
- * INSET, getStonePainter().getStoneHeight() + 2 * INSET);
- setVisible(true);
-
- repaint();
- }
- }
-
- @Override
- public void paintComponent(Graphics g1) {
- Insets insets = getInsets();
- int x = insets.left, y = insets.top, width = getWidth() - insets.left
- - insets.right, height = getHeight() - insets.top - insets.bottom;
- Graphics2D g = (Graphics2D) g1.create(x, y, width, height);
-
- if (!selectedStones.isEmpty()) {
- g1.setColor(new Color(0, 0, 0, 0.25f));
- g1.fillRoundRect(0, 0, getWidth(), getHeight(), INSET, INSET);
-
- float xpos = 0;
-
- for (Stone stone : selectedStones) {
- getStonePainter().paintStone(g, stone, new Position(xpos, 0), false);
- xpos++;
- }
- }
- }
+ IStoneCollectionPanel {
+ private final static int INSET = 7;
+ private final static float STONE_SCALE = 1.1f;
+
+ private Collection<Stone> selectedStones = Collections.emptyList();
+
+ /**
+ * Creates a new StoneCollection instance
+ */
+ StoneCollectionPanel() {
+ super(STONE_SCALE);
+
+ setOpaque(false);
+ setVisible(false);
+ setBorder(new EmptyBorder(INSET, INSET, INSET, INSET));
+ }
+
+ /**
+ * Sets the stones to be shown in the collection
+ *
+ * @param selectedStones
+ * the selected stones
+ */
+ void setSelectedStones(Collection<Stone> selectedStones) {
+ this.selectedStones = selectedStones;
+
+ Map<Stone, Position> stones = new HashMap<Stone, Position>();
+ float x = 0;
+
+ for (Stone stone : selectedStones) {
+ stones.put(stone, new Position(x, 0));
+ x++;
+ }
+
+ setStones(stones);
+
+ if (selectedStones.isEmpty()) {
+ setVisible(false);
+ } else {
+ setSize(getStonePainter().getStoneWidth() * selectedStones.size() + 2
+ * INSET, getStonePainter().getStoneHeight() + 2 * INSET);
+ setVisible(true);
+
+ repaint();
+ }
+ }
+
+ @Override
+ public void paintComponent(Graphics g1) {
+ Insets insets = getInsets();
+ int x = insets.left, y = insets.top, width = getWidth() - insets.left
+ - insets.right, height = getHeight() - insets.top - insets.bottom;
+ Graphics2D g = (Graphics2D) g1.create(x, y, width, height);
+
+ if (!selectedStones.isEmpty()) {
+ g1.setColor(new Color(0, 0, 0, 0.25f));
+ g1.fillRoundRect(0, 0, getWidth(), getHeight(), INSET, INSET);
+
+ float xpos = 0;
+
+ for (Stone stone : selectedStones) {
+ getStonePainter().paintStone(g, stone, new Position(xpos, 0), false);
+ xpos++;
+ }
+ }
+ }
}
diff --git a/src/jrummikub/view/impl/TablePanel.java b/src/jrummikub/view/impl/TablePanel.java
index 3eb33d8..6a91b41 100644
--- a/src/jrummikub/view/impl/TablePanel.java
+++ b/src/jrummikub/view/impl/TablePanel.java
@@ -8,6 +8,7 @@ import java.awt.RenderingHints;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
+import java.awt.geom.Rectangle2D;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -19,6 +20,7 @@ import javax.swing.JLabel;
import jrummikub.model.Position;
import jrummikub.model.Stone;
import jrummikub.model.StoneSet;
+import jrummikub.util.Event1;
import jrummikub.view.IStoneCollectionPanel;
import jrummikub.view.ITablePanel;
@@ -27,159 +29,197 @@ import jrummikub.view.ITablePanel;
*/
@SuppressWarnings("serial")
class TablePanel extends AbstractStonePanel implements ITablePanel {
- private final static ImageIcon background = new ImageIcon(
- HandPanel.class.getResource("/jrummikub/resource/felt.png"));
-
- private final static float DEFAULT_SCALE = 1;
- private final int COLLECTION_GAP = 5;
-
- private JLabel leftPlayerLabel, topPlayerLabel, rightPlayerLabel;
- private StoneCollectionPanel stoneCollection;
-
- private Map<StoneSet, Position> stoneSets = Collections.emptyMap();
- private Collection<Stone> selectedStones = Collections.emptyList();
-
- @Override
- public void setLeftPlayerName(String playerName) {
- leftPlayerLabel.setText(playerName);
- }
-
- @Override
- public void setTopPlayerName(String playerName) {
- topPlayerLabel.setText(playerName);
- }
-
- @Override
- public void setRightPlayerName(String playerName) {
- rightPlayerLabel.setText(playerName);
- }
-
- @Override
- public void setStoneSets(Map<StoneSet, Position> stoneSets) {
- Map<Stone, Position> stones = new HashMap<Stone, Position>();
-
- for (Map.Entry<StoneSet, Position> entry : stoneSets.entrySet()) {
- float x = entry.getValue().getX(), y = entry.getValue().getY();
-
- for (Stone stone : entry.getKey()) {
- stones.put(stone, new Position(x, y));
- x += stone.getWidth();
- }
- }
-
- setStones(stones);
- this.stoneSets = stoneSets;
-
- repaint();
- }
-
- @Override
- public IStoneCollectionPanel getStoneCollectionPanel() {
- return stoneCollection;
- }
-
- /**
- * Sets the currently selected stones
- *
- * @param stones
- * the selected stones
- */
- void setSelectedStones(Collection<Stone> stones) {
- selectedStones = stones;
- stoneCollection.setSelectedStones(stones);
- repaint();
- }
-
- private void rescale() {
- Insets insets = getInsets();
- int x = insets.left, y = insets.top, width = getWidth() - insets.left
- - insets.right, height = getHeight() - insets.top - insets.bottom;
-
- leftPlayerLabel.setBounds(x, y, width, height);
- topPlayerLabel.setBounds(x, y, width, height);
- rightPlayerLabel.setBounds(x, y, width, height);
-
- stoneCollection.setLocation(x + width / 2 - stoneCollection.getWidth() / 2,
- y + height - stoneCollection.getHeight() - COLLECTION_GAP);
- }
-
- /**
- * Creates a new Table instance
- */
- TablePanel() {
- super(DEFAULT_SCALE);
-
- setLayout(null);
-
- leftPlayerLabel = new JLabel();
- leftPlayerLabel.setForeground(Color.WHITE);
- leftPlayerLabel.setHorizontalAlignment(JLabel.LEFT);
- leftPlayerLabel.setHorizontalTextPosition(JLabel.LEFT);
- add(leftPlayerLabel);
-
- topPlayerLabel = new JLabel();
- topPlayerLabel.setHorizontalAlignment(JLabel.CENTER);
- topPlayerLabel.setHorizontalTextPosition(JLabel.CENTER);
- topPlayerLabel.setVerticalAlignment(JLabel.TOP);
- topPlayerLabel.setVerticalTextPosition(JLabel.TOP);
- topPlayerLabel.setForeground(Color.WHITE);
- add(topPlayerLabel);
-
- rightPlayerLabel = new JLabel();
- rightPlayerLabel.setForeground(Color.WHITE);
- rightPlayerLabel.setHorizontalAlignment(JLabel.RIGHT);
- rightPlayerLabel.setHorizontalTextPosition(JLabel.RIGHT);
- add(rightPlayerLabel);
-
- stoneCollection = new StoneCollectionPanel();
- add(stoneCollection);
-
- ComponentListener rescaleListener = new ComponentAdapter() {
- @Override
- public void componentResized(ComponentEvent e) {
- rescale();
- }
- };
-
- addComponentListener(rescaleListener);
- stoneCollection.addComponentListener(rescaleListener);
- }
-
- private void paintStoneSet(Graphics2D g, StoneSet stoneSet, Position pos) {
- float x = pos.getX();
- int width = getStonePainter().getStoneWidth(), height = getStonePainter()
- .getStoneHeight();
-
- g.setColor(new Color(0, 0, 0, 0.25f));
- g.fillRect((int) (x * width) - width / 4, (int) (pos.getY() * height),
- width / 4, height);
-
- for (Stone stone : stoneSet) {
- getStonePainter().paintStone(g, stone, new Position(x, pos.getY()),
- selectedStones.contains(stone));
- x++;
- }
-
- g.setColor(new Color(0, 0, 0, 0.25f));
- g.fillRect((int) (x * width), (int) (pos.getY() * height), width / 4,
- height);
- }
-
- @Override
- protected void paintComponent(Graphics g1) {
- Graphics2D g = (Graphics2D) g1;
-
- for (int x = 0; x < getWidth(); x += background.getIconWidth()) {
- for (int y = 0; y < getHeight(); y += background.getIconHeight()) {
- background.paintIcon(this, g, x, y);
- }
- }
-
- g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- RenderingHints.VALUE_ANTIALIAS_ON);
-
- for (Map.Entry<StoneSet, Position> stoneSet : stoneSets.entrySet()) {
- paintStoneSet(g, stoneSet.getKey(), stoneSet.getValue());
- }
- }
+ private final static ImageIcon background = new ImageIcon(
+ HandPanel.class.getResource("/jrummikub/resource/felt.png"));
+
+ private final static float DEFAULT_SCALE = 1;
+ private final static float CONNECTOR_WIDTH = 0.25f;
+ private final int COLLECTION_GAP = 5;
+
+ private JLabel leftPlayerLabel, topPlayerLabel, rightPlayerLabel;
+ private StoneCollectionPanel stoneCollection;
+
+ private Map<StoneSet, Position> stoneSets = Collections.emptyMap();
+ private Collection<Stone> selectedStones = Collections.emptyList();
+
+ private Event1<StoneSet> leftConnectorClickEvent = new Event1<StoneSet>();
+ private Event1<StoneSet> rightConnectorClickEvent = new Event1<StoneSet>();
+
+ @Override
+ public void setLeftPlayerName(String playerName) {
+ leftPlayerLabel.setText(playerName);
+ }
+
+ @Override
+ public void setTopPlayerName(String playerName) {
+ topPlayerLabel.setText(playerName);
+ }
+
+ @Override
+ public void setRightPlayerName(String playerName) {
+ rightPlayerLabel.setText(playerName);
+ }
+
+ @Override
+ public Event1<StoneSet> getLeftConnectorClickEvent() {
+ return leftConnectorClickEvent;
+ }
+
+ @Override
+ public Event1<StoneSet> getRightConnectorClickEvent() {
+ return rightConnectorClickEvent;
+ }
+
+ @Override
+ public void setStoneSets(Map<StoneSet, Position> stoneSets) {
+ Map<Stone, Position> stones = new HashMap<Stone, Position>();
+
+ for (Map.Entry<StoneSet, Position> entry : stoneSets.entrySet()) {
+ float x = entry.getValue().getX(), y = entry.getValue().getY();
+
+ for (Stone stone : entry.getKey()) {
+ stones.put(stone, new Position(x, y));
+ x++;
+ }
+ }
+
+ setStones(stones);
+ this.stoneSets = stoneSets;
+
+ repaint();
+ }
+
+ @Override
+ public IStoneCollectionPanel getStoneCollectionPanel() {
+ return stoneCollection;
+ }
+
+ /**
+ * Sets the currently selected stones
+ *
+ * @param stones
+ * the selected stones
+ */
+ void setSelectedStones(Collection<Stone> stones) {
+ selectedStones = stones;
+ stoneCollection.setSelectedStones(stones);
+ repaint();
+ }
+
+ private void rescale() {
+ Insets insets = getInsets();
+ int x = insets.left, y = insets.top, width = getWidth() - insets.left
+ - insets.right, height = getHeight() - insets.top - insets.bottom;
+
+ leftPlayerLabel.setBounds(x, y, width, height);
+ topPlayerLabel.setBounds(x, y, width, height);
+ rightPlayerLabel.setBounds(x, y, width, height);
+
+ stoneCollection.setLocation(x + width / 2 - stoneCollection.getWidth() / 2,
+ y + height - stoneCollection.getHeight() - COLLECTION_GAP);
+ }
+
+ /**
+ * Creates a new Table instance
+ */
+ TablePanel() {
+ super(DEFAULT_SCALE);
+
+ setLayout(null);
+
+ leftPlayerLabel = new JLabel();
+ leftPlayerLabel.setForeground(Color.WHITE);
+ leftPlayerLabel.setHorizontalAlignment(JLabel.LEFT);
+ leftPlayerLabel.setHorizontalTextPosition(JLabel.LEFT);
+ add(leftPlayerLabel);
+
+ topPlayerLabel = new JLabel();
+ topPlayerLabel.setHorizontalAlignment(JLabel.CENTER);
+ topPlayerLabel.setHorizontalTextPosition(JLabel.CENTER);
+ topPlayerLabel.setVerticalAlignment(JLabel.TOP);
+ topPlayerLabel.setVerticalTextPosition(JLabel.TOP);
+ topPlayerLabel.setForeground(Color.WHITE);
+ add(topPlayerLabel);
+
+ rightPlayerLabel = new JLabel();
+ rightPlayerLabel.setForeground(Color.WHITE);
+ rightPlayerLabel.setHorizontalAlignment(JLabel.RIGHT);
+ rightPlayerLabel.setHorizontalTextPosition(JLabel.RIGHT);
+ add(rightPlayerLabel);
+
+ stoneCollection = new StoneCollectionPanel();
+ add(stoneCollection);
+
+ ComponentListener rescaleListener = new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ rescale();
+ }
+ };
+
+ addComponentListener(rescaleListener);
+ stoneCollection.addComponentListener(rescaleListener);
+ }
+
+ protected boolean handleOtherClickEvent(Position pos) {
+ for (Map.Entry<StoneSet, Position> entry : stoneSets.entrySet()) {
+ Position p = entry.getValue();
+ StoneSet stoneSet = entry.getKey();
+ float x = p.getX(), y = p.getY();
+
+ // left connector
+ Rectangle2D rect = new Rectangle2D.Float(x - CONNECTOR_WIDTH, y,
+ CONNECTOR_WIDTH, 1);
+ if (rect.contains(pos.getX(), pos.getY())) {
+ leftConnectorClickEvent.emit(stoneSet);
+ return true;
+ }
+
+ // right connector
+ rect = new Rectangle2D.Float(x + stoneSet.size(), y, CONNECTOR_WIDTH, 1);
+ if (rect.contains(pos.getX(), pos.getY())) {
+ rightConnectorClickEvent.emit(stoneSet);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private void paintStoneSet(Graphics2D g, StoneSet stoneSet, Position pos) {
+ float x = pos.getX();
+ int width = getStonePainter().getStoneWidth(), height = getStonePainter()
+ .getStoneHeight();
+
+ g.setColor(new Color(0, 0, 0, 0.25f));
+ g.fillRect((int) (x * width - width * CONNECTOR_WIDTH),
+ (int) (pos.getY() * height), (int) (width * CONNECTOR_WIDTH), height);
+
+ for (Stone stone : stoneSet) {
+ getStonePainter().paintStone(g, stone, new Position(x, pos.getY()),
+ selectedStones.contains(stone));
+ x++;
+ }
+
+ g.setColor(new Color(0, 0, 0, 0.25f));
+ g.fillRect((int) (x * width), (int) (pos.getY() * height),
+ (int) (width * CONNECTOR_WIDTH), height);
+ }
+
+ @Override
+ protected void paintComponent(Graphics g1) {
+ Graphics2D g = (Graphics2D) g1;
+
+ for (int x = 0; x < getWidth(); x += background.getIconWidth()) {
+ for (int y = 0; y < getHeight(); y += background.getIconHeight()) {
+ background.paintIcon(this, g, x, y);
+ }
+ }
+
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ for (Map.Entry<StoneSet, Position> entry : stoneSets.entrySet()) {
+ paintStoneSet(g, entry.getKey(), entry.getValue());
+ }
+ }
}