This repository has been archived on 2025-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
JRummikub/src/jrummikub/view/impl/AbstractStonePanel.java
Bennet Gerlach 9c056cfef7 Implemented direct placing of stones via alt-key
git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@209 72836036-5685-4462-b002-a69064685172
2011-05-10 02:10:30 +02:00

223 lines
5 KiB
Java

package jrummikub.view.impl;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Rectangle2D;
import java.util.Collections;
import javax.swing.JPanel;
import jrummikub.model.Position;
import jrummikub.model.Stone;
import jrummikub.util.Event1;
import jrummikub.util.Event2;
import jrummikub.util.Pair;
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 Iterable<Pair<Stone, Position>> stones = Collections.emptySet();
private Stone hoveredStone = null;
/**
* @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) {
clickAt(e.getPoint(), e.getClickCount(), e.isShiftDown(),
e.isControlDown(), e.isAltDown());
}
@Override
public void mouseExited(MouseEvent e) {
setHoveredStone(null);
}
});
addMouseMotionListener(new MouseMotionAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
Insets insets = getInsets();
Pair<Integer, Integer> trans = getTranslation();
Position pos = stonePainter.calculatePosition(e.getX() - insets.left
- trans.getFirst(), e.getY() - insets.top - trans.getSecond());
setHoveredStone(getStoneAt(pos));
}
});
}
/**
* clickAt is called when a click has occurred
*
* @param p
* the point in component coordinates
* @param clickCount
* the click count
* @param shift
* is shift down?
* @param control
* is control down?
* @param alt
* is alt down?
*/
protected void clickAt(Point p, int clickCount, boolean shift,
boolean control, boolean alt) {
Insets insets = getInsets();
Pair<Integer, Integer> trans = getTranslation();
Position pos = stonePainter.calculatePosition(
p.x - insets.left - trans.getFirst(),
p.y - insets.top - trans.getSecond());
if (alt) {
clickEvent.emit(pos);
return;
}
Stone stone = getStoneAt(pos);
if (stone == null) {
if (!handleOtherClickEvent(pos))
clickEvent.emit(pos);
return;
}
Event2<Stone, Boolean> event = stoneClickEvent;
if (shift)
event = rangeClickEvent;
else if (clickCount >= 2)
event = setClickEvent;
event.emit(stone, control);
}
private void setHoveredStone(Stone stone) {
Stone oldStone = hoveredStone;
hoveredStone = stone;
if (oldStone != hoveredStone)
repaint();
}
/**
* Returns the stone the mouse pointer is hovering over
*
* @return the hovered stone
*/
protected Stone getHoveredStone() {
return hoveredStone;
}
/**
* *Overwrite this method* to signal if special zone was clicked
*
* @param pos
* the clicked position
*
* @return special zone clicked
*/
protected boolean handleOtherClickEvent(Position pos) {
return false;
}
private Stone getStoneAt(Position pos) {
for (Pair<Stone, Position> entry : stones) {
Stone stone = entry.getFirst();
Position p = entry.getSecond();
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(Iterable<Pair<Stone, Position>> stones) {
this.stones = stones;
}
/**
* Returns the translation in pixels the stones in this panel are painted with
*
* @return the translation
*/
protected Pair<Integer, Integer> getTranslation() {
return new Pair<Integer, Integer>(0, 0);
}
/**
* Returns the list of stones and positions currently set
*
* @return the stones
*/
protected Iterable<Pair<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;
}
}