package ch.sahits.game.graphic.display.start;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.TreeMap;
import javax.imageio.ImageIO;
import ch.sahits.game.event.EViewChangeEvent;
import ch.sahits.game.event.Event;
import ch.sahits.game.event.MouseClickEvent;
import ch.sahits.game.event.MouseMoveEvent;
import ch.sahits.game.event.ViewChangeEvent;
import ch.sahits.game.graphic.display.GameView;
import ch.sahits.game.graphic.display.util.NamedPolygon;
import ch.sahits.game.graphic.display.util.OffsetCalculator;
import ch.sahits.game.graphic.image.LanguageImageLoader;
import ch.sahits.game.graphic.image.NamedBufferedImage;
import ch.sahits.game.rendering.AbstractRenderPart;
import ch.sahits.game.rendering.RenderablePart;
public class StartupView extends AbstractRenderPart {
// clip image names
private final static int TEXT_UNFOCUSED = 1;
private final static int TEXT_FOCUS_NEW = 2;
private final static int TEXT_FOCUS_LOAD = 3;
private final static int TEXT_FOCUS_OPTIONS = 4;
private final static int TEXT_FOCUS_CREDITS = 5;
private final static int TEXT_FOCUS_HISTORY = 6;
private final static int TEXT_CREDITS = 7;
private final static int TEXT_FOCUS_BACK = 8;
private final static int TEXT_HISTORY = 9;
private final static int TEXT_BACK_NEXT = 10;
private final static int TEXT_FOCUS_NEXT = 11;
private final static String[] names = { "PaperScroll",
"StartScreen_texts", "StartScreen_texts_highlight_new",
"StartScreen_texts_highlight_load",
"StartScreen_texts_highlight_options",
"StartScreen_texts_highlight_credits",
"StartScreen_texts_highlight_history", "Credits",
"Back_highlight","History_Hansa", "Back_next","Next_highlight"
// , "quill"
};
private int historyIndex=-1;
private int historySize=0;
/** Index of the text image in the {@link #images} List */
private int textImageIndex = -1; // TODO remove
private Rectangle size;
private OffsetCalculator offsetter;
/**
* Store the polygons for checking against clicking them
* Using a TreeMap so it may be possible do define polygons that cover the same
* are but in a different z-order.
*/
private TreeMap<Integer, NamedPolygon> polygons = new TreeMap<Integer, NamedPolygon>();
/**
* Storage of the offsets for each image.
*/
private HashMap<String, Point> offsets = new HashMap<String, Point>();
// location of image and sound info
private final static String IMS_FILE = "startScreen.txt";
// private int numImages;
private ArrayList<NamedBufferedImage> images; // TODO make sure no image is contained twice (no set)
/** Number of images that are initially drawn */
private final int initialRenderedImages; // TODO remove
private MouseState state;
private PageState pageState = PageState.STARTPAGE;
// private FSEMOpenPatrician topLevel;
private final LanguageImageLoader imsLoader;
private volatile boolean viewChanged=true;
public StartupView(Rectangle bounds) {
super(bounds);
imsLoader = new LanguageImageLoader(IMS_FILE, Locale.ENGLISH);
initImages();
initStartPolygons();
initialRenderedImages = images.size();
initMouseState();
Event.add(this);
}
private void initMouseState() {
Point p = MouseInfo.getPointerInfo().getLocation();
String polyName = findPolygon(p.x, p.y);
updateMouseState(polyName);
}
protected void updateMouseState(String polyName) {
if (pageState == PageState.STARTPAGE) {
if (polyName == null) {
state = MouseState.UNFOCUSED;
} else if (polyName.equals(names[TEXT_FOCUS_NEW])) {
state = MouseState.NEW;
// } else if (polyName.equals(names[TEXT_FOCUS_LOAD])){
// // TODO check if there is something to load
// state=MouseState.LOAD;
// } else if (polyName.equals(names[TEXT_FOCUS_OPTIONS])){
// // TODO to be enabled
// state=MouseState.OPTIONS;
} else if (polyName.equals(names[TEXT_FOCUS_CREDITS])) {
state = MouseState.CREDITS;
} else if (polyName.equals(names[TEXT_FOCUS_HISTORY])) {
state = MouseState.HISTORY;
} else {
state = MouseState.UNFOCUSED;
}
} else if (pageState == PageState.CREDITS) {
if (polyName == null) {
state = MouseState.CREDITS_PAGE;
} else if (polyName.equals(names[TEXT_FOCUS_BACK])) {
state = MouseState.BACK;
}
} else if (pageState == PageState.HISTORY){
if (polyName == null) {
state = MouseState.HISTORY_PAGE;
} else if (polyName.equals(names[TEXT_FOCUS_BACK])) {
state = MouseState.BACK;
} else if (polyName.equals(names[TEXT_FOCUS_NEXT])){
state = MouseState.NEXT;
}
}
}
/**
* Find the polygon name that contains the coordinates. It is expected that the polygons
* are not overlapping. Is this not the case the first found polygon name is returned.
* @param x coordinate
* @param y coordinate
* @return name of the polygon
*/
private String findPolygon(int x, int y) { // Use a better algo
for (NamedPolygon poly : polygons.values()) {
if (poly.contains(x, y)) {
return poly.getName();
}
}
return null;
}
/**
* Setting the positions of the polygons on the screen
*/
private void initStartPolygons() {
// TODO implement PolygonLoader
NamedPolygon poly = new NamedPolygon(names[TEXT_FOCUS_NEW]);
poly.addPoint(offsetter.computeXOffset(590),
offsetter.computeYOffset(38));
poly.addPoint(offsetter.computeXOffset(662),
offsetter.computeYOffset(45));
poly.addPoint(offsetter.computeXOffset(654),
offsetter.computeYOffset(74));
poly.addPoint(offsetter.computeXOffset(585),
offsetter.computeYOffset(65));
int meanY = (poly.ypoints[0] + poly.ypoints[3]) / 2;
polygons.put(meanY, poly);
poly = new NamedPolygon(names[TEXT_FOCUS_LOAD]);
poly.addPoint(offsetter.computeXOffset(565),
offsetter.computeYOffset(91));
poly.addPoint(offsetter.computeXOffset(656),
offsetter.computeYOffset(110));
poly.addPoint(offsetter.computeXOffset(649),
offsetter.computeYOffset(148));
poly.addPoint(offsetter.computeXOffset(552),
offsetter.computeYOffset(138));
meanY = (poly.ypoints[0] + poly.ypoints[3]) / 2;
polygons.put(meanY, poly);
poly = new NamedPolygon(names[TEXT_FOCUS_OPTIONS]);
poly.addPoint(offsetter.computeXOffset(543),
offsetter.computeYOffset(162));
poly.addPoint(offsetter.computeXOffset(657),
offsetter.computeYOffset(193));
poly.addPoint(offsetter.computeXOffset(648),
offsetter.computeYOffset(233));
poly.addPoint(offsetter.computeXOffset(537),
offsetter.computeYOffset(217));
meanY = (poly.ypoints[0] + poly.ypoints[3]) / 2;
polygons.put(meanY, poly);
poly = new NamedPolygon(names[TEXT_FOCUS_CREDITS]);
poly.addPoint(offsetter.computeXOffset(501),
offsetter.computeYOffset(252));
poly.addPoint(offsetter.computeXOffset(619),
offsetter.computeYOffset(285));
poly.addPoint(offsetter.computeXOffset(603),
offsetter.computeYOffset(324));
poly.addPoint(offsetter.computeXOffset(490),
offsetter.computeYOffset(309));
meanY = (poly.ypoints[0] + poly.ypoints[3]) / 2;
polygons.put(meanY, poly);
poly = new NamedPolygon(names[TEXT_FOCUS_HISTORY]);
poly.addPoint(offsetter.computeXOffset(459),
offsetter.computeYOffset(325));
poly.addPoint(offsetter.computeXOffset(587),
offsetter.computeYOffset(365));
poly.addPoint(offsetter.computeXOffset(574),
offsetter.computeYOffset(422));
poly.addPoint(offsetter.computeXOffset(423),
offsetter.computeYOffset(389));
meanY = (poly.ypoints[0] + poly.ypoints[3]) / 2;
polygons.put(meanY, poly);
poly = new NamedPolygon(names[TEXT_FOCUS_BACK]);
poly.addPoint(offsetter.computeXOffset(392),offsetter.computeYOffset(397));
poly.addPoint(offsetter.computeXOffset(433),offsetter.computeYOffset(408));
poly.addPoint(offsetter.computeXOffset(427),offsetter.computeYOffset(426));
poly.addPoint(offsetter.computeXOffset(385),offsetter.computeYOffset(416));
meanY = (poly.ypoints[0] + poly.ypoints[3]) / 2;
polygons.put(meanY, poly);
poly = new NamedPolygon(names[TEXT_FOCUS_NEXT]);
poly.addPoint(offsetter.computeXOffset(854),offsetter.computeYOffset(468));
poly.addPoint(offsetter.computeXOffset(913),offsetter.computeYOffset(484));
poly.addPoint(offsetter.computeXOffset(913),offsetter.computeYOffset(512));
poly.addPoint(offsetter.computeXOffset(858),offsetter.computeYOffset(495));
meanY = (poly.ypoints[0] + poly.ypoints[3]) / 2;
polygons.put(meanY, poly);
}
/**
* load and initialize the images, and build their 'hot-spots'
*/
private void initImages() {
images = new ArrayList<NamedBufferedImage>();
textImageIndex = 1;
// Insert top image fist and add at the begining
// insertFirst(names[12]);
insertFirst(names[TEXT_UNFOCUSED]);
insertFirst(names[0]);
// textImageIndex = 1;
size = getBounds();
initOffsets();
} // end of initImages()
// public void paintComponent(Graphics g)
// // show the images against a white background
// {
// super.paintComponent(g);
// g.setColor(Color.black);
// g.fillRect(0, 0, size.width, size.height); // black background
//
// // display the images
// for (int i = 0; i < images.size(); i++) {
// NamedBufferedImage img = images.get(i);
// Point offset = offsets.get(img.getName());
// if (offset == null) {
// throw new NullPointerException("The offset must be stored for "+img.getName());
// }
// System.out.println("Draw image: "+img.getName());
// g.drawImage(img.getImage(), offset.x, offset.y, this);
// }
// System.out.println("---------------------");
// } // end of paintComponent()
/**
* Compute the offsets for the images to be drawn onto the panel
*/
protected void initOffsets() {
int h = images.get(0).getHeight();
int w = images.get(0).getWidth();
// PaperScroll
Point offset = new Point(size.width - (w + 150), size.height - h);
offsetter = new OffsetCalculator(size.width - (w + 150),
size.height - h);
offsets.put(names[0], offset);
// // Offset for the quill
// // same x as paper scroll
// // y such that the bottom border aligns with the window
// h = images.get(2).getHeight();
// offset = new Point(size.width - (w + 150), size.height - h);
// offsets.put(names[12], offset);
// Texts
offsets.put(names[textImageIndex], offsetter.computeOffset(337, 0));
offsets.put(names[TEXT_FOCUS_CREDITS],
offsetter.computeOffset(337, 0));
offsets.put(names[TEXT_FOCUS_HISTORY],
offsetter.computeOffset(337, 0));
offsets.put(names[TEXT_FOCUS_LOAD], offsetter.computeOffset(337, 0));
offsets.put(names[TEXT_FOCUS_NEW], offsetter.computeOffset(337, 0));
offsets.put(names[TEXT_FOCUS_OPTIONS],
offsetter.computeOffset(337, 0));
offsets.put(names[TEXT_CREDITS], offsetter.computeOffset(337, 0));
offsets.put(names[TEXT_FOCUS_BACK], offsetter.computeOffset(337, 0));
offsets.put(names[TEXT_BACK_NEXT], offsetter.computeOffset(337, 0));
offsets.put(names[TEXT_HISTORY], offsetter.computeOffset(337, 0));
offsets.put(names[TEXT_FOCUS_NEXT], offsetter.computeOffset(337, 0));
}
/**
* Remove the image with the name. If the image is not contained it
* cannot be removed.
*
* @param name
*/
protected void removeImage(String name) {
for (Iterator<NamedBufferedImage> iterator = images.iterator(); iterator
.hasNext();) {
NamedBufferedImage img = iterator.next();
if (img.getName().equals(name)) {
iterator.remove();
viewChanged=true;
break;
}
}
}
/**
* Insert the image before another image. If the image is not found, no
* image will be inserted
*
* @param insertImageName
* Name of the image to be inserted.
* @param imageName
* Name of the image before which to insert.
*/
protected void insertImageBefore(String insertImageName,
String imageName) {
if (contains(insertImageName)){
throw new IllegalStateException("The image "+insertImageName+" cannot be added twice");
}
for (int i = 0; i < images.size(); i++) {
NamedBufferedImage img = images.get(i);
System.out.println("check image "+img.getName());
if (img.getName().equals(imageName)) {
NamedBufferedImage insertImage = new NamedBufferedImage(
imsLoader.getImage(insertImageName),
insertImageName);
images.add(i, insertImage);
viewChanged=true;
break;
}
}
}
protected final void insertFirst(String insertImageName){
if (contains(insertImageName)){
throw new IllegalStateException("The image "+insertImageName+" cannot be added twice");
}
NamedBufferedImage insertImage = new NamedBufferedImage(
imsLoader.getImage(insertImageName),
insertImageName);
images.add(0, insertImage);
viewChanged=true;
}
/**
* check if an image is already contained.
* @param imageName
* @return
*/
private boolean contains(String imageName){
for (NamedBufferedImage img : images) {
if (img.getName().equals(imageName)){
return true;
}
}
return false;
}
/**
* Inserts an image at the last position
*
* @param insertImageName
*/
protected void insertImageLast(String insertImageName) {
if (contains(insertImageName)){
throw new IllegalStateException("The image "+insertImageName+" cannot be added twice");
}
NamedBufferedImage insertImage = new NamedBufferedImage(
imsLoader.getImage(insertImageName), insertImageName);
images.add(insertImage);
viewChanged=true;
}
protected void insertImageLast(NamedBufferedImage img){
if (contains(img.getName())){
throw new IllegalStateException("The image "+img.getName()+" cannot be added twice");
}
images.add(img);
viewChanged=true;
}
private String getImageName(MouseState state) {
switch (state) {
case UNFOCUSED:
return names[TEXT_UNFOCUSED];
case CREDITS:
return names[TEXT_FOCUS_CREDITS];
case HISTORY:
return names[TEXT_FOCUS_HISTORY];
case LOAD: {
return names[TEXT_FOCUS_LOAD];
}
case NEW:
return names[TEXT_FOCUS_NEW];
case OPTIONS: {
return names[TEXT_FOCUS_OPTIONS];
}
case CREDITS_PAGE: {
return names[TEXT_CREDITS];
}
case BACK: {
return names[TEXT_FOCUS_BACK];
}
case BACK_NEXT:{
return names[TEXT_BACK_NEXT];
}
case NEXT: {
return names[TEXT_FOCUS_NEXT];
}
case HISTORY_PAGE:{
return names[TEXT_HISTORY];
}
default:
return null;
}
}
private void returnBackToStartFromHistory() {
// remove highlight image
removeImage(getImageName(state));
// remove credit text
removeImage(getImageName(MouseState.HISTORY_PAGE));
// remove back_next
removeImage(getImageName(MouseState.BACK_NEXT));
// add start page
insertImageLast(getImageName(MouseState.UNFOCUSED));
pageState=PageState.STARTPAGE;
state=MouseState.UNFOCUSED;
}
@Override
public void gameRender(Graphics gScr) {
if (viewChanged) {
Color oldColor = gScr.getColor();
gScr.setColor(Color.black);
gScr.fillRect(rect.x, rect.y, rect.width, rect.height); // black background
// display the images
for (int i = 0; i < images.size(); i++) {
NamedBufferedImage img = images.get(i);
Point offset = offsets.get(img.getName());
if (offset == null) {
throw new NullPointerException(
"The offset must be stored for " + img.getName());
}
//System.out.println("Draw image: "+img.getName());
gScr.drawImage(img.getImage(), offset.x, offset.y, null);
// try {
// ImageIO.write(img.getImage(), "png", new File("ImagePart"
// + i + ".png"));
// } catch (IOException e) {
// e.printStackTrace();
// }
}
gScr.setColor(oldColor);
viewChanged=false;
}
}
@Override
public void gameUpdate(Event e, Object notice) {
if (e instanceof MouseMoveEvent){
Point p = (Point) notice;
String polyName = findPolygon(p.x, p.y);
MouseState prevState = state;
updateMouseState(polyName);
if (prevState != state) { // there was a change
if (state == MouseState.UNFOCUSED || state==MouseState.CREDITS_PAGE || state==MouseState.HISTORY_PAGE) {
// remove the prevState
removeImage(getImageName(prevState));
} else {
String name = getImageName(state);
String insertBeforImageName=null;
if (pageState==PageState.STARTPAGE){
// insert the new state before unfocused
insertBeforImageName=getImageName(MouseState.UNFOCUSED);
} else if (pageState==PageState.CREDITS){
// insert before credit text
insertBeforImageName=getImageName(MouseState.CREDITS_PAGE);
} else if (pageState==PageState.HISTORY){
// insert before back_next
insertBeforImageName=getImageName(MouseState.BACK_NEXT);
}
if (insertBeforImageName!=null){
System.out.println("Try inserert before "+insertBeforImageName);
insertImageBefore(name, insertBeforImageName);
}
}
}
} // end mouse move
if (e instanceof MouseClickEvent){
Point p = (Point) notice;
String polyName = findPolygon(p.x, p.y);
if (polyName != null) {
// decide on action
if (polyName.equals(names[TEXT_FOCUS_CREDITS])) {
System.out.println("Clicked on credits");
// remove highlight image
removeImage(getImageName(state));
// remove the text
removeImage(getImageName(MouseState.UNFOCUSED));
// add credits
insertImageLast(getImageName(MouseState.CREDITS_PAGE));
// change page state
pageState = PageState.CREDITS;
state = MouseState.CREDITS_PAGE;
}
if (polyName.equals(names[TEXT_FOCUS_BACK])){
if (pageState==PageState.CREDITS){
// remove highlight image
removeImage(getImageName(state));
// remove credit text
removeImage(getImageName(MouseState.CREDITS_PAGE));
// add start page
insertImageLast(getImageName(MouseState.UNFOCUSED));
pageState=PageState.STARTPAGE;
state=MouseState.UNFOCUSED;
}
if (pageState==PageState.HISTORY){
if (historyIndex==0){
// back to start page
returnBackToStartFromHistory();
} else {
// remove the old page
removeImage(getImageName(MouseState.HISTORY_PAGE));
// add next image
BufferedImage img = imsLoader.getLocalImageGroup(names[TEXT_HISTORY], --historyIndex);
insertImageLast(new NamedBufferedImage(img, names[TEXT_HISTORY]));
}
}
}
if (polyName.equals(names[TEXT_FOCUS_NEXT])){
if (pageState==PageState.HISTORY){
if (historyIndex==historySize-1){
// back to start page
returnBackToStartFromHistory();
} else {
// remove the old page
removeImage(getImageName(MouseState.HISTORY_PAGE));
// add next image
BufferedImage img = imsLoader.getLocalImageGroup(names[TEXT_HISTORY], ++historyIndex);
insertImageLast(new NamedBufferedImage(img, names[TEXT_HISTORY]));
}
}
}
if (polyName.equals(names[TEXT_FOCUS_HISTORY])){
System.out.println("Clicked on history");
// remove highlight image
removeImage(getImageName(state));
// remove the text
removeImage(getImageName(MouseState.UNFOCUSED));
// add back and next
insertImageLast(names[TEXT_BACK_NEXT]);
// add history
historyIndex=0;
historySize=imsLoader.getLocalImageGroupeSize(names[TEXT_HISTORY]);
BufferedImage img = imsLoader.getLocalImageGroup(names[TEXT_HISTORY], historyIndex);
insertImageLast(new NamedBufferedImage(img, names[TEXT_HISTORY]));
// change page state
pageState = PageState.HISTORY;
state = MouseState.HISTORY_PAGE;
} // end history
if (polyName.equals(names[TEXT_FOCUS_NEW])){
System.out.println("Clicked on new");
new ViewChangeEvent(GameView.class).notify(EViewChangeEvent.DISPLAY_NEW_SP);
}
}
} // end of mouse click
}
private enum MouseState {
UNFOCUSED, CREDITS, OPTIONS, HISTORY, LOAD, NEW, CREDITS_PAGE, BACK, HISTORY_PAGE, NEXT, BACK_NEXT
}
private enum PageState {
STARTPAGE, CREDITS, HISTORY
}
}