package jimmm.gui;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import jimmm.data.Card;
import jimmm.data.Card.Value;
/**
* Layouts a set of cards in a rectangular region. Can either arrange them in vertical columns (used for
* face up cards) or in a single horizontal row (used for ones hidden cards).
* @author Simon Hampe
*
*/
public class PlayerCardsLayoutManager implements LayoutManager {
// *** MEMBERS ***
//Whether we use horizontal layout.
private boolean isHorizontalLayout = false;
//Geometric variables: For now everything is fixed
private int horizontalPadding = 10;
private int verticalPadding = 10;
private int horizontalGap = 20;
private int verticalGap = 20;
// *** CONSTRUCTOR ***
/**
* Constructs a card layout manager.
* @param isHorizontalLayout Whether the cards should be laid out in a single horizonal row (true) or
* in columns, ordered by value (false).
*/
public PlayerCardsLayoutManager(boolean isHorizontalLayout) {
this.isHorizontalLayout = isHorizontalLayout;
}
// *** INTERNAL METHODS ***
/**
* Computes the number of different card values occurring.
*/
private int noOfValues(Container parent) {
Component[] clist = parent.getComponents();
HashSet<Value> values = new HashSet<Card.Value>();
for(Component c : clist) {
values.add( ((CardPanel)c).getCard().getValue());
}
return values.size();
}
/**
* Computes what the maximal number of cards per value is.
*/
private int maximalNumber(Container parent) {
Component[] clist = parent.getComponents();
HashMap<Value, Integer> numbers = new HashMap<Card.Value, Integer>();
int current_max = 0;
for(Value v : Card.Value.values()) numbers.put(v,0);
for(Component c : clist) {
Value cval = ((CardPanel)c).getCard().getValue();
numbers.put(cval, numbers.get(cval)+1);
if(numbers.get(cval) > current_max) current_max = numbers.get(cval);
}
return current_max;
}
// *** MANAGER METHODS ***
@Override
public void addLayoutComponent(String name, Component comp) {
//Do nothing
}
@Override
public void layoutContainer(Container parent) {
//First get all cards and sort them
Component[] clist = parent.getComponents();
ArrayList<CardPanel> panelList = new ArrayList<CardPanel>();
for(Component c : clist) panelList.add((CardPanel)c);
Collections.sort(panelList, new CardComparator());
int xpos = horizontalPadding;
int ypos = verticalPadding;
//In both cases, z-component order is inverse to the order in the list
//For horizontal layout, simply draw in order.
if(isHorizontalLayout) {
for(CardPanel p : panelList) {
p.setBounds(xpos, ypos, p.getPreferredSize().width, p.getPreferredSize().height);
parent.setComponentZOrder(p, clist.length -1-panelList.indexOf(p));
xpos += horizontalGap;
}
}
//Otherwise, look at card types
else {
Value prevValue = null;
for(CardPanel p : panelList) {
if(prevValue != null) {
if(p.getCard().getValue() == prevValue) {
ypos += verticalGap;
}
else {
ypos = verticalPadding;
xpos += p.getPreferredSize().width + horizontalGap;
prevValue = p.getCard().getValue();
}
}
else {
prevValue = p.getCard().getValue();
}
p.setBounds(xpos, ypos, p.getPreferredSize().width, p.getPreferredSize().height);
parent.setComponentZOrder(p, clist.length -1-panelList.indexOf(p));
}
}
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return new Dimension(
2*horizontalPadding + (isHorizontalLayout? 100 + parent.getComponentCount()*horizontalGap - horizontalGap:
noOfValues(parent)*(100 + horizontalGap) - horizontalGap),
2*verticalPadding + 160 + (isHorizontalLayout? 0 : (maximalNumber(parent)-1) *verticalGap) );
}
@Override
public Dimension preferredLayoutSize(Container parent) {
return minimumLayoutSize(parent);
}
@Override
public void removeLayoutComponent(Component comp) {
//Do nothing
}
// *** COMPARATOR ***
/**
* Compares two {@link CardPanel}s: First value (7 < 8 .... < Ace), then Color (as by enum value), then hashcode
* @author Simon Hampe
*
*/
private class CardComparator implements Comparator<CardPanel> {
@Override
public int compare(CardPanel o1, CardPanel o2) {
if(o1.getCard().getValue() != o2.getCard().getValue()) return o1.getCard().getValue().compareTo(o2.getCard().getValue());
if(o2.getCard().getColor() != o2.getCard().getColor()) return o2.getCard().getColor().compareTo(o2.getCard().getColor());
return Integer.compare(o1.hashCode(), o2.hashCode());
}
}
}