Added connector click events

git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@94 72836036-5685-4462-b002-a69064685172
This commit is contained in:
Bennet Gerlach 2011-05-03 20:39:21 +02:00
parent e7613bfd93
commit 344d63598a
6 changed files with 392 additions and 308 deletions

View file

@ -139,6 +139,22 @@ public class JRummikub {
}
});
view.getTablePanel().getLeftConnectorClickEvent()
.add(new IListener1<StoneSet>() {
@Override
public void handle(StoneSet s) {
System.out.println("Left connector clicked on " + s);
}
});
view.getTablePanel().getRightConnectorClickEvent()
.add(new IListener1<StoneSet>() {
@Override
public void handle(StoneSet s) {
System.out.println("Right connector clicked on " + s);
}
});
view.getTablePanel().getStoneCollectionPanel().getStoneClickEvent()
.add(new IListener2<Stone, Boolean>() {
@ -149,6 +165,7 @@ public class JRummikub {
}
});
view.getTablePanel().getStoneCollectionPanel().getRangeClickEvent()
.add(new IListener2<Stone, Boolean>() {
@Override

View file

@ -1,6 +1,6 @@
package jrummikub.model;
/** Class specifing possible StoneColors */
/** Class specifying possible StoneColors */
public enum StoneColor {
BLACK, ORANGE, BLUE, RED
}

View file

@ -4,48 +4,65 @@ import java.util.Map;
import jrummikub.model.Position;
import jrummikub.model.StoneSet;
import jrummikub.util.Event1;
/**
* The view of the table, where the stone sets lie
*/
public interface ITablePanel extends IStonePanel, IClickable {
/**
* Sets the player name on the left label
*
* @param playerName
* the name to set
*/
public void setLeftPlayerName(String playerName);
/**
* Sets the player name on the left label
*
* @param playerName
* the name to set
*/
public void setLeftPlayerName(String playerName);
/**
* Sets the player name on the top label
*
* @param playerName
* the name to set
*/
public void setTopPlayerName(String playerName);
/**
* Sets the player name on the top label
*
* @param playerName
* the name to set
*/
public void setTopPlayerName(String playerName);
/**
* Sets the player name on the right label
*
* @param playerName
* the name to set
*/
public void setRightPlayerName(String playerName);
/**
* Sets the player name on the right label
*
* @param playerName
* the name to set
*/
public void setRightPlayerName(String playerName);
/**
* Sets the stone sets lying on the table
*
* @param stoneSets
* set stone sets on the table
*/
public void setStoneSets(Map<StoneSet, Position> stoneSets);
/**
* Sets the stone sets lying on the table
*
* @param stoneSets
* set stone sets on the table
*/
public void setStoneSets(Map<StoneSet, Position> stoneSets);
/**
* Returns the stone collection (the panel showing the stones currently
* selected)
*
* @return the stone collection
*/
IStoneCollectionPanel getStoneCollectionPanel();
/**
* Returns the stone collection (the panel showing the stones currently
* selected)
*
* @return the stone collection
*/
public IStoneCollectionPanel getStoneCollectionPanel();
/**
* the left connector click event is emitted when the player clicks on a left
* connector of a stone set on the table .
*
* @return the event
*/
public Event1<StoneSet> getLeftConnectorClickEvent();
/**
* the right connector click event is emitted when the player clicks on a
* right connector of a stone set on the table .
*
* @return the event
*/
public Event1<StoneSet> getRightConnectorClickEvent();
}

View file

@ -21,117 +21,127 @@ import jrummikub.view.IStonePanel;
*/
@SuppressWarnings("serial")
abstract class AbstractStonePanel extends JPanel implements IStonePanel,
IClickable {
private StonePainter stonePainter;
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 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();
private Map<Stone, Position> stones = Collections.emptyMap();
/**
* @return the stone painter
*/
protected StonePainter getStonePainter() {
return stonePainter;
}
/**
* @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 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
/**
* 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);
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);
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;
}
if (stone == null) {
if (!handleOtherClickEvent(pos))
clickEvent.emit(pos);
Event2<Stone, Boolean> event = stoneClickEvent;
return;
}
if (e.isShiftDown())
event = rangeClickEvent;
else if (e.getClickCount() >= 2)
event = setClickEvent;
Event2<Stone, Boolean> event = stoneClickEvent;
event.emit(stone, e.isControlDown());
}
});
}
if (e.isShiftDown())
event = rangeClickEvent;
else if (e.getClickCount() >= 2)
event = setClickEvent;
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());
event.emit(stone, e.isControlDown());
}
});
}
if (rect.contains(pos.getX(), pos.getY()))
return stone;
}
/*
* *Overwrite this method* to signal if special zone was clicked
*
* @return special zone clicked
*/
protected boolean handleOtherClickEvent(Position pos) {
return false;
}
return null;
}
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);
/**
* 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;
}
if (rect.contains(pos.getX(), pos.getY()))
return stone;
}
/**
* Returns the list of stones and positions currently set
*
* @return the stones
*/
protected Map<Stone, Position> getStones() {
return stones;
}
return null;
}
@Override
public Event1<Position> getClickEvent() {
return clickEvent;
}
/**
* 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;
}
@Override
public Event2<Stone, Boolean> getStoneClickEvent() {
return stoneClickEvent;
}
/**
* Returns the list of stones and positions currently set
*
* @return the stones
*/
protected Map<Stone, Position> getStones() {
return stones;
}
@Override
public Event2<Stone, Boolean> getRangeClickEvent() {
return rangeClickEvent;
}
@Override
public Event1<Position> getClickEvent() {
return clickEvent;
}
@Override
public Event2<Stone, Boolean> getSetClickEvent() {
return setClickEvent;
}
@Override
public Event2<Stone, Boolean> getStoneClickEvent() {
return stoneClickEvent;
}
@Override
public Event2<Stone, Boolean> getRangeClickEvent() {
return rangeClickEvent;
}
@Override
public Event2<Stone, Boolean> getSetClickEvent() {
return setClickEvent;
}
}

