package it.freedomotic.gwtclient.client.widgets;
import it.freedomotic.gwtclient.client.api.EnvironmentController;
import it.freedomotic.gwtclient.client.utils.DrawableElement;
import it.freedomotic.gwtclient.client.utils.DrawableObject;
import it.freedomotic.gwtclient.client.utils.DrawableRoom;
import it.freedomotic.gwtclient.client.utils.DrawingUtils;
import it.freedomotic.gwtclient.client.utils.ImageUtils;
import it.freedomotic.model.environment.Environment;
import it.freedomotic.model.environment.Zone;
import it.freedomotic.model.geometry.FreedomPolygon;
import it.freedomotic.model.object.EnvObject;
import java.awt.Color;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.HashMap;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.ImageData;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;
import com.levigo.util.gwtawt.client.WebGraphics;
public class FloorPlanWidget {
Canvas canvas;
Context2d ctx;
Canvas ghostCanvas;
Context2d gctx;
Path2D envPath = new Path2D.Double(); // the enviroment path that is going
// to be draw.
// WebGraphics mPaint;
// WebGraphics environmentPaint;
// WebGraphics environmentPaint2;
// WebGraphics environmentShadowPaint;
//GPT private static EnvironmentResourceProxy environmentResource;
public static Environment environment;
ArrayList<DrawableRoom> drawingRooms = new ArrayList<DrawableRoom>();
ArrayList<DrawableObject> drawingObjects = new ArrayList<DrawableObject>();
ArrayList<DrawableObject> objectsShowingBehaviors = new ArrayList<DrawableObject>();
// Map of objects that are drawed
HashMap<Integer, DrawableElement> objectsIndex = new HashMap<Integer,DrawableElement>();
//TODO: add get /set
boolean dataInitialized = false;
//timer refresh rate, in milliseconds
static final int refreshRate = 25;
// canvas size, in px
//static final int height = 1500;
//static final int width = 1324;
private static final double MARGIN = 50;
private static int BORDER_X = 10; //the empty space around the map
private static int BORDER_Y = 10; //the empty space around the map
private static int CANVAS_WIDTH = 1300+ (BORDER_X * 2);
private static int CANVAS_HEIGHT = 900+ (BORDER_X * 2);
private double ENVIRONMENT_WIDTH = CANVAS_WIDTH;
private double ENVIRONMENT_HEIGHT = CANVAS_HEIGHT;
private double mScaleFactor = 1;
boolean transformed = false;
private double mPosX;
private double mPosY;
private DockLayoutPanel parent;
public FloorPlanWidget(DockLayoutPanel parent) {
this.parent = parent;
canvas = Canvas.createIfSupported();
canvas.setWidth(CANVAS_WIDTH + "px");
canvas.setHeight(CANVAS_HEIGHT + "px");
canvas.setCoordinateSpaceWidth(CANVAS_WIDTH);
canvas.setCoordinateSpaceHeight(CANVAS_HEIGHT);
ctx = canvas.getContext2d();
canvas.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
final DrawableObject dobj = getObjectUnderCoordinates(event.getX(),event.getY());
if (dobj!= null)
{
final EnvObjectProperties eop = new EnvObjectProperties(dobj.getEnvObject());
eop.setPopupPositionAndShow(new EnvObjectProperties.PositionCallback() {
@Override
public void setPosition(int offsetWidth, int offsetHeight) {
int left= event.getX()+canvas.getAbsoluteLeft()+ dobj.getCurrentWidth()/4;
int top = event.getY()+canvas.getAbsoluteTop() - dobj.getCurrentHeight()/2;
eop.setPopupPosition(left, top);
}
});
}
}
});
canvas.addMouseMoveHandler(new MouseMoveHandler() {
//TODO: maybe there is a better way making DrawableObjects implement MouseListener and transforming it on widgets
@Override
public void onMouseMove(final MouseMoveEvent event) {
GWT.log("On mouse over");
final DrawableObject dobj = getObjectUnderCoordinates(event.getX(),event.getY());
if (dobj!= null )
{
if (!dobj.isShowingBehavioursPanel()) //to avoid blinking
{
int left = canvas.getAbsoluteLeft();
int top = canvas.getAbsoluteTop();
dobj.showBehavioursPanel(left, top, mScaleFactor);
objectsShowingBehaviors.add(dobj);
}
}
else
{
for (DrawableObject dobj2: objectsShowingBehaviors)
{
dobj2.hideBehavioursPanel();
}
objectsShowingBehaviors.clear();
}
}
});
ghostCanvas = Canvas.createIfSupported();
ghostCanvas.setWidth(CANVAS_WIDTH + "px");
ghostCanvas.setHeight(CANVAS_HEIGHT + "px");
ghostCanvas.setCoordinateSpaceWidth(CANVAS_WIDTH);
ghostCanvas.setCoordinateSpaceHeight(CANVAS_HEIGHT);
gctx = ghostCanvas.getContext2d();
// setup timer
final Timer timer = new Timer() {
@Override
public void run() {
if (dataInitialized)
draw();
else
{
initializeData();
fitToScreen();
}
}
};
timer.scheduleRepeating(refreshRate);
Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(ResizeEvent event) {
// TODO Auto-generated method stub
GWT.log("resized");
GWT.log("parentHeight: "+canvas.getParent().getOffsetHeight());
GWT.log("parentWidth: "+canvas.getParent().getOffsetWidth());
}
});
}
void initializeData()
{
if (EnvironmentController.getInstance().HasData())
{
environment = EnvironmentController.getInstance().getEnvironment();
FreedomPolygon poly = environment.getShape();
envPath = DrawingUtils.freedomPolygonToPath(poly);
ENVIRONMENT_WIDTH = environment.getWidth();
ENVIRONMENT_HEIGHT = environment.getHeight();
ImageUtils.queueImage("v1/environment/resources/"+environment.getBackgroundImage());
// create all drawingrooms
for (Zone r : environment.getZones()) {
if( r.isRoom())
{
DrawableRoom dr = new DrawableRoom(r);
drawingRooms.add(dr);
//GWT.log("index: "+((Integer)dr.getIndexColor()).toString());
objectsIndex.put(dr.getIndexColor(), dr);
// TODO: Take care of the objects not in room
for (EnvObject obj : r.getObjects()) {
GWT.log("object in a room "+obj.getName());
DrawableObject dobj =new DrawableObject(obj);
drawingObjects.add(dobj);
objectsIndex.put(dobj.getIndexColor(), dobj);
}
}
}
dataInitialized = true;
}
}
void draw() {
int parentWidth =canvas.getParent().getOffsetWidth();
int parentHeight=canvas.getParent().getOffsetHeight();
if(CANVAS_WIDTH!=parentWidth || CANVAS_HEIGHT!=parentHeight) //the size of the canvas has changed, adjust the map
{
CANVAS_WIDTH= parentWidth;
CANVAS_HEIGHT= parentHeight;
canvas.setWidth(CANVAS_WIDTH + "px");
canvas.setHeight(CANVAS_HEIGHT + "px");
canvas.setCoordinateSpaceWidth(CANVAS_WIDTH);
canvas.setCoordinateSpaceHeight(CANVAS_HEIGHT);
ghostCanvas.setWidth(CANVAS_WIDTH + "px");
ghostCanvas.setHeight(CANVAS_HEIGHT + "px");
ghostCanvas.setCoordinateSpaceWidth(CANVAS_WIDTH);
ghostCanvas.setCoordinateSpaceHeight(CANVAS_HEIGHT);
fitToScreen();
}
ctx.save();
gctx.save();
ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
gctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
ctx.scale(mScaleFactor, mScaleFactor);
ctx.translate(BORDER_X, BORDER_Y);
gctx.scale(mScaleFactor, mScaleFactor);
gctx.translate(BORDER_X, BORDER_Y);
prepareBackground();
//TODO: If we render the environment, the border moves the shape, so we must move the background also
//renderEnvironment(ctx);
renderRooms();
renderObjects();
gctx.restore();
ctx.restore();
//ImageUtils.newData = false;
}
public void prepareBackground()
{
if (ImageUtils.CachedImages.containsKey("v1/environment/resources/"+environment.getBackgroundImage()))
{
Image im =ImageUtils.CachedImages.get("v1/environment/resources/"+environment.getBackgroundImage());
ImageElement ie = ImageElement.as(im.getElement());
//ghostBitmap =Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(),Config.ARGB_8888);
//im.setVisible(true);
ctx.drawImage(ie, 0, 0,ENVIRONMENT_WIDTH,ENVIRONMENT_HEIGHT);
}
}
public DrawableObject getObjectUnderCoordinates(int x, int y)
{
if (gctx!= null)
{
int posX = 0;
int posY = 0;
//retrieve the color under the click on the ghost canvas
ImageData id = gctx.getImageData(x, y, 1,1);
Color c = new Color(id.getRedAt(posX, posY),id.getGreenAt(posX, posY),id.getBlueAt(posX, posY),id.getAlphaAt(posX, posY));
if (objectsIndex.containsKey(c.getRGB()));
{
if (objectsIndex.get(c.getRGB())!= null)
{
DrawableElement de = objectsIndex.get(c.getRGB());
if (de instanceof DrawableObject)
return (DrawableObject)de;
}
}
}
return null;
}
public void renderEnvironment(Context2d ctx)
{
WebGraphics g = new WebGraphics(ctx);
// Draw it on the Canvas
ctx.setLineWidth(33);
g.setColor(java.awt.Color.WHITE);
g.draw(envPath);
ctx.setLineWidth(30);
g.setColor(java.awt.Color.LIGHT_GRAY);
g.draw(envPath);
ctx.setLineWidth(7);
g.setColor(java.awt.Color.DARK_GRAY);
g.draw(envPath);
}
public void renderRooms()
{
for (DrawableRoom dr: drawingRooms)
{
dr.drawGhost(gctx);
dr.draw(ctx);
}
}
public void renderObjects()
{
for (DrawableObject dobj: drawingObjects)
{
dobj.drawGhost(gctx);
dobj.draw(ctx);
//objectsIndex.put(dobj.getIndexColor(), dobj);
}
}
public Canvas getCanvas()
{
return canvas;
}
//Adapt the "original coordinates" from freedomotic to the canvas size
public void fitToScreen()
{
//double xSize = ENVIRONMENT_WIDTH-MARGIN*2;
//double ySize = ENVIRONMENT_HEIGHT-MARGIN*2;
//double xSize = CANVAS_WIDTH-MARGIN*2;
//double ySize = CANVAS_HEIGHT-MARGIN*2;
double xSize = CANVAS_WIDTH-BORDER_X;
double ySize = CANVAS_HEIGHT-BORDER_Y-200;
//Rectangle2D pathBounds = envPath.getBounds2D();
double xPathSize = ENVIRONMENT_WIDTH;
double yPathSize = ENVIRONMENT_HEIGHT;
double xScale = xSize/xPathSize;
double yScale = ySize/yPathSize;
if (xScale <yScale)
mScaleFactor = xScale;
else
mScaleFactor = yScale;
mPosX = 0;//MARGIN;
mPosY = 0;//MARGIN;
}
}