org.iplantc.phyloviewer.client.tree.viewer.OverviewView.java Source code

Java tutorial

Introduction

Here is the source code for org.iplantc.phyloviewer.client.tree.viewer.OverviewView.java

Source

/**
 * Copyright (c) 2009, iPlant Collaborative, Texas Advanced Computing Center This software is licensed
 * under the CC-GNU GPL version 2.0 or later. License: http://creativecommons.org/licenses/GPL/2.0/
 */

package org.iplantc.phyloviewer.client.tree.viewer;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.iplantc.phyloviewer.client.math.ConvertMathTypes;
import org.iplantc.phyloviewer.client.services.TreeImage;
import org.iplantc.phyloviewer.client.services.TreeImageAsync;
import org.iplantc.phyloviewer.client.services.TreeIntersectService;
import org.iplantc.phyloviewer.client.services.TreeIntersectServiceAsync;
import org.iplantc.phyloviewer.client.tree.viewer.canvas.Canvas;
import org.iplantc.phyloviewer.client.tree.viewer.canvas.Image;
import org.iplantc.phyloviewer.client.tree.viewer.canvas.ImageListener;
import org.iplantc.phyloviewer.shared.math.Box2D;
import org.iplantc.phyloviewer.shared.math.Matrix33;
import org.iplantc.phyloviewer.shared.math.Vector2;
import org.iplantc.phyloviewer.shared.model.IDocument;
import org.iplantc.phyloviewer.shared.model.ITree;
import org.iplantc.phyloviewer.shared.render.Camera;
import org.iplantc.phyloviewer.shared.render.Defaults;
import org.iplantc.phyloviewer.shared.render.IGraphics;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsonUtils;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * A View that shows an overview image of the tree
 */
public class OverviewView extends AnimatedView {
    private static final String MESSAGE_ERROR_LOADING_IMAGE = "Error loading image.";
    private static final String MESSAGE_LOADING_IMAGE = "Loading image...";

    private final class ImageListenerImpl implements ImageListener {
        private OverviewView view = null;

        public ImageListenerImpl(OverviewView view) {
            this.view = view;
        }

        public void onLoadingComplete(Image image) {
            view.image = image;
            view.downloadingImage = null;
            view.imageStatus = ImageStatus.IMAGE_STATUS_IMAGE_LOADED;
            view.requestRender();
        }
    }

    enum ImageStatus {
        IMAGE_STATUS_NO_TREE, IMAGE_STATUS_IMAGE_LOADED, IMAGE_STATUS_LOADING_IMAGE, IMAGE_STATUS_ERROR
    }

    private Canvas canvas = null;
    private Image image = null;
    @SuppressWarnings("unused")
    private Image downloadingImage = null;
    private int width;
    private int height;
    private ImageStatus imageStatus = ImageStatus.IMAGE_STATUS_NO_TREE;
    private JsHit hit;
    private TreeImageAsync treeImageService = GWT.create(TreeImage.class);
    private TreeIntersectServiceAsync treeIntersectService = GWT.create(TreeIntersectService.class);

    public OverviewView(int width, int height) {
        this.width = width;
        this.height = height;

        canvas = new Canvas(width, height);

        this.add(canvas);

        this.addMouseMoveHandler(new MouseMoveHandler() {

            @Override
            public void onMouseMove(MouseMoveEvent arg0) {
                int x = arg0.getX();
                int y = arg0.getY();

                // Project the point in screen space to object space.
                Vector2 position = new Vector2((double) x / OverviewView.this.width,
                        (double) y / OverviewView.this.height);

                ITree tree = getTree();
                if (tree != null) {
                    String layoutID = OverviewView.this.getLayoutType().toString();

                    treeIntersectService.intersectTree(tree.getRootNode().getId(), layoutID, position.getX(),
                            position.getY(), new AsyncCallback<String>() {

                                @Override
                                public void onFailure(Throwable arg0) {
                                    hit = null;
                                    OverviewView.this.requestRender();
                                }

                                @Override
                                public void onSuccess(String arg0) {
                                    JsHitResult result = (JsHitResult) JsonUtils.safeEval(arg0);
                                    hit = result.getHit();
                                    OverviewView.this.requestRender();
                                }
                            });
                }
            }

        });

        this.addMouseDownHandler(new MouseDownHandler() {

            @Override
            public void onMouseDown(MouseDownEvent arg0) {
                if (hit != null) {
                    Box2D bbox = ConvertMathTypes.convertToBox2(hit.boundingBox());
                    zoomToBoundingBox(bbox);
                }
            }
        });
    }

