package ch.sahits.game.graphic.display.dialog;
import java.awt.Color;
import java.awt.FontFormatException;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.font.GlyphVector;
import java.awt.image.BufferedImage;
import java.io.IOException;
import ch.sahits.game.event.EViewChangeEvent;
import ch.sahits.game.event.Event;
import ch.sahits.game.event.IEventListener;
import ch.sahits.game.event.KeyPressEvent;
import ch.sahits.game.event.MouseClickEvent;
import ch.sahits.game.event.ViewChangeEvent;
import ch.sahits.game.graphic.display.gameplay.MainView;
import ch.sahits.game.graphic.display.model.CityPlayerProxy;
import ch.sahits.game.graphic.display.notice.NoticeView;
import ch.sahits.game.graphic.display.util.ClickablePolygons;
import ch.sahits.game.graphic.image.DisplayImageDIResolver;
import ch.sahits.game.graphic.image.IImageLoader;
import ch.sahits.game.graphic.image.IOpenPatricianPainter;
import ch.sahits.game.graphic.image.model.NamedPolygon;
import ch.sahits.game.image.IImageUtilities;
import ch.sahits.game.openpatrician.model.city.ICity;
import ch.sahits.game.openpatrician.model.product.AmountablePrice;
import ch.sahits.game.openpatrician.model.product.EWare;
import ch.sahits.game.openpatrician.model.product.IWare;
import ch.sahits.game.rendering.RenderablePart;
/**
* This is a statistical dialog displaying the socked wares in the city and their prices.
* @author Andi Hotz, (c) Sahits GmbH, 2012
* Created on Jul 17, 2012
*
*/
public class TradingStockDialog extends OpenPatricianGameDialog implements IEventListener, RenderablePart{
private boolean enabled = true;
private ClickablePolygons footerPolygons;
/** Hold all the positioning information, initialized in initBackgroundImage */
private DialogPositions positions;
/** reference to the utilities for image manipulation */
private IImageUtilities imageUtils;
private IOpenPatricianPainter opPainter;
public TradingStockDialog(Point topLeft, double scale,
CityPlayerProxy cityProxy) {
super(topLeft, DisplayImageDIResolver.getInstance().getMainScreenLoader(), scale, cityProxy);
Event.add(this);
}
@Override
protected void init() {
DisplayImageDIResolver resolver = DisplayImageDIResolver.getInstance();
opPainter = resolver.getOpenPatricianPainter();
imageUtils = resolver.getImageUtilities();
super.init();
}
/**
* Compute the insets as a factor of the scaling
* @param scale
*/
protected void initInsets(double scale) {
int top = (int) Math.ceil(scale*30);
int side = (int) Math.ceil(scale*3);
inset = new Insets(top, side, top, side);
}
@Override
protected void initiatePolygons() {
footerPolygons = new ClickablePolygons();
}
@Override
public void gameUpdate(Event e, Object notice) {
if (e instanceof KeyPressEvent){
KeyEvent key= ((KeyPressEvent)e).getKey();
if (key.getKeyCode()==KeyEvent.VK_ESCAPE){
new ViewChangeEvent(MainView.class).notify(EViewChangeEvent.CLOSE_DIALOG);
new ViewChangeEvent(NoticeView.class).notify(EViewChangeEvent.NOTICE_HIDE);
Event.remove(this);
}
}
if (e instanceof MouseClickEvent){
footerPolygons.testAndExecute((Point) notice);
}
}
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public void setEnabled(boolean flag) {
enabled=flag;
}
/**
* Draw the table header
* @param g2d
* @param y position of the table header baseline
* @throws FontFormatException
* @throws IOException
*/
private void drawTableHeader(Graphics2D g2d,final int y) throws FontFormatException, IOException{
GlyphVector gv = opPainter.createGlyphVector(g2d, "Ware", 19); // TODO externalize
int x = positions.xWare-(int)Math.rint(gv.getVisualBounds().getWidth());
g2d.drawGlyphVector(gv, x, y);
String columnTitle = "Stock";
gv = opPainter.createGlyphVector(g2d, columnTitle, 19);
g2d.drawGlyphVector(gv, positions.xCity, y);
gv = opPainter.createGlyphVector(g2d, "from City", 19);
g2d.drawGlyphVector(gv, positions.xBuy, y);
gv = opPainter.createGlyphVector(g2d, "to City", 19);
g2d.drawGlyphVector(gv, positions.xSell, y);
}
@Override
protected BufferedImage initBackgroundImage(IImageLoader loader,Point topLeft) {
BufferedImage bg = super.initBackgroundImage(loader,topLeft);
Graphics2D g2d = bg.createGraphics();
g2d.setColor(Color.BLACK);
try {
GlyphVector gv = opPainter.createGlyphVector(g2d, "Wares in stock", 24); // TODO externalize
double titleHeight = gv.getVisualBounds().getHeight();
int length = (int) Math.rint(gv.getVisualBounds().getWidth());
int x = ((bg.getWidth()-getInset().left-getInset().right)-length)/2;
int y = getInset().top+10+(int)Math.rint(titleHeight*2/3);
g2d.drawGlyphVector(gv, x, y);
// Dynamic row
y += titleHeight;
y += (int)Math.rint(titleHeight*2/3);
BufferedImage waxSeal = loader.getImage("waxseal");
int leftBorderX = topLeft.x+getInset().left;
int xWare = leftBorderX+100; // right aligned
int xCity = leftBorderX+110;
int xBuy = leftBorderX+200; // size of the image + 10
int xSell = leftBorderX+280;// size of the image + 10
int yLineDiff = waxSeal.getHeight();
// Initialize the position relative to the frame
positions = new DialogPositions(titleHeight, yLineDiff, leftBorderX, xWare, xCity, xBuy, xSell);
leftBorderX = getInset().left; // Use local coordinates
xWare = leftBorderX+100; // right aligned
// table header
y += positions.lineHeight; // more space to the title
y += positions.lineHeight;
// Table
EWare[] wares = EWare.values();
for (EWare ware : wares) {
// Ware name
y += positions.lineHeight;
gv = opPainter.createGlyphVector(g2d, ware.getLocalDisplayName(), 18);
x = xWare-(int)Math.rint(gv.getVisualBounds().getWidth());
g2d.drawGlyphVector(gv, x, y);
// Amount available
// from city
// to city
}
// Footer buttons
y = bg.getHeight()-getInset().bottom-positions.lineHeight;
x = getInset().left+30;
int footerWidth = bg.getWidth()-getInset().left-getInset().right-2*30;
x += 3*footerWidth/4;
// close
g2d.drawImage(waxSeal, x,y-(int)(positions.lineHeight*0.8), null);
NamedPolygon polygon = new NamedPolygon("Close");
polygon.addPoint(topLeft.x+x, topLeft.y+y-(int)(positions.lineHeight*0.8));
polygon.addPoint(topLeft.x+x+waxSeal.getWidth(), topLeft.y+y-(int)(positions.lineHeight*0.8));
polygon.addPoint(topLeft.x+x+waxSeal.getWidth(), topLeft.y+y-(int)(positions.lineHeight*0.8)+waxSeal.getHeight());
polygon.addPoint(topLeft.x+x, topLeft.y+y-(int)(positions.lineHeight*0.8)+waxSeal.getHeight());
footerPolygons.add(polygon, new CloseAction(this));
g2d.setColor(new Color(0xEA,0xC1,0x17)); // Gold
gv = opPainter.createGlyphVector(g2d, "X", 18);
int xPadding = imageUtils.computeCenterAlignX(x, waxSeal.getWidth(), (int)gv.getVisualBounds().getWidth());
g2d.drawGlyphVector(gv, xPadding, y); // centeralign
} catch (FontFormatException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
return bg;
}
@Override
public void gameRender(Graphics gScr) {
Color oldColor = gScr.getColor();
super.gameRender(gScr);
gScr.setColor(Color.BLACK);
Graphics2D g2d = (Graphics2D) gScr;
try {
// Dialog title
int y = getBounds().y+getInset().top+10+(int)Math.rint(positions.titleHeigth*2/3);
final BufferedImage barrel = loader.getImage("barrel_icon");
final BufferedImage bale = loader.getImage("bale_icon");
final BufferedImage coin = loader.getImage("coin_icon");
// Sub title
y += positions.titleHeigth;
ICity cityModel = city.getCity();
y += (int)Math.rint(positions.titleHeigth*2/3);
// Table header
y += positions.lineHeight; // more space to the title
y += positions.lineHeight;
drawTableHeader(g2d, y);
// Table
EWare[] wares = EWare.values();
for (EWare ware : wares) {
// Ware name
y += positions.lineHeight;
// Available amount in the city
int availableAmount = drawAvailableAmount(g2d, cityModel,
ware, barrel, bale, y);
// from city
drawBuyFromCityPrice(g2d, availableAmount, ware, coin, y);
// to city
drawSellIconText(g2d, availableAmount, ware, coin, y);
} // end for wares
} catch (FontFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
gScr.setColor(oldColor);
}
/**
* Draw the available amount (second column). Available refers either to city or the storage based on
* the current dialog type.
* @param g2d 2D graphics context used for drawing
* @param city Reference to the city
* @param ware Reference to the ware
* @param barrel icon
* @param bale icon
* @param y position of from the top
* @return the available amount
* @throws FontFormatException Error while creating a font
* @throws IOException Error while reading a resource
*/
private int drawAvailableAmount(Graphics2D g2d, ICity city,IWare ware,BufferedImage barrel, BufferedImage bale,int y) throws FontFormatException, IOException{
AmountablePrice available = city.getWare(ware);
int availableAmount = available.getAmount();
int value = availableAmount; // amount available
if (value>0){
GlyphVector gv = opPainter.createGlyphVector(g2d, String.valueOf(value), 18);
g2d.drawGlyphVector(gv, positions.xCity, y);
// draw barrel or burden
if (ware.getSizeAsBarrels()==1){
// barrel
g2d.drawImage(barrel, (int)(positions.xCity+gv.getVisualBounds().getWidth())+5, y-positions.lineHeight*2/3, null);
} else {
g2d.drawImage(bale, (int)(positions.xCity+gv.getVisualBounds().getWidth())+5, y-positions.lineHeight*2/3, null);
}
}
return availableAmount;
}
/**
* Draw the text on the wax seal corresponding to the buy button
* @param g2d 2D graphics context used for drawing
* @param availableAmount amount that is actually available
* @param ware Reference to the ware
* @param coin icon
* @param y position of from the top
* @throws FontFormatException Error while creating a font
* @throws IOException Error while reading a resource
*/
private void drawBuyFromCityPrice(Graphics2D g2d, int availableAmount, IWare ware, BufferedImage coin, int y) throws FontFormatException, IOException{
int amount = 1;
String value;
if (availableAmount>0){
value = String.valueOf(ware.computeBuyPrice(availableAmount, amount));
} else {
value = "0"; // cannot buy anything if nothing is there
}
GlyphVector gv = opPainter.createGlyphVector(g2d, value, 18);
final int coinSpace = 3;
final int coindWidth = coin.getWidth();
final int maxPriceWidth = (int)opPainter.createGlyphVector(g2d, "00000", 18).getVisualBounds().getWidth();
int xRight = positions.xBuy-15+10+maxPriceWidth+coinSpace+coindWidth;
int x = xRight-((int)gv.getVisualBounds().getWidth()+coinSpace+coindWidth);
g2d.drawGlyphVector(gv, x, y);
x = xRight-coindWidth;
y -= (int) Math.ceil(gv.getVisualBounds().getHeight());
g2d.drawImage(coin, x, y, null);
}
/**
* Draw the text on the wax seal corresponding to the sell button
* @param g2d 2D graphics context used for drawing
* @param availableAmount amount that is actually available
* @param ware Reference to the ware
* @param coin icon
* @param y position of from the top
* @throws FontFormatException Error while creating a font
* @throws IOException Error while reading a resource
*/
private void drawSellIconText(Graphics2D g2d, int availableAmount, IWare ware, BufferedImage coin, int y) throws FontFormatException, IOException{
int amount = 1;
String value = String.valueOf(ware.computeSellPrice(availableAmount, amount));
GlyphVector gv = opPainter.createGlyphVector(g2d, value, 18);
final int coinSpace = 3;
final int coindWidth = coin.getWidth();
final int maxPriceWidth = (int)opPainter.createGlyphVector(g2d, "00000", 18).getVisualBounds().getWidth();
int xRight = positions.xSell-30+10+maxPriceWidth+coinSpace+coindWidth;
int x = xRight-((int)gv.getVisualBounds().getWidth()+coinSpace+coindWidth);
g2d.drawGlyphVector(gv, x, y);
x = xRight-coindWidth;
y -= (int) Math.ceil(gv.getVisualBounds().getHeight());
g2d.drawImage(coin, x, y, null);
// GlyphVector gv = opPainter.createGlyphVector(g2d, value, 18);
// int xPadding = imageUtils.computeCenterAlignX(positions.xSell, waxSeal.getWidth(), (int)gv.getVisualBounds().getWidth());
// g2d.drawGlyphVector(gv, xPadding, y);
}
/**
* This class holds the positions where different elements are
* placed on the dialog.
* @author Andi Hotz, (c) Sahits GmbH, 2011
* Created on Dec 9, 2011
*
*/
private static class DialogPositions{
private final double titleHeigth;
private final int lineHeight;
private final int xWare;
private final int xCity;
private final int xBuy;
private final int xSell;
public DialogPositions(double titleHeigth, int lineHeight,
int leftBorder, int xWare, int xCity, int xBuy, int xSell) {
super();
this.titleHeigth = titleHeigth;
this.lineHeight = lineHeight;
this.xWare = xWare;
this.xCity = xCity;
this.xBuy = xBuy;
this.xSell = xSell;
}
}
}