View file

@ -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;
IStoneCollectionPanel {
private final static int INSET = 7;
private final static float STONE_SCALE = 1.1f;
private Collection<Stone> selectedStones = Collections.emptyList();
private Collection<Stone> selectedStones = Collections.emptyList();
/**
* Creates a new StoneCollection instance
*/
StoneCollectionPanel() {
super(STONE_SCALE);
/**
* Creates a new StoneCollection instance
*/
StoneCollectionPanel() {
super(STONE_SCALE);
setOpaque(false);
setVisible(false);
setBorder(new EmptyBorder(INSET, INSET, INSET, INSET));
}
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;
/**
* 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;
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();
}
for (Stone stone : selectedStones) {
stones.put(stone, new Position(x, 0));
x++;
}
setStones(stones);
setStones(stones);
if (selectedStones.isEmpty()) {
setVisible(false);
} else {
setSize(getStonePainter().getStoneWidth() * selectedStones.size() + 2
* INSET, getStonePainter().getStoneHeight() + 2 * INSET);
setVisible(true);
if (selectedStones.isEmpty()) {
setVisible(false);
} else {
setSize(getStonePainter().getStoneWidth() * selectedStones.size() + 2
* INSET, getStonePainter().getStoneHeight() + 2 * INSET);
setVisible(true);
repaint();
}
}
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);
@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);
if (!selectedStones.isEmpty()) {
g1.setColor(new Color(0, 0, 0, 0.25f));
g1.fillRoundRect(0, 0, getWidth(), getHeight(), INSET, INSET);
float xpos = 0;
float xpos = 0;
for (Stone stone : selectedStones) {
getStonePainter().paintStone(g, stone, new Position(xpos, 0), false);
xpos++;
}
}
}
for (Stone stone : selectedStones) {
getStonePainter().paintStone(g, stone, new Position(xpos, 0), false);
xpos++;
}
}
}
}

View file

@ -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 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 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 JLabel leftPlayerLabel, topPlayerLabel, rightPlayerLabel;
private StoneCollectionPanel stoneCollection;
private Map<StoneSet, Position> stoneSets = Collections.emptyMap();
private Collection<Stone> selectedStones = Collections.emptyList();
private Map<StoneSet, Position> stoneSets = Collections.emptyMap();
private Collection<Stone> selectedStones = Collections.emptyList();
@Override
public void setLeftPlayerName(String playerName) {
leftPlayerLabel.setText(playerName);
}
private Event1<StoneSet> leftConnectorClickEvent = new Event1<StoneSet>();
private Event1<StoneSet> rightConnectorClickEvent = new Event1<StoneSet>();
@Override
public void setTopPlayerName(String playerName) {
topPlayerLabel.setText(playerName);
}
@Override
public void setLeftPlayerName(String playerName) {
leftPlayerLabel.setText(playerName);
}
@Override
public void setRightPlayerName(String playerName) {
rightPlayerLabel.setText(playerName);
}
@Override
public void setTopPlayerName(String playerName) {
topPlayerLabel.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 void setRightPlayerName(String playerName) {
rightPlayerLabel.setText(playerName);
}
@Override
public IStoneCollectionPanel getStoneCollectionPanel() {
return stoneCollection;
}
@Override
public Event1<StoneSet> getLeftConnectorClickEvent() {
return leftConnectorClickEvent;
}
/**
* Sets the currently selected stones
*
* @param stones
* the selected stones
*/
void setSelectedStones(Collection<Stone> stones) {
selectedStones = stones;
stoneCollection.setSelectedStones(stones);
repaint();
}
@Override
public Event1<StoneSet> getRightConnectorClickEvent() {
return rightConnectorClickEvent;
}
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;
@Override
public void setStoneSets(Map<StoneSet, Position> stoneSets) {
Map<Stone, Position> stones = new HashMap<Stone, Position>();
leftPlayerLabel.setBounds(x, y, width, height);
topPlayerLabel.setBounds(x, y, width, height);
rightPlayerLabel.setBounds(x, y, width, height);
for (Map.Entry<StoneSet, Position> entry : stoneSets.entrySet()) {
float x = entry.getValue().getX(), y = entry.getValue().getY();
stoneCollection.setLocation(x + width / 2 - stoneCollection.getWidth() / 2,
y + height - stoneCollection.getHeight() - COLLECTION_GAP);
}
for (Stone stone : entry.getKey()) {
stones.put(stone, new Position(x, y));
x++;
}
}
/**
* Creates a new Table instance
*/
TablePanel() {
super(DEFAULT_SCALE);
setStones(stones);
this.stoneSets = stoneSets;
setLayout(null);
repaint();
}
leftPlayerLabel = new JLabel();
leftPlayerLabel.setForeground(Color.WHITE);
leftPlayerLabel.setHorizontalAlignment(JLabel.LEFT);
leftPlayerLabel.setHorizontalTextPosition(JLabel.LEFT);
add(leftPlayerLabel);
@Override
public IStoneCollectionPanel getStoneCollectionPanel() {
return stoneCollection;
}
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);
/**
* Sets the currently selected stones
*
* @param stones
* the selected stones
*/
void setSelectedStones(Collection<Stone> stones) {
selectedStones = stones;
stoneCollection.setSelectedStones(stones);
repaint();
}
rightPlayerLabel = new JLabel();
rightPlayerLabel.setForeground(Color.WHITE);
rightPlayerLabel.setHorizontalAlignment(JLabel.RIGHT);
rightPlayerLabel.setHorizontalTextPosition(JLabel.RIGHT);
add(rightPlayerLabel);
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;
stoneCollection = new StoneCollectionPanel();
add(stoneCollection);
leftPlayerLabel.setBounds(x, y, width, height);
topPlayerLabel.setBounds(x, y, width, height);
rightPlayerLabel.setBounds(x, y, width, height);
ComponentListener rescaleListener = new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
rescale();
}
};
stoneCollection.setLocation(x + width / 2 - stoneCollection.getWidth() / 2,
y + height - stoneCollection.getHeight() - COLLECTION_GAP);
}
addComponentListener(rescaleListener);
stoneCollection.addComponentListener(rescaleListener);
}
/**
* Creates a new Table instance
*/
TablePanel() {
super(DEFAULT_SCALE);
private void paintStoneSet(Graphics2D g, StoneSet stoneSet, Position pos) {
float x = pos.getX();
int width = getStonePainter().getStoneWidth(), height = getStonePainter()
.getStoneHeight();
setLayout(null);
g.setColor(new Color(0, 0, 0, 0.25f));
g.fillRect((int) (x * width) - width / 4, (int) (pos.getY() * height),
width / 4, height);
leftPlayerLabel = new JLabel();
leftPlayerLabel.setForeground(Color.WHITE);
leftPlayerLabel.setHorizontalAlignment(JLabel.LEFT);
leftPlayerLabel.setHorizontalTextPosition(JLabel.LEFT);
add(leftPlayerLabel);
for (Stone stone : stoneSet) {
getStonePainter().paintStone(g, stone, new Position(x, pos.getY()),
selectedStones.contains(stone));
x++;
}
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);
g.setColor(new Color(0, 0, 0, 0.25f));
g.fillRect((int) (x * width), (int) (pos.getY() * height), width / 4,
height);
}
rightPlayerLabel = new JLabel();
rightPlayerLabel.setForeground(Color.WHITE);
rightPlayerLabel.setHorizontalAlignment(JLabel.RIGHT);
rightPlayerLabel.setHorizontalTextPosition(JLabel.RIGHT);
add(rightPlayerLabel);
@Override
protected void paintComponent(Graphics g1) {
Graphics2D g = (Graphics2D) g1;
stoneCollection = new StoneCollectionPanel();
add(stoneCollection);
for (int x = 0; x < getWidth(); x += background.getIconWidth()) {
for (int y = 0; y < getHeight(); y += background.getIconHeight()) {
background.paintIcon(this, g, x, y);
}
}
ComponentListener rescaleListener = new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
rescale();
}
};
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
addComponentListener(rescaleListener);
stoneCollection.addComponentListener(rescaleListener);
}
for (Map.Entry<StoneSet, Position> stoneSet : stoneSets.entrySet()) {
paintStoneSet(g, stoneSet.getKey(), stoneSet.getValue());
}
}
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());
}
}
}