    @Override
    public void setDocument(IDocument document) {
        super.setDocument(document);

        this.image = null;
        this.downloadingImage = null;

        this.requestRender();
    }

    /**
     * Update the overview image
     */
    public void updateImage() {
        this.downloadingImage = null;

        if (this.getTree() == null) {
            this.image = null;
            return;
        }

        this.imageStatus = ImageStatus.IMAGE_STATUS_LOADING_IMAGE;

        final AsyncCallback<String> callback = new AsyncCallback<String>() {
            final OverviewView caller = OverviewView.this;

            @Override
            public void onFailure(Throwable arg0) {
                image = null;
                downloadingImage = null;
                caller.imageStatus = ImageStatus.IMAGE_STATUS_ERROR;

                Logger.getLogger("").log(Level.INFO, "Failure retrieving overview image.", arg0);
            }

            @Override
            public void onSuccess(String result) {
                downloadingImage = new Image(result, new ImageListenerImpl(caller));
                caller.requestRender();
            }
        };

        if (this.getTree() != null && this.getLayout() != null) {
            final ITree tree = this.getTree();

            String layoutID = this.getLayoutType().toString();
            treeImageService.getTreeImageURL(tree, layoutID, width, height, callback);
        } else {
            imageStatus = ImageStatus.IMAGE_STATUS_ERROR;
        }

    }

    public void render() {
        try {
            canvas.clear();

            if (image != null && image.isLoaded()) {
                canvas.save();

                canvas.scale((double) width / image.getWidth(), (double) height / image.getHeight());
                canvas.drawImage(image, 0, 0);

                canvas.restore();
            } else {
                switch (imageStatus) {
                case IMAGE_STATUS_LOADING_IMAGE:
                    showStatusMessage(OverviewView.MESSAGE_LOADING_IMAGE);
                    break;
                case IMAGE_STATUS_ERROR:
                    showStatusMessage(OverviewView.MESSAGE_ERROR_LOADING_IMAGE);
                }
            }

            Camera camera = this.getCamera();
            if (camera != null) {
                Matrix33 V = camera.getViewMatrix();
                Matrix33 IV = V.inverse();
                Vector2 min = new Vector2(0, 0);
                Vector2 max = new Vector2(1, 1);

                min = IV.transform(min);
                max = IV.transform(max);

                Matrix33 S = Matrix33.makeScale(canvas.getWidth(), canvas.getHeight());
                min = S.transform(min);
                max = S.transform(max);

                double x = min.getX();
                double y = min.getY();
                double width = max.getX() - x;
                double height = max.getY() - y;

                canvas.setStrokeStyle(Defaults.OVERVIEW_OUTLINE_COLOR);
                canvas.setFillStyle(Defaults.OVERVIEW_FILL_COLOR);
                canvas.beginPath();
                canvas.rect(x, y, width, height);
                canvas.fill();
                canvas.stroke();
            }

            if (hit != null) {
                canvas.setFillStyle("red");
                canvas.beginPath();

                double x = hit.position().getX();
                double y = hit.position().getY();

                canvas.arc(x * this.width, y * this.height, Defaults.POINT_SIZE / 2.0, 0, Math.PI * 2, true);
                canvas.closePath();
                canvas.fill();
            }
        } catch (Exception e) {
            Logger.getLogger("").log(Level.WARNING,
                    "An exception was caught in OverviewView.render: " + e.getMessage());
        }
    }

    @Override
    public void renderTo(IGraphics g) {
        //TODO?
    }

    private void showStatusMessage(String message) {
        canvas.setStrokeStyle(Defaults.TEXT_COLOR);
        canvas.setFillStyle(Defaults.TEXT_COLOR);
        canvas.fillText(message, 0, canvas.getHeight() / 2);
    }

    public void resize(int width, int height) {
        this.width = width;
        this.height = height;
        canvas.setWidth(width);
        canvas.setHeight(height);
        updateImage(); // FIXME: limit the rate of these requests. Most browsers are going to
                       // have many resize events as the user drags the window border
                       // around.
    }

    @Override
    protected boolean isReady() {
        return true;
    }

    @Override
    public String exportImageURL() {
        return image.getElement().getSrc();
    }
}