summaryrefslogtreecommitdiffstats
path: root/src/jrummikub/view/impl/AbstractStonePanel.java
blob: 19e58919054e7b45bce5c5dcc371d646f2c0805d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package jrummikub.view.impl;

import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.util.Collections;
import java.util.Map;

import javax.swing.JPanel;

import jrummikub.model.Position;
import jrummikub.model.Stone;
import jrummikub.util.Event1;
import jrummikub.util.Event2;
import jrummikub.view.IClickable;
import jrummikub.view.IStonePanel;

/**
 * Base class for panels that draw stones
 */
@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.fire(pos);
          return;
        }

        Event2<Stone, Boolean> event = stoneClickEvent;

        if (e.isShiftDown())
          event = rangeClickEvent;
        else if (e.getClickCount() >= 2)
          event = setClickEvent;

        event.fire(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;
  }